diff options
author | Hans Boehm <hboehm@google.com> | 2017-09-01 21:42:22 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-09-01 21:42:22 +0000 |
commit | f37a3039bfe6f4e3fa6b965d1a68827032161a71 (patch) | |
tree | bee0fb3b74ad3e3f94f6eb0595351e71f69a39d4 | |
parent | bbde06a8bc0d0c282d3022ac05b5bd06e02b4f6c (diff) | |
parent | 3588b0e5cbdf34503fca088d0a22ca2b15ceba38 (diff) | |
download | crcalc-f37a3039bfe6f4e3fa6b965d1a68827032161a71.tar.gz |
Added test for floating point conversions am: 170e00af50
am: 3588b0e5cb
Change-Id: Iffb68df1bb95929242d21f70f944027c9af77d49
-rw-r--r-- | Android.mk | 2 | ||||
-rw-r--r-- | src/com/hp/creals/CR.java | 8 | ||||
-rw-r--r-- | tests/Android.mk | 2 | ||||
-rw-r--r-- | tests/AndroidManifest.xml | 2 | ||||
-rw-r--r-- | tests/README.txt | 2 | ||||
-rw-r--r-- | tests/src/com/hp/creals/ConversionTest.java | 85 |
6 files changed, 96 insertions, 5 deletions
@@ -24,7 +24,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_MODULE := cr LOCAL_MODULE_TAGS := optional -LOCAL_SDK_VERSION := 8 +LOCAL_SDK_VERSION := 19 include $(BUILD_STATIC_JAVA_LIBRARY) diff --git a/src/com/hp/creals/CR.java b/src/com/hp/creals/CR.java index cce2a92..5312b15 100644 --- a/src/com/hp/creals/CR.java +++ b/src/com/hp/creals/CR.java @@ -714,6 +714,8 @@ public volatile static boolean please_stop = false; /** * Return a double which differs by less than one in the least * represented bit from the constructive real. +* (We're in fact closer to round-to-nearest than that, but we can't and +* don't promise correct rounding.) */ public double doubleValue() { int my_msd = iter_msd(-1080 /* slightly > exp. range */); @@ -725,7 +727,9 @@ public volatile static boolean please_stop = false; long exp_adj = may_underflow? needed_prec + 96 : needed_prec; long orig_exp = (scaled_int_rep >> 52) & 0x7ff; if (((orig_exp + exp_adj) & ~0x7ff) != 0) { - // overflow + // Original unbiased exponent is > 50. Exp_adj > -1050. + // Thus this can overflow the 11 bit exponent only if the result + // itself overflows. if (scaled_int < 0.0) { return Double.NEGATIVE_INFINITY; } else { @@ -748,6 +752,8 @@ public volatile static boolean please_stop = false; */ public float floatValue() { return (float)doubleValue(); + // Note that double-rounding is not a problem here, since we + // cannot, and do not, guarantee correct rounding. } /** diff --git a/tests/Android.mk b/tests/Android.mk index 59a564a..441752e 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -21,7 +21,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PACKAGE_NAME := CRTests -LOCAL_SDK_VERSION := 8 +LOCAL_SDK_VERSION := 19 LOCAL_MODULE_TAGS := tests LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-java-files-under, ../src) # Empirically, LOCAL_INSTRUMENTATION_FOR doesn't work, perhaps because it diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 48e1c98..4bc08c9 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -25,7 +25,7 @@ android:versionName="1.0"> <uses-sdk - android:minSdkVersion="8" /> + android:minSdkVersion="19" /> <instrumentation android:name="android.test.InstrumentationTestRunner" diff --git a/tests/README.txt b/tests/README.txt index a940b2c..6cedac3 100644 --- a/tests/README.txt +++ b/tests/README.txt @@ -1,7 +1,7 @@ Run on Android with 1) Build the tests. -2) adb install <tree root>/out/target/product/generic/data/app/CRTests/CRTests.apk +2) adb install <tree root>/out/target/product/<name>/data/app/CRTests/CRTests.apk 3) adb shell am instrument -w com.hp.creals.tests/android.test.InstrumentationTestRunner The last step takes around 10 minutes on a Nexus 5. diff --git a/tests/src/com/hp/creals/ConversionTest.java b/tests/src/com/hp/creals/ConversionTest.java new file mode 100644 index 0000000..90844b6 --- /dev/null +++ b/tests/src/com/hp/creals/ConversionTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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.hp.creals; + +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; + +import java.util.Random; + +public class ConversionTest extends TestCase { + private static void check(boolean x, String s) { + if (!x) throw new AssertionFailedError(s); + } + final static int NRANDOM = 100; // Number of random values to + // test. Bigger ==> slower + final CR BIG = CR.valueOf(Double.MAX_VALUE); + final CR HUGE = BIG.multiply(BIG); + final CR TINY = CR.ONE.shiftRight(1078); + + public void checkDoubleConversion(double x) { + if (!Double.isNaN(x) && !Double.isInfinite(x)) { + CR crValue = CR.valueOf(x); + check(x == crValue.doubleValue(), "double conversion: " + x); + } + } + + public void checkFloatConversion(float f) { + if (!Float.isNaN(f) && !Float.isInfinite(f)) { + CR crValue = CR.valueOf(f); + check(f == crValue.floatValue(), "float conversion: " + f); + } + } + + public void checkNearbyConversions(double x) { + checkDoubleConversion(x); + checkDoubleConversion(Math.nextAfter(x, Double.NEGATIVE_INFINITY)); + checkDoubleConversion(Math.nextAfter(x, Double.POSITIVE_INFINITY)); + float f = (float)x; + checkFloatConversion(f); + checkFloatConversion(Math.nextAfter(f, Double.NEGATIVE_INFINITY)); + checkFloatConversion(Math.nextAfter(f, Double.POSITIVE_INFINITY)); + } + + public void testConversions() { + check(TINY.doubleValue() == 0.0d, "Tiny.doubleValue()"); + checkNearbyConversions(0.0d); + checkNearbyConversions(Double.MAX_VALUE); + checkNearbyConversions(Double.MIN_VALUE); + check(HUGE.doubleValue() == Double.POSITIVE_INFINITY, + "double +infinity"); + check(HUGE.negate().doubleValue() == Double.NEGATIVE_INFINITY, + "double -infinity"); + check(HUGE.floatValue() == Float.POSITIVE_INFINITY, + "float +infinity"); + check(HUGE.negate().floatValue() == Float.NEGATIVE_INFINITY, + "float -infinity"); + for (double x = 1.0d; x != 0.0d; x /= 2.0d) { + checkNearbyConversions(x); + } + for (double x = -1.0d; x != Double.NEGATIVE_INFINITY; x *= 2.0d) { + checkNearbyConversions(x); + } + Random r = new Random(); // Random seed! + for (int i = 0; i < NRANDOM; ++i) { + double d = Math.exp(1000.0 * r.nextDouble()); + if (r.nextBoolean()) d = -d; + checkNearbyConversions(d); + } + } +} |