blob: 0f0c4799a433d52abf0e3f88080ddb9d8231a2dd [file] [log] [blame]
darcy32db4492009-01-26 19:49:26 -08001/*
2 * Copyright 2003 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 4074599 4939441
27 * @summary Tests for {Math, StrictMath}.log10
28 * @author Joseph D. Darcy
29 */
30
31import sun.misc.FpUtils;
32import sun.misc.DoubleConsts;
33
34public class Log10Tests {
35 private Log10Tests(){}
36
37 static final double infinityD = Double.POSITIVE_INFINITY;
38 static final double NaNd = Double.NaN;
39 static final double LN_10 = StrictMath.log(10.0);
40
41 // Initialize shared random number generator
42 static java.util.Random rand = new java.util.Random(0L);
43
44 static int testLog10Case(double input, double expected) {
45 int failures=0;
46
47 failures+=Tests.test("Math.log10(double)", input,
48 Math.log10(input), expected);
49
50 failures+=Tests.test("StrictMath.log10(double)", input,
51 StrictMath.log10(input), expected);
52
53 return failures;
54 }
55
56 static int testLog10() {
57 int failures = 0;
58
59 double [][] testCases = {
60 {Double.NaN, NaNd},
61 {Double.longBitsToDouble(0x7FF0000000000001L), NaNd},
62 {Double.longBitsToDouble(0xFFF0000000000001L), NaNd},
63 {Double.longBitsToDouble(0x7FF8555555555555L), NaNd},
64 {Double.longBitsToDouble(0xFFF8555555555555L), NaNd},
65 {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL), NaNd},
66 {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL), NaNd},
67 {Double.longBitsToDouble(0x7FFDeadBeef00000L), NaNd},
68 {Double.longBitsToDouble(0xFFFDeadBeef00000L), NaNd},
69 {Double.longBitsToDouble(0x7FFCafeBabe00000L), NaNd},
70 {Double.longBitsToDouble(0xFFFCafeBabe00000L), NaNd},
71 {Double.NEGATIVE_INFINITY, NaNd},
72 {-8.0, NaNd},
73 {-1.0, NaNd},
74 {-DoubleConsts.MIN_NORMAL, NaNd},
75 {-Double.MIN_VALUE, NaNd},
76 {-0.0, -infinityD},
77 {+0.0, -infinityD},
78 {+1.0, 0.0},
79 {Double.POSITIVE_INFINITY, infinityD},
80 };
81
82 // Test special cases
83 for(int i = 0; i < testCases.length; i++) {
84 failures += testLog10Case(testCases[i][0],
85 testCases[i][1]);
86 }
87
88 // Test log10(10^n) == n for integer n; 10^n, n < 0 is not
89 // exactly representable as a floating-point value -- up to
90 // 10^22 can be represented exactly
91 double testCase = 1.0;
92 for(int i = 0; i < 23; i++) {
93 failures += testLog10Case(testCase, i);
94 testCase *= 10.0;
95 }
96
97 // Test for gross inaccuracy by comparing to log; should be
98 // within a few ulps of log(x)/log(10)
99 for(int i = 0; i < 10000; i++) {
100 double input = Double.longBitsToDouble(rand.nextLong());
101 if(! FpUtils.isFinite(input))
102 continue; // avoid testing NaN and infinite values
103 else {
104 input = Math.abs(input);
105
106 double expected = StrictMath.log(input)/LN_10;
107 if( ! FpUtils.isFinite(expected))
108 continue; // if log(input) overflowed, try again
109 else {
110 double result;
111
112 if( Math.abs(((result=Math.log10(input)) - expected)/Math.ulp(expected)) > 3) {
113 failures++;
114 System.err.println("For input " + input +
115 ", Math.log10 was more than 3 ulps different from " +
116 "log(input)/log(10): log10(input) = " + result +
117 "\tlog(input)/log(10) = " + expected);
118 }
119
120 if( Math.abs(((result=StrictMath.log10(input)) - expected)/Math.ulp(expected)) > 3) {
121 failures++;
122 System.err.println("For input " + input +
123 ", StrictMath.log10 was more than 3 ulps different from " +
124 "log(input)/log(10): log10(input) = " + result +
125 "\tlog(input)/log(10) = " + expected);
126 }
127
128
129 }
130 }
131 }
132
133 // Test for accuracy and monotonicity near log10(1.0). From
134 // the Taylor expansion of log,
135 // log10(1+z) ~= (z -(z^2)/2)/LN_10;
136 {
137 double neighbors[] = new double[40];
138 double neighborsStrict[] = new double[40];
139 double z = Double.NaN;
140
141 // Test inputs greater than 1.0.
142 neighbors[0] = Math.log10(1.0);
143 neighborsStrict[0] = StrictMath.log10(1.0);
144
145 double input[] = new double[40];
146 int half = input.length/2;
147
148
149 // Initialize input to the 40 consecutive double values
150 // "centered" at 1.0.
151 double up = Double.NaN;
152 double down = Double.NaN;
153 for(int i = 0; i < half; i++) {
154 if (i == 0) {
155 input[half] = 1.0;
156 up = FpUtils.nextUp(1.0);
157 down = FpUtils.nextDown(1.0);
158 } else {
159 input[half + i] = up;
160 input[half - i] = down;
161 up = FpUtils.nextUp(up);
162 down = FpUtils.nextDown(down);
163 }
164 }
165 input[0] = FpUtils.nextDown(input[1]);
166
167 for(int i = 0; i < neighbors.length; i++) {
168 neighbors[i] = Math.log10(input[i]);
169 neighborsStrict[i] = StrictMath.log10(input[i]);
170
171 // Test accuracy.
172 z = input[i] - 1.0;
173 double expected = (z - (z*z)*0.5)/LN_10;
174 if ( Math.abs(neighbors[i] - expected ) > 3*Math.ulp(expected) ) {
175 failures++;
176 System.err.println("For input near 1.0 " + input[i] +
177 ", Math.log10(1+z) was more than 3 ulps different from " +
178 "(z-(z^2)/2)/ln(10): log10(input) = " + neighbors[i] +
179 "\texpected about = " + expected);
180 }
181
182 if ( Math.abs(neighborsStrict[i] - expected ) > 3*Math.ulp(expected) ) {
183 failures++;
184 System.err.println("For input near 1.0 " + input[i] +
185 ", StrictMath.log10(1+z) was more than 3 ulps different from " +
186 "(z-(z^2)/2)/ln(10): log10(input) = " + neighborsStrict[i] +
187 "\texpected about = " + expected);
188 }
189
190 // Test monotonicity
191 if( i > 0) {
192 if( neighbors[i-1] > neighbors[i] ) {
193 failures++;
194 System.err.println("Monotonicity failure for Math.log10 at " + input[i] +
195 " and prior value.");
196 }
197
198 if( neighborsStrict[i-1] > neighborsStrict[i] ) {
199 failures++;
200 System.err.println("Monotonicity failure for StrictMath.log10 at " + input[i] +
201 " and prior value.");
202 }
203 }
204 }
205
206 }
207
208 return failures;
209 }
210
211 public static void main(String argv[]) {
212 int failures = 0;
213
214 failures += testLog10();
215
216 if (failures > 0) {
217 System.err.println("Testing log10 incurred "
218 + failures + " failures.");
219 throw new RuntimeException();
220 }
221 }
222
223}