Skip to content

Commit a772075

Browse files
committed
Clean up WasmMath.
1 parent ff26244 commit a772075

File tree

1 file changed

+3
-161
lines changed

1 file changed

+3
-161
lines changed
Lines changed: 3 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -41,8 +41,6 @@
4141

4242
package org.graalvm.wasm;
4343

44-
import com.oracle.truffle.api.ExactMath;
45-
4644
import static java.lang.Integer.compareUnsigned;
4745

4846
/**
@@ -51,29 +49,6 @@
5149
*/
5250
public final class WasmMath {
5351

54-
/**
55-
* The number of logical bits in the significand of a {@code double}, <strong>excluding</strong>
56-
* the implicit bit.
57-
*/
58-
private static final long DOUBLE_SIGNIFICAND_WIDTH = 52;
59-
60-
/**
61-
* Bit mask to isolate the significand field of a <code>double</code>.
62-
*/
63-
public static final long DOUBLE_SIGNIFICAND_BIT_MASK = 0x000FFFFFFFFFFFFFL;
64-
65-
/**
66-
* The spacing between two consecutive {@code float} values (aka Unit in the Last Place) in the
67-
* range [2^31, 2^32): 2^40.
68-
*/
69-
private static final long FLOAT_POWER_63_ULP = (long) Math.ulp(0x1p63f);
70-
71-
/**
72-
* The spacing between two consecutive {@code double} values (aka Unit in the Last Place) in the
73-
* range [2^63, 2^64): 2^11.
74-
*/
75-
private static final long DOUBLE_POWER_63_ULP = (long) Math.ulp(0x1p63);
76-
7752
/**
7853
* Don't let anyone instantiate this class.
7954
*/
@@ -130,147 +105,14 @@ public static int toUnsignedIntExact(long value) {
130105
* Converts the given unsigned {@code int} to the closest {@code float} value.
131106
*/
132107
public static float unsignedIntToFloat(int x) {
133-
return unsignedIntToLong(x);
108+
return Integer.toUnsignedLong(x);
134109
}
135110

136111
/**
137112
* Converts the given unsigned {@code int} to the closest {@code double} value.
138113
*/
139114
public static double unsignedIntToDouble(int x) {
140-
return unsignedIntToLong(x);
141-
}
142-
143-
/**
144-
* Converts the given unsigned {@code int} to the corresponding {@code long}.
145-
*/
146-
public static long unsignedIntToLong(int x) {
147-
// See https://stackoverflow.com/a/22938125.
148-
return x & 0xFFFFFFFFL;
149-
}
150-
151-
/**
152-
* Converts the given unsigned {@code long} to the closest {@code float} value.
153-
*/
154-
public static float unsignedLongToFloat(long x) {
155-
if (x >= 0) {
156-
// If the first bit is not set, then we can simply cast which is faster.
157-
return x;
158-
}
159-
160-
// Transpose x from [Integer.MIN_VALUE,-1] to [0, Integer.MAX_VALUE]
161-
final long shiftedX = x + Long.MIN_VALUE;
162-
163-
// We cannot simply compute 0x1p63f + shiftedX because it yields incorrect results in some
164-
// edge cases due to rounding twice (conversion to long, and addition). See
165-
// https://github.com/WebAssembly/spec/issues/421 and mentioned test cases for more context.
166-
// Instead, we manually compute the offset from 0x1p63f.
167-
final boolean roundUp = shiftedX % FLOAT_POWER_63_ULP > FLOAT_POWER_63_ULP / 2;
168-
final long offset = (shiftedX / FLOAT_POWER_63_ULP) + (roundUp ? 1 : 0);
169-
170-
// Return the offset-nth next floating-point value starting from 2^63. This is equivalent to
171-
// incrementing the significand (as Math.nextUp would do) offset times.
172-
return 0x1p63f + (offset * (float) FLOAT_POWER_63_ULP);
173-
}
174-
175-
/**
176-
* Converts the given unsigned {@code long} to the closest {@code double} value.
177-
*/
178-
public static double unsignedLongToDouble(long x) {
179-
if (x >= 0) {
180-
// If the first bit is not set, then we can simply cast which is faster.
181-
return x;
182-
}
183-
184-
// Transpose x from [Long.MIN_VALUE,-1] to [0, Long.MAX_VALUE].
185-
final long shiftedX = x + Long.MIN_VALUE;
186-
187-
// We cannot simply compute 0x1p63 + shiftedX because it yields incorrect results in some
188-
// edge cases due to rounding twice (conversion to long, and addition). See
189-
// https://github.com/WebAssembly/spec/issues/421 and mentioned test cases for more context.
190-
// Instead, we manually compute the offset from 0x1p63.
191-
final boolean roundUp = shiftedX % DOUBLE_POWER_63_ULP > DOUBLE_POWER_63_ULP / 2;
192-
final long offset = (shiftedX / DOUBLE_POWER_63_ULP) + (roundUp ? 1 : 0);
193-
194-
// Return the offset-nth next floating-point value starting form 2^63. This is equivalent to
195-
// incrementing the significand (as Math.nextUp would do) offset times.
196-
return 0x1p63 + (offset * (double) DOUBLE_POWER_63_ULP);
197-
}
198-
199-
/**
200-
* Removes the decimal part (aka truncation or rounds towards zero) of the given float and
201-
* converts it to a <strong>signed</strong> long.
202-
* <p>
203-
* The operation is saturating: if the float is smaller than {@link Integer#MIN_VALUE} or larger
204-
* than {@link Integer#MAX_VALUE}, then respectively {@link Integer#MIN_VALUE} or
205-
* {@link Integer#MAX_VALUE} is returned.
206-
*/
207-
public static long truncFloatToLong(float x) {
208-
return truncDoubleToLong(x);
209-
}
210-
211-
/**
212-
* Removes the decimal part (aka truncation or rounds towards zero) of the given double and
213-
* converts it to a <strong>signed</strong> long.
214-
* <p>
215-
* The operation is saturating: if the double is smaller than {@link Long#MIN_VALUE} or larger
216-
* than {@link Long#MAX_VALUE}, then respectively {@link Long#MIN_VALUE} or
217-
* {@link Long#MAX_VALUE} is returned.
218-
*/
219-
public static long truncDoubleToLong(double x) {
220-
return (long) ExactMath.truncate(x);
221-
}
222-
223-
/**
224-
* Removes the decimal part (aka truncation or rounds towards zero) of the given float and
225-
* converts it to an <strong>unsigned</strong> long.
226-
* <p>
227-
* The operation is saturating: if the float is smaller than 0 or larger than 2^32 - 1, then
228-
* respectively 0 or 2^32 - 1 is returned.
229-
*/
230-
public static long truncFloatToUnsignedLong(float x) {
231-
return truncDoubleToUnsignedLong(x);
232-
}
233-
234-
/**
235-
* Removes the decimal part (aka truncation or rounds towards zero) of the given double and
236-
* converts it to an <strong>unsigned</strong> long.
237-
* <p>
238-
* The operation is saturating: if the double is smaller than 0 or larger than 2^64 - 1, then
239-
* respectively 0 or 2^64 - 1 is returned.
240-
*/
241-
public static long truncDoubleToUnsignedLong(double x) {
242-
if (x < Long.MAX_VALUE) {
243-
// If the first bit is not set, then we use the signed variant which is faster.
244-
return truncDoubleToLong(x);
245-
}
246-
247-
// There is no direct way to convert a double to an _unsigned_ long in Java. Therefore we
248-
// manually split the binary representation of x into significand (aka base or mantissa) and
249-
// exponent, and compute the resulting long by shifting the significand.
250-
251-
final long shift = Math.getExponent(x) - DOUBLE_SIGNIFICAND_WIDTH;
252-
final long xBits = Double.doubleToRawLongBits(x);
253-
final long significand = (1L << DOUBLE_SIGNIFICAND_WIDTH) | (xBits & DOUBLE_SIGNIFICAND_BIT_MASK);
254-
255-
if (shift >= Long.SIZE - DOUBLE_SIGNIFICAND_WIDTH) {
256-
// Saturation: if x is too large to convert to a long, we return the highest possible
257-
// value (all bits set).
258-
return 0xffff_ffff_ffff_ffffL;
259-
} else if (shift > 0) {
260-
// Multiply significand by 2^shift.
261-
return significand << shift;
262-
}
263-
264-
// Should not reach here because x >= Long.MAX_VALUE, so shift >=
265-
// (Math.getExponent(Long.MAX_VALUE) - DOUBLE_SIGNIFICAND_WIDTH) == 11.
266-
267-
if (shift >= -DOUBLE_SIGNIFICAND_WIDTH) {
268-
// Multiply significand by 2^shift == divide significand by 2^(-shift).
269-
return significand >> -shift;
270-
} else {
271-
// Saturation: if x is too small to convert to a long, we return 0.
272-
return 0;
273-
}
115+
return Integer.toUnsignedLong(x);
274116
}
275117

276118
}

0 commit comments

Comments
 (0)