1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.math;
18
19 import static com.google.common.math.MathTesting.ALL_LONG_CANDIDATES;
20 import static com.google.common.math.MathTesting.ALL_ROUNDING_MODES;
21 import static com.google.common.math.MathTesting.ALL_SAFE_ROUNDING_MODES;
22 import static com.google.common.math.MathTesting.NEGATIVE_INTEGER_CANDIDATES;
23 import static com.google.common.math.MathTesting.NEGATIVE_LONG_CANDIDATES;
24 import static com.google.common.math.MathTesting.POSITIVE_LONG_CANDIDATES;
25 import static java.math.BigInteger.valueOf;
26 import static java.math.RoundingMode.UNNECESSARY;
27
28 import com.google.common.annotations.GwtCompatible;
29
30 import junit.framework.TestCase;
31
32 import java.math.BigDecimal;
33 import java.math.BigInteger;
34 import java.math.RoundingMode;
35
36
37
38
39
40
41 @GwtCompatible(emulated = true)
42 public class LongMathTest extends TestCase {
43
44 public void testLessThanBranchFree() {
45 for (long x : ALL_LONG_CANDIDATES) {
46 for (long y : ALL_LONG_CANDIDATES) {
47 BigInteger difference = BigInteger.valueOf(x).subtract(BigInteger.valueOf(y));
48 if (fitsInLong(difference)) {
49 int expected = (x < y) ? 1 : 0;
50 int actual = LongMath.lessThanBranchFree(x, y);
51 assertEquals(expected, actual);
52 }
53 }
54 }
55 }
56
57
58
59 public void testLog2ZeroAlwaysThrows() {
60 for (RoundingMode mode : ALL_ROUNDING_MODES) {
61 try {
62 LongMath.log2(0L, mode);
63 fail("Expected IllegalArgumentException");
64 } catch (IllegalArgumentException expected) {}
65 }
66 }
67
68 public void testLog2NegativeAlwaysThrows() {
69 for (long x : NEGATIVE_LONG_CANDIDATES) {
70 for (RoundingMode mode : ALL_ROUNDING_MODES) {
71 try {
72 LongMath.log2(x, mode);
73 fail("Expected IllegalArgumentException");
74 } catch (IllegalArgumentException expected) {}
75 }
76 }
77 }
78
79
80 public void testLog2MatchesBigInteger() {
81 for (long x : POSITIVE_LONG_CANDIDATES) {
82 for (RoundingMode mode : ALL_SAFE_ROUNDING_MODES) {
83
84 assertEquals(BigIntegerMath.log2(valueOf(x), mode), LongMath.log2(x, mode));
85 }
86 }
87 }
88
89
90 public void testLog2Exact() {
91 for (long x : POSITIVE_LONG_CANDIDATES) {
92
93 boolean isPowerOf2 = LongMath.isPowerOfTwo(x);
94 try {
95 assertEquals(x, 1L << LongMath.log2(x, UNNECESSARY));
96 assertTrue(isPowerOf2);
97 } catch (ArithmeticException e) {
98 assertFalse(isPowerOf2);
99 }
100 }
101 }
102
103
104
105
106
107
108
109
110
111 public void testGCDExhaustive() {
112 for (long a : POSITIVE_LONG_CANDIDATES) {
113 for (long b : POSITIVE_LONG_CANDIDATES) {
114 assertEquals(valueOf(a).gcd(valueOf(b)), valueOf(LongMath.gcd(a, b)));
115 }
116 }
117 }
118
119
120
121
122 public void testBinomial() {
123 for (int n = 0; n <= 70; n++) {
124 for (int k = 0; k <= n; k++) {
125 BigInteger expectedBig = BigIntegerMath.binomial(n, k);
126 long expectedLong = fitsInLong(expectedBig) ? expectedBig.longValue() : Long.MAX_VALUE;
127 assertEquals(expectedLong, LongMath.binomial(n, k));
128 }
129 }
130 }
131
132 public void testBinomialOutside() {
133 for (int n = 0; n <= 50; n++) {
134 try {
135 LongMath.binomial(n, -1);
136 fail("Expected IllegalArgumentException");
137 } catch (IllegalArgumentException expected) {}
138 try {
139 LongMath.binomial(n, n + 1);
140 fail("Expected IllegalArgumentException");
141 } catch (IllegalArgumentException expected) {}
142 }
143 }
144
145 public void testBinomialNegative() {
146 for (int n : NEGATIVE_INTEGER_CANDIDATES) {
147 try {
148 LongMath.binomial(n, 0);
149 fail("Expected IllegalArgumentException");
150 } catch (IllegalArgumentException expected) {}
151 }
152 }
153
154 public void testSqrtOfLongIsAtMostFloorSqrtMaxLong() {
155 long sqrtMaxLong = (long) Math.sqrt(Long.MAX_VALUE);
156 assertTrue(sqrtMaxLong <= LongMath.FLOOR_SQRT_MAX_LONG);
157 }
158
159
160
161
162
163 private static void assertMean(long expectedMean, long x, long y) {
164 assertEquals("The expectedMean should be the same as computeMeanSafely",
165 expectedMean, computeMeanSafely(x, y));
166 assertMean(x, y);
167 }
168
169
170
171
172
173 private static void assertMean(long x, long y) {
174 long expectedMean = computeMeanSafely(x, y);
175 assertEquals(expectedMean, LongMath.mean(x, y));
176 assertEquals("The mean of x and y should equal the mean of y and x",
177 expectedMean, LongMath.mean(y, x));
178 }
179
180
181
182
183
184 private static long computeMeanSafely(long x, long y) {
185 BigInteger bigX = BigInteger.valueOf(x);
186 BigInteger bigY = BigInteger.valueOf(y);
187 BigDecimal bigMean = new BigDecimal(bigX.add(bigY))
188 .divide(BigDecimal.valueOf(2), BigDecimal.ROUND_FLOOR);
189
190 return Long.parseLong(bigMean.toString());
191 }
192
193 private static boolean fitsInLong(BigInteger big) {
194 return big.bitLength() <= 63;
195 }
196 }
197