mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 22:10:15 +03:00
Add Number.noise
to the standard library (#1295)
This commit is contained in:
parent
4d5f794122
commit
cf9be4ff29
71
distribution/std-lib/Base/src/Data/Interval.enso
Normal file
71
distribution/std-lib/Base/src/Data/Interval.enso
Normal file
@ -0,0 +1,71 @@
|
||||
from Base import all
|
||||
|
||||
import Base.Data.Interval.Bound
|
||||
|
||||
export Base.Data.Interval.Bound
|
||||
|
||||
## Creates an interval that excludes both its bounds.
|
||||
|
||||
> Example
|
||||
Create the bounds-exclusive range from 1 to 5.
|
||||
Interval.exclusive 1 5
|
||||
exclusive : Any -> Any -> Interval
|
||||
exclusive start end = Interval (Bound.Exclusive start) (Bound.Exclusive end)
|
||||
|
||||
## Creates an interval that excludes its lower bound.
|
||||
|
||||
> Example
|
||||
Create the start-exclusive range from 1 to 5.
|
||||
Interval.start_exclusive 1 5
|
||||
start_exclusive : Any -> Any -> Interval
|
||||
start_exclusive start end = Interval (Bound.Exclusive start) (Bound.Inclusive end)
|
||||
|
||||
## Creates an interval that excludes its upper bound.
|
||||
|
||||
> Example
|
||||
Create the end-exclusive range from 1 to 5.
|
||||
Interval.end_exclusive 1 5
|
||||
end_exclusive : Any -> Any -> Interval
|
||||
end_exclusive start end = Interval (Bound.Inclusive start) (Bound.Exclusive end)
|
||||
|
||||
## Creates an interval that includes its upper bound.
|
||||
|
||||
> Example
|
||||
Create the inclusive range from 1 to 5.
|
||||
Interval.inclusive 1 5
|
||||
inclusive : Any -> Any -> Interval
|
||||
inclusive start end = Interval (Bound.Inclusive start) (Bound.Inclusive end)
|
||||
|
||||
## An interval type
|
||||
type Interval
|
||||
type Interval start end
|
||||
|
||||
## Checks if the interval contains `that`.
|
||||
|
||||
> Example
|
||||
Checking if the interval 1 to 5 contains 7.
|
||||
(Interval.inclusive 1 5) . contains 7
|
||||
contains : Any -> Boolean
|
||||
contains that = if this.start.n > this.end.n then False else
|
||||
case this.start of
|
||||
Bound.Exclusive s -> (that > s) && case this.end of
|
||||
Bound.Exclusive e -> that < e
|
||||
Bound.Inclusive e -> that <= e
|
||||
Bound.Inclusive s -> (that >= s) && case this.end of
|
||||
Bound.Exclusive e -> that < e
|
||||
Bound.Inclusive e -> that <= e
|
||||
|
||||
## Check if this interval is empty.
|
||||
is_empty : Boolean
|
||||
is_empty = case this.start of
|
||||
Bound.Exclusive s -> case this.end of
|
||||
Bound.Exclusive e -> s >= e
|
||||
Bound.Inclusive e -> s >= e
|
||||
Bound.Inclusive s -> case this.end of
|
||||
Bound.Exclusive e -> s >= e
|
||||
Bound.Inclusive e -> s > e
|
||||
|
||||
## Check if this interval is not empty.
|
||||
not_empty : Boolean
|
||||
not_empty = this.is_empty.not
|
||||
|
11
distribution/std-lib/Base/src/Data/Interval/Bound.enso
Normal file
11
distribution/std-lib/Base/src/Data/Interval/Bound.enso
Normal file
@ -0,0 +1,11 @@
|
||||
from Base import all
|
||||
|
||||
## A type representing an interval bound over any orderable type.
|
||||
|
||||
An orderable type is one that
|
||||
type Bound
|
||||
## A bound that includes `n`.
|
||||
type Inclusive n
|
||||
|
||||
## A bound that excludes `n`.
|
||||
type Exclusive n
|
19
distribution/std-lib/Base/src/Data/Noise.enso
Normal file
19
distribution/std-lib/Base/src/Data/Noise.enso
Normal file
@ -0,0 +1,19 @@
|
||||
from Base import all
|
||||
|
||||
from Base.Data.Noise.Generator import all
|
||||
|
||||
## Generate noise based on the input number.
|
||||
|
||||
The output of the noise generator will depend on the input and the range over
|
||||
which the noise is being generated.
|
||||
|
||||
By default, this uses a seeded deterministic generator that will always
|
||||
return the same input for the same output. In addition, it will, by default,
|
||||
generate values in the exclusive range 0 to 1.
|
||||
|
||||
> Example
|
||||
Deterministically perturb the input number 1.
|
||||
1.noise
|
||||
Number.noise : Interval -> Generator -> Any
|
||||
Number.noise (interval = Interval.exclusive 0 1) gen=Deterministic_Random =
|
||||
gen.step this interval
|
45
distribution/std-lib/Base/src/Data/Noise/Generator.enso
Normal file
45
distribution/std-lib/Base/src/Data/Noise/Generator.enso
Normal file
@ -0,0 +1,45 @@
|
||||
from Base import all
|
||||
|
||||
import Base.Data.Interval.Bound
|
||||
import Base.Error.Extensions
|
||||
|
||||
polyglot java import java.util.Random
|
||||
polyglot java import java.lang.Long
|
||||
|
||||
## The interface for the noise generator abstraction.
|
||||
|
||||
To be a valid generator, it must provide the `step` method as described
|
||||
below.
|
||||
type Generator
|
||||
type Generator
|
||||
|
||||
## Step the generator to produce the next value..
|
||||
|
||||
The parameters are as follows:
|
||||
- The input number, which is intended for use as a seed.
|
||||
- A range for output values, which should range over the chosen output
|
||||
type.
|
||||
|
||||
The return type may be chosen freely by the generator implementation, as
|
||||
it usually depends on the generator and its intended use.
|
||||
step : Number -> Interval -> Any
|
||||
step _ _ = Unimplemented "Only intended to demonstrate an interface."
|
||||
|
||||
## A noise generator that implements a seeded deterministic random peterbation
|
||||
of the input.
|
||||
|
||||
It produces what is commonly termed "white" noise, where any value in the
|
||||
range has an equal chance of occurring.
|
||||
type Deterministic_Random
|
||||
type Deterministic_Random
|
||||
|
||||
## Step the generator to produce the next value.
|
||||
step : Number -> Interval -> Number
|
||||
step input interval =
|
||||
max_long = Polyglot.get_member Long "MAX_VALUE"
|
||||
seed = input.floor % max_long
|
||||
gen = Random.new [seed].to_array
|
||||
value_range = (interval.end.n - interval.start.n).abs
|
||||
offset = (interval.start.n)
|
||||
val = gen.nextDouble []
|
||||
(val * value_range) + offset
|
@ -94,3 +94,4 @@ Number.max that = if this > that then this else that
|
||||
## Number to JSON conversion.
|
||||
Number.to_json : Json.Number
|
||||
Number.to_json = Json.Number this
|
||||
|
||||
|
@ -4,3 +4,11 @@ from Base import all
|
||||
No_Such_Method_Error.method_name : Text
|
||||
No_Such_Method_Error.method_name =
|
||||
Meta.meta this.symbol . name
|
||||
|
||||
## A type used to represent that something has not yet been implemented.
|
||||
type Unimplemented_Error message
|
||||
|
||||
## A function that can be used to indicate that something hasn't been
|
||||
implemented yet.
|
||||
unimplemented : Text -> Void ! Unimplemented_Error
|
||||
unimplemented message="" = Panic.throw (Unimplemented_Error message)
|
||||
|
@ -1,7 +1,9 @@
|
||||
import Base.Data.Any.Extensions
|
||||
import Base.Data.Interval
|
||||
import Base.Data.Json
|
||||
import Base.Data.List
|
||||
import Base.Data.Map
|
||||
import Base.Data.Noise
|
||||
import Base.Data.Number.Extensions
|
||||
import Base.Data.Pair
|
||||
import Base.Data.Range
|
||||
@ -16,6 +18,7 @@ import Base.System.File
|
||||
|
||||
from Builtins import Nothing, Number, Integer, Any, True, False, Cons, Boolean
|
||||
|
||||
export Base.Data.Interval
|
||||
export Base.Data.Json
|
||||
export Base.Data.Map
|
||||
export Base.Data.Vector
|
||||
@ -25,6 +28,7 @@ export Base.System.File
|
||||
|
||||
from Base.Data.Any.Extensions export all
|
||||
from Base.Data.List export Nil, Cons
|
||||
from Base.Data.Noise export all hiding Noise
|
||||
from Base.Data.Number.Extensions export all hiding Math, String
|
||||
from Base.Data.Pair export Pair
|
||||
from Base.Data.Range export Range
|
||||
|
@ -48,6 +48,22 @@ Any.should verb argument = Verbs.verb this argument
|
||||
## Fail a test with the given message.
|
||||
fail message = Panic.throw (Failure message)
|
||||
|
||||
## Expect a function to fail with the provided error.
|
||||
expect_fail_with ~action matcher =
|
||||
res = Panic.recover action
|
||||
case res of
|
||||
_ -> here.fail ("Expected a " + matcher.to_text + " to be thrown, but the action succeeded.")
|
||||
err = res.catch x->x
|
||||
case Meta.meta matcher of
|
||||
Meta.Atom _ -> if err == matcher then Success else
|
||||
here.fail ("Expected a " + matcher.to_text + "be thrown, but found " + err.to_text + ".")
|
||||
Meta.Constructor _ ->
|
||||
meta_err = Meta.meta err
|
||||
case meta_err of
|
||||
Meta.Atom _ -> if meta_err.constructor == matcher then Success else
|
||||
here.fail ("Unexpected error " + err.to_text + " thrown.")
|
||||
_ -> here.fail ("Incorrect instance " + err.to_text + ".")
|
||||
|
||||
## Asserts that `this` value is equal to the expected value.
|
||||
Any.should_equal that = case this == that of
|
||||
True -> Success
|
||||
|
@ -0,0 +1,12 @@
|
||||
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.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "ceil", description = "Big integer ceiling.")
|
||||
public class CeilNode extends Node {
|
||||
Object execute(EnsoBigInteger _this) {
|
||||
return _this;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
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.runtime.number.EnsoBigInteger;
|
||||
|
||||
@BuiltinMethod(type = "Big_Integer", name = "floor", description = "Big integer floor.")
|
||||
public class FloorNode extends Node {
|
||||
Object execute(EnsoBigInteger _this) {
|
||||
return _this;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import java.math.BigDecimal;
|
||||
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 = "ceil",
|
||||
description = "Decimal ceiling, converting to a small or big integer depending on size.")
|
||||
public class CeilNode extends Node {
|
||||
private final ConditionProfile fitsProfile = ConditionProfile.createCountingProfile();
|
||||
|
||||
Object execute(double _this) {
|
||||
double ceil = Math.ceil(_this);
|
||||
if (fitsProfile.profile(BigIntegerOps.fitsInLong(ceil))) {
|
||||
return (long) ceil;
|
||||
} else {
|
||||
return new EnsoBigInteger(BigDecimal.valueOf(ceil).toBigIntegerExact());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.decimal;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import java.math.BigDecimal;
|
||||
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 = "floor",
|
||||
description = "Decimal floor, converting to a small or big integer depending on size.")
|
||||
public class FloorNode extends Node {
|
||||
private final ConditionProfile fitsProfile = ConditionProfile.createCountingProfile();
|
||||
|
||||
Object execute(double _this) {
|
||||
double floor = Math.floor(_this);
|
||||
if (fitsProfile.profile(BigIntegerOps.fitsInLong(floor))) {
|
||||
return (long) floor;
|
||||
} else {
|
||||
return new EnsoBigInteger(BigDecimal.valueOf(floor).toBigIntegerExact());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.smallInteger;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = "ceil", description = "Small integer ceiling.")
|
||||
public class CeilNode extends Node {
|
||||
long execute(long _this) {
|
||||
return _this;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number.smallInteger;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Small_Integer", name = "floor", description = "Small integer floor.")
|
||||
public class FloorNode extends Node {
|
||||
long execute(long _this) {
|
||||
return _this;
|
||||
}
|
||||
}
|
@ -6,6 +6,9 @@ import java.math.BigInteger;
|
||||
|
||||
/** Re-exposes big-integer operations behind a truffle boundary. */
|
||||
public class BigIntegerOps {
|
||||
private static final BigInteger MIN_LONG_BIGINT = BigInteger.valueOf(Long.MIN_VALUE);
|
||||
private static final BigInteger MAX_LONG_BIGINT = BigInteger.valueOf(Long.MAX_VALUE);
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static BigInteger multiply(long a, long b) {
|
||||
return BigInteger.valueOf(a).multiply(BigInteger.valueOf(b));
|
||||
@ -125,4 +128,13 @@ public class BigIntegerOps {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
public static boolean fitsInLong(BigInteger bigInteger) {
|
||||
return bigInteger.compareTo(MIN_LONG_BIGINT) >= 0 && bigInteger.compareTo(MAX_LONG_BIGINT) <= 0;
|
||||
}
|
||||
|
||||
public static boolean fitsInLong(double decimal) {
|
||||
return decimal <= Long.MAX_VALUE && decimal >= Long.MIN_VALUE;
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,6 @@ import java.math.BigInteger;
|
||||
public class ToEnsoNumberNode extends Node {
|
||||
private final ConditionProfile fitsProfile = ConditionProfile.createCountingProfile();
|
||||
|
||||
private static final BigInteger MIN_LONG_BIGINT = BigInteger.valueOf(Long.MIN_VALUE);
|
||||
private static final BigInteger MAX_LONG_BIGINT = BigInteger.valueOf(Long.MAX_VALUE);
|
||||
|
||||
/** @return a new instance of this node. */
|
||||
public static ToEnsoNumberNode build() {
|
||||
return new ToEnsoNumberNode();
|
||||
@ -30,17 +27,12 @@ public class ToEnsoNumberNode extends Node {
|
||||
* org.enso.interpreter.runtime.number.EnsoBigInteger} otherwise.
|
||||
*/
|
||||
public Object execute(BigInteger bigInteger) {
|
||||
if (fitsProfile.profile(fitsInLong(bigInteger))) {
|
||||
if (fitsProfile.profile(BigIntegerOps.fitsInLong(bigInteger))) {
|
||||
return toLong(bigInteger);
|
||||
}
|
||||
return new EnsoBigInteger(bigInteger);
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
private static boolean fitsInLong(BigInteger bigInteger) {
|
||||
return bigInteger.compareTo(MIN_LONG_BIGINT) >= 0 && bigInteger.compareTo(MAX_LONG_BIGINT) <= 0;
|
||||
}
|
||||
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
private static long toLong(BigInteger bigInteger) {
|
||||
return bigInteger.longValue();
|
||||
|
@ -112,6 +112,16 @@ public class Number {
|
||||
"to_decimal",
|
||||
org.enso.interpreter.node.expression.builtin.number.smallInteger.ToDecimalMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"floor",
|
||||
org.enso.interpreter.node.expression.builtin.number.smallInteger.FloorMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
smallInteger,
|
||||
"ceil",
|
||||
org.enso.interpreter.node.expression.builtin.number.smallInteger.CeilMethodGen.makeFunction(
|
||||
language));
|
||||
}
|
||||
|
||||
private void registerBigIntegerMethods(Language language, ModuleScope scope) {
|
||||
@ -191,6 +201,16 @@ public class Number {
|
||||
"to_decimal",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.ToDecimalMethodGen
|
||||
.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"floor",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.FloorMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
bigInteger,
|
||||
"ceil",
|
||||
org.enso.interpreter.node.expression.builtin.number.bigInteger.CeilMethodGen.makeFunction(
|
||||
language));
|
||||
}
|
||||
|
||||
private void registerDecimalMethods(Language language, ModuleScope scope) {
|
||||
@ -260,6 +280,16 @@ public class Number {
|
||||
"to_decimal",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.ToDecimalMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"floor",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.FloorMethodGen.makeFunction(
|
||||
language));
|
||||
scope.registerMethod(
|
||||
decimal,
|
||||
"ceil",
|
||||
org.enso.interpreter.node.expression.builtin.number.decimal.CeilMethodGen.makeFunction(
|
||||
language));
|
||||
}
|
||||
|
||||
/** @return the Int64 atom constructor. */
|
||||
|
@ -1,11 +1,15 @@
|
||||
package org.enso.interpreter.runtime.number;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.TruffleObject;
|
||||
|
||||
import com.oracle.truffle.api.library.ExportLibrary;
|
||||
import com.oracle.truffle.api.library.ExportMessage;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/** Internal wrapper for a {@link BigInteger}. */
|
||||
@ExportLibrary(InteropLibrary.class)
|
||||
public class EnsoBigInteger implements TruffleObject {
|
||||
private final BigInteger value;
|
||||
|
||||
@ -28,4 +32,9 @@ public class EnsoBigInteger implements TruffleObject {
|
||||
public String toString() {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
String toDisplayString(boolean allowSideEffects) {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
|
@ -448,8 +448,8 @@ object Builtin {
|
||||
sequenceLiteral,
|
||||
typesetLiteral,
|
||||
case_of,
|
||||
if_then,
|
||||
if_then_else,
|
||||
if_then,
|
||||
polyglotJavaImport,
|
||||
itemsImport,
|
||||
qualifiedImport,
|
||||
|
90
test/Tests/src/Data/Interval_Spec.enso
Normal file
90
test/Tests/src/Data/Interval_Spec.enso
Normal file
@ -0,0 +1,90 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
|
||||
spec =
|
||||
describe "Bound" <|
|
||||
it "should allow constructing inclusive bounds" <|
|
||||
bound = Interval.Bound.Inclusive 0
|
||||
bound.n . should_equal 0
|
||||
it "should allow constructing exclusive bounds" <|
|
||||
bound = Interval.Bound.Exclusive 0
|
||||
bound.n . should_equal 0
|
||||
it "should be able to be checked for equality" <|
|
||||
inclusive_1 = Interval.Bound.Inclusive 10
|
||||
inclusive_2 = Interval.Bound.Inclusive 5
|
||||
exclusive_1 = Interval.Bound.Exclusive 10
|
||||
exclusive_2 = Interval.Bound.Exclusive 5
|
||||
(inclusive_1 == inclusive_1) . should_be_true
|
||||
(inclusive_1 == inclusive_2) . should_be_false
|
||||
(exclusive_1 == exclusive_1) . should_be_true
|
||||
(exclusive_1 == exclusive_2) . should_be_false
|
||||
(inclusive_1 == exclusive_1) . should_be_false
|
||||
describe "Interval" <|
|
||||
it "should allow constructing exclusive intervals" <|
|
||||
interval = Interval.exclusive 1 5
|
||||
interval.start . should_equal (Interval.Bound.Exclusive 1)
|
||||
interval.end . should_equal (Interval.Bound.Exclusive 5)
|
||||
it "should allow constructing start-exclusive intervals" <|
|
||||
interval = Interval.start_exclusive 1 5
|
||||
interval.start . should_equal (Interval.Bound.Exclusive 1)
|
||||
interval.end . should_equal (Interval.Bound.Inclusive 5)
|
||||
it "should allow constructing end-exclusive intervals" <|
|
||||
interval = Interval.end_exclusive 1 5
|
||||
interval.start . should_equal (Interval.Bound.Inclusive 1)
|
||||
interval.end . should_equal (Interval.Bound.Exclusive 5)
|
||||
it "should allow constructing inclusive intervals" <|
|
||||
interval = Interval.inclusive 1 5
|
||||
interval.start . should_equal (Interval.Bound.Inclusive 1)
|
||||
interval.end . should_equal (Interval.Bound.Inclusive 5)
|
||||
it "should allow checking if an interval contains a value of the contained type" <|
|
||||
interval = Interval.end_exclusive 1 10
|
||||
interval.contains 0 . should_be_false
|
||||
interval.contains 1 . should_be_true
|
||||
interval.contains 9 . should_be_true
|
||||
interval.contains 10 . should_be_false
|
||||
interval.contains 10 . should_be_false
|
||||
|
||||
interval_2 = Interval.end_exclusive 0 0
|
||||
interval_2.contains -1 . should_be_false
|
||||
interval_2.contains 0 . should_be_false
|
||||
interval_2.contains 1 . should_be_false
|
||||
|
||||
interval_3 = Interval.end_exclusive 0 1
|
||||
interval_3.contains -1 . should_be_false
|
||||
interval_3.contains 0 . should_be_true
|
||||
interval_3.contains 1 . should_be_false
|
||||
|
||||
interval_4 = Interval.inclusive 0 0
|
||||
interval_4.contains -1 . should_be_false
|
||||
interval_4.contains 0 . should_be_true
|
||||
interval_4.contains 1 . should_be_false
|
||||
|
||||
interval_5 = Interval.exclusive 0 0
|
||||
interval_5.contains -1 . should_be_false
|
||||
interval_5.contains 0 . should_be_false
|
||||
interval_5.contains 1 . should_be_false
|
||||
|
||||
interval_6 = Interval.start_exclusive 0 0
|
||||
interval_6.contains -1 . should_be_false
|
||||
interval_6.contains 0 . should_be_false
|
||||
interval_6.contains 1 . should_be_false
|
||||
it "can be checked for emptiness" <|
|
||||
Interval.exclusive 0 0 . is_empty . should_be_true
|
||||
Interval.exclusive 1 10 . is_empty . should_be_false
|
||||
Interval.start_exclusive 0 0 . is_empty . should_be_true
|
||||
Interval.start_exclusive 1 10 . is_empty . should_be_false
|
||||
Interval.end_exclusive 0 0 . is_empty . should_be_true
|
||||
Interval.end_exclusive 1 10 . is_empty . should_be_false
|
||||
Interval.inclusive 0 0 . is_empty . should_be_false
|
||||
Interval.inclusive 10 0 . is_empty . should_be_true
|
||||
it "can be checked for non-emptiness" <|
|
||||
Interval.exclusive 0 0 . not_empty . should_be_false
|
||||
Interval.exclusive 1 10 . not_empty . should_be_true
|
||||
Interval.start_exclusive 0 0 . not_empty . should_be_false
|
||||
Interval.start_exclusive 1 10 . not_empty . should_be_true
|
||||
Interval.end_exclusive 0 0 . not_empty . should_be_false
|
||||
Interval.end_exclusive 1 10 . not_empty . should_be_true
|
||||
Interval.inclusive 0 0 . not_empty . should_be_true
|
||||
Interval.inclusive 10 0 . not_empty . should_be_false
|
||||
|
24
test/Tests/src/Data/Noise/Generator_Spec.enso
Normal file
24
test/Tests/src/Data/Noise/Generator_Spec.enso
Normal file
@ -0,0 +1,24 @@
|
||||
from Base import all
|
||||
|
||||
import Base.Data.Noise.Generator
|
||||
import Base.Error.Extensions
|
||||
|
||||
import Test
|
||||
|
||||
spec =
|
||||
describe "Generator Interface" <|
|
||||
gen = Generator.Generator
|
||||
it "should not be invokable" <|
|
||||
interval = Interval.inclusive 0 1
|
||||
Test.expect_fail_with (gen.step 1 interval) Extensions.Unimplemented_Error
|
||||
describe "Deterministic Random Noise Generator" <|
|
||||
gen = Generator.Deterministic_Random
|
||||
it "should always return the same output for the same input" <|
|
||||
interval = Interval.inclusive 0 1
|
||||
values = Vector.fill 10000 1 . map (gen.step _ interval)
|
||||
values.all (== values.at 0) . should_be_true
|
||||
it "should always produce values within the specified interval" <|
|
||||
interval = Interval.inclusive -100 100
|
||||
values = 1.up_to 10000 . to_vector . map (gen.step _ interval)
|
||||
values.all (v -> (v >= -100) && (v <= 100)) . should_be_true
|
||||
|
19
test/Tests/src/Data/Noise_Spec.enso
Normal file
19
test/Tests/src/Data/Noise_Spec.enso
Normal file
@ -0,0 +1,19 @@
|
||||
from Base import all
|
||||
|
||||
import Test
|
||||
|
||||
type My_Generator
|
||||
My_Generator.step _ _ = 1
|
||||
|
||||
spec = describe "Noise" <|
|
||||
it "should be able to be called on numbers" <|
|
||||
result = 1.noise
|
||||
result-result . should_equal 0
|
||||
it "should allow the user to specify a generator" <|
|
||||
result = 1.noise (gen=My_Generator)
|
||||
result-result . should_equal 0
|
||||
it "should allow the user to specify the interval" <|
|
||||
interval = Interval.inclusive -250 250
|
||||
values = 1.up_to 10000 . to_vector . map (_.noise interval)
|
||||
values.all (v -> (v >= -250) && (v <= 250)) . should_be_true
|
||||
|
@ -9,14 +9,15 @@ spec =
|
||||
eps = 0.000001
|
||||
almost_max_long = 9223372036854775806
|
||||
almost_max_long_times_three = 27670116110564327418
|
||||
almost_max_long_times_three_plus_1 = 27670116110564327419
|
||||
almost_max_long_times_three_decimal = 27670116110564327418.8
|
||||
hundred_factorial = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
|
||||
describe "Integers" <|
|
||||
it "should be of unbound size when multiplied" <|
|
||||
1.up_to 101 . fold 1 (*) . should_equal hundred_factorial
|
||||
it "should be of unbound size when added" <|
|
||||
(almost_max_long + almost_max_long + almost_max_long).should_equal almost_max_long_times_three
|
||||
it "should be of unbound size when subtracted" <|
|
||||
(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 subtracted" <| (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.up_to 101 . fold 1 (*)).div 3*almost_max_long).should_equal expected
|
||||
@ -70,3 +71,14 @@ spec =
|
||||
(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
|
||||
it "should allow calculating the floor value" <|
|
||||
1.2314.floor . should_equal 1
|
||||
1.floor . should_equal 1
|
||||
almost_max_long_times_three_decimal.floor.to_decimal . should_equal almost_max_long_times_three.to_decimal
|
||||
almost_max_long_times_three.floor . should_equal almost_max_long_times_three
|
||||
it "should allow calculating the ceil value" <|
|
||||
1.2314.ceil . should_equal 2
|
||||
1.ceil . should_equal 1
|
||||
almost_max_long_times_three_decimal.ceil.to_decimal . should_equal almost_max_long_times_three_plus_1.to_decimal
|
||||
almost_max_long_times_three_plus_1.ceil . should_equal almost_max_long_times_three_plus_1
|
||||
|
||||
|
@ -7,9 +7,12 @@ import Tests.Semantic.Java_Interop_Spec
|
||||
import Tests.Semantic.Meta_Spec
|
||||
import Tests.Semantic.Names_Spec
|
||||
|
||||
import Tests.Data.Interval_Spec
|
||||
import Tests.Data.Json_Spec
|
||||
import Tests.Data.List_Spec
|
||||
import Tests.Data.Map_Spec
|
||||
import Tests.Data.Noise.Generator_Spec
|
||||
import Tests.Data.Noise_Spec
|
||||
import Tests.Data.Numbers_Spec
|
||||
import Tests.Data.Range_Spec
|
||||
import Tests.Data.Text_Spec
|
||||
@ -27,15 +30,18 @@ main = Test.Suite.runMain <|
|
||||
Deep_Export_Spec.spec
|
||||
Error_Spec.spec
|
||||
File_Spec.spec
|
||||
Generator_Spec.spec
|
||||
Header_Spec.spec
|
||||
Http_Spec.spec
|
||||
Import_Loop_Spec.spec
|
||||
Interval_Spec.spec
|
||||
Java_Interop_Spec.spec
|
||||
Json_Spec.spec
|
||||
List_Spec.spec
|
||||
Map_Spec.spec
|
||||
Meta_Spec.spec
|
||||
Names_Spec.spec
|
||||
Noise_Spec.spec
|
||||
Numbers_Spec.spec
|
||||
Process_Spec.spec
|
||||
Range_Spec.spec
|
||||
|
@ -22,3 +22,4 @@ spec = describe "Meta-Value Manipulation" <|
|
||||
it "should correctly return representations of different classes of objects" <|
|
||||
Meta.meta 1 . should equal (Meta.Primitive 1)
|
||||
Meta.meta "foo" . should equal (Meta.Primitive "foo")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user