xref: /aosp_15_r20/art/test/057-math-intrinsics/src/CopySignTest.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // Note that $opt$ is a marker for the optimizing compiler to test
18 // it does compile the method, and that $noinline$ is a marker to
19 // test that it does not inline it.
20 
21 public class CopySignTest {
22 
main()23   public static void main() {
24     copySignFloat();
25     copySignDouble();
26   }
27 
$opt$noinline$copySignFloat(float a, float b)28   private static float $opt$noinline$copySignFloat(float a, float b) {
29     return Math.copySign(a, b);
30   }
31 
copySignFloat()32   private static void copySignFloat() {
33     float testCases [][] = {
34       { +0.0f,
35          Float.MIN_VALUE,
36          0x0.fffffcP-126f,
37          0x0.fffffeP-126f,
38          Float.MIN_NORMAL,
39          1.0f,
40          3.0f,
41          0x1.fffffcP+127f,
42          Float.MAX_VALUE,
43          Float.POSITIVE_INFINITY,
44          Float.NaN
45       },
46       {  Float.NEGATIVE_INFINITY,
47         -Float.MAX_VALUE,
48         -3.0f,
49         -1.0f,
50         -Float.MIN_NORMAL,
51         -0x0.fffffcP-126f,
52         -0x0.fffffeP-126f,
53         -Float.MIN_VALUE,
54         -0.0f,
55          Float.intBitsToFloat(0xFFC00000),  // "negative" NaN
56         -0x1.fffffcP+127f
57       }
58     };
59 
60     for (int i = 0; i < 2; i++) {
61       for (int j = 0; j < 2; j++) {
62         for (int m = 0; m < testCases[i].length; m++) {
63           for (int n = 0; n < testCases[j].length; n++) {
64             float expected = (j == 0 ? 1.0f : -1.0f) * Math.abs(testCases[i][m]);
65 
66             float calculated = Math.copySign(testCases[i][m], testCases[j][n]);
67             if (Float.isNaN(testCases[i][m])) {
68               assertEquals(calculated, Float.NaN);
69             } else if (Float.isNaN(testCases[j][n])) {
70               assertEquals(Math.abs(calculated), Math.abs(testCases[i][m]));
71             } else {
72               assertEquals(calculated, expected);
73             }
74 
75             calculated = $opt$noinline$copySignFloat(testCases[i][m], testCases[j][n]);
76             if (Float.isNaN(testCases[i][m])) {
77               assertEquals(calculated, Float.NaN);
78             } else if (Float.isNaN(testCases[j][n])) {
79               assertEquals(Math.abs(calculated), Math.abs(testCases[i][m]));
80             } else {
81               assertEquals(calculated, expected);
82             }
83           }
84         }
85       }
86     }
87   }
88 
$opt$noinline$copySignDouble(double a, double b)89   private static double $opt$noinline$copySignDouble(double a, double b) {
90     return Math.copySign(a, b);
91   }
92 
copySignDouble()93   private static void copySignDouble() {
94     double testCases [][] = {
95       { +0.0d,
96          Double.MIN_VALUE,
97          0x0.ffffffffffffeP-1022,
98          0x0.fffffffffffffP-1022,
99          Double.MIN_NORMAL,
100          1.0d,
101          3.0d,
102          0x1.ffffffffffffeP+1023,
103          Double.MAX_VALUE,
104          Double.POSITIVE_INFINITY,
105          Double.NaN
106       },
107       {  Double.NEGATIVE_INFINITY,
108         -Double.MAX_VALUE,
109         -3.0d,
110         -1.0d,
111         -Double.MIN_NORMAL,
112         -0x0.ffffffffffffeP-1022,
113         -0x0.fffffffffffffP-1022,
114         -Double.MIN_VALUE,
115         -0.0d,
116          Double.longBitsToDouble(0xfff8000000000000L),  // "negative" NaN
117         -0x1.ffffffffffffeP+1023
118       }
119     };
120 
121     for (int i = 0; i < 2; i++) {
122       for (int j = 0; j < 2; j++) {
123         for (int m = 0; m < testCases[i].length; m++) {
124           for (int n = 0; n < testCases[j].length; n++) {
125             double expected = (j == 0 ? 1.0f : -1.0f) * Math.abs(testCases[i][m]);
126 
127             double calculated = Math.copySign(testCases[i][m], testCases[j][n]);
128             if (Double.isNaN(testCases[i][m])) {
129               assertEquals(calculated, Double.NaN);
130             } else if (Double.isNaN(testCases[j][n])) {
131               assertEquals(Math.abs(calculated), Math.abs(testCases[i][m]));
132             } else {
133               assertEquals(calculated, expected);
134             }
135 
136             calculated = $opt$noinline$copySignDouble(testCases[i][m], testCases[j][n]);
137             if (Double.isNaN(testCases[i][m])) {
138               assertEquals(calculated, Double.NaN);
139             } else if (Double.isNaN(testCases[j][n])) {
140               assertEquals(Math.abs(calculated), Math.abs(testCases[i][m]));
141             } else {
142               assertEquals(calculated, expected);
143             }
144           }
145         }
146       }
147     }
148   }
149 
assertEquals(float calculated, float expected)150   private static void assertEquals(float calculated, float expected) {
151     if (0 != Float.compare(calculated, expected)) {
152       throw new Error("Expected: " + expected + ", found: " + calculated);
153     }
154   }
155 
assertEquals(double calculated, double expected)156   private static void assertEquals(double calculated, double expected) {
157     if (0 != Double.compare(calculated, expected)) {
158       throw new Error("Expected: " + expected + ", found: " + calculated);
159     }
160   }
161 
162 }
163