Adds java.lang.Math and java.util.HashSet

This commit is contained in:
konsoletyper 2014-03-04 15:31:33 +04:00
parent 9c4f00c18a
commit cb0dd8e992
4 changed files with 506 additions and 0 deletions

View File

@ -0,0 +1,59 @@
/*
* Copyright 2014 Alexey Andreev.
*
* 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 org.teavm.classlib.java.lang;
import java.io.IOException;
import org.teavm.codegen.SourceWriter;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class MathNativeGenerator implements Generator {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
switch (methodRef.getName()) {
case "sin":
case "cos":
case "tan":
case "asin":
case "acos":
case "atan":
case "exp":
case "log":
case "sqrt":
case "floor":
case "ceil":
function(context, writer, "Math." + methodRef.getName(), methodRef.parameterCount());
break;
}
}
private void function(GeneratorContext context, SourceWriter writer, String name, int paramCount)
throws IOException {
writer.append("return ").append(name).append("(");
for (int i = 0; i < paramCount; ++i) {
if (i > 0) {
writer.append(",").ws();
}
writer.append(context.getParameterName(i + 1));
}
writer.append(");").softNewLine();
}
}

View File

@ -15,14 +15,94 @@
*/
package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.GeneratedBy;
/**
*
* @author Alexey Andreev
*/
public final class TMath extends TObject {
public static double E = 2.71828182845904523536;
public static double PI = 3.14159265358979323846;
private TMath() {
}
@GeneratedBy(MathNativeGenerator.class)
public static native double sin(double a);
@GeneratedBy(MathNativeGenerator.class)
public static native double cos(double a);
@GeneratedBy(MathNativeGenerator.class)
public static native double tan(double a);
@GeneratedBy(MathNativeGenerator.class)
public static native double asin(double a);
@GeneratedBy(MathNativeGenerator.class)
public static native double acos(double a);
@GeneratedBy(MathNativeGenerator.class)
public static native double atan(double a);
public static double toRadians(double angdeg) {
return angdeg * PI / 180;
}
public static double toDegrees(double angrad) {
return angrad * 180 / PI;
}
@GeneratedBy(MathNativeGenerator.class)
public static native double exp(double a);
@GeneratedBy(MathNativeGenerator.class)
public static native double log(double a);
public static double log10(double a) {
return log(a) / 2.302585092994046 /* log_e 10 */;
}
@GeneratedBy(MathNativeGenerator.class)
public static native double sqrt(double a);
public static double cbrt(double a) {
return a > 0 ? pow(a, 1.0 / 3) : -pow(-a, 1.0 / 3);
}
public static double IEEEremainder(double f1, double f2) {
int n = (int)(f1 / f2);
return f1 - n * f2;
}
@GeneratedBy(MathNativeGenerator.class)
public static native double ceil(double a);
@GeneratedBy(MathNativeGenerator.class)
public static native double floor(double a);
@GeneratedBy(MathNativeGenerator.class)
public static native double pow(double x, double y);
public static double rint(double a) {
return round(a);
}
@GeneratedBy(MathNativeGenerator.class)
public static native double atan2(double y, double x);
public static int round(float a) {
return (int)(a + 1.5f);
}
public static long round(double a) {
return (long)(a + 0.5);
}
@GeneratedBy(MathNativeGenerator.class)
public static native double random();
public static int min(int a, int b) {
return a < b ? a : b;
}
@ -47,6 +127,14 @@ public final class TMath extends TObject {
return a > b ? a : b;
}
public static float min(float a, float b) {
return a < b ? a : b;
}
public static float max(float a, float b) {
return a > b ? a : b;
}
public static int abs(int n) {
return n > 0 ? n : -n;
}
@ -55,7 +143,127 @@ public final class TMath extends TObject {
return n > 0 ? n : -n;
}
public static float abs(float n) {
return n > 0 ? n : -n;
}
public static double abs(double n) {
return n > 0 ? n : -n;
}
public static double ulp(double d) {
return pow(1, -getExponent(d) - 52);
}
public static float ulp(float d) {
return (float)pow(1, -getExponent(d) - 23);
}
public static double signum(double d) {
return d > 0 ? 1 : d < -0 ? -1 : d;
}
public static float signum(float d) {
return d > 0 ? 1 : d < -0 ? -1 : d;
}
public static double sinh(double x) {
double e = exp(x);
return e - 1 / e;
}
public static double cosh(double x) {
double e = exp(x);
return e + 1 / e;
}
public static double tanh(double x) {
double e = exp(x);
return (e - 1 / e) / (e + 1 / e);
}
public static double hypot(double x, double y) {
return x * x + y * y;
}
public static double expm1(double x) {
return exp(x) - 1;
}
public static double log1p(double x) {
return log(x + 1);
}
public static float copySign(float magnitude, float sign) {
if (sign == 0 || sign == -0) {
return sign;
}
return (sign > 0) == (magnitude > 0) ? magnitude : -magnitude;
}
public static double copySign(double magnitude, double sign) {
if (sign == 0 || sign == -0) {
return sign;
}
return (sign > 0) == (magnitude > 0) ? magnitude : -magnitude;
}
public static int getExponent(double d) {
d = abs(d);
int exp = 0;
double[] exponents = ExponentConstants.exponents;
double[] negativeExponents = ExponentConstants.negativeExponents;
if (d > 1) {
int expBit = 1 << (exponents.length - 1);
for (int i = exponents.length - 1; i >= 0; --i) {
if (d > exponents[i]) {
d *= negativeExponents[i];
exp |= expBit;
}
expBit >>>= 1;
}
} else if (d < 1) {
int expBit = 1 << (negativeExponents.length - 1);
for (int i = negativeExponents.length - 1; i >= 0; --i) {
if (d < negativeExponents[i]) {
d *= exponents[i];
exp |= expBit;
}
expBit >>>= 1;
}
exp = -exp;
}
return exp;
}
public static int getExponent(float f) {
return getExponent(f);
}
public static double nextAfter(double start, double direction) {
if (start == direction) {
return direction;
}
return direction > start ? start + ulp(start) : start - ulp(start);
}
public static float nextAfter(float start, float direction) {
if (start == direction) {
return direction;
}
return direction > start ? start + ulp(start) : start - ulp(start);
}
public static double nextUp(double d) {
return d + ulp(d);
}
public static float nextUp(float d) {
return d + ulp(d);
}
private static class ExponentConstants {
public static double[] exponents = { 1E1, 1E2, 1E4, 1E8, 1E16, 1E32, 1E64, 1E128, 1E256 };
public static double[] negativeExponents = { 1E-1, 1E-2, 1E-4, 1E-8, 1E-16, 1E-32, 1E-64, 1E-128, 1E-256 };
}
}

