Skip to content

Commit 3b19b52

Browse files
committed
Add saturating float to unsigned integer truncation methods.
1 parent f6d1dbb commit 3b19b52

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

truffle/src/com.oracle.truffle.api/snapshot.sigtest

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,12 @@ meth public static double truncate(double)
125125
meth public static float truncate(float)
126126
meth public static int multiplyHigh(int,int)
127127
meth public static int multiplyHighUnsigned(int,int)
128+
meth public static int truncateToUnsignedInt(double)
129+
meth public static int truncateToUnsignedInt(float)
128130
meth public static long multiplyHigh(long,long)
129131
meth public static long multiplyHighUnsigned(long,long)
132+
meth public static long truncateToUnsignedLong(double)
133+
meth public static long truncateToUnsignedLong(float)
130134
supr java.lang.Object
131135

132136
CLSS public final com.oracle.truffle.api.HostCompilerDirectives

truffle/src/com.oracle.truffle.api/src/com/oracle/truffle/api/ExactMath.java

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 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
@@ -141,4 +141,99 @@ public static double truncate(double x) {
141141
return x < 0.0 ? Math.ceil(x) : Math.floor(x);
142142
}
143143

144+
/**
145+
* Converts the double value to unsigned long with truncation (i.e. rounding towards zero) and
146+
* saturation of <code>NaN</code> and <code>x &lt;= -1</code> to <code>0</code>, and
147+
* <code>x >= 2<sup>64</sup></code> to <code>2<sup>63</sup>-1</code> (<code>-1</code>).
148+
* <p>
149+
* Non-saturating (e.g. trapping) behavior can be implemented by checking the input for NaN,
150+
* underflow (<code>x &lt;= -1</code>) and overflow (<code>x >= 0x1p64</code>) first.
151+
*
152+
* @param x input value
153+
* @return the unsigned integer result, wrapped in a signed integer
154+
* @since 25.0
155+
*/
156+
public static long truncateToUnsignedLong(double x) {
157+
if (CompilerDirectives.injectBranchProbability(CompilerDirectives.UNLIKELY_PROBABILITY, x >= 0x1p63)) {
158+
// x >= 2**63
159+
long signedResult = (long) (x - 0x1p63);
160+
return signedResult | (1L << 63);
161+
} else {
162+
// x < 2**63 or NaN
163+
long signedResult = (long) x;
164+
return signedResult & ~(signedResult >> 63); // max(result, 0)
165+
}
166+
}
167+
168+
/**
169+
* Converts the float value to unsigned long with truncation (i.e. rounding towards zero) and
170+
* saturation of <code>NaN</code> and <code>x &lt;= -1</code> to <code>0</code>, and
171+
* <code>x >= 2<sup>64</sup></code> to <code>2<sup>63</sup>-1</code> (<code>-1</code>).
172+
* <p>
173+
* Non-saturating (e.g. trapping) behavior can be implemented by checking the input for NaN,
174+
* underflow (<code>x &lt;= -1f</code>) and overflow (<code>x >= 0x1p64f</code>) first.
175+
*
176+
* @param x input value
177+
* @return the unsigned integer result, wrapped in a signed integer
178+
* @since 25.0
179+
*/
180+
public static long truncateToUnsignedLong(float x) {
181+
if (CompilerDirectives.injectBranchProbability(CompilerDirectives.UNLIKELY_PROBABILITY, x >= 0x1p63f)) {
182+
// x >= 2**63
183+
long signedResult = (long) (x - 0x1p63f);
184+
return signedResult | (1L << 63);
185+
} else {
186+
// x < 2**31 or NaN
187+
long signedResult = (long) x;
188+
return (signedResult & ~(signedResult >> 63)); // max(result, 0)
189+
}
190+
}
191+
192+
/**
193+
* Converts the double value to unsigned long with truncation (i.e. rounding towards zero) and
194+
* saturation of <code>NaN</code> and <code>x &lt;= -1</code> to <code>0</code>, and
195+
* <code>x >= 2<sup>32</sup></code> to <code>2<sup>31</sup>-1</code> (<code>-1</code>).
196+
* <p>
197+
* Non-saturating (e.g. trapping) behavior can be implemented by checking the input for NaN,
198+
* underflow (<code>x &lt;= -1</code>) and overflow (<code>x >= 0x1p32</code>) first.
199+
*
200+
* @param x input value
201+
* @return the unsigned integer result, wrapped in a signed integer
202+
* @since 25.0
203+
*/
204+
public static int truncateToUnsignedInt(double x) {
205+
if (CompilerDirectives.injectBranchProbability(CompilerDirectives.UNLIKELY_PROBABILITY, x >= 0x1p31)) {
206+
// x >= 2**31
207+
int signedResult = (int) (x - 0x1p31);
208+
return signedResult | (1 << 31);
209+
} else {
210+
// x < 2**31 or NaN
211+
int signedResult = (int) x;
212+
return (signedResult & ~(signedResult >> 31)); // max(result, 0)
213+
}
214+
}
215+
216+
/**
217+
* Converts the float value to unsigned int with truncation (i.e. rounding towards zero) and
218+
* saturation of <code>NaN</code> and <code>x &lt;= -1</code> to <code>0</code>, and
219+
* <code>x >= 2<sup>32</sup></code> to <code>2<sup>31</sup>-1</code> (<code>-1</code>).
220+
* <p>
221+
* Non-saturating (e.g. trapping) behavior can be implemented by checking the input for NaN,
222+
* underflow (<code>x &lt;= -1</code>) and overflow (<code>x >= 0x1p64</code>) first.
223+
*
224+
* @param x input value
225+
* @return the unsigned integer result, wrapped in a signed integer
226+
* @since 25.0
227+
*/
228+
public static int truncateToUnsignedInt(float x) {
229+
if (CompilerDirectives.injectBranchProbability(CompilerDirectives.UNLIKELY_PROBABILITY, x >= 0x1p31f)) {
230+
// x >= 2**31
231+
int signedResult = (int) (x - 0x1p31f);
232+
return signedResult | (1 << 31);
233+
} else {
234+
// x < 2**31 or NaN
235+
int signedResult = (int) x;
236+
return (signedResult & ~(signedResult >> 31)); // max(result, 0)
237+
}
238+
}
144239
}

0 commit comments

Comments
 (0)