1 /*
2 * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package java.lang.runtime;
26
27 /**
28 * A testing conversion of a value is exact if it yields a result without loss
29 * of information or throwing an exception. Otherwise, it is inexact. Some
30 * conversions are always exact regardless of the value. These conversions are
31 * said to be unconditionally exact.
32 * <p>
33 * For example, a conversion from {@code int} to {@code byte} for the value 10
34 * is exact because the result, 10, is the same as the original value. In
35 * contrast, if the {@code int} variable {@code i} stores the value 1000 then a
36 * narrowing primitive conversion to {@code byte} will yield the result -24.
37 * Loss of information has occurred: both the magnitude and the sign of the
38 * result are different than those of the original value. As such, a conversion
39 * from {@code int} to {@code byte} for the value 1000 is inexact. Finally a
40 * widening primitive conversion from {@code byte} to {@code int} is
41 * unconditionally exact because it will always succeed with no loss of
42 * information about the magnitude of the numeric value.
43 * <p>
44 * The methods in this class provide the run-time support for the exactness
45 * checks of testing conversions from a primitive type to primitive type. These
46 * methods may be used, for example, by Java compiler implementations to
47 * implement checks for {@code instanceof} and pattern matching runtime
48 * implementations. Unconditionally exact testing conversions do not require a
49 * corresponding action at run time and, for this reason, methods corresponding
50 * to these exactness checks are omitted here.
51 * <p>
52 * The run time conversion checks examine whether loss of information would
53 * occur if a testing conversion would be to be applied. In those cases where a
54 * floating-point primitive type is involved, and the value of the testing
55 * conversion is either signed zero, signed infinity or {@code NaN}, these
56 * methods comply with the following:
57 *
58 * <ul>
59 * <li>Converting a floating-point negative zero to an integer type is considered
60 * inexact.</li>
61 * <li>Converting a floating-point {@code NaN} or infinity to an integer type is
62 * considered inexact.</li>
63 * <li>Converting a floating-point {@code NaN} or infinity or signed zero to another
64 * floating-point type is considered exact.</li>
65 * </ul>
66 *
67 * @see <a href="../../../../../specs/primitive-types-in-patterns-instanceof-switch-jls.html#jls-5.7.1">
68 * JLS 5.7.1 Exact Testing Conversions</a>
69 * @see <a href="../../../../../specs/primitive-types-in-patterns-instanceof-switch-jls.html#jls-5.7.2">
70 * JLS 5.7.2 Unconditionally Exact Testing Conversions</a>
71 * @see <a href="../../../../../specs/primitive-types-in-patterns-instanceof-switch-jls.html#jls-15.20.2">
72 * JLS 15.20.2 The instanceof Operator</a>
73 *
74 * @implNote Some exactness checks describe a test which can be redirected
75 * safely through one of the existing methods. Those are omitted too (i.e.,
76 * {@code byte} to {@code char} can be redirected to
77 * {@link ExactConversionsSupport#isIntToCharExact(int)}, {@code short} to
78 * {@code byte} can be redirected to
79 * {@link ExactConversionsSupport#isIntToByteExact(int)} and similarly for
80 * {@code short} to {@code char}, {@code char} to {@code byte} and {@code char}
81 * to {@code short} to the corresponding methods that take an {@code int}).
82 *
83 * @since 23
84 */
85 public final class ExactConversionsSupport {
86
87 private ExactConversionsSupport() { }
88
89 /**
90 * Exactness method from int to byte
91 * @param n value
92 * @return true if and only if the passed value can be converted exactly to the target type
93 */
94 public static boolean isIntToByteExact(int n) {return n == (int)(byte)n;}
95
96 /**
97 * Exactness method from int to short
98 * @param n value
99 * @return true if and only if the passed value can be converted exactly to the target type
100 */
101 public static boolean isIntToShortExact(int n) {return n == (int)(short)n;}
102
103 /**
104 * Exactness method from int to char
105 * @param n value
106 * @return true if and only if the passed value can be converted exactly to the target type
107 */
108 public static boolean isIntToCharExact(int n) {return n == (int)(char)n;}
109
110 /**
111 * Exactness method from int to float
112 * @param n value
113 * @return true if and only if the passed value can be converted exactly to the target type
114 *
115 * @implSpec relies on the notion of representation equivalence defined in the
116 * specification of the {@linkplain Double} class.
117 */
118 public static boolean isIntToFloatExact(int n) {
119 return n == (int)(float)n && n != Integer.MAX_VALUE;
120 }
121 /**
122 * Exactness method from long to byte
123 * @param n value
124 * @return true if and only if the passed value can be converted exactly to the target type
125 */
126 public static boolean isLongToByteExact(long n) {return n == (long)(byte)n;}
127
128 /**
129 * Exactness method from long to short
130 * @param n value
131 * @return true if and only if the passed value can be converted exactly to the target type
132 */
133 public static boolean isLongToShortExact(long n) {return n == (long)(short)n;}
134
135 /**
136 * Exactness method from long to char
137 * @param n value
138 * @return true if and only if the passed value can be converted exactly to the target type
139 */
140 public static boolean isLongToCharExact(long n) {return n == (long)(char)n;}
141
142 /**
143 * Exactness method from long to int
144 * @param n value
145 * @return true if and only if the passed value can be converted exactly to the target type
146 */
147 public static boolean isLongToIntExact(long n) {return n == (long)(int)n;}
148
149 /**
150 * Exactness method from long to float
151 * @param n value
152 * @return true if and only if the passed value can be converted exactly to the target type
153 * @implSpec relies on the notion of representation equivalence defined in the
154 * specification of the {@linkplain Double} class.
155 */
156 public static boolean isLongToFloatExact(long n) {
157 return n == (long)(float)n && n != Long.MAX_VALUE;
158 }
159
160 /**
161 * Exactness method from long to double
162 * @param n value
163 * @return true if and only if the passed value can be converted exactly to the target type
164 * @implSpec relies on the notion of representation equivalence defined in the
165 * specification of the {@linkplain Double} class.
166 */
167 public static boolean isLongToDoubleExact(long n) {
168 return n == (long)(double)n && n != Long.MAX_VALUE;
169 }
170
171 /**
172 * Exactness method from float to byte
173 * @param n value
174 * @return true if and only if the passed value can be converted exactly to the target type
175 * @implSpec relies on the notion of representation equivalence defined in the
176 * specification of the {@linkplain Double} class.
177 */
178 public static boolean isFloatToByteExact(float n) {
179 return n == (float)(byte)n && !isNegativeZero(n);
180 }
181
182 /**
183 * Exactness method from float to short
184 * @param n value
185 * @return true if and only if the passed value can be converted exactly to the target type
186 * @implSpec relies on the notion of representation equivalence defined in the
187 * specification of the {@linkplain Double} class.
188 */
189 public static boolean isFloatToShortExact(float n) {
190 return n == (float)(short)n && !isNegativeZero(n);
191 }
192
193 /**
194 * Exactness method from float to char
195 * @param n value
196 * @return true if and only if the passed value can be converted exactly to the target type
197 * @implSpec relies on the notion of representation equivalence defined in the
198 * specification of the {@linkplain Double} class.
199 */
200 public static boolean isFloatToCharExact(float n) {
201 return n == (float)(char)n && !isNegativeZero(n);
202 }
203
204 /**
205 * Exactness method from float to int
206 * @param n value
207 * @return true if and only if the passed value can be converted exactly to the target type
208 * @implSpec relies on the notion of representation equivalence defined in the
209 * specification of the {@linkplain Double} class.
210 */
211 public static boolean isFloatToIntExact(float n) {
212 return n == (float)(int)n && n != 0x1p31f && !isNegativeZero(n);
213 }
214
215 /**
216 * Exactness method from float to long
217 * @param n value
218 * @return true if and only if the passed value can be converted exactly to the target type
219 * @implSpec relies on the notion of representation equivalence defined in the
220 * specification of the {@linkplain Double} class.
221 */
222 public static boolean isFloatToLongExact(float n) {
223 return n == (float)(long)n && n != 0x1p63f && !isNegativeZero(n);
224 }
225
226 /**
227 * Exactness method from double to byte
228 * @param n value
229 * @return true if and only if the passed value can be converted exactly to the target type
230 * @implSpec relies on the notion of representation equivalence defined in the
231 * specification of the {@linkplain Double} class.
232 */
233 public static boolean isDoubleToByteExact(double n) {
234 return n == (double)(byte)n && !isNegativeZero(n);
235 }
236
237 /**
238 * Exactness method from double to short
239 * @param n value
240 * @return true if and only if the passed value can be converted exactly to the target type
241 * @implSpec relies on the notion of representation equivalence defined in the
242 * specification of the {@linkplain Double} class.
243 */
244 public static boolean isDoubleToShortExact(double n){
245 return n == (double)(short)n && !isNegativeZero(n);
246 }
247
248 /**
249 * Exactness method from double to char
250 * @param n value
251 * @return true if and only if the passed value can be converted exactly to the target type
252 * @implSpec relies on the notion of representation equivalence defined in the
253 * specification of the {@linkplain Double} class.
254 */
255 public static boolean isDoubleToCharExact(double n) {
256 return n == (double)(char)n && !isNegativeZero(n);
257 }
258
259 /**
260 * Exactness method from double to int
261 * @param n value
262 * @return true if and only if the passed value can be converted exactly to the target type
263 * @implSpec relies on the notion of representation equivalence defined in the
264 * specification of the {@linkplain Double} class.
265 */
266 public static boolean isDoubleToIntExact(double n) {
267 return n == (double)(int)n && !isNegativeZero(n);
268 }
269
270 /**
271 * Exactness method from double to long
272 * @param n value
273 * @return true if and only if the passed value can be converted exactly to the target type
274 * @implSpec relies on the notion of representation equivalence defined in the
275 * specification of the {@linkplain Double} class.
276 */
277 public static boolean isDoubleToLongExact(double n) {
278 return n == (double)(long)n && n != 0x1p63 && !isNegativeZero(n);
279 }
280
281 /**
282 * Exactness method from double to float
283 * @param n value
284 * @return true if and only if the passed value can be converted exactly to the target type
285 * @implSpec relies on the notion of representation equivalence defined in the
286 * specification of the {@linkplain Double} class.
287 */
288 public static boolean isDoubleToFloatExact(double n) {
289 return n == (double)(float)n || n != n;
290 }
291
292 private static boolean isNegativeZero(float n) {
293 return Float.floatToRawIntBits(n) == Integer.MIN_VALUE;
294 }
295
296 private static boolean isNegativeZero(double n) {
297 return Double.doubleToRawLongBits(n) == Long.MIN_VALUE;
298 }
299 }