summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Boehm <hboehm@google.com>2017-09-01 21:52:52 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-09-01 21:52:52 +0000
commit5e665f4267104b37122bd94884401009926f6d59 (patch)
treebee0fb3b74ad3e3f94f6eb0595351e71f69a39d4
parent664b07b0d60d3923613bc9d28bccec73268dda94 (diff)
parentf37a3039bfe6f4e3fa6b965d1a68827032161a71 (diff)
downloadcrcalc-5e665f4267104b37122bd94884401009926f6d59.tar.gz
Added test for floating point conversions am: 170e00af50 am: 3588b0e5cb
am: f37a3039bf Change-Id: I2791a9735376b47d2f99a6131ebc6c5a9ea31bd0
-rw-r--r--Android.mk2
-rw-r--r--src/com/hp/creals/CR.java8
-rw-r--r--tests/Android.mk2
-rw-r--r--tests/AndroidManifest.xml2
-rw-r--r--tests/README.txt2
-rw-r--r--tests/src/com/hp/creals/ConversionTest.java85
6 files changed, 96 insertions, 5 deletions
diff --git a/Android.mk b/Android.mk
index 8220ee0..b78e9e1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -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);
+ }
+ }
+}