No more trying to force truncation of int division
This commit is contained in:
@@ -5,17 +5,17 @@ import haxe.ds.Either;
|
||||
/**
|
||||
Arithmetic operands
|
||||
**/
|
||||
abstract Operand(Either<String, Either<Int, Float>>) from Either<String, Either<Int, Float>> to Either<String, Either<Int, Float>> {
|
||||
abstract Operand(Either<String, Float>) from Either<String, Float> to Either<String, Float> {
|
||||
@:from inline static function fromString(s:String):Operand {
|
||||
return Left(s);
|
||||
}
|
||||
|
||||
@:from inline static function fromInt(f:Int):Operand {
|
||||
return Right(Left(f));
|
||||
@:from inline static function fromInt(i:Int):Operand {
|
||||
return Right(0.0 + i);
|
||||
}
|
||||
|
||||
@:from inline static function fromFloat(f:Float):Operand {
|
||||
return Right(Right(f));
|
||||
return Right(f);
|
||||
}
|
||||
|
||||
// Doing this one implicitly just wasn't working in conjunction with Lambda.fold
|
||||
@@ -23,8 +23,7 @@ abstract Operand(Either<String, Either<Int, Float>>) from Either<String, Either<
|
||||
/* @:from */
|
||||
public inline static function fromDynamic(d:Dynamic):Operand {
|
||||
return switch (Type.typeof(d)) {
|
||||
case TInt: Right(Left(d));
|
||||
case TFloat: Right(Right(d));
|
||||
case TInt | TFloat: Right(d);
|
||||
default:
|
||||
if (Std.isOfType(d, String)) {
|
||||
Left(d);
|
||||
@@ -34,7 +33,7 @@ abstract Operand(Either<String, Either<Int, Float>>) from Either<String, Either<
|
||||
else if (Std.isOfType(d, Either)) {
|
||||
d;
|
||||
} else {
|
||||
throw '$d cannot be Operand';
|
||||
throw '$d cannot be converted to Operand';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -48,16 +47,14 @@ abstract Operand(Either<String, Either<Int, Float>>) from Either<String, Either<
|
||||
|
||||
@:to public inline function toFloat():Null<Float> {
|
||||
return switch (this) {
|
||||
case Right(Right(f)): f;
|
||||
case Right(Left(i)): i;
|
||||
case Right(f): f;
|
||||
default: null;
|
||||
};
|
||||
}
|
||||
|
||||
@:to public inline function toInt():Null<Int> {
|
||||
return switch (this) {
|
||||
case Right(Left(i)): i;
|
||||
case Right(Right(f)): Math.floor(f);
|
||||
case Right(f): Math.floor(f);
|
||||
default: null;
|
||||
};
|
||||
}
|
||||
@@ -69,8 +66,7 @@ abstract Operand(Either<String, Either<Int, Float>>) from Either<String, Either<
|
||||
return if (Std.isOfType(o, Either)) {
|
||||
var o:Operand = cast o;
|
||||
switch (o) {
|
||||
case Right(Left(i)): i;
|
||||
case Right(Right(f)): f;
|
||||
case Right(f): f;
|
||||
case Left(str): str;
|
||||
};
|
||||
} else {
|
||||
|
@@ -8,65 +8,46 @@ import haxe.ds.Either;
|
||||
class Prelude {
|
||||
// Kiss arithmetic will incur overhead because of these switch statements, but the results will not be platform-dependent
|
||||
public static function add(a:Operand, b:Operand):Operand {
|
||||
return switch (a) {
|
||||
case Left(str):
|
||||
var firstStr = if (b.toString() != null) {
|
||||
b.toString();
|
||||
} else {
|
||||
throw 'cannot add string $str and float ${b.toFloat()}';
|
||||
};
|
||||
Left(firstStr + str);
|
||||
case Right(Left(i)):
|
||||
switch (b) {
|
||||
case Right(Right(f)):
|
||||
add(b, a);
|
||||
case Right(Left(bI)):
|
||||
Right(Left(i + bI));
|
||||
case Left(s): throw 'cannot add int $i and string $s';
|
||||
}
|
||||
case Right(Right(f)):
|
||||
Right(Right(f + if (b.toFloat() != null) b.toFloat() else throw 'cannot add float $f and string ${b.toString()}'));
|
||||
return switch ([a, b]) {
|
||||
case [Left(str), Left(str2)]:
|
||||
Left(str2 + str);
|
||||
case [Right(f), Right(f2)]:
|
||||
Right(f + f2);
|
||||
default:
|
||||
throw 'cannot add mismatched types ${Operand.toDynamic(a)} and ${Operand.toDynamic(b)}';
|
||||
};
|
||||
}
|
||||
|
||||
public static function subtract(val:Operand, from:Operand):Operand {
|
||||
return switch ([from, val]) {
|
||||
case [Right(Left(from)), Right(Left(val))]:
|
||||
Right(Left(from - val));
|
||||
case [Right(_), Right(_)]:
|
||||
Right(Right(from.toFloat() - val.toFloat()));
|
||||
case [Right(from), Right(val)]:
|
||||
Right(from - val);
|
||||
default:
|
||||
throw 'cannot subtract $val from $from';
|
||||
throw 'cannot subtract ${Operand.toDynamic(val)} from ${Operand.toDynamic(from)}';
|
||||
}
|
||||
}
|
||||
|
||||
public static function multiply(a:Operand, b:Operand):Operand {
|
||||
return switch ([a, b]) {
|
||||
case [Right(Right(f)), Right(Left(_)) | Right(Right(_))]:
|
||||
Right(Right(f * b.toFloat()));
|
||||
case [Right(Left(i)), Right(Right(_))]:
|
||||
multiply(b, a);
|
||||
case [Right(Left(i)), Right(Left(bI))]:
|
||||
Right(Left(i * bI));
|
||||
case [Right(f), Right(f2)]:
|
||||
Right(f * f2);
|
||||
case [Left(a), Left(b)]:
|
||||
throw 'cannot multiply strings "$a" and "$b"';
|
||||
case [Right(Left(i)), Left(s)] | [Left(s), Right(Left(i))]:
|
||||
case [Right(i), Left(s)] | [Left(s), Right(i)] if (i % 1 == 0):
|
||||
var result = "";
|
||||
for (_ in 0...i) {
|
||||
for (_ in 0...Math.floor(i)) {
|
||||
result += s;
|
||||
}
|
||||
Left(result);
|
||||
default:
|
||||
throw 'cannot multiply $a and $b';
|
||||
throw 'cannot multiply ${Operand.toDynamic(a)} and ${Operand.toDynamic(b)}';
|
||||
};
|
||||
}
|
||||
|
||||
public static function divide(bottom:Operand, top:Operand):Operand {
|
||||
return switch ([top, bottom]) {
|
||||
case [Right(Left(top)), Right(Left(bottom))]:
|
||||
Math.floor(top / bottom);
|
||||
case [Right(_), Right(_)]:
|
||||
top.toFloat() / bottom.toFloat();
|
||||
case [Right(f), Right(f2)]:
|
||||
Right(f / f2);
|
||||
default:
|
||||
throw 'cannot divide $top by $bottom';
|
||||
};
|
||||
@@ -97,7 +78,7 @@ class Prelude {
|
||||
}
|
||||
|
||||
public static function areEqual(a:Operand, b:Operand):Operand {
|
||||
return if (Operand.toDynamic(a) == Operand.toDynamic(b)) a else Right(Right(Math.NaN));
|
||||
return if (Operand.toDynamic(a) == Operand.toDynamic(b)) a else Right(Math.NaN);
|
||||
}
|
||||
|
||||
public static function groups<T>(a:Array<T>, size, keepRemainder = false) {
|
||||
|
@@ -63,8 +63,7 @@ class BasicTestCase extends Test {
|
||||
}
|
||||
|
||||
function testVariadicDivide() {
|
||||
Assert.equals(0, BasicTestCase.myQuotientInt);
|
||||
Assert.equals(0.5, BasicTestCase.myQuotientFloat);
|
||||
Assert.equals(0.5, BasicTestCase.myQuotient);
|
||||
}
|
||||
|
||||
function testMod() {
|
||||
|
@@ -31,9 +31,8 @@
|
||||
|
||||
(defvar myProduct (* 2 5 6))
|
||||
|
||||
(defvar myQuotientInt (/ 6 3 2 2))
|
||||
|
||||
(defvar myQuotientFloat (/ 6 3 2 2.0))
|
||||
// All math operations return floats, none truncate by default
|
||||
(defvar myQuotient (/ 6 3 2 2))
|
||||
|
||||
(defvar myRemainder (% 10 6))
|
||||
|
||||
|
Reference in New Issue
Block a user