diff options
author | David Beaumont <dbeaumont@google.com> | 2011-10-31 18:43:24 -0400 |
---|---|---|
committer | Michael Bolin <bolinfest@google.com> | 2011-10-31 18:43:24 -0400 |
commit | b9d250e7997c91a27551d7d5ba7f8d9409bb9cec (patch) | |
tree | 236da7403ef88e72a438daed64a1ea4a305ac873 | |
parent | e3151c74f4ab0a69bfcbd867409881a96aafdd9e (diff) | |
download | s2-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.java | 78 | ||||
-rw-r--r-- | src/com/google/common/geometry/S2.java | 43 | ||||
-rw-r--r-- | tests/com/google/common/geometry/DoubleMathTest.java | 69 | ||||
-rw-r--r-- | tests/com/google/common/geometry/S2Test.java | 14 |
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)); + } } |