diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..d744708
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,32 @@
+apply plugin: 'com.android.application'
+
+sourceCompatibility = source_compatibility
+targetCompatibility = target_compatibility
+
+repositories {
+ google()
+ jcenter()
+}
+
+android {
+ compileSdkVersion 28
+ defaultConfig {
+ applicationId "org.kynosarges.tektosyne"
+ minSdkVersion 16
+ targetSdkVersion 28
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..0e159cd
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..a9844a8
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..49e2583
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..6d5e5d0
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..6d5e5d0
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..898f3ed
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dffca36
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..64ba76f
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dae5e08
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e5ed465
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..14ed0af
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b0907ca
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d8ae031
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2c18de9
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..beed3cd
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..b2b4267
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #008577
+ #00574B
+ #D81B60
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..d7149f9
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ Tektosyne
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..705be27
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/build.gradle b/build.gradle
index 4e190d7..c6ce7cd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,14 +8,18 @@ buildscript {
ext.project_license_tag = 'MIT' // the license tag name
ext.project_license_url = 'https://raw.githubusercontent.com/kynosarges/tektosyne/master/LICENSE.txt' // link to the license
- ext.your_github_name = 'PixelBumper'
+ ext.your_github_name = 'toteto'
ext.source_compatibility = '1.8'
ext.target_compatibility = '1.8'
repositories{
+ google()
mavenCentral()
jcenter()
}
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.2.1'
+ }
}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..82618ce
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,15 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+
+
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index e1205dc..e3fd96f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sun Mar 12 18:46:54 CET 2017
+#Thu Nov 29 21:00:46 CET 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/settings.gradle b/settings.gradle
index f852a0c..c8aa638 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,4 @@
rootProject.name = 'tektosyne'
include 'tektosyne'
include 'tektosyne-demo'
+include ':app'
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/Fortran.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/Fortran.java
index 98d549a..8ac9388 100755
--- a/tektosyne/src/main/java/org/kynosarges/tektosyne/Fortran.java
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/Fortran.java
@@ -334,7 +334,7 @@ public static float modulo(float a, float p) {
* @throws ArithmeticException if {@code p} is zero
*/
public static int modulo(int a, int p) {
- return Math.floorMod(a, p);
+ return MathCompat.floorMod(a, p);
}
/**
@@ -348,7 +348,7 @@ public static int modulo(int a, int p) {
* @throws ArithmeticException if {@code p} is zero
*/
public static long modulo(long a, long p) {
- return Math.floorMod(a, p);
+ return MathCompat.floorMod(a, p);
}
/**
@@ -429,7 +429,7 @@ public static float sum(float... args) {
public static int sum(int... args) {
int sum = 0;
for (int n: args)
- sum = Math.addExact(sum, n);
+ sum = MathCompat.addExact(sum, n);
return sum;
}
@@ -446,7 +446,7 @@ public static int sum(int... args) {
public static long sum(long... args) {
long sum = 0;
for (long n: args)
- sum = Math.addExact(sum, n);
+ sum = MathCompat.addExact(sum, n);
return sum;
}
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/MathCompat.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/MathCompat.java
new file mode 100644
index 0000000..4d6ac9f
--- /dev/null
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/MathCompat.java
@@ -0,0 +1,241 @@
+package org.kynosarges.tektosyne;
+
+/**
+ * Provide needed {@link Math} from Java 1.8 to standard Java 1.7 for backward compatibility.
+ */
+public final class MathCompat {
+
+ private MathCompat() {
+ //no instance
+ }
+
+ /**
+ * Returns the sum of its arguments,
+ * throwing an exception if the result overflows an {@code int}.
+ *
+ * @param x the first value
+ * @param y the second value
+ * @return the result
+ * @throws ArithmeticException if the result overflows an int
+ * @since 1.8
+ */
+ public static int addExact(int x, int y) {
+ int r = x + y;
+ // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+ if (((x ^ r) & (y ^ r)) < 0) {
+ throw new ArithmeticException("integer overflow");
+ }
+ return r;
+ }
+
+ /**
+ * Returns the sum of its arguments,
+ * throwing an exception if the result overflows a {@code long}.
+ *
+ * @param x the first value
+ * @param y the second value
+ * @return the result
+ * @throws ArithmeticException if the result overflows a long
+ * @since 1.8
+ */
+ public static long addExact(long x, long y) {
+ long r = x + y;
+ // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+ if (((x ^ r) & (y ^ r)) < 0) {
+ throw new ArithmeticException("long overflow");
+ }
+ return r;
+ }
+
+ /**
+ * Returns the difference of the arguments,
+ * throwing an exception if the result overflows an {@code int}.
+ *
+ * @param x the first value
+ * @param y the second value to subtract from the first
+ * @return the result
+ * @throws ArithmeticException if the result overflows an int
+ * @since 1.8
+ */
+ public static int subtractExact(int x, int y) {
+ int r = x - y;
+ // HD 2-12 Overflow iff the arguments have different signs and
+ // the sign of the result is different than the sign of x
+ if (((x ^ y) & (x ^ r)) < 0) {
+ throw new ArithmeticException("integer overflow");
+ }
+ return r;
+ }
+
+ /**
+ * Returns the difference of the arguments,
+ * throwing an exception if the result overflows a {@code long}.
+ *
+ * @param x the first value
+ * @param y the second value to subtract from the first
+ * @return the result
+ * @throws ArithmeticException if the result overflows a long
+ * @since 1.8
+ */
+ public static long subtractExact(long x, long y) {
+ long r = x - y;
+ // HD 2-12 Overflow iff the arguments have different signs and
+ // the sign of the result is different than the sign of x
+ if (((x ^ y) & (x ^ r)) < 0) {
+ throw new ArithmeticException("long overflow");
+ }
+ return r;
+ }
+
+ /**
+ * Returns the largest (closest to positive infinity)
+ * {@code int} value that is less than or equal to the algebraic quotient.
+ * There is one special case, if the dividend is the
+ * {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1},
+ * then integer overflow occurs and
+ * the result is equal to the {@code Integer.MIN_VALUE}.
+ *
+ * Normal integer division operates under the round to zero rounding mode
+ * (truncation). This operation instead acts under the round toward
+ * negative infinity (floor) rounding mode.
+ * The floor rounding mode gives different results than truncation
+ * when the exact result is negative.
+ *
+ * - If the signs of the arguments are the same, the results of
+ * {@code floorDiv} and the {@code /} operator are the same.
+ * For example, {@code floorDiv(4, 3) == 1} and {@code (4 / 3) == 1}.
+ * - If the signs of the arguments are different, the quotient is negative and
+ * {@code floorDiv} returns the integer less than or equal to the quotient
+ * and the {@code /} operator returns the integer closest to zero.
+ * For example, {@code floorDiv(-4, 3) == -2},
+ * whereas {@code (-4 / 3) == -1}.
+ *
+ *
+ *
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the largest (closest to positive infinity)
+ * {@code int} value that is less than or equal to the algebraic quotient.
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see #floorMod(int, int)
+ * @since 1.8
+ */
+ public static int floorDiv(int x, int y) {
+ int r = x / y;
+ // if the signs are different and modulo not zero, round down
+ if ((x ^ y) < 0 && (r * y != x)) {
+ r--;
+ }
+ return r;
+ }
+
+ /**
+ * Returns the largest (closest to positive infinity)
+ * {@code long} value that is less than or equal to the algebraic quotient.
+ * There is one special case, if the dividend is the
+ * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1},
+ * then integer overflow occurs and
+ * the result is equal to the {@code Long.MIN_VALUE}.
+ *
+ * Normal integer division operates under the round to zero rounding mode
+ * (truncation). This operation instead acts under the round toward
+ * negative infinity (floor) rounding mode.
+ * The floor rounding mode gives different results than truncation
+ * when the exact result is negative.
+ *
+ * For examples, see {@link #floorDiv(int, int)}.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the largest (closest to positive infinity)
+ * {@code long} value that is less than or equal to the algebraic quotient.
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see #floorMod(long, long)
+ * @since 1.8
+ */
+ public static long floorDiv(long x, long y) {
+ long r = x / y;
+ // if the signs are different and modulo not zero, round down
+ if ((x ^ y) < 0 && (r * y != x)) {
+ r--;
+ }
+ return r;
+ }
+
+ /**
+ * Returns the floor modulus of the {@code int} arguments.
+ *
+ * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+ * has the same sign as the divisor {@code y}, and
+ * is in the range of {@code -abs(y) < r < +abs(y)}.
+ *
+ *
+ * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+ *
+ * - {@code floorDiv(x, y) * y + floorMod(x, y) == x}
+ *
+ *
+ * The difference in values between {@code floorMod} and
+ * the {@code %} operator is due to the difference between
+ * {@code floorDiv} that returns the integer less than or equal to the quotient
+ * and the {@code /} operator that returns the integer closest to zero.
+ *
+ * Examples:
+ *
+ * - If the signs of the arguments are the same, the results
+ * of {@code floorMod} and the {@code %} operator are the same.
+ *
+ * - {@code floorMod(4, 3) == 1}; and {@code (4 % 3) == 1}
+ *
+ * - If the signs of the arguments are different, the results differ from the {@code %} operator.
+ *
+ * - {@code floorMod(+4, -3) == -2}; and {@code (+4 % -3) == +1}
+ * - {@code floorMod(-4, +3) == +2}; and {@code (-4 % +3) == -1}
+ * - {@code floorMod(-4, -3) == -1}; and {@code (-4 % -3) == -1 }
+ *
+ *
+ *
+ *
+ * If the signs of arguments are unknown and a positive modulus
+ * is needed it can be computed as {@code (floorMod(x, y) + abs(y)) % abs(y)}.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see #floorDiv(int, int)
+ * @since 1.8
+ */
+ public static int floorMod(int x, int y) {
+ int r = x - floorDiv(x, y) * y;
+ return r;
+ }
+
+ /**
+ * Returns the floor modulus of the {@code long} arguments.
+ *
+ * The floor modulus is {@code x - (floorDiv(x, y) * y)},
+ * has the same sign as the divisor {@code y}, and
+ * is in the range of {@code -abs(y) < r < +abs(y)}.
+ *
+ *
+ * The relationship between {@code floorDiv} and {@code floorMod} is such that:
+ *
+ * - {@code floorDiv(x, y) * y + floorMod(x, y) == x}
+ *
+ *
+ * For examples, see {@link #floorMod(int, int)}.
+ *
+ * @param x the dividend
+ * @param y the divisor
+ * @return the floor modulus {@code x - (floorDiv(x, y) * y)}
+ * @throws ArithmeticException if the divisor {@code y} is zero
+ * @see #floorDiv(long, long)
+ * @since 1.8
+ */
+ public static long floorMod(long x, long y) {
+ return x - floorDiv(x, y) * y;
+ }
+
+}
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/MathUtils.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/MathUtils.java
index 20e4ce0..1ede4a1 100755
--- a/tektosyne/src/main/java/org/kynosarges/tektosyne/MathUtils.java
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/MathUtils.java
@@ -14,7 +14,7 @@
*/
public final class MathUtils {
- private final static ThreadLocalRandom RANDOM = ThreadLocalRandom.current();
+ private final static Random RANDOM = ThreadLocalRandomCompat.current();
/**
* Creates a {@link MathUtils} instance.
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/QuadTree.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/QuadTree.java
index 48e3948..326dd66 100755
--- a/tektosyne/src/main/java/org/kynosarges/tektosyne/QuadTree.java
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/QuadTree.java
@@ -240,8 +240,8 @@ public boolean containsValue(V value, Node node) {
* {@code arrayIndex} plus {@link #size} is greater than the length of {@code array}
* @throws NullPointerException if {@code array} is {@code null}
*/
- public void copyTo(Map.Entry[] array, int arrayIndex) {
- for (Map.Entry entry: entrySet())
+ public void copyTo(Entry[] array, int arrayIndex) {
+ for (Entry entry: entrySet())
array[arrayIndex++] = entry;
}
@@ -701,7 +701,7 @@ public V put(PointD key, V value) {
*/
@Override
public void putAll(Map extends PointD, ? extends V> map) {
- for (Map.Entry extends PointD, ? extends V> entry: map.entrySet())
+ for (Entry extends PointD, ? extends V> entry: map.entrySet())
put(entry.getKey(), entry.getValue());
}
@@ -874,7 +874,7 @@ public boolean addAll(Collection extends Entry> collection) {
final int oldSize = _size;
boolean changed = false;
- for (Map.Entry entry: collection) {
+ for (Entry entry: collection) {
final V value = entry.getValue();
if (!Objects.equals(value, put(entry.getKey(), value)))
changed = true;
@@ -912,7 +912,7 @@ public void clear() {
*
* @param obj the element to examine
* @return {@code true} if {@code obj} was found, else {@code false}
- * @throws ClassCastException if {@code obj} cannot be cast to {@link Map.Entry}
+ * @throws ClassCastException if {@code obj} cannot be cast to {@link Entry}
* with a {@link PointD} key and a V value
* @throws NullPointerException if {@code obj} or its key is {@code null}
*/
@@ -970,7 +970,7 @@ public Iterator> iterator() {
*
* @param obj the element to remove
* @return {@code true} if {@code obj} was found and removed, else {@code false}
- * @throws ClassCastException if {@code obj} cannot be cast to {@link Map.Entry}
+ * @throws ClassCastException if {@code obj} cannot be cast to {@link Entry}
* with a {@link PointD} key and a V value
* @throws NullPointerException if {@code obj} or its key is {@code null}
*/
@@ -1396,7 +1396,7 @@ private void findRange(RectD range, boolean useCircle, Map output) {
final double x = range.min.x + radius;
final double y = range.min.y + radius;
- for (Map.Entry pair: _entries.entrySet()) {
+ for (Entry pair: _entries.entrySet()) {
final PointD key = pair.getKey();
if (range.contains(key)) {
final double dx = key.x - x, dy = key.y - y;
@@ -1405,7 +1405,7 @@ private void findRange(RectD range, boolean useCircle, Map output) {
}
}
} else {
- for (Map.Entry pair: _entries.entrySet())
+ for (Entry pair: _entries.entrySet())
if (range.contains(pair.getKey()))
output.put(pair.getKey(), pair.getValue());
}
@@ -1483,7 +1483,7 @@ else if (child == _maxXmaxY) {
*/
private void split() {
- for (Map.Entry pair: _entries.entrySet()) {
+ for (Entry pair: _entries.entrySet()) {
final PointD key = pair.getKey();
final Node child = findOrCreateChild(key);
child._entries.put(key, pair.getValue());
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/ThreadLocalRandomCompat.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/ThreadLocalRandomCompat.java
new file mode 100644
index 0000000..bbb7600
--- /dev/null
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/ThreadLocalRandomCompat.java
@@ -0,0 +1,26 @@
+package org.kynosarges.tektosyne;
+
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Provide {@link java.util.concurrent.ThreadLocalRandom} compatibility for Java 1.7.
+ */
+public final class ThreadLocalRandomCompat {
+
+ private static ThreadLocal RANDOM_INSTANCE = new ThreadLocal() {
+ @Override
+ public Random get() {
+ return new SecureRandom();
+ }
+ };
+
+ /**
+ * Compatible replacement for {@link ThreadLocalRandom#current()}.
+ */
+ public static Random current() {
+ return RANDOM_INSTANCE.get();
+ }
+
+}
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/GeoUtils.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/GeoUtils.java
index 759fa00..266b271 100755
--- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/GeoUtils.java
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/GeoUtils.java
@@ -16,7 +16,7 @@
*/
public final class GeoUtils {
- private final static ThreadLocalRandom RANDOM = ThreadLocalRandom.current();
+ private final static Random RANDOM = ThreadLocalRandomCompat.current();
/**
* Creates a {@link GeoUtils} instance.
@@ -475,10 +475,10 @@ public static LineD randomLine(double x, double y, double width, double height)
throw new IllegalArgumentException("height <= 0");
return new LineD(
- x + RANDOM.nextDouble(width),
- y + RANDOM.nextDouble(height),
- x + RANDOM.nextDouble(width),
- y + RANDOM.nextDouble(height));
+ x + RANDOM.nextDouble() * width,
+ y + RANDOM.nextDouble() * height,
+ x + RANDOM.nextDouble() * width,
+ y + RANDOM.nextDouble() * height);
}
/**
@@ -498,8 +498,8 @@ public static PointD randomPoint(double x, double y, double width, double height
throw new IllegalArgumentException("height <= 0");
return new PointD(
- x + RANDOM.nextDouble(width),
- y + RANDOM.nextDouble(height));
+ x + RANDOM.nextDouble() * width,
+ y + RANDOM.nextDouble() * height);
}
/**
@@ -520,8 +520,8 @@ public static PointD randomPoint(RectD bounds) {
throw new IllegalArgumentException("bounds.height == 0");
return new PointD(
- bounds.min.x + RANDOM.nextDouble(width),
- bounds.min.y + RANDOM.nextDouble(height));
+ bounds.min.x + RANDOM.nextDouble() * width,
+ bounds.min.y + RANDOM.nextDouble() * height);
}
/**
@@ -549,8 +549,8 @@ public static PointD[] randomPoints(int count, RectD bounds) {
for (int i = 0; i < points.length; i++)
points[i] = new PointD(
- bounds.min.x + RANDOM.nextDouble(width),
- bounds.min.y + RANDOM.nextDouble(height));
+ bounds.min.x + RANDOM.nextDouble() * width,
+ bounds.min.y + RANDOM.nextDouble() * height);
return points;
}
@@ -596,8 +596,8 @@ public static PointD[] randomPoints(int count,
for (int i = 0; i < count; i++) {
do {
point = new PointD(
- bounds.min.x + RANDOM.nextDouble(width),
- bounds.min.y + RANDOM.nextDouble(height));
+ bounds.min.x + RANDOM.nextDouble() * width,
+ bounds.min.y + RANDOM.nextDouble() * height);
if (points.isEmpty()) break;
@@ -606,7 +606,7 @@ public static PointD[] randomPoints(int count,
} while (length2 < distance);
points.add(point);
- points.sort(comparer);
+ Collections.sort(points, comparer);
}
return points.toArray(new PointD[count]);
@@ -645,7 +645,7 @@ public static PointD[] randomPolygon(double x, double y, double width, double he
for (double degrees = 0; degrees < 360; degrees += 6.0) {
// random increment of angle for next vertex
- degrees += RANDOM.nextDouble(110);
+ degrees += RANDOM.nextDouble() * 110;
if (degrees >= 360) break;
final double radians = degrees * Angle.DEGREES_TO_RADIANS;
@@ -687,10 +687,10 @@ public static RectD randomRect(double x, double y, double width, double height)
throw new IllegalArgumentException("height <= 0");
return new RectD(
- x + RANDOM.nextDouble(width / 2),
- y + RANDOM.nextDouble(height / 2),
- x + width - RANDOM.nextDouble(width / 2),
- y + height - RANDOM.nextDouble(height / 2));
+ x + RANDOM.nextDouble() * width / 2,
+ y + RANDOM.nextDouble() * height / 2,
+ x + width - RANDOM.nextDouble() * width / 2,
+ y + height - RANDOM.nextDouble() * height /2);
}
/**
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/LineI.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/LineI.java
index da4b314..48a70bb 100755
--- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/LineI.java
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/LineI.java
@@ -1,5 +1,7 @@
package org.kynosarges.tektosyne.geometry;
+import org.kynosarges.tektosyne.MathCompat;
+
/**
* Represents a directed line segment in two-dimensional space, using {@link Integer} coordinates.
* {@link LineI} contains two immutable {@link PointI} locations, indicating the {@link LineI#start}
@@ -385,8 +387,8 @@ public LineD toLineD() {
*/
public PointI vector() {
return new PointI(
- Math.subtractExact(end.x, start.x),
- Math.subtractExact(end.y, start.y));
+ MathCompat.subtractExact(end.x, start.x),
+ MathCompat.subtractExact(end.y, start.y));
}
/**
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/PointI.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/PointI.java
index 566a86f..7505990 100755
--- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/PointI.java
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/PointI.java
@@ -54,8 +54,8 @@ public PointI(int x, int y) {
*/
public PointI add(PointI point) {
return new PointI(
- Math.addExact(x, point.x),
- Math.addExact(y, point.y));
+ MathCompat.addExact(x, point.x),
+ MathCompat.addExact(y, point.y));
}
/**
@@ -273,8 +273,8 @@ public PointI restrict(int minX, int minY, int maxX, int maxY) {
*/
public PointI subtract(PointI point) {
return new PointI(
- Math.subtractExact(x, point.x),
- Math.subtractExact(y, point.y));
+ MathCompat.subtractExact(x, point.x),
+ MathCompat.subtractExact(y, point.y));
}
/**
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/RectI.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/RectI.java
index d3a311c..7c63d77 100755
--- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/RectI.java
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/RectI.java
@@ -1,5 +1,7 @@
package org.kynosarges.tektosyne.geometry;
+import org.kynosarges.tektosyne.MathCompat;
+
/**
* Represents a rectangular region in two-dimensional space, using {@link Integer} coordinates.
* {@link RectI} contains two immutable {@link PointI} locations, defining the opposite corners
@@ -178,11 +180,11 @@ public boolean containsOpen(PointI point) {
*/
public PointI distanceVector(PointI q) {
- final int x = (q.x < min.x ? Math.subtractExact(q.x, min.x) :
- q.x > max.x ? Math.subtractExact(q.x, max.x) : 0);
+ final int x = (q.x < min.x ? MathCompat.subtractExact(q.x, min.x) :
+ q.x > max.x ? MathCompat.subtractExact(q.x, max.x) : 0);
- final int y = (q.y < min.y ? Math.subtractExact(q.y, min.y) :
- q.y > max.y ? Math.subtractExact(q.y, max.y) : 0);
+ final int y = (q.y < min.y ? MathCompat.subtractExact(q.y, min.y) :
+ q.y > max.y ? MathCompat.subtractExact(q.y, max.y) : 0);
return new PointI(x, y);
}
@@ -290,8 +292,8 @@ public RectLocation locate(PointI q) {
*/
public RectI offset(int x, int y) {
return new RectI(
- Math.addExact(min.x, x), Math.addExact(min.y, y),
- Math.addExact(max.x, x), Math.addExact(max.y, y));
+ MathCompat.addExact(min.x, x), MathCompat.addExact(min.y, y),
+ MathCompat.addExact(max.x, x), MathCompat.addExact(max.y, y));
}
/**
diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/SizeI.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/SizeI.java
index f2a3f16..a90f223 100755
--- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/SizeI.java
+++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/SizeI.java
@@ -1,5 +1,7 @@
package org.kynosarges.tektosyne.geometry;
+import org.kynosarges.tektosyne.MathCompat;
+
/**
* Represents an extension in two-dimensional space, using {@link Integer} coordinates.
* {@link SizeI} contains two immutable non-negative {@link Integer} dimensions.
@@ -60,8 +62,8 @@ public SizeI(int width, int height) {
*/
public SizeI add(SizeI size) {
return new SizeI(
- Math.addExact(width, size.width),
- Math.addExact(height, size.height));
+ MathCompat.addExact(width, size.width),
+ MathCompat.addExact(height, size.height));
}
/**