summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Beaumont <dbeaumont@google.com>2011-10-31 18:43:24 -0400
committerMichael Bolin <bolinfest@google.com>2011-10-31 18:43:24 -0400
commitb9d250e7997c91a27551d7d5ba7f8d9409bb9cec (patch)
tree236da7403ef88e72a438daed64a1ea4a305ac873
parente3151c74f4ab0a69bfcbd867409881a96aafdd9e (diff)
downloads2-geometry-library-java-b9d250e7997c91a27551d7d5ba7f8d9409bb9cec.tar.gz
Removed DoubleMath from geometry package and inlined the one function that was
actually ever being invoked into S2.java. ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=24952377
-rw-r--r--src/com/google/common/geometry/DoubleMath.java78
-rw-r--r--src/com/google/common/geometry/S2.java43
-rw-r--r--tests/com/google/common/geometry/DoubleMathTest.java69
-rw-r--r--tests/com/google/common/geometry/S2Test.java14
4 files changed, 49 insertions, 155 deletions
diff --git a/src/com/google/common/geometry/DoubleMath.java b/src/com/google/common/geometry/DoubleMath.java
deleted file mode 100644
index 8d64b06..0000000
--- a/src/com/google/common/geometry/DoubleMath.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2005 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.common.geometry;
-
-/**
- * Defines the Java equivalent of a couple of advanced floating point functions
- * that are available in C.
- *
- */
-strictfp class DoubleMath {
- /** Number of significant digits in a double */
- private static final int DIGITS = 52;
-
- /** A class that represents a double and a magnitude */
- public static class MantissaExponent implements Comparable<MantissaExponent> {
- public double mantissa;
- public int exp;
-
- /** No instantiation allowed */
- private MantissaExponent() {
- }
-
- @Override
- public int compareTo(MantissaExponent dm) {
- return Math.signum(mantissa) * exp < Math.signum(dm.mantissa) * dm.exp ? -1 :
- Math.signum(mantissa) * exp > Math.signum(dm.mantissa) * dm.exp ? 1 : mantissa
- < dm.mantissa ? -1 : mantissa > dm.mantissa ? 1 : 0;
- }
- }
-
- /**
- * If v is non-zero return an integer exp, so that (0.5 <= |v|*2^(-exp) < 1).
- * this is analogous to the integer part of the return value frexp If v is
- * zero return 0.
- */
- public static int getExp(double v) {
- if (v == 0) {
- return 0;
- }
- return (int) ((0x7ff0000000000000L & Double.doubleToLongBits(v)) >> DIGITS) - 1022;
- }
-
-
- /**
- * As in C++'s <code>double frexp ( double x , int * exp )</code> from math.h,
- * this function separates the mantissa and exponent of a floating-point
- * value.
- *
- * This code certainly does not handle java's non-numerical values (NaN and
- * the like).
- */
- public static MantissaExponent frexp(double v) {
- MantissaExponent dm = new MantissaExponent();
- if (v == 0) {
- dm.mantissa = 0;
- dm.exp = 0;
- return dm;
- }
- long bits = Double.doubleToLongBits(v);
- dm.mantissa = Double.longBitsToDouble((0x800fffffffffffffL & bits) | 0x3fe0000000000000L);
- dm.exp = (int) ((0x7ff0000000000000L & bits) >> DIGITS) - 1022;
- return dm;
- }
-
-}
diff --git a/src/com/google/common/geometry/S2.java b/src/com/google/common/geometry/S2.java
index 80a994e..9fc876a 100644
--- a/src/com/google/common/geometry/S2.java
+++ b/src/com/google/common/geometry/S2.java
@@ -15,10 +15,12 @@
*/
package com.google.common.geometry;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
-public strictfp class S2 {
- // declare some frequently use constants
+public final strictfp class S2 {
+
+ // Declare some frequently used constants
public static final double M_PI = Math.PI;
public static final double M_1_PI = 1.0 / Math.PI;
public static final double M_PI_2 = Math.PI / 2.0;
@@ -35,6 +37,30 @@ public strictfp class S2 {
public static final int SWAP_MASK = 0x01;
public static final int INVERT_MASK = 0x02;
+ // Number of bits in the mantissa of a double.
+ private static final int EXPONENT_SHIFT = 52;
+ // Mask to extract the exponent from a double.
+ private static final long EXPONENT_MASK = 0x7ff0000000000000L;
+
+ /**
+ * If v is non-zero, return an integer {@code exp} such that
+ * {@code (0.5 <= |v|*2^(-exp) < 1)}. If v is zero, return 0.
+ *
+ * <p>Note that this arguably a bad definition of exponent because it makes
+ * {@code exp(9) == 4}. In decimal this would be like saying that the exponent
+ * of 1234 is 4, when in scientific 'exponent' notation 1234 is
+ * {@code 1.234 x 10^3}.
+ *
+ * TODO(dbeaumont): Replace this with "DoubleUtils.getExponent(v) - 1" ?
+ */
+ @VisibleForTesting
+ static int exp(double v) {
+ if (v == 0) {
+ return 0;
+ }
+ long bits = Double.doubleToLongBits(v);
+ return (int) ((EXPONENT_MASK & bits) >> EXPONENT_SHIFT) - 1022;
+ }
/**
* kPosToOrientation[pos] -> orientation_modifier
@@ -114,10 +140,10 @@ public strictfp class S2 {
}
// This code is equivalent to computing a floating-point "level"
- // value and rounding up. frexp() returns a fraction in the
- // range [0.5,1) and the corresponding exponent.
- int level = DoubleMath.frexp(value / ((1 << dim) * deriv)).exp;
- level = Math.max(0, Math.min(S2CellId.MAX_LEVEL, -((level - 1) >> (dim - 1))));
+ // value and rounding up.
+ int exponent = exp(value / ((1 << dim) * deriv));
+ int level = Math.max(0,
+ Math.min(S2CellId.MAX_LEVEL, -((exponent - 1) >> (dim - 1))));
// assert (level == S2CellId.MAX_LEVEL || getValue(level) <= value);
// assert (level == 0 || getValue(level - 1) > value);
return level;
@@ -137,8 +163,9 @@ public strictfp class S2 {
// This code is equivalent to computing a floating-point "level"
// value and rounding down.
- int level = DoubleMath.frexp((1 << dim) * deriv / value).exp;
- level = Math.max(0, Math.min(S2CellId.MAX_LEVEL, (level - 1) >> (dim - 1)));
+ int exponent = exp((1 << dim) * deriv / value);
+ int level = Math.max(0,
+ Math.min(S2CellId.MAX_LEVEL, ((exponent - 1) >> (dim - 1))));
// assert (level == 0 || getValue(level) >= value);
// assert (level == S2CellId.MAX_LEVEL || getValue(level + 1) < value);
return level;
diff --git a/tests/com/google/common/geometry/DoubleMathTest.java b/tests/com/google/common/geometry/DoubleMathTest.java
deleted file mode 100644
index 0443426..0000000
--- a/tests/com/google/common/geometry/DoubleMathTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2005 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.common.geometry;
-
-import com.google.common.geometry.DoubleMath.MantissaExponent;
-
-import junit.framework.TestCase;
-
-import java.util.Random;
-
-/**
- * Tests the advanced floating point operations defined in DoubleMath.java.
- *
- */
-public class DoubleMathTest extends TestCase {
-
- Random rnd = new Random(12345);
-
- public void testFrexp() {
- for (int i = 0; i < 10; ++i) {
- MantissaExponent me = DoubleMath.frexp(Math.pow(2, i));
- assertEquals(0.5, me.mantissa);
- assertEquals(i + 1, me.exp);
- }
-
- for (int i = 0; i < 10; ++i) {
- MantissaExponent me = DoubleMath.frexp(-Math.pow(2, i));
- assertEquals(-0.5, me.mantissa);
- assertEquals(i + 1, me.exp);
- }
-
- MantissaExponent me = DoubleMath.frexp(0);
- assertEquals(0.0, me.mantissa);
- assertEquals(0, me.exp);
-
- me = DoubleMath.frexp(3);
- assertEquals(0.75, me.mantissa);
- assertEquals(2, me.exp);
-
- me = DoubleMath.frexp(5);
- assertEquals(0.625, me.mantissa);
- assertEquals(3, me.exp);
- }
-
- public void testCompareTo() {
- for (int i = 0; i < 100; ++i) {
- double x = rnd.nextDouble() * 100 - 50;
- double y = rnd.nextDouble() * 100 - 50;
- MantissaExponent m1 = DoubleMath.frexp(x);
- MantissaExponent m2 = DoubleMath.frexp(y);
-
- assertEquals(new Double(x).compareTo(y), m1.compareTo(m2));
- }
- }
-}
diff --git a/tests/com/google/common/geometry/S2Test.java b/tests/com/google/common/geometry/S2Test.java
index f94f594..6b90661 100644
--- a/tests/com/google/common/geometry/S2Test.java
+++ b/tests/com/google/common/geometry/S2Test.java
@@ -302,4 +302,18 @@ public strictfp class S2Test extends GeometryTestCase {
assertEquals(S2Projections.MIN_AREA.getClosestLevel(0.8 * area1), expectedLevel);
}
}
+
+ public void testExp() {
+ for (int i = 0; i < 10; ++i) {
+ assertEquals(i + 1, S2.exp(Math.pow(2, i)));
+ }
+
+ for (int i = 0; i < 10; ++i) {
+ assertEquals(i + 1, S2.exp(-Math.pow(2, i)));
+ }
+
+ assertEquals(0, S2.exp(0));
+ assertEquals(2, S2.exp(3));
+ assertEquals(3, S2.exp(5));
+ }
}