1 /*
2  * Copyright (c) 2002, 2020, 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.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  *
27  * @summary converted from VM Testbase runtime/jbe/subcommon/subcommon02.
28  * VM Testbase keywords: [runtime]
29  * VM Testbase comments: 7190319
30  *
31  * @library /vmTestbase
32  *          /test/lib
33  * @run main/othervm vm.compiler.jbe.subcommon.subcommon02.subcommon02
34  */
35 
36 package vm.compiler.jbe.subcommon.subcommon02;
37 
38 /* -- Common subexpression elimination testing
39    Using global common subexpression in method fopt() to calculate x**n.
40  */
41 import java.io.*;
42 
43 public class subcommon02 {
44     int LEN = 5000;
45     int WIDTH = 20;
46     int ngrt10000 = 0; // number of elements > 10,000
47     int ngrtO10000 = 0;
48     int ngrt1000 = 0; // number of elements > 1,000
49     int ngrtO1000 = 0;
50     int ngrt100 = 0; // number of elements > 100
51     int ngrtO100 = 0;
52     int nsmet100 = 0; // number of elements <= 100
53     int nsmetO100 = 0;
54     double a[][] = new double[LEN][WIDTH];
55     double aopt[][] = new double[LEN][WIDTH];
56 
main(String args[])57     public static void main(String args[]) {
58         subcommon02 sce = new subcommon02();
59 
60         sce.f();
61         sce.fopt();
62         if (sce.eCheck()) {
63             System.out.println("Test subcommon02 Passed.");
64         } else {
65             throw new Error("Test subcommon02 Failed.");
66         }
67     }
68 
69 
nPower(int x, int pwr)70     double nPower(int x, int pwr) {
71         return Math.pow(x, pwr); // x**pwr
72     }
73 
74     // non-optimized version
f()75     void f() {
76         for (int x = 0; x < LEN; x++) {
77             for (int n = 0; n < WIDTH; n++) {
78                 if (nPower(x, n) > 10000) {
79                     a[x][n] = nPower(x, n);
80                     ngrt10000++;
81                 }
82                 else if (nPower(x, n) > 1000) {
83                     a[x][n] = nPower(x, n);
84                     ngrt1000++;
85                 }
86                 else if (nPower(x, n) > 100) {
87                     a[x][n] = nPower(x, n);
88                     ngrt100++;
89                 }
90                 else {
91                     a[x][n] = nPower(x, n);
92                     nsmet100++;
93                 }
94             }
95         }
96     }
97 
98     // hand-optimized version
fopt()99     void fopt() {
100         for (int x = 0; x < LEN; x++) {
101             for (int n = 0; n < WIDTH; n++) {
102                 double tmp = nPower(x, n);
103 
104                 aopt[x][n] = tmp;
105                 if (tmp > 10000)
106                     ngrtO10000++;
107                 else if (tmp > 1000)
108                     ngrtO1000++;
109                 else if (tmp > 100)
110                     ngrtO100++;
111                 else
112                     nsmetO100++;
113             }
114         }
115     }
116 
117     // Compare non-optimized and hand-optimized results
eCheck()118     boolean eCheck() {
119         boolean r = true;
120 
121         for (int i = 0; i < LEN; i++) {
122             for (int j = 0; j < WIDTH; j++) {
123               // if (a[i][j] != aopt[i][j]) {
124               if (ulpDiff(a[i][j], aopt[i][j]) > 1) {
125                     System.out.println("Bad result: a["+i+","+j+"]="+a[i][j]+"; aopt["+i+","+j+"]="+aopt[i][j]);
126                     r = false;
127                 }
128             }
129         }
130 
131         if ((ngrt10000!=ngrtO10000) || (ngrt1000!=ngrtO1000) || (ngrt100!=ngrtO100) || (nsmetO100!=nsmetO100)) {
132             System.out.println("Bad result: number of elements found is not matching");
133             r = false;
134         }
135         return r;
136     }
137 
138     /**
139      * Paired-down nextAfter routine
140      */
nextAfter(double base, double direction)141     public  static double nextAfter(double base, double direction) {
142         //first check for NaN values
143         if (Double.isNaN(base) || Double.isNaN(direction)) {
144             // return a NaN dervied from the input NaN(s)
145             return base + direction;
146         } else if (base == direction) {
147             return base;
148         } else  {
149             long doppelganger;
150             double result=0.0;
151 
152             doppelganger = Double.doubleToLongBits(base + 0.0);
153             if (direction > base) //next greater value
154             {
155                 if (doppelganger >= 0 )
156                     result = Double.longBitsToDouble(++doppelganger);
157                 else
158                     result = Double.longBitsToDouble(--doppelganger);
159             } else if (direction < base) { // calculate next lesser value
160                 if (doppelganger > 0)
161                     result = Double.longBitsToDouble(--doppelganger);
162                 else if (doppelganger < 0)
163                     result = Double.longBitsToDouble(++doppelganger);
164                 else
165                     /*
166                      * doppelganger==0L, result is -MIN_VALUE
167                      *
168                      * The transition from zero (implicitly
169                      * positive) to the smallest negative
170                      * signed magnitude value must be done
171                      * explicitly.
172                      */
173                     result = -Double.MIN_VALUE;
174             }
175 
176             return result;
177         }
178     }
179 
180     /*
181      * return ulp of a floating-point value
182      */
ulp(double d)183     static double ulp(double d) {
184         d = Math.abs(d);        // don't worry about negative numbers
185 
186         if(Double.isNaN(d))
187             return Double.NaN;
188         else if(Double.isInfinite(d))
189             return Double.POSITIVE_INFINITY;
190         else {
191             // can't represent (Double.MAX_VALUE + ulp) so special case it
192             if(d == Double.MAX_VALUE)
193                 return 1.9958403095347198E292; // 2^971
194             else
195                 return nextAfter(d, Double.POSITIVE_INFINITY) - d;
196         }
197     }
198 
199 
200     /*
201      * return signed difference in ulps between two floating-point
202      * values.  ulpDiff(NaN, NaN) is zero.
203      */
ulpDiff(double ref, double test)204     static double ulpDiff(double ref, double test) {
205         double ulp;
206         // assume ref is "correct" value
207 
208         // Infinity, NaN handling
209         if(Double.isInfinite(ref)) {
210             if(ref == test)
211                 return 0.0;
212             else
213                 return Double.POSITIVE_INFINITY;
214         } else  if(Double.isNaN(ref)) {
215             if(Double.isNaN(test))
216                 return 0.0;
217             else
218                 return Double.NaN;
219         }
220         else {
221             ulp = ulp(ref);
222             // the expression below can overflow
223             return (test - ref) / ulp;
224         }
225     }
226 
227 }
228