1 /* 2 * Copyright (C) 2011 The Guava Authors 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 package com.google.common.math; 18 19 import static java.math.BigInteger.ONE; 20 import static java.math.BigInteger.ZERO; 21 import static java.math.RoundingMode.CEILING; 22 import static java.math.RoundingMode.DOWN; 23 import static java.math.RoundingMode.FLOOR; 24 import static java.math.RoundingMode.HALF_DOWN; 25 import static java.math.RoundingMode.HALF_EVEN; 26 import static java.math.RoundingMode.HALF_UP; 27 import static java.math.RoundingMode.UP; 28 import static java.util.Arrays.asList; 29 30 import com.google.common.annotations.GwtCompatible; 31 import com.google.common.base.Function; 32 import com.google.common.base.Predicate; 33 import com.google.common.collect.ImmutableList; 34 import com.google.common.collect.ImmutableSet; 35 import com.google.common.collect.Iterables; 36 import com.google.common.primitives.Doubles; 37 38 import java.math.BigInteger; 39 import java.math.RoundingMode; 40 41 /** 42 * Exhaustive input sets for every integral type. 43 * 44 * @author Louis Wasserman 45 */ 46 @GwtCompatible 47 public class MathTesting { 48 static final ImmutableSet<RoundingMode> ALL_ROUNDING_MODES = ImmutableSet.copyOf(RoundingMode 49 .values()); 50 51 static final ImmutableList<RoundingMode> ALL_SAFE_ROUNDING_MODES = ImmutableList.of(DOWN, UP, 52 FLOOR, CEILING, HALF_EVEN, HALF_UP, HALF_DOWN); 53 54 // Exponents to test for the pow() function. 55 static final ImmutableList<Integer> EXPONENTS = ImmutableList.of(0, 1, 2, 3, 4, 7, 10, 15, 56 20, 25, 40, 70); 57 58 /* Helper function to make a Long value from an Integer. */ 59 private static final Function<Integer, Long> TO_LONG = new Function<Integer, Long>() { 60 @Override 61 public Long apply(Integer n) { 62 return Long.valueOf(n); 63 } 64 }; 65 66 /* Helper function to make a BigInteger value from a Long. */ 67 private static final Function<Long, BigInteger> TO_BIGINTEGER = 68 new Function<Long, BigInteger>() { 69 @Override 70 public BigInteger apply(Long n) { 71 return BigInteger.valueOf(n); 72 } 73 }; 74 75 private static final Function<Integer, Integer> NEGATE_INT = new Function<Integer, Integer>() { 76 @Override 77 public Integer apply(Integer x) { 78 return -x; 79 } 80 }; 81 82 private static final Function<Long, Long> NEGATE_LONG = new Function<Long, Long>() { 83 @Override 84 public Long apply(Long x) { 85 return -x; 86 } 87 }; 88 89 private static final Function<BigInteger, BigInteger> NEGATE_BIGINT = 90 new Function<BigInteger, BigInteger>() { 91 @Override 92 public BigInteger apply(BigInteger x) { 93 return x.negate(); 94 } 95 }; 96 97 /* 98 * This list contains values that attempt to provoke overflow in integer operations. It contains 99 * positive values on or near 2^N for N near multiples of 8 (near byte boundaries). 100 */ 101 static final ImmutableSet<Integer> POSITIVE_INTEGER_CANDIDATES; 102 103 static final Iterable<Integer> NEGATIVE_INTEGER_CANDIDATES; 104 105 static final Iterable<Integer> NONZERO_INTEGER_CANDIDATES; 106 107 static final Iterable<Integer> ALL_INTEGER_CANDIDATES; 108 109 static { 110 ImmutableSet.Builder<Integer> intValues = ImmutableSet.builder(); 111 // Add boundary values manually to avoid over/under flow (this covers 2^N for 0 and 31). 112 intValues.add(Integer.MAX_VALUE - 1, Integer.MAX_VALUE); 113 // Add values up to 40. This covers cases like "square of a prime" and such. 114 for (int i = 1; i <= 40; i++) { 115 intValues.add(i); 116 } 117 // Now add values near 2^N for lots of values of N. 118 for (int exponent : asList(2, 3, 4, 9, 15, 16, 17, 24, 25, 30)) { 119 int x = 1 << exponent; intValues.add(x, x + 1, x - 1)120 intValues.add(x, x + 1, x - 1); 121 } 122 intValues.add(9999).add(10000).add(10001).add(1000000); // near powers of 10 123 intValues.add(5792).add(5793); // sqrt(2^25) rounded up and down 124 POSITIVE_INTEGER_CANDIDATES = intValues.build(); 125 NEGATIVE_INTEGER_CANDIDATES = ImmutableList.copyOf(Iterables.concat( 126 Iterables.transform(POSITIVE_INTEGER_CANDIDATES, NEGATE_INT), 127 ImmutableList.of(Integer.MIN_VALUE))); 128 NONZERO_INTEGER_CANDIDATES = ImmutableList.copyOf( 129 Iterables.concat(POSITIVE_INTEGER_CANDIDATES, NEGATIVE_INTEGER_CANDIDATES)); 130 ALL_INTEGER_CANDIDATES = Iterables.concat(NONZERO_INTEGER_CANDIDATES, ImmutableList.of(0)); 131 } 132 133 /* 134 * This list contains values that attempt to provoke overflow in long operations. It contains 135 * positive values on or near 2^N for N near multiples of 8 (near byte boundaries). This list is 136 * a superset of POSITIVE_INTEGER_CANDIDATES. 137 */ 138 static final ImmutableSet<Long> POSITIVE_LONG_CANDIDATES; 139 140 static final Iterable<Long> NEGATIVE_LONG_CANDIDATES; 141 142 static final Iterable<Long> NONZERO_LONG_CANDIDATES; 143 144 static final Iterable<Long> ALL_LONG_CANDIDATES; 145 146 static { 147 ImmutableSet.Builder<Long> longValues = ImmutableSet.builder(); 148 // First of all add all the integer candidate values. Iterables.transform(POSITIVE_INTEGER_CANDIDATES, TO_LONG)149 longValues.addAll(Iterables.transform(POSITIVE_INTEGER_CANDIDATES, TO_LONG)); 150 // Add boundary values manually to avoid over/under flow (this covers 2^N for 31 and 63). 151 longValues.add(Integer.MAX_VALUE + 1L, Long.MAX_VALUE - 1L, Long.MAX_VALUE); 152 153 // Now add values near 2^N for lots of values of N. 154 for (int exponent : asList(32, 33, 39, 40, 41, 47, 48, 49, 55, 56, 57)) { 155 long x = 1L << exponent; longValues.add(x, x + 1, x - 1)156 longValues.add(x, x + 1, x - 1); 157 } 158 longValues.add(194368031998L).add(194368031999L); // sqrt(2^75) rounded up and down 159 POSITIVE_LONG_CANDIDATES = longValues.build(); 160 NEGATIVE_LONG_CANDIDATES = 161 Iterables.concat(Iterables.transform(POSITIVE_LONG_CANDIDATES, NEGATE_LONG), 162 ImmutableList.of(Long.MIN_VALUE)); 163 NONZERO_LONG_CANDIDATES = Iterables.concat(POSITIVE_LONG_CANDIDATES, NEGATIVE_LONG_CANDIDATES); 164 ALL_LONG_CANDIDATES = Iterables.concat(NONZERO_LONG_CANDIDATES, ImmutableList.of(0L)); 165 } 166 167 /* 168 * This list contains values that attempt to provoke overflow in big integer operations. It 169 * contains positive values on or near 2^N for N near multiples of 8 (near byte boundaries). This 170 * list is a superset of POSITIVE_LONG_CANDIDATES. 171 */ 172 static final ImmutableSet<BigInteger> POSITIVE_BIGINTEGER_CANDIDATES; 173 174 static final Iterable<BigInteger> NEGATIVE_BIGINTEGER_CANDIDATES; 175 176 static final Iterable<BigInteger> NONZERO_BIGINTEGER_CANDIDATES; 177 178 static final Iterable<BigInteger> ALL_BIGINTEGER_CANDIDATES; 179 180 static { 181 ImmutableSet.Builder<BigInteger> bigValues = ImmutableSet.builder(); 182 // First of all add all the long candidate values. Iterables.transform(POSITIVE_LONG_CANDIDATES, TO_BIGINTEGER)183 bigValues.addAll(Iterables.transform(POSITIVE_LONG_CANDIDATES, TO_BIGINTEGER)); 184 // Add boundary values manually to avoid over/under flow. 185 bigValues.add(BigInteger.valueOf(Long.MAX_VALUE).add(ONE)); 186 // Now add values near 2^N for lots of values of N. 187 for (int exponent : asList(64, 65, 71, 72, 73, 79, 80, 81, 255, 256, 257, 511, 512, 513, 188 Double.MAX_EXPONENT - 1, Double.MAX_EXPONENT, Double.MAX_EXPONENT + 1)) { 189 BigInteger x = ONE.shiftLeft(exponent); bigValues.add(x, x.add(ONE), x.subtract(ONE))190 bigValues.add(x, x.add(ONE), x.subtract(ONE)); 191 } bigValues.add(new BigInteger("218838949120258359057546633"))192 bigValues.add(new BigInteger("218838949120258359057546633")); // sqrt(2^175) rounded up and 193 // down bigValues.add(new BigInteger("218838949120258359057546634"))194 bigValues.add(new BigInteger("218838949120258359057546634")); 195 POSITIVE_BIGINTEGER_CANDIDATES = bigValues.build(); 196 NEGATIVE_BIGINTEGER_CANDIDATES = 197 Iterables.transform(POSITIVE_BIGINTEGER_CANDIDATES, NEGATE_BIGINT); 198 NONZERO_BIGINTEGER_CANDIDATES = 199 Iterables.concat(POSITIVE_BIGINTEGER_CANDIDATES, NEGATIVE_BIGINTEGER_CANDIDATES); 200 ALL_BIGINTEGER_CANDIDATES = 201 Iterables.concat(NONZERO_BIGINTEGER_CANDIDATES, ImmutableList.of(ZERO)); 202 } 203 204 static final ImmutableSet<Double> INTEGRAL_DOUBLE_CANDIDATES; 205 static final ImmutableSet<Double> FRACTIONAL_DOUBLE_CANDIDATES; 206 static final Iterable<Double> INFINITIES = Doubles.asList( 207 Double.POSITIVE_INFINITY, 208 Double.NEGATIVE_INFINITY); 209 static final Iterable<Double> FINITE_DOUBLE_CANDIDATES; 210 static final Iterable<Double> POSITIVE_FINITE_DOUBLE_CANDIDATES; 211 static final Iterable<Double> ALL_DOUBLE_CANDIDATES; 212 static final Iterable<Double> DOUBLE_CANDIDATES_EXCEPT_NAN; 213 static { 214 ImmutableSet.Builder<Double> integralBuilder = ImmutableSet.builder(); 215 ImmutableSet.Builder<Double> fractionalBuilder = ImmutableSet.builder(); 216 integralBuilder.addAll(Doubles.asList(0.0, -0.0, Double.MAX_VALUE, -Double.MAX_VALUE)); 217 // Add small multiples of MIN_VALUE and MIN_NORMAL 218 for (int scale = 1; scale <= 4; scale++) { 219 for (double d : Doubles.asList(Double.MIN_VALUE, Double.MIN_NORMAL)) { 220 fractionalBuilder.add(d * scale).add(-d * scale); 221 } 222 } 223 for (double d : Doubles.asList(0, 1, 2, 7, 51, 102, Math.scalb(1.0, 53), Integer.MIN_VALUE, 224 Integer.MAX_VALUE, Long.MIN_VALUE, Long.MAX_VALUE)) { 225 for (double delta : Doubles.asList(0.0, 1.0, 2.0)) { 226 integralBuilder.addAll(Doubles.asList(d + delta, d - delta, -d - delta, -d + delta)); 227 } 228 for (double delta : Doubles.asList(0.01, 0.1, 0.25, 0.499, 0.5, 0.501, 0.7, 0.8)) { 229 double x = d + delta; 230 if (x != Math.round(x)) { 231 fractionalBuilder.add(x); 232 } 233 } 234 } 235 INTEGRAL_DOUBLE_CANDIDATES = integralBuilder.build(); 236 fractionalBuilder.add(1.414).add(1.415).add(Math.sqrt(2)); 237 fractionalBuilder.add(5.656).add(5.657).add(4 * Math.sqrt(2)); 238 for (double d : INTEGRAL_DOUBLE_CANDIDATES) { 239 double x = 1 / d; 240 if (x != Math.rint(x)) { 241 fractionalBuilder.add(x); 242 } 243 } 244 FRACTIONAL_DOUBLE_CANDIDATES = fractionalBuilder.build(); 245 FINITE_DOUBLE_CANDIDATES = 246 Iterables.concat(FRACTIONAL_DOUBLE_CANDIDATES, INTEGRAL_DOUBLE_CANDIDATES); 247 POSITIVE_FINITE_DOUBLE_CANDIDATES = 248 Iterables.filter(FINITE_DOUBLE_CANDIDATES, new Predicate<Double>() { 249 @Override 250 public boolean apply(Double input) { 251 return input.doubleValue() > 0.0; 252 } 253 }); 254 DOUBLE_CANDIDATES_EXCEPT_NAN = Iterables.concat(FINITE_DOUBLE_CANDIDATES, INFINITIES); 255 ALL_DOUBLE_CANDIDATES = 256 Iterables.concat(DOUBLE_CANDIDATES_EXCEPT_NAN, asList(Double.NaN)); 257 } 258 } 259