1/*
2 * Copyright (C) 2014 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.
20public class Main {
21
22  public static void assertEquals(int expected, int result) {
23    if (expected != result) {
24      throw new Error("Expected: " + expected + ", found: " + result);
25    }
26  }
27
28  public static void assertEquals(long expected, long result) {
29    if (expected != result) {
30      throw new Error("Expected: " + expected + ", found: " + result);
31    }
32  }
33
34  public static void assertEquals(float expected, float result) {
35    if (expected != result) {
36      throw new Error("Expected: " + expected + ", found: " + result);
37    }
38  }
39
40  public static void assertEquals(String expected, float result) {
41    if (!expected.equals(new Float(result).toString())) {
42      throw new Error("Expected: " + expected + ", found: " + result);
43    }
44  }
45
46  public static void assertEquals(double expected, double result) {
47    if (expected != result) {
48      throw new Error("Expected: " + expected + ", found: " + result);
49    }
50  }
51
52  public static void assertEquals(String expected, double result) {
53    if (!expected.equals(new Double(result).toString())) {
54      throw new Error("Expected: " + expected + ", found: " + result);
55    }
56  }
57
58  public static void assertIsNaN(float result) {
59    if (!Float.isNaN(result)) {
60      throw new Error("Expected NaN: " + result);
61    }
62  }
63
64  public static void assertIsNaN(double result) {
65    if (!Double.isNaN(result)) {
66      throw new Error("Expected NaN: " + result);
67    }
68  }
69
70  public static void main(String[] args) {
71    negInt();
72    $opt$noinline$InplaceNegOneInt(1);
73
74    negLong();
75    $opt$noinline$InplaceNegOneLong(1L);
76
77    negFloat();
78    negDouble();
79  }
80
81  private static void negInt() {
82    assertEquals(-1, $opt$noinline$NegInt(1));
83    assertEquals(1, $opt$noinline$NegInt(-1));
84    assertEquals(0, $opt$noinline$NegInt(0));
85    assertEquals(51, $opt$noinline$NegInt(-51));
86    assertEquals(-51, $opt$noinline$NegInt(51));
87    assertEquals(2147483647, $opt$noinline$NegInt(-2147483647));  // -(2^31 - 1)
88    assertEquals(-2147483647, $opt$noinline$NegInt(2147483647));  // 2^31 - 1
89    // From the Java 7 SE Edition specification:
90    // http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.15.4
91    //
92    //   For integer values, negation is the same as subtraction from
93    //   zero.  The Java programming language uses two's-complement
94    //   representation for integers, and the range of two's-complement
95    //   values is not symmetric, so negation of the maximum negative
96    //   int or long results in that same maximum negative number.
97    //   Overflow occurs in this case, but no exception is thrown.
98    //   For all integer values x, -x equals (~x)+1.''
99    assertEquals(-2147483648, $opt$noinline$NegInt(-2147483648)); // -(2^31)
100  }
101
102  private static void negLong() {
103    assertEquals(-1L, $opt$noinline$NegLong(1L));
104    assertEquals(1L, $opt$noinline$NegLong(-1L));
105    assertEquals(0L, $opt$noinline$NegLong(0L));
106    assertEquals(51L, $opt$noinline$NegLong(-51L));
107    assertEquals(-51L, $opt$noinline$NegLong(51L));
108
109    assertEquals(2147483647L, $opt$noinline$NegLong(-2147483647L));  // -(2^31 - 1)
110    assertEquals(-2147483647L, $opt$noinline$NegLong(2147483647L));  // (2^31 - 1)
111    assertEquals(2147483648L, $opt$noinline$NegLong(-2147483648L));  // -(2^31)
112    assertEquals(-2147483648L, $opt$noinline$NegLong(2147483648L));  // 2^31
113
114    assertEquals(9223372036854775807L, $opt$noinline$NegLong(-9223372036854775807L));  // -(2^63 - 1)
115    assertEquals(-9223372036854775807L, $opt$noinline$NegLong(9223372036854775807L));  // 2^63 - 1
116    // See remark regarding the negation of the maximum negative
117    // (long) value in negInt().
118    assertEquals(-9223372036854775808L, $opt$noinline$NegLong(-9223372036854775808L)); // -(2^63)
119  }
120
121  private static void negFloat() {
122     assertEquals("-0.0", $opt$noinline$NegFloat(0F));
123     assertEquals("0.0", $opt$noinline$NegFloat(-0F));
124     assertEquals(-1F, $opt$noinline$NegFloat(1F));
125     assertEquals(1F, $opt$noinline$NegFloat(-1F));
126     assertEquals(51F, $opt$noinline$NegFloat(-51F));
127     assertEquals(-51F, $opt$noinline$NegFloat(51F));
128
129     assertEquals(-0.1F, $opt$noinline$NegFloat(0.1F));
130     assertEquals(0.1F, $opt$noinline$NegFloat(-0.1F));
131     assertEquals(343597.38362F, $opt$noinline$NegFloat(-343597.38362F));
132     assertEquals(-343597.38362F, $opt$noinline$NegFloat(343597.38362F));
133
134     assertEquals(-Float.MIN_NORMAL, $opt$noinline$NegFloat(Float.MIN_NORMAL));
135     assertEquals(Float.MIN_NORMAL, $opt$noinline$NegFloat(-Float.MIN_NORMAL));
136     assertEquals(-Float.MIN_VALUE, $opt$noinline$NegFloat(Float.MIN_VALUE));
137     assertEquals(Float.MIN_VALUE, $opt$noinline$NegFloat(-Float.MIN_VALUE));
138     assertEquals(-Float.MAX_VALUE, $opt$noinline$NegFloat(Float.MAX_VALUE));
139     assertEquals(Float.MAX_VALUE, $opt$noinline$NegFloat(-Float.MAX_VALUE));
140
141     assertEquals(Float.NEGATIVE_INFINITY, $opt$noinline$NegFloat(Float.POSITIVE_INFINITY));
142     assertEquals(Float.POSITIVE_INFINITY, $opt$noinline$NegFloat(Float.NEGATIVE_INFINITY));
143     assertIsNaN($opt$noinline$NegFloat(Float.NaN));
144  }
145
146  private static void negDouble() {
147     assertEquals("-0.0", $opt$noinline$NegDouble(0D));
148     assertEquals("0.0", $opt$noinline$NegDouble(-0D));
149     assertEquals(-1D, $opt$noinline$NegDouble(1D));
150     assertEquals(1D, $opt$noinline$NegDouble(-1D));
151     assertEquals(51D, $opt$noinline$NegDouble(-51D));
152     assertEquals(-51D, $opt$noinline$NegDouble(51D));
153
154     assertEquals(-0.1D, $opt$noinline$NegDouble(0.1D));
155     assertEquals(0.1D, $opt$noinline$NegDouble(-0.1D));
156     assertEquals(343597.38362D, $opt$noinline$NegDouble(-343597.38362D));
157     assertEquals(-343597.38362D, $opt$noinline$NegDouble(343597.38362D));
158
159     assertEquals(-Double.MIN_NORMAL, $opt$noinline$NegDouble(Double.MIN_NORMAL));
160     assertEquals(Double.MIN_NORMAL, $opt$noinline$NegDouble(-Double.MIN_NORMAL));
161     assertEquals(-Double.MIN_VALUE, $opt$noinline$NegDouble(Double.MIN_VALUE));
162     assertEquals(Double.MIN_VALUE, $opt$noinline$NegDouble(-Double.MIN_VALUE));
163     assertEquals(-Double.MAX_VALUE, $opt$noinline$NegDouble(Double.MAX_VALUE));
164     assertEquals(Double.MAX_VALUE, $opt$noinline$NegDouble(-Double.MAX_VALUE));
165
166     assertEquals(Double.NEGATIVE_INFINITY, $opt$noinline$NegDouble(Double.POSITIVE_INFINITY));
167     assertEquals(Double.POSITIVE_INFINITY, $opt$noinline$NegDouble(Double.NEGATIVE_INFINITY));
168     assertIsNaN($opt$noinline$NegDouble(Double.NaN));
169  }
170
171
172  static boolean doThrow = false;
173
174  private static void $opt$noinline$InplaceNegOneInt(int a) {
175    if (doThrow) {
176      // Try defeating inlining.
177      throw new Error();
178    }
179    a = -a;
180    assertEquals(-1, a);
181  }
182
183  private static void $opt$noinline$InplaceNegOneLong(long a) {
184    if (doThrow) {
185      // Try defeating inlining.
186      throw new Error();
187    }
188    a = -a;
189    assertEquals(-1L, a);
190  }
191
192  private static int $opt$noinline$NegInt(int a){
193    if (doThrow) {
194      // Try defeating inlining.
195      throw new Error();
196    }
197    return -a;
198  }
199
200  private static long $opt$noinline$NegLong(long a){
201    if (doThrow) {
202      // Try defeating inlining.
203      throw new Error();
204    }
205    return -a;
206  }
207
208  private static float $opt$noinline$NegFloat(float a){
209    if (doThrow) {
210      // Try defeating inlining.
211      throw new Error();
212    }
213    return -a;
214  }
215
216  private static double $opt$noinline$NegDouble(double a){
217    if (doThrow) {
218      // Try defeating inlining.
219      throw new Error();
220    }
221    return -a;
222  }
223}
224