View File

@ -0,0 +1,182 @@
/*
* Copyright 2014 Alexey Andreev.
*
* 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 org.teavm.classlib.java.util;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.lang.TCloneNotSupportedException;
import org.teavm.classlib.java.lang.TCloneable;
import org.teavm.classlib.java.lang.TObject;
/**
*
* @author Alexey Andreev
*/
public class THashSet<E> extends TAbstractSet<E> implements TCloneable, TSerializable {
transient THashMap<E, THashSet<E>> backingMap;
/**
* Constructs a new empty instance of {@code HashSet}.
*/
public THashSet() {
this(new THashMap<E, THashSet<E>>());
}
/**
* Constructs a new instance of {@code HashSet} with the specified capacity.
*
* @param capacity
* the initial capacity of this {@code HashSet}.
*/
public THashSet(int capacity) {
this(new THashMap<E, THashSet<E>>(capacity));
}
/**
* Constructs a new instance of {@code HashSet} with the specified capacity
* and load factor.
*
* @param capacity
* the initial capacity.
* @param loadFactor
* the initial load factor.
*/
public THashSet(int capacity, float loadFactor) {
this(new THashMap<E, THashSet<E>>(capacity, loadFactor));
}
/**
* Constructs a new instance of {@code HashSet} containing the unique
* elements in the specified collection.
*
* @param collection
* the collection of elements to add.
*/
public THashSet(TCollection<? extends E> collection) {
this(new THashMap<E, THashSet<E>>(collection.size() < 6 ? 11 : collection.size() * 2));
for (TIterator<? extends E> iter = collection.iterator(); iter.hasNext();) {
add(iter.next());
}
}
THashSet(THashMap<E, THashSet<E>> backingMap) {
this.backingMap = backingMap;
}
/**
* Adds the specified object to this {@code HashSet} if not already present.
*
* @param object
* the object to add.
* @return {@code true} when this {@code HashSet} did not already contain
* the object, {@code false} otherwise
*/
@Override
public boolean add(E object) {
return backingMap.put(object, this) == null;
}
/**
* Removes all elements from this {@code HashSet}, leaving it empty.
*
* @see #isEmpty
* @see #size
*/
@Override
public void clear() {
backingMap.clear();
}
/**
* Returns a new {@code HashSet} with the same elements and size as this
* {@code HashSet}.
*
* @return a shallow copy of this {@code HashSet}.
* @see java.lang.Cloneable
*/
@Override
@SuppressWarnings("unchecked")
public TObject clone() {
try {
THashSet<E> clone = (THashSet<E>) super.clone();
clone.backingMap = (THashMap<E, THashSet<E>>)backingMap.clone();
return clone;
} catch (TCloneNotSupportedException e) {
return null;
}
}
/**
* Searches this {@code HashSet} for the specified object.
*
* @param object
* the object to search for.
* @return {@code true} if {@code object} is an element of this
* {@code HashSet}, {@code false} otherwise.
*/
@Override
public boolean contains(Object object) {
return backingMap.containsKey(object);
}
/**
* Returns true if this {@code HashSet} has no elements, false otherwise.
*
* @return {@code true} if this {@code HashSet} has no elements,
* {@code false} otherwise.
* @see #size
*/
@Override
public boolean isEmpty() {
return backingMap.isEmpty();
}
/**
* Returns an Iterator on the elements of this {@code HashSet}.
*
* @return an Iterator on the elements of this {@code HashSet}.
* @see Iterator
*/
@Override
public TIterator<E> iterator() {
return backingMap.keySet().iterator();
}
/**
* Removes the specified object from this {@code HashSet}.
*
* @param object
* the object to remove.
* @return {@code true} if the object was removed, {@code false} otherwise.
*/
@Override
public boolean remove(Object object) {
return backingMap.remove(object) != null;
}
/**
* Returns the number of elements in this {@code HashSet}.
*
* @return the number of elements in this {@code HashSet}.
*/
@Override
public int size() {
return backingMap.size();
}
THashMap<E, THashSet<E>> createBackingMap(int capacity, float loadFactor) {
return new THashMap<>(capacity, loadFactor);
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright 2014 Alexey Andreev.
*
* 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 org.teavm.classlib.java.lang;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
* @author Alexey Andreev
*/
public class MathTest {
@Test
public void sinComputed() {
assertEquals(0.90929742682568, Math.sin(2), 1E-14);
}
@Test
public void expComputed() {
assertEquals(3.4212295362896734, Math.exp(1.23), 1E-14);
}
@Test
public void cbrtComputed() {
assertEquals(3.0, Math.cbrt(27.0), 1E-14);
assertEquals(-3.0, Math.cbrt(-27.0), 1E-14);
assertEquals(0, Math.cbrt(0), 1E-14);
}
@Test
public void ulpComputed() {
assertEquals(1.4210854715202004e-14, Math.ulp(123.456), 1E-25);
}
@Test
public void sinhComputed() {
assertEquals(1.3097586593745313E53, Math.sinh(123), 1E40);
}
@Test
public void getExponentComputed() {
assertEquals(6, Math.getExponent(123.456));
}
}