mirror of
https://github.com/enso-org/enso.git
synced 2024-09-11 13:15:52 +03:00
Decimal Numbers (#1146)
This commit is contained in:
parent
9666d9065e
commit
e38d1ab521
@ -26,11 +26,6 @@ Number.times = act ->
|
||||
res = here.reverse_list (go Nil this)
|
||||
res
|
||||
|
||||
zeropad number =
|
||||
txt = number.to_text
|
||||
if number % 10 == number then "00" + txt else
|
||||
if number % 100 == number then "0" + txt else txt
|
||||
|
||||
measure = ~act -> label -> iter_size -> num_iters ->
|
||||
single_call = _ ->
|
||||
x1 = System.nano_time
|
||||
@ -41,6 +36,6 @@ measure = ~act -> label -> iter_size -> num_iters ->
|
||||
act_it_num = num_iters - it_num
|
||||
res = iter_size.times single_call
|
||||
avg = here.avg_list res
|
||||
fmt = (avg / 1000000).to_text + "." + here.zeropad ((avg / 1000) % 1000)
|
||||
fmt = (avg / 1000000).format "%.2f"
|
||||
IO.println (label + "/iteration:" + act_it_num.to_text + ": " + fmt + "ms")
|
||||
num_iters.times iteration
|
||||
|
@ -1,11 +1,13 @@
|
||||
import Base.List
|
||||
import Base.Vector
|
||||
from Builtins import Number, Unit
|
||||
import Base.Number.Extensions
|
||||
from Builtins import Unit, Number, Integer
|
||||
|
||||
from Builtins export all
|
||||
|
||||
from Base.List export Nil, Cons
|
||||
from Base.Vector export Vector
|
||||
from Base.Number.Extensions export all hiding Math
|
||||
|
||||
## Represents a right-exclusive range of integer values.
|
||||
type Range
|
||||
@ -42,5 +44,9 @@ type Range
|
||||
res = it initial this.start this.end
|
||||
res
|
||||
|
||||
## Creates a new right-exclusive range of integers from `this` to `n`.
|
||||
Number.upto n = Range this n
|
||||
type Math
|
||||
|
||||
## The mathematical constant pi, equal to the ratio of a circle circumference
|
||||
to its diameter.
|
||||
Math.pi : Decimal
|
||||
Math.pi = 3.141592653589793
|
||||
|
85
distribution/std-lib/Base/src/Number/Extensions.enso
Normal file
85
distribution/std-lib/Base/src/Number/Extensions.enso
Normal file
@ -0,0 +1,85 @@
|
||||
from Base import all
|
||||
polyglot java import java.lang.Math
|
||||
polyglot java import java.lang.String
|
||||
|
||||
## Computes the inverse of the sine function
|
||||
|
||||
Selects a value in the -pi/2 through pi/2 range.
|
||||
Number.asin : Decimal
|
||||
Number.asin = Math.asin [this.to_decimal]
|
||||
|
||||
## Computes the inverse of the cosine function.
|
||||
|
||||
Selects a value in the -pi/2 through pi/2 range.
|
||||
Number.acos : Decimal
|
||||
Number.acos = Math.acos [this.to_decimal]
|
||||
|
||||
## Computes the inverse of the tangent function.
|
||||
|
||||
Selects a value in the -pi/2 through pi/2 range.
|
||||
Number.atan : Decimal
|
||||
Number.atan = Math.atan [this.to_decimal]
|
||||
|
||||
## Computes the argument (angle) in the conversion from cartesian
|
||||
to polar coordinates.
|
||||
|
||||
The returned angle is in the -pi through pi range.
|
||||
Number.atan_2 : Number -> Decimal
|
||||
Number.atan_2 y = Math.atan2 [this.to_decimal, y.to_decimal]
|
||||
|
||||
## Computes the sine function.
|
||||
Number.sin : Decimal
|
||||
Number.sin = Math.sin [this.to_decimal]
|
||||
|
||||
## Computes the cosine function.
|
||||
Number.cos : Decimal
|
||||
Number.cos = Math.cos [this.to_decimal]
|
||||
|
||||
## Computes the tangent function.
|
||||
Number.tan : Decimal
|
||||
Number.tan = Math.tan [this.to_decimal]
|
||||
|
||||
## Computes the hyperbolic sine function.
|
||||
Number.sinh : Decimal
|
||||
Number.sinh = Math.sinh [this.to_decimal]
|
||||
|
||||
## Computes the hyperbolic cosine function.
|
||||
Number.cosh : Decimal
|
||||
Number.cosh = Math.cosh [this.to_decimal]
|
||||
|
||||
## Computes the hyperbolic tangent function.
|
||||
Number.tanh : Decimal
|
||||
Number.tanh = Math.tanh [this.to_decimal]
|
||||
|
||||
## Computes the exponential function.
|
||||
Number.exp : Decimal
|
||||
Number.exp = Math.exp [this.to_decimal]
|
||||
|
||||
## Computes the natural logarithm function.
|
||||
Number.ln : Decimal
|
||||
Number.ln = Math.log [this.to_decimal]
|
||||
|
||||
## Computes the square root of `this`.
|
||||
Number.sqrt : Decimal
|
||||
Number.sqrt = Math.sqrt [this.to_decimal]
|
||||
|
||||
## Computes the `base`-log of `this`.
|
||||
Number.log : Number -> Decimal
|
||||
Number.log base = this.ln / base.ln
|
||||
|
||||
## Converts a decimal value to a string, using the Java string formatting
|
||||
syntax.
|
||||
|
||||
TODO this should expose a more-user friendly API in the future.
|
||||
Decimal.format : Text -> Text
|
||||
Decimal.format fmt = String.format [fmt, this]
|
||||
|
||||
## Creates a new right-exclusive range of integers from `this` to `n`.
|
||||
Integer.upto : Integer -> Range
|
||||
Integer.upto n = Range this n
|
||||
|
||||
## Checks equality of numbers, using an `epsilon` value.
|
||||
|
||||
Returns `True` when `this` and `that` are at most `epsilon` apart.
|
||||
Number.equals : Number -> Number -> Boolean
|
||||
Number.equals that epsilon = (this - that).abs <= epsilon
|
@ -1,5 +1,4 @@
|
||||
import Base.List
|
||||
from Builtins import all
|
||||
from Base import all
|
||||
|
||||
## The top-level entry point for a test suite.
|
||||
type Suite specs
|
||||
@ -38,6 +37,13 @@ Any.should_equal that = case this == that of
|
||||
msg = this.to_text + " did not equal " + that.to_text + "."
|
||||
Panic.throw (Failure msg)
|
||||
|
||||
## Asserts that `this` is within `epsilon` from `that`.
|
||||
Decimal.should_equal that (epsilon = 0) = case this.equals that epsilon of
|
||||
True -> Success
|
||||
False ->
|
||||
msg = this.to_text + " did not equal " + that.to_text + "."
|
||||
Panic.throw (Failure msg)
|
||||
|
||||
## Asserts that the given `Boolean` is `True`
|
||||
Boolean.should_be_true = case this of
|
||||
True -> Success
|
||||
|
66
docs/semantics/numbers.md
Normal file
66
docs/semantics/numbers.md
Normal file
@ -0,0 +1,66 @@
|
||||
---
|
||||
layout: developer-doc
|
||||
title: Numbers
|
||||
category: semantics
|
||||
tags: [semantics, runtime, number]
|
||||
order: 8
|
||||
---
|
||||
|
||||
# Numbers
|
||||
|
||||
In order to enhance the user experience, Enso provides a number hierarchy,
|
||||
encompassing both integers of unbound size and floating-point decimals.
|
||||
|
||||
<!-- MarkdownTOC levels="2,3" autolink="true" -->
|
||||
|
||||
- [Number Types](#number-types)
|
||||
- [Internal Representation](#internal-representation)
|
||||
- [Type Conversions](#type-conversions)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## Number Types
|
||||
|
||||
The base number type in Enso is `Number`. It includes both integers and
|
||||
floating-point numbers and is the basic type that should be used whenever
|
||||
numerical computations are performed. Any method defined on the type `Number` is
|
||||
automatically available on all types of numeric values.
|
||||
|
||||
The hierarchy is further split into the `Integer` and `Decimal` types. `Integer`
|
||||
is capable of representing values of unbound length. `Decimal` is capable of
|
||||
representing IEEE 64-bit (double precision) floating numbers.
|
||||
|
||||
Any method defined on `Integer` is available for all integers, while any method
|
||||
defined on `Decimal` is available on all floating-point numbers. Methods defined
|
||||
on `Integer` or `Decimal` take precedence over methods defined on `Number`, when
|
||||
name resolution is performed.
|
||||
|
||||
## Internal Representation
|
||||
|
||||
Integers that can be represented in a 64-bit integer type are represented as
|
||||
such. When a 64-bit representation would overflow (either by the result of
|
||||
creating a large number literal or an arithmetic operation), it is represented
|
||||
in a Java `BigInteger` type, thus becoming significantly slower than the 64-bit
|
||||
representation.
|
||||
|
||||
Decimals are represented using the Java `double` type.
|
||||
|
||||
## Type Conversions
|
||||
|
||||
Number literals that do not contain a decimal point, are treated as integers.
|
||||
Other literals are interpreted as decimals (even if the fractional part is 0).
|
||||
|
||||
Any arithmetic operation where at least one of the operands is a decimal will
|
||||
result in a decimal result.
|
||||
|
||||
Moreover, the default division operator `/` is implemented as floating-point
|
||||
division and always returns a decimal. If the desired behavior is integral
|
||||
division instead, the `Integer.div` method implements it.
|
||||
|
||||
Another operator worth noting is the exponentiation operator (`^`). It will
|
||||
always result in a decimal whenever either operand is decimal or the exponent is
|
||||
negative. It will also return a float result when the exponent is outside the
|
||||
64-bit integer range.
|
||||
|
||||
There is a `Number.to_decimal` method, that allows converting any number to a
|
||||
decimal. This is useful in certain high-performance and polyglot applications.
|
@ -97,6 +97,16 @@ public abstract class MethodResolverNode extends Node {
|
||||
return function;
|
||||
}
|
||||
|
||||
@Specialization(guards = "cachedSymbol == symbol")
|
||||
Function resolveDouble(
|
||||
UnresolvedSymbol symbol,
|
||||
double self,
|
||||
@Cached(value = "symbol", allowUncached = true) UnresolvedSymbol cachedSymbol,
|
||||
@Cached(value = "resolveMethodOnDouble(cachedSymbol)", allowUncached = true)
|
||||
Function function) {
|
||||
return function;
|
||||
}
|
||||
|
||||
@Specialization(guards = {"cachedSymbol == symbol", "function != null"})
|
||||
Function resolveBoolean(
|
||||
UnresolvedSymbol symbol,
|
||||
@ -220,6 +230,14 @@ public abstract class MethodResolverNode extends Node {
|
||||
symbol);
|
||||
}
|
||||
|
||||
Function resolveMethodOnDouble(UnresolvedSymbol symbol) {
|
||||
Number number = getBuiltins().number();
|
||||
return ensureMethodExists(
|
||||
symbol.resolveFor(number.getDecimal(), number.getNumber(), getBuiltins().any()),
|
||||
"Decimal",
|
||||
symbol);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
Function resolveMethodOnPrimBoolean(UnresolvedSymbol symbol, Context context) {
|
||||
Bool bool = context.getBuiltins().bool();
|
||||
|
@ -0,0 +1,55 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.syntax;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
|
||||
/**
|
||||
* Converts a value returned by a polyglot call back to a value that can be further used within Enso
|
||||
* programs.
|
||||
*/
|
||||
@ReportPolymorphism
|
||||
public abstract class HostValueToEnsoNode extends Node {
|
||||
public static HostValueToEnsoNode build() {
|
||||
return HostValueToEnsoNodeGen.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an arbitrary value to a value usable within Enso code.
|
||||
*
|
||||
* @param o the value to convert.
|
||||
* @return the Enso counterpart of the value.
|
||||
*/
|
||||
public abstract Object execute(Object o);
|
||||
|
||||
@Specialization
|
||||
double doFloat(float f) {
|
||||
return f;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doInt(int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doShort(short i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doByte(byte i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doChar(char i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(Object o) {
|
||||
return o;
|
||||
}
|
||||
}
|
@ -1,9 +1,6 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.syntax;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Bind;
|
||||
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.dsl.*;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.interop.*;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
@ -17,6 +14,7 @@ import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@ -29,6 +27,7 @@ public abstract class MethodDispatchNode extends BuiltinRootNode {
|
||||
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private @Child HostValueToEnsoNode hostValueToEnsoNode = HostValueToEnsoNode.build();
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
private @Child InvokeCallableNode invokeCallableNode =
|
||||
@ -53,12 +52,12 @@ public abstract class MethodDispatchNode extends BuiltinRootNode {
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Specialization(guards = "symbol == cachedSymbol")
|
||||
@Specialization(guards = "symbol.getScope() == cachedScope")
|
||||
public Stateful run(
|
||||
VirtualFrame frame,
|
||||
@Bind("getSymbol(frame)") UnresolvedSymbol symbol,
|
||||
@Cached("symbol") UnresolvedSymbol cachedSymbol,
|
||||
@Cached("buildToArray(cachedSymbol)") UnresolvedSymbol toArray) {
|
||||
@Cached("symbol.getScope()") ModuleScope cachedScope,
|
||||
@Cached("buildToArray(cachedScope)") UnresolvedSymbol toArray) {
|
||||
Object[] args = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());
|
||||
Object callable = args[0];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
@ -66,7 +65,8 @@ public abstract class MethodDispatchNode extends BuiltinRootNode {
|
||||
Stateful casted = invokeCallableNode.execute(toArray, frame, state, new Object[] {arguments});
|
||||
try {
|
||||
Object[] castedArgs = TypesGen.expectArray(casted.getValue()).getItems();
|
||||
Object res = library.invokeMember(callable, symbol.getName(), castedArgs);
|
||||
Object res =
|
||||
hostValueToEnsoNode.execute(library.invokeMember(callable, symbol.getName(), castedArgs));
|
||||
return new Stateful(casted.getState(), res);
|
||||
} catch (UnsupportedMessageException
|
||||
| ArityException
|
||||
@ -78,8 +78,14 @@ public abstract class MethodDispatchNode extends BuiltinRootNode {
|
||||
}
|
||||
}
|
||||
|
||||
UnresolvedSymbol buildToArray(UnresolvedSymbol originalSymbol) {
|
||||
return UnresolvedSymbol.build("to_array", originalSymbol.getScope());
|
||||
@Specialization
|
||||
public Stateful runUncached(VirtualFrame frame) {
|
||||
UnresolvedSymbol sym = getSymbol(frame);
|
||||
return run(frame, sym, sym.getScope(), buildToArray(sym.getScope()));
|
||||
}
|
||||
|
||||
UnresolvedSymbol buildToArray(ModuleScope scope) {
|
||||
return UnresolvedSymbol.build("to_array", scope);
|
||||
}
|
||||
|
||||
UnresolvedSymbol getSymbol(VirtualFrame frame) {
|
||||
|
@ -0,0 +1,16 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "abs", description = "Big integer absolute value.")
|
||||
public class AbsNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
Object execute(EnsoBigInteger _this) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.abs(_this.getValue()));
|
||||
}
|
||||
}
|
@ -29,6 +29,11 @@ public abstract class AddNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.add(_this.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(EnsoBigInteger _this, double that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) + that;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.+", this);
|
||||
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "div", description = "Big integer integral division.")
|
||||
public abstract class DivNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static DivNode build() {
|
||||
return DivNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doLong(EnsoBigInteger _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.divide(_this.getValue(), that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.divide(_this.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.div", this);
|
||||
}
|
||||
}
|
@ -5,32 +5,34 @@ import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "/", description = "Big integer division.")
|
||||
public abstract class DivideNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
abstract double execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static DivideNode build() {
|
||||
return DivideNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doLong(EnsoBigInteger _this, long that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.divide(_this.getValue(), that));
|
||||
double doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) / BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.divide(_this.getValue(), that.getValue()));
|
||||
double doLong(EnsoBigInteger _this, long that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) / that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(EnsoBigInteger _this, double that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) / that;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
double doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer./", this);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,11 @@ public abstract class EqualsNode extends Node {
|
||||
return BigIntegerOps.equals(_this.getValue(), that.getValue());
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(EnsoBigInteger _this, double that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) == that;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(EnsoBigInteger _this, Object that) {
|
||||
return false;
|
||||
|
@ -0,0 +1,39 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = ">", description = "Comparison of numbers.")
|
||||
public abstract class GreaterNode extends Node {
|
||||
|
||||
abstract boolean execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static GreaterNode build() {
|
||||
return GreaterNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(EnsoBigInteger _this, double that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) > that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(EnsoBigInteger _this, long that) {
|
||||
return _this.getValue().signum() > 0;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return BigIntegerOps.compare(_this.getValue(), that.getValue()) > 0;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.>", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = ">=", description = "Comparison of numbers.")
|
||||
public abstract class GreaterOrEqualNode extends Node {
|
||||
|
||||
abstract boolean execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static GreaterOrEqualNode build() {
|
||||
return GreaterOrEqualNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(EnsoBigInteger _this, double that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) >= that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(EnsoBigInteger _this, long that) {
|
||||
return _this.getValue().signum() > 0;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return BigIntegerOps.compare(_this.getValue(), that.getValue()) >= 0;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.>=", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "<", description = "Comparison of numbers.")
|
||||
public abstract class LessNode extends Node {
|
||||
|
||||
abstract boolean execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static LessNode build() {
|
||||
return LessNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(EnsoBigInteger _this, double that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) < that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(EnsoBigInteger _this, long that) {
|
||||
return _this.getValue().signum() < 0;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return BigIntegerOps.compare(_this.getValue(), that.getValue()) < 0;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.<", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "<=", description = "Comparison of numbers.")
|
||||
public abstract class LessOrEqualNode extends Node {
|
||||
|
||||
abstract boolean execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static LessOrEqualNode build() {
|
||||
return LessOrEqualNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(EnsoBigInteger _this, double that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) <= that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(EnsoBigInteger _this, long that) {
|
||||
return _this.getValue().signum() < 0;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
return BigIntegerOps.compare(_this.getValue(), that.getValue()) <= 0;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.<=", this);
|
||||
}
|
||||
}
|
@ -13,9 +13,9 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
public abstract class MultiplyNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
public abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
static MultiplyNode build() {
|
||||
public static MultiplyNode build() {
|
||||
return MultiplyNodeGen.create();
|
||||
}
|
||||
|
||||
@ -29,6 +29,11 @@ public abstract class MultiplyNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.multiply(_this.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(EnsoBigInteger _this, double that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) * that;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.*", this);
|
||||
|
@ -0,0 +1,54 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "^", description = "Big integer exponentiation.")
|
||||
public abstract class PowNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
public abstract Object execute(EnsoBigInteger _this, Object that);
|
||||
|
||||
public static PowNode build() {
|
||||
return PowNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doLong(EnsoBigInteger _this, long that) {
|
||||
if (that == 0) {
|
||||
return 1L;
|
||||
} else if (that > 0) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.pow(_this.getValue(), that));
|
||||
} else {
|
||||
return Math.pow(BigIntegerOps.toDouble(_this.getValue()), that);
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(EnsoBigInteger _this, EnsoBigInteger that) {
|
||||
if (that.getValue().signum() > 0) {
|
||||
return Math.pow(
|
||||
BigIntegerOps.toDouble(_this.getValue()), BigIntegerOps.toDouble(that.getValue()));
|
||||
} else if (that.getValue().signum() == 0) {
|
||||
return 1.0D;
|
||||
} else {
|
||||
return 0.0D;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(EnsoBigInteger _this, double that) {
|
||||
return Math.pow(BigIntegerOps.toDouble(_this.getValue()), that);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.^", this);
|
||||
}
|
||||
}
|
@ -29,6 +29,11 @@ public abstract class SubtractNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.subtract(_this.getValue(), that.getValue()));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(EnsoBigInteger _this, double that) {
|
||||
return BigIntegerOps.toDouble(_this.getValue()) - that;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(EnsoBigInteger _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.-", this);
|
||||
|
@ -0,0 +1,16 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.bigInteger;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Big_Integer",
|
||||
name = "to_decimal",
|
||||
description = "Conversion of integers to decimals")
|
||||
public class ToDecimalNode extends Node {
|
||||
double execute(EnsoBigInteger _this) {
|
||||
return BigIntegerOps.toDouble(_this.getValue());
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "abs", description = "Absolute value of a number.")
|
||||
public class AbsNode extends Node {
|
||||
double execute(double _this) {
|
||||
return Math.abs(_this);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "+", description = "Addition of numbers.")
|
||||
public abstract class AddNode extends Node {
|
||||
abstract double execute(double _this, Object that);
|
||||
|
||||
static AddNode build() {
|
||||
return AddNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(double _this, double that) {
|
||||
return _this + that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doLong(double _this, long that) {
|
||||
return _this + that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return _this + BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Decimal.+", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "/", description = "Division of numbers.")
|
||||
public abstract class DivideNode extends Node {
|
||||
abstract double execute(double _this, Object that);
|
||||
|
||||
static DivideNode build() {
|
||||
return DivideNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(double _this, double that) {
|
||||
return _this / that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doLong(double _this, long that) {
|
||||
return _this / that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return _this / BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Decimal./", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "==", description = "Equality on numbers.")
|
||||
public abstract class EqualsNode extends Node {
|
||||
|
||||
abstract boolean execute(double _this, Object that);
|
||||
|
||||
static EqualsNode build() {
|
||||
return EqualsNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(double _this, double that) {
|
||||
return _this == that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(double _this, long that) {
|
||||
return _this == (double) that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return _this == BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(double _this, Object that) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = ">", description = "Comparison of numbers.")
|
||||
public abstract class GreaterNode extends Node {
|
||||
|
||||
abstract boolean execute(double _this, Object that);
|
||||
|
||||
static GreaterNode build() {
|
||||
return GreaterNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(double _this, double that) {
|
||||
return _this > that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(double _this, long that) {
|
||||
return _this > (double) that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return _this > BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(double _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Decimal.>", this);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = ">=", description = "Comparison of numbers.")
|
||||
public abstract class GreaterOrEqualNode extends Node {
|
||||
|
||||
abstract boolean execute(double _this, Object that);
|
||||
|
||||
static GreaterOrEqualNode build() {
|
||||
return GreaterOrEqualNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(double _this, double that) {
|
||||
return _this >= that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(double _this, long that) {
|
||||
return _this >= (double) that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return _this >= BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(double _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Decimal.>=", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "<", description = "Comparison of numbers.")
|
||||
public abstract class LessNode extends Node {
|
||||
|
||||
abstract boolean execute(double _this, Object that);
|
||||
|
||||
static LessNode build() {
|
||||
return LessNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(double _this, double that) {
|
||||
return _this < that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(double _this, long that) {
|
||||
return _this < (double) that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return _this < BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(double _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Decimal.<", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "<=", description = "Comparison of numbers.")
|
||||
public abstract class LessOrEqualNode extends Node {
|
||||
|
||||
abstract boolean execute(double _this, Object that);
|
||||
|
||||
static LessOrEqualNode build() {
|
||||
return LessOrEqualNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(double _this, double that) {
|
||||
return _this <= that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(double _this, long that) {
|
||||
return _this <= (double) that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return _this <= BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(double _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Decimal.<=", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "*", description = "Multiplication of numbers.")
|
||||
public abstract class MultiplyNode extends Node {
|
||||
abstract double execute(double _this, Object that);
|
||||
|
||||
static MultiplyNode build() {
|
||||
return MultiplyNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(double _this, double that) { return _this * that;}
|
||||
|
||||
@Specialization
|
||||
double doLong(double _this, long that) {
|
||||
return _this * that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return _this * BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Decimal.*", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "negate", description = "Negation for numbers.")
|
||||
public class NegateNode extends Node {
|
||||
double execute(double _this) {
|
||||
return -_this;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "^", description = "Exponentiation of numbers.")
|
||||
public abstract class PowNode extends Node {
|
||||
abstract double execute(double _this, Object that);
|
||||
|
||||
static PowNode build() {
|
||||
return PowNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(double _this, double that) {
|
||||
return Math.pow(_this, that);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doLong(double _this, long that) {
|
||||
return Math.pow(_this, that);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return Math.pow(_this, BigIntegerOps.toDouble(that.getValue()));
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Decimal.^", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Decimal", name = "-", description = "Subtraction of numbers.")
|
||||
public abstract class SubtractNode extends Node {
|
||||
abstract double execute(double _this, Object that);
|
||||
|
||||
static SubtractNode build() {
|
||||
return SubtractNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(double _this, double that) {
|
||||
return _this - that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doLong(double _this, long that) {
|
||||
return _this - that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doBigInteger(double _this, EnsoBigInteger that) {
|
||||
return _this - BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
double doOther(double _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Decimal.-", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Decimal",
|
||||
name = "to_decimal",
|
||||
description = "Identity on decimals")
|
||||
public class ToDecimalNode extends Node {
|
||||
double execute(double _this) {
|
||||
return _this;
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = "negate", description = "Negation for numbers.")
|
||||
public abstract class AbsNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
static AbsNode build() {
|
||||
return AbsNodeGen.create();
|
||||
}
|
||||
|
||||
abstract Object execute(long _this);
|
||||
|
||||
@Specialization(rewriteOn = ArithmeticException.class)
|
||||
long doNormal(long _this) {
|
||||
if (_this < 0) {
|
||||
return Math.negateExact(_this);
|
||||
} else {
|
||||
return _this;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doOverflow(long _this) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.abs(_this));
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNod
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "+", description = "Addition of numbers.")
|
||||
@BuiltinMethod(type = "Small_Integer", name = "+", description = "Addition of numbers.")
|
||||
public abstract class AddNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
@ -29,6 +29,11 @@ public abstract class AddNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.add(_this, that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(long _this, double that) {
|
||||
return _this + that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.add(that.getValue(), _this));
|
||||
|
@ -0,0 +1,32 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = "div", description = "Division of numbers.")
|
||||
public abstract class DivNode extends Node {
|
||||
abstract Object execute(long _this, Object that);
|
||||
|
||||
static DivNode build() {
|
||||
return DivNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doLong(long _this, long that) {
|
||||
return _this / that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return 0L;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.div", this);
|
||||
}
|
||||
}
|
@ -4,29 +4,35 @@ import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "/", description = "Division of numbers.")
|
||||
@BuiltinMethod(type = "Small_Integer", name = "/", description = "Division of numbers.")
|
||||
public abstract class DivideNode extends Node {
|
||||
abstract Object execute(long _this, Object that);
|
||||
abstract double execute(long _this, Object that);
|
||||
|
||||
static DivideNode build() {
|
||||
return DivideNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doLong(long _this, long that) {
|
||||
double doLong(long _this, long that) {
|
||||
return ((double) _this) / ((double) that);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(long _this, double that) {
|
||||
return _this / that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
long doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return 0L;
|
||||
double doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return ((double) _this) / BigIntegerOps.toDouble(that.getValue());
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(long _this, Object that) {
|
||||
double doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer./", this);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "==", description = "Equality on numbers.")
|
||||
@BuiltinMethod(type = "Small_Integer", name = "==", description = "Equality on numbers.")
|
||||
public abstract class EqualsNode extends Node {
|
||||
|
||||
abstract boolean execute(long _this, Object that);
|
||||
@ -19,6 +19,11 @@ public abstract class EqualsNode extends Node {
|
||||
return _this == that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(long _this, double that) {
|
||||
return (double) _this == that;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(long _this, Object that) {
|
||||
return false;
|
||||
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = ">", description = "Comparison of numbers.")
|
||||
public abstract class GreaterNode extends Node {
|
||||
|
||||
abstract boolean execute(long _this, Object that);
|
||||
|
||||
static GreaterNode build() {
|
||||
return GreaterNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(long _this, long that) {
|
||||
return _this > that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(long _this, double that) {
|
||||
return (double) _this > that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return that.getValue().signum() < 0;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.>", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = ">=", description = "Comparison of numbers.")
|
||||
public abstract class GreaterOrEqualNode extends Node {
|
||||
|
||||
abstract boolean execute(long _this, Object that);
|
||||
|
||||
static GreaterOrEqualNode build() {
|
||||
return GreaterOrEqualNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(long _this, long that) {
|
||||
return _this >= that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(long _this, double that) {
|
||||
return (double) _this >= that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return that.getValue().signum() < 0;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.>=", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = "<", description = "Comparison of numbers.")
|
||||
public abstract class LessNode extends Node {
|
||||
|
||||
abstract boolean execute(long _this, Object that);
|
||||
|
||||
static LessNode build() {
|
||||
return LessNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(long _this, long that) {
|
||||
return _this < that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(long _this, double that) {
|
||||
return (double) _this < that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return that.getValue().signum() > 0;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.<", this);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = "<=", description = "Comparison of numbers.")
|
||||
public abstract class LessOrEqualNode extends Node {
|
||||
|
||||
abstract boolean execute(long _this, Object that);
|
||||
|
||||
static LessOrEqualNode build() {
|
||||
return LessOrEqualNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doLong(long _this, long that) {
|
||||
return _this <= that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doDouble(long _this, double that) {
|
||||
return (double) _this <= that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
boolean doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return that.getValue().signum() > 0;
|
||||
}
|
||||
|
||||
@Fallback
|
||||
boolean doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.<=", this);
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "%", description = "Modulo division of numbers.")
|
||||
@BuiltinMethod(type = "Small_Integer", name = "%", description = "Modulo division of numbers.")
|
||||
public abstract class ModNode extends Node {
|
||||
abstract Object execute(long _this, Object that);
|
||||
|
||||
|
@ -9,7 +9,7 @@ import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNod
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "*", description = "Multiplication of numbers.")
|
||||
@BuiltinMethod(type = "Small_Integer", name = "*", description = "Multiplication of numbers.")
|
||||
public abstract class MultiplyNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
@ -29,6 +29,11 @@ public abstract class MultiplyNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.multiply(_this, that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(long _this, double that) {
|
||||
return ((double) _this) * that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.multiply(that.getValue(), _this));
|
||||
|
@ -6,7 +6,7 @@ import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "negate", description = "Negation for numbers.")
|
||||
@BuiltinMethod(type = "Small_Integer", name = "negate", description = "Negation for numbers.")
|
||||
public abstract class NegateNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
|
@ -0,0 +1,78 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.BigIntegerOps;
|
||||
import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNode;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = "^", description = "Exponentation of numbers.")
|
||||
public abstract class PowNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
private @Child org.enso.interpreter.node.expression.builtin.number.int64.MultiplyNode
|
||||
longMultiplyNode =
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.MultiplyNode.build();
|
||||
private @Child org.enso.interpreter.node.expression.builtin.number.bigInteger.MultiplyNode
|
||||
bigIntMultiplyNode =
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.MultiplyNode.build();
|
||||
private @Child org.enso.interpreter.node.expression.builtin.number.bigInteger.PowNode
|
||||
bigIntPowNode =
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.PowNode.build();
|
||||
|
||||
abstract Object execute(long _this, Object that);
|
||||
|
||||
static PowNode build() {
|
||||
return PowNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doLong(long _this, long that) {
|
||||
if (that < 0) {
|
||||
return Math.pow(_this, that);
|
||||
} else if (that == 0) {
|
||||
return 1L;
|
||||
} else {
|
||||
Object res = 1L;
|
||||
Object base = _this;
|
||||
while (that > 0) {
|
||||
if (that % 2 == 0) {
|
||||
if (base instanceof Long) {
|
||||
base = longMultiplyNode.execute((long) base, base);
|
||||
} else {
|
||||
base = bigIntMultiplyNode.execute((EnsoBigInteger) base, base);
|
||||
}
|
||||
that /= 2;
|
||||
} else {
|
||||
if (res instanceof Long) {
|
||||
res = longMultiplyNode.execute((long) res, base);
|
||||
} else {
|
||||
res = bigIntMultiplyNode.execute((EnsoBigInteger) res, base);
|
||||
}
|
||||
that--;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(long _this, double that) {
|
||||
return Math.pow(_this, that);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return bigIntPowNode.execute(new EnsoBigInteger(BigInteger.valueOf(_this)), that);
|
||||
}
|
||||
|
||||
@Fallback
|
||||
Object doOther(long _this, Object that) {
|
||||
throw new TypeError("Unexpected type provided for argument `that` in Integer.^", this);
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import org.enso.interpreter.node.expression.builtin.number.utils.ToEnsoNumberNod
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Int_64", name = "-", description = "Subtraction of numbers.")
|
||||
@BuiltinMethod(type = "Small_Integer", name = "-", description = "Subtraction of numbers.")
|
||||
public abstract class SubtractNode extends Node {
|
||||
private @Child ToEnsoNumberNode toEnsoNumberNode = ToEnsoNumberNode.build();
|
||||
|
||||
@ -29,6 +29,11 @@ public abstract class SubtractNode extends Node {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.subtract(_this, that));
|
||||
}
|
||||
|
||||
@Specialization
|
||||
double doDouble(long _this, double that) {
|
||||
return _this - that;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Object doBigInteger(long _this, EnsoBigInteger that) {
|
||||
return toEnsoNumberNode.execute(BigIntegerOps.subtract(_this, that.getValue()));
|
||||
|
@ -0,0 +1,14 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.int64;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Small_Int",
|
||||
name = "to_decimal",
|
||||
description = "Conversion of integers to decimals.")
|
||||
public class ToDecimalNode extends Node {
|
||||
double execute(long _this) {
|
||||
return _this;
|
||||
}
|
||||
}
|
@ -86,8 +86,43 @@ public class BigIntegerOps {
|
||||
return BigInteger.valueOf(a).negate();
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger abs(BigInteger a) {
|
||||
return a.abs();
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger abs(long a) {
|
||||
return BigInteger.valueOf(a).abs();
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static boolean equals(BigInteger a, BigInteger b) {
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static double toDouble(BigInteger a) {
|
||||
return a.doubleValue();
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static int compare(BigInteger a, BigInteger b) {
|
||||
return a.compareTo(b);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger pow(BigInteger a, long b) {
|
||||
BigInteger res = BigInteger.valueOf(1);
|
||||
while (b > 0) {
|
||||
if (b % 2 == 0) {
|
||||
a = a.pow(2);
|
||||
b /= 2;
|
||||
} else {
|
||||
res = res.multiply(a);
|
||||
b--;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.literal;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.node.ExpressionNode;
|
||||
|
||||
/** A representation of decimal literals in Enso. */
|
||||
@NodeInfo(description = "A decimal literal.")
|
||||
public final class DecimalLiteralNode extends ExpressionNode {
|
||||
private final double value;
|
||||
|
||||
private DecimalLiteralNode(double value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of this node.
|
||||
*
|
||||
* @param value the value for the node to represent
|
||||
* @return a node representing the literal given by {@code value}
|
||||
*/
|
||||
public static DecimalLiteralNode build(double value) {
|
||||
return new DecimalLiteralNode(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the literal.
|
||||
*
|
||||
* @param frame the stack frame for execution
|
||||
* @return the value of the integer literal
|
||||
*/
|
||||
@Override
|
||||
public Object executeGeneric(VirtualFrame frame) {
|
||||
return this.value;
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ public class Number {
|
||||
private final AtomConstructor bigInteger;
|
||||
private final AtomConstructor integer;
|
||||
private final AtomConstructor number;
|
||||
private final AtomConstructor decimal;
|
||||
|
||||
/**
|
||||
* Creates and registers number builtins.
|
||||
@ -22,14 +23,17 @@ public class Number {
|
||||
smallInteger = new AtomConstructor("Small_Integer", scope).initializeFields();
|
||||
integer = new AtomConstructor("Integer", scope).initializeFields();
|
||||
bigInteger = new AtomConstructor("Big_Integer", scope).initializeFields();
|
||||
decimal = new AtomConstructor("Decimal", scope).initializeFields();
|
||||
|
||||
registerInt64Methods(language, scope);
|
||||
registerBigIntegerMethods(language, scope);
|
||||
registerDecimalMethods(language, scope);
|
||||
|
||||
scope.registerConstructor(number);
|
||||
scope.registerConstructor(smallInteger);
|
||||
scope.registerConstructor(integer);
|
||||
scope.registerConstructor(bigInteger);
|
||||
scope.registerConstructor(decimal);
|
||||
}
|
||||
|
||||
private void registerInt64Methods(Language language, ModuleScope scope) {
|
||||
@ -48,11 +52,21 @@ public class Number {
|
||||
"*",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.MultiplyMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"^",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.PowMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"/",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.DivideMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"div",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.DivMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"%",
|
||||
@ -63,11 +77,41 @@ public class Number {
|
||||
"negate",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.NegateMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"abs",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.AbsMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"==",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.EqualsMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
">",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.GreaterMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
">=",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.GreaterOrEqualMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"<",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.LessMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"<=",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.LessOrEqualMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"to_decimal",
|
||||
org.enso.interpreter.node.expression.builtin.number.int64.ToDecimalMethodGen.makeFunction(
|
||||
language));
|
||||
}
|
||||
|
||||
private void registerBigIntegerMethods(Language language, ModuleScope scope) {
|
||||
@ -87,11 +131,21 @@ public class Number {
|
||||
"*",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.MultiplyMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"^",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.PowMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"/",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.DivideMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"div",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.DivMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"%",
|
||||
@ -102,11 +156,110 @@ public class Number {
|
||||
"negate",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.NegateMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"abs",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.AbsMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"==",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.EqualsMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
">",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.GreaterMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
">=",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.GreaterOrEqualMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"<",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.LessMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"<=",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.LessOrEqualMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"to_decimal",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.ToDecimalMethodGen
|
||||
.makeFunction(language));
|
||||
}
|
||||
|
||||
private void registerDecimalMethods(Language language, ModuleScope scope) {
|
||||
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"+",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.AddMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"-",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.SubtractMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"*",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.MultiplyMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"^",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.PowMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"/",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.DivideMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"negate",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.NegateMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"abs",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.AbsMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"==",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.EqualsMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
">",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.GreaterMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
">=",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.GreaterOrEqualMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"<",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.LessMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"<=",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.LessOrEqualMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"to_decimal",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.ToDecimalMethodGen.makeFunction(
|
||||
language));
|
||||
}
|
||||
|
||||
/** @return the Int64 atom constructor. */
|
||||
@ -128,4 +281,9 @@ public class Number {
|
||||
public AtomConstructor getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
/** @return the Decimal atom constructor */
|
||||
public AtomConstructor getDecimal() {
|
||||
return decimal;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package org.enso.interpreter.runtime.number;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/** Internal wrapper for a {@link BigInteger}. */
|
||||
@ -19,4 +21,10 @@ public class EnsoBigInteger {
|
||||
public BigInteger getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public String toString() {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||
@TypeSystem({
|
||||
long.class,
|
||||
boolean.class,
|
||||
double.class,
|
||||
String.class,
|
||||
Function.class,
|
||||
Atom.class,
|
||||
|
@ -377,6 +377,8 @@ object AstToIr {
|
||||
allBranches,
|
||||
getIdentifiedLocation(inputAst)
|
||||
)
|
||||
case AstView.DecimalLiteral(intPart, fracPart) =>
|
||||
translateDecimalLiteral(inputAst, intPart, fracPart)
|
||||
case AST.App.any(inputAST) => translateApplicationLike(inputAST)
|
||||
case AST.Mixfix.any(inputAST) => translateApplicationLike(inputAST)
|
||||
case AST.Literal.any(inputAST) => translateLiteral(inputAST)
|
||||
@ -421,6 +423,26 @@ object AstToIr {
|
||||
* argument and cannot be performed any other way.
|
||||
*/
|
||||
|
||||
def translateDecimalLiteral(
|
||||
ast: AST,
|
||||
int: AST.Literal.Number,
|
||||
frac: AST.Literal.Number
|
||||
): Expression = {
|
||||
if (int.base.isDefined && int.base.get != "10") {
|
||||
Error.Syntax(
|
||||
int,
|
||||
Error.Syntax.UnsupportedSyntax("non-base-10 number literals")
|
||||
)
|
||||
} else if (frac.base.isDefined && frac.base.get != "10") {
|
||||
Error.Syntax(frac, Error.Syntax.InvalidBaseInDecimalLiteral)
|
||||
} else {
|
||||
Literal.Number(
|
||||
s"${int.shape.int}.${frac.shape.int}",
|
||||
getIdentifiedLocation(ast)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Translates a program literal from its [[AST]] representation into
|
||||
* [[IR]].
|
||||
*
|
||||
|
@ -842,6 +842,19 @@ object AstView {
|
||||
}
|
||||
}
|
||||
|
||||
object DecimalLiteral {
|
||||
def unapply(ast: AST): Option[(AST.Literal.Number, AST.Literal.Number)] =
|
||||
ast match {
|
||||
case AST.App.Infix(
|
||||
AST.Literal.Number.any(int),
|
||||
AST.Ident.Opr("."),
|
||||
AST.Literal.Number.any(frac)
|
||||
) =>
|
||||
Some((int, frac))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
|
||||
object UnaryMinus {
|
||||
def minusSymbol: String = "-"
|
||||
|
||||
|
@ -44,6 +44,7 @@ import org.enso.interpreter.node.expression.constant.{
|
||||
}
|
||||
import org.enso.interpreter.node.expression.literal.{
|
||||
BigIntegerLiteralNode,
|
||||
DecimalLiteralNode,
|
||||
IntegerLiteralNode,
|
||||
TextLiteralNode
|
||||
}
|
||||
@ -859,10 +860,14 @@ class IrToTruffle(
|
||||
*/
|
||||
def processLiteral(literal: IR.Literal): RuntimeExpression =
|
||||
literal match {
|
||||
case IR.Literal.Number(value, location, _, _) =>
|
||||
val node = value.toLongOption
|
||||
case lit @ IR.Literal.Number(value, location, _, _) =>
|
||||
val node = if (lit.isFractional) {
|
||||
DecimalLiteralNode.build(value.toDouble)
|
||||
} else {
|
||||
value.toLongOption
|
||||
.map(IntegerLiteralNode.build)
|
||||
.getOrElse(BigIntegerLiteralNode.build(new BigInteger(value)))
|
||||
}
|
||||
setLocation(node, location)
|
||||
case IR.Literal.Text(text, location, _, _) =>
|
||||
setLocation(TextLiteralNode.build(text), location)
|
||||
|
@ -1581,6 +1581,13 @@ object IR {
|
||||
override def children: List[IR] = List()
|
||||
|
||||
override def showCode(indent: Int): String = value
|
||||
|
||||
/**
|
||||
* Checks whether the literal represents a fractional value.
|
||||
*
|
||||
* @return `true` if the value is fractional, `false` otherwise.
|
||||
*/
|
||||
def isFractional: Boolean = value.contains(".")
|
||||
}
|
||||
|
||||
/** A textual Enso literal.
|
||||
@ -5563,6 +5570,11 @@ object IR {
|
||||
def explanation: String
|
||||
}
|
||||
|
||||
case object InvalidBaseInDecimalLiteral extends Reason {
|
||||
override def explanation: String =
|
||||
"Cannot change base of the fractional part of a number literal."
|
||||
}
|
||||
|
||||
case class UnsupportedSyntax(syntaxName: String) extends Reason {
|
||||
override def explanation: String =
|
||||
s"Syntax is not supported yet: $syntaxName."
|
||||
|
@ -15,5 +15,7 @@ main =
|
||||
mil = 1000000
|
||||
list = here.gen_list mil
|
||||
vec = Vector.new mil (ix -> ix + 1)
|
||||
vec_decimal = Vector.new mil (ix -> ix + 0.0)
|
||||
Bench_Utils.measure (vec.fold 0 (+)) "vector fold" 1000 10
|
||||
Bench_Utils.measure (list.fold 0 (+)) "list fold" 1000 10
|
||||
Bench_Utils.measure (vec_decimal.fold 0 (+)) "vector decimal fold" 1000 10
|
||||
|
@ -12,6 +12,14 @@ sum_tco = sum_to ->
|
||||
res = summator 0 sum_to
|
||||
res
|
||||
|
||||
sum_tco_decimal = sum_to ->
|
||||
s = sum_to.to_decimal
|
||||
summator = acc -> current ->
|
||||
if current >= s then acc else summator acc+current current+1.0
|
||||
res = summator 0.0 0.0
|
||||
res
|
||||
|
||||
|
||||
sum_tco_java = sum_to ->
|
||||
summator = acc -> current ->
|
||||
if current == 0 then acc else summator (Long.sum [acc, current]) (current - 1)
|
||||
@ -40,8 +48,10 @@ sum_state = sum_to ->
|
||||
|
||||
main =
|
||||
hundred_mil = 100000000
|
||||
IO.println "Measuring Sum TCO Decimal"
|
||||
Bench_Utils.measure (here.sum_tco_decimal hundred_mil) "sum_tco" 100 10
|
||||
IO.println "Measuring SumTCO"
|
||||
Bench_Utils.measure (here.sum_tco hundred_mil) "sum_tco" 500 10
|
||||
Bench_Utils.measure (here.sum_tco hundred_mil) "sum_tco" 100 10
|
||||
IO.println "Measuring SumTCO Java"
|
||||
Bench_Utils.measure (here.sum_tco_java hundred_mil) "sum_tco" 100 10
|
||||
IO.println "Measuring State"
|
||||
|
@ -2,7 +2,13 @@ from Base import all
|
||||
import Base.Test
|
||||
|
||||
polyglot java import java.lang.Long
|
||||
polyglot java import java.lang.Integer
|
||||
polyglot java import java.lang.Float
|
||||
|
||||
spec = describe "Java FFI" <|
|
||||
it "should call methods imported from Java" <|
|
||||
Long.sum [1, 2] . should_equal 3
|
||||
it "should auto-convert numeric types across the polyglot boundary" <|
|
||||
(Float.valueOf ["123.3"] + 5).should_equal 128.3 epsilon=0.0001
|
||||
(Integer.sum [1, 2] + 3) . should_equal 6
|
||||
|
||||
|
@ -3,8 +3,10 @@ from Base import all
|
||||
import Base.Test
|
||||
|
||||
Integer.is_even = this % 2 == 0
|
||||
Decimal.get_fun_factor = "Wow, " + this.to_text + " is such a fun number!"
|
||||
|
||||
spec =
|
||||
eps = 0.000001
|
||||
almost_max_long = 9223372036854775806
|
||||
almost_max_long_times_three = 27670116110564327418
|
||||
hundred_factorial = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
|
||||
@ -17,7 +19,7 @@ spec =
|
||||
(0 - almost_max_long - almost_max_long - almost_max_long).should_equal almost_max_long_times_three.negate
|
||||
it "should be of unbound size when dividing" <|
|
||||
expected = 3372816184472482867110284450043137767873196479305249187406461598235841786750685581361224832688174410089430537516012695688121622150430744676
|
||||
((1.upto 101 . fold 1 (*)) / 3*almost_max_long).should_equal expected
|
||||
((1.upto 101 . fold 1 (*)).div 3*almost_max_long).should_equal expected
|
||||
it "should be of unbound size when taking remainder" <|
|
||||
expected = 3191479909175673432
|
||||
((1.upto 101 . fold 1 (*)) % 3*almost_max_long).should_equal expected
|
||||
@ -34,4 +36,33 @@ spec =
|
||||
(hundred_factorial == 1).should_be_false
|
||||
it "should properly handle going to big numbers and back" <|
|
||||
((almost_max_long * 3) / 3) . should_equal almost_max_long
|
||||
|
||||
it "should use floating point arithmetic for division" <|
|
||||
(3 / 4) . should_equal 0.75 epsilon=eps
|
||||
(almost_max_long * 2 / almost_max_long_times_three) . should_equal 0.6666666 epsilon=eps
|
||||
describe "Decimals" <|
|
||||
it "should exist and expose basic arithmetic operations" <|
|
||||
((1.5 + 1.5)*1.3 / 2 - 3) . should_equal -1.05 epsilon=eps
|
||||
it "should allow defining extension methods through the Decimal type" <|
|
||||
32.5.get_fun_factor.should_equal "Wow, 32.5 is such a fun number!"
|
||||
describe "Numbers" <|
|
||||
it "should expose comparison operators" <|
|
||||
(3 < hundred_factorial).should_be_true
|
||||
(hundred_factorial < 3).should_be_false
|
||||
(3.0 < hundred_factorial).should_be_true
|
||||
(3.0 <= 3.4).should_be_true
|
||||
(3.0 >= 2).should_be_true
|
||||
(-hundred_factorial > 0).should_be_false
|
||||
it "should expose exponentiation operations" <|
|
||||
(3.14 ^ 2.71).should_equal 22.216689546 epsilon=eps
|
||||
(3.14 ^ 14).should_equal 9057640.36635 epsilon=eps
|
||||
a = almost_max_long
|
||||
(a ^ 4).should_equal (a * a * a * a)
|
||||
(2 ^ 10).should_equal 1024
|
||||
(2 ^ 0.5).should_equal 1.41421356237 epsilon=eps
|
||||
(a^2)^0.5 . should_equal a epsilon=eps
|
||||
it "should expose more involved mathematical functions" <|
|
||||
Math.Pi.sin.should_equal 0 epsilon=eps
|
||||
(Math.Pi / 4).sin.should_equal (2 ^ 0.5)/2 epsilon=eps
|
||||
(Math.Pi / 6).cos.should_equal (3.sqrt / 2) epsilon=eps
|
||||
(17 ^ 0.13).log base=17 . should_equal 0.13 epsilon=eps
|
||||
0.exp.should_equal 1
|
||||
|
Loading…
Reference in New Issue
Block a user