From ac9648bb257f28d146bc2ba74b6520f3226ebd9f Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 7 Jul 2022 09:26:45 +0300 Subject: [PATCH 001/134] Add BigInteger type --- std/haxe/math/bigint/BigInt.hx | 328 +++++++ std/haxe/math/bigint/BigIntArithmetic.hx | 763 ++++++++++++++++ std/haxe/math/bigint/BigIntExceptions.hx | 30 + std/haxe/math/bigint/BigIntHelper.hx | 127 +++ std/haxe/math/bigint/BigIntTools.hx | 83 ++ std/haxe/math/bigint/BigInt_.hx | 463 ++++++++++ std/haxe/math/bigint/MultiwordArithmetic.hx | 960 ++++++++++++++++++++ std/haxe/math/bigint/MutableBigInt.hx | 438 +++++++++ std/haxe/math/bigint/MutableBigInt_.hx | 478 ++++++++++ 9 files changed, 3670 insertions(+) create mode 100644 std/haxe/math/bigint/BigInt.hx create mode 100644 std/haxe/math/bigint/BigIntArithmetic.hx create mode 100644 std/haxe/math/bigint/BigIntExceptions.hx create mode 100644 std/haxe/math/bigint/BigIntHelper.hx create mode 100644 std/haxe/math/bigint/BigIntTools.hx create mode 100644 std/haxe/math/bigint/BigInt_.hx create mode 100644 std/haxe/math/bigint/MultiwordArithmetic.hx create mode 100644 std/haxe/math/bigint/MutableBigInt.hx create mode 100644 std/haxe/math/bigint/MutableBigInt_.hx diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx new file mode 100644 index 00000000000..fa53ea57b20 --- /dev/null +++ b/std/haxe/math/bigint/BigInt.hx @@ -0,0 +1,328 @@ +/* + * Copyright (C)2005-2022 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +import haxe.ds.Vector; +import haxe.io.Bytes; + +@:allow(haxe.math.bigint) +abstract BigInt(BigInt_) +{ + //----------------------------------------------------------------------- + // Public constants + //----------------------------------------------------------------------- + + public static var ZERO(default, null) : BigInt = new BigInt(BigInt_.fromInt(0)); + public static var ONE(default, null) : BigInt = new BigInt(BigInt_.fromInt(1)); + public static var NEGATIVE_ONE(default, null) : BigInt = new BigInt(BigInt_.fromInt(-1)); + + //----------------------------------------------------------------------- + // Public interface + //----------------------------------------------------------------------- + + public inline function sign() : Int + { + return BigInt_.sign1(this); + } + + public inline function isZero() : Bool + { + return BigInt_.isZero1(this); + } + + public inline function isNegative() : Bool + { + return BigInt_.isNegative1(this); + } + + public inline function toString() : String + { + return BigInt_.toString1(this); + } + + public inline function toHex() : String + { + return BigInt_.toHex1(this); + } + + public inline function toBytes() : Bytes + { + return BigInt_.toBytes1(this); + } + + public inline function toInts(output : Vector) : Int + { + return BigInt_.toInts1(this, output); + } + + public static inline function fromInt(value : Int) : BigInt + { + return new BigInt(BigInt_.fromInt(value)); + } + + public static inline function fromString(value : String) : BigInt + { + return new BigInt(BigInt_.fromString(value)); + } + + public static inline function fromHex(value : String) : BigInt + { + return fromHexSigned(value); + } + + public static inline function fromHexSigned(value : String) : BigInt + { + return new BigInt(BigInt_.fromHexSigned(value)); + } + + public static inline function fromHexUnsigned(value : String) : BigInt + { + return new BigInt(BigInt_.fromHexUnsigned(value)); + } + + public static inline function fromUnsignedInts(value : Vector, length : Int = 0) : BigInt + { + return new BigInt(BigInt_.fromUnsignedInts(value, length)); + } + + public inline function getBit(index : Int) : Int + { + return BigIntArithmetic.getBit(this, index); + } + + //----------------------------------------------------------------------- + // Operators + //----------------------------------------------------------------------- + + // The declaration order of the operations is significant in Haxe. + // Recommended order is: + // * BigInt Int + // * BigInt BigInt + // * BigInt MutableBigInt + + // Unary negation + @:op(-A) @:noCompletion public static inline function negate_(a : BigInt) : BigInt + { + return new BigInt(BigInt_.negate1(a)); + } + + // Binary equality + @:op(A == B) @:noCompletion public static inline function eqInt_(a : BigInt, b : Int) : Bool + { + return BigInt_.equals2Int(a, b); + } + @:op(A == B) @:noCompletion public static inline function eq_(a : BigInt, b : BigInt) : Bool + { + return BigInt_.equals2(a, b); + } + @:op(A == B) @:noCompletion public static inline function eqMutable_(a : BigInt, b : MutableBigInt) : Bool + { + return BigInt_.equals2(a, b); + } + + // Binary inequality + @:op(A != B) @:noCompletion public static inline function ineqInt_(a : BigInt, b : Int) : Bool + { + return !BigInt_.equals2Int(a, b); + } + @:op(A != B) @:noCompletion public static inline function ineq_(a : BigInt, b : BigInt) : Bool + { + return !BigInt_.equals2(a, b); + } + @:op(A != B) @:noCompletion public static inline function ineqMutable_(a : BigInt, b : MutableBigInt) : Bool + { + return !BigInt_.equals2(a, b); + } + + // Binary less than + @:op(A < B) @:noCompletion public static inline function ltInt_(a : BigInt, b : Int) : Bool + { + return BigIntArithmetic.compareInt(a, b) < 0; + } + @:op(A < B) @:noCompletion public static inline function lt_(a : BigInt, b : BigInt) : Bool + { + return BigIntArithmetic.compare(a, b) < 0; + } + @:op(A < B) @:noCompletion public static inline function ltMutable_(a : BigInt, b : MutableBigInt) : Bool + { + return BigIntArithmetic.compare(a, b) < 0; + } + + // Binary less than or equal + @:op(A <= B) @:noCompletion public static inline function lteInt_(a : BigInt, b : Int) : Bool + { + return BigIntArithmetic.compareInt(a, b) <= 0; + } + @:op(A <= B) @:noCompletion public static inline function lte_(a : BigInt, b : BigInt) : Bool + { + return BigIntArithmetic.compare(a, b) <= 0; + } + @:op(A <= B) @:noCompletion public static inline function lteMutable_(a : BigInt, b : MutableBigInt) : Bool + { + return BigIntArithmetic.compare(a, b) <= 0; + } + + // Binary greater than + @:op(A > B) @:noCompletion public static inline function gtInt_(a : BigInt, b : Int) : Bool + { + return BigIntArithmetic.compareInt(a, b) > 0; + } + @:op(A > B) @:noCompletion public static inline function gt_(a : BigInt, b : BigInt) : Bool + { + return BigIntArithmetic.compare(a, b) > 0; + } + @:op(A > B) @:noCompletion public static inline function gtMutable_(a : BigInt, b : MutableBigInt) : Bool + { + return BigIntArithmetic.compare(a, b) > 0; + } + + // Binary greater than or equal + @:op(A >= B) @:noCompletion public static inline function gteInt_(a : BigInt, b : Int) : Bool + { + return BigIntArithmetic.compareInt(a, b) >= 0; + } + @:op(A >= B) @:noCompletion public static inline function gte_(a : BigInt, b : BigInt) : Bool + { + return BigIntArithmetic.compare(a, b) >= 0; + } + @:op(A >= B) @:noCompletion public static inline function gteMutable_(a : BigInt, b : MutableBigInt) : Bool + { + return BigIntArithmetic.compare(a, b) >= 0; + } + + // Binary addition + @:op(A + B) @:noCompletion public static inline function addInt_(a : BigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.addInt2(a, b)); + } + @:op(A + B) @:noCompletion public static inline function add_(a : BigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.add2(a, b)); + } + @:op(A + B) @:noCompletion public static inline function addMutable_(a : BigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.add2(a, b)); + } + + // Binary subtraction + @:op(A - B) @:noCompletion public static inline function subInt_(a : BigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.subInt2(a, b)); + } + @:op(A - B) @:noCompletion public static inline function sub_(a : BigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.sub2(a, b)); + } + @:op(A - B) @:noCompletion public static inline function subMutable_(a : BigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.sub2(a, b)); + } + + // Binary multiplication + @:op(A * B) @:noCompletion public static inline function mulInt_(a : BigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.multiplyInt2(a, b)); + } + @:op(A * B) @:noCompletion public static inline function mul_(a : BigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.multiply2(a, b)); + } + @:op(A * B) @:noCompletion public static inline function mulMutable_(a : BigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.multiply2(a, b)); + } + + // Binary division + @:op(A / B) @:noCompletion public static inline function divInt_(a : BigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.divideInt2(a, b)); + } + @:op(A / B) @:noCompletion public static inline function div_(a : BigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.divide2(a, b)); + } + @:op(A / B) @:noCompletion public static inline function divMutable_(a : BigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.divide2(a, b)); + } + + // Binary modulus + @:op(A % B) @:noCompletion public static inline function modInt_(a : BigInt, b : Int) : Int + { + return BigInt_.modulusInt2(a, b); + } + @:op(A % B) @:noCompletion public static inline function mod_(a : BigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.modulus2(a, b)); + } + @:op(A % B) @:noCompletion public static inline function modMutable_(a : BigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.modulus2(a, b)); + } + + // Binary AND + @:op(A & B) @:noCompletion public static inline function andInt_(a : BigInt, b : Int) : Int + { + return BigIntArithmetic.bitwiseAndInt(a, b); + } + + // Binary shift left + @:op(A << B) @:noCompletion public static inline function asl_(a : BigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.arithmeticShiftLeft2(a, b)); + } + + // Binary shift right + @:op(A >> B) @:noCompletion public static inline function asr_(a : BigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.arithmeticShiftRight2(a, b)); + } + + //----------------------------------------------------------------------- + // Automatic conversions + //----------------------------------------------------------------------- + + @:from @:noCompletion public static inline function fromInt_(a : Int) : BigInt + { + return new BigInt(BigInt_.fromInt(a)); + } + + @:to @:noCompletion public inline function toBigInt_() : BigInt_ + { + return this; + } + + @:to @:noCompletion public inline function toMutableBigInt() : MutableBigInt + { + return new MutableBigInt(MutableBigInt_.fromBigInt(this)); + } + + //----------------------------------------------------------------------- + // Private implementation + //----------------------------------------------------------------------- + + @:noCompletion private inline function new(a : BigInt_) + { + this = a; + } +} diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx new file mode 100644 index 00000000000..b4b6fdfb086 --- /dev/null +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -0,0 +1,763 @@ +/* + * Copyright (C)2005-2022 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +import haxe.math.bigint.BigIntExceptions; +import haxe.math.bigint.BigIntHelper; +import haxe.ds.Vector; + +class BigIntArithmetic +{ + /** + Compare a big integer with an Int. + + Returns -1 if `a < b`; otherwise + returns 1 if `a > b`; otherwise + returns 0 (`a == b`). + **/ + public static function compareInt(a : BigInt_, b : Int) : Int + { + if (a.m_count > 1) + { + return (a.sign() << 1) + 1; + } + var x : Int = a.m_data.get(0); + var lt : Int = (x - b) ^ ((x ^ b) & ((x - b) ^ x)); // "Hacker's Delight" p. 23 + var gt : Int = (b - x) ^ ((x ^ b) & ((b - x) ^ b)); + return (lt >> 31) | (gt >>> 31); + } + + /** + Compare two big integers. + + Returns -1 if `a < b`; otherwise + returns 1 if `a > b`; otherwise + returns 0 (`a == b`). + **/ + public static function compare(a : BigInt_, b : BigInt_) : Int + { + if (a != b) + { + var c : Int = (a.sign() & 2) + (b.sign() & 1); + switch (c) + { + case 0: // a and b are positive + if (a.m_count > b.m_count) + { + return 1; + } + if (a.m_count < b.m_count) + { + return -1; + } + case 1: // a is positive, b is negative + return 1; + case 2: // a is negative, b is positive + return -1; + case 3: // a and b are negative + if (a.m_count > b.m_count) + { + return -1; + } + if (a.m_count < b.m_count) + { + return 1; + } + } + return MultiwordArithmetic.compareUnsigned(a.m_data, b.m_data, a.m_count); + } + return 0; + } + + /** + Perform the unary negation of big integer `operand` and put + the result into big integer `result`. + + Ok for `result` and `operand` to be the same object. + **/ + public static function negate(result : MutableBigInt_, operand : BigInt_) : Void + { + var c : Int = 1; + var x : Int = 0; + var z : Int = 0; + result.ensureCapacity(operand.m_count + 1, result == operand); // overflow may add a digit + for (i in 0 ... operand.m_count) + { + x = ~operand.m_data.get(i); + z = x + c; + result.m_data.set(i, z); + c = (x & ~z) >>> 31; // "Hacker's Delight" p. 38 + } + result.m_count = operand.m_count; + // detect overflow; intuitively, this can only occur for inputs of 2 ^ (32 * N - 1). + if ((~x & z) < 0) + { + result.m_data.set(result.m_count++, 0); + } + else + { + // Handle compacting; intuitively, this can only occur for inputs of -[2 ^ (32 * N - 1)]. + // TODO: good way to detect this specific scenario? + result.compact(); + } + } + + /** + Add big integer `operand2` to big integer `operand1` and put + the result into big integer `result`. + + Ok for `result`, `operand1`, and `operand2` to be the same object. + **/ + public static function add(result : MutableBigInt_, operand1 : BigInt_, operand2 : BigInt_) : Void + { + var c : Int = 0; + var x : Int = 0, y : Int = 0, z : Int = 0; + if (operand1.m_count == operand2.m_count) + { + result.ensureCapacity(operand1.m_count + 1, (result == operand1) || (result == operand2)); + for (i in 0 ... operand1.m_count) + { + x = operand1.m_data.get(i); + y = operand2.m_data.get(i); + z = x + y + c; + result.m_data.set(i, z); + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + } + result.m_count = operand1.m_count; + } + else + { + // longer operand is put into o1 + var o1 = (operand1.m_count > operand2.m_count) ? operand1 : operand2; + var o2 = (operand1.m_count > operand2.m_count) ? operand2 : operand1; + result.ensureCapacity(o1.m_count + 1, (result == operand1) || (result == operand2)); + var s : Int = o2.sign(); + for (i in 0 ... o2.m_count) + { + x = o1.m_data.get(i); + y = o2.m_data.get(i); + z = x + y + c; + result.m_data.set(i, z); + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + } + y = s; + for (i in o2.m_count ... o1.m_count) + { + x = o1.m_data.get(i); + z = x + y + c; + result.m_data.set(i, z); + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + } + result.m_count = o1.m_count; + } + var o : Int = (z ^ x) & (z ^ y); // "Hacker's Delight" p. 29 + if (o < 0) // overflow flag is in sign bit + { + result.m_data.set(result.m_count++, ~(z >> 31)); + } + else + { + result.compact(); // TODO: True that this will only ever eliminate at most one digit? Lighter way to detect? + } + } + + /** + Add integer `operand2` to big integer `operand1` and put the + result into big integer `result`. + + Ok for `result` and `operand1` to be the same object. + **/ + public static function addInt(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void + { + var c : Int = 0; + var x : Int; + var y : Int = operand2; + var z : Int; + + result.ensureCapacity(operand1.m_count + 1, result == operand1); + if (operand1.m_count > 1) + { + x = operand1.m_data.get(0); + z = x + y; + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + result.m_data.set(0, z); + y >>= 31; + for (i in 1 ... operand1.m_count - 1) + { + x = operand1.m_data.get(i); + z = x + y + c; + result.m_data.set(i, z); + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + } + } + x = operand1.m_data.get(operand1.m_count - 1); + z = x + y + c; + result.m_data.set(operand1.m_count - 1, z); + result.m_count = operand1.m_count; + var o : Int = (z ^ x) & (z ^ y); // "Hacker's Delight" p. 29 + if (o < 0) // overflow flag is in sign bit + { + result.m_data.set(result.m_count++, x >> 31); + } + else if (result.m_count > 1) + { + if (z == (result.m_data.get(result.m_count - 2) >> 31)) + { + --result.m_count; + } + } + } + + /** + Subtract big integer `operand2` from big integer `operand1` + and put the result into big integer `result`. + + Ok for `result`, `operand1`, and `operand2` to be the same object. + **/ + public static function subtract(result : MutableBigInt_, operand1 : BigInt_, operand2 : BigInt_) : Void + { + var c : Int = 0; + var x : Int = 0, y : Int = 0, z : Int = 0; + if (operand1.m_count == operand2.m_count) + { + result.ensureCapacity(operand1.m_count + 1, (result == operand1) || (result == operand2)); + for (i in 0 ... operand1.m_count) + { + x = operand1.m_data.get(i); + y = operand2.m_data.get(i); + z = x - y - c; + result.m_data.set(i, z); + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + } + result.m_count = operand1.m_count; + } + else if (operand1.m_count > operand2.m_count) + { + // operand1 is longer + result.ensureCapacity(operand1.m_count + 1, (result == operand1) || (result == operand2)); + var s : Int = operand2.sign(); + for (i in 0 ... operand2.m_count) + { + x = operand1.m_data.get(i); + y = operand2.m_data.get(i); + z = x - y - c; + result.m_data.set(i, z); + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + } + y = s; + for (i in operand2.m_count ... operand1.m_count) + { + x = operand1.m_data.get(i); + z = x - y - c; + result.m_data.set(i, z); + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + } + result.m_count = operand1.m_count; + } + else + { + // operand2 is longer + result.ensureCapacity(operand2.m_count + 1, (result == operand1) || (result == operand2)); + var s : Int = operand1.sign(); + for (i in 0 ... operand1.m_count) + { + x = operand1.m_data.get(i); + y = operand2.m_data.get(i); + z = x - y - c; + result.m_data.set(i, z); + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + } + x = s; + for (i in operand1.m_count ... operand2.m_count) + { + y = operand2.m_data.get(i); + z = x - y - c; + result.m_data.set(i, z); + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + } + result.m_count = operand2.m_count; + } + var o : Int = (x ^ y) & (z ^ x); // "Hacker's Delight" p. 29 + if (o < 0) // overflow flag is in sign bit + { + result.m_data.set(result.m_count++, ~(z >> 31)); + } + else + { + result.compact(); // TODO: True that this will only ever eliminate at most one digit? Lighter way to detect? + } + } + + /** + Subtract integer `operand2` from big integer `operand1` and + put the result into big integer `result`. + + Ok for `result` and `operand1` to be the same object. + **/ + public static function subtractInt(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void + { + var c : Int = 0; + var x : Int; + var y : Int = operand2; + var z : Int; + + result.ensureCapacity(operand1.m_count + 1, result == operand1); + if (operand1.m_count > 1) + { + x = operand1.m_data.get(0); + z = x - y; + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + result.m_data.set(0, z); + y >>= 31; + for (i in 1 ... operand1.m_count - 1) + { + x = operand1.m_data.get(i); + z = x - y - c; + result.m_data.set(i, z); + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + } + } + x = operand1.m_data.get(operand1.m_count - 1); + z = x - y - c; + result.m_data.set(operand1.m_count - 1, z); + result.m_count = operand1.m_count; + var o : Int = (x ^ y) & (z ^ x); // "Hacker's Delight" p. 29 + if (o < 0) // overflow flag is in sign bit + { + result.m_data.set(result.m_count++, x >> 31); + } + else if (result.m_count > 1) + { + if (z == (result.m_data.get(result.m_count - 2) >> 31)) + { + --result.m_count; + } + } + } + + /** + Multiply big integer `operand1` by integer `operand2` and put + the result into `result`. + + `result` may not refer the same object as either `operand1` + or `operand2`; however, `operand1` and `operand2` may be the + same object. + **/ + public static function multiplyInt(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void + { + // TODO: Optimize. + multiply(result, operand1, BigInt_.fromInt(operand2)); + } + + /** + Multiply big integer `operand1` by big integer `operand2` and + put the result into `result`. + + `result` may not refer the same object as either `operand1` + or `operand2`; however, `operand1` and `operand2` may be the + same object. + **/ + public static function multiply(result : MutableBigInt_, operand1 : BigInt_, operand2 : BigInt_) : Void + { + // Implements Figure 8-1 (p. 172) from "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. + + if ((operand1 == result) || (operand2 == result)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + + if (operand1.isZero() || operand2.isZero()) + { + result.setFromInt(0); + return; + } + + var resultSize : Int = operand1.m_count + operand2.m_count; + result.ensureCapacity(resultSize, false); // always overwrite result + for (i in 0 ... resultSize) + { + result.m_data.set(i, 0); + } + result.m_count = resultSize; + + var b : Int, k : Int, t : Int; + var u : Int, v : Int, w : Int; + var m : Int = operand1.m_count << 1; + var n : Int = operand2.m_count << 1; + + for (j in 0 ... n) + { + v = operand2.getShort(j); + k = 0; + for (i in 0 ... m) + { + u = operand1.getShort(i); + w = result.getShort(i + j); + t = u * v + w + k; + result.setShort(i + j, t); + k = t >>> 16; + } + result.setShort(j + m, k); + } + + // Now result has the unsigned product. Correct by + // subtracting v * 2 ^ (16m) if u < 0, and + // subtracting u * 2 ^ (16n) if v < 0. + // TODO: Do these as 32-bit operations. + if (operand1.isNegative()) + { + b = 0; + for (j in 0 ... n) + { + w = result.getShort(j + m); + v = operand2.getShort(j); + t = w - v - b; + result.setShort(j + m, t); + b = t >>> 31; + } + } + if (operand2.isNegative()) + { + b = 0; + for (i in 0 ... m) + { + w = result.getShort(i + n); + u = operand1.getShort(i); + t = w - u - b; + result.setShort(i + n, t); + b = t >>> 31; + } + } + + result.compact(); + } + + /** + Divide the big integer `dividend` by the integer `divisor`. + The quotient of the division is put into `quotientOut`; + the remainder is the return value. + + `quotientOut` may refer to `dividend`. + + `work`, if supplied, must not refer to any of the inputs. + **/ + public static function divideInt(dividend : BigInt_, divisor : Int, quotientOut : MutableBigInt_, work : MutableBigInt_ = null) : Int + { + // TODO: Consider optimizing this case. + var remainder = new MutableBigInt_(); + var divisorBi = BigInt_.fromInt(divisor); + divide(dividend, divisorBi, quotientOut, remainder, work); + return remainder.m_data.get(0); + } + + /** + Divide the big integer `dividend` by the big integer `divisor`. + The quotient of the division is put into `quotientOut`; + the remainder is put into `remainderOut`. + + `remainderOut` may be `null` if the remainder value is not + needed. + + `dividend` and `divisor` may refer to the same object. + + `quotientOut` and `remainderOut` must not refer to the same + object; but either may refer to the inputs. + + `work`, if supplied, must not refer to any of the inputs. + **/ + public static function divide(dividend : BigInt_, divisor : BigInt_, quotientOut : MutableBigInt_, remainderOut : MutableBigInt_, work : MutableBigInt_ = null) : Void + { + var c : Int = (dividend.sign() & 2) + (divisor.sign() & 1); + switch (c) + { + case 0: // dividend positive, divisor positive + multiwordUnsignedDivide(dividend, divisor, quotientOut, remainderOut, work); + case 1: // dividend positive, divisor negative + negate(quotientOut, divisor); + multiwordUnsignedDivide(dividend, quotientOut, quotientOut, remainderOut, work); + negate(quotientOut, quotientOut); + case 2: // dividend negative, divisor positive + negate(quotientOut, dividend); + multiwordUnsignedDivide(quotientOut, divisor, quotientOut, remainderOut, work); + negate(quotientOut, quotientOut); + if (remainderOut != null) + { + negate(remainderOut, remainderOut); + } + case 3: // dividend negative, divisor negative + if (remainderOut == null) + { + // TODO: use work buffer rather than creating an object here + remainderOut = new MutableBigInt_(); + } + negate(quotientOut, dividend); + negate(remainderOut, divisor); + multiwordUnsignedDivide(quotientOut, remainderOut, quotientOut, remainderOut, work); + negate(remainderOut, remainderOut); + } + } + + /* + Unsigned division; inputs must not be negative. + + `remainderOut` may be `null` if the remainder value is not + needed. + + `dividend` and `divisor` may refer to the same object. + + `quotientOut` and `remainderOut` must not refer to the same + object; but either may refer to the inputs. + + `work`, if supplied, must not refer to any of the inputs. + */ + private static function multiwordUnsignedDivide(dividend : BigInt_, divisor : BigInt_, quotientOut : MutableBigInt_, remainderOut : MutableBigInt_, work : MutableBigInt_ = null) : Void + { + if ((quotientOut == null) || (dividend == null) || (divisor == null)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if ((work == dividend) || (work == divisor) || (work == quotientOut)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + + var dividendInts : Int = dividend.getUnsignedDigitCount(); + var divisorInts : Int = divisor.getUnsignedDigitCount(); + + var quotientLength : Int = MultiwordArithmetic.getDivisionQuotientLengthUnsigned(dividendInts, divisorInts); + + if (remainderOut != null) + { + if (work == remainderOut) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + remainderOut.ensureCapacity(divisor.m_count, (remainderOut == dividend) || (remainderOut == divisor)); + } + quotientOut.ensureCapacity(quotientLength + 1, (quotientOut == dividend) || (quotientOut == divisor)); // +1 in case we need leading 0 digit + + if (work == null) + { + work = new MutableBigInt_(); + } + work.ensureCapacity(dividendInts + divisorInts + 1, false); + + MultiwordArithmetic.divideUnsigned(dividend.m_data, dividendInts, divisor.m_data, divisorInts, quotientOut.m_data, (remainderOut != null) ? remainderOut.m_data : null, work.m_data); + + quotientOut.m_count = quotientLength; + if (quotientOut.isNegative()) + { + quotientOut.m_data.set(quotientOut.m_count++, 0); + } + else + { + quotientOut.compact(); + } + + if (remainderOut != null) + { + remainderOut.m_count = divisorInts; + if (remainderOut.isNegative()) + { + remainderOut.m_data.set(remainderOut.m_count++, 0); + } + else + { + remainderOut.compact(); + } + } + } + + /** + Shift big integer `operand1` to the left by `operand2` bits + and put the result into big integer `result`. + + Ok for `result` and `operand1` to be the same object. + **/ + public static function arithmeticShiftLeft(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void + { + if (operand2 < 0) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + + if ((operand2 == 0) || operand1.isZero()) + { + result.copyFrom(operand1); + return; + } + + result.ensureCapacity(operand1.m_count + ((operand2 + 31) >> 5), result == operand1); + + var whole : Int = operand2 >> 5; // whole digits portion + var n : Int = operand2 & 0x1f; // sub digit poortion + if (n > 0) + { + asl32(result.m_data, whole, operand1.m_data, operand1.m_count, n); + result.m_count = operand1.m_count + whole + 1; + result.compact(); + } + else if (whole > 0) + { + for (i in 0 ... operand1.m_count) + { + result.m_data.set(operand1.m_count - i - 1 + whole, operand1.m_data.get(operand1.m_count - i - 1)); + } + result.m_count = operand1.m_count + whole; + } + for (i in 0 ... whole) + { + result.m_data.set(i, 0); + } + } + + /** + Shift big integer `operand1` to the right by `operand2` bits + and put the result into big integer `result`. + + Ok for `result` and `operand1` to be the same object. + **/ + public static function arithmeticShiftRight(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void + { + if (operand2 < 0) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + + if ((operand2 == 0) || operand1.isZero()) + { + result.copyFrom(operand1); + return; + } + + result.ensureCapacity(operand1.m_count, result == operand1); + + var whole : Int = operand2 >> 5; // whole digits portion + var n : Int = operand2 & 0x1f; // sub digit poortion + if (whole >= operand1.m_count) + { + result.m_data.set(0, operand1.sign()); + result.m_count = 1; + } + else if (n > 0) + { + MultiwordArithmetic._asr32(result.m_data, operand1.m_data, operand1.m_count, whole, n); + result.m_count = operand1.m_count - whole; + result.compact(); + } + else if (whole > 0) + { + for (i in 0 ... operand1.m_count - whole) + { + result.m_data.set(i, operand1.m_data.get(i + whole)); + } + result.m_count = operand1.m_count - whole; + } + } + + /** + Returns the value, 0 or 1, of the bit at 2^`index` place. + **/ + public static inline function getBit(value : BigInt_, index : Int) : Int + { + return MultiwordArithmetic.getBitSigned(value.m_data, value.m_count, index); + } + + /** + Returns the bitwise AND of `operand1` with `operand2`. + **/ + public static inline function bitwiseAndInt(operand1 : BigInt_, operand2 : Int) : Int + { + return operand1.m_data.get(0) & operand2; + } + + /** + Returns `floor(log2(input))`. + **/ + public static function floorLog2(input : BigInt_) : Int + { + return (input.m_count << 5) - BigIntHelper.nlz(input.m_data.get(input.m_count - 1)); + } + + //----------------------------------------------------------------------- + // Private helpers + //----------------------------------------------------------------------- + + // assumes 0 < shift < 32 + // ok if output == input + private static inline function asl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int) : Void + { + var x : Int = input.get(inputSize - 1) >> 31; // sign extend + var r : Int = 32 - shift; + var y : Int; + while (inputSize > 0) + { + y = input[inputSize - 1]; + x = (x << shift) | (y >>> r); + output.set(inputSize + outputOffset, x); + x = y; + --inputSize; + } + output.set(outputOffset, x << shift); + } + + // assumes 0 < shift < 32 + // ok if output == input + private static inline function lsl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int) : Void + { + var x : Int = 0; + var r : Int = 32 - shift; + var y : Int; + while (inputSize > 0) + { + y = input[inputSize - 1]; + x = (x << shift) | (y >>> r); + output.set(inputSize + outputOffset, x); + x = y; + --inputSize; + } + output.set(outputOffset, x << shift); + } + + // assumes 0 < shift < 32 + // ok if output == input + private static inline function lsr32(output : Vector, input : Vector, inputSize : Int, inputOffset : Int, shift : Int) : Void + { + var r : Int = 32 - shift; + var i : Int = 0; + while (i < inputSize - 1) + { + output.set(i, (input.get(inputOffset + i) >>> shift) | (input.get(inputOffset + i + 1) << r)); + ++i; + } + output.set(i, input.get(inputOffset + i) >>> shift); + } + + private static inline function copy(output : Vector, outputOffset : Int, input : Vector, inputOffset : Int, length : Int) : Void + { + for (i in 0 ... length) + { + output.set(outputOffset + i, input.get(inputOffset + i)); + } + } +} diff --git a/std/haxe/math/bigint/BigIntExceptions.hx b/std/haxe/math/bigint/BigIntExceptions.hx new file mode 100644 index 00000000000..e3d3f883198 --- /dev/null +++ b/std/haxe/math/bigint/BigIntExceptions.hx @@ -0,0 +1,30 @@ +/* + * Copyright (C)2005-2022 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +class BigIntExceptions +{ + public static inline var INVALID_ARGUMENT = "invalid argument"; + public static inline var BUFFER_TOO_SMALL = "buffer too small"; + public static inline var DIVISION_BY_ZERO = "division by zero"; +} \ No newline at end of file diff --git a/std/haxe/math/bigint/BigIntHelper.hx b/std/haxe/math/bigint/BigIntHelper.hx new file mode 100644 index 00000000000..ff99e469ebf --- /dev/null +++ b/std/haxe/math/bigint/BigIntHelper.hx @@ -0,0 +1,127 @@ +/* + * Copyright (C)2005-2022 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +class BigIntHelper +{ + + /** + "Numbler of leading zeros" - return the number of leading + 0-value bits in the binary representation of `x`. + **/ + public static function nlz(x : Int) : Int + { + // From "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. Figure 5-15, p. 102. + var y : Int, m : Int, n : Int; + + y = -(x >>> 16); + m = (y >> 16) & 16; + n = 16 - m; + x = x >>> m; + + y = x - 0x100; + m = (y >> 16) & 8; + n = n + m; + x = x << m; + + y = x - 0x1000; + m = (y >> 16) & 4; + n = n + m; + x = x << m; + + y = x - 0x4000; + m = (y >> 16) & 2; + n = n + m; + x = x << m; + + y = x >> 14; + m = y & (~y >> 1); + return n + 2 - m; + } + + + /** + "Ceiling power of two" -- round up to the least power of two + greater than or equal to input `x`, which is interpreted as + unsigned. + **/ + public static function clp2(x : Int) : Int + { + // From "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. Figure 3-3, p. 62. + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >> 16); + return x + 1; + } + + /** + Unsigned greater than comparison. + + Returns `true` if `a > b` when both `a` and `b` are + interpreted as unsigned integers; `false` otherwise. + **/ + public static inline function u32gtu32(a : Int, b : Int) : Bool + { + return (a ^ -2147483648) > (b ^ -2147483648); // unsigned comparison, see "Hacker's Delight" p. 25. + } + + + /** + Integer division of unsigned 32-bit integer by unsigned 16-bit integer. + + Result is undefined when `divisor` <= 0 or `divisor` >= 2^16. + **/ + public static function u32divu16(dividend : Int, divisor : Int) : Int + { + /* + Complicated because Haxe's division is always performed as + floating-point. Here we rely on the ability to exactly represent + a 31-bit integer as a Float. In other words, 64-bit floating + point is required. + + TODO: Implement a method without this restriction. + TODO: Consider C++-specific optimization here. + */ + // From "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. Section 9-3, p. 192. + var t : Int = divisor >> 31; + var nprime : Int = dividend & ~t; + var q : Int = Std.int((nprime >>> 1) / divisor) << 1; + var r : Int = dividend - q * divisor; + var c : Int = u32geu32(r, divisor) ? 1 : 0; + return q + c; + } + + /** + Unsigned greater than or equal comparison. + Returns `true` if `a >= b` when both `a` and `b` are + interpreted as unsigned integers; `false` otherwise. + **/ + public static inline function u32geu32(a : Int, b : Int) : Bool + { + return (a ^ -2147483648) >= (b ^ -2147483648); // unsigned comparison, see "Hacker's Delight" p. 25. + } + +} diff --git a/std/haxe/math/bigint/BigIntTools.hx b/std/haxe/math/bigint/BigIntTools.hx new file mode 100644 index 00000000000..995d07d987b --- /dev/null +++ b/std/haxe/math/bigint/BigIntTools.hx @@ -0,0 +1,83 @@ +/* + * Copyright (C)2005-2022 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +import haxe.math.bigint.BigIntExceptions; + +class BigIntTools +{ + public static inline function isNull(value : BigInt) : Bool + { + var a : BigInt_ = value; + return a == null; + } + + public static inline function isBigInt(value : Dynamic) : Bool + { + return Std.isOfType(value, BigInt_); + } + + public static inline function castFrom(value : Dynamic) : BigInt + { + return new BigInt(Std.downcast(value, BigInt_)); + } + + public static function parseValueUnsigned(value : Dynamic) : BigInt + { + var bi : BigInt; + if (Std.isOfType(value, String)) + { + bi = parseStringUnsigned(cast(value, String)); + } + else if (isBigInt(value)) + { + var t = new MutableBigInt_(); + t.copyFrom(castFrom(value)); + return new BigInt(t); + } + else if (Std.isOfType(value, Int)) + { + bi = BigInt.fromInt(cast(value, Int)); + } + else + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + return bi; + } + + private static function parseStringUnsigned(value : String) : BigInt + { + var result = new MutableBigInt_(); + if (StringTools.startsWith(value, "0x")) + { + result.setFromHexUnsigned(value.substr(2)); + } + else + { + result.setFromString(value); + } + var result2 : MutableBigInt = result; + return result2; + } +} diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx new file mode 100644 index 00000000000..4df03b5f0ad --- /dev/null +++ b/std/haxe/math/bigint/BigInt_.hx @@ -0,0 +1,463 @@ +/* + * Copyright (C)2005-2022 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +import haxe.ds.Vector; +import haxe.io.Bytes; + +@:allow(haxe.math.bigint) +class BigInt_ +{ + //----------------------------------------------------------------------- + // Public interface + //----------------------------------------------------------------------- + + /** + Returns `true` if this big integer is equivalent to 0, otherwise returns `false`. + **/ + public inline function isZero() : Bool + { + return (m_count == 1) && (m_data.get(0) == 0); + } + + /** + Returns `true` if this big integer is less than 0, otherwise returns `false`. + **/ + public inline function isNegative() : Bool + { + return m_data.get(m_count - 1) < 0; + } + + /** + Retrieve the sign value of this big integer; 0 if positive, -1 if negative. + **/ + public inline function sign() : Int + { + return m_data.get(m_count - 1) >> 31; + } + + /** + Test for numeric equality between this big integer and another. + **/ + public function equals(other : BigInt_) : Bool + { + if (this.m_count != other.m_count) + { + return false; + } + for (n in 0 ... this.m_count) + { + if (this.m_data.get(n) != other.m_data.get(n)) + { + return false; + } + } + return true; + } + + /** + Test for numeric equality between this big integer and another. + **/ + public function equalsInt(other : Int) : Bool + { + if (this.m_count != 1) + { + return false; + } + return m_data.get(0) == other; + } + + /** + Get the value in decimal form. + **/ + public inline function toString() : String + { + return MultiwordArithmetic.toDecimalSigned(m_data, m_count); + } + + /** + Get the value in hexadecimal form. + **/ + public function toHex() : String + { + var sb = new StringBuf(); + var i : Int = m_count; + while (--i >= 0) + { + var v = m_data.get(i); + for (j in 0 ... 8) + { + var c : Int = (v >> 28) & 0x0f; + v <<= 4; + c = (c < 10) ? (c + 48) : (c - 10 + 97); + sb.addChar(c); + } + } + return sb.toString(); + } + + /** + Get the value as bytes, big endian order. + **/ + public function toBytes() : Bytes + { + var result = Bytes.alloc(m_count << 2); + for (i in 0 ... m_count) + { + var v : Int = m_data.get(m_count - i - 1); + result.set((i << 2) + 0, (v >> 24) & 0xff); + result.set((i << 2) + 1, (v >> 16) & 0xff); + result.set((i << 2) + 2, (v >> 8) & 0xff); + result.set((i << 2) + 3, (v >> 0) & 0xff); + } + return result; + } + + /** + Get the value as a vector of Ints. + + Values go from less significant to more significant with + increasing index in the vector. + + Returns the number of Ints required to store the value. + **/ + public function toInts(output : Vector) : Int + { + if (output != null) + { + var n : Int = (m_count > output.length) ? output.length : m_count; + for (i in 0 ... n) + { + output.set(i, m_data.get(i)); + } + } + return m_count; + } + + /** + Creates a big integer with value `value`. + **/ + public static function fromInt(value : Int) : BigInt_ + { + var c = getCachedValue(value); + if (c == null) + { + c = newFromInt(value); + } + return c; + } + + /** + Creates a big integer with the value represented by the decimal string `value`. + **/ + public static function fromString(value : String) : BigInt_ + { + var bi = new MutableBigInt_(); + bi.setFromString(value); + return bi; + } + + /** + Creates a big integer with the signed value represented by + the hexadecimal string `value`. + **/ + public static function fromHexSigned(value : String) : BigInt_ + { + var bi = new MutableBigInt_(); + bi.setFromHexSigned(value); + return bi; + } + + /** + Creates a big integer with the unsigned value represented by + the hexadecimal string `value`. + **/ + public static function fromHexUnsigned(value : String) : BigInt_ + { + var bi = new MutableBigInt_(); + bi.setFromHexUnsigned(value); + return bi; + } + + /** + Creates a big integer with the value represented by the integer vector `value`. + **/ + public static function fromUnsignedInts(value : Vector, length : Int = 0) : BigInt_ + { + var bi = new MutableBigInt_(); + bi.setFromUnsignedInts(value, length); + return bi; + } + + //----------------------------------------------------------------------- + // Private implementation + //----------------------------------------------------------------------- + + private inline function getUnsignedDigitCount() : Int + { + if ((m_count > 1) && (m_data.get(m_count - 1) == 0)) + { + return m_count - 1; + } + return m_count; + } + + private inline function getShort(n : Int) : Int + { + return MultiwordArithmetic.getShort(m_data, n); + } + + private function compact() : Void + { + if (isNegative()) + { + while (m_count > 1) + { + if ((m_data.get(m_count - 1) == -1) && (m_data.get(m_count - 2) < 0)) + { + --m_count; + } + else + { + break; + } + } + } + else + { + while (m_count > 1) + { + if ((m_data.get(m_count - 1) == 0) && (m_data.get(m_count - 2) >= 0)) + { + --m_count; + } + else + { + break; + } + } + } + } + + private static function newFromInt(value : Int) : BigInt_ + { + var bi = new MutableBigInt_(); + bi.setFromInt(value); + return bi; + } + + private function new() : Void + { + } + + private static function getCachedValue(value : Int) : BigInt_ + { + if ((s_firstCachedValue <= value) && (value <= s_lastCachedValue)) + { + initCache(); + return s_cache[value - s_firstCachedValue]; + } + return null; + } + + private static function initCache() : Void + { + if (s_cache == null) + { + s_cache = new Vector(s_lastCachedValue + 1 - s_firstCachedValue); + for (i in 0 ... s_cache.length) + { + s_cache[i] = newFromInt(i + s_firstCachedValue); + } + } + } + + private var m_count : Int; + private var m_data : Vector; + + private static inline var s_firstCachedValue : Int = -16; + private static inline var s_lastCachedValue : Int = 16; + private static var s_cache : Vector = null; + + //----------------------------------------------------------------------- + // Static helpers + //----------------------------------------------------------------------- + + @:noCompletion + private static inline function negate1(a : BigInt_) : BigInt_ + { + var r = new MutableBigInt_(); + BigIntArithmetic.negate(r, a); + return r; + } + + @:noCompletion + private static inline function equals2Int(a : BigInt_, b : Int) : Bool + { + return a.equalsInt(b); + } + + @:noCompletion + private static inline function equals2(a : BigInt_, b : BigInt_) : Bool + { + return a.equals(b); + } + + @:noCompletion + private static inline function addInt2(a : BigInt_, b : Int) : BigInt_ + { + var r = new MutableBigInt_(); + BigIntArithmetic.addInt(r, a, b); + return r; + } + + @:noCompletion + private static inline function add2(a : BigInt_, b : BigInt_) : BigInt_ + { + var r = new MutableBigInt_(); + BigIntArithmetic.add(r, a, b); + return r; + } + + @:noCompletion + private static inline function subInt2(a : BigInt_, b : Int) : BigInt_ + { + var r = new MutableBigInt_(); + BigIntArithmetic.subtractInt(r, a, b); + return r; + } + + @:noCompletion + private static inline function sub2(a : BigInt_, b : BigInt_) : BigInt_ + { + var r = new MutableBigInt_(); + BigIntArithmetic.subtract(r, a, b); + return r; + } + + @:noCompletion + private static inline function multiplyInt2(a : BigInt_, b : Int) : BigInt_ + { + var r = new MutableBigInt_(); + BigIntArithmetic.multiplyInt(r, a, b); + return r; + } + + @:noCompletion + private static inline function multiply2(a : BigInt_, b : BigInt_) : BigInt_ + { + var r = new MutableBigInt_(); + BigIntArithmetic.multiply(r, a, b); + return r; + } + + @:noCompletion + private static inline function divideInt2(a : BigInt_, b : Int) : BigInt_ + { + var q = new MutableBigInt_(); + BigIntArithmetic.divideInt(a, b, q); + return q; + } + + @:noCompletion + private static inline function divide2(a : BigInt_, b : BigInt_) : BigInt_ + { + var q = new MutableBigInt_(); + BigIntArithmetic.divide(a, b, q, null); + return q; + } + + @:noCompletion + private static inline function modulusInt2(a : BigInt_, b : Int) : Int + { + var q = new MutableBigInt_(); + return BigIntArithmetic.divideInt(a, b, q); + } + + @:noCompletion + private static inline function modulus2(a : BigInt_, b : BigInt_) : BigInt_ + { + var q = new MutableBigInt_(); + var r = new MutableBigInt_(); + BigIntArithmetic.divide(a, b, q, r); + return r; + } + + @:noCompletion + private static inline function arithmeticShiftLeft2(a : BigInt_, b : Int) : BigInt_ + { + var r = new MutableBigInt_(); + BigIntArithmetic.arithmeticShiftLeft(r, a, b); + return r; + } + + @:noCompletion + private static inline function arithmeticShiftRight2(a : BigInt_, b : Int) : BigInt_ + { + var r = new MutableBigInt_(); + BigIntArithmetic.arithmeticShiftRight(r, a, b); + return r; + } + + @:noCompletion + private static inline function sign1(a : BigInt_) : Int + { + return a.sign(); + } + + @:noCompletion + private static inline function isZero1(a : BigInt_) : Bool + { + return a.isZero(); + } + + @:noCompletion + private static inline function isNegative1(a : BigInt_) : Bool + { + return a.isNegative(); + } + + @:noCompletion + private static inline function toString1(a : BigInt_) : String + { + return a.toString(); + } + + @:noCompletion + private static inline function toHex1(a : BigInt_) : String + { + return a.toHex(); + } + + @:noCompletion + private static inline function toBytes1(a : BigInt_) : Bytes + { + return a.toBytes(); + } + + @:noCompletion + private static inline function toInts1(a : BigInt_, v : Vector) : Int + { + return a.toInts(v); + } +} diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx new file mode 100644 index 00000000000..46c89d42839 --- /dev/null +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -0,0 +1,960 @@ +/* + * Copyright (C)2005-2022 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +import haxe.math.bigint.BigIntExceptions; +import haxe.math.bigint.BigIntHelper; +import haxe.ds.Vector; + +@:allow(haxe.math.bigint) +class MultiwordArithmetic +{ + public static function isZero(value : Vector, length : Int) : Bool + { + if (length < 1) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + for (i in 0 ... length) + { + if (value.get(i) != 0) + { + return false; + } + } + return true; + } + + public static inline function isNegative(value : Vector, length : Int) : Bool + { + return value.get(length - 1) < 0; + } + + public static function getLengthUnsigned(value : Vector, length : Int) : Int + { + if (length < 1) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + while (--length > 0) + { + if (value.get(length) != 0) + { + break; + } + } + return length + 1; + } + + /** + Perform unsigned (zero) extension of `input` into `result`. + + `input` and `result` may refer to the same object. + **/ + public static function extendUnsigned(result : Vector, resultLength : Int, input : Vector, inputLength : Int) : Void + { + if (input == result) + { + if (resultLength > inputLength) + { + for (i in inputLength ... resultLength) + { + result.set(i, 0); + } + } + } + else + { + if (resultLength > inputLength) + { + copy(result, input, inputLength); + for (i in inputLength ... resultLength) + { + result.set(i, 0); + } + } + else + { + copy(result, input, resultLength); + } + } + } + + /** + Perform the unary negation of big integer `operand` and put + the result into big integer `result`. + + Returns `true` if the operation overflowed; `false` + otherwise. + + Ok for `result` and `operand` to be the same object. + **/ + public static function negate(result : Vector, operand : Vector, length : Int) : Bool + { + var c : Int = 1; + var x : Int = 0; + var z : Int = 0; + for (i in 0 ... length) + { + x = ~operand.get(i); + z = x + c; + result.set(i, z); + c = (x & ~z) >>> 31; // "Hacker's Delight" p. 38 + } + // detect overflow; intuitively, this can only occur for inputs of 2 ^ (32 * N - 1). + return (~x & z) < 0; + } + + /** + Add big integer `operand2` to big integer `operand1` and put + the result into big integer `result`. + + Ok for `result`, `operand1`, and `operand2` to be the same object. + + Returns the "carry" value of either 0 or 1. + **/ + public static function add(result : Vector, operand1 : Vector, operand2 : Vector, length : Int) : Int + { + if ((length < 1) || (result.length < length) || (operand1.length < length) || (operand2.length < length)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + var c : Int = 0; + var x : Int = 0, y : Int = 0, z : Int = 0; + for (i in 0 ... length) + { + x = operand1.get(i); + y = operand2.get(i); + z = x + y + c; + result.set(i, z); + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + } + return c; + } + + /** + Subtract big integer `operand2` from big integer `operand1` + and put the result into big integer `result`. + + Ok for `result`, `operand1`, and `operand2` to be the same object. + + Returns the "borrow" value of either 0 or 1. + **/ + public static function subtract(result : Vector, operand1 : Vector, operand2 : Vector, length : Int) : Int + { + if ((length < 1) || (result.length < length) || (operand1.length < length) || (operand2.length < length)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + var c : Int = 0; + var x : Int = 0, y : Int = 0, z : Int = 0; + for (i in 0 ... length) + { + x = operand1.get(i); + y = operand2.get(i); + z = x - y - c; + result.set(i, z); + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + } + return c; + } + + /** + Multiply `operand1` by `operand2`, where both are unsigned, + and put the result into `result`. + + `result` must have length >= `operand1Length` + 1. + + `result` may not refer the same object as either `operand1` + or `operand2`; however, `operand1` and `operand2` may be the + same object. + **/ + public static function multiplyIntUnsigned(result : Vector, operand1 : Vector, operand1Length : Int, operand2 : Int) : Void + { + // TODO: Optimize. + var op2 = new Vector(1); + op2.set(0, operand2); + multiplyUnsigned(result, operand1, operand1Length, op2, 1); + } + + /** + Multiply `operand1` by `operand2`, where both are unsigned, + and put the result into `result`. + + `result` must have length >= `operand1Length` + + `operand2Length`. + + `result` may not refer the same object as either `operand1` + or `operand2`; however, `operand1` and `operand2` may be the + same object. + **/ + public static function multiplyUnsigned(result : Vector, operand1 : Vector, operand1Length : Int, operand2 : Vector, operand2Length : Int) : Void + { + // Implements Figure 8-1 (p. 172) from "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. + + if ((operand1 == result) || (operand2 == result)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if ((operand1Length < 1) || (operand2Length < 1)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if ((operand1.length < operand1Length) || (operand2.length < operand2Length)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + + var resultSize : Int = operand1Length + operand2Length; + if (result.length < resultSize) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + setZero(result, resultSize); + + if (isZero(operand1, operand1Length) || isZero(operand2, operand2Length)) + { + return; + } + + var b : Int, k : Int, t : Int; + var u : Int, v : Int, w : Int; + var m : Int = operand1Length << 1; + var n : Int = operand2Length << 1; + + for (j in 0 ... n) + { + v = getShort(operand2, j); + k = 0; + for (i in 0 ... m) + { + u = getShort(operand1, i); + w = getShort(result, i + j); + t = u * v + w + k; + setShort(result, i + j, t); + k = t >>> 16; + } + setShort(result, j + m, k); + } + } + + public static inline function getDivisionQuotientLengthUnsigned(dividendLength : Int, divisorLength : Int) : Int + { + var max:Int = dividendLength - divisorLength + 1; + return ((max>1)?max:1); + } + + /** + Divide `dividend` by `divisor`, where both are unsigned. + The quotient of the division is put into `quotientOut`; + the remainder is the return value. + + `quotientOut` must have length >= `dividendLength`. + + `quotientOut` may refer to `dividend`. + + `work` must not refer to any of the inputs, and must have + length >= `dividendLength` + 2. + + `dividend` is not modified, unless it refers to `quotientOut`. + + The results are unspecified if `divisor` is negative. + **/ + public static function divideIntUnsigned(dividend : Vector, dividendLength : Int, divisor : Int, quotientOut : Vector, work : Vector) : Int + { + // TODO: Consider optimizing this case. + var remainder = new Vector(1); + var vDivisor = new Vector(1); + vDivisor.set(0, divisor); + divideUnsigned(dividend, dividendLength, vDivisor, 1, quotientOut, remainder, work); + return remainder.get(0); + } + + /** + Divide `dividend` by `divisor`, where both are unsigned. + The quotient of the division is put into `quotientOut`; + the remainder is put into `remainderOut`. + + `divisor` must not have any leading zeros. + + `quotientOut` must have length >= `dividendLength` - + `divisorLength` + 1. + + `remainderOut` may be `null` if the remainder value is not + needed. If supplied, it must be of length >= `divisorLength`. + + `quotientOut` and `remainderOut` must not refer to the same + object; but either may refer to the inputs. + + `dividend` and `divisor` may refer to the same object. + + `work` must not refer to any of the inputs, and must have + length >= `dividendLength` + `divisorLength` + 1. + + `dividend` and `divisor` are not modified, unless they + reference one of the outputs. + **/ + public static function divideUnsigned(dividend : Vector, dividendLength : Int, divisor : Vector, divisorLength : Int, quotientOut : Vector, remainderOut : Vector, work : Vector) : Void + { + if ((quotientOut == null) || (work == null) || (quotientOut == remainderOut)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if ((work == dividend) || (work == divisor) || (work == quotientOut) || (work == remainderOut)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if ((divisorLength < 1) || (dividendLength < 1)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + + var quotientLength : Int = getDivisionQuotientLengthUnsigned(dividendLength, divisorLength); + if (quotientOut.length < quotientLength) + { + // quotient storage too small + throw BigIntExceptions.INVALID_ARGUMENT; + } + if ((remainderOut != null) && (remainderOut.length < divisorLength)) + { + // remainder storage too small + throw BigIntExceptions.INVALID_ARGUMENT; + } + if (work.length < dividendLength + divisorLength + 1) + { + // quotient storage too small + throw BigIntExceptions.INVALID_ARGUMENT; + } + + // special cases + var dh : Int = divisor.get(divisorLength - 1); + if (divisorLength < 2) + { + switch (dh) + { + case 0: + throw BigIntExceptions.DIVISION_BY_ZERO; + case 1: + copy(quotientOut, dividend, dividendLength); // quotientLength == dividendLength + if (remainderOut != null) + { + setZero(remainderOut, divisorLength); + } + return; + } + } + else if (dh == 0) + { + // leading zero + throw BigIntExceptions.INVALID_ARGUMENT; + } + + // trim leading zeros + /*while ((dividendLength > 1) && (dividend.get(dividendLength - 1) == 0)) + { + --dividendLength; + }*/ + + if (dividendLength < 2) + { + switch (dividend.get(0)) + { + case 0: + setZero(quotientOut, quotientLength); + if (remainderOut != null) + { + setZero(remainderOut, divisorLength); + } + return; + } + } + + // if dividend is shorter than divisor + if (dividendLength < divisorLength) + { + if (remainderOut != null) + { + copy(remainderOut, dividend, dividendLength); + for (i in dividendLength ... divisorLength) + { + remainderOut.set(i, 0); + } + } + setZero(quotientOut, quotientLength); + return; + } + + // TODO: Handle special case of dividend < divisor. + + // Based on Figure 9-1 (p. 185) from "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. + + var j : Int, k : Int, t : Int; + var m : Int = dividendLength << 1; + var un : Int = divisorLength << 1; + var n : Int = un; + if (getShort(divisor, n - 1) == 0) + { + --n; + } + + // Take care of the case of a single-digit divisor here. + if (n == 1) + { + var v0 : Int = divisor.get(0); + if (quotientOut != dividend) + { + setZero(quotientOut, quotientLength); + } + var uj : Int; + k = 0; + j = m; + while (--j >= 0) + { + uj = getShort(dividend, j); + t = BigIntHelper.u32divu16((k << 16) + uj, v0); + setShort(quotientOut, j, t); + k = (k << 16) + uj - t * v0; + } + if (remainderOut != null) + { + setFromIntUnsigned(remainderOut, divisorLength, k); + } + return; + } + + // vn is work[0] through work[divisor.m_count - 1] or shorts [0, n) + // un is work[divisor.m_count] through work[dividend.m_count + divisor.m_count] or shorts [n, n + m] + + var s : Int = BigIntHelper.nlz(getShort(divisor, n - 1)) - 16; // 0 <= s < 16 + if (s > 0) + { + _lsl32x(work, 0, divisor, divisorLength, s); + _lsl32x(work, divisorLength, dividend, dividendLength, s); + } + else + { + Vector.blit(divisor, 0, work, 0, divisorLength); + Vector.blit(dividend, 0, work, divisorLength, dividendLength); + work.set(divisorLength + dividendLength, 0); + } + + setZero(quotientOut, quotientLength); + + // Main loop. + var qhat : Int, rhat : Int, p : Int, t : Int; + var vn : Int = getShort(work, n - 1); + j = m - n + 1; + while (--j >= 0) + { + // Compute estimate qhat of q[j] + t = (getShort(work, j + n + un) << 16) + getShort(work, j + n + un - 1); + qhat = BigIntHelper.u32divu16(t, vn); + rhat = t - qhat * vn; + while ((qhat >= 65536) || BigIntHelper.u32gtu32(qhat * getShort(work, n - 2), (rhat << 16) + getShort(work, j + n + un - 2))) + { + qhat -= 1; + rhat += vn; + if (rhat >= 65536) + { + break; + } + } + + // Multiply and subtract + k = 0; + for (i in 0 ... n) + { + p = qhat * getShort(work, i); + t = getShort(work, i + j + un) - k - (p & 0xffff); + setShort(work, i + j + un, t); + k = (p >>> 16) - (t >> 16); + } + t = getShort(work, j + n + un) - k; + setShort(work, j + n + un, t); + + // Store quotient digit. + // If we subtracted too much, add back. + if (t >= 0) + { + setShort(quotientOut, j, qhat); + } + else + { + setShort(quotientOut, j, qhat - 1); + k = 0; + for (i in 0 ... n) + { + t = getShort(work, i + j + un) + getShort(work, i) + k; + setShort(work, i + j + un, t); + k = t >> 16; + } + t = getShort(work, j + n + un) + k; + setShort(work, j + n + un, t); + } + } + + // If the caller wants the remainder, unnormalize it and pass back. + if (remainderOut != null) + { + if (s > 0) + { + _lsr32(remainderOut, work, divisorLength, divisorLength, s); + } + else + { + Vector.blit(work, divisorLength, remainderOut, 0, divisorLength); + } + } + } + + /** + Shift multiword integer `input` right by `shift` binary + places and store the result in `result`, with the high bit + duplicated for bits inserted from the left. + + `shift` must meet the critera 0 <= `shift` < 32. + + `result` and `input` may be the same object. + **/ + public static function arithmeticShiftRight(result : Vector, input : Vector, length : Int, shift : Int) : Void + { + if ((length < 1) || (result.length < length) || (input.length < length)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if (shift < 0) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + else if (shift == 0) + { + if (input != result) + { + Vector.blit(input, 0, result, 0, length); + } + } + else if (shift < 32) + { + _asr32(result, input, length, 0, shift); + } + else + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + } + + /** + Shift multiword integer `input` right by `shift` binary + places and store the result in `result`, with zeros inserted + from the left. + + `shift` must meet the critera 0 <= `shift` < 32. + + `result` and `input` may be the same object. + **/ + public static function logicalShiftRight(result : Vector, input : Vector, length : Int, shift : Int) : Void + { + if ((length < 1) || (result.length < length) || (input.length < length)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if (shift < 0) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + else if (shift == 0) + { + if (input != result) + { + Vector.blit(input, 0, result, 0, length); + } + } + else if (shift < 32) + { + _lsr32(result, input, length, 0, shift); + } + else + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + } + + /** + Shift multiword integer `input` left by `shift` binary + places and store the result in `result`, with zeros inserted + from the right. + + `shift` must meet the critera 0 <= `shift` < 32. + + `result` and `input` may be the same object. + **/ + public static function shiftLeft(result : Vector, input : Vector, length : Int, shift : Int) : Void + { + if ((length < 1) || (result.length < length) || (input.length < length)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if (shift < 0) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + else if (shift == 0) + { + if (input != result) + { + Vector.blit(input, 0, result, 0, length); + } + } + else if (shift < 32) + { + _lsl32(result, 0, input, length, shift); + } + else + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + } + + /** + Compare two signed multiword integers. + + Returns -1 if `a < b`; otherwise + returns 1 if `a > b`; otherwise + returns 0 (`a == b`). + **/ + public static function compareSigned(a : Vector, b : Vector, length : Int) : Int + { + if (a != b) + { + var ah : Int = a.get(length - 1); + var bh : Int = b.get(length - 1); + if ((ah ^ bh) < 0) + { + // differing signs + return (ah >> 30) | 1; + } + return compareUnsigned(a, b, length); + } + return 0; + } + + /** + Compare two unsigned multiword integers. + + Returns -1 if `a < b`; otherwise + returns 1 if `a > b`; otherwise + returns 0 (`a == b`). + **/ + public static function compareUnsigned(a : Vector, b : Vector, length : Int) : Int + { + if (a != b) + { + var an : Int, bn : Int, d : Int; + var x : Int = -2147483648; + while (--length >= 0) + { + an = a.get(length) + x; + bn = b.get(length) + x; + if (an > bn) return 1; + if (an < bn) return -1; + } + } + return 0; + } + + public static function setZero(dest : Vector, length : Int) : Void + { + if (dest.length < length) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + for (i in 0 ... length) + { + dest.set(i, 0); + } + } + + public static function setFromIntUnsigned(dest : Vector, length : Int, value : Int) : Void + { + if (dest.length < length) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + dest.set(0, value); + for (i in 1 ... length) + { + dest.set(i, 0); + } + } + + public static function setFromHexUnsigned(dest : Vector, length : Int, value : String) : Bool + { + if ((value == null) || (dest == null)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if (dest.length < length) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + var index = value.length; + if (index <= 0) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if (length < 1) + { + return false; + } + var c : Int; + var start : Int = 0; + while (start < index) + { + c = value.charCodeAt(start); + if ((c != 48) && (c != 32)) + { + break; + } + ++start; + } + var pos : Int = 0; + var bit : Int = 0; + var acc : Int = 0; + while (index > start) + { + c = value.charCodeAt(--index); + if ((48 <= c) && (c <= 57)) + { + c -= 48; + } + else if ((65 <= c) && (c <= 70)) + { + c -= 55; + } + else if ((97 <= c) && (c <= 102)) + { + c -= 87; + } + else if (c == 32) + { + continue; + } + else + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + acc |= c << bit; + bit += 4; + if (bit >= 32) + { + if (pos >= length) + { + return false; + } + dest.set(pos++, acc); + acc = 0; + bit = 0; + } + } + if (bit > 0) + { + if (pos >= length) + { + return false; + } + dest.set(pos++, acc); + } + for (c in pos ... length) + { + dest.set(c, 0); + } + return true; + } + + public static function toHex(input : Vector, length : Int) : String + { + var sb = new StringBuf(); + while (--length >= 0) + { + var v = input.get(length); + for (j in 0 ... 8) + { + var c : Int = (v >> 28) & 0x0f; + v <<= 4; + c = (c < 10) ? (c + 48) : (c - 10 + 97); + sb.addChar(c); + } + } + return sb.toString(); + } + + /** + Get the value in decimal form. + **/ + public static function toDecimalSigned(value : Vector, length : Int) : String + { + var sb = new StringBuf(); + var work = new Vector(length); + if (isNegative(value, length)) + { + negate(work, value, length); + sb.addChar(45); // '-' + } + else + { + copy(work, value, length); + } + return _toDecimal(sb, work, length); + } + + /** + Get the value in decimal form. + **/ + public static function toDecimalUnsigned(value : Vector, length : Int) : String + { + var sb = new StringBuf(); + var work = new Vector(length); + copy(work, value, length); + return _toDecimal(sb, work, length); + } + + public static function copy(dest : Vector, source : Vector, length : Int) : Void + { + if (dest.length < length) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + Vector.blit(source, 0, dest, 0, length); + } + + public static function getBitSigned(value : Vector, length : Int, index : Int) : Int + { + var d : Int = index >> 5; + if (d >= length) + { + return value.get(length - 1) >>> 31; + } + return (value.get(d) >> (index & 31)) & 1; + } + + //----------------------------------------------------------------------- + // Private helpers + //----------------------------------------------------------------------- + + // assumes 0 < shift < 32 + // ok if output == input + private static function _lsl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int) : Void + { + var x : Int = input.get(inputSize - 1); + var r : Int = 32 - shift; + var y : Int; + while (--inputSize > 0) + { + y = input.get(inputSize - 1); + x = (x << shift) | (y >>> r); + output.set(inputSize + outputOffset, x); + x = y; + } + output.set(outputOffset, x << shift); + } + + // assumes 0 < shift < 32 + // ok if output == input + // note this writes inputSize + 1 words to output + private static function _lsl32x(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int) : Void + { + var x : Int = 0; + var r : Int = 32 - shift; + var y : Int; + while (inputSize > 0) + { + y = input.get(inputSize - 1); + x = (x << shift) | (y >>> r); + output.set(inputSize + outputOffset, x); + x = y; + --inputSize; + } + output.set(outputOffset, x << shift); + } + + // assumes 0 < shiftBits < 32 + // assumes shiftDigits < length + private static function _asr32(result : Vector, input : Vector, length : Int, shiftDigits : Int, shiftBits : Int) : Void + { + var r : Int = 32 - shiftBits; + var i : Int = 0; + while (i < length - shiftDigits - 1) + { + result.set(i, (input.get(i + shiftDigits) >>> shiftBits) | (input.get(i + shiftDigits + 1) << r)); + ++i; + } + result.set(i, input.get(i + shiftDigits) >> shiftBits); + } + + // assumes 0 < shift < 32 + // ok if output == input + private static function _lsr32(output : Vector, input : Vector, inputSize : Int, inputOffset : Int, shift : Int) : Void + { + var r : Int = 32 - shift; + var i : Int = 0; + while (i < inputSize - 1) + { + output.set(i, (input.get(inputOffset + i) >>> shift) | (input.get(inputOffset + i + 1) << r)); + ++i; + } + output.set(i, input.get(inputOffset + i) >>> shift); + } + + @:noCompletion + private static function _toDecimal(sb : StringBuf, value : Vector, length : Int) : String + { + length = getLengthUnsigned(value, length); + var digits = new Vector(length * 10); // it is really log10 2^32 ~= 9.633, but this is close, simple, and never too little + var work = new Vector(length + 1 + 1); + var pos : Int = digits.length; + var r : Int; + do + { + r = divideIntUnsigned(value, length, 10, value, work); + length = getLengthUnsigned(value, length); + digits.set(--pos, r + 48); + } while (!isZero(value, length)); + for (i in pos ... digits.length) + { + sb.addChar(digits.get(i)); + } + return sb.toString(); + } + + private static inline function getShort(v : Vector, n : Int) : Int + { + return (v.get(n >> 1) >> ((n & 1) << 4)) & 0xffff; + } + + private static inline function setShort(a : Vector, n : Int, v : Int) : Void + { + var s : Int = (n & 1) << 4; + var t : Int = a.get(n >> 1) & (~0xffff >>> s); + a.set(n >> 1, t | ((v & 0xffff) << s)); + } +} diff --git a/std/haxe/math/bigint/MutableBigInt.hx b/std/haxe/math/bigint/MutableBigInt.hx new file mode 100644 index 00000000000..344ca945497 --- /dev/null +++ b/std/haxe/math/bigint/MutableBigInt.hx @@ -0,0 +1,438 @@ +/* + * Copyright (C)2005-2022 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +import haxe.ds.Vector; +import haxe.io.Bytes; + +@:allow(haxe.math.bigint) +abstract MutableBigInt(MutableBigInt_) +{ + //----------------------------------------------------------------------- + // Public interface + //----------------------------------------------------------------------- + + public inline function sign() : Int + { + return BigInt_.sign1(this); + } + + public inline function isZero() : Bool + { + return BigInt_.isZero1(this); + } + + public inline function isNegative() : Bool + { + return BigInt_.isNegative1(this); + } + + public inline function toString() : String + { + return BigInt_.toString1(this); + } + + public inline function toHex() : String + { + return BigInt_.toHex1(this); + } + + public inline function toBytes() : Bytes + { + return BigInt_.toBytes1(this); + } + + public inline function toInts(output : Vector) : Int + { + return BigInt_.toInts1(this, output); + } + + public inline function setFromInt(value : Int) : Void + { + var a : MutableBigInt_ = this; + a.setFromInt(value); + } + + public inline function setFromUnsignedInts(value : Vector, length : Int = 0) : Void + { + var a : MutableBigInt_ = this; + a.setFromUnsignedInts(value, length); + } + + public inline function setFromBigEndianBytesUnsigned(value : Bytes, offset : Int = 0, length : Int = 0) : Void + { + var a : MutableBigInt_ = this; + a.setFromBigEndianBytesUnsigned(value, offset, length); + } + + public inline function setFromLittleEndianBytesUnsigned(value : Bytes, offset : Int = 0, length : Int = 0) : Void + { + var a : MutableBigInt_ = this; + a.setFromLittleEndianBytesUnsigned(value, offset, length); + } + + public inline function clear() : Void + { + var a : MutableBigInt_ = this; + a.clear(); + } + + public inline function copyFrom(other : BigInt) : Void + { + var a : MutableBigInt_ = this; + a.copyFrom(other); + } + + public inline function getBit(index : Int) : Int + { + return BigIntArithmetic.getBit(this, index); + } + + public static function fromBigEndianBytesUnsigned(value : Bytes) : MutableBigInt + { + var r = new MutableBigInt_(); + r.setFromBigEndianBytesUnsigned(value); + return new MutableBigInt(r); + } + + public static function fromLittleEndianBytesUnsigned(value : Bytes) : MutableBigInt + { + var r = new MutableBigInt_(); + r.setFromLittleEndianBytesUnsigned(value); + return new MutableBigInt(r); + } + + //----------------------------------------------------------------------- + // Operators + //----------------------------------------------------------------------- + + // The declaration order of the operations is significant in Haxe. + // Recommended order is: + // * MutableBigInt Int + // * MutableBigInt BigInt + // * MutableBigInt MutableBigInt + // * MutableBigInt Int + // * MutableBigInt BigInt + // * MutableBigInt MutableBigInt + + // Unary negation + @:op(-A) @:noCompletion public static inline function negate_(a : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.negate1(a)); + } + + // Binary equality + @:op(A == B) @:noCompletion public static inline function eqInt_(a : MutableBigInt, b : Int) : Bool + { + return BigInt_.equals2Int(a, b); + } + @:op(A == B) @:noCompletion public static inline function eq_(a : MutableBigInt, b : BigInt) : Bool + { + return BigInt_.equals2(a, b); + } + @:op(A == B) @:noCompletion public static inline function eqMutable_(a : MutableBigInt, b : MutableBigInt) : Bool + { + return BigInt_.equals2(a, b); + } + + // Binary inequality + @:op(A != B) @:noCompletion public static inline function ineqInt_(a : MutableBigInt, b : Int) : Bool + { + return !BigInt_.equals2Int(a, b); + } + @:op(A != B) @:noCompletion public static inline function ineq_(a : MutableBigInt, b : BigInt) : Bool + { + return !BigInt_.equals2(a, b); + } + @:op(A != B) @:noCompletion public static inline function ineqMutable_(a : MutableBigInt, b : MutableBigInt) : Bool + { + return !BigInt_.equals2(a, b); + } + + // Binary less than + @:op(A < B) @:noCompletion public static inline function ltInt_(a : MutableBigInt, b : Int) : Bool + { + return BigIntArithmetic.compareInt(a, b) < 0; + } + @:op(A < B) @:noCompletion public static inline function lt_(a : MutableBigInt, b : BigInt) : Bool + { + return BigIntArithmetic.compare(a, b) < 0; + } + @:op(A < B) @:noCompletion public static inline function ltMutable_(a : MutableBigInt, b : MutableBigInt) : Bool + { + return BigIntArithmetic.compare(a, b) < 0; + } + + // Binary less than or equal + @:op(A <= B) @:noCompletion public static inline function lteInt_(a : MutableBigInt, b : Int) : Bool + { + return BigIntArithmetic.compareInt(a, b) <= 0; + } + @:op(A <= B) @:noCompletion public static inline function lte_(a : MutableBigInt, b : BigInt) : Bool + { + return BigIntArithmetic.compare(a, b) <= 0; + } + @:op(A <= B) @:noCompletion public static inline function lteMutable_(a : MutableBigInt, b : MutableBigInt) : Bool + { + return BigIntArithmetic.compare(a, b) <= 0; + } + + // Binary greater than + @:op(A > B) @:noCompletion public static inline function gtInt_(a : MutableBigInt, b : Int) : Bool + { + return BigIntArithmetic.compareInt(a, b) > 0; + } + @:op(A > B) @:noCompletion public static inline function gt_(a : MutableBigInt, b : BigInt) : Bool + { + return BigIntArithmetic.compare(a, b) > 0; + } + @:op(A > B) @:noCompletion public static inline function gtMutable_(a : MutableBigInt, b : MutableBigInt) : Bool + { + return BigIntArithmetic.compare(a, b) > 0; + } + + // Binary greater than or equal + @:op(A >= B) @:noCompletion public static inline function gteInt_(a : MutableBigInt, b : Int) : Bool + { + return BigIntArithmetic.compareInt(a, b) >= 0; + } + @:op(A >= B) @:noCompletion public static inline function gte_(a : MutableBigInt, b : BigInt) : Bool + { + return BigIntArithmetic.compare(a, b) >= 0; + } + @:op(A >= B) @:noCompletion public static inline function gteMutable_(a : MutableBigInt, b : MutableBigInt) : Bool + { + return BigIntArithmetic.compare(a, b) >= 0; + } + + // Binary addition + @:op(A += B) @:noCompletion public static inline function addAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt + { + BigIntArithmetic.addInt(a, a, b); + return a; + } + @:op(A += B) @:noCompletion public static inline function addAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt + { + BigIntArithmetic.add(a, a, b); + return a; + } + @:op(A += B) @:noCompletion public static inline function addAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt + { + BigIntArithmetic.add(a, a, b); + return a; + } + @:op(A + B) @:noCompletion public static inline function addInt_(a : MutableBigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.addInt2(a, b)); + } + @:op(A + B) @:noCompletion public static inline function add_(a : MutableBigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.add2(a, b)); + } + @:op(A + B) @:noCompletion public static inline function addMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.add2(a, b)); + } + + // Binary subtraction + @:op(A -= B) @:noCompletion public static inline function subAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt + { + BigIntArithmetic.subtractInt(a, a, b); + return a; + } + @:op(A -= B) @:noCompletion public static inline function subAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt + { + BigIntArithmetic.subtract(a, a, b); + return a; + } + @:op(A -= B) @:noCompletion public static inline function subAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt + { + BigIntArithmetic.subtract(a, a, b); + return a; + } + @:op(A - B) @:noCompletion public static inline function subInt_(a : MutableBigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.subInt2(a, b)); + } + @:op(A - B) @:noCompletion public static inline function sub_(a : MutableBigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.sub2(a, b)); + } + @:op(A - B) @:noCompletion public static inline function subMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.sub2(a, b)); + } + + // Binary multiplication + @:op(A *= B) @:noCompletion public static inline function mulAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt + { + MutableBigInt_.multiplyAssignInt2(a, b); + return a; + } + @:op(A *= B) @:noCompletion public static inline function mulAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt + { + MutableBigInt_.multiplyAssign2(a, b); + return a; + } + @:op(A *= B) @:noCompletion public static inline function mulAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt + { + MutableBigInt_.multiplyAssign2(a, b); + return a; + } + @:op(A * B) @:noCompletion public static inline function mulInt_(a : MutableBigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.multiplyInt2(a, b)); + } + @:op(A * B) @:noCompletion public static inline function mul_(a : MutableBigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.multiply2(a, b)); + } + @:op(A * B) @:noCompletion public static inline function mulMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.multiply2(a, b)); + } + + // Binary division + @:op(A /= B) @:noCompletion public static inline function divAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt + { + MutableBigInt_.divideAssignInt2(a, b); + return a; + } + @:op(A /= B) @:noCompletion public static inline function divAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt + { + MutableBigInt_.divideAssign2(a, b); + return a; + } + @:op(A /= B) @:noCompletion public static inline function divAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt + { + MutableBigInt_.divideAssign2(a, b); + return a; + } + @:op(A / B) @:noCompletion public static inline function divInt_(a : MutableBigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.divideInt2(a, b)); + } + @:op(A / B) @:noCompletion public static inline function div_(a : MutableBigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.divide2(a, b)); + } + @:op(A / B) @:noCompletion public static inline function divMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.divide2(a, b)); + } + + // Binary modulus + @:op(A %= B) @:noCompletion public static inline function modAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt + { + MutableBigInt_.modulusAssignInt2(a, b); + return a; + } + @:op(A %= B) @:noCompletion public static inline function modAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt + { + MutableBigInt_.modulusAssign2(a, b); + return a; + } + @:op(A %= B) @:noCompletion public static inline function modAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt + { + MutableBigInt_.modulusAssign2(a, b); + return a; + } + @:op(A % B) @:noCompletion public static inline function modInt_(a : MutableBigInt, b : Int) : Int + { + return BigInt_.modulusInt2(a, b); + } + @:op(A % B) @:noCompletion public static inline function mod_(a : MutableBigInt, b : BigInt) : BigInt + { + return new BigInt(BigInt_.modulus2(a, b)); + } + @:op(A % B) @:noCompletion public static inline function modMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt + { + return new BigInt(BigInt_.modulus2(a, b)); + } + + // Binary AND + @:op(A & B) @:noCompletion public static inline function andInt_(a : MutableBigInt, b : Int) : Int + { + return BigIntArithmetic.bitwiseAndInt(a, b); + } + + // Binary shift left + @:op(A <<= B) @:noCompletion public static inline function arithmeticShiftLeftAssign_(a : MutableBigInt, b : Int) : MutableBigInt + { + MutableBigInt_.arithmeticShiftLeftAssign2(a, b); + return a; + } + @:op(A << B) @:noCompletion public static inline function asl_(a : MutableBigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.arithmeticShiftLeft2(a, b)); + } + + // Binary shift right + @:op(A >>= B) @:noCompletion public static inline function arithmeticShiftRightAssign_(a : MutableBigInt, b : Int) : MutableBigInt + { + MutableBigInt_.arithmeticShiftRightAssign2(a, b); + return a; + } + @:op(A >> B) @:noCompletion public static inline function asr_(a : MutableBigInt, b : Int) : BigInt + { + return new BigInt(BigInt_.arithmeticShiftRight2(a, b)); + } + + //----------------------------------------------------------------------- + // Automatic conversions + //----------------------------------------------------------------------- + + @:from @:noCompletion public static inline function fromInt_(a : Int) : MutableBigInt + { + return new MutableBigInt(MutableBigInt_.fromInt(a)); + } + + @:from @:noCompletion public static inline function fromBigInt_(a : BigInt_) : MutableBigInt + { + return new MutableBigInt(MutableBigInt_.fromBigInt(a)); + } + + @:from @:noCompletion public static inline function fromMutableBigInt_(a : MutableBigInt_) : MutableBigInt + { + return new MutableBigInt(MutableBigInt_.fromBigInt(a)); + } + + @:to @:noCompletion public inline function toMutableBigInt_() : MutableBigInt_ + { + return this; + } + + @:to @:noCompletion public inline function toBigInt() : BigInt + { + return new BigInt(this); + } + + //----------------------------------------------------------------------- + // Private implementation + //----------------------------------------------------------------------- + + private inline function new(a : MutableBigInt_) + { + this = a; + } +} diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx new file mode 100644 index 00000000000..da88e51bee9 --- /dev/null +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -0,0 +1,478 @@ +/* + * Copyright (C)2005-2022 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +import haxe.math.bigint.BigIntExceptions; +import haxe.math.bigint.BigIntHelper; +import haxe.ds.Vector; +import haxe.io.Bytes; + +@:allow(haxe.math.bigint) +class MutableBigInt_ extends BigInt_ +{ + //----------------------------------------------------------------------- + // Public interface + //----------------------------------------------------------------------- + + /** + Set the value of this big int with an integer of value `value`. + **/ + public function setFromInt(value : Int) : Void + { + ensureCapacity(1, false); + m_data.set(0, value); + m_count = 1; + } + + /** + Set the value of this big integer with the signed value + represented by the hexadecimal string `value`. + **/ + public inline function setFromHexSigned(value : String) : Void + { + _setFromHex(value, true); + } + + /** + Set the value of this big integer with the unsigned value + represented by the hexadecimal string `value`. + **/ + public inline function setFromHexUnsigned(value : String) : Void + { + _setFromHex(value, false); + } + + /** + Set the value of this big integer with the value represented by the decimal string `value`. + **/ + public function setFromString(value : String) : Void + { + if ((value == null) || (value.length < 1)) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + var negate = value.charCodeAt(0) == 0x2d; + var index = negate ? 1 : 0; + if (value.length <= index) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + this.setFromInt(0); + var t = new MutableBigInt_(); + for (i in index ... value.length) + { + var c = value.charCodeAt(i); + if ((48 <= c) && (c <= 57)) + { + BigIntArithmetic.multiplyInt(t, this, 10); + BigIntArithmetic.addInt(this, t, c - 48); + } + else + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + } + if (negate) + { + BigIntArithmetic.negate(this, this); + } + } + + /** + Set the value of this big integer with the unsigned value + represented by the integer vector `value`. + **/ + public function setFromUnsignedInts(value : Vector, length : Int = 0) : Void + { + if (length <= 0) + { + length = value.length; + } + var neg = value.get(length - 1) >>> 31; + ensureCapacity(length + neg, false); + m_data.set(length + neg - 1, 0); + MultiwordArithmetic.copy(m_data, value, length); + m_count = length + neg; + compact(); + } + + public function setFromBigEndianBytesUnsigned(value : Bytes, offset : Int = 0, valueLength : Int = 0) : Void + { + if (valueLength <= 0) + { + valueLength = value.length; + } + if (offset + valueLength > value.length) + { + throw BigIntExceptions.BUFFER_TOO_SMALL; + } + if (valueLength < 1) + { + setFromInt(0); + return; + } + var neg = ((valueLength & 3) == 0) ? (value.get(0) >> 7) : 0; + var length = (valueLength + 3) >> 2; + ensureCapacity(length + neg, false); + m_data.set(length + neg - 1, 0); + var pos = 0; + var i = offset + valueLength; + while (i >= offset + 4) + { + m_data.set(pos++, + (value.get(i - 1) << 0) | + (value.get(i - 2) << 8) | + (value.get(i - 3) << 16) | + (value.get(i - 4) << 24)); + i -= 4; + } + if (i > offset) + { + var x : Int = 0; + for (j in offset ... i) + { + x = (x << 8) | value.get(j); + } + m_data.set(pos++, x); + } + m_count = length + neg; + compact(); + } + + public function setFromLittleEndianBytesUnsigned(value : Bytes, offset : Int = 0, valueLength : Int = 0) : Void + { + if (valueLength <= 0) + { + valueLength = value.length; + } + if (offset + valueLength > value.length) + { + throw BigIntExceptions.BUFFER_TOO_SMALL; + } + if (valueLength < 1) + { + setFromInt(0); + return; + } + var neg = ((valueLength & 3) == 0) ? (value.get(valueLength - 1) >> 7) : 0; + var length = (valueLength + 3) >> 2; + ensureCapacity(length + neg, false); + m_data.set(length + neg - 1, 0); + var pos = 0; + var i = offset; + while (i <= offset + valueLength - 4) + { + m_data.set(pos++, + (value.get(i + 0) << 0) | + (value.get(i + 1) << 8) | + (value.get(i + 2) << 16) | + (value.get(i + 3) << 24)); + i += 4; + } + if (i < offset + valueLength) + { + var x : Int = 0; + for (j in i ... offset + valueLength) + { + x |= value.get(j) << ((j - i) << 3); + } + m_data.set(pos++, x); + } + m_count = length + neg; + compact(); + } + + public function clear() : Void + { + MultiwordArithmetic.setZero(m_data, m_data.length); + m_count = 1; + } + + /** + Copy the value from big integer `other` into this big + integer. + **/ + private function copyFrom(other : BigInt_) : Void + { + if (other != this) + { + ensureCapacity(other.m_count, false); + for (i in 0 ... other.m_count) + { + m_data.set(i, other.m_data.get(i)); + } + m_count = other.m_count; + } + } + + //----------------------------------------------------------------------- + // Private implementation + //----------------------------------------------------------------------- + + private inline function setShort(n : Int, v : Int) : Void + { + var s : Int = (n & 1) << 4; + var t : Int = m_data.get(n >> 1) & (~0xffff >>> s); + m_data.set(n >> 1, t | ((v & 0xffff) << s)); + } + + private function copy(other : MutableBigInt_) : Void + { + this.m_data = other.m_data; + this.m_count = other.m_count; + this.m_owned = other.m_owned; + } + + private inline function ensureCapacity(n : Int, preserve : Bool) : Void + { + #if debug + if (s_testAllocation) + { + ensureCapacityDebug(n, preserve); + return; + } + #end + ensureCapacityProd(n, preserve); + } + + @:noCompletion + private function ensureCapacityDebug(n : Int, preserve : Bool) : Void + { + // always allocate the minimum amount necessary, to catch + // bounds edge cases as well as use of stale buffer data + if (preserve && (m_data != null) && (m_count > 0)) + { + n = (m_count > n) ? m_count : n; + n += s_debugAllocationPadding; + var newData = new Vector(n); + for (i in 0 ... m_count) + { + newData.set(i, m_data.get(i)); + } + for (i in m_count ... n) + { + newData.set(i, 0xdeadbeef); + } + m_data = newData; + } + else + { + n += s_debugAllocationPadding; + m_data = new Vector(n); + for (i in 0 ... n) + { + m_data.set(i, 0xdeadbeef); + } + } + } + + @:noCompletion + private function ensureCapacityProd(n : Int, preserve : Bool) : Void + { + if (n < 1) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if ((!m_owned) || (m_data == null) || (n > m_data.length)) + { + n = BigIntHelper.clp2(n); + if (preserve && (m_data != null)) + { + var newData = new Vector(n); + for (i in 0 ... m_count) + { + newData.set(i, m_data.get(i)); + } + m_data = newData; + } + else + { + m_data = new Vector(n); + } + } + m_owned = true; + } + + private function new() + { + super(); + } + + private static function fromInt(other : Int) : MutableBigInt_ + { + var c = BigInt_.getCachedValue(other); + if (c != null) + { + return fromBigInt(c); + } + var r = new MutableBigInt_(); + r.ensureCapacity(1, false); + r.m_data.set(0, other); + r.m_count = 1; + return r; + } + + private static function fromBigInt(other : BigInt_) : MutableBigInt_ + { + // TODO: this will be problematic if `other` is actually a MutableBigInt_ + var r = new MutableBigInt_(); // unowned + r.m_data = other.m_data; + r.m_count = other.m_count; + return r; + } + + private var m_owned : Bool = false; + + private static var s_testAllocation : Bool = false; + private static var s_debugAllocationPadding : Int = 0; + + //----------------------------------------------------------------------- + // Static helpers + //----------------------------------------------------------------------- + + private function _setFromHex(value : String, signed : Bool) : Void + { + if (value == null) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + var index = value.length; + if (index <= 0) + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + var extra : Int = signed ? 0 : 1; + ensureCapacity(((index + 7) >> 3) + extra, false); + var pos = -1; + var bit : Int = 32; + var c : Int = 0; + while (index > 0) + { + c = value.charCodeAt(--index); + if ((48 <= c) && (c <= 57)) + { + c -= 48; + } + else if ((65 <= c) && (c <= 70)) + { + c -= 55; + } + else if ((97 <= c) && (c <= 102)) + { + c -= 87; + } + else if (c == 32) + { + continue; + } + else + { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if (bit >= 32) + { + m_data.set(++pos, 0); + bit = 0; + } + m_data.set(pos, m_data.get(pos) | (c << bit)); + bit += 4; + } + // Sign extend + m_count = pos + 1; + if (signed) + { + c = ((c & 8) != 0) ? 15 : 0; + while (bit < 32) + { + m_data.set(pos, m_data.get(pos) | (c << bit)); + bit += 4; + } + } + else if (m_data.get(pos) < 0) + { + m_data.set(m_count++, 0); + } + compact(); + } + + @:noCompletion + private static inline function multiplyAssignInt2(a : MutableBigInt_, b : Int) : Void + { + var r = new MutableBigInt_(); + BigIntArithmetic.multiplyInt(r, a, b); + a.copy(r); + } + + @:noCompletion + private static inline function multiplyAssign2(a : MutableBigInt_, b : BigInt_) : Void + { + var r = new MutableBigInt_(); + BigIntArithmetic.multiply(r, a, b); + a.copy(r); + } + + @:noCompletion + private static inline function divideAssignInt2(a : MutableBigInt_, b : Int) : Void + { + var q = new MutableBigInt_(); + BigIntArithmetic.divideInt(a, b, q); + a.copy(q); + } + + @:noCompletion + private static inline function divideAssign2(a : MutableBigInt_, b : BigInt_) : Void + { + var q = new MutableBigInt_(); + BigIntArithmetic.divide(a, b, q, null); + a.copy(q); + } + + @:noCompletion + private static inline function modulusAssignInt2(a : MutableBigInt_, b : Int) : Void + { + var q = new MutableBigInt_(); + var r = BigIntArithmetic.divideInt(a, b, q); + a.setFromInt(r); + } + + @:noCompletion + private static inline function modulusAssign2(a : MutableBigInt_, b : BigInt_) : Void + { + var q = new MutableBigInt_(); + var r = new MutableBigInt_(); + BigIntArithmetic.divide(a, b, q, r); + a.copy(r); + } + + @:noCompletion + private static inline function arithmeticShiftLeftAssign2(a : MutableBigInt_, b : Int) : Void + { + BigIntArithmetic.arithmeticShiftLeft(a, a, b); + } + + @:noCompletion + private static inline function arithmeticShiftRightAssign2(a : MutableBigInt_, b : Int) : Void + { + BigIntArithmetic.arithmeticShiftRight(a, a, b); + } +} From d502605324c36d3899ee9a6d5f3ea6515eea7596 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 10 Jul 2022 17:52:57 +0300 Subject: [PATCH 002/134] Add BigInt test and allow unit package --- std/haxe/math/bigint/BigInt_.hx | 1 + std/haxe/math/bigint/MutableBigInt_.hx | 1 + tests/unit/src/unit/TestBigInt.hx | 2331 ++++++++++++++++++++++++ 3 files changed, 2333 insertions(+) create mode 100644 tests/unit/src/unit/TestBigInt.hx diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 4df03b5f0ad..a0d5049eb03 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -25,6 +25,7 @@ package haxe.math.bigint; import haxe.ds.Vector; import haxe.io.Bytes; +@:allow(unit) @:allow(haxe.math.bigint) class BigInt_ { diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index da88e51bee9..1e31f13be9a 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -27,6 +27,7 @@ import haxe.math.bigint.BigIntHelper; import haxe.ds.Vector; import haxe.io.Bytes; +@:allow(unit) @:allow(haxe.math.bigint) class MutableBigInt_ extends BigInt_ { diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx new file mode 100644 index 00000000000..2c28ae26a3c --- /dev/null +++ b/tests/unit/src/unit/TestBigInt.hx @@ -0,0 +1,2331 @@ +package unit; + +import haxe.PosInfos; +import haxe.math.bigint.MultiwordArithmetic; +import haxe.math.bigint.MutableBigInt_; +import haxe.math.bigint.BigInt_; +import haxe.ds.Vector; +import haxe.io.Bytes; +import haxe.math.bigint.BigIntArithmetic; +import haxe.math.bigint.BigIntExceptions; +import haxe.math.bigint.BigIntTools; +import haxe.math.bigint.MutableBigInt; +import haxe.math.bigint.BigInt; + +class TestBigInt extends Test { + public function testBigInt():Void { + MutableBigInt_.s_testAllocation = false; + bigIntAllChecks(); + + MutableBigInt_.s_testAllocation = true; + MutableBigInt_.s_debugAllocationPadding = 0; + bigIntAllChecks(); + + MutableBigInt_.s_testAllocation = true; + MutableBigInt_.s_debugAllocationPadding = 1; + bigIntAllChecks(); + } + + private function bigIntAllChecks():Void { + bigIntWorkOverlapsDividendDoesntDestroyDividend(); + bigIntSetFromBigEndianBytesUnsignedWithLengthAndOffset(); + bigIntSetFromBytesUnsigned(); + bigIntSetFromUnsignedIntsReusing(); + bigIntSetFromUnsignedInts(); + bigIntCompare(); + bigIntMultiplicationAndDivisionSemantics(); + bigIntMultiplicationAndDivision(); + bigIntEquality(); + bigIntAdditionAndSubtraction(); + bigIntAddAssignDoesntClobber(); + bigIntNegate(); + bigIntFromString(); + bigIntArithmeticShiftLeftAssignDoesntClobber(); + bigIntArithmeticShiftRightAssignDoesntClobber(); + bigIntArithmeticShiftLeft(); + bigIntIsZero(); + bigIntSign(); + bigIntSetFromIntWithLargeLength(); + bigIntHexStrings(); + bigIntDecimalStrings(); + } + + public function bigIntWorkOverlapsDividendDoesntDestroyDividend():Void { + // Test work overlaps dividend doesn't destroy dividend + var dividend:MutableBigInt = 0; + var divisor:MutableBigInt = 1; + var quotient:MutableBigInt = 0; + var remainder:MutableBigInt = 0; + try { + BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + eq("00000000", dividend.toHex()); + } + + public function bigIntSetFromBigEndianBytesUnsignedWithLengthAndOffset():Void { + // test set from big endian by test unsigned with length and offset + var t:MutableBigInt = 0; + t.setFromBigEndianBytesUnsigned(Bytes.ofHex("812345"), 0, 1); + eq("129", t.toString()); + t.setFromBigEndianBytesUnsigned(Bytes.ofHex("812345"), 1, 1); + eq("35", t.toString()); + } + + public function bigIntSetFromBytesUnsigned():Void { + // test set from bytes unsigned + eq(BigInt.ZERO.toHex(), MutableBigInt.fromBigEndianBytesUnsigned(Bytes.alloc(0)).toHex()); + eq(BigInt.ZERO.toHex(), MutableBigInt.fromLittleEndianBytesUnsigned(Bytes.alloc(0)).toHex()); + checkSetFromBytesUnsigned("81"); + checkSetFromBytesUnsigned("8123"); + checkSetFromBytesUnsigned("812345"); + checkSetFromBytesUnsigned("81234567"); + checkSetFromBytesUnsigned("8123456789"); + checkSetFromBytesUnsigned("8123456789ab"); + checkSetFromBytesUnsigned("8123456789abcd"); + checkSetFromBytesUnsigned("8123456789abcdef"); + checkSetFromBytesUnsigned("8123456789abcdef01"); + checkSetFromBytesUnsigned("8123456789abcdef0123"); + checkSetFromBytesUnsigned("8123456789abcdef012345"); + checkSetFromBytesUnsigned("8123456789abcdef01234567"); + + checkSetFromBytesUnsigned("572e4794"); + } + + public function bigIntSetFromUnsignedIntsReusing():Void { + // set from unsigned ints reusing + var t1:MutableBigInt = 0; + var v1 = new Vector(3); + v1[0] = 0; + v1[1] = 1; + v1[2] = -2147483648; + t1.setFromUnsignedInts(v1, 3); + eq(BigInt.fromHexUnsigned("80000000 00000001 00000000").toHex(), t1.toHex()); + v1[1] = -2147483648; + t1.setFromUnsignedInts(v1, 2); + eq(BigInt.fromHexUnsigned("80000000 00000000").toHex(), t1.toHex()); + } + + function bigIntSetFromUnsignedInts():Void { + // set from unsigned ints + checkSetFromUnsignedInts("00000000", [0]); + checkSetFromUnsignedInts("7fffffff", [2147483647]); + checkSetFromUnsignedInts("80000000", [-2147483648]); + checkSetFromUnsignedInts("ffffffff", [-1]); + + checkSetFromUnsignedInts("00000000 55555555", [1431655765, 0]); + checkSetFromUnsignedInts("7fffffff 55555555", [1431655765, 2147483647]); + checkSetFromUnsignedInts("80000000 55555555", [1431655765, -2147483648]); + checkSetFromUnsignedInts("ffffffff 55555555", [1431655765, -1]); + + checkSetFromUnsignedInts("00000000 aaaaaaaa", [-1431655766, 0]); + checkSetFromUnsignedInts("7fffffff aaaaaaaa", [-1431655766, 2147483647]); + checkSetFromUnsignedInts("80000000 aaaaaaaa", [-1431655766, -2147483648]); + checkSetFromUnsignedInts("ffffffff aaaaaaaa", [-1431655766, -1]); + } + + private function checkSetFromBytesUnsigned(hex:String):Void { + var t:MutableBigInt = 0; + t.setFromBigEndianBytesUnsigned(Bytes.ofHex(hex)); + eq(BigInt.fromHexUnsigned(hex).toHex(), t.toHex()); + + var sb = new StringBuf(); + var i = hex.length; + while (i >= 2) { + i -= 2; + sb.addChar(hex.charCodeAt(i)); + sb.addChar(hex.charCodeAt(i + 1)); + } + t.setFromLittleEndianBytesUnsigned(Bytes.ofHex(sb.toString())); + eq(BigInt.fromHexUnsigned(hex).toHex(), t.toHex()); + } + + private function checkSetFromUnsignedInts(hex:String, arr:Array):Void { + var v = Vector.fromArrayCopy(arr); + var t:MutableBigInt = 0; + t.setFromUnsignedInts(v, v.length); + eq(BigInt.fromHexUnsigned(hex).toHex(), t.toHex()); + } + + public function bigIntCompare():Void { + // equality, single-word + checkCompareInt(0, 0, 0); + checkCompareInt(0, 1, 1); + checkCompareInt(0, -1, -1); + checkCompareInt(0, -2147483648, -2147483648); + checkCompareInt(0, 2147483647, 2147483647); + + // equality, multi-word + checkCompare(0, BigInt.fromHex("12345678 9abcdef0"), BigInt.fromHex("12345678 9abcdef0")); + checkCompare(0, BigInt.fromHex("f2345678 9abcdef0"), BigInt.fromHex("f2345678 9abcdef0")); + checkCompare(0, BigInt.fromHex("12345678 9abcdef0 12345678"), BigInt.fromHex("12345678 9abcdef0 12345678")); + checkCompare(0, BigInt.fromHex("f2345678 9abcdef0 12345678"), BigInt.fromHex("f2345678 9abcdef0 12345678")); + + // less than, single-word + checkCompareInt(-1, 0, 1); + checkCompareInt(-1, 1, 2); + checkCompareInt(-1, -1, 0); + checkCompareInt(-1, -2, -1); + checkCompareInt(-1, -2147483648, 2147483647); + checkCompareInt(-1, -2147483648, -2147483647); + checkCompareInt(-1, -2147483648, 0); + checkCompareInt(-1, 0, 2147483647); + checkCompareInt(-1, 1, 2147483647); + checkCompareInt(-1, 2147483646, 2147483647); + checkCompareInt(-1, -1, 2147483647); + + // less than, multi-word, same length + checkCompare(-1, BigInt.fromHex("12345678 9abcdeef"), BigInt.fromHex("12345678 9abcdef0")); + checkCompare(-1, BigInt.fromHex("12345677 9abcdef0"), BigInt.fromHex("12345678 9abcdef0")); + checkCompare(-1, BigInt.fromHex("f2345678 9abcdef0"), BigInt.fromHex("12345678 9abcdef0")); + checkCompare(-1, BigInt.fromHex("f2345678 9abcdeef"), BigInt.fromHex("f2345678 9abcdef0")); + checkCompare(-1, BigInt.fromHex("f2345677 9abcdef0"), BigInt.fromHex("f2345678 9abcdef0")); + + // less than, multi-word, different length + checkCompare(-1, BigInt.fromHex("12345678 9abcdef0"), BigInt.fromHex("00000001 12345678 9abcdef0")); + checkCompare(-1, BigInt.fromHex("f2345678 9abcdef0"), BigInt.fromHex("00000001 12345678 9abcdef0")); + checkCompare(-1, BigInt.fromHex("fffffffe 12345678 9abcdef0"), BigInt.fromHex("12345678 9abcdef0")); + checkCompare(-1, BigInt.fromHex("fffffffe 12345678 9abcdef0"), BigInt.fromHex("f2345678 9abcdef0")); + + // greater than, single-word + checkCompareInt(1, 1, 0); + checkCompareInt(1, 2, 1); + checkCompareInt(1, 0, -1); + checkCompareInt(1, -1, -2); + checkCompareInt(1, 2147483647, 2147483646); + checkCompareInt(1, -2147483647, -2147483648); + + // greater than, multi-word, same length + checkCompare(1, BigInt.fromHex("12345678 9abcdef1"), BigInt.fromHex("12345678 9abcdef0")); + checkCompare(1, BigInt.fromHex("12345679 9abcdef0"), BigInt.fromHex("12345678 9abcdef0")); + checkCompare(1, BigInt.fromHex("12345678 9abcdef0"), BigInt.fromHex("f2345678 9abcdef0")); + checkCompare(1, BigInt.fromHex("f2345678 9abcdef1"), BigInt.fromHex("f2345678 9abcdef0")); + checkCompare(1, BigInt.fromHex("f2345679 9abcdef0"), BigInt.fromHex("f2345678 9abcdef0")); + + // greater than, multi-word, different length + checkCompare(1, BigInt.fromHex("00000001 12345678 9abcdef0"), BigInt.fromHex("12345678 9abcdef0")); + checkCompare(1, BigInt.fromHex("00000001 12345678 9abcdef0"), BigInt.fromHex("f2345678 9abcdef0")); + checkCompare(1, BigInt.fromHex("12345678 9abcdef0"), BigInt.fromHex("fffffffe 12345678 9abcdef0")); + checkCompare(1, BigInt.fromHex("f2345678 9abcdef0"), BigInt.fromHex("fffffffe 12345678 9abcdef0")); + + checkCompare(1, BigInt.fromHex("00000001 ffffffff"), BigInt.fromHex("00000001 00000000")); + } + + private function checkCompareInt(expected:Int, a:Int, b:Int):Void { + var an:BigInt = a; + var am:MutableBigInt = a; + switch (expected) { + case -1: + f(a == b); + f(am == b); + f(an == b); + t(a != b); + t(am != b); + t(an != b); + t(a < b); + t(am < b); + t(an < b); + t(a <= b); + t(am <= b); + t(an <= b); + f(a > b); + f(am > b); + f(an > b); + f(a >= b); + f(am >= b); + f(an >= b); + case 0: + t(a == b); + t(am == b); + t(an == b); + f(a != b); + f(am != b); + f(an != b); + f(a < b); + f(am < b); + f(an < b); + t(a <= b); + t(am <= b); + t(an <= b); + f(a > b); + f(am > b); + f(an > b); + t(a >= b); + t(am >= b); + t(an >= b); + case 1: + f(a == b); + f(am == b); + f(an == b); + t(a != b); + t(am != b); + t(an != b); + f(a < b); + f(am < b); + f(an < b); + f(a <= b); + f(am <= b); + f(an <= b); + t(a > b); + t(am > b); + t(an > b); + t(a >= b); + t(am >= b); + t(an >= b); + } + checkCompare(expected, BigInt.fromInt(a), BigInt.fromInt(b)); + } + + private function checkCompare(expected:Int, a:BigInt, b:BigInt):Void { + checkCompareSingle(expected, a, b); + checkCompareSingle(-expected, -a, -b); + if ((expected != 0) && (a.sign() == b.sign())) { + var s:Int = (a.sign() << 1) + 1; + checkCompareSingle(-s, -a, b); + checkCompareSingle(s, a, -b); + } + } + + private function checkCompareSingle(expected:Int, a:BigInt, b:BigInt):Void { + eq(expected, BigIntArithmetic.compare(a, b)); + if (expected == 0) { + eq(expected, BigIntArithmetic.compare(b, a)); + } else { + eq(-expected, BigIntArithmetic.compare(b, a)); + } + + var am:MutableBigInt = a; + var bm:MutableBigInt = b; + switch (expected) { + case -1: + f(a == b); + f(am == b); + f(a == bm); + f(am == bm); + t(a != b); + t(am != b); + t(a != bm); + t(am != bm); + t(a < b); + t(am < b); + t(a < bm); + t(am < bm); + t(a <= b); + t(am <= b); + t(a <= bm); + t(am <= bm); + f(a > b); + f(am > b); + f(a > bm); + f(am > bm); + f(a >= b); + f(am >= b); + f(a >= bm); + f(am >= bm); + case 0: + t(a == b); + t(am == b); + t(a == bm); + t(am == bm); + f(a != b); + f(am != b); + f(a != bm); + f(am != bm); + f(a < b); + f(am < b); + f(a < bm); + f(am < bm); + t(a <= b); + t(am <= b); + t(a <= bm); + t(am <= bm); + f(a > b); + f(am > b); + f(a > bm); + f(am > bm); + t(a >= b); + t(am >= b); + t(a >= bm); + t(am >= bm); + case 1: + f(a == b); + f(am == b); + f(a == bm); + f(am == bm); + t(a != b); + t(am != b); + t(a != bm); + t(am != bm); + f(a < b); + f(am < b); + f(a < bm); + f(am < bm); + f(a <= b); + f(am <= b); + f(a <= bm); + f(am <= bm); + t(a > b); + t(am > b); + t(a > bm); + t(am > bm); + t(a >= b); + t(am >= b); + t(a >= bm); + t(am >= bm); + } + } + + public function bigIntMultiplicationAndDivisionSemantics():Void { + var dividend:MutableBigInt = 0; + var divisor:MutableBigInt; + var quotient:MutableBigInt; + var remainder:MutableBigInt = 0; + var remainderInt:Int; + + // if result of multiplication is an input, should throw an exception + var a:MutableBigInt = 2; + try { + BigIntArithmetic.multiply(a, a, BigInt.fromInt(2)); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + BigIntArithmetic.multiply(a, BigInt.fromInt(2), a); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + // division by zero should throw exception + try { + BigInt.fromInt(1) / 0; + } catch (e:String) { + eq(BigIntExceptions.DIVISION_BY_ZERO, e); + } + try { + BigInt.fromInt(0) / 0; + } catch (e:String) { + eq(BigIntExceptions.DIVISION_BY_ZERO, e); + } + + // Multiplication of same inputs is ok + var b:MutableBigInt = 0; + BigIntArithmetic.multiply(b, a, a); + eq("4", b.toString()); + + // check quotient overlaps with dividend, divisor < 65536 case + quotient = 12345; + remainderInt = BigIntArithmetic.divideInt(quotient, 11, quotient); + eq("1122", quotient.toString()); + eq(3, remainderInt); + quotient = 12345; + BigIntArithmetic.divide(quotient, BigInt.fromInt(11), quotient, remainder); + eq("1122", quotient.toString()); + eq("3", remainder.toString()); + + // check quotient overlaps with dividend, divisor >= 65536 case + quotient = 721018; + divisor = 65537; + BigIntArithmetic.divide(quotient, divisor, quotient, remainder); + eq("11", quotient.toString()); + eq("111", remainder.toString()); + + // check quotient overlaps with dividend, special case 1 + quotient = 0; + divisor = 11; + BigIntArithmetic.divide(quotient, divisor, quotient, remainder); + eq("0", quotient.toString()); + eq("0", remainder.toString()); + + // check quotient overlaps with dividend, special case 2 + quotient = 7; + BigIntArithmetic.divide(quotient, BigInt.fromInt(1), quotient, remainder); + eq("7", quotient.toString()); + eq("0", remainder.toString()); + + // check quotient overlaps with dividend, special case 3 + quotient = 11; + BigIntArithmetic.divide(quotient, BigInt.fromHex("1 00000000"), quotient, remainder); + eq("0", quotient.toString()); + eq("11", remainder.toString()); + + // check quotient overlaps with divisor, divisor < 65536 case + quotient = 11; + BigIntArithmetic.divide(BigInt.fromInt(12345), quotient, quotient, remainder); + eq("1122", quotient.toString()); + eq("3", remainder.toString()); + + // check quotient overlaps with divisor, divisor >= 65536 case + quotient = 65537; + BigIntArithmetic.divide(BigInt.fromInt(721018), quotient, quotient, remainder); + eq("11", quotient.toString()); + eq("111", remainder.toString()); + + // check quotient overlaps with divisor, special case 1 + quotient = 10; + BigIntArithmetic.divide(BigInt.fromInt(0), quotient, quotient, remainder); + eq("0", quotient.toString()); + eq("0", remainder.toString()); + + // check quotient overlaps with divisor, special case 2 + quotient = 1; + BigIntArithmetic.divide(BigInt.fromInt(7), quotient, quotient, remainder); + eq("7", quotient.toString()); + eq("0", remainder.toString()); + + // check quotient overlaps with divisor, special case 3 + quotient = BigInt.fromHex("1 00000000"); + BigIntArithmetic.divide(BigInt.fromInt(11), quotient, quotient, remainder); + eq("0", quotient.toString()); + eq("11", remainder.toString()); + + // check remainder overlaps with dividend, divisor < 65536 case + remainder = 12345; + BigIntArithmetic.divide(remainder, BigInt.fromInt(11), quotient, remainder); + eq("1122", quotient.toString()); + eq("3", remainder.toString()); + + // check remainder overlaps with dividend, divisor >= 65536 case + remainder = 721018; + BigIntArithmetic.divide(remainder, BigInt.fromInt(65537), quotient, remainder); + eq("11", quotient.toString()); + eq("111", remainder.toString()); + + // check remainder overlaps with dividend, special case 1 + remainder = 0; + BigIntArithmetic.divide(remainder, BigInt.fromInt(10), quotient, remainder); + eq("0", quotient.toString()); + eq("0", remainder.toString()); + + // check remainder overlaps with dividend, special case 2 + remainder = 7; + BigIntArithmetic.divide(remainder, BigInt.fromInt(1), quotient, remainder); + eq("7", quotient.toString()); + eq("0", remainder.toString()); + + // check remainder overlaps with dividend, special case 3 + remainder = 11; + BigIntArithmetic.divide(remainder, BigInt.fromHex("1 00000000"), quotient, remainder); + eq("0", quotient.toString()); + eq("11", remainder.toString()); + + // check remainder overlaps with divisor, divisor < 65536 case + remainder = 11; + BigIntArithmetic.divide(BigInt.fromInt(12345), remainder, quotient, remainder); + eq("1122", quotient.toString()); + eq("3", remainder.toString()); + + // check remainder overlaps with divisor, divisor >= 65536 case + remainder = 65537; + BigIntArithmetic.divide(BigInt.fromInt(721018), remainder, quotient, remainder); + eq("11", quotient.toString()); + eq("111", remainder.toString()); + + // check remainder overlaps with divisor, special case 1 + remainder = 10; + BigIntArithmetic.divide(BigInt.fromInt(0), remainder, quotient, remainder); + eq("0", quotient.toString()); + eq("0", remainder.toString()); + + // check remainder overlaps with divisor, special case 2 + remainder = 1; + BigIntArithmetic.divide(BigInt.fromInt(7), remainder, quotient, remainder); + eq("7", quotient.toString()); + eq("0", remainder.toString()); + + // check remainder overlaps with divisor, special case 3 + remainder = BigInt.fromHex("1 00000000"); + BigIntArithmetic.divide(BigInt.fromInt(11), remainder, quotient, remainder); + eq("0", quotient.toString()); + eq("11", remainder.toString()); + + // quotient and remainder cannot be the same object + try { + BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), quotient, quotient); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // quotient cannot be null + try { + BigIntArithmetic.divideInt(BigInt.fromInt(1), 10, null); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), null, remainder); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // remainder can be null + BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), quotient, null); + eq("0", quotient.toString()); + + // dividend and divisor can be the same object + divisor = 10; + BigIntArithmetic.divide(divisor, divisor, quotient, remainder); + eq("1", quotient.toString()); + eq("0", remainder.toString()); + + // work may not overlap any input + try { + BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + BigIntArithmetic.divide(dividend, divisor, quotient, remainder, divisor); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + BigIntArithmetic.divide(dividend, divisor, quotient, remainder, quotient); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + BigIntArithmetic.divide(dividend, divisor, quotient, remainder, remainder); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + } + + public function bigIntMultiplicationAndDivision():Void { + checkLinearEqInt(BigInt.fromInt(0), 0, BigInt.fromInt(0), 0); + checkLinearEqInt(BigInt.fromInt(0), 1, BigInt.fromInt(0), 0); + checkLinearEqInt(BigInt.fromInt(0), 0, BigInt.fromInt(1), 0); + checkLinearEqInt(BigInt.fromInt(0), 100, BigInt.fromInt(0), 0); + checkLinearEqInt(BigInt.fromInt(1), 1, BigInt.fromInt(1), 0); + checkLinearEqInt(BigInt.fromInt(1), 2, BigInt.fromInt(0), 1); + checkLinearEqInt(BigInt.fromInt(2), 1, BigInt.fromInt(2), 0); + checkLinearEqInt(BigInt.fromInt(2), 3, BigInt.fromInt(0), 2); + checkLinearEqInt(BigInt.fromInt(3), 3, BigInt.fromInt(1), 0); + checkLinearEqInt(BigInt.fromInt(4), 2, BigInt.fromInt(2), 0); + checkLinearEqInt(BigInt.fromInt(4), 3, BigInt.fromInt(1), 1); + checkLinearEqInt(BigInt.fromInt(5), 3, BigInt.fromInt(1), 2); + checkLinearEqInt(BigInt.fromInt(6), 3, BigInt.fromInt(2), 0); + checkLinearEqInt(BigInt.fromInt(6), 2, BigInt.fromInt(3), 0); + checkLinearEqInt(BigInt.fromHex("12A05F2001"), 81, BigInt.fromInt(987654321), 0); + + checkLinearEq(BigInt.fromHex("0 fffffffe 00000001"), BigInt.fromHex("0 ffffffff"), BigInt.fromHex("0 ffffffff"), + BigInt.fromInt(0)); // exercises qhat = 65536 + checkLinearEq(BigInt.fromHex("00003fff c0000000 7fff8000 00000000"), BigInt.fromHex("7fff8000 00000000"), BigInt.fromHex("00008000 00000001"), + BigInt.fromInt(0)); + + checkLinearEqInt(BigInt.fromInt(2147483647), 1, BigInt.fromInt(2147483647), 0); + checkLinearEqInt(BigInt.fromInt(2147483647), 10, BigInt.fromInt(214748364), 7); + checkLinearEqInt(BigInt.fromInt(2147483647), 100, BigInt.fromInt(21474836), 47); + checkLinearEqInt(BigInt.fromInt(2147483647), 1000, BigInt.fromInt(2147483), 647); + checkLinearEqInt(BigInt.fromInt(2147483647), 10000, BigInt.fromInt(214748), 3647); + checkLinearEqInt(BigInt.fromInt(2147483647), 100000, BigInt.fromInt(21474), 83647); // exercises rhat >= 65536 + checkLinearEqInt(BigInt.fromInt(2147483647), 1000000, BigInt.fromInt(2147), 483647); + checkLinearEqInt(BigInt.fromInt(2147483647), 10000000, BigInt.fromInt(214), 7483647); + checkLinearEqInt(BigInt.fromInt(2147483647), 100000000, BigInt.fromInt(21), 47483647); + checkLinearEqInt(BigInt.fromInt(2147483647), 1000000000, BigInt.fromInt(2), 147483647); + + checkLinearEqInt(BigInt.fromInt(2147483647), 2147483647, BigInt.fromInt(1), 0); // exercises use of uninitialized quotient data + + checkLinearEqInt(BigInt.fromHex("100000000"), 1, BigInt.fromHex("100000000"), 0); + checkLinearEqInt(BigInt.fromHex("100000000"), 10, BigInt.fromInt(429496729), 6); + checkLinearEqInt(BigInt.fromHex("100000000"), 100, BigInt.fromInt(42949672), 96); + checkLinearEqInt(BigInt.fromHex("100000000"), 1000, BigInt.fromInt(4294967), 296); + checkLinearEqInt(BigInt.fromHex("100000000"), 10000, BigInt.fromInt(429496), 7296); + checkLinearEqInt(BigInt.fromHex("100000000"), 100000, BigInt.fromInt(42949), 67296); // exercises rhat >= 65536 + checkLinearEqInt(BigInt.fromHex("100000000"), 1000000, BigInt.fromInt(4294), 967296); + checkLinearEqInt(BigInt.fromHex("100000000"), 10000000, BigInt.fromInt(429), 4967296); + checkLinearEqInt(BigInt.fromHex("100000000"), 100000000, BigInt.fromInt(42), 94967296); + checkLinearEqInt(BigInt.fromHex("100000000"), 1000000000, BigInt.fromInt(4), 294967296); + checkLinearEq(BigInt.fromHex("100000000"), BigInt.fromHex("2540BE400"), BigInt.fromInt(0), BigInt.fromHex("100000000")); + + checkLinearEqInt(BigInt.fromHex("08000"), 1, BigInt.fromHex("08000"), 0); + checkLinearEqInt(BigInt.fromHex("080000000"), 1, BigInt.fromHex("080000000"), 0); + checkLinearEqInt(BigInt.fromHex("0800000000000"), 1, BigInt.fromHex("0800000000000"), 0); + checkLinearEqInt(BigInt.fromHex("08000000000000000"), 1, BigInt.fromHex("08000000000000000"), 0); + checkLinearEqInt(BigInt.fromHex("10001"), 2, BigInt.fromHex("08000"), 1); + checkLinearEqInt(BigInt.fromHex("100000001"), 2, BigInt.fromHex("080000000"), 1); + checkLinearEqInt(BigInt.fromHex("1000000000001"), 2, BigInt.fromHex("0800000000000"), 1); + checkLinearEqInt(BigInt.fromHex("10000000000000001"), 2, BigInt.fromHex("08000000000000000"), 1); + + checkLinearEqInt(BigInt.fromHex("0ffffffff"), 1, BigInt.fromHex("0ffffffff"), 0); + checkLinearEqInt(BigInt.fromHex("0ffffffffffffffff"), 1, BigInt.fromHex("0ffffffffffffffff"), 0); + checkLinearEqInt(BigInt.fromHex("0ffffffffffffffffffffffff"), 1, BigInt.fromHex("0ffffffffffffffffffffffff"), 0); + checkLinearEqInt(BigInt.fromHex("0ffffffff"), 2, BigInt.fromHex("07fffffff"), 1); + checkLinearEqInt(BigInt.fromHex("0ffffffffffffffff"), 2, BigInt.fromHex("07fffffffffffffff"), 1); + checkLinearEqInt(BigInt.fromHex("0ffffffffffffffffffffffff"), 2, BigInt.fromHex("07fffffffffffffffffffffff"), 1); + + // exercise quotient with high bit set when length of divisor == length of dividend and divisor >= 65536 + checkLinearEq(BigInt.fromHex("4000000000000000"), BigInt.fromHex("080000000"), BigInt.fromHex("080000000"), + BigInt.fromInt(0)); // exercises uninitialized work data + checkLinearEq(BigInt.fromHex("4000000080000000"), BigInt.fromHex("080000001"), BigInt.fromHex("080000000"), BigInt.fromInt(0)); + checkLinearEq(BigInt.fromHex("4000000100000000"), BigInt.fromHex("080000001"), BigInt.fromHex("080000000"), BigInt.fromHex("080000000")); + checkLinearEq(BigInt.fromHex("40000000ffffffff"), BigInt.fromHex("080000001"), BigInt.fromHex("080000000"), BigInt.fromHex("7fffffff")); + checkLinearEq(BigInt.fromHex("4000000100000001"), BigInt.fromHex("080000001"), BigInt.fromHex("080000001"), BigInt.fromInt(0)); + + checkLinearEq(BigInt.fromHex("08000"), BigInt.fromHex("0800000001"), BigInt.fromHex("0"), BigInt.fromHex("08000")); + // these exercise the qhat reduction path + checkLinearEq(BigInt.fromHex("080000000"), BigInt.fromHex("080000001"), BigInt.fromHex("0"), BigInt.fromHex("080000000")); + checkLinearEq(BigInt.fromHex("0800080010000"), BigInt.fromHex("080000001"), BigInt.fromHex("10000"), BigInt.fromHex("080000000")); + checkLinearEq(BigInt.fromHex("0800100010001"), BigInt.fromHex("080000001"), BigInt.fromHex("10001"), BigInt.fromHex("080000000")); + checkLinearEq(BigInt.fromHex("08000000180000000"), BigInt.fromHex("080000001"), BigInt.fromHex("100000000"), BigInt.fromHex("080000000")); + checkLinearEq(BigInt.fromHex("08000000200000001"), BigInt.fromHex("080000001"), BigInt.fromHex("100000001"), BigInt.fromHex("080000000")); + + // this exercises long division with a quotient with high bit set + checkLinearEq(BigInt.fromHex("08000000180000000"), BigInt.fromHex("100000000"), BigInt.fromHex("080000001"), BigInt.fromHex("080000000")); + + // these exercise the "add back" path + checkLinearEq(BigInt.fromHex("7fff800000000000"), BigInt.fromHex("0800000000001"), BigInt.fromHex("0fffe"), BigInt.fromHex("7fffffff0002")); + checkLinearEq(BigInt.fromHex("7fffffff800000010000000000000000"), BigInt.fromHex("0800000008000000200000005"), BigInt.fromHex("0fffffffd"), + BigInt.fromHex("080000000800000010000000f")); + + checkLinearEq(BigInt.fromInt(1), BigInt.fromHex("100000000"), BigInt.fromInt(0), BigInt.fromInt(1)); + } + + private function checkLinearEqInt(y:BigInt, a:Int, x:BigInt, b:Int):Void { + // checks that y = ax + b + eq(y.toHex(), (a * x + b).toHex()); + eq(y.toHex(), (x * a + b).toHex()); + eq(y.toHex(), (b + a * x).toHex()); + eq(y.toHex(), (b + x * a).toHex()); + checkMultiplyInt(x, a, y - b); + if (a != 0) { + checkDivInt(y, a, x, b); + } + checkLinearEq(y, BigInt.fromInt(a), x, BigInt.fromInt(b)); + } + + private function checkLinearEq(y:BigInt, a:BigInt, x:BigInt, b:BigInt):Void { + // checks that y = ax + b + eq(y.toHex(), (a * x + b).toHex()); + eq(y.toHex(), (x * a + b).toHex()); + eq(y.toHex(), (b + a * x).toHex()); + eq(y.toHex(), (b + x * a).toHex()); + checkMultiply(a, x, y - b); + if (!a.isZero()) { + checkDiv(y, a, x, b); + } + // if we have n / d = q + r / d, then n / q = n * d / (n - r) + var y_b = y - b; + if (!y_b.isZero()) { + var q2 = y * a / y_b; + var r2 = y - q2 * x; + checkDiv(y, x, q2, r2); + } + } + + private function checkMultiplyInt(a:BigInt, b:Int, expected:BigInt):Void { + var am:MutableBigInt = a; + eq(expected.toHex(), (a * b).toHex()); + eq(expected.toHex(), (am * b).toHex()); + am *= b; + eq(expected.toHex(), am.toHex()); + + checkMultiply(a, BigInt.fromInt(b), expected); + } + + private function checkMultiply(a:BigInt, b:BigInt, expected:BigInt):Void { + checkMultiplyCommute(a, b, expected); + checkMultiplyCommute(-a, b, -expected); + checkMultiplyCommute(a, -b, -expected); + checkMultiplyCommute(-a, -b, expected); + } + + private function checkMultiplyCommute(a:BigInt, b:BigInt, expected:BigInt):Void { + checkMultiplySingle(a, b, expected); + checkMultiplySingle(b, a, expected); + } + + private function checkMultiplySingle(a:BigInt, b:BigInt, expected:BigInt):Void { + var am:MutableBigInt = a; + var bm:MutableBigInt = b; + + eq(expected.toHex(), (a * b).toHex()); + eq(expected.toHex(), (am * b).toHex()); + eq(expected.toHex(), (a * bm).toHex()); + eq(expected.toHex(), (am * bm).toHex()); + + am = a; + am *= b; + eq(expected.toHex(), am.toHex()); + am = a; + am *= bm; + eq(expected.toHex(), am.toHex()); + } + + private function checkDivInt(dividend:BigInt, divisor:Int, expectedQuotient:BigInt, expectedRemainder:Int):Void { + var dividendM:MutableBigInt = dividend; + + var quotient:MutableBigInt = 0; + var remainder:Int; + remainder = BigIntArithmetic.divideInt(dividend, divisor, quotient); + eq(expectedRemainder, remainder); + eq(expectedQuotient.toHex(), quotient.toHex()); + + eq(expectedQuotient.toHex(), (dividend / divisor).toHex()); + eq(expectedQuotient.toHex(), (dividendM / divisor).toHex()); + eq(expectedRemainder, (dividend % divisor)); + eq(expectedRemainder, (dividendM % divisor)); + + dividendM = dividend; + dividendM /= divisor; + eq(expectedQuotient.toHex(), dividendM.toHex()); + dividendM = dividend; + dividendM %= divisor; + eq(Std.string(expectedRemainder), dividendM.toString()); + + checkDiv(dividend, BigInt.fromInt(divisor), expectedQuotient, BigInt.fromInt(expectedRemainder)); + } + + private function checkDiv(dividend:BigInt, divisor:BigInt, expectedQuotient:BigInt, expectedRemainder:BigInt):Void { + checkDivSingle(dividend, divisor, expectedQuotient, expectedRemainder); + checkDivSingle(dividend, -divisor, -expectedQuotient, expectedRemainder); + checkDivSingle(-dividend, divisor, -expectedQuotient, -expectedRemainder); + checkDivSingle(-dividend, -divisor, expectedQuotient, -expectedRemainder); + } + + private function checkDivSingle(dividend:BigInt, divisor:BigInt, expectedQuotient:BigInt, expectedRemainder:BigInt):Void { + var dividendM:MutableBigInt = dividend; + var divisorM:MutableBigInt = divisor; + + var quotient:MutableBigInt = 0; + var remainder:MutableBigInt = 0; + BigIntArithmetic.divide(dividend, divisor, quotient, remainder); + eq(expectedRemainder.toHex(), remainder.toHex()); + eq(expectedQuotient.toHex(), quotient.toHex()); + + eq(dividend.toHex(), (quotient * divisor + remainder).toHex()); + + eq(expectedQuotient.toHex(), (dividend / divisor).toHex()); + eq(expectedQuotient.toHex(), (dividendM / divisor).toHex()); + eq(expectedQuotient.toHex(), (dividend / divisorM).toHex()); + eq(expectedQuotient.toHex(), (dividendM / divisorM).toHex()); + eq(expectedRemainder.toHex(), (dividend % divisor).toHex()); + eq(expectedRemainder.toHex(), (dividendM % divisor).toHex()); + eq(expectedRemainder.toHex(), (dividend % divisorM).toHex()); + eq(expectedRemainder.toHex(), (dividendM % divisorM).toHex()); + + dividendM = dividend; + dividendM /= divisor; + eq(expectedQuotient.toHex(), dividendM.toHex()); + dividendM = dividend; + dividendM /= divisorM; + eq(expectedQuotient.toHex(), dividendM.toHex()); + dividendM = dividend; + dividendM %= divisor; + eq(expectedRemainder.toHex(), dividendM.toHex()); + dividendM = dividend; + dividendM %= divisorM; + eq(expectedRemainder.toHex(), dividendM.toHex()); + } + + public function bigIntEquality():Void { + checkEquality(BigInt.fromInt(0), BigInt.fromInt(0), true); + checkEquality(BigInt.fromInt(0), BigInt.fromInt(1), false); + checkEquality(BigInt.fromInt(1), BigInt.fromInt(1), true); + checkEquality(BigInt.fromInt(0x12345678), BigInt.fromInt(0x12345678), true); + checkEquality(BigInt.fromInt(0x12345678), BigInt.fromInt(0x12345670), false); + checkEquality(BigInt.fromHex("1234567800000000"), BigInt.fromInt(0), false); + checkEquality(BigInt.fromHex("1234567800000000"), BigInt.fromHex("1234567800000000"), true); + checkEquality(BigInt.fromHex("1234567800000000"), BigInt.fromHex("11234567800000000"), false); + checkEquality(BigInt.fromHex("1234567800000000"), BigInt.fromHex("123456780000000"), false); + } + + private function checkEquality(a:BigInt, b:BigInt, expected:Bool):Void { + eq(expected, a == b); + eq(expected, b == a); + + var a1:MutableBigInt = a; + eq(expected, a1 == b); + eq(expected, b == a1); + + var b1:MutableBigInt = b; + eq(expected, a == b1); + eq(expected, b1 == a); + + eq(expected, a1 == b1); + eq(expected, b1 == a1); + } + + public function bigIntAdditionAndSubtraction():Void { + checkAddInt(BigInt.fromInt(0), 0, BigInt.fromInt(0)); + checkAddInt(BigInt.fromInt(0), 1, BigInt.fromInt(1)); + checkAddInt(BigInt.fromInt(1), 1, BigInt.fromInt(2)); + checkAddInt(BigInt.fromInt(-1), 0, BigInt.fromInt(-1)); + checkAddInt(BigInt.fromInt(-1), 1, BigInt.fromInt(0)); + checkAddInt(BigInt.fromInt(-1), 2, BigInt.fromInt(1)); + checkAddInt(BigInt.fromInt(-1), -1, BigInt.fromInt(-2)); + + checkAddInt(BigInt.fromHex("000000000000000007fffffff"), 1, BigInt.fromHex("0000000000000000080000000")); + checkAddInt(BigInt.fromHex("0000000007fffffffffffffff"), 1, BigInt.fromHex("0000000008000000000000000")); + checkAddInt(BigInt.fromHex("07fffffffffffffffffffffff"), 1, BigInt.fromHex("0800000000000000000000000")); + checkAddInt(BigInt.fromHex("0ffffffffffffffffffffffff"), 1, BigInt.fromHex("1000000000000000000000000")); + checkAddInt(BigInt.fromHex("0fffffffffffffffeffffffff"), 1, BigInt.fromHex("0ffffffffffffffff00000000")); + + checkAdd(BigInt.fromHex("0ffffffffffffffff00000000"), BigInt.fromHex("100000000"), BigInt.fromHex("1000000000000000000000000")); + checkAdd(BigInt.fromHex("0ffffffff0000000000000000"), BigInt.fromHex("10000000000000000"), BigInt.fromHex("1000000000000000000000000")); + + checkAdd(BigInt.fromHex("12345678"), BigInt.fromHex("11111111"), BigInt.fromHex("23456789")); + checkAdd(BigInt.fromHex("1234567812345678"), BigInt.fromHex("1111111111111111"), BigInt.fromHex("2345678923456789")); + checkAdd(BigInt.fromHex("123456781234567812345678"), BigInt.fromHex("111111111111111111111111"), BigInt.fromHex("234567892345678923456789")); + checkAdd(BigInt.fromHex("1234567812345678"), BigInt.fromHex("11111111"), BigInt.fromHex("1234567823456789")); + checkAdd(BigInt.fromHex("123456781234567812345678"), BigInt.fromHex("11111111"), BigInt.fromHex("123456781234567823456789")); + checkAdd(BigInt.fromHex("1234567812345678"), BigInt.fromHex("1111111100000000"), BigInt.fromHex("2345678912345678")); + checkAdd(BigInt.fromHex("123456781234567812345678"), BigInt.fromHex("111111110000000000000000"), BigInt.fromHex("234567891234567812345678")); + checkAdd(BigInt.fromHex("123456781234567812345678"), BigInt.fromHex("111111110000000011111111"), BigInt.fromHex("234567891234567823456789")); + } + + private function checkAddInt(a:BigInt, b:Int, expected:BigInt):Void { + var am:MutableBigInt = a; + eq(expected.toHex(), (a + b).toHex()); + eq(expected.toHex(), (am + b).toHex()); + am += b; + eq(expected.toHex(), am.toHex()); + + checkAdd(a, BigInt.fromInt(b), expected); + } + + private function checkAdd(a:BigInt, b:BigInt, expected:BigInt):Void { + checkAddCommute(a, b, expected); + checkAddCommute(-a, -b, -expected); + checkAddCommute(expected, -a, b); + checkAddCommute(expected, -b, a); + } + + private function checkAddCommute(a:BigInt, b:BigInt, expected:BigInt):Void { + checkAddSingle(a, b, expected); + checkAddSingle(b, a, expected); + } + + private function checkAddSingle(a:BigInt, b:BigInt, expected:BigInt):Void { + var am:MutableBigInt = a; + var bm:MutableBigInt = b; + var em:MutableBigInt = expected; + + // addition + eq(expected.toHex(), (a + b).toHex()); + eq(expected.toHex(), (am + bm).toHex()); + eq(expected.toHex(), (am + b).toHex()); + eq(expected.toHex(), (a + bm).toHex()); + am = a; + am += b; + eq(expected.toHex(), am.toHex()); + am = a; + am += bm; + eq(expected.toHex(), am.toHex()); + + // subtraction + eq(a.toHex(), (expected - b).toHex()); + eq(a.toHex(), (expected - bm).toHex()); + eq(a.toHex(), (em - b).toHex()); + eq(a.toHex(), (em - bm).toHex()); + em = expected; + em -= b; + eq(a.toHex(), em.toHex()); + em = expected; + em -= bm; + eq(a.toHex(), em.toHex()); + } + + public function bigIntAddAssignDoesntClobber():Void { + var a:BigInt = BigInt.fromInt(1); + var b:MutableBigInt = a; + b += 1; + eq("1", a.toString()); + eq("2", b.toString()); + } + + public function bigIntNegate():Void { + eq("0", (-BigInt.fromInt(0)).toString()); + eq(BigInt.fromInt(-1).toString(), (-BigInt.fromInt(1)).toString()); + eq("1", (-BigInt.fromInt(-1)).toString()); + eq(BigInt.fromInt(-100).toString(), (-BigInt.fromInt(100)).toString()); + eq("100", (-BigInt.fromInt(-100)).toString()); + eq(BigInt.fromHex("080000000").toHex(), (-BigInt.fromInt(-2147483648)).toHex()); + eq(BigInt.fromInt(-2147483648).toHex(), (-BigInt.fromHex("080000000")).toHex()); + eq(BigInt.fromHex("08000000000000000").toHex(), (-BigInt.fromHex("8000000000000000")).toHex()); + eq(BigInt.fromHex("8000000000000000").toHex(), (-BigInt.fromHex("08000000000000000")).toHex()); + eq(BigInt.fromHex("edcba98800000000").toHex(), (-BigInt.fromHex("1234567800000000")).toHex()); + } + + public function bigIntFromString():Void { + try { + var x = BigInt.fromString(null); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + var x = BigInt.fromString(""); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + var x = BigInt.fromString("-"); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + var x = BigInt.fromString(" 0"); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + var x = BigInt.fromString("0 "); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + eq("0", BigInt.fromString("0").toString()); + eq("1", BigInt.fromString("1").toString()); + eq("ffffffff", BigInt.fromString("-1").toHex()); + eq("100", BigInt.fromString("100").toString()); + eq(BigInt.fromInt(-100).toHex(), BigInt.fromString("-100").toHex()); + eq("7fffffff", BigInt.fromString("2147483647").toHex()); + eq("7fffffff", BigInt.fromString("02147483647").toHex()); + eq(BigInt.fromInt(-2147483648).toHex(), BigInt.fromString("-2147483648").toHex()); + eq(BigInt.fromInt(-2147483648).toHex(), BigInt.fromString("-02147483648").toHex()); + eq(BigInt.fromHex("080000000").toHex(), BigInt.fromString("2147483648").toHex()); + eq(BigInt.fromHex("f7fffffff").toHex(), BigInt.fromString("-2147483649").toHex()); + + var a:MutableBigInt = 1; + for (i in 0...96) { + eq(a.toHex(), BigInt.fromString(s_powersOfTwo[i]).toHex()); + eq((-a).toHex(), BigInt.fromString("-" + s_powersOfTwo[i]).toHex()); + a <<= 1; + } + } + + public function bigIntArithmeticShiftLeftAssignDoesntClobber():Void { + var a:BigInt = BigInt.fromInt(1); + var b:MutableBigInt = a; + b <<= 1; + eq("1", a.toString()); + eq("2", b.toString()); + } + + public function bigIntArithmeticShiftRightAssignDoesntClobber():Void { + var a:BigInt = BigInt.fromInt(2); + var b:MutableBigInt = a; + b >>= 1; + eq("2", a.toString()); + eq("1", b.toString()); + } + + public function bigIntArithmeticShiftLeft():Void { + asl(BigInt.ZERO, 0, BigInt.ZERO); + asl(BigInt.ZERO, 1, BigInt.ZERO); + asl(BigInt.ZERO, 128, BigInt.ZERO); + asl(BigInt.ZERO, 2147483647, BigInt.ZERO); + + var a:MutableBigInt = BigInt.ZERO; + try { + a <<= -1; + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + a << -1; + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + BigInt.ONE << -1; + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + asl(BigInt.ONE, 1, BigInt.fromInt(2)); + asl(BigInt.ONE, 31, BigInt.fromHex("080000000")); + asl(BigInt.fromHex("080000000"), 1, BigInt.fromHex("100000000")); + + var sb = new StringBuf(); + sb.add("1"); + for (i in 0...100) { + asl(BigInt.ONE, i * 4, BigInt.fromHex(sb.toString())); + sb.add("0"); + } + sb = new StringBuf(); + sb.add("08"); + for (i in 0...100) { + asl(BigInt.ONE, i * 4 + 3, BigInt.fromHex(sb.toString())); + sb.add("0"); + } + + asl(BigInt.fromHex("08000000180000000"), 15, BigInt.fromHex("40000000c00000000000")); + } + + private function asl(a:BigInt, b:Int, expected:BigInt):Void { + var result:MutableBigInt = 0; + BigIntArithmetic.arithmeticShiftLeft(result, a, b); + eq(expected.toHex(), result.toHex()); + eq(expected.toHex(), (a << b).toHex()); + result = a; + result <<= b; + eq(expected.toHex(), result.toHex()); + + BigIntArithmetic.arithmeticShiftRight(result, expected, b); + eq(a.toHex(), result.toHex()); + eq(a.toHex(), (expected >> b).toHex()); + result = expected; + result >>= b; + eq(a.toHex(), result.toHex()); + } + + public function bigIntIsZero():Void { + t(BigInt.ZERO.isZero()); + f(BigInt.ONE.isZero()); + f(BigInt.NEGATIVE_ONE.isZero()); + } + + public function bigIntSign():Void { + eq(0, BigInt.ZERO.sign()); + eq(0, BigInt.ONE.sign()); + eq(-1, BigInt.NEGATIVE_ONE.sign()); + eq(0, BigInt.fromInt(2147483647).sign()); + eq(-1, BigInt.fromInt(-2147483648).sign()); + } + + public function bigIntSetFromIntWithLargeLength():Void { + var x:MutableBigInt = BigInt.fromHex("1 00000000"); + x <<= 1; // make it owned + var y:MutableBigInt_ = x; + y.setFromInt(11); + eq("11", y.toString()); + } + + public function bigIntHexStrings():Void { + eq("00000000", BigInt.ZERO.toHex()); + eq("00000001", BigInt.ONE.toHex()); + eq("ffffffff", BigInt.NEGATIVE_ONE.toHex()); + + eq("0", BigInt.fromHex("0").toString()); + eq("1", BigInt.fromHex("1").toString()); + eq(BigInt.fromInt(-1).toHex(), BigInt.fromHex("f").toHex()); + + try { + var x = BigInt.fromHex(null); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + var x = BigInt.fromHex(""); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + var x = BigInt.fromHex("0q0"); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + var sb = new StringBuf(); + var v = 1; + for (i in 0...32) { + for (j in 0...8) { + var c:Int = (v < 10) ? (v + 48) : (v - 10 + 65); + v = (v + 1) & 0x0f; + sb.addChar(c); + } + checkHexString(sb.toString()); + } + + eq("2147483647", BigInt.fromHex("07fffffff").toString()); + eq("-2147483648", BigInt.fromHex("f80000000").toString()); + + eq("-2147483648", BigInt.fromHex("8000 0000").toString()); + + eq(BigInt.fromHexSigned("080000000").toHex(), BigInt.fromHexUnsigned("80000000").toHex()); + eq(BigInt.fromHexSigned("0ffffffff").toHex(), BigInt.fromHexUnsigned("ffffffff").toHex()); + eq(BigInt.fromHexSigned("0f80000000").toHex(), BigInt.fromHexUnsigned("f80000000").toHex()); + } + + private function checkHexString(value:String):Void { + var bi = BigInt.fromHex(value); + eq(value.toLowerCase(), bi.toHex().toLowerCase()); + var by = bi.toBytes(); + eq(by.toHex().toLowerCase(), bi.toHex().toLowerCase()); + } + + public function bigIntDecimalStrings():Void { + eq("0", BigInt.ZERO.toString()); + checkDecString("1"); + checkDecString("99"); + checkDecString("2147483647"); + checkDecString("2147483648"); + checkDecString("2147483649"); + checkDecString("4294967295"); + checkDecString("4294967296"); + checkDecString("4294967297"); + for (i in 0...s_powersOfTwo.length) { + var s = s_powersOfTwo[i]; + checkDecString(s); + checkDecString("9" + s); + checkDecString(s + "9"); + checkDecString("9" + s + "9"); + } + var s = "1"; + for (i in 0...100) { + s = s + "0"; + checkDecString(s); + } + eq("1512366075204170929049582354406559215", BigInt.fromHex("01234567 89abcdef 01234567 89abcdef").toString()); + } + + private function checkDecString(value:String):Void { + var biPos = BigInt.fromString(value); + eq(value, biPos.toString()); + value = "-" + value; + var biNeg = BigInt.fromString(value); + eq(value, biNeg.toString()); + } + + public function testBigIntTools() { + // Test makes copy + var a:MutableBigInt = BigInt.fromHex("123456789abcdef0"); + var b = BigIntTools.parseValueUnsigned(a); + eq("123456789abcdef0", b.toHex()); + a.clear(); + eq("123456789abcdef0", b.toHex()); + + // Test is null + var m_a:MutableBigInt = null; + t(BigIntTools.isNull(m_a)); + m_a = 0; + f(BigIntTools.isNull(m_a)); + + // Cast from dynamic + eq(null, BigIntTools.castFrom(null)); + eq(null, BigIntTools.castFrom("whee")); + eq(null, BigIntTools.castFrom(5)); + var a1:BigInt = 0; + eq(a1.toHex(), BigIntTools.castFrom(a1).toHex()); + var b1:MutableBigInt = 0; + eq(b1.toHex(), BigIntTools.castFrom(b1).toHex()); + var c:BigInt_ = new BigInt_(); + eq(c, BigIntTools.castFrom(c)); + var d:MutableBigInt_ = new MutableBigInt_(); + eq(cast d, BigIntTools.castFrom(d)); + + // Test is bigint + f(BigIntTools.isBigInt("whee")); + f(BigIntTools.isBigInt(5)); + t(BigIntTools.isBigInt(a1)); + t(BigIntTools.isBigInt(b1)); + + // Test parse + eq(BigInt.fromHex("123456789abcdef0").toHex(), BigIntTools.parseValueUnsigned("0x123456789abcdef0").toHex()); + eq(BigInt.fromString("12345678901234567890").toHex(), BigIntTools.parseValueUnsigned("12345678901234567890").toHex()); + eq(BigInt.fromHex("080000000").toHex(), BigIntTools.parseValueUnsigned("0x80000000").toHex()); + } + + public function testMultiwordArithmeticCompare():Void { + checkCompareMultiwordArithmetic(0, fromInt(0), fromInt(0)); + checkCompareMultiwordArithmetic(-1, fromInt(0), fromInt(1)); + checkCompareMultiwordArithmetic(-1, fromInt(1), fromInt(2)); + checkCompareMultiwordArithmetic(-1, fromInt(-1), fromInt(0)); + checkCompareMultiwordArithmetic(-1, fromInt(-2), fromInt(-1)); + checkCompareMultiwordArithmetic(-1, fromInt(2147483646), fromInt(2147483647)); + checkCompareMultiwordArithmetic(-1, fromInt(-2147483648), fromInt(2147483647)); + checkCompareMultiwordArithmetic(-1, fromInt(-2147483648), fromInt(-2147483647)); + checkCompareMultiwordArithmetic(-1, fromInt(-2147483648), fromInt(-1)); + + checkCompareMultiwordArithmetic(1, fromHex("00000001 80000000", 2), fromHex("00000001 7fffffff", 2)); + checkCompareMultiwordArithmetic(1, fromHex("00000001 ffffffff", 2), fromHex("00000001 00000000", 2)); + } + + private function checkCompareMultiwordArithmetic(expected:Int, a:Vector, b:Vector):Void { + eq(expected, MultiwordArithmetic.compareSigned(a, b, a.length)); + eq(-expected, MultiwordArithmetic.compareSigned(b, a, a.length)); + var as:Int = (a[a.length - 1]) < 0 ? -1 : 1; + var bs:Int = (b[b.length - 1]) < 0 ? -1 : 1; + var s:Int = as * bs; + eq(expected * s, MultiwordArithmetic.compareUnsigned(a, b, a.length)); + eq(-expected * s, MultiwordArithmetic.compareUnsigned(b, a, a.length)); + } + + public function testMultiwordArithmeticArithmeticShiftRight():Void { + MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 1); + try { + MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // result and input overlap + var result = fromHex("12345678 9abcdef0"); + MultiwordArithmetic.arithmeticShiftRight(result, result, 2, 4); + assertEqualsBI(fromHex("01234567 89abcdef"), result); + + // result and input overlap and shift is 0 + var result = fromHex("12345678 9abcdef0"); + MultiwordArithmetic.arithmeticShiftRight(result, result, 2, 0); + assertEqualsBI(fromHex("12345678 9abcdef0"), result); + + checkASR(fromHex("00000000 00000000", 2), fromHex("00000000 00000000", 2), 1); + checkASR(fromHex("00000000 00000000", 2), fromHex("00000000 00000001", 2), 1); + checkASR(fromHex("00000000 00000001", 2), fromHex("00000000 00000002", 2), 1); + checkASR(fromHex("00000000 80000000", 2), fromHex("00000001 00000001", 2), 1); + checkASR(fromHex("ffffffff ffffffff", 2), fromHex("ffffffff ffffffff", 2), 1); + checkASR(fromHex("ffffffff ffffffff", 2), fromHex("ffffffff ffffffff", 2), 31); + checkASR(fromHex("12345678 9abcdef0", 2), fromHex("12345678 9abcdef0", 2), 0); + checkASR(fromHex("01234567 89abcdef", 2), fromHex("12345678 9abcdef0", 2), 4); + checkASR(fromHex("00000001 23456789", 2), fromHex("12345678 9abcdef0", 2), 28); + checkASR(fromHex("00000000 40000000", 2), fromHex("00000000 80000000", 2), 1); + checkASR(fromHex("c0000000 00000000", 2), fromHex("80000000 00000000", 2), 1); + } + + public function checkASR(expected:Vector, input:Vector, shift:Int):Void { + var result = new Vector(input.length); + MultiwordArithmetic.arithmeticShiftRight(result, input, input.length, shift); + assertEqualsBI(expected, result); + } + + public function testMultiwordArithmeticLogicalShiftRight():Void { + MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 1); + try { + MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.logicalShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // result and input overlap + var result = fromHex("12345678 9abcdef0"); + MultiwordArithmetic.logicalShiftRight(result, result, 2, 4); + assertEqualsBI(fromHex("01234567 89abcdef"), result); + + // result and input overlap and shift is 0 + var result = fromHex("12345678 9abcdef0"); + MultiwordArithmetic.logicalShiftRight(result, result, 2, 0); + assertEqualsBI(fromHex("12345678 9abcdef0"), result); + + checkShiftRight(fromHex("00000000 00000000", 2), fromHex("00000000 00000000", 2), 1); + checkShiftRight(fromHex("00000000 00000000", 2), fromHex("00000000 00000001", 2), 1); + checkShiftRight(fromHex("00000000 00000001", 2), fromHex("00000000 00000002", 2), 1); + checkShiftRight(fromHex("00000000 80000000", 2), fromHex("00000001 00000001", 2), 1); + checkShiftRight(fromHex("7fffffff ffffffff", 2), fromHex("ffffffff ffffffff", 2), 1); + checkShiftRight(fromHex("00000001 ffffffff", 2), fromHex("ffffffff ffffffff", 2), 31); + checkShiftRight(fromHex("12345678 9abcdef0", 2), fromHex("12345678 9abcdef0", 2), 0); + checkShiftRight(fromHex("01234567 89abcdef", 2), fromHex("12345678 9abcdef0", 2), 4); + checkShiftRight(fromHex("00000001 23456789", 2), fromHex("12345678 9abcdef0", 2), 28); + } + + public function checkShiftRight(expected:Vector, input:Vector, shift:Int):Void { + var result = new Vector(input.length); + MultiwordArithmetic.logicalShiftRight(result, input, input.length, shift); + assertEqualsBI(expected, result); + } + + public function testMultiwordArithmeticExtendUnsigned():Void { + var result = new Vector(4); + + fill(result); + MultiwordArithmetic.extendUnsigned(result, 2, fromInt(0), 1); + assertEqualsBI(0, result, 2); + eq(0xdeadbeef, result[2]); + + fill(result); + MultiwordArithmetic.extendUnsigned(result, 2, fromInt(-2147483648), 1); + assertEqualsBI(-2147483648, result, 2); + eq(0xdeadbeef, result[2]); + + fill(result); + MultiwordArithmetic.extendUnsigned(result, 2, fromInt(-1), 1); + assertEqualsBI(-1, result, 2); + eq(0xdeadbeef, result[2]); + + fill(result); + MultiwordArithmetic.extendUnsigned(result, 4, fromHex("1 00000000"), 2); + assertEqualsBI(fromHex("1 00000000", 4), result, 4); + + fill(result); + MultiwordArithmetic.setFromIntUnsigned(result, 1, 123); + MultiwordArithmetic.extendUnsigned(result, 4, result, 1); + assertEqualsBI(123, result, 4); + } + + public function testMultiwordArithmeticSubtractSemantics():Void { + // All inputs can be the same + var result = fromInt(11); + MultiwordArithmetic.subtract(result, result, result, 1); + assertEqualsBI(0, result); + + // Bounds + MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 2); + try { + MultiwordArithmetic.subtract(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + } + + public function testMultiwordArithmeticSubtractCarry():Void { + var result = new Vector(2); + var c:Int; + + eq(0, MultiwordArithmetic.subtract(result, fromInt(0), fromInt(0), 1)); + eq(1, MultiwordArithmetic.subtract(result, fromInt(0), fromInt(1), 1)); + eq(0, MultiwordArithmetic.subtract(result, fromInt(-1), fromInt(-1), 1)); + eq(1, MultiwordArithmetic.subtract(result, fromInt(-2), fromInt(-1), 1)); + eq(0, MultiwordArithmetic.subtract(result, fromInt(-2147483648), fromInt(-2147483648), 1)); + eq(1, MultiwordArithmetic.subtract(result, fromInt(2147483647), fromInt(-2147483648), 1)); + + eq(0, MultiwordArithmetic.subtract(result, fromHex("00000000 00000001", 2), fromInt(1, 2), 2)); + eq(0, MultiwordArithmetic.subtract(result, fromHex("00000001 00000000", 2), fromInt(1, 2), 2)); + eq(1, MultiwordArithmetic.subtract(result, fromHex("00000000 00000000", 2), fromInt(1, 2), 2)); + } + + public function testMultiwordArithmeticAddSemantics():Void { + // All inputs can be the same + var result = fromInt(11); + MultiwordArithmetic.add(result, result, result, 1); + assertEqualsBI(22, result); + + // Bounds + MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 2); + try { + MultiwordArithmetic.add(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + } + + public function testMultiwordArithmeticAddCarry():Void { + var result = new Vector(2); + var c:Int; + + eq(0, MultiwordArithmetic.add(result, fromInt(0), fromInt(0), 1)); + eq(0, MultiwordArithmetic.add(result, fromInt(0), fromInt(1), 1)); + eq(0, MultiwordArithmetic.add(result, fromInt(1), fromInt(2147483647), 1)); + eq(0, MultiwordArithmetic.add(result, fromInt(1), fromInt(-2), 1)); + eq(1, MultiwordArithmetic.add(result, fromInt(1), fromInt(-1), 1)); + eq(1, MultiwordArithmetic.add(result, fromInt(-2147483648), fromInt(-2147483648), 1)); + + eq(0, MultiwordArithmetic.add(result, fromHex("ffffffff fffffffe"), fromInt(1, 2), 2)); + eq(0, MultiwordArithmetic.add(result, fromHex("fffffffe ffffffff"), fromInt(1, 2), 2)); + eq(1, MultiwordArithmetic.add(result, fromHex("ffffffff ffffffff"), fromInt(1, 2), 2)); + } + + public function testMultiwordArithmeticAddAndSubtract():Void { + checkAddMultiwordArithmetic(fromInt(0), fromInt(0), fromInt(0)); + checkAddMultiwordArithmetic(fromInt(1), fromInt(0), fromInt(1)); + checkAddMultiwordArithmetic(fromInt(2), fromInt(1), fromInt(1)); + checkAddMultiwordArithmetic(fromInt(-1), fromInt(-1), fromInt(0)); + checkAddMultiwordArithmetic(fromInt(0), fromInt(-1), fromInt(1)); + checkAddMultiwordArithmetic(fromInt(1), fromInt(-1), fromInt(2)); + checkAddMultiwordArithmetic(fromInt(-2), fromInt(-1), fromInt(-1)); + + checkAddMultiwordArithmetic(fromHex("00000000 00000000 80000000", 3), fromHex("00000000 00000000 7fffffff", 3), fromInt(1, 3)); + checkAddMultiwordArithmetic(fromHex("00000000 80000000 00000000", 3), fromHex("00000000 7fffffff ffffffff", 3), fromInt(1, 3)); + checkAddMultiwordArithmetic(fromHex("80000000 00000000 00000000", 3), fromHex("7fffffff ffffffff ffffffff", 3), fromInt(1, 3)); + checkAddMultiwordArithmetic(fromHex("ffffffff ffffffff 00000000", 3), fromHex("ffffffff fffffffe ffffffff", 3), fromInt(1, 3)); + checkAddMultiwordArithmetic(fromHex("00000001 00000000 00000000 00000000", 4), fromHex("00000000 ffffffff ffffffff ffffffff", 4), + fromHex("00000000 00000000 00000001", 4)); + checkAddMultiwordArithmetic(fromHex("00000001 00000000 00000000 00000000", 4), fromHex("00000000 ffffffff ffffffff 00000000", 4), + fromHex("00000000 00000001 00000000", 4)); + checkAddMultiwordArithmetic(fromHex("00000001 00000000 00000000 00000000", 4), fromHex("00000000 ffffffff 00000000 00000000", 4), + fromHex("00000001 00000000 00000000", 4)); + + checkAddMultiwordArithmetic(fromHex("23456789"), fromHex("12345678"), fromHex("11111111")); + checkAddMultiwordArithmetic(fromHex("2345678923456789"), fromHex("1234567812345678"), fromHex("1111111111111111")); + checkAddMultiwordArithmetic(fromHex("234567892345678923456789"), fromHex("123456781234567812345678"), fromHex("111111111111111111111111")); + + checkAddMultiwordArithmetic(fromHex("1234567823456789"), fromHex("1234567812345678"), fromHex("11111111", 2)); + checkAddMultiwordArithmetic(fromHex("123456781234567823456789"), fromHex("123456781234567812345678"), fromHex("11111111", 3)); + checkAddMultiwordArithmetic(fromHex("2345678912345678"), fromHex("1234567812345678"), fromHex("1111111100000000")); + checkAddMultiwordArithmetic(fromHex("234567891234567812345678"), fromHex("123456781234567812345678"), fromHex("111111110000000000000000")); + checkAddMultiwordArithmetic(fromHex("234567891234567823456789"), fromHex("123456781234567812345678"), fromHex("111111110000000011111111")); + } + + private function checkAddMultiwordArithmetic(expected:Vector, a:Vector, b:Vector):Void { + var negExpected = new Vector(expected.length); + var negA = new Vector(a.length); + var negB = new Vector(b.length); + + MultiwordArithmetic.negate(negExpected, expected, expected.length); + MultiwordArithmetic.negate(negA, a, a.length); + MultiwordArithmetic.negate(negB, b, b.length); + + checkAddCommuteMultiwordArithmetic(expected, a, b); + checkAddCommuteMultiwordArithmetic(negExpected, negA, negB); + checkAddCommuteMultiwordArithmetic(b, expected, negA); + checkAddCommuteMultiwordArithmetic(a, expected, negB); + } + + private function checkAddCommuteMultiwordArithmetic(expected:Vector, a:Vector, b:Vector):Void { + checkAddSingleMultiwordArithmetic(expected, a, b); + checkAddSingleMultiwordArithmetic(expected, b, a); + } + + private function checkAddSingleMultiwordArithmetic(expected:Vector, a:Vector, b:Vector):Void { + var result = new Vector(expected.length); + var c = MultiwordArithmetic.add(result, a, b, expected.length); + assertEqualsBI(expected, result); + c = MultiwordArithmetic.subtract(result, expected, b, expected.length); + assertEqualsBI(a, result); + } + + public function testMultiwordArithmeticNegate():Void { + checkNegate(fromInt(0), fromInt(0)); + checkNegate(fromInt(1), fromInt(-1)); + checkNegate(fromInt(100), fromInt(-100)); + checkNegate(fromHex("80000000"), fromInt(-2147483648)); + checkNegate(fromHex("8000000000000000"), fromHex("8000000000000000")); + checkNegate(fromHex("edcba98800000000"), fromHex("1234567800000000")); + } + + private function checkNegate(expected:Vector, value:Vector):Void { + var temp = new Vector(value.length); + MultiwordArithmetic.negate(temp, value, value.length); + assertEqualsBI(expected, temp); + MultiwordArithmetic.negate(temp, temp, temp.length); + assertEqualsBI(value, temp); + } + + public function testMultiwordArithmeticToDecimal():Void { + var value = new Vector(1); + value[0] = 0; + eq("0", MultiwordArithmetic.toDecimalUnsigned(value, value.length)); + eq("0", MultiwordArithmetic.toDecimalSigned(value, value.length)); + + checkDecStringMultiwordArithmetic("1"); + checkDecStringMultiwordArithmetic("99"); + checkDecStringMultiwordArithmetic("2147483647"); + checkDecStringMultiwordArithmetic("2147483648"); + checkDecStringMultiwordArithmetic("2147483649"); + checkDecStringMultiwordArithmetic("4294967295"); + checkDecStringMultiwordArithmetic("4294967296"); + checkDecStringMultiwordArithmetic("4294967297"); + // TODO + /*for (i in 0 ... s_powersOfTwo.length) + { + var s = s_powersOfTwo[i]; + checkDecStringMultiwordArithmetic(s); + checkDecStringMultiwordArithmetic("9" + s); + checkDecStringMultiwordArithmetic(s + "9"); + checkDecStringMultiwordArithmetic("9" + s + "9"); + }*/ + var s = "1"; + for (i in 0...100) { + s = s + "0"; + checkDecStringMultiwordArithmetic(s); + } + eq("1512366075204170929049582354406559215", MultiwordArithmetic.toDecimalUnsigned(fromHex("01234567 89abcdef 01234567 89abcdef"), 4)); + } + + private function checkDecStringMultiwordArithmetic(value:String):Void { + // TODO + /*var biPos = fromString(value); + assertEquals(value, biPos.toString()); + value = "-" + value; + var biNeg = fromString(value); + assertEquals(value, biNeg.toString()); */ + } + + public function testMultiwordArithmeticIsZero():Void { + eq(true, MultiwordArithmetic.isZero(fromInt(0), 1)); + eq(false, MultiwordArithmetic.isZero(fromInt(1), 1)); + eq(false, MultiwordArithmetic.isZero(fromInt(-1), 1)); + } + + public function testMultiwordArithmeticSetFromHexUnsignedInitializesWordsWithoutHexDigits():Void { + var result = new Vector(4); + MultiwordArithmetic.setFromHexUnsigned(result, 4, "abc"); + eq(2748, result[0]); + eq(0, result[1]); + eq(0, result[2]); + eq(0, result[3]); + } + + public function testMultiwordArithmeticSetFromHexUnsigned():Void { + var value = fromInt(0); + + try { + MultiwordArithmetic.setFromHexUnsigned(value, 1, null); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.setFromHexUnsigned(value, 1, ""); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.setFromHexUnsigned(null, 1, "0"); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.setFromHexUnsigned(value, 2, "0"); // buffer too small + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.setFromHexUnsigned(value, 1, "0g0"); // invalid char + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + value = new Vector(3); + f(MultiwordArithmetic.setFromHexUnsigned(value, 0, "0")); + f(MultiwordArithmetic.setFromHexUnsigned(value, 1, "1 00000000")); + f(MultiwordArithmetic.setFromHexUnsigned(value, 2, "1 00000000 00000000")); + t(MultiwordArithmetic.setFromHexUnsigned(value, 1, "00000000 00000000 000000cb")); + eq(203, value[0]); + + checkSetFromHexUnsigned("00000000", "0"); + checkSetFromHexUnsigned("0000000000000000", "0"); + checkSetFromHexUnsigned("000000000000000000000000", "0"); + + checkSetFromHexUnsigned("00000001", "1"); + checkSetFromHexUnsigned("0000000100000000", "1 00000000"); + checkSetFromHexUnsigned("000000000000000100000000", "1 00000000"); + + checkSetFromHexUnsigned("7fffffff", "7fffffff"); + checkSetFromHexUnsigned("7fffffffffffffff", "7fffffff ffffffff"); + checkSetFromHexUnsigned("7fffffffffffffffffffffff", "7fffffff ffffffff ffffffff"); + + checkSetFromHexUnsigned("80000000", "80000000"); + checkSetFromHexUnsigned("8000000000000000", "80000000 00000000"); + checkSetFromHexUnsigned("800000000000000000000000", "80000000 00000000 00000000"); + + checkSetFromHexUnsigned("ffffffff", "ffffffff"); + checkSetFromHexUnsigned("ffffffffffffffff", "ffffffff ffffffff"); + checkSetFromHexUnsigned("ffffffffffffffffffffffff", "ffffffff ffffffff ffffffff"); + checkSetFromHexUnsigned("0000000000000000ffffffff", "ffffffff"); + + checkSetFromHexUnsigned("00abcdef", "ABCDEF"); + checkSetFromHexUnsigned("00abcdef", "abcdef"); + } + + private function checkSetFromHexUnsigned(expected:String, input:String):Void { + var len:Int = (expected.length + 7) >> 3; + var result = new Vector(len); + t(MultiwordArithmetic.setFromHexUnsigned(result, len, input)); + var hex = MultiwordArithmetic.toHex(result, len); + eq(expected, hex); + } + + public function testMultiwordArithmeticMultiplySemantics():Void { + var result:Vector; + + // if result of multiplication is an input, should throw an exception + result = fromInt(2, 4); + try { + MultiwordArithmetic.multiplyUnsigned(result, result, 1, fromInt(2), 1); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.multiplyUnsigned(result, fromInt(2), 1, result, 1); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.multiplyIntUnsigned(result, result, 1, 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // Multiplication of same inputs is ok + var a = fromInt(2); + result = fromInt(0, 2); + MultiwordArithmetic.multiplyUnsigned(result, a, 1, a, 1); + assertEqualsBI(4, result); + + // check for result length too short + try { + MultiwordArithmetic.multiplyUnsigned(fromInt(0), fromInt(2), 1, fromInt(2), 1); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.multiplyIntUnsigned(fromInt(0), fromInt(2), 1, 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // check input lengths + try { + MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 0, fromInt(2), 1); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 1, fromInt(2), 0); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 2), fromInt(2), 0, 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // check input bounds + MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 2), 2, fromInt(2, 2), 2); + try { + MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 1), 2, fromInt(2, 2), 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 2), 2, fromInt(2, 1), 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 4), fromInt(2, 1), 2, 2); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + } + + public function testMultiwordArithmeticDivideSemantics():Void { + var dividend = fromInt(0); + var divisor:Vector; + var quotient:Vector; + var remainder = fromInt(0); + var remainderInt:Int; + var work = new Vector(10); + + // check quotient overlaps with dividend, divisor < 65536 case + quotient = fromInt(12345); + remainderInt = MultiwordArithmetic.divideIntUnsigned(quotient, quotient.length, 11, quotient, work); + assertEqualsBI(1122, quotient); + eq(3, remainderInt); + quotient = fromInt(12345); + MultiwordArithmetic.divideUnsigned(quotient, quotient.length, fromInt(11), 1, quotient, remainder, work); + assertEqualsBI(1122, quotient); + assertEqualsBI(3, remainder); + + // check quotient overlaps with dividend, divisor >= 65536 case + quotient = fromInt(721018); + divisor = fromInt(65537); + MultiwordArithmetic.divideUnsigned(quotient, quotient.length, divisor, divisor.length, quotient, remainder, work); + assertEqualsBI(11, quotient); + assertEqualsBI(111, remainder); + + // check quotient overlaps with dividend, special case 1 + quotient = fromInt(0); + divisor = fromInt(11); + MultiwordArithmetic.divideUnsigned(quotient, quotient.length, divisor, divisor.length, quotient, remainder, work); + assertEqualsBI(0, quotient); + assertEqualsBI(0, remainder); + + // check quotient overlaps with dividend, special case 2 + quotient = fromInt(7); + MultiwordArithmetic.divideUnsigned(quotient, quotient.length, fromInt(1), 1, quotient, remainder, work); + assertEqualsBI(7, quotient); + assertEqualsBI(0, remainder); + + // check quotient overlaps with dividend, special case 3 + quotient = fromInt(11); + remainder = fromInt(0, 2); + MultiwordArithmetic.divideUnsigned(quotient, quotient.length, fromHex("1 00000000"), 2, quotient, remainder, work); + assertEqualsBI(0, quotient); + assertEqualsBI(11, remainder); + + // check quotient overlaps with divisor, divisor < 65536 case + quotient = fromInt(11); + MultiwordArithmetic.divideUnsigned(fromInt(12345), 1, quotient, quotient.length, quotient, remainder, work); + assertEqualsBI(1122, quotient); + assertEqualsBI(3, remainder); + + // check quotient overlaps with divisor, divisor >= 65536 case + quotient = fromInt(65537); + MultiwordArithmetic.divideUnsigned(fromInt(721018), 1, quotient, quotient.length, quotient, remainder, work); + assertEqualsBI(11, quotient); + assertEqualsBI(111, remainder); + + // check quotient overlaps with divisor, special case 1 + quotient = fromInt(10); + MultiwordArithmetic.divideUnsigned(fromInt(0), 1, quotient, quotient.length, quotient, remainder, work); + assertEqualsBI(0, quotient); + assertEqualsBI(0, remainder); + + // check quotient overlaps with divisor, special case 2 + quotient = fromInt(1); + MultiwordArithmetic.divideUnsigned(fromInt(7), 1, quotient, quotient.length, quotient, remainder, work); + assertEqualsBI(7, quotient); + assertEqualsBI(0, remainder); + + // check quotient overlaps with divisor, special case 3 + quotient = fromHex("1 00000000"); + MultiwordArithmetic.divideUnsigned(fromInt(11), 1, quotient, quotient.length, quotient, remainder, work); + assertEqualsBI(0, quotient, 1); + assertEqualsBI(11, remainder); + + // check remainder overlaps with dividend, divisor < 65536 case + quotient = fromInt(0); + remainder = fromInt(12345); + MultiwordArithmetic.divideUnsigned(remainder, remainder.length, fromInt(11), 1, quotient, remainder, work); + assertEqualsBI(1122, quotient); + assertEqualsBI(3, remainder); + + // check remainder overlaps with dividend, divisor >= 65536 case + remainder = fromInt(721018); + MultiwordArithmetic.divideUnsigned(remainder, remainder.length, fromInt(65537), 1, quotient, remainder, work); + assertEqualsBI(11, quotient); + assertEqualsBI(111, remainder); + + // check remainder overlaps with dividend, special case 1 + remainder = fromInt(0); + MultiwordArithmetic.divideUnsigned(remainder, remainder.length, fromInt(10), 1, quotient, remainder, work); + assertEqualsBI(0, quotient); + assertEqualsBI(0, remainder); + + // check remainder overlaps with dividend, special case 2 + remainder = fromInt(7); + MultiwordArithmetic.divideUnsigned(remainder, remainder.length, fromInt(1), 1, quotient, remainder, work); + assertEqualsBI(7, quotient); + assertEqualsBI(0, remainder); + + // check remainder overlaps with dividend, special case 3 + remainder = fromInt(11, 2); + MultiwordArithmetic.divideUnsigned(remainder, 1, fromHex("1 00000000"), 2, quotient, remainder, work); + assertEqualsBI(0, quotient); + assertEqualsBI(11, remainder); + + // check remainder overlaps with divisor, divisor < 65536 case + remainder = fromInt(11); + MultiwordArithmetic.divideUnsigned(fromInt(12345), 1, remainder, remainder.length, quotient, remainder, work); + assertEqualsBI(1122, quotient); + assertEqualsBI(3, remainder); + + // check remainder overlaps with divisor, divisor >= 65536 case + remainder = fromInt(65537); + MultiwordArithmetic.divideUnsigned(fromInt(721018), 1, remainder, remainder.length, quotient, remainder, work); + assertEqualsBI(11, quotient); + assertEqualsBI(111, remainder); + + // check remainder overlaps with divisor, special case 1 + remainder = fromInt(10); + MultiwordArithmetic.divideUnsigned(fromInt(0), 1, remainder, remainder.length, quotient, remainder, work); + assertEqualsBI(0, quotient); + assertEqualsBI(0, remainder); + + // check remainder overlaps with divisor, special case 2 + remainder = fromInt(1); + MultiwordArithmetic.divideUnsigned(fromInt(7), 1, remainder, remainder.length, quotient, remainder, work); + assertEqualsBI(7, quotient); + assertEqualsBI(0, remainder); + + // check remainder overlaps with divisor, special case 3 + remainder = fromHex("1 00000000"); + MultiwordArithmetic.divideUnsigned(fromInt(11), 1, remainder, remainder.length, quotient, remainder, work); + assertEqualsBI(0, quotient); + assertEqualsBI(11, remainder); + + // quotient and remainder cannot be the same object + try { + MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, quotient, work); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // quotient cannot be null + try { + MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, null, work); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, null, remainder, work); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // work cannot be null + try { + MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, quotient, null); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, remainder, null); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // remainder can be null + MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, null, work); + assertEqualsBI(0, quotient); + + // dividend and divisor can be the same object + divisor = fromInt(10); + MultiwordArithmetic.divideUnsigned(divisor, divisor.length, divisor, divisor.length, quotient, remainder, work); + assertEqualsBI(1, quotient); + assertEqualsBI(0, remainder); + + // work may not overlap any input + try { + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, dividend); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + try { + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, divisor); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, quotient); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, remainder); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // bounds + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, work); + try { + MultiwordArithmetic.divideUnsigned(dividend, 0, divisor, divisor.length, quotient, remainder, work); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, 0, quotient, remainder, work); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + try { + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, new Vector(0), remainder, work); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + + // division by zero + try { + MultiwordArithmetic.divideIntUnsigned(dividend, dividend.length, 0, quotient, work); + } catch (e:String) { + eq(BigIntExceptions.DIVISION_BY_ZERO, e); + } + try { + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromInt(0), 1, quotient, remainder, work); + } catch (e:String) { + eq(BigIntExceptions.DIVISION_BY_ZERO, e); + } + + // divisor with leading 0 + try { + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromHex("1", 2), 2, quotient, remainder, work); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + } + + public function testMultiwordArithmeticMultiplicationAndDivision():Void { + checkLinearEqIntMultiwordArithmetic(fromInt(0), 0, fromInt(0), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(0), 1, fromInt(0), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(0), 0, fromInt(1), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(0), 100, fromInt(0), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(1), 1, fromInt(1), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(1), 2, fromInt(0), 1); + checkLinearEqIntMultiwordArithmetic(fromInt(2), 1, fromInt(2), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(2), 3, fromInt(0), 2); + checkLinearEqIntMultiwordArithmetic(fromInt(3), 3, fromInt(1), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(4), 2, fromInt(2), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(4), 3, fromInt(1), 1); + checkLinearEqIntMultiwordArithmetic(fromInt(5), 3, fromInt(1), 2); + checkLinearEqIntMultiwordArithmetic(fromInt(6), 3, fromInt(2), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(6), 2, fromInt(3), 0); + checkLinearEqIntMultiwordArithmetic(fromHex("12A05F2001"), 81, fromInt(987654321), 0); + + checkLinearEqMultiwordArithmetic(fromHex("0 fffffffe 00000001"), fromHex("0 ffffffff"), fromHex("0 ffffffff"), fromInt(0)); // exercises qhat = 65536 + checkLinearEqMultiwordArithmetic(fromHex("00003fff c0000000 7fff8000 00000000"), fromHex("7fff8000 00000000"), fromHex("00008000 00000001"), + fromInt(0)); + + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 1, fromInt(2147483647), 0); + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 10, fromInt(214748364), 7); + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 100, fromInt(21474836), 47); + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 1000, fromInt(2147483), 647); + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 10000, fromInt(214748), 3647); + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 100000, fromInt(21474), 83647); // exercises rhat >= 65536 + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 1000000, fromInt(2147), 483647); + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 10000000, fromInt(214), 7483647); + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 100000000, fromInt(21), 47483647); + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 1000000000, fromInt(2), 147483647); + + checkLinearEqIntMultiwordArithmetic(fromInt(2147483647), 2147483647, fromInt(1), 0); // exercises use of uninitialized quotient data + + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 1, fromHex("100000000"), 0); + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 10, fromInt(429496729), 6); + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 100, fromInt(42949672), 96); + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 1000, fromInt(4294967), 296); + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 10000, fromInt(429496), 7296); + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 100000, fromInt(42949), 67296); // exercises rhat >= 65536 + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 1000000, fromInt(4294), 967296); + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 10000000, fromInt(429), 4967296); + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 100000000, fromInt(42), 94967296); + checkLinearEqIntMultiwordArithmetic(fromHex("100000000"), 1000000000, fromInt(4), 294967296); + checkLinearEqMultiwordArithmetic(fromHex("100000000"), fromHex("2540BE400"), fromInt(0), fromHex("100000000")); + + checkLinearEqIntMultiwordArithmetic(fromHex("08000"), 1, fromHex("08000"), 0); + checkLinearEqIntMultiwordArithmetic(fromHex("080000000"), 1, fromHex("080000000"), 0); + checkLinearEqIntMultiwordArithmetic(fromHex("0800000000000"), 1, fromHex("0800000000000"), 0); + checkLinearEqIntMultiwordArithmetic(fromHex("08000000000000000"), 1, fromHex("08000000000000000"), 0); + checkLinearEqIntMultiwordArithmetic(fromHex("10001"), 2, fromHex("08000"), 1); + checkLinearEqIntMultiwordArithmetic(fromHex("100000001"), 2, fromHex("080000000"), 1); + checkLinearEqIntMultiwordArithmetic(fromHex("1000000000001"), 2, fromHex("0800000000000"), 1); + checkLinearEqIntMultiwordArithmetic(fromHex("10000000000000001"), 2, fromHex("08000000000000000"), 1); + + checkLinearEqIntMultiwordArithmetic(fromHex("0ffffffff"), 1, fromHex("0ffffffff"), 0); + checkLinearEqIntMultiwordArithmetic(fromHex("0ffffffffffffffff"), 1, fromHex("0ffffffffffffffff"), 0); + checkLinearEqIntMultiwordArithmetic(fromHex("0ffffffffffffffffffffffff"), 1, fromHex("0ffffffffffffffffffffffff"), 0); + checkLinearEqIntMultiwordArithmetic(fromHex("0ffffffff"), 2, fromHex("07fffffff"), 1); + checkLinearEqIntMultiwordArithmetic(fromHex("0ffffffffffffffff"), 2, fromHex("07fffffffffffffff"), 1); + checkLinearEqIntMultiwordArithmetic(fromHex("0ffffffffffffffffffffffff"), 2, fromHex("07fffffffffffffffffffffff"), 1); + + // exercise quotient with high bit set when length of divisor == length of dividend and divisor >= 65536 + checkLinearEqMultiwordArithmetic(fromHex("4000000000000000"), fromHex("080000000"), fromHex("080000000"), + fromInt(0)); // exercises uninitialized work data + checkLinearEqMultiwordArithmetic(fromHex("4000000080000000"), fromHex("080000001"), fromHex("080000000"), fromInt(0)); + checkLinearEqMultiwordArithmetic(fromHex("4000000100000000"), fromHex("080000001"), fromHex("080000000"), fromHex("080000000")); + checkLinearEqMultiwordArithmetic(fromHex("40000000ffffffff"), fromHex("080000001"), fromHex("080000000"), fromHex("7fffffff")); + checkLinearEqMultiwordArithmetic(fromHex("4000000100000001"), fromHex("080000001"), fromHex("080000001"), fromInt(0)); + + checkLinearEqMultiwordArithmetic(fromHex("08000"), fromHex("0800000001"), fromHex("0"), fromHex("08000")); + // these exercise the qhat reduction path + checkLinearEqMultiwordArithmetic(fromHex("080000000"), fromHex("080000001"), fromHex("0"), fromHex("080000000")); + checkLinearEqMultiwordArithmetic(fromHex("0800080010000"), fromHex("080000001"), fromHex("10000"), fromHex("080000000")); + checkLinearEqMultiwordArithmetic(fromHex("0800100010001"), fromHex("080000001"), fromHex("10001"), fromHex("080000000")); + checkLinearEqMultiwordArithmetic(fromHex("08000000180000000"), fromHex("080000001"), fromHex("100000000"), fromHex("080000000")); + checkLinearEqMultiwordArithmetic(fromHex("08000000200000001"), fromHex("080000001"), fromHex("100000001"), fromHex("080000000")); + + // this exercises long division with a quotient with high bit set + checkLinearEqMultiwordArithmetic(fromHex("08000000180000000"), fromHex("100000000"), fromHex("080000001"), fromHex("080000000")); + + // these exercise the "add back" path + checkLinearEqMultiwordArithmetic(fromHex("7fff800000000000"), fromHex("0800000000001"), fromHex("0fffe"), fromHex("7fffffff0002")); + checkLinearEqMultiwordArithmetic(fromHex("7fffffff800000010000000000000000"), fromHex("0800000008000000200000005"), fromHex("0fffffffd"), + fromHex("080000000800000010000000f")); + + checkLinearEqMultiwordArithmetic(fromInt(1), fromHex("100000000"), fromInt(0), fromInt(1)); + } + + private function checkLinearEqIntMultiwordArithmetic(y:Vector, a:Int, x:Vector, b:Int):Void { + // checks that y = ax + b + // assertBIEqualsBI(y, a * x + b); + var y_b = new Vector(y.length); + MultiwordArithmetic.subtract(y_b, y, fromInt(b, y.length), y.length); + checkMultiplyIntMultiwordArithmetic(x, a, y_b); + if (a != 0) { + checkDivIntMultiwordArithmetic(y, a, x, b); + } + checkLinearEqMultiwordArithmetic(y, fromInt(a), x, fromInt(b)); + } + + private function checkLinearEqMultiwordArithmetic(y:Vector, a:Vector, x:Vector, b:Vector):Void { + // checks that y = ax + b + // assertBIEqualsBI(y, a * x + b); + var bExt = new Vector(y.length); + MultiwordArithmetic.extendUnsigned(bExt, y.length, b, b.length); + var y_b = new Vector(y.length); + MultiwordArithmetic.subtract(y_b, y, bExt, y.length); + checkMultiplyMultiwordArithmetic(a, x, y_b); + if (!MultiwordArithmetic.isZero(a, a.length)) { + checkDivMultiwordArithmetic(y, a, x, b); + } + // if we have n / d = q + r / d, then n / q = n * d / (n - r) + if (!MultiwordArithmetic.isZero(y_b, y_b.length)) { + var temp = new Vector(y.length + a.length); + MultiwordArithmetic.multiplyUnsigned(temp, y, y.length, a, a.length); + var y_bLength = MultiwordArithmetic.getLengthUnsigned(y_b, y_b.length); + var q2 = new Vector(MultiwordArithmetic.getDivisionQuotientLengthUnsigned(temp.length, y_bLength)); + var work = new Vector(temp.length + y_bLength + 1); + MultiwordArithmetic.divideUnsigned(temp, temp.length, y_b, y_bLength, q2, null, work); + + var r2Length = ((q2.length + x.length) > y.length) ? (q2.length + x.length) : y.length; + temp = new Vector(r2Length); + MultiwordArithmetic.multiplyUnsigned(temp, q2, q2.length, x, x.length); + MultiwordArithmetic.extendUnsigned(temp, r2Length, temp, q2.length + x.length); + var r2 = new Vector(r2Length); + MultiwordArithmetic.extendUnsigned(r2, r2Length, y, y.length); + MultiwordArithmetic.subtract(r2, r2, temp, r2Length); + checkDivMultiwordArithmetic(y, x, q2, r2); + } + } + + private function checkMultiplyIntMultiwordArithmetic(a:Vector, b:Int, expected:Vector):Void { + // TODO + checkMultiplyMultiwordArithmetic(a, fromInt(b), expected); + } + + private function checkMultiplyMultiwordArithmetic(a:Vector, b:Vector, expected:Vector):Void { + checkMultiplyCommuteMultiwordArithmetic(a, b, expected); + // checkMultiplyCommute(-a, b, -expected); + // checkMultiplyCommute( a, -b, -expected); + // checkMultiplyCommute(-a, -b, expected); + } + + private function checkMultiplyCommuteMultiwordArithmetic(a:Vector, b:Vector, expected:Vector):Void { + checkMultiplySingleMultiwordArithmetic(a, b, expected); + checkMultiplySingleMultiwordArithmetic(b, a, expected); + } + + private function checkMultiplySingleMultiwordArithmetic(a:Vector, b:Vector, expected:Vector):Void { + var result = new Vector(a.length + b.length); + MultiwordArithmetic.multiplyUnsigned(result, a, a.length, b, b.length); + var expectedExt = new Vector(result.length); + MultiwordArithmetic.extendUnsigned(expectedExt, result.length, expected, expected.length); + assertEqualsBI(expectedExt, result, result.length); + } + + private function checkDivIntMultiwordArithmetic(dividend:Vector, divisor:Int, expectedQuotient:Vector, expectedRemainder:Int):Void { + var quotient = new Vector(MultiwordArithmetic.getDivisionQuotientLengthUnsigned(dividend.length, 1)); + var work = new Vector(dividend.length + 1 + 1); + var remainder:Int = MultiwordArithmetic.divideIntUnsigned(dividend, dividend.length, divisor, quotient, work); + eq(expectedRemainder, remainder); + assertEqualsBI(expectedQuotient, quotient, MultiwordArithmetic.getLengthUnsigned(quotient, quotient.length)); + + checkDivMultiwordArithmetic(dividend, fromInt(divisor), expectedQuotient, fromInt(expectedRemainder)); + } + + private function checkDivMultiwordArithmetic(dividend:Vector, divisor:Vector, expectedQuotient:Vector, expectedRemainder:Vector):Void { + checkDivSingleMultiwordArithmetic(dividend, divisor, expectedQuotient, expectedRemainder); + // checkDivSingle( dividend, -divisor, -expectedQuotient, expectedRemainder); + // checkDivSingle(-dividend, divisor, -expectedQuotient, -expectedRemainder); + // checkDivSingle(-dividend, -divisor, expectedQuotient, -expectedRemainder); + } + + private function checkDivSingleMultiwordArithmetic(dividend:Vector, divisor:Vector, expectedQuotient:Vector, + expectedRemainder:Vector):Void { + var quotient = new Vector(MultiwordArithmetic.getDivisionQuotientLengthUnsigned(dividend.length, divisor.length)); + var remainder = new Vector(divisor.length); + var work = new Vector(dividend.length + divisor.length + 1); + MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, work); + assertEqualsBI(expectedRemainder, remainder, MultiwordArithmetic.getLengthUnsigned(remainder, remainder.length)); + assertEqualsBI(expectedQuotient, quotient, MultiwordArithmetic.getLengthUnsigned(quotient, quotient.length)); + } + + private static function fromInt(value:Int, length:Int = 1):Vector { + var result = new Vector(length); + MultiwordArithmetic.setFromIntUnsigned(result, length, value); + return result; + } + + private static function fromHex(value:String, length:Int = 1):Vector { + while (true) { + var result = new Vector(length); + if (!MultiwordArithmetic.setFromHexUnsigned(result, length, value)) { + ++length; + continue; + } + return result; + } + } + + private static function fill(value:Vector):Void { + for (i in 0...value.length) { + value.set(i, 0xdeadbeef); + } + } + + public function assertEqualsBI(expected:Dynamic, actual:Dynamic, length:Int = 0, ?c:PosInfos):Void { + if (Std.isOfType(actual, BigInt_)) { + var e = Std.downcast(expected, BigInt_); + if (e == null) { + if (Std.isOfType(expected, Int)) { + e = BigInt.fromInt(cast(expected, Int)); + } + } + eq(e.toHex(), cast(actual, BigInt_).toHex(), c); + return; + } + + var vActual:Vector = cast actual; + var vExpected:Vector = null; + if (Std.isOfType(expected, Int)) { + vExpected = new Vector(vActual.length); + MultiwordArithmetic.setFromIntUnsigned(vExpected, vExpected.length, cast(expected, Int)); + } else { + vExpected = cast expected; + } + eq(MultiwordArithmetic.toHex(vExpected, (length != 0) ? length : vExpected.length), + MultiwordArithmetic.toHex(vActual, (length != 0) ? length : vActual.length), c); + return; + } + + private static var s_powersOfTwo = [ + "1", + "2", + "4", + "8", + "16", + "32", + "64", + "128", + "256", + "512", + "1024", + "2048", + "4096", + "8192", + "16384", + "32768", + "65536", + "131072", + "262144", + "524288", + "1048576", + "2097152", + "4194304", + "8388608", + "16777216", + "33554432", + "67108864", + "134217728", + "268435456", + "536870912", + "1073741824", + "2147483648", + "4294967296", + "8589934592", + "17179869184", + "34359738368", + "68719476736", + "137438953472", + "274877906944", + "549755813888", + "1099511627776", + "2199023255552", + "4398046511104", + "8796093022208", + "17592186044416", + "35184372088832", + "70368744177664", + "140737488355328", + "281474976710656", + "562949953421312", + "1125899906842624", + "2251799813685248", + "4503599627370496", + "9007199254740992", + "18014398509481984", + "36028797018963968", + "72057594037927936", + "144115188075855872", + "288230376151711744", + "576460752303423488", + "1152921504606846976", + "2305843009213693952", + "4611686018427387904", + "9223372036854775808", + "18446744073709551616", + "36893488147419103232", + "73786976294838206464", + "147573952589676412928", + "295147905179352825856", + "590295810358705651712", + "1180591620717411303424", + "2361183241434822606848", + "4722366482869645213696", + "9444732965739290427392", + "18889465931478580854784", + "37778931862957161709568", + "75557863725914323419136", + "151115727451828646838272", + "302231454903657293676544", + "604462909807314587353088", + "1208925819614629174706176", + "2417851639229258349412352", + "4835703278458516698824704", + "9671406556917033397649408", + "19342813113834066795298816", + "38685626227668133590597632", + "77371252455336267181195264", + "154742504910672534362390528", + "309485009821345068724781056", + "618970019642690137449562112", + "1237940039285380274899124224", + "2475880078570760549798248448", + "4951760157141521099596496896", + "9903520314283042199192993792", + "19807040628566084398385987584", + "39614081257132168796771975168", + /* 2^128 */ "340282366920938463463374607431768211456", + /* 2^256 */ "115792089237316195423570985008687907853269984665640564039457584007913129639936", + /* 2^512 */ "13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096", + ]; +} \ No newline at end of file From 6aa9204a53844b46f6e791013cf8de67a303885b Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 16 Jul 2022 13:58:27 +0300 Subject: [PATCH 003/134] Add abs,pow,modPow,isProbablePrime,getLowestSetBit,bitLength methods --- std/haxe/math/bigint/BigInt.hx | 30 +++++++ std/haxe/math/bigint/BigInt_.hx | 125 ++++++++++++++++++++++++++ std/haxe/math/bigint/MutableBigInt.hx | 29 ++++++ 3 files changed, 184 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index fa53ea57b20..6617e849563 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -34,6 +34,7 @@ abstract BigInt(BigInt_) public static var ZERO(default, null) : BigInt = new BigInt(BigInt_.fromInt(0)); public static var ONE(default, null) : BigInt = new BigInt(BigInt_.fromInt(1)); + public static var TWO(default, null) : BigInt = new BigInt(BigInt_.fromInt(2)); public static var NEGATIVE_ONE(default, null) : BigInt = new BigInt(BigInt_.fromInt(-1)); //----------------------------------------------------------------------- @@ -109,6 +110,35 @@ abstract BigInt(BigInt_) { return BigIntArithmetic.getBit(this, index); } + + public function abs() : BigInt + { + return new BigInt(this.abs()); + } + + public function pow(exponent:UInt) : BigInt + { + return new BigInt(BigInt_.pow(exponent,this)); + } + + public function modPow(exponent:BigInt, modulus:BigInt) : BigInt + { + return new BigInt(BigInt_.modPow(exponent,modulus,this)); + } + + public function isProbablePrime(tolerance:UInt):Bool + { + return this.isProbablePrime(tolerance); + } + + public function getLowestSetBit():Int + { + return this.getLowestSetBit(); + } + + public function bitLength():Int { + return this.bitLength(); + } //----------------------------------------------------------------------- // Operators diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index a0d5049eb03..1f15711f7ab 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -33,6 +33,16 @@ class BigInt_ // Public interface //----------------------------------------------------------------------- + public inline function abs():BigInt_ + { + if ( this.sign() < 0) { + return BigInt_.negate1(this); + } + var r = new MutableBigInt_(); + r.copyFrom(this); + return r; + } + /** Returns `true` if this big integer is equivalent to 0, otherwise returns `false`. **/ @@ -56,6 +66,48 @@ class BigInt_ { return m_data.get(m_count - 1) >> 31; } + + public function getLowestSetBit():Int + { + if ( this.isZero() ) return -1; + var result:Int = -1; + var i:Int = 0; + var b = m_data.get(0); + while ( b == 0 ) { i++; b = m_data.get(i); } + result = (i<<5) +BigIntHelper.ntz(b); + return result; + } + + public function bitLength():Int { + if ( m_count <=0) return 0; + return ( 32 * m_count - BigIntHelper.nlz(m_data.get(m_count-1)^sign()) ); + } + + public function isProbablePrime(tolerance:UInt):Bool + { + if ( tolerance <= 0 ) return true; + var b:BigInt_ = this.abs(); + if ( equals2Int(b,1) ) return false; + if ( equals2Int(b,2) ) return true; + if ( b.m_data.get(0) & 1 == 0 ) return false; + + var rounds:UInt = 0; + if ( b.m_count <= 4) { + rounds = (tolerance>64)?64:tolerance; + } else if ( b.m_count < 8) { + rounds = 32; + } else if ( b.m_count < 16) { + rounds = 16; + } else if ( b.m_count < 24) { + rounds = 8; + } else if ( b.m_count < 32) { + rounds = 4; + } else { + rounds = 2; + } + rounds = (tolerance> 1; + if (exponent == 0) break; + p = multiply2(p,p); + } + return r; + } //----------------------------------------------------------------------- // Private implementation @@ -259,6 +341,49 @@ class BigInt_ } } } + + private function random():BigInt_ + { + var r = new MutableBigInt_(); + var countBits:Int = bitLength(); + var countBytes:Int = Std.int((countBits+7)/8); + var randomBytes = Bytes.alloc(countBytes); + for(j in 0...countBytes) { + var rnd = Std.int(( Math.random() * 256 )); + randomBytes.set(j,rnd); + } + r.setFromHexUnsigned(randomBytes.toHex()); + r.compact(); + return r; + } + + private function millerRabin(rounds:UInt):Bool + { + var minusOne:BigInt_ = subInt2(this,1); + var m = subInt2(this,1); + var lsb = m.getLowestSetBit(); + if ( lsb <=0 ) return false; + m = arithmeticShiftRight2(m,lsb); + var num:BigInt_; + for(i in 0...rounds) { + do { + num =random(); + } while (BigIntArithmetic.compare(num, BigInt.ONE) <= 0 || BigIntArithmetic.compare(num, this) >= 0 ); + var z:BigInt_ = BigInt_.modPow(m,this,num); + if ( BigIntArithmetic.compare(z, BigInt.ONE) != 0 && BigIntArithmetic.compare(z, minusOne) != 0) { + var j:Int = 1; + while ( j<=lsb && BigIntArithmetic.compare(z, minusOne) != 0) + { + if ( BigIntArithmetic.compare(z, BigInt.ONE) == 0 || j == lsb) { + return false; + } + z = BigInt_.modPow(BigInt.TWO,this,z); + j++; + } + } + } + return true; + } private static function newFromInt(value : Int) : BigInt_ { diff --git a/std/haxe/math/bigint/MutableBigInt.hx b/std/haxe/math/bigint/MutableBigInt.hx index 344ca945497..e7a79007329 100644 --- a/std/haxe/math/bigint/MutableBigInt.hx +++ b/std/haxe/math/bigint/MutableBigInt.hx @@ -121,6 +121,35 @@ abstract MutableBigInt(MutableBigInt_) r.setFromLittleEndianBytesUnsigned(value); return new MutableBigInt(r); } + + public function abs() : MutableBigInt + { + return this.abs(); + } + + public function pow(exponent:UInt) : MutableBigInt + { + return BigInt_.pow(exponent,this); + } + + public function modPow(exponent:BigInt, modulus:BigInt) : MutableBigInt + { + return BigInt_.modPow(exponent,modulus,this); + } + + public function isProbablePrime(tolerance:UInt):Bool + { + return this.isProbablePrime(tolerance); + } + + public function getLowestSetBit():Int + { + return this.getLowestSetBit(); + } + + public function bitLength():Int { + return this.bitLength(); + } //----------------------------------------------------------------------- // Operators From 17a09e602abcb3a72ad3f752b53118e308177557 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 16 Jul 2022 16:08:11 +0300 Subject: [PATCH 004/134] Add missing tests and counting of trailing zeros --- std/haxe/math/bigint/BigIntHelper.hx | 22 +- tests/unit/src/unit/TestBigInt.hx | 445 +++++++++++++++++++++++++++ 2 files changed, 464 insertions(+), 3 deletions(-) diff --git a/std/haxe/math/bigint/BigIntHelper.hx b/std/haxe/math/bigint/BigIntHelper.hx index ff99e469ebf..e4bc3297e44 100644 --- a/std/haxe/math/bigint/BigIntHelper.hx +++ b/std/haxe/math/bigint/BigIntHelper.hx @@ -114,14 +114,30 @@ class BigIntHelper return q + c; } - /** + /** Unsigned greater than or equal comparison. Returns `true` if `a >= b` when both `a` and `b` are interpreted as unsigned integers; `false` otherwise. **/ public static inline function u32geu32(a : Int, b : Int) : Bool - { + { return (a ^ -2147483648) >= (b ^ -2147483648); // unsigned comparison, see "Hacker's Delight" p. 25. - } + } + + /** + Number of trailing zeros - return the number of trailing + 0-value bits + **/ + public static function ntz( x : Int ):Int + { + if (x == 0) return 32; + var y:Int; + var n:Int = 31; + y = x << 16; if (y != 0) { n -= 16; x = y; } + y = x << 8; if (y != 0) { n -= 8; x = y; } + y = x << 4; if (y != 0) { n -= 4; x = y; } + y = x << 2; if (y != 0) { n -= 2; x = y; } + return (n - ((x << 1) >>> 31)); + } } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 2c28ae26a3c..796956ef4ca 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -11,6 +11,7 @@ import haxe.math.bigint.BigIntExceptions; import haxe.math.bigint.BigIntTools; import haxe.math.bigint.MutableBigInt; import haxe.math.bigint.BigInt; +import haxe.math.bigint.BigIntHelper; class TestBigInt extends Test { public function testBigInt():Void { @@ -2226,6 +2227,450 @@ class TestBigInt extends Test { MultiwordArithmetic.toHex(vActual, (length != 0) ? length : vActual.length), c); return; } + + public function test_nlz():Void + { + eq(32, BigIntHelper.nlz(0)); + eq(31, BigIntHelper.nlz(1)); + eq(30, BigIntHelper.nlz(2)); + eq(30, BigIntHelper.nlz(3)); + eq(29, BigIntHelper.nlz(4)); + eq(29, BigIntHelper.nlz(5)); + eq(29, BigIntHelper.nlz(7)); + eq(28, BigIntHelper.nlz(8)); + eq(28, BigIntHelper.nlz(9)); + eq(28, BigIntHelper.nlz(15)); + eq(27, BigIntHelper.nlz(16)); + eq(27, BigIntHelper.nlz(17)); + eq(27, BigIntHelper.nlz(31)); + eq(26, BigIntHelper.nlz(32)); + eq(26, BigIntHelper.nlz(33)); + eq(26, BigIntHelper.nlz(63)); + eq(25, BigIntHelper.nlz(64)); + eq(25, BigIntHelper.nlz(65)); + eq(25, BigIntHelper.nlz(127)); + eq(24, BigIntHelper.nlz(128)); + eq(24, BigIntHelper.nlz(129)); + eq(24, BigIntHelper.nlz(255)); + eq(23, BigIntHelper.nlz(256)); + eq(23, BigIntHelper.nlz(257)); + eq(23, BigIntHelper.nlz(511)); + eq(22, BigIntHelper.nlz(512)); + eq(22, BigIntHelper.nlz(513)); + eq(22, BigIntHelper.nlz(1023)); + eq(21, BigIntHelper.nlz(1024)); + eq(21, BigIntHelper.nlz(1025)); + eq(21, BigIntHelper.nlz(2047)); + eq(20, BigIntHelper.nlz(2048)); + eq(20, BigIntHelper.nlz(2049)); + eq(20, BigIntHelper.nlz(4095)); + eq(19, BigIntHelper.nlz(4096)); + eq(19, BigIntHelper.nlz(4097)); + eq(19, BigIntHelper.nlz(8191)); + eq(18, BigIntHelper.nlz(8192)); + eq(18, BigIntHelper.nlz(8193)); + eq(18, BigIntHelper.nlz(16383)); + eq(17, BigIntHelper.nlz(16384)); + eq(17, BigIntHelper.nlz(16385)); + eq(17, BigIntHelper.nlz(32767)); + eq(16, BigIntHelper.nlz(32768)); + eq(16, BigIntHelper.nlz(32769)); + eq(16, BigIntHelper.nlz(65535)); + eq(15, BigIntHelper.nlz(65536)); + eq(15, BigIntHelper.nlz(65537)); + eq(15, BigIntHelper.nlz(131071)); + eq(14, BigIntHelper.nlz(131072)); + eq(14, BigIntHelper.nlz(131073)); + eq(14, BigIntHelper.nlz(262143)); + eq(13, BigIntHelper.nlz(262144)); + eq(13, BigIntHelper.nlz(262145)); + eq(13, BigIntHelper.nlz(524287)); + eq(12, BigIntHelper.nlz(524288)); + eq(12, BigIntHelper.nlz(524289)); + eq(12, BigIntHelper.nlz(1048575)); + eq(11, BigIntHelper.nlz(1048576)); + eq(11, BigIntHelper.nlz(1048577)); + eq(11, BigIntHelper.nlz(2097151)); + eq(10, BigIntHelper.nlz(2097152)); + eq(10, BigIntHelper.nlz(2097153)); + eq(10, BigIntHelper.nlz(4194303)); + eq(9, BigIntHelper.nlz(4194304)); + eq(9, BigIntHelper.nlz(4194305)); + eq(9, BigIntHelper.nlz(8388607)); + eq(8, BigIntHelper.nlz(8388608)); + eq(8, BigIntHelper.nlz(8388609)); + eq(8, BigIntHelper.nlz(16777215)); + eq(7, BigIntHelper.nlz(16777216)); + eq(7, BigIntHelper.nlz(16777217)); + eq(7, BigIntHelper.nlz(33554431)); + eq(6, BigIntHelper.nlz(33554432)); + eq(6, BigIntHelper.nlz(33554433)); + eq(6, BigIntHelper.nlz(67108863)); + eq(5, BigIntHelper.nlz(67108864)); + eq(5, BigIntHelper.nlz(67108865)); + eq(5, BigIntHelper.nlz(134217727)); + eq(4, BigIntHelper.nlz(134217728)); + eq(4, BigIntHelper.nlz(134217729)); + eq(4, BigIntHelper.nlz(268435455)); + eq(3, BigIntHelper.nlz(268435456)); + eq(3, BigIntHelper.nlz(268435457)); + eq(3, BigIntHelper.nlz(536870911)); + eq(2, BigIntHelper.nlz(536870912)); + eq(2, BigIntHelper.nlz(536870913)); + eq(2, BigIntHelper.nlz(1073741823)); + eq(1, BigIntHelper.nlz(1073741824)); + eq(1, BigIntHelper.nlz(1073741825)); + eq(1, BigIntHelper.nlz(2147483647)); + eq(0, BigIntHelper.nlz(-2147483648)); + eq(0, BigIntHelper.nlz(-2147483647)); + eq(0, BigIntHelper.nlz(-1)); + } + + public function test_ntz():Void + { + eq(32, BigIntHelper.ntz(0)); + eq(31, BigIntHelper.ntz(-2147483648)); + eq(30, BigIntHelper.ntz(1073741824)); + eq(29, BigIntHelper.ntz(536870912)); + eq(28, BigIntHelper.ntz(268435456)); + eq(27, BigIntHelper.ntz(134217728)); + eq(26, BigIntHelper.ntz(67108864)); + eq(25, BigIntHelper.ntz(33554432)); + eq(24, BigIntHelper.ntz(16777216)); + eq(23, BigIntHelper.ntz(8388608)); + eq(22, BigIntHelper.ntz(4194304)); + eq(21, BigIntHelper.ntz(2097152)); + eq(20, BigIntHelper.ntz(1048576)); + eq(19, BigIntHelper.ntz(524288)); + eq(18, BigIntHelper.ntz(262144)); + eq(17, BigIntHelper.ntz(131072)); + eq(16, BigIntHelper.ntz(65536)); + eq(15, BigIntHelper.ntz(32768)); + eq(14, BigIntHelper.ntz(16384)); + eq(13, BigIntHelper.ntz(8192)); + eq(12, BigIntHelper.ntz(4096)); + eq(11, BigIntHelper.ntz(2048)); + eq(10, BigIntHelper.ntz(1024)); + eq(9, BigIntHelper.ntz(512)); + eq(8, BigIntHelper.ntz(256)); + eq(7, BigIntHelper.ntz(128)); + eq(6, BigIntHelper.ntz(64)); + eq(5, BigIntHelper.ntz(32)); + eq(4, BigIntHelper.ntz(16)); + eq(3, BigIntHelper.ntz(8)); + eq(2, BigIntHelper.ntz(4)); + eq(1, BigIntHelper.ntz(2)); + eq(0, BigIntHelper.ntz(-2147483647)); + eq(0, BigIntHelper.ntz(-1)); + eq(0, BigIntHelper.ntz(1)); + eq(0, BigIntHelper.ntz(3)); + } + + public function test_clp2():Void + { + eq(0, BigIntHelper.clp2(0)); + eq(1, BigIntHelper.clp2(1)); + eq(2, BigIntHelper.clp2(2)); + eq(4, BigIntHelper.clp2(3)); + eq(4, BigIntHelper.clp2(4)); + eq(8, BigIntHelper.clp2(5)); + eq(8, BigIntHelper.clp2(7)); + eq(8, BigIntHelper.clp2(8)); + eq(16, BigIntHelper.clp2(9)); + eq(16, BigIntHelper.clp2(15)); + eq(16, BigIntHelper.clp2(16)); + eq(32, BigIntHelper.clp2(17)); + eq(32, BigIntHelper.clp2(31)); + eq(32, BigIntHelper.clp2(32)); + eq(64, BigIntHelper.clp2(33)); + eq(64, BigIntHelper.clp2(63)); + eq(64, BigIntHelper.clp2(64)); + eq(128, BigIntHelper.clp2(65)); + eq(128, BigIntHelper.clp2(127)); + eq(128, BigIntHelper.clp2(128)); + eq(256, BigIntHelper.clp2(129)); + eq(256, BigIntHelper.clp2(255)); + eq(256, BigIntHelper.clp2(256)); + eq(512, BigIntHelper.clp2(257)); + eq(512, BigIntHelper.clp2(511)); + eq(512, BigIntHelper.clp2(512)); + eq(1024, BigIntHelper.clp2(513)); + eq(1024, BigIntHelper.clp2(1023)); + eq(1024, BigIntHelper.clp2(1024)); + eq(2048, BigIntHelper.clp2(1025)); + eq(2048, BigIntHelper.clp2(2047)); + eq(2048, BigIntHelper.clp2(2048)); + eq(4096, BigIntHelper.clp2(2049)); + eq(4096, BigIntHelper.clp2(4095)); + eq(4096, BigIntHelper.clp2(4096)); + eq(8192, BigIntHelper.clp2(4097)); + eq(8192, BigIntHelper.clp2(8191)); + eq(8192, BigIntHelper.clp2(8192)); + eq(16384, BigIntHelper.clp2(8193)); + eq(16384, BigIntHelper.clp2(16383)); + eq(16384, BigIntHelper.clp2(16384)); + eq(32768, BigIntHelper.clp2(16385)); + eq(32768, BigIntHelper.clp2(32767)); + eq(32768, BigIntHelper.clp2(32768)); + eq(65536, BigIntHelper.clp2(32769)); + eq(65536, BigIntHelper.clp2(65535)); + eq(65536, BigIntHelper.clp2(65536)); + eq(131072, BigIntHelper.clp2(65537)); + eq(131072, BigIntHelper.clp2(131071)); + eq(131072, BigIntHelper.clp2(131072)); + eq(262144, BigIntHelper.clp2(131073)); + eq(262144, BigIntHelper.clp2(262143)); + eq(262144, BigIntHelper.clp2(262144)); + eq(524288, BigIntHelper.clp2(262145)); + eq(524288, BigIntHelper.clp2(524287)); + eq(524288, BigIntHelper.clp2(524288)); + eq(1048576, BigIntHelper.clp2(524289)); + eq(1048576, BigIntHelper.clp2(1048575)); + eq(1048576, BigIntHelper.clp2(1048576)); + eq(2097152, BigIntHelper.clp2(1048577)); + eq(2097152, BigIntHelper.clp2(2097151)); + eq(2097152, BigIntHelper.clp2(2097152)); + eq(4194304, BigIntHelper.clp2(2097153)); + eq(4194304, BigIntHelper.clp2(4194303)); + eq(4194304, BigIntHelper.clp2(4194304)); + eq(8388608, BigIntHelper.clp2(4194305)); + eq(8388608, BigIntHelper.clp2(8388607)); + eq(8388608, BigIntHelper.clp2(8388608)); + eq(16777216, BigIntHelper.clp2(8388609)); + eq(16777216, BigIntHelper.clp2(16777215)); + eq(16777216, BigIntHelper.clp2(16777216)); + eq(33554432, BigIntHelper.clp2(16777217)); + eq(33554432, BigIntHelper.clp2(33554431)); + eq(33554432, BigIntHelper.clp2(33554432)); + eq(67108864, BigIntHelper.clp2(33554433)); + eq(67108864, BigIntHelper.clp2(67108863)); + eq(67108864, BigIntHelper.clp2(67108864)); + eq(134217728, BigIntHelper.clp2(67108865)); + eq(134217728, BigIntHelper.clp2(134217727)); + eq(134217728, BigIntHelper.clp2(134217728)); + eq(268435456, BigIntHelper.clp2(134217729)); + eq(268435456, BigIntHelper.clp2(268435455)); + eq(268435456, BigIntHelper.clp2(268435456)); + eq(536870912, BigIntHelper.clp2(268435457)); + eq(536870912, BigIntHelper.clp2(536870911)); + eq(536870912, BigIntHelper.clp2(536870912)); + eq(1073741824, BigIntHelper.clp2(536870913)); + eq(1073741824, BigIntHelper.clp2(1073741823)); + eq(1073741824, BigIntHelper.clp2(1073741824)); + eq(-2147483648, BigIntHelper.clp2(1073741825)); + eq(-2147483648, BigIntHelper.clp2(2147483647)); + eq(-2147483648, BigIntHelper.clp2(-2147483648)); + eq(0, BigIntHelper.clp2(-2147483647)); + eq(0, BigIntHelper.clp2(-1)); + } + + public function test_u32gtu32():Void + { + checkUnsignedRelation(0, 0); + checkUnsignedRelation(1, 0); + checkUnsignedRelation(2147483647, 2147483647); + checkUnsignedRelation(-2147483648, 2147483647); + checkUnsignedRelation(-2147483648, -2147483648); + checkUnsignedRelation(-2147483647, -2147483648); + checkUnsignedRelation(-1, -1); + checkUnsignedRelation(-1, -2); + } + + private function checkUnsignedRelation(a:Int, b:Int):Void + { + eq(a != b, BigIntHelper.u32gtu32(a, b)); + f(BigIntHelper.u32gtu32(b, a)); + t(BigIntHelper.u32geu32(a, b)); + eq(a == b, BigIntHelper.u32geu32(b, a)); + } + + public function testDivision():Void + { + divide1(0, 1, 0, 0); + divide1(0, 2147483647, 0, 0); + divide1(0, -2147483648, 0, 0); + divide1(0, -1, 0, 0); + + divide1(1, 1, 1, 0); + divide1(1, 2, 0, 1); + divide1(1, 2147483647, 0, 1); + divide1(1, -2147483648, 0, 1); + divide1(1, -1, 0, 1); + + divide1(-1, 2147483647, 2, 1); + divide1(-2, 2147483647, 2, 0); + divide1(-3, 2147483647, 1, 2147483646); + divide1(-4, 2147483647, 1, 2147483645); + divide1(-2147483648, 2147483647, 1, 1); + divide1(2147483647, 2147483647, 1, 0); + divide1(2147483646, 2147483647, 0, 2147483646); + divide1(2147483645, 2147483647, 0, 2147483645); + + divide1(-1, -2147483648, 1, 2147483647); + divide1(-2, -2147483648, 1, 2147483646); + divide1(-3, -2147483648, 1, 2147483645); + divide1(-2147483646, -2147483648, 1, 2); + divide1(-2147483647, -2147483648, 1, 1); + divide1(-2147483648, -2147483648, 1, 0); + divide1(2147483647, -2147483648, 0, 2147483647); + divide1(2147483646, -2147483648, 0, 2147483646); + divide1(2147483645, -2147483648, 0, 2147483645); + + divide1(0, -2147483647, 0, 0); + divide1(2147483647, -2147483647, 0, 2147483647); + divide1(-2147483648, -2147483647, 0, -2147483648); + divide1(-2147483647, -2147483647, 1, 0); + divide1(-2147483646, -2147483647, 1, 1); + divide1(-2147483645, -2147483647, 1, 2); + + divide1(4500, 501, 8, 492); + + divide1(-1, 1, -1, 0); + divide1(-1, 2, 2147483647, 1); + divide1(-1, 3, 1431655765, 0); + divide1(-1, 4, 1073741823, 3); + divide1(-1, 5, 858993459, 0); + divide1(-1, 6, 715827882, 3); + divide1(-1, 7, 613566756, 3); + divide1(-1, 8, 536870911, 7); + divide1(-1, 9, 477218588, 3); + divide1(-1, 10, 429496729, 5); + divide1(-1, 11, 390451572, 3); + + divide1(-2147483648, 1, -2147483648, 0); + divide1(-2147483648, 2, 1073741824, 0); + divide1(-2147483648, 3, 715827882, 2); + divide1(-2147483648, 4, 536870912, 0); + divide1(-2147483648, 5, 429496729, 3); + divide1(-2147483648, 6, 357913941, 2); + divide1(-2147483648, 7, 306783378, 2); + divide1(-2147483648, 8, 268435456, 0); + divide1(-2147483648, 9, 238609294, 2); + divide1(-2147483648, 10, 214748364, 8); + divide1(-2147483648, 11, 195225786, 2); + + divide1(0, 65535, 0, 0); + divide1(1, 65535, 0, 1); + divide1(65534, 65535, 0, 65534); + divide1(65535, 65535, 1, 0); + divide1(65536, 65535, 1, 1); + divide1(2147483647, 65535, 32768, 32767); + divide1(-2147483648, 65535, 32768, 32768); + divide1(-2, 65535, 65536, 65534); + divide1(-1, 65535, 65537, 0); + } + + private function divide1(dividend:Int, divisor:Int, expectedQuotient:Int, expectedRemainder:Int):Void { + if ((0 < divisor) && (divisor < 65536)) { + eq(expectedQuotient, BigIntHelper.u32divu16(dividend, divisor)); + } + } + + public function testAbs():Void + { + var an:BigInt = -1; + var am:MutableBigInt = -1; + eq("1",an.abs().toString()); + eq("1",am.abs().toString()); + an = -2147483648; + am = -2147483648; + eq("2147483648",an.abs().toString()); + eq("2147483648",am.abs().toString()); + an = 0; + am = 0; + eq("0",an.abs().toString()); + eq("0",am.abs().toString()); + am = 2147483647; + an = 2147483647; + eq("2147483647",an.abs().toString()); + eq("2147483647",am.abs().toString()); + } + + public function testPow():Void + { + var b:BigInt = 2; + var bm:MutableBigInt = 2; + for (i in 0...(s_powersOfTwo.length-3)) { + var s = s_powersOfTwo[i]; + eq(s,b.pow(i).toString()); + eq(s,bm.pow(i).toString()); + } + } + + public function testModPow():Void + { + var b:BigInt = 2; + var bm:MutableBigInt = 2; + var exp:BigInt = 3; + var mod:BigInt = 5; + eq("3",b.modPow(exp,mod).toString()); + eq("3",b.modPow(exp,mod).toString()); + exp = 5; + mod = 13; + eq("6",b.modPow(exp,mod).toString()); + eq("6",b.modPow(exp,mod).toString()); + } + + public function testPrimeNumber():Void + { + for(i in 0...s_primeNumbers.length) { + var b:BigInt = s_primeNumbers[i]; + var bm:BigInt = s_primeNumbers[i]; + t(b.isProbablePrime(5)); + t(bm.isProbablePrime(5)); + } + for(i in 0...s_notPrimeNumbers.length) { + var b:BigInt = s_notPrimeNumbers[i]; + var bm:BigInt = s_notPrimeNumbers[i]; + f(b.isProbablePrime(5)); + f(bm.isProbablePrime(5)); + } + } + + public function testLowestSetBit():Void + { + var b:BigInt = 2162; + var bm:MutableBigInt = 2162; + eq(1, b.getLowestSetBit()); + eq(1, bm.getLowestSetBit()); + b = 5607; + bm = 5607; + eq(0, b.getLowestSetBit()); + eq(0, bm.getLowestSetBit()); + b = 3520; + bm = 3520; + eq(6, b.getLowestSetBit()); + eq(6, bm.getLowestSetBit()); + b = 2068; + bm = 2068; + eq(2, b.getLowestSetBit()); + eq(2, bm.getLowestSetBit()); + b = 4583952; + bm = 4583952; + eq(4, b.getLowestSetBit()); + eq(4, bm.getLowestSetBit()); + } + + public function testBitLength():Void + { + var b:BigInt = 4036232; + var bm:MutableBigInt = 6661810; + eq(22, b.bitLength()); + eq(23, bm.bitLength()); + b = 54342; + bm = 4471; + eq(16, b.bitLength()); + eq(13, bm.bitLength()); + b = 241; + bm = 519; + eq(8, b.bitLength()); + eq(10, bm.bitLength()); + } + + private static var s_primeNumbers = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; + + private static var s_notPrimeNumbers = [0,1,4,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30,32,33,34,35,36,38,39,40,42,44,45,46,48,49,50,51,52,54,55,56,57,58,60,62,63,64,65,66,68,69,70,72,74,75,76,77,78,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,102,104,105,106,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,132,133,134,135,136,138,140,141,142,143,144,145,146,147,148,150,152,153,154,155,156,158,159,160,161,162,164,165,166,168,169,170,171,172,174,175,176,177,178,180,182,183,184,185,186,187,188,189,190,192,194,195,196,198,200,201,202,203,204,205,206,207,208,209,210,212,213,214,215,216,217,218,219,220,221,222,224,225,226,228,230,231,232,234,235,236,237,238,240,242,243,244,245,246,247,248,249,250,252,253,254,255,256,258,259,260,261,262,264,265,266,267,268,270,272,273,274,275,276,278,279,280,282,284,285,286,287,288,289,290,291,292,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,312,314,315,316,318,319,320,321,322,323,324,325,326,327,328,329,330,332,333,334,335,336,338,339,340,341,342,343,344,345,346,348,350,351,352,354,355,356,357,358,360,361,362,363,364,365,366,368,369,370,371,372,374,375,376,377,378,380,381,382,384,385,386,387,388,390,391,392,393,394,395,396,398,399,400,402,403,404,405,406,407,408,410,411,412,413,414,415,416,417,418,420,422,423,424,425,426,427,428,429,430,432,434,435,436,437,438,440,441,442,444,445,446,447,448,450,451,452,453,454,455,456,458,459,460,462,464,465,466,468,469,470,471,472,473,474,475,476,477,478,480,481,482,483,484,485,486,488,489,490,492,493,494,495,496,497,498,500,501,502,504,505,506,507,508,510,511,512,513,514,515,516,517,518,519,520,522,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,542,543,544,545,546,548,549,550,551,552,553,554,555,556,558,559,560,561,562,564,565,566,567,568,570,572,573,574,575,576,578,579,580,581,582,583,584,585,586,588,589,590,591,592,594,595,596,597,598,600,602,603,604,605,606,608,609,610,611,612,614,615,616,618,620,621,622,623,624,625,626,627,628,629,630,632,633,634,635,636,637,638,639,640,642,644,645,646,648,649,650,651,652,654,655,656,657,658,660,662,663,664,665,666,667,668,669,670,671,672,674,675,676,678,679,680,681,682,684,685,686,687,688,689,690,692,693,694,695,696,697,698,699,700,702,703,704,705,706,707,708,710,711,712,713,714,715,716,717,718,720,721,722,723,724,725,726,728,729,730,731,732,734,735,736,737,738,740,741,742,744,745,746,747,748,749,750,752,753,754,755,756,758,759,760,762,763,764,765,766,767,768,770,771,772,774,775,776,777,778,779,780,781,782,783,784,785,786,788,789,790,791,792,793,794,795,796,798,799,800,801,802,803,804,805,806,807,808,810,812,813,814,815,816,817,818,819,820,822,824,825,826,828,830,831,832,833,834,835,836,837,838,840,841,842,843,844,845,846,847,848,849,850,851,852,854,855,856,858,860,861,862,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,882,884,885,886,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,908,909,910,912,913,914,915,916,917,918,920,921,922,923,924,925,926,927,928,930,931,932,933,934,935,936,938,939,940,942,943,944,945,946,948,949,950,951,952,954,955,956,957,958,959,960,961,962,963,964,965,966,968,969,970,972,973,974,975,976,978,979,980,981,982,984,985,986,987,988,989,990,992,993,994,995,996,998,999]; + private static var s_powersOfTwo = [ "1", From 60de60db314dfef39f988fa5809fc611cc646eb3 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 16 Jul 2022 17:06:35 +0300 Subject: [PATCH 005/134] Run tests for BigInt --- tests/unit/src/unit/TestMain.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/src/unit/TestMain.hx b/tests/unit/src/unit/TestMain.hx index 1370c085224..2174c2ba392 100644 --- a/tests/unit/src/unit/TestMain.hx +++ b/tests/unit/src/unit/TestMain.hx @@ -78,6 +78,7 @@ function main() { new TestNumericCasts(), new TestHashMap(), new TestRest(), + new TestBigInt(), #if !no_http new TestHttp(), #end #if !no_pattern_matching From e2fdb58540539f091cdddc74fa1e26cdab306557 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 16 Jul 2022 21:40:10 +0300 Subject: [PATCH 006/134] Add missing const --- std/haxe/math/bigint/BigIntExceptions.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/std/haxe/math/bigint/BigIntExceptions.hx b/std/haxe/math/bigint/BigIntExceptions.hx index e3d3f883198..b50aaf2525e 100644 --- a/std/haxe/math/bigint/BigIntExceptions.hx +++ b/std/haxe/math/bigint/BigIntExceptions.hx @@ -27,4 +27,5 @@ class BigIntExceptions public static inline var INVALID_ARGUMENT = "invalid argument"; public static inline var BUFFER_TOO_SMALL = "buffer too small"; public static inline var DIVISION_BY_ZERO = "division by zero"; + public static inline var NEGATIVE_EXPONENT = "Negative exponent"; } \ No newline at end of file From 65bd87cc5520bca19b3ed328980a5e8bdcd01075 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 17 Jul 2022 16:49:17 +0300 Subject: [PATCH 007/134] Fiexes for Int32 ( javascript) --- std/haxe/math/bigint/BigIntHelper.hx | 2 +- std/haxe/math/bigint/MultiwordArithmetic.hx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/std/haxe/math/bigint/BigIntHelper.hx b/std/haxe/math/bigint/BigIntHelper.hx index e4bc3297e44..0b4574cffdf 100644 --- a/std/haxe/math/bigint/BigIntHelper.hx +++ b/std/haxe/math/bigint/BigIntHelper.hx @@ -65,7 +65,7 @@ class BigIntHelper greater than or equal to input `x`, which is interpreted as unsigned. **/ - public static function clp2(x : Int) : Int + public static function clp2(x : Int32) : Int { // From "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. Figure 3-3, p. 62. x = x - 1; diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 46c89d42839..3b9fe1fd0b8 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -461,7 +461,7 @@ class MultiwordArithmetic setZero(quotientOut, quotientLength); // Main loop. - var qhat : Int, rhat : Int, p : Int, t : Int; + var qhat : Int32, rhat : Int32, p : Int32, t : Int32; var vn : Int = getShort(work, n - 1); j = m - n + 1; while (--j >= 0) From 2979ee93ddfee5261f2c20b74b5d31ebf60e573c Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 18 Jul 2022 14:44:59 +0300 Subject: [PATCH 008/134] More fixes for Int32 --- std/haxe/math/bigint/BigIntArithmetic.hx | 4 +- std/haxe/math/bigint/MultiwordArithmetic.hx | 2 +- tests/unit/src/unit/TestBigInt.hx | 67 +++++++++++---------- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index b4b6fdfb086..2f71420afb9 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -98,7 +98,7 @@ class BigIntArithmetic public static function negate(result : MutableBigInt_, operand : BigInt_) : Void { var c : Int = 1; - var x : Int = 0; + var x : Int32 = 0; var z : Int = 0; result.ensureCapacity(operand.m_count + 1, result == operand); // overflow may add a digit for (i in 0 ... operand.m_count) @@ -236,7 +236,7 @@ class BigIntArithmetic **/ public static function subtract(result : MutableBigInt_, operand1 : BigInt_, operand2 : BigInt_) : Void { - var c : Int = 0; + var c : Int32 = 0; var x : Int = 0, y : Int = 0, z : Int = 0; if (operand1.m_count == operand2.m_count) { diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 3b9fe1fd0b8..5c2ea942632 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -670,7 +670,7 @@ class MultiwordArithmetic if (a != b) { var an : Int, bn : Int, d : Int; - var x : Int = -2147483648; + var x : Int32 = -2147483648; while (--length >= 0) { an = a.get(length) + x; diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 796956ef4ca..66b238ff461 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -14,6 +14,7 @@ import haxe.math.bigint.BigInt; import haxe.math.bigint.BigIntHelper; class TestBigInt extends Test { + public function testBigInt():Void { MutableBigInt_.s_testAllocation = false; bigIntAllChecks(); @@ -739,17 +740,17 @@ class TestBigInt extends Test { var am:MutableBigInt = a; var bm:MutableBigInt = b; - eq(expected.toHex(), (a * b).toHex()); - eq(expected.toHex(), (am * b).toHex()); - eq(expected.toHex(), (a * bm).toHex()); - eq(expected.toHex(), (am * bm).toHex()); + eq(expected.toString(), (a * b).toString()); + eq(expected.toString(), (am * b).toString()); + eq(expected.toString(), (a * bm).toString()); + eq(expected.toString(), (am * bm).toString()); am = a; am *= b; - eq(expected.toHex(), am.toHex()); + eq(expected.toString(), am.toString()); am = a; am *= bm; - eq(expected.toHex(), am.toHex()); + eq(expected.toString(), am.toString()); } private function checkDivInt(dividend:BigInt, divisor:Int, expectedQuotient:BigInt, expectedRemainder:Int):Void { @@ -790,32 +791,32 @@ class TestBigInt extends Test { var quotient:MutableBigInt = 0; var remainder:MutableBigInt = 0; BigIntArithmetic.divide(dividend, divisor, quotient, remainder); - eq(expectedRemainder.toHex(), remainder.toHex()); - eq(expectedQuotient.toHex(), quotient.toHex()); + eq(expectedRemainder.toString(), remainder.toString()); + eq(expectedQuotient.toString(), quotient.toString()); - eq(dividend.toHex(), (quotient * divisor + remainder).toHex()); + eq(dividend.toString(), (quotient * divisor + remainder).toString()); - eq(expectedQuotient.toHex(), (dividend / divisor).toHex()); - eq(expectedQuotient.toHex(), (dividendM / divisor).toHex()); - eq(expectedQuotient.toHex(), (dividend / divisorM).toHex()); - eq(expectedQuotient.toHex(), (dividendM / divisorM).toHex()); - eq(expectedRemainder.toHex(), (dividend % divisor).toHex()); - eq(expectedRemainder.toHex(), (dividendM % divisor).toHex()); - eq(expectedRemainder.toHex(), (dividend % divisorM).toHex()); - eq(expectedRemainder.toHex(), (dividendM % divisorM).toHex()); + eq(expectedQuotient.toString(), (dividend / divisor).toString()); + eq(expectedQuotient.toString(), (dividendM / divisor).toString()); + eq(expectedQuotient.toString(), (dividend / divisorM).toString()); + eq(expectedQuotient.toString(), (dividendM / divisorM).toString()); + eq(expectedRemainder.toString(), (dividend % divisor).toString()); + eq(expectedRemainder.toString(), (dividendM % divisor).toString()); + eq(expectedRemainder.toString(), (dividend % divisorM).toString()); + eq(expectedRemainder.toString(), (dividendM % divisorM).toString()); dividendM = dividend; dividendM /= divisor; - eq(expectedQuotient.toHex(), dividendM.toHex()); + eq(expectedQuotient.toString(), dividendM.toString()); dividendM = dividend; dividendM /= divisorM; - eq(expectedQuotient.toHex(), dividendM.toHex()); + eq(expectedQuotient.toString(), dividendM.toString()); dividendM = dividend; dividendM %= divisor; - eq(expectedRemainder.toHex(), dividendM.toHex()); + eq(expectedRemainder.toString(), dividendM.toString()); dividendM = dividend; dividendM %= divisorM; - eq(expectedRemainder.toHex(), dividendM.toHex()); + eq(expectedRemainder.toString(), dividendM.toString()); } public function bigIntEquality():Void { @@ -902,28 +903,28 @@ class TestBigInt extends Test { var em:MutableBigInt = expected; // addition - eq(expected.toHex(), (a + b).toHex()); - eq(expected.toHex(), (am + bm).toHex()); - eq(expected.toHex(), (am + b).toHex()); - eq(expected.toHex(), (a + bm).toHex()); + eq(expected.toString(), (a + b).toString()); + eq(expected.toString(), (am + bm).toString()); + eq(expected.toString(), (am + b).toString()); + eq(expected.toString(), (a + bm).toString()); am = a; am += b; - eq(expected.toHex(), am.toHex()); + eq(expected.toString(), am.toString()); am = a; am += bm; - eq(expected.toHex(), am.toHex()); + eq(expected.toString(), am.toString()); // subtraction - eq(a.toHex(), (expected - b).toHex()); - eq(a.toHex(), (expected - bm).toHex()); - eq(a.toHex(), (em - b).toHex()); - eq(a.toHex(), (em - bm).toHex()); + eq(a.toString(), (expected - b).toString()); + eq(a.toString(), (expected - bm).toString()); + eq(a.toString(), (em - b).toString()); + eq(a.toString(), (em - bm).toString()); em = expected; em -= b; - eq(a.toHex(), em.toHex()); + eq(a.toString(), em.toString()); em = expected; em -= bm; - eq(a.toHex(), em.toHex()); + eq(a.toString(), em.toString()); } public function bigIntAddAssignDoesntClobber():Void { From e0b02182979662ff9c28fbd33a9901fb48cab0eb Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 18 Jul 2022 17:06:37 +0300 Subject: [PATCH 009/134] Add trace for macro crash --- std/haxe/math/bigint/MultiwordArithmetic.hx | 1 + tests/unit/src/unit/TestBigInt.hx | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 5c2ea942632..d6bd39f29d9 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -353,6 +353,7 @@ class MultiwordArithmetic switch (dh) { case 0: + trace(" Divisor: "+divisor+", Length: "+divisorLength); throw BigIntExceptions.DIVISION_BY_ZERO; case 1: copy(quotientOut, dividend, dividendLength); // quotientLength == dividendLength diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 66b238ff461..cd8e58a2e63 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2668,6 +2668,21 @@ class TestBigInt extends Test { eq(10, bm.bitLength()); } + public function testMacroCrash():Void + { + trace("Start testMacroCrash") + var y:BigInt = BigInt.fromHex("080000000"); + var a:BigInt = BigInt.fromInt(1); + var x:BigInt = BigInt.fromHex("080000000"); + var b:BigInt = BigInt.fromInt(0); + + var y_b = y - b; + if (!y_b.isZero()) { + var q2 = y * a / y_b; + } + trace("End testMacroCrash"); + } + private static var s_primeNumbers = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; private static var s_notPrimeNumbers = [0,1,4,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30,32,33,34,35,36,38,39,40,42,44,45,46,48,49,50,51,52,54,55,56,57,58,60,62,63,64,65,66,68,69,70,72,74,75,76,77,78,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,102,104,105,106,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,132,133,134,135,136,138,140,141,142,143,144,145,146,147,148,150,152,153,154,155,156,158,159,160,161,162,164,165,166,168,169,170,171,172,174,175,176,177,178,180,182,183,184,185,186,187,188,189,190,192,194,195,196,198,200,201,202,203,204,205,206,207,208,209,210,212,213,214,215,216,217,218,219,220,221,222,224,225,226,228,230,231,232,234,235,236,237,238,240,242,243,244,245,246,247,248,249,250,252,253,254,255,256,258,259,260,261,262,264,265,266,267,268,270,272,273,274,275,276,278,279,280,282,284,285,286,287,288,289,290,291,292,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,312,314,315,316,318,319,320,321,322,323,324,325,326,327,328,329,330,332,333,334,335,336,338,339,340,341,342,343,344,345,346,348,350,351,352,354,355,356,357,358,360,361,362,363,364,365,366,368,369,370,371,372,374,375,376,377,378,380,381,382,384,385,386,387,388,390,391,392,393,394,395,396,398,399,400,402,403,404,405,406,407,408,410,411,412,413,414,415,416,417,418,420,422,423,424,425,426,427,428,429,430,432,434,435,436,437,438,440,441,442,444,445,446,447,448,450,451,452,453,454,455,456,458,459,460,462,464,465,466,468,469,470,471,472,473,474,475,476,477,478,480,481,482,483,484,485,486,488,489,490,492,493,494,495,496,497,498,500,501,502,504,505,506,507,508,510,511,512,513,514,515,516,517,518,519,520,522,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,542,543,544,545,546,548,549,550,551,552,553,554,555,556,558,559,560,561,562,564,565,566,567,568,570,572,573,574,575,576,578,579,580,581,582,583,584,585,586,588,589,590,591,592,594,595,596,597,598,600,602,603,604,605,606,608,609,610,611,612,614,615,616,618,620,621,622,623,624,625,626,627,628,629,630,632,633,634,635,636,637,638,639,640,642,644,645,646,648,649,650,651,652,654,655,656,657,658,660,662,663,664,665,666,667,668,669,670,671,672,674,675,676,678,679,680,681,682,684,685,686,687,688,689,690,692,693,694,695,696,697,698,699,700,702,703,704,705,706,707,708,710,711,712,713,714,715,716,717,718,720,721,722,723,724,725,726,728,729,730,731,732,734,735,736,737,738,740,741,742,744,745,746,747,748,749,750,752,753,754,755,756,758,759,760,762,763,764,765,766,767,768,770,771,772,774,775,776,777,778,779,780,781,782,783,784,785,786,788,789,790,791,792,793,794,795,796,798,799,800,801,802,803,804,805,806,807,808,810,812,813,814,815,816,817,818,819,820,822,824,825,826,828,830,831,832,833,834,835,836,837,838,840,841,842,843,844,845,846,847,848,849,850,851,852,854,855,856,858,860,861,862,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,882,884,885,886,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,908,909,910,912,913,914,915,916,917,918,920,921,922,923,924,925,926,927,928,930,931,932,933,934,935,936,938,939,940,942,943,944,945,946,948,949,950,951,952,954,955,956,957,958,959,960,961,962,963,964,965,966,968,969,970,972,973,974,975,976,978,979,980,981,982,984,985,986,987,988,989,990,992,993,994,995,996,998,999]; From b63329ff4f6b0dff07784917a4f2b37e86eacf61 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 18 Jul 2022 18:35:01 +0300 Subject: [PATCH 010/134] Fix missing ; --- tests/unit/src/unit/TestBigInt.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index cd8e58a2e63..d7ae5712ba0 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2670,7 +2670,7 @@ class TestBigInt extends Test { public function testMacroCrash():Void { - trace("Start testMacroCrash") + trace("Start testMacroCrash"); var y:BigInt = BigInt.fromHex("080000000"); var a:BigInt = BigInt.fromInt(1); var x:BigInt = BigInt.fromHex("080000000"); From 91688aceb92b092b4e8b03b1d75737fd53f1e0eb Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 18 Jul 2022 21:20:11 +0300 Subject: [PATCH 011/134] Fix macro test --- std/haxe/math/bigint/MultiwordArithmetic.hx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index d6bd39f29d9..7d169386913 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -347,13 +347,12 @@ class MultiwordArithmetic } // special cases - var dh : Int = divisor.get(divisorLength - 1); + var dh : Int32 = divisor.get(divisorLength - 1); if (divisorLength < 2) { switch (dh) { case 0: - trace(" Divisor: "+divisor+", Length: "+divisorLength); throw BigIntExceptions.DIVISION_BY_ZERO; case 1: copy(quotientOut, dividend, dividendLength); // quotientLength == dividendLength From 4da8487231b7158d6098ec418bea2f695eba8153 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 18 Jul 2022 22:05:06 +0300 Subject: [PATCH 012/134] Remove macrotest crash --- tests/unit/src/unit/TestBigInt.hx | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index d7ae5712ba0..66b238ff461 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2668,21 +2668,6 @@ class TestBigInt extends Test { eq(10, bm.bitLength()); } - public function testMacroCrash():Void - { - trace("Start testMacroCrash"); - var y:BigInt = BigInt.fromHex("080000000"); - var a:BigInt = BigInt.fromInt(1); - var x:BigInt = BigInt.fromHex("080000000"); - var b:BigInt = BigInt.fromInt(0); - - var y_b = y - b; - if (!y_b.isZero()) { - var q2 = y * a / y_b; - } - trace("End testMacroCrash"); - } - private static var s_primeNumbers = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; private static var s_notPrimeNumbers = [0,1,4,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30,32,33,34,35,36,38,39,40,42,44,45,46,48,49,50,51,52,54,55,56,57,58,60,62,63,64,65,66,68,69,70,72,74,75,76,77,78,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,102,104,105,106,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,132,133,134,135,136,138,140,141,142,143,144,145,146,147,148,150,152,153,154,155,156,158,159,160,161,162,164,165,166,168,169,170,171,172,174,175,176,177,178,180,182,183,184,185,186,187,188,189,190,192,194,195,196,198,200,201,202,203,204,205,206,207,208,209,210,212,213,214,215,216,217,218,219,220,221,222,224,225,226,228,230,231,232,234,235,236,237,238,240,242,243,244,245,246,247,248,249,250,252,253,254,255,256,258,259,260,261,262,264,265,266,267,268,270,272,273,274,275,276,278,279,280,282,284,285,286,287,288,289,290,291,292,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,312,314,315,316,318,319,320,321,322,323,324,325,326,327,328,329,330,332,333,334,335,336,338,339,340,341,342,343,344,345,346,348,350,351,352,354,355,356,357,358,360,361,362,363,364,365,366,368,369,370,371,372,374,375,376,377,378,380,381,382,384,385,386,387,388,390,391,392,393,394,395,396,398,399,400,402,403,404,405,406,407,408,410,411,412,413,414,415,416,417,418,420,422,423,424,425,426,427,428,429,430,432,434,435,436,437,438,440,441,442,444,445,446,447,448,450,451,452,453,454,455,456,458,459,460,462,464,465,466,468,469,470,471,472,473,474,475,476,477,478,480,481,482,483,484,485,486,488,489,490,492,493,494,495,496,497,498,500,501,502,504,505,506,507,508,510,511,512,513,514,515,516,517,518,519,520,522,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,542,543,544,545,546,548,549,550,551,552,553,554,555,556,558,559,560,561,562,564,565,566,567,568,570,572,573,574,575,576,578,579,580,581,582,583,584,585,586,588,589,590,591,592,594,595,596,597,598,600,602,603,604,605,606,608,609,610,611,612,614,615,616,618,620,621,622,623,624,625,626,627,628,629,630,632,633,634,635,636,637,638,639,640,642,644,645,646,648,649,650,651,652,654,655,656,657,658,660,662,663,664,665,666,667,668,669,670,671,672,674,675,676,678,679,680,681,682,684,685,686,687,688,689,690,692,693,694,695,696,697,698,699,700,702,703,704,705,706,707,708,710,711,712,713,714,715,716,717,718,720,721,722,723,724,725,726,728,729,730,731,732,734,735,736,737,738,740,741,742,744,745,746,747,748,749,750,752,753,754,755,756,758,759,760,762,763,764,765,766,767,768,770,771,772,774,775,776,777,778,779,780,781,782,783,784,785,786,788,789,790,791,792,793,794,795,796,798,799,800,801,802,803,804,805,806,807,808,810,812,813,814,815,816,817,818,819,820,822,824,825,826,828,830,831,832,833,834,835,836,837,838,840,841,842,843,844,845,846,847,848,849,850,851,852,854,855,856,858,860,861,862,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,882,884,885,886,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,908,909,910,912,913,914,915,916,917,918,920,921,922,923,924,925,926,927,928,930,931,932,933,934,935,936,938,939,940,942,943,944,945,946,948,949,950,951,952,954,955,956,957,958,959,960,961,962,963,964,965,966,968,969,970,972,973,974,975,976,978,979,980,981,982,984,985,986,987,988,989,990,992,993,994,995,996,998,999]; From 99adeca21fb6f9fa345431b786d11f04ae700358 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 19 Jul 2022 11:11:52 +0300 Subject: [PATCH 013/134] Fix Int32 (python) --- std/haxe/math/bigint/MultiwordArithmetic.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 7d169386913..05210705356 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -739,7 +739,7 @@ class MultiwordArithmetic } var pos : Int = 0; var bit : Int = 0; - var acc : Int = 0; + var acc : Int32 = 0; while (index > start) { c = value.charCodeAt(--index); From f7c405ffe55a97304de6ffaf02ca6a6c21f3e885 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 19 Jul 2022 15:03:48 +0300 Subject: [PATCH 014/134] More fixes --- std/haxe/math/bigint/BigIntHelper.hx | 6 +++--- std/haxe/math/bigint/MutableBigInt_.hx | 4 ++-- tests/unit/src/unit/TestBigInt.hx | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/std/haxe/math/bigint/BigIntHelper.hx b/std/haxe/math/bigint/BigIntHelper.hx index 0b4574cffdf..16c9d6c7a66 100644 --- a/std/haxe/math/bigint/BigIntHelper.hx +++ b/std/haxe/math/bigint/BigIntHelper.hx @@ -94,7 +94,7 @@ class BigIntHelper Result is undefined when `divisor` <= 0 or `divisor` >= 2^16. **/ - public static function u32divu16(dividend : Int, divisor : Int) : Int + public static function u32divu16(dividend : Int32, divisor : Int32) : Int { /* Complicated because Haxe's division is always performed as @@ -108,7 +108,7 @@ class BigIntHelper // From "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. Section 9-3, p. 192. var t : Int = divisor >> 31; var nprime : Int = dividend & ~t; - var q : Int = Std.int((nprime >>> 1) / divisor) << 1; + var q : Int32 = Std.int((nprime >>> 1) / divisor) << 1; var r : Int = dividend - q * divisor; var c : Int = u32geu32(r, divisor) ? 1 : 0; return q + c; @@ -128,7 +128,7 @@ class BigIntHelper Number of trailing zeros - return the number of trailing 0-value bits **/ - public static function ntz( x : Int ):Int + public static function ntz( x : Int32 ):Int { if (x == 0) return 32; var y:Int; diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index 1e31f13be9a..dd951414e05 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -230,7 +230,7 @@ class MutableBigInt_ extends BigInt_ // Private implementation //----------------------------------------------------------------------- - private inline function setShort(n : Int, v : Int) : Void + private inline function setShort(n : Int32, v : Int32) : Void { var s : Int = (n & 1) << 4; var t : Int = m_data.get(n >> 1) & (~0xffff >>> s); @@ -366,7 +366,7 @@ class MutableBigInt_ extends BigInt_ ensureCapacity(((index + 7) >> 3) + extra, false); var pos = -1; var bit : Int = 32; - var c : Int = 0; + var c : Int32 = 0; while (index > 0) { c = value.charCodeAt(--index); diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 66b238ff461..1fe0099a43b 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -103,10 +103,10 @@ class TestBigInt extends Test { v1[1] = 1; v1[2] = -2147483648; t1.setFromUnsignedInts(v1, 3); - eq(BigInt.fromHexUnsigned("80000000 00000001 00000000").toHex(), t1.toHex()); + eq(BigInt.fromHexUnsigned("80000000 00000001 00000000").toString(), t1.toString()); v1[1] = -2147483648; t1.setFromUnsignedInts(v1, 2); - eq(BigInt.fromHexUnsigned("80000000 00000000").toHex(), t1.toHex()); + eq(BigInt.fromHexUnsigned("80000000 00000000").toString(), t1.toString()); } function bigIntSetFromUnsignedInts():Void { @@ -130,7 +130,7 @@ class TestBigInt extends Test { private function checkSetFromBytesUnsigned(hex:String):Void { var t:MutableBigInt = 0; t.setFromBigEndianBytesUnsigned(Bytes.ofHex(hex)); - eq(BigInt.fromHexUnsigned(hex).toHex(), t.toHex()); + eq(BigInt.fromHexUnsigned(hex).toString(), t.toString()); var sb = new StringBuf(); var i = hex.length; @@ -140,14 +140,14 @@ class TestBigInt extends Test { sb.addChar(hex.charCodeAt(i + 1)); } t.setFromLittleEndianBytesUnsigned(Bytes.ofHex(sb.toString())); - eq(BigInt.fromHexUnsigned(hex).toHex(), t.toHex()); + eq(BigInt.fromHexUnsigned(hex).toString(), t.toString()); } private function checkSetFromUnsignedInts(hex:String, arr:Array):Void { var v = Vector.fromArrayCopy(arr); var t:MutableBigInt = 0; t.setFromUnsignedInts(v, v.length); - eq(BigInt.fromHexUnsigned(hex).toHex(), t.toHex()); + eq(BigInt.fromHexUnsigned(hex).toString(), t.toString()); } public function bigIntCompare():Void { From c5dfc60b30710d7275f4a98c215de475af17831a Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 19 Jul 2022 19:41:48 +0300 Subject: [PATCH 015/134] More fixes for python --- std/haxe/math/bigint/BigIntArithmetic.hx | 2 +- tests/unit/src/unit/TestBigInt.hx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 2f71420afb9..09587ca435c 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -190,7 +190,7 @@ class BigIntArithmetic public static function addInt(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void { var c : Int = 0; - var x : Int; + var x : Int32; var y : Int = operand2; var z : Int; diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 1fe0099a43b..83ba0239fff 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -877,10 +877,10 @@ class TestBigInt extends Test { private function checkAddInt(a:BigInt, b:Int, expected:BigInt):Void { var am:MutableBigInt = a; - eq(expected.toHex(), (a + b).toHex()); - eq(expected.toHex(), (am + b).toHex()); + eq(expected.toString(), (a + b).toString()); + eq(expected.toString(), (am + b).toString()); am += b; - eq(expected.toHex(), am.toHex()); + eq(expected.toString(), am.toString()); checkAdd(a, BigInt.fromInt(b), expected); } From 2dca9df115e7cb469a6e982523f65313a9237063 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 19 Jul 2022 22:24:36 +0300 Subject: [PATCH 016/134] more fixes --- std/haxe/math/bigint/MultiwordArithmetic.hx | 2 +- tests/unit/src/unit/TestBigInt.hx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 05210705356..f3d64aebb78 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -951,7 +951,7 @@ class MultiwordArithmetic return (v.get(n >> 1) >> ((n & 1) << 4)) & 0xffff; } - private static inline function setShort(a : Vector, n : Int, v : Int) : Void + private static inline function setShort(a : Vector, n : Int, v : Int32) : Void { var s : Int = (n & 1) << 4; var t : Int = a.get(n >> 1) & (~0xffff >>> s); diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 83ba0239fff..b93e62276bc 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -760,16 +760,16 @@ class TestBigInt extends Test { var remainder:Int; remainder = BigIntArithmetic.divideInt(dividend, divisor, quotient); eq(expectedRemainder, remainder); - eq(expectedQuotient.toHex(), quotient.toHex()); + eq(expectedQuotient.toString(), quotient.toString()); - eq(expectedQuotient.toHex(), (dividend / divisor).toHex()); - eq(expectedQuotient.toHex(), (dividendM / divisor).toHex()); + eq(expectedQuotient.toString(), (dividend / divisor).toString()); + eq(expectedQuotient.toString(), (dividendM / divisor).toString()); eq(expectedRemainder, (dividend % divisor)); eq(expectedRemainder, (dividendM % divisor)); dividendM = dividend; dividendM /= divisor; - eq(expectedQuotient.toHex(), dividendM.toHex()); + eq(expectedQuotient.toString(), dividendM.toString()); dividendM = dividend; dividendM %= divisor; eq(Std.string(expectedRemainder), dividendM.toString()); @@ -989,8 +989,8 @@ class TestBigInt extends Test { var a:MutableBigInt = 1; for (i in 0...96) { - eq(a.toHex(), BigInt.fromString(s_powersOfTwo[i]).toHex()); - eq((-a).toHex(), BigInt.fromString("-" + s_powersOfTwo[i]).toHex()); + eq(a.toString(), BigInt.fromString(s_powersOfTwo[i]).toString()); + eq((-a).toString(), BigInt.fromString("-" + s_powersOfTwo[i]).toString()); a <<= 1; } } From 984a69687dcc59eb08e534e56726a7368caf1e1b Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 22 Jul 2022 21:36:50 +0300 Subject: [PATCH 017/134] Fix for Python target --- std/haxe/math/bigint/BigIntArithmetic.hx | 6 +++--- std/haxe/math/bigint/MultiwordArithmetic.hx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 09587ca435c..5315be68bc7 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -705,7 +705,7 @@ class BigIntArithmetic // assumes 0 < shift < 32 // ok if output == input - private static inline function asl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int) : Void + private static inline function asl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int32) : Void { var x : Int = input.get(inputSize - 1) >> 31; // sign extend var r : Int = 32 - shift; @@ -723,7 +723,7 @@ class BigIntArithmetic // assumes 0 < shift < 32 // ok if output == input - private static inline function lsl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int) : Void + private static inline function lsl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int32) : Void { var x : Int = 0; var r : Int = 32 - shift; @@ -741,7 +741,7 @@ class BigIntArithmetic // assumes 0 < shift < 32 // ok if output == input - private static inline function lsr32(output : Vector, input : Vector, inputSize : Int, inputOffset : Int, shift : Int) : Void + private static inline function lsr32(output : Vector, input : Vector, inputSize : Int, inputOffset : Int, shift : Int32) : Void { var r : Int = 32 - shift; var i : Int = 0; diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index f3d64aebb78..08bdbd68ca9 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -899,7 +899,7 @@ class MultiwordArithmetic // assumes 0 < shiftBits < 32 // assumes shiftDigits < length - private static function _asr32(result : Vector, input : Vector, length : Int, shiftDigits : Int, shiftBits : Int) : Void + private static function _asr32(result : Vector, input : Vector, length : Int, shiftDigits : Int, shiftBits : Int32) : Void { var r : Int = 32 - shiftBits; var i : Int = 0; @@ -913,7 +913,7 @@ class MultiwordArithmetic // assumes 0 < shift < 32 // ok if output == input - private static function _lsr32(output : Vector, input : Vector, inputSize : Int, inputOffset : Int, shift : Int) : Void + private static function _lsr32(output : Vector, input : Vector, inputSize : Int, inputOffset : Int, shift : Int32) : Void { var r : Int = 32 - shift; var i : Int = 0; From 2f45acc2cb71288dd87dd9ac3769782517a36e5e Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 22 Jul 2022 22:50:04 +0300 Subject: [PATCH 018/134] Correct test for mutable bigint --- tests/unit/src/unit/TestBigInt.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index b93e62276bc..f108424594f 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2616,13 +2616,13 @@ class TestBigInt extends Test { { for(i in 0...s_primeNumbers.length) { var b:BigInt = s_primeNumbers[i]; - var bm:BigInt = s_primeNumbers[i]; + var bm:MutableBigInt = s_primeNumbers[i]; t(b.isProbablePrime(5)); t(bm.isProbablePrime(5)); } for(i in 0...s_notPrimeNumbers.length) { var b:BigInt = s_notPrimeNumbers[i]; - var bm:BigInt = s_notPrimeNumbers[i]; + var bm:MutableBigInt = s_notPrimeNumbers[i]; f(b.isProbablePrime(5)); f(bm.isProbablePrime(5)); } From 39e31fa8f041235a93df3cd86baf3b2b752071e1 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 24 Jul 2022 16:04:06 +0300 Subject: [PATCH 019/134] Add method to create BigInt from bytes --- std/haxe/math/bigint/BigInt.hx | 5 ++++ std/haxe/math/bigint/BigInt_.hx | 10 ++++++++ std/haxe/math/bigint/MutableBigInt_.hx | 35 ++++++++++++++++++++++++++ tests/unit/src/unit/TestBigInt.hx | 26 ++++++++++++++++--- 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 6617e849563..3311dac0a12 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -105,6 +105,11 @@ abstract BigInt(BigInt_) { return new BigInt(BigInt_.fromUnsignedInts(value, length)); } + + public static inline function fromBytes(value : Bytes, offset : Int = 0, length : Int = 0) : BigInt + { + return new BigInt(BigInt_.fromBytes(value, offset, length)); + } public inline function getBit(index : Int) : Int { diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 1f15711f7ab..835319d648a 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -251,6 +251,16 @@ class BigInt_ bi.setFromHexUnsigned(value); return bi; } + + /** + Creates a big integer with the signed value represented by bytes + **/ + public static function fromBytes(value : Bytes, offset : Int = 0, length : Int = 0) : BigInt_ + { + var bi = new MutableBigInt_(); + bi.setFromBigEndianBytesSigned(value, offset, length); + return bi; + } /** Creates a big integer with the value represented by the integer vector `value`. diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index dd951414e05..86e3ea2bc85 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -116,6 +116,41 @@ class MutableBigInt_ extends BigInt_ m_count = length + neg; compact(); } + + public function setFromBigEndianBytesSigned(value:Bytes, offset:Int = 0, valueLength:Int = 0):Void + { + if ( value == null) { + throw BigIntExceptions.INVALID_ARGUMENT; + } + if (valueLength <= 0) { + valueLength = value.length; + } + if (offset + valueLength > value.length) { + throw BigIntExceptions.BUFFER_TOO_SMALL; + } + if (valueLength < 1) { + setFromInt(0); + return; + } + var length = (valueLength + 3) >> 2; + ensureCapacity(length, false); + m_data.set(length - 1, 0); + var pos = 0; + var i = offset + valueLength; + while (i >= offset + 4) { + m_data.set(pos++, (value.get(i - 1) << 0) | (value.get(i - 2) << 8) | (value.get(i - 3) << 16) | (value.get(i - 4) << 24)); + i -= 4; + } + if (i > offset) { + var x:Int = 0; + for (j in offset...i) { + x = (x << 8) | value.get(j); + } + m_data.set(pos++, x); + } + m_count = length; + compact(); + } public function setFromBigEndianBytesUnsigned(value : Bytes, offset : Int = 0, valueLength : Int = 0) : Void { diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index f108424594f..0712820fe2e 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -42,6 +42,7 @@ class TestBigInt extends Test { bigIntAddAssignDoesntClobber(); bigIntNegate(); bigIntFromString(); + bigIntFromBytes(); bigIntArithmeticShiftLeftAssignDoesntClobber(); bigIntArithmeticShiftRightAssignDoesntClobber(); bigIntArithmeticShiftLeft(); @@ -994,6 +995,23 @@ class TestBigInt extends Test { a <<= 1; } } + + public function bigIntFromBytes():Void + { + try { + var x = BigInt.fromBytes(null); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + eq("0", BigInt.fromBytes(Bytes.ofHex("00")).toString()); + eq("1", BigInt.fromBytes(Bytes.ofHex("01")).toString()); + eq("ffffffff", BigInt.fromBytes(Bytes.ofHex("ffffffff")).toHex()); + eq("100", BigInt.fromBytes(Bytes.ofHex("64")).toString()); + eq(BigInt.fromInt(-100).toHex(), BigInt.fromBytes(Bytes.ofHex("ffffff9c")).toHex()); + eq("7fffffff", BigInt.fromBytes(Bytes.ofHex("7fffffff")).toHex()); + eq(BigInt.fromInt(-2147483648).toHex(), BigInt.fromBytes(Bytes.ofHex("80000000")).toHex()); + eq(BigInt.fromHex("f7fffffff").toHex(), BigInt.fromBytes(Bytes.ofHex("ffffffff7fffffff")).toHex()); + } public function bigIntArithmeticShiftLeftAssignDoesntClobber():Void { var a:BigInt = BigInt.fromInt(1); @@ -2617,14 +2635,14 @@ class TestBigInt extends Test { for(i in 0...s_primeNumbers.length) { var b:BigInt = s_primeNumbers[i]; var bm:MutableBigInt = s_primeNumbers[i]; - t(b.isProbablePrime(5)); - t(bm.isProbablePrime(5)); + t(b.isProbablePrime(10)); + t(bm.isProbablePrime(10)); } for(i in 0...s_notPrimeNumbers.length) { var b:BigInt = s_notPrimeNumbers[i]; var bm:MutableBigInt = s_notPrimeNumbers[i]; - f(b.isProbablePrime(5)); - f(bm.isProbablePrime(5)); + f(b.isProbablePrime(10)); + f(bm.isProbablePrime(10)); } } From 7b5b70bc1459d713fc34ee72958b63bee11ca1bd Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 25 Jul 2022 11:40:12 +0300 Subject: [PATCH 020/134] Add auto convert from String --- std/haxe/math/bigint/BigInt.hx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 3311dac0a12..1e1f81d0ca6 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -341,6 +341,11 @@ abstract BigInt(BigInt_) { return new BigInt(BigInt_.fromInt(a)); } + + @:from @:noCompletion public static inline function fromString_(a : String) : BigInt + { + return new BigInt(BigInt_.fromString(a)); + } @:to @:noCompletion public inline function toBigInt_() : BigInt_ { From 464879046160001487e22bff321b294924fc463d Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 25 Jul 2022 17:17:06 +0300 Subject: [PATCH 021/134] Add greater common divisor (gcd) of two BigInt values --- std/haxe/math/bigint/BigInt.hx | 6 +++++ std/haxe/math/bigint/BigInt_.hx | 13 ++++++++++ std/haxe/math/bigint/MutableBigInt.hx | 5 ++++ tests/unit/src/unit/TestBigInt.hx | 35 +++++++++++++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 1e1f81d0ca6..bb890e36411 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -121,6 +121,12 @@ abstract BigInt(BigInt_) return new BigInt(this.abs()); } + // Finds the greatest common denominator of this and b + public function gcd(b:BigInt) : BigInt + { + return new BigInt(this.gcd(b)); + } + public function pow(exponent:UInt) : BigInt { return new BigInt(BigInt_.pow(exponent,this)); diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 835319d648a..c69c8c3f8ad 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -43,6 +43,19 @@ class BigInt_ return r; } + public function gcd( b : BigInt_) : BigInt_ + { + var m:BigInt_ = this.abs(); + b = b.abs(); + var t:BigInt_; + while ( !equals2Int(b, 0) ) { + t = m; + m = b; + b = modulus2(t , m); + } + return m; + } + /** Returns `true` if this big integer is equivalent to 0, otherwise returns `false`. **/ diff --git a/std/haxe/math/bigint/MutableBigInt.hx b/std/haxe/math/bigint/MutableBigInt.hx index e7a79007329..c3bca41a045 100644 --- a/std/haxe/math/bigint/MutableBigInt.hx +++ b/std/haxe/math/bigint/MutableBigInt.hx @@ -127,6 +127,11 @@ abstract MutableBigInt(MutableBigInt_) return this.abs(); } + public function gcd(b:BigInt) : MutableBigInt + { + return this.gcd(b); + } + public function pow(exponent:UInt) : MutableBigInt { return BigInt_.pow(exponent,this); diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 0712820fe2e..65608f40608 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2686,6 +2686,41 @@ class TestBigInt extends Test { eq(10, bm.bitLength()); } + public function testGcd():Void + { + var gcdCache = new Array>(); + var a:BigInt ,b:BigInt; + for(i in 0...255) { + gcdCache[i] = new Array(); + var j = i; + a = i; + while ( j >=0 ) { + b = j; + gcdCache[i][j] = gcdCache[j][i] = Std.parseInt(a.gcd(b).toString()); + j--; + } + } + for(i in 0...255) { + eq(i,gcdCache[i][0]); + eq(1,gcdCache[i][1]); + } + a = 259; + b = 261; + eq("1",a.gcd(b).toString()); + a = 42; + b = -7; + eq("7",b.gcd(a).toString()); + a = 255*3; + b = 255*5; + eq("255",a.gcd(b).toString()); + a = 128; // 256/2 + b = 64; // 256/4 + eq("64",a.gcd(b).toString()); + a = 6; + b = 3; + eq("3",a.gcd(b).toString()); + } + private static var s_primeNumbers = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; private static var s_notPrimeNumbers = [0,1,4,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30,32,33,34,35,36,38,39,40,42,44,45,46,48,49,50,51,52,54,55,56,57,58,60,62,63,64,65,66,68,69,70,72,74,75,76,77,78,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,102,104,105,106,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,132,133,134,135,136,138,140,141,142,143,144,145,146,147,148,150,152,153,154,155,156,158,159,160,161,162,164,165,166,168,169,170,171,172,174,175,176,177,178,180,182,183,184,185,186,187,188,189,190,192,194,195,196,198,200,201,202,203,204,205,206,207,208,209,210,212,213,214,215,216,217,218,219,220,221,222,224,225,226,228,230,231,232,234,235,236,237,238,240,242,243,244,245,246,247,248,249,250,252,253,254,255,256,258,259,260,261,262,264,265,266,267,268,270,272,273,274,275,276,278,279,280,282,284,285,286,287,288,289,290,291,292,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,312,314,315,316,318,319,320,321,322,323,324,325,326,327,328,329,330,332,333,334,335,336,338,339,340,341,342,343,344,345,346,348,350,351,352,354,355,356,357,358,360,361,362,363,364,365,366,368,369,370,371,372,374,375,376,377,378,380,381,382,384,385,386,387,388,390,391,392,393,394,395,396,398,399,400,402,403,404,405,406,407,408,410,411,412,413,414,415,416,417,418,420,422,423,424,425,426,427,428,429,430,432,434,435,436,437,438,440,441,442,444,445,446,447,448,450,451,452,453,454,455,456,458,459,460,462,464,465,466,468,469,470,471,472,473,474,475,476,477,478,480,481,482,483,484,485,486,488,489,490,492,493,494,495,496,497,498,500,501,502,504,505,506,507,508,510,511,512,513,514,515,516,517,518,519,520,522,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,542,543,544,545,546,548,549,550,551,552,553,554,555,556,558,559,560,561,562,564,565,566,567,568,570,572,573,574,575,576,578,579,580,581,582,583,584,585,586,588,589,590,591,592,594,595,596,597,598,600,602,603,604,605,606,608,609,610,611,612,614,615,616,618,620,621,622,623,624,625,626,627,628,629,630,632,633,634,635,636,637,638,639,640,642,644,645,646,648,649,650,651,652,654,655,656,657,658,660,662,663,664,665,666,667,668,669,670,671,672,674,675,676,678,679,680,681,682,684,685,686,687,688,689,690,692,693,694,695,696,697,698,699,700,702,703,704,705,706,707,708,710,711,712,713,714,715,716,717,718,720,721,722,723,724,725,726,728,729,730,731,732,734,735,736,737,738,740,741,742,744,745,746,747,748,749,750,752,753,754,755,756,758,759,760,762,763,764,765,766,767,768,770,771,772,774,775,776,777,778,779,780,781,782,783,784,785,786,788,789,790,791,792,793,794,795,796,798,799,800,801,802,803,804,805,806,807,808,810,812,813,814,815,816,817,818,819,820,822,824,825,826,828,830,831,832,833,834,835,836,837,838,840,841,842,843,844,845,846,847,848,849,850,851,852,854,855,856,858,860,861,862,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,882,884,885,886,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,908,909,910,912,913,914,915,916,917,918,920,921,922,923,924,925,926,927,928,930,931,932,933,934,935,936,938,939,940,942,943,944,945,946,948,949,950,951,952,954,955,956,957,958,959,960,961,962,963,964,965,966,968,969,970,972,973,974,975,976,978,979,980,981,982,984,985,986,987,988,989,990,992,993,994,995,996,998,999]; From 45980efa8036cbba3c6308f0820bc93667dfef6b Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 26 Jul 2022 10:53:20 +0300 Subject: [PATCH 022/134] Add lcm,min,max,nextprobableprime methods --- std/haxe/math/bigint/BigInt.hx | 20 +++++++++++++- std/haxe/math/bigint/BigInt_.hx | 33 +++++++++++++++++++++++ tests/unit/src/unit/TestBigInt.hx | 45 +++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index bb890e36411..910eb83cd1f 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -55,6 +55,14 @@ abstract BigInt(BigInt_) { return BigInt_.isNegative1(this); } + + public inline function min(other : BigInt ) : BigInt { + return new BigInt(this.min(other)); + } + + public inline function max(other : BigInt) : BigInt { + return new BigInt(this.max(other)); + } public inline function toString() : String { @@ -127,6 +135,11 @@ abstract BigInt(BigInt_) return new BigInt(this.gcd(b)); } + public function lcm( b : BigInt) : BigInt + { + return new BigInt(this.lcm(b)); + } + public function pow(exponent:UInt) : BigInt { return new BigInt(BigInt_.pow(exponent,this)); @@ -137,10 +150,15 @@ abstract BigInt(BigInt_) return new BigInt(BigInt_.modPow(exponent,modulus,this)); } - public function isProbablePrime(tolerance:UInt):Bool + public function isProbablePrime(tolerance:UInt) : Bool { return this.isProbablePrime(tolerance); } + + public function nextProbablePrime() : BigInt + { + return new BigInt(this.nextProbablePrime()); + } public function getLowestSetBit():Int { diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index c69c8c3f8ad..c7cb0e61de5 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -56,6 +56,16 @@ class BigInt_ return m; } + /** + Calculates the least common multiple of the specified big integer numbers. + **/ + public function lcm( b : BigInt_) : BigInt_ + { + var m:BigInt_ = this.abs(); + var n:BigInt_ = b.abs(); + return BigInt_.divide2(BigInt_.multiply2(m,n),m.gcd(n)); + } + /** Returns `true` if this big integer is equivalent to 0, otherwise returns `false`. **/ @@ -121,6 +131,21 @@ class BigInt_ rounds = (tolerance 0) ? this : other; + } /** Get the value in decimal form. diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 65608f40608..dd2da068c42 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2721,6 +2721,51 @@ class TestBigInt extends Test { eq("3",a.gcd(b).toString()); } + public function testLcm():Void + { + var a:BigInt ,b:BigInt; + a = 12; b = 15; + eq("60",a.lcm(b).toString()); + a = 30; b = 25; + eq("150",a.lcm(b).toString()); + a = 26; b = 20; + eq("260",a.lcm(b).toString()); + a = "234516789234023485693020129"; b = "176892058718950472893785940"; + eq("41484157651764614525905399263631111992263435437186260",a.lcm(b).toString()); + a = "36594652830916364940473625749407"; b = "448507083624364748494746353648484939"; + eq("443593541011902763984944550799004089258248037004507648321189937329",a.lcm(b).toString()); + } + + public function testMaxMin():Void + { + var a:BigInt ,b:BigInt; + a = -1; b = 23; + eq("-1",a.min(b).toString()); + eq("-1",b.min(a).toString()); + a = 2399; b= 692421; + eq("692421",b.max(a).toString()); + eq("692421",a.max(b).toString()); + } + + public function testNextProbablePrime():Void + { + var a:BigInt; + a = "8329132432461"; + eq("8329132432469",a.nextProbablePrime().toString()); + a = 269234; + eq("269237",a.nextProbablePrime().toString()); + a = 409993; + eq("409999",a.nextProbablePrime().toString()); + a = 950091; + eq("950099",a.nextProbablePrime().toString()); + a = 141682; + eq("141689",a.nextProbablePrime().toString()); + a = 40870716; + eq("40870721",a.nextProbablePrime().toString()); + a = 32747015; + eq("32747023",a.nextProbablePrime().toString()); + } + private static var s_primeNumbers = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; private static var s_notPrimeNumbers = [0,1,4,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30,32,33,34,35,36,38,39,40,42,44,45,46,48,49,50,51,52,54,55,56,57,58,60,62,63,64,65,66,68,69,70,72,74,75,76,77,78,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,102,104,105,106,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,132,133,134,135,136,138,140,141,142,143,144,145,146,147,148,150,152,153,154,155,156,158,159,160,161,162,164,165,166,168,169,170,171,172,174,175,176,177,178,180,182,183,184,185,186,187,188,189,190,192,194,195,196,198,200,201,202,203,204,205,206,207,208,209,210,212,213,214,215,216,217,218,219,220,221,222,224,225,226,228,230,231,232,234,235,236,237,238,240,242,243,244,245,246,247,248,249,250,252,253,254,255,256,258,259,260,261,262,264,265,266,267,268,270,272,273,274,275,276,278,279,280,282,284,285,286,287,288,289,290,291,292,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,312,314,315,316,318,319,320,321,322,323,324,325,326,327,328,329,330,332,333,334,335,336,338,339,340,341,342,343,344,345,346,348,350,351,352,354,355,356,357,358,360,361,362,363,364,365,366,368,369,370,371,372,374,375,376,377,378,380,381,382,384,385,386,387,388,390,391,392,393,394,395,396,398,399,400,402,403,404,405,406,407,408,410,411,412,413,414,415,416,417,418,420,422,423,424,425,426,427,428,429,430,432,434,435,436,437,438,440,441,442,444,445,446,447,448,450,451,452,453,454,455,456,458,459,460,462,464,465,466,468,469,470,471,472,473,474,475,476,477,478,480,481,482,483,484,485,486,488,489,490,492,493,494,495,496,497,498,500,501,502,504,505,506,507,508,510,511,512,513,514,515,516,517,518,519,520,522,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,542,543,544,545,546,548,549,550,551,552,553,554,555,556,558,559,560,561,562,564,565,566,567,568,570,572,573,574,575,576,578,579,580,581,582,583,584,585,586,588,589,590,591,592,594,595,596,597,598,600,602,603,604,605,606,608,609,610,611,612,614,615,616,618,620,621,622,623,624,625,626,627,628,629,630,632,633,634,635,636,637,638,639,640,642,644,645,646,648,649,650,651,652,654,655,656,657,658,660,662,663,664,665,666,667,668,669,670,671,672,674,675,676,678,679,680,681,682,684,685,686,687,688,689,690,692,693,694,695,696,697,698,699,700,702,703,704,705,706,707,708,710,711,712,713,714,715,716,717,718,720,721,722,723,724,725,726,728,729,730,731,732,734,735,736,737,738,740,741,742,744,745,746,747,748,749,750,752,753,754,755,756,758,759,760,762,763,764,765,766,767,768,770,771,772,774,775,776,777,778,779,780,781,782,783,784,785,786,788,789,790,791,792,793,794,795,796,798,799,800,801,802,803,804,805,806,807,808,810,812,813,814,815,816,817,818,819,820,822,824,825,826,828,830,831,832,833,834,835,836,837,838,840,841,842,843,844,845,846,847,848,849,850,851,852,854,855,856,858,860,861,862,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,882,884,885,886,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,908,909,910,912,913,914,915,916,917,918,920,921,922,923,924,925,926,927,928,930,931,932,933,934,935,936,938,939,940,942,943,944,945,946,948,949,950,951,952,954,955,956,957,958,959,960,961,962,963,964,965,966,968,969,970,972,973,974,975,976,978,979,980,981,982,984,985,986,987,988,989,990,992,993,994,995,996,998,999]; From 4f99754259d5f8122f64c0325920b0ba7bb01540 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 26 Jul 2022 13:29:02 +0300 Subject: [PATCH 023/134] Add method to create random BigInt --- std/haxe/math/bigint/BigInt.hx | 5 +++++ std/haxe/math/bigint/BigInt_.hx | 13 ++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 910eb83cd1f..082cd4e4e7f 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -118,6 +118,11 @@ abstract BigInt(BigInt_) { return new BigInt(BigInt_.fromBytes(value, offset, length)); } + + public static inline function random(bits : Int32):BigInt + { + return new BigInt(BigInt_.random(bits)); + } public inline function getBit(index : Int) : Int { diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index c7cb0e61de5..5e84a3f11ff 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -398,17 +398,16 @@ class BigInt_ } } - private function random():BigInt_ + public static function random(bits:Int32 = 0):BigInt_ { var r = new MutableBigInt_(); - var countBits:Int = bitLength(); - var countBytes:Int = Std.int((countBits+7)/8); + var countBytes:Int = Std.int((bits+7)/8); var randomBytes = Bytes.alloc(countBytes); for(j in 0...countBytes) { - var rnd = Std.int(( Math.random() * 256 )); - randomBytes.set(j,rnd); + var rndN = Math.floor( Math.random() * 256 ); + randomBytes.set(j,rndN); } - r.setFromHexUnsigned(randomBytes.toHex()); + r.setFromBigEndianBytesUnsigned(randomBytes); r.compact(); return r; } @@ -423,7 +422,7 @@ class BigInt_ var num:BigInt_; for(i in 0...rounds) { do { - num =random(); + num = random(bitLength()); } while (BigIntArithmetic.compare(num, BigInt.ONE) <= 0 || BigIntArithmetic.compare(num, this) >= 0 ); var z:BigInt_ = BigInt_.modPow(m,this,num); if ( BigIntArithmetic.compare(z, BigInt.ONE) != 0 && BigIntArithmetic.compare(z, minusOne) != 0) { From d2916d707d6f621f940e8730b201dc8e9e873eb0 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 26 Jul 2022 15:11:51 +0300 Subject: [PATCH 024/134] Add test for random and small fixes --- std/haxe/math/bigint/BigInt_.hx | 29 +++++++++++++++-------------- tests/unit/src/unit/TestBigInt.hx | 10 ++++++++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 5e84a3f11ff..5eed9da213c 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -347,6 +347,21 @@ class BigInt_ } return r; } + + public static function random(bits:Int32) : BigInt_ + { + if ( bits <= 0 ) return BigInt.ZERO; + var r = new MutableBigInt_(); + var countBytes:Int = Std.int((bits+7)/8); + var randomBytes = Bytes.alloc(countBytes); + for(j in 0...countBytes) { + var rndN = Math.floor( Math.random() * 256 ); + randomBytes.set(j,rndN); + } + r.setFromBigEndianBytesSigned(randomBytes); + r.compact(); + return r; + } //----------------------------------------------------------------------- // Private implementation @@ -398,20 +413,6 @@ class BigInt_ } } - public static function random(bits:Int32 = 0):BigInt_ - { - var r = new MutableBigInt_(); - var countBytes:Int = Std.int((bits+7)/8); - var randomBytes = Bytes.alloc(countBytes); - for(j in 0...countBytes) { - var rndN = Math.floor( Math.random() * 256 ); - randomBytes.set(j,rndN); - } - r.setFromBigEndianBytesUnsigned(randomBytes); - r.compact(); - return r; - } - private function millerRabin(rounds:UInt):Bool { var minusOne:BigInt_ = subInt2(this,1); diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index dd2da068c42..b812dc8af88 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2766,6 +2766,16 @@ class TestBigInt extends Test { eq("32747023",a.nextProbablePrime().toString()); } + public function testBigIntRandom():Void + { + for(j in 3...15) { + for ( i in 0...100) { + var random = BigInt.random(Std.parseInt(s_powersOfTwo[j+2])); + eq(Std.parseInt(s_powersOfTwo[j]),random.toHex().length); + } + } + } + private static var s_primeNumbers = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; private static var s_notPrimeNumbers = [0,1,4,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30,32,33,34,35,36,38,39,40,42,44,45,46,48,49,50,51,52,54,55,56,57,58,60,62,63,64,65,66,68,69,70,72,74,75,76,77,78,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,102,104,105,106,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,132,133,134,135,136,138,140,141,142,143,144,145,146,147,148,150,152,153,154,155,156,158,159,160,161,162,164,165,166,168,169,170,171,172,174,175,176,177,178,180,182,183,184,185,186,187,188,189,190,192,194,195,196,198,200,201,202,203,204,205,206,207,208,209,210,212,213,214,215,216,217,218,219,220,221,222,224,225,226,228,230,231,232,234,235,236,237,238,240,242,243,244,245,246,247,248,249,250,252,253,254,255,256,258,259,260,261,262,264,265,266,267,268,270,272,273,274,275,276,278,279,280,282,284,285,286,287,288,289,290,291,292,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,312,314,315,316,318,319,320,321,322,323,324,325,326,327,328,329,330,332,333,334,335,336,338,339,340,341,342,343,344,345,346,348,350,351,352,354,355,356,357,358,360,361,362,363,364,365,366,368,369,370,371,372,374,375,376,377,378,380,381,382,384,385,386,387,388,390,391,392,393,394,395,396,398,399,400,402,403,404,405,406,407,408,410,411,412,413,414,415,416,417,418,420,422,423,424,425,426,427,428,429,430,432,434,435,436,437,438,440,441,442,444,445,446,447,448,450,451,452,453,454,455,456,458,459,460,462,464,465,466,468,469,470,471,472,473,474,475,476,477,478,480,481,482,483,484,485,486,488,489,490,492,493,494,495,496,497,498,500,501,502,504,505,506,507,508,510,511,512,513,514,515,516,517,518,519,520,522,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,542,543,544,545,546,548,549,550,551,552,553,554,555,556,558,559,560,561,562,564,565,566,567,568,570,572,573,574,575,576,578,579,580,581,582,583,584,585,586,588,589,590,591,592,594,595,596,597,598,600,602,603,604,605,606,608,609,610,611,612,614,615,616,618,620,621,622,623,624,625,626,627,628,629,630,632,633,634,635,636,637,638,639,640,642,644,645,646,648,649,650,651,652,654,655,656,657,658,660,662,663,664,665,666,667,668,669,670,671,672,674,675,676,678,679,680,681,682,684,685,686,687,688,689,690,692,693,694,695,696,697,698,699,700,702,703,704,705,706,707,708,710,711,712,713,714,715,716,717,718,720,721,722,723,724,725,726,728,729,730,731,732,734,735,736,737,738,740,741,742,744,745,746,747,748,749,750,752,753,754,755,756,758,759,760,762,763,764,765,766,767,768,770,771,772,774,775,776,777,778,779,780,781,782,783,784,785,786,788,789,790,791,792,793,794,795,796,798,799,800,801,802,803,804,805,806,807,808,810,812,813,814,815,816,817,818,819,820,822,824,825,826,828,830,831,832,833,834,835,836,837,838,840,841,842,843,844,845,846,847,848,849,850,851,852,854,855,856,858,860,861,862,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,882,884,885,886,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,908,909,910,912,913,914,915,916,917,918,920,921,922,923,924,925,926,927,928,930,931,932,933,934,935,936,938,939,940,942,943,944,945,946,948,949,950,951,952,954,955,956,957,958,959,960,961,962,963,964,965,966,968,969,970,972,973,974,975,976,978,979,980,981,982,984,985,986,987,988,989,990,992,993,994,995,996,998,999]; From e6fe7c5ebf57f2920ca5e879f26b613329db404d Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 28 Jul 2022 15:12:17 +0300 Subject: [PATCH 025/134] More random methods and some fixes --- std/haxe/math/bigint/BigInt.hx | 21 ++++++- std/haxe/math/bigint/BigInt_.hx | 81 ++++++++++++++++++++------- std/haxe/math/bigint/MutableBigInt.hx | 4 +- 3 files changed, 83 insertions(+), 23 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 082cd4e4e7f..a686036cd41 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -119,10 +119,20 @@ abstract BigInt(BigInt_) return new BigInt(BigInt_.fromBytes(value, offset, length)); } - public static inline function random(bits : Int32):BigInt + public static inline function random(bits : Int32) : BigInt { return new BigInt(BigInt_.random(bits)); } + + public static function randomInRange(min:BigInt, max:BigInt) : BigInt + { + return new BigInt(BigInt_.randomInRange(min,max)); + } + + public static function randomPrime(bits:Int32 , tolerance:UInt) : BigInt + { + return new BigInt(BigInt_.randomPrime(bits,tolerance)); + } public inline function getBit(index : Int) : Int { @@ -152,7 +162,7 @@ abstract BigInt(BigInt_) public function modPow(exponent:BigInt, modulus:BigInt) : BigInt { - return new BigInt(BigInt_.modPow(exponent,modulus,this)); + return new BigInt(this.modPow(exponent,modulus)); } public function isProbablePrime(tolerance:UInt) : Bool @@ -394,4 +404,11 @@ abstract BigInt(BigInt_) { this = a; } + + //----------------------------------------------------------------------- + // Private constants + //----------------------------------------------------------------------- + + private static var SMALL_PRIMES_PRODUCT: BigInt = BigInt.fromString("1451887755777639901511587432083070202422614380984889313550570919659315177065956574359078912654149167643992684236991305777574330831666511589145701059710742276692757882915756220901998212975756543223550490431013061082131040808010565293748926901442915057819663730454818359472391642885328171302299245556663073719855"); + } diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 5eed9da213c..6504894f482 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -318,12 +318,12 @@ class BigInt_ return bi; } - public static function modPow(exponent:BigInt_, modulus:BigInt_, n:BigInt_) : BigInt_ + public function modPow(exponent:BigInt_, modulus:BigInt_) : BigInt_ { if (BigIntArithmetic.compareInt(exponent,0) < 0) throw BigIntExceptions.NEGATIVE_EXPONENT; - if ( n.isZero() ) return ( BigIntArithmetic.compareInt(exponent,0) == 0 ? BigInt.fromInt(1) : n); + if ( this.isZero() ) return ( BigIntArithmetic.compareInt(exponent,0) == 0 ? BigInt.fromInt(1) : this); var r = BigInt_.newFromInt(1); - var p:BigInt_ = BigInt_.fromString(n.toString()); + var p:BigInt_ = this; while(true) { if ( BigIntArithmetic.bitwiseAndInt(exponent,1) == 1 ) r = modulus2(multiply2(p,r),modulus); exponent= BigInt_.arithmeticShiftRight2(exponent, 1); @@ -333,12 +333,12 @@ class BigInt_ return r; } - public static function pow(exponent:UInt, n:BigInt_) : BigInt_ + public function pow(exponent:UInt) : BigInt_ { if (exponent < 0) throw BigIntExceptions.NEGATIVE_EXPONENT; - if ( n.isZero() ) return ( exponent == 0 ? BigInt.fromInt(1) : n); + if ( this.isZero() ) return ( exponent == 0 ? BigInt.fromInt(1) : this); var r = BigInt_.newFromInt(1); - var p:BigInt_ = BigInt_.fromString(n.toString()); + var p:BigInt_ = this; while(true) { if ( (exponent & 1) == 1 ) r = multiply2(p,r); exponent= exponent >> 1; @@ -348,17 +348,48 @@ class BigInt_ return r; } - public static function random(bits:Int32) : BigInt_ + public static function randomPrime(bits:Int32 , tolerance:UInt):BigInt_ { - if ( bits <= 0 ) return BigInt.ZERO; + if ( bits < 2 ) throw BigIntExceptions.INVALID_ARGUMENT; + if ( bits == 2 ) return ( (Math.random()<0.5)?BigInt.TWO:BigInt.fromInt(3)); var r = new MutableBigInt_(); - var countBytes:Int = Std.int((bits+7)/8); - var randomBytes = Bytes.alloc(countBytes); - for(j in 0...countBytes) { - var rndN = Math.floor( Math.random() * 256 ); - randomBytes.set(j,rndN); + do { + var bytes = randomBytes(bits); + var excessBits = 8 * bytes.length - bits; + bytes.set(0,bytes.get(0)|(1 << (7 - excessBits))); + bytes.set(bytes.length-1,bytes.get(bytes.length-1)|1); + r.setFromBigEndianBytesSigned(bytes); + if ( bits > 10 ) { + while(!equals2Int(r.gcd(BigInt.SMALL_PRIMES_PRODUCT),1)) + { + BigIntArithmetic.addInt(r, r, 2); + } + } + } while (!r.isProbablePrime(tolerance)); + BigIntArithmetic.negate(r, r); + return r; + } + + public static function randomInRange(min:BigInt_, max:BigInt_):BigInt_ + { + var initCheck = BigIntArithmetic.compare(min, max); + if ( initCheck == 0) return min; + if ( initCheck > 0 ) throw BigIntExceptions.INVALID_ARGUMENT; + if ( min.bitLength() > (max.bitLength()>>1)) return add2(randomInRange(BigInt.ZERO,sub2(max,min)),min); + for(i in 0...1000) { + var rnd = random(max.bitLength()); + if ( BigIntArithmetic.compare(rnd, min) >= 0 && BigIntArithmetic.compare(rnd, max) <= 0) { + return rnd; + } } - r.setFromBigEndianBytesSigned(randomBytes); + return add2(random(sub2(max,min).bitLength()-1),min); + } + + public static function random(bits:Int32 ):BigInt_ + { + if ( bits <= 0 ) return BigInt.ZERO; + var r = new MutableBigInt_(); + r.setFromBigEndianBytesSigned(randomBytes(bits)); r.compact(); return r; } @@ -422,10 +453,8 @@ class BigInt_ m = arithmeticShiftRight2(m,lsb); var num:BigInt_; for(i in 0...rounds) { - do { - num = random(bitLength()); - } while (BigIntArithmetic.compare(num, BigInt.ONE) <= 0 || BigIntArithmetic.compare(num, this) >= 0 ); - var z:BigInt_ = BigInt_.modPow(m,this,num); + num = randomInRange(BigInt.TWO,minusOne); + var z:BigInt_ = num.modPow(m,this); if ( BigIntArithmetic.compare(z, BigInt.ONE) != 0 && BigIntArithmetic.compare(z, minusOne) != 0) { var j:Int = 1; while ( j<=lsb && BigIntArithmetic.compare(z, minusOne) != 0) @@ -433,7 +462,7 @@ class BigInt_ if ( BigIntArithmetic.compare(z, BigInt.ONE) == 0 || j == lsb) { return false; } - z = BigInt_.modPow(BigInt.TWO,this,z); + z = z.modPow(BigInt.TWO,this); j++; } } @@ -447,6 +476,20 @@ class BigInt_ bi.setFromInt(value); return bi; } + + private static function randomBytes(bits:Int32) : Bytes + { + var countBytes:Int = Std.int((bits+7)/8); + var randomBytes = Bytes.alloc(countBytes); + for(j in 0...countBytes) { + var rndN = Math.floor( Math.random() * 256 ); + randomBytes.set(j,rndN); + } + var excessBits:Int = 8 * countBytes - bits; + if ( excessBits > 0) + randomBytes.set(0, randomBytes.get(0)&(255 >>> excessBits)); + return randomBytes; + } private function new() : Void { diff --git a/std/haxe/math/bigint/MutableBigInt.hx b/std/haxe/math/bigint/MutableBigInt.hx index c3bca41a045..6815a8ea2d9 100644 --- a/std/haxe/math/bigint/MutableBigInt.hx +++ b/std/haxe/math/bigint/MutableBigInt.hx @@ -134,12 +134,12 @@ abstract MutableBigInt(MutableBigInt_) public function pow(exponent:UInt) : MutableBigInt { - return BigInt_.pow(exponent,this); + return this.pow(exponent); } public function modPow(exponent:BigInt, modulus:BigInt) : MutableBigInt { - return BigInt_.modPow(exponent,modulus,this); + return this.modPow(exponent,modulus); } public function isProbablePrime(tolerance:UInt):Bool From ce5378d1f1f6467bd4e814d24436bc0996fa0532 Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 28 Jul 2022 16:35:06 +0300 Subject: [PATCH 026/134] Fix pow bug --- std/haxe/math/bigint/BigInt.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index a686036cd41..acf963b1fe8 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -157,7 +157,7 @@ abstract BigInt(BigInt_) public function pow(exponent:UInt) : BigInt { - return new BigInt(BigInt_.pow(exponent,this)); + return new BigInt(this.pow(exponent)); } public function modPow(exponent:BigInt, modulus:BigInt) : BigInt From 76a883fe60c8e6ff2004786fe776ee6d90a68cd5 Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 28 Jul 2022 21:32:14 +0300 Subject: [PATCH 027/134] Add test for random prime and random in range + prime fix --- std/haxe/math/bigint/BigInt_.hx | 2 +- tests/unit/src/unit/TestBigInt.hx | 41 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 6504894f482..53dd3d44e63 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -366,7 +366,7 @@ class BigInt_ } } } while (!r.isProbablePrime(tolerance)); - BigIntArithmetic.negate(r, r); + if ( r.sign() < 0) BigIntArithmetic.negate(r, r); return r; } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index b812dc8af88..935fdc23731 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2776,6 +2776,47 @@ class TestBigInt extends Test { } } + public function testBigIntRandomPrime():Void + { + var randomPrimeNumber = BigInt.randomPrime(5,5); + t(randomPrimeNumber.isProbablePrime(5)); + randomPrimeNumber = BigInt.randomPrime(11,5); + t(randomPrimeNumber.isProbablePrime(5)); + randomPrimeNumber = BigInt.randomPrime(16,5); + t(randomPrimeNumber.isProbablePrime(5)); + randomPrimeNumber = BigInt.randomPrime(32,5); + t(randomPrimeNumber.isProbablePrime(5)); + randomPrimeNumber = BigInt.randomPrime(55,5); + t(randomPrimeNumber.isProbablePrime(5)); + randomPrimeNumber = BigInt.randomPrime(128,5); + t(randomPrimeNumber.isProbablePrime(5)); + randomPrimeNumber = BigInt.randomPrime(156,5); + trace("randomPrimeNumber: "+randomPrimeNumber.toString()); + t(randomPrimeNumber.isProbablePrime(5)); + } + + public function testBigIntRandomInRange():Void + { + var a:BigInt = "100"; + var b:BigInt = 1000; + var randomBigInt = BigInt.randomInRange(a,b); + t( (randomBigInt>=a && randomBigInt<=b) ); + a = "100000"; + b = "1000000"; + t( (randomBigInt>=a && randomBigInt<=b) ); + a = 1; + b = "151115727451828646838272"; + randomBigInt = BigInt.randomInRange(a,b); + t( (randomBigInt>=a && randomBigInt<=b) ); + a = "618970019642690137449562112"; + b = "604462909807314587353088"; + try { + randomBigInt = BigInt.randomInRange(a,b); + } catch (e:String) { + eq(BigIntExceptions.INVALID_ARGUMENT, e); + } + } + private static var s_primeNumbers = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; private static var s_notPrimeNumbers = [0,1,4,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30,32,33,34,35,36,38,39,40,42,44,45,46,48,49,50,51,52,54,55,56,57,58,60,62,63,64,65,66,68,69,70,72,74,75,76,77,78,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,102,104,105,106,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,132,133,134,135,136,138,140,141,142,143,144,145,146,147,148,150,152,153,154,155,156,158,159,160,161,162,164,165,166,168,169,170,171,172,174,175,176,177,178,180,182,183,184,185,186,187,188,189,190,192,194,195,196,198,200,201,202,203,204,205,206,207,208,209,210,212,213,214,215,216,217,218,219,220,221,222,224,225,226,228,230,231,232,234,235,236,237,238,240,242,243,244,245,246,247,248,249,250,252,253,254,255,256,258,259,260,261,262,264,265,266,267,268,270,272,273,274,275,276,278,279,280,282,284,285,286,287,288,289,290,291,292,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,312,314,315,316,318,319,320,321,322,323,324,325,326,327,328,329,330,332,333,334,335,336,338,339,340,341,342,343,344,345,346,348,350,351,352,354,355,356,357,358,360,361,362,363,364,365,366,368,369,370,371,372,374,375,376,377,378,380,381,382,384,385,386,387,388,390,391,392,393,394,395,396,398,399,400,402,403,404,405,406,407,408,410,411,412,413,414,415,416,417,418,420,422,423,424,425,426,427,428,429,430,432,434,435,436,437,438,440,441,442,444,445,446,447,448,450,451,452,453,454,455,456,458,459,460,462,464,465,466,468,469,470,471,472,473,474,475,476,477,478,480,481,482,483,484,485,486,488,489,490,492,493,494,495,496,497,498,500,501,502,504,505,506,507,508,510,511,512,513,514,515,516,517,518,519,520,522,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,542,543,544,545,546,548,549,550,551,552,553,554,555,556,558,559,560,561,562,564,565,566,567,568,570,572,573,574,575,576,578,579,580,581,582,583,584,585,586,588,589,590,591,592,594,595,596,597,598,600,602,603,604,605,606,608,609,610,611,612,614,615,616,618,620,621,622,623,624,625,626,627,628,629,630,632,633,634,635,636,637,638,639,640,642,644,645,646,648,649,650,651,652,654,655,656,657,658,660,662,663,664,665,666,667,668,669,670,671,672,674,675,676,678,679,680,681,682,684,685,686,687,688,689,690,692,693,694,695,696,697,698,699,700,702,703,704,705,706,707,708,710,711,712,713,714,715,716,717,718,720,721,722,723,724,725,726,728,729,730,731,732,734,735,736,737,738,740,741,742,744,745,746,747,748,749,750,752,753,754,755,756,758,759,760,762,763,764,765,766,767,768,770,771,772,774,775,776,777,778,779,780,781,782,783,784,785,786,788,789,790,791,792,793,794,795,796,798,799,800,801,802,803,804,805,806,807,808,810,812,813,814,815,816,817,818,819,820,822,824,825,826,828,830,831,832,833,834,835,836,837,838,840,841,842,843,844,845,846,847,848,849,850,851,852,854,855,856,858,860,861,862,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,882,884,885,886,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,908,909,910,912,913,914,915,916,917,918,920,921,922,923,924,925,926,927,928,930,931,932,933,934,935,936,938,939,940,942,943,944,945,946,948,949,950,951,952,954,955,956,957,958,959,960,961,962,963,964,965,966,968,969,970,972,973,974,975,976,978,979,980,981,982,984,985,986,987,988,989,990,992,993,994,995,996,998,999]; From 57927b82b421170b5c98b083632489c840fc78fc Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 28 Jul 2022 22:08:22 +0300 Subject: [PATCH 028/134] Remove trace(..) --- tests/unit/src/unit/TestBigInt.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 935fdc23731..41b17b1514a 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2791,7 +2791,6 @@ class TestBigInt extends Test { randomPrimeNumber = BigInt.randomPrime(128,5); t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(156,5); - trace("randomPrimeNumber: "+randomPrimeNumber.toString()); t(randomPrimeNumber.isProbablePrime(5)); } From 39252d49550ce412b60ad3a48224a52c0c887a22 Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 28 Jul 2022 22:51:56 +0300 Subject: [PATCH 029/134] Fix test --- tests/unit/src/unit/TestBigInt.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 41b17b1514a..7fb64b24881 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2802,6 +2802,7 @@ class TestBigInt extends Test { t( (randomBigInt>=a && randomBigInt<=b) ); a = "100000"; b = "1000000"; + randomBigInt = BigInt.randomInRange(a,b); t( (randomBigInt>=a && randomBigInt<=b) ); a = 1; b = "151115727451828646838272"; From 70fbb335e5f0ec61c4b07766648a77e3b21077bb Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 29 Jul 2022 07:51:17 +0300 Subject: [PATCH 030/134] Fix unsigned compare for randomInRange --- std/haxe/math/bigint/BigInt_.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 53dd3d44e63..c51fe5f9149 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -372,13 +372,13 @@ class BigInt_ public static function randomInRange(min:BigInt_, max:BigInt_):BigInt_ { - var initCheck = BigIntArithmetic.compare(min, max); + var initCheck = MultiwordArithmetic.compareUnsigned(min.m_data, max.m_data, min.m_count); if ( initCheck == 0) return min; if ( initCheck > 0 ) throw BigIntExceptions.INVALID_ARGUMENT; if ( min.bitLength() > (max.bitLength()>>1)) return add2(randomInRange(BigInt.ZERO,sub2(max,min)),min); for(i in 0...1000) { var rnd = random(max.bitLength()); - if ( BigIntArithmetic.compare(rnd, min) >= 0 && BigIntArithmetic.compare(rnd, max) <= 0) { + if ( MultiwordArithmetic.compareUnsigned(rnd.m_data, min.m_data, rnd.m_count) >= 0 && MultiwordArithmetic.compareUnsigned(rnd.m_data, max.m_data, rnd.m_count) <= 0) { return rnd; } } From f2de36944b746d930b3f0b885a364bc5854254e1 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 29 Jul 2022 08:25:26 +0300 Subject: [PATCH 031/134] Fix for randomInRange --- std/haxe/math/bigint/BigInt_.hx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index c51fe5f9149..7566ded0db7 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -372,13 +372,15 @@ class BigInt_ public static function randomInRange(min:BigInt_, max:BigInt_):BigInt_ { - var initCheck = MultiwordArithmetic.compareUnsigned(min.m_data, max.m_data, min.m_count); + min = min.abs(); + max = max.abs(); + var initCheck = BigIntArithmetic.compare(min,max); if ( initCheck == 0) return min; if ( initCheck > 0 ) throw BigIntExceptions.INVALID_ARGUMENT; if ( min.bitLength() > (max.bitLength()>>1)) return add2(randomInRange(BigInt.ZERO,sub2(max,min)),min); for(i in 0...1000) { var rnd = random(max.bitLength()); - if ( MultiwordArithmetic.compareUnsigned(rnd.m_data, min.m_data, rnd.m_count) >= 0 && MultiwordArithmetic.compareUnsigned(rnd.m_data, max.m_data, rnd.m_count) <= 0) { + if ( BigIntArithmetic.compare(rnd,min) >= 0 && BigIntArithmetic.compare(rnd,max) <= 0) { return rnd; } } From 8bf946acc912136c216c47583bb8275845410070 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 29 Jul 2022 11:11:51 +0300 Subject: [PATCH 032/134] Hope dies last --- std/haxe/math/bigint/BigInt_.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 7566ded0db7..07f1640a0d3 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -87,7 +87,7 @@ class BigInt_ **/ public inline function sign() : Int { - return m_data.get(m_count - 1) >> 31; + return ( ((m_data.get(m_count - 1) >> 31)& 1)==1) ?-1:0; } public function getLowestSetBit():Int From 2866088331a8f877845bcd54052332ca7d3fd869 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 29 Jul 2022 22:18:45 +0300 Subject: [PATCH 033/134] Fix for JS --- std/haxe/math/bigint/MultiwordArithmetic.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 08bdbd68ca9..f820042cf7b 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -408,7 +408,7 @@ class MultiwordArithmetic // Based on Figure 9-1 (p. 185) from "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. - var j : Int, k : Int, t : Int; + var j : Int, k : Int32, t : Int; var m : Int = dividendLength << 1; var un : Int = divisorLength << 1; var n : Int = un; From c26f036ee18d5b932e965ea4df76093802152d1c Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 30 Jul 2022 21:50:20 +0300 Subject: [PATCH 034/134] Better check for sign --- std/haxe/math/bigint/BigInt_.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 07f1640a0d3..1b6681b08fb 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -87,7 +87,7 @@ class BigInt_ **/ public inline function sign() : Int { - return ( ((m_data.get(m_count - 1) >> 31)& 1)==1) ?-1:0; + return ( m_data.get(m_count - 1)>>31 !=0 )?-1:0; } public function getLowestSetBit():Int From 6e8f2d851782d3b8e255754915dcdb8f231b0ec5 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 1 Aug 2022 08:29:34 +0300 Subject: [PATCH 035/134] Thanks to cbatson --- std/haxe/math/bigint/BigInt.hx | 1 + std/haxe/math/bigint/BigIntArithmetic.hx | 1 + std/haxe/math/bigint/BigIntExceptions.hx | 1 + std/haxe/math/bigint/BigIntHelper.hx | 1 + std/haxe/math/bigint/BigIntTools.hx | 1 + std/haxe/math/bigint/BigInt_.hx | 1 + std/haxe/math/bigint/MultiwordArithmetic.hx | 1 + std/haxe/math/bigint/MutableBigInt.hx | 1 + std/haxe/math/bigint/MutableBigInt_.hx | 1 + 9 files changed, 9 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index acf963b1fe8..dc9a3ed8d62 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -25,6 +25,7 @@ package haxe.math.bigint; import haxe.ds.Vector; import haxe.io.Bytes; +/* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(haxe.math.bigint) abstract BigInt(BigInt_) { diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 5315be68bc7..ecc4fb93e01 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -26,6 +26,7 @@ import haxe.math.bigint.BigIntExceptions; import haxe.math.bigint.BigIntHelper; import haxe.ds.Vector; +/* Original code courtesy Chuck Batson (github.com/cbatson) */ class BigIntArithmetic { /** diff --git a/std/haxe/math/bigint/BigIntExceptions.hx b/std/haxe/math/bigint/BigIntExceptions.hx index b50aaf2525e..5ce2eab9d47 100644 --- a/std/haxe/math/bigint/BigIntExceptions.hx +++ b/std/haxe/math/bigint/BigIntExceptions.hx @@ -22,6 +22,7 @@ package haxe.math.bigint; +/* Original code courtesy Chuck Batson (github.com/cbatson) */ class BigIntExceptions { public static inline var INVALID_ARGUMENT = "invalid argument"; diff --git a/std/haxe/math/bigint/BigIntHelper.hx b/std/haxe/math/bigint/BigIntHelper.hx index 16c9d6c7a66..24b3a08111a 100644 --- a/std/haxe/math/bigint/BigIntHelper.hx +++ b/std/haxe/math/bigint/BigIntHelper.hx @@ -22,6 +22,7 @@ package haxe.math.bigint; +/* Original code courtesy Chuck Batson (github.com/cbatson) */ class BigIntHelper { diff --git a/std/haxe/math/bigint/BigIntTools.hx b/std/haxe/math/bigint/BigIntTools.hx index 995d07d987b..1beb3734d33 100644 --- a/std/haxe/math/bigint/BigIntTools.hx +++ b/std/haxe/math/bigint/BigIntTools.hx @@ -24,6 +24,7 @@ package haxe.math.bigint; import haxe.math.bigint.BigIntExceptions; +/* Original code courtesy Chuck Batson (github.com/cbatson) */ class BigIntTools { public static inline function isNull(value : BigInt) : Bool diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 1b6681b08fb..571688deabf 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -25,6 +25,7 @@ package haxe.math.bigint; import haxe.ds.Vector; import haxe.io.Bytes; +/* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(unit) @:allow(haxe.math.bigint) class BigInt_ diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index f820042cf7b..53af89bf354 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -26,6 +26,7 @@ import haxe.math.bigint.BigIntExceptions; import haxe.math.bigint.BigIntHelper; import haxe.ds.Vector; +/* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(haxe.math.bigint) class MultiwordArithmetic { diff --git a/std/haxe/math/bigint/MutableBigInt.hx b/std/haxe/math/bigint/MutableBigInt.hx index 6815a8ea2d9..deb34d5ad9d 100644 --- a/std/haxe/math/bigint/MutableBigInt.hx +++ b/std/haxe/math/bigint/MutableBigInt.hx @@ -25,6 +25,7 @@ package haxe.math.bigint; import haxe.ds.Vector; import haxe.io.Bytes; +/* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(haxe.math.bigint) abstract MutableBigInt(MutableBigInt_) { diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index 86e3ea2bc85..ce8c8965252 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -27,6 +27,7 @@ import haxe.math.bigint.BigIntHelper; import haxe.ds.Vector; import haxe.io.Bytes; +/* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(unit) @:allow(haxe.math.bigint) class MutableBigInt_ extends BigInt_ From bec8abe34a0c30dd783c5ec4aa789dd4897f333c Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 20 Aug 2022 14:56:27 +0300 Subject: [PATCH 036/134] Add modInverse method --- std/haxe/math/bigint/BigInt.hx | 5 + std/haxe/math/bigint/BigIntExceptions.hx | 11 +- std/haxe/math/bigint/BigInt_.hx | 128 +++++++++++++++++++++++ 3 files changed, 140 insertions(+), 4 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index dc9a3ed8d62..699c0440c01 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -145,6 +145,11 @@ abstract BigInt(BigInt_) return new BigInt(this.abs()); } + public function modInverse(modulus:BigInt_) : BigInt + { + return new BigInt(this.modInverse(modulus)); + } + // Finds the greatest common denominator of this and b public function gcd(b:BigInt) : BigInt { diff --git a/std/haxe/math/bigint/BigIntExceptions.hx b/std/haxe/math/bigint/BigIntExceptions.hx index 5ce2eab9d47..8c008b31b2a 100644 --- a/std/haxe/math/bigint/BigIntExceptions.hx +++ b/std/haxe/math/bigint/BigIntExceptions.hx @@ -25,8 +25,11 @@ package haxe.math.bigint; /* Original code courtesy Chuck Batson (github.com/cbatson) */ class BigIntExceptions { - public static inline var INVALID_ARGUMENT = "invalid argument"; - public static inline var BUFFER_TOO_SMALL = "buffer too small"; - public static inline var DIVISION_BY_ZERO = "division by zero"; - public static inline var NEGATIVE_EXPONENT = "Negative exponent"; + public static inline var INVALID_ARGUMENT = "Invalid argument"; + public static inline var BUFFER_TOO_SMALL = "Buffer too small"; + public static inline var DIVISION_BY_ZERO = "Division by zero"; + public static inline var NEGATIVE_EXPONENT = "Negative exponent"; + public static inline var INVALID_OPERATION = "Invalid operation"; + public static inline var NEGATIVE_MODULUS = "Modulus should be positive"; + public static inline var EVEN_VALUES = "Both values are even"; } \ No newline at end of file diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 571688deabf..562903b10b0 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -349,6 +349,89 @@ class BigInt_ return r; } + /* hac 14.61, pp. 608 */ + public function modInverse(modulus:BigInt_):BigInt_ + { + if (modulus.sign() == -1 || modulus.isZero()) + throw BigIntExceptions.NEGATIVE_MODULUS; + if (equals2Int(modulus, 1)) + return BigInt.ZERO; + + var isModulusEven:Bool = (BigIntArithmetic.bitwiseAndInt(modulus, 1) == 0); + if ((BigIntArithmetic.bitwiseAndInt(this, 1) == 0) && isModulusEven || modulus.isZero()) + return BigInt.ZERO; + + var x:BigInt_ = MutableBigInt_.fromBigInt(this); + var y:BigInt_ = MutableBigInt_.fromBigInt(modulus); + + if (x.sign() == -1 || BigIntArithmetic.compare(x, modulus) >= 0) + x = modulus2(x, modulus); + if (equals2Int(x, 1)) + return BigInt.ONE; + + if ((BigIntArithmetic.bitwiseAndInt(x, 1) == 0) && (BigIntArithmetic.bitwiseAndInt(y, 1) == 0)) + throw BigIntExceptions.EVEN_VALUES; + + if (!isModulusEven) { + // fast odd calculation + return modInverseOdd(x, y); + } + + var a:BigInt_ = fromInt(1); + var b:BigInt_ = fromInt(0); + var c:BigInt_ = fromInt(0); + var d:BigInt_ = fromInt(1); + var u:BigInt_ = MutableBigInt_.fromBigInt(x); + var v:BigInt_ = MutableBigInt_.fromBigInt(y); + + do { + while ((BigIntArithmetic.bitwiseAndInt(u, 1) == 0)) { + u = arithmeticShiftRight2(u, 1); + if ((BigIntArithmetic.bitwiseAndInt(a, 1) == 1) || (BigIntArithmetic.bitwiseAndInt(b, 1) == 1)) { + a = add2(a, y); + b = sub2(b, x); + } + a = arithmeticShiftRight2(a, 1); + b = arithmeticShiftRight2(b, 1); + } + + while ((BigIntArithmetic.bitwiseAndInt(v, 1) == 0)) { + v = arithmeticShiftRight2(v, 1); + if ((BigIntArithmetic.bitwiseAndInt(c, 1) == 1) || (BigIntArithmetic.bitwiseAndInt(d, 1) == 1)) { + c = add2(c, y); + d = sub2(d, x); + } + + c = arithmeticShiftRight2(c, 1); + d = arithmeticShiftRight2(d, 1); + } + + if (BigIntArithmetic.compare(u, v) >= 0) { + u = sub2(u, v); + a = sub2(a, c); + b = sub2(b, d); + } else { + v = sub2(v, u); + c = sub2(c, a); + d = sub2(d, b); + } + } while (!u.isZero()); + + if (!equals2Int(v, 1)) { + return BigInt.ZERO; + } + + while (BigIntArithmetic.compareInt(c, 0) < 0) { + c = add2(c, modulus); + } + + while (BigIntArithmetic.compare(c, modulus) >= 0) { + c = sub2(c, modulus); + } + + return c; + } + public static function randomPrime(bits:Int32 , tolerance:UInt):BigInt_ { if ( bits < 2 ) throw BigIntExceptions.INVALID_ARGUMENT; @@ -472,6 +555,51 @@ class BigInt_ } return true; } + + /* hac 14.64, pp. 610 */ + private function modInverseOdd(y:BigInt_, x:BigInt_):BigInt_ + { + var b:BigInt_ = fromInt(0); + var d:BigInt_ = fromInt(1); + var u:BigInt_ = MutableBigInt_.fromBigInt(x); + var v:BigInt_ = MutableBigInt_.fromBigInt(y); + do { + while ((BigIntArithmetic.bitwiseAndInt(u, 1) == 0)) { + u = arithmeticShiftRight2(u, 1); + if (BigIntArithmetic.bitwiseAndInt(b, 1) == 1) + b = sub2(b, x); + b = arithmeticShiftRight2(b, 1); + } + while ((BigIntArithmetic.bitwiseAndInt(v, 1) == 0)) { + v = arithmeticShiftRight2(v, 1); + if (BigIntArithmetic.bitwiseAndInt(d, 1) == 1) + d = sub2(d, x); + + d = arithmeticShiftRight2(d, 1); + } + if (BigIntArithmetic.compare(u, v) >= 0) { + u = sub2(u, v); + b = sub2(b, d); + } else { + v = sub2(v, u); + d = sub2(d, b); + } + } while (!u.isZero()); + + if (!equals2Int(v, 1)) { + return BigInt.ZERO; + } + + while (BigIntArithmetic.compareInt(d, 0) < 0) { + d = add2(d, x); + } + + while (BigIntArithmetic.compare(d, x) >= 0) { + d = sub2(d, x); + } + + return d; + } private static function newFromInt(value : Int) : BigInt_ { From f4d5e6d8bae063bcf915486847e9208b7a2818cf Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 21 Aug 2022 16:49:17 +0300 Subject: [PATCH 037/134] Add bitcount(),isPositive,isEven and isOdd methods --- std/haxe/math/bigint/BigInt.hx | 20 +++++++++++++ std/haxe/math/bigint/BigInt_.hx | 52 +++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 699c0440c01..8ac4812571b 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -57,6 +57,21 @@ abstract BigInt(BigInt_) return BigInt_.isNegative1(this); } + public inline function isPositive() : Bool + { + return BigInt_.isPositive1(this); + } + + public inline function isOdd() : Bool + { + return BigInt_.isOdd1(this); + } + + public inline function isEven() : Bool + { + return BigInt_.isEven1(this); + } + public inline function min(other : BigInt ) : BigInt { return new BigInt(this.min(other)); } @@ -189,6 +204,11 @@ abstract BigInt(BigInt_) public function bitLength():Int { return this.bitLength(); } + + public function bitCount():Int + { + return this.bitCount(); + } //----------------------------------------------------------------------- // Operators diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 562903b10b0..15d4e014d35 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -82,6 +82,21 @@ class BigInt_ { return m_data.get(m_count - 1) < 0; } + + public function isPositive():Bool + { + return m_data.get(m_count - 1) >= 0; + } + + public function isOdd():Bool + { + return ( ( m_data.get(0) & 1) == 1 ); + } + + public function isEven():Bool + { + return ( (m_data.get(0) & 1) == 0); + } /** Retrieve the sign value of this big integer; 0 if positive, -1 if negative. @@ -107,6 +122,25 @@ class BigInt_ return ( 32 * m_count - BigIntHelper.nlz(m_data.get(m_count-1)^sign()) ); } + public function bitCount():Int + { + var totalBits:Int = 0; + var x:Int, m:Int; + for (n in 0...this.m_count) { + x = this.m_data.get(n); + m = (x >> 1) & 0x77777777; + x = x - m; + m = (m >> 1) & 0x77777777; + x = x - m; + m = (m >> 1) & 0x77777777; + x = x - m; + x = (x + (x >> 4)) & 0x0F0F0F0F; + x = x * 0x01010101; + totalBits += x >> 24; + } + return totalBits; + } + public function isProbablePrime(tolerance:UInt):Bool { if ( tolerance <= 0 ) return true; @@ -792,6 +826,24 @@ class BigInt_ { return a.isNegative(); } + + @:noCompletion + private static inline function isPositive1(a : BigInt_) : Bool + { + return a.isPositive(); + } + + @:noCompletion + private static inline function isOdd1(a : BigInt_) : Bool + { + return a.isOdd(); + } + + @:noCompletion + private static inline function isEven1(a : BigInt_) : Bool + { + return a.isEven(); + } @:noCompletion private static inline function toString1(a : BigInt_) : String From a0e15988c74ae4a9744a3d766577e873a6496607 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 21 Aug 2022 17:41:35 +0300 Subject: [PATCH 038/134] Add testBit() method --- std/haxe/math/bigint/BigInt.hx | 5 +++++ std/haxe/math/bigint/BigInt_.hx | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 8ac4812571b..c5670cba2dd 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -209,6 +209,11 @@ abstract BigInt(BigInt_) { return this.bitCount(); } + + public function testBit(n:Int):Bool + { + return this.testBit(n); + } //----------------------------------------------------------------------- // Operators diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 15d4e014d35..23fc63b3ab9 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -141,6 +141,14 @@ class BigInt_ return totalBits; } + public function testBit(n:Int):Bool + { + if ( n < 0 ) throw BigIntExceptions.INVALID_ARGUMENT; + var chunk = n >> 5; //divide by 32 + if ( chunk >= m_count) return false; + return ( ( m_data.get(chunk) & (1<<(n & 0x1f))) != 0); + } + public function isProbablePrime(tolerance:UInt):Bool { if ( tolerance <= 0 ) return true; From 3c5c0a28081121f928bfa6243617401da82ea74c Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 21 Aug 2022 19:49:19 +0300 Subject: [PATCH 039/134] Add tests for modInverse,isPositive,isEven,isOdd, testBit, bitCount --- tests/unit/src/unit/TestBigInt.hx | 79 +++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 7fb64b24881..86e11671722 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2817,6 +2817,85 @@ class TestBigInt extends Test { } } + public function testModInverse():Void + { + var m:Array = [ "2885628006", "3452672361", "2693781441", "3446368347", "1495928706" , "3144152002", "1680946273"]; + var n:Array = [ "898595849", "2540385371", "1304452195", "2448267533", "2053023521", "4287024253", "1920144361", "504475217", "887965291", "300193913", "2394418165" ]; + var mn:Array = ["681936597","980871030","323007506","112883568","683798641","1331447622","1514136460","438360889","585723972","102755466","818276521", + "565144203","2230262406","55288816","1361792736","293899217","244543810","1508822196","237344825","670834209","151186306","1741057836", + "198144249","2077049753","1187239881","2435102952","1947607550","2483570286","725766574","284956416","606548574","242581937","1287460391", + "500716917","910017586","666455683","1268170143","751080606","3325520905","1230560432","124770931","580887745","121788521","1422101743", + "858074026","791210169","823419966","1678016129","1682774644","1196897481","244305979","462331726","867267019","166516939","1303195691", + "712131840","2106472611","967422418","273950480","1682853299","4248168436","1597159081","254025827","233894683","63539412","736767788", + "279559525","387786944","1228135902","494650428","146720719","1425245481","1438770027","120084998","310304596","244283899","1212900932"]; + + var pos = 0; + for(i in 0...m.length) { + var a:BigInt = BigInt.fromString(m[i]); + for(j in 0...n.length) { + var b:BigInt = BigInt.fromString(n[j]); + var r = a.modInverse(b); + eq(r.toString(),mn[pos]); + pos++; + } + } + } + + public function testBitCount():Void + { + var b:BigInt; + for(i in 0...s_primeNumbers.length) + { + b = s_primeNumbers[i]; + eq(b.bitCount(),bitcount_primeNumbers[i]); + } + b = "31289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095"; + eq(b.bitCount(),14286); + } + + public function testIsPositive():Void + { + var b:BigInt = -1; + f(b.isPositive()); + b = 0; + t(b.isPositive()); + b = 1; + t(b.isPositive()); + b = 3829; + t(b.isPositive()); + b = -32943; + f(b.isPositive()); + } + + public function testEvenOdd():Void + { + var b:BigInt = 1; + t(b.isOdd()); + f(b.isEven()); + b = 2; + f(b.isOdd()); + t(b.isEven()); + b = 76; + f(b.isOdd()); + t(b.isEven()); + b = "500638577896799483816152607866547736957740898853209483873285677143564366192332208307174317959001709443039404185797701672275527838488848483763636556445777023797930138165123350019004132380446348231021254368110746126663615959395864308678978278260535734556772116555567464463944778761494325692023874761887965433325891748738093112709958788369487884977010548779088188484331392128315526085363468945546963420585208800664404356458139205589044250148264071701123009387700818846733471543158424023118048291252187133437780648242543956566170672422350843150080779372519053879333392134884951949440626103615875779513578928323532154688532003749917394291989161377389875366073468404983368368097031044949613470296667047208143363341323720962260335461968963306358427170789478369967512574983206915797533599998535087953469304411850522622672461336345855355508007855385321221106261546814248579179126016547764554328074845477357114937006730911294360182786223565951598223920151163494948086030036705028558864380824193953573225449943077940239329925228264218792118724026347617320530827300651961339871631931340901163772928730439359425128354171228396689527810082955319463306776797758296764576356156478933492520370117517191201473793019864639561873521807073656608329937521"; + t(b.isOdd()); + f(b.isEven()); + } + + public function testTestBit():Void + { + var b:BigInt = "31289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095"; + t(b.testBit(1)); + f(b.testBit(10)); + t(b.testBit(200)); + f(b.testBit(12345)); + t(b.testBit(12347)); + } + + private static var bitcount_primeNumbers = [1,2,2,3,3,3,2,3,4,4,5,3,3,4,5,4,5,5,3,4,3,5,4,4,3,4,5,5,5,4,7,3,3,4,4,5,5,4,5,5,5,5,7,3,4,5,5,7,5,5,5,7,5,7,2,4,4,5,4,4,5,4,5,6,5,6,5,4,6,6,4,6,7,6,7,8,4,5,4,5,5,5,7,5,7,7,4,5,6,7,6,8,7,7,7,8,8,3,4,5,4,5,5,5,6,3,5,4,6,5,7,5,5,6,7,3,4,5,5,5,5,4,5,6,6,7,5,7,7,7,6,7,8,7,7,3,4,5,6,5,6,6,7,7,7,6,6,6,7,8,7,6,7,8,6,7,7,5,6,7,7,7,7,7,6,8,9,7]; + + private static var s_primeNumbers = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997]; private static var s_notPrimeNumbers = [0,1,4,6,8,9,10,12,14,15,16,18,20,21,22,24,25,26,27,28,30,32,33,34,35,36,38,39,40,42,44,45,46,48,49,50,51,52,54,55,56,57,58,60,62,63,64,65,66,68,69,70,72,74,75,76,77,78,80,81,82,84,85,86,87,88,90,91,92,93,94,95,96,98,99,100,102,104,105,106,108,110,111,112,114,115,116,117,118,119,120,121,122,123,124,125,126,128,129,130,132,133,134,135,136,138,140,141,142,143,144,145,146,147,148,150,152,153,154,155,156,158,159,160,161,162,164,165,166,168,169,170,171,172,174,175,176,177,178,180,182,183,184,185,186,187,188,189,190,192,194,195,196,198,200,201,202,203,204,205,206,207,208,209,210,212,213,214,215,216,217,218,219,220,221,222,224,225,226,228,230,231,232,234,235,236,237,238,240,242,243,244,245,246,247,248,249,250,252,253,254,255,256,258,259,260,261,262,264,265,266,267,268,270,272,273,274,275,276,278,279,280,282,284,285,286,287,288,289,290,291,292,294,295,296,297,298,299,300,301,302,303,304,305,306,308,309,310,312,314,315,316,318,319,320,321,322,323,324,325,326,327,328,329,330,332,333,334,335,336,338,339,340,341,342,343,344,345,346,348,350,351,352,354,355,356,357,358,360,361,362,363,364,365,366,368,369,370,371,372,374,375,376,377,378,380,381,382,384,385,386,387,388,390,391,392,393,394,395,396,398,399,400,402,403,404,405,406,407,408,410,411,412,413,414,415,416,417,418,420,422,423,424,425,426,427,428,429,430,432,434,435,436,437,438,440,441,442,444,445,446,447,448,450,451,452,453,454,455,456,458,459,460,462,464,465,466,468,469,470,471,472,473,474,475,476,477,478,480,481,482,483,484,485,486,488,489,490,492,493,494,495,496,497,498,500,501,502,504,505,506,507,508,510,511,512,513,514,515,516,517,518,519,520,522,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,542,543,544,545,546,548,549,550,551,552,553,554,555,556,558,559,560,561,562,564,565,566,567,568,570,572,573,574,575,576,578,579,580,581,582,583,584,585,586,588,589,590,591,592,594,595,596,597,598,600,602,603,604,605,606,608,609,610,611,612,614,615,616,618,620,621,622,623,624,625,626,627,628,629,630,632,633,634,635,636,637,638,639,640,642,644,645,646,648,649,650,651,652,654,655,656,657,658,660,662,663,664,665,666,667,668,669,670,671,672,674,675,676,678,679,680,681,682,684,685,686,687,688,689,690,692,693,694,695,696,697,698,699,700,702,703,704,705,706,707,708,710,711,712,713,714,715,716,717,718,720,721,722,723,724,725,726,728,729,730,731,732,734,735,736,737,738,740,741,742,744,745,746,747,748,749,750,752,753,754,755,756,758,759,760,762,763,764,765,766,767,768,770,771,772,774,775,776,777,778,779,780,781,782,783,784,785,786,788,789,790,791,792,793,794,795,796,798,799,800,801,802,803,804,805,806,807,808,810,812,813,814,815,816,817,818,819,820,822,824,825,826,828,830,831,832,833,834,835,836,837,838,840,841,842,843,844,845,846,847,848,849,850,851,852,854,855,856,858,860,861,862,864,865,866,867,868,869,870,871,872,873,874,875,876,878,879,880,882,884,885,886,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,908,909,910,912,913,914,915,916,917,918,920,921,922,923,924,925,926,927,928,930,931,932,933,934,935,936,938,939,940,942,943,944,945,946,948,949,950,951,952,954,955,956,957,958,959,960,961,962,963,964,965,966,968,969,970,972,973,974,975,976,978,979,980,981,982,984,985,986,987,988,989,990,992,993,994,995,996,998,999]; From 157c0e20b42496b7440d0e65983a7d91f9d97185 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 21 Aug 2022 21:11:17 +0300 Subject: [PATCH 040/134] Fix bitcount --- std/haxe/math/bigint/BigInt_.hx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 23fc63b3ab9..3d3791c7ddb 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -128,15 +128,15 @@ class BigInt_ var x:Int, m:Int; for (n in 0...this.m_count) { x = this.m_data.get(n); - m = (x >> 1) & 0x77777777; + m = (x >>> 1) & 0x77777777; x = x - m; - m = (m >> 1) & 0x77777777; + m = (m >>> 1) & 0x77777777; x = x - m; - m = (m >> 1) & 0x77777777; + m = (m >>> 1) & 0x77777777; x = x - m; - x = (x + (x >> 4)) & 0x0F0F0F0F; + x = (x + (x >>> 4)) & 0x0F0F0F0F; x = x * 0x01010101; - totalBits += x >> 24; + totalBits += x >>> 24; } return totalBits; } From 8bd592c893107ed2290c773e3f362871ddbe4d8a Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 21 Aug 2022 21:58:38 +0300 Subject: [PATCH 041/134] Try to fix bitCount() --- std/haxe/math/bigint/BigInt_.hx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 3d3791c7ddb..8ace6515c48 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -125,18 +125,18 @@ class BigInt_ public function bitCount():Int { var totalBits:Int = 0; - var x:Int, m:Int; + var x:Int32, m:Int32; for (n in 0...this.m_count) { x = this.m_data.get(n); - m = (x >>> 1) & 0x77777777; + m = (x >> 1) & 0x77777777; x = x - m; - m = (m >>> 1) & 0x77777777; + m = (m >> 1) & 0x77777777; x = x - m; - m = (m >>> 1) & 0x77777777; + m = (m >> 1) & 0x77777777; x = x - m; - x = (x + (x >>> 4)) & 0x0F0F0F0F; + x = (x + (x >> 4)) & 0x0F0F0F0F; x = x * 0x01010101; - totalBits += x >>> 24; + totalBits += x >> 24; } return totalBits; } From 3eb46e4a7d47977c5d27330efa01e6d3b5f7e794 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 22 Aug 2022 07:48:20 +0300 Subject: [PATCH 042/134] Debug cpp (couldn't repeat) --- tests/unit/src/unit/TestBigInt.hx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 86e11671722..bb0836ba465 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2847,7 +2847,14 @@ class TestBigInt extends Test { for(i in 0...s_primeNumbers.length) { b = s_primeNumbers[i]; - eq(b.bitCount(),bitcount_primeNumbers[i]); + var bc = b.bitCount(); + eq(bitcount_primeNumbers[i],bc); + #if cpp + if ( bc != bitcount_primeNumbers[i]) + { + trace("b: "+b.toString()); + } + #end } b = "31289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095"; eq(b.bitCount(),14286); From 880f7102035a4b590e4e67c22a10043de343cd29 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 22 Aug 2022 08:36:56 +0300 Subject: [PATCH 043/134] Fix debug --- tests/unit/src/unit/TestBigInt.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index bb0836ba465..14d0e3bb916 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2848,13 +2848,13 @@ class TestBigInt extends Test { { b = s_primeNumbers[i]; var bc = b.bitCount(); - eq(bitcount_primeNumbers[i],bc); #if cpp if ( bc != bitcount_primeNumbers[i]) { trace("b: "+b.toString()); } #end + eq(bitcount_primeNumbers[i],bc); } b = "31289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095"; eq(b.bitCount(),14286); From b15c9f01c732e15b850834c7d423f0aaaa319983 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 22 Aug 2022 10:53:19 +0300 Subject: [PATCH 044/134] Debug --- std/haxe/math/bigint/BigInt_.hx | 10 ++++++++++ tests/unit/src/unit/TestBigInt.hx | 14 ++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 8ace6515c48..c1cbfd68fa6 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -128,15 +128,25 @@ class BigInt_ var x:Int32, m:Int32; for (n in 0...this.m_count) { x = this.m_data.get(n); + #if cpp trace("x:"+x); #end m = (x >> 1) & 0x77777777; + #if cpp trace("m:"+m); #end x = x - m; + #if cpp trace("x:"+x); #end m = (m >> 1) & 0x77777777; + #if cpp trace("m:"+m); #end x = x - m; + #if cpp trace("x:"+x); #end m = (m >> 1) & 0x77777777; + #if cpp trace("m:"+m); #end x = x - m; + #if cpp trace("x:"+x); #end x = (x + (x >> 4)) & 0x0F0F0F0F; + #if cpp trace("x:"+x); #end x = x * 0x01010101; + #if cpp trace("x:"+x); #end totalBits += x >> 24; + #if cpp trace("totalBits:"+totalBits); #end } return totalBits; } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 14d0e3bb916..a66903d522e 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2844,20 +2844,18 @@ class TestBigInt extends Test { public function testBitCount():Void { var b:BigInt; + #if cpp + b = 257; + eq(2,b.bitCount()); + #else for(i in 0...s_primeNumbers.length) { b = s_primeNumbers[i]; - var bc = b.bitCount(); - #if cpp - if ( bc != bitcount_primeNumbers[i]) - { - trace("b: "+b.toString()); - } - #end - eq(bitcount_primeNumbers[i],bc); + eq(bitcount_primeNumbers[i],b.bitCount()); } b = "31289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095"; eq(b.bitCount(),14286); + #end } public function testIsPositive():Void From edbb6d49b69aaaf6e1072be2a073b93caf12ca03 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 22 Aug 2022 14:11:48 +0300 Subject: [PATCH 045/134] [cpp] Fix bitCount() --- std/haxe/math/bigint/BigInt_.hx | 25 ++++++------------------- tests/unit/src/unit/TestBigInt.hx | 9 ++------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index c1cbfd68fa6..44c7faac177 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -125,28 +125,15 @@ class BigInt_ public function bitCount():Int { var totalBits:Int = 0; - var x:Int32, m:Int32; + var x:Int32; for (n in 0...this.m_count) { x = this.m_data.get(n); - #if cpp trace("x:"+x); #end - m = (x >> 1) & 0x77777777; - #if cpp trace("m:"+m); #end - x = x - m; - #if cpp trace("x:"+x); #end - m = (m >> 1) & 0x77777777; - #if cpp trace("m:"+m); #end - x = x - m; - #if cpp trace("x:"+x); #end - m = (m >> 1) & 0x77777777; - #if cpp trace("m:"+m); #end - x = x - m; - #if cpp trace("x:"+x); #end + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); x = (x + (x >> 4)) & 0x0F0F0F0F; - #if cpp trace("x:"+x); #end - x = x * 0x01010101; - #if cpp trace("x:"+x); #end - totalBits += x >> 24; - #if cpp trace("totalBits:"+totalBits); #end + x = x + (x >> 8); + x = x + (x >> 16); + totalBits += x & 0x0000003F; } return totalBits; } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index a66903d522e..9742d6a9d52 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2835,7 +2835,7 @@ class TestBigInt extends Test { for(j in 0...n.length) { var b:BigInt = BigInt.fromString(n[j]); var r = a.modInverse(b); - eq(r.toString(),mn[pos]); + eq(mn[pos],r.toString()); pos++; } } @@ -2844,18 +2844,13 @@ class TestBigInt extends Test { public function testBitCount():Void { var b:BigInt; - #if cpp - b = 257; - eq(2,b.bitCount()); - #else for(i in 0...s_primeNumbers.length) { b = s_primeNumbers[i]; eq(bitcount_primeNumbers[i],b.bitCount()); } b = "31289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095"; - eq(b.bitCount(),14286); - #end + eq(14286,b.bitCount()); } public function testIsPositive():Void From 257e7512f63713e303ca585978085d1ea4705dd5 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 3 Sep 2022 21:47:00 +0300 Subject: [PATCH 046/134] Add square() and Karatsuba multiplication --- std/haxe/math/bigint/BigInt.hx | 5 +++ std/haxe/math/bigint/BigIntArithmetic.hx | 41 ++++++++++++++++++++++++ std/haxe/math/bigint/BigInt_.hx | 7 ++++ 3 files changed, 53 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index c5670cba2dd..51ccd7174b7 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -185,6 +185,11 @@ abstract BigInt(BigInt_) { return new BigInt(this.modPow(exponent,modulus)); } + + public function square():BigInt + { + return new BigInt(this.square()); + } public function isProbablePrime(tolerance:UInt) : Bool { diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index ecc4fb93e01..c96683933ca 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -392,6 +392,11 @@ class BigIntArithmetic result.setFromInt(0); return; } + + if ((operand1.bitLength() >= 2500) && (operand2.bitLength() >= 2500)) { + multiplyKaratsuba(result, operand1,operand2); + return; + } var resultSize : Int = operand1.m_count + operand2.m_count; result.ensureCapacity(resultSize, false); // always overwrite result @@ -699,6 +704,42 @@ class BigIntArithmetic { return (input.m_count << 5) - BigIntHelper.nlz(input.m_data.get(input.m_count - 1)); } + + public static function multiplyKaratsuba(result:MutableBigInt_, x:BigInt_, y:BigInt_):Void + { + var n = (x.bitLength()>y.bitLength())?x.bitLength():y.bitLength(); + if ( n < 2500 ) { + multiply(result,x,y); + return; + } + n = (n+1) >> 1; + var b = new MutableBigInt_(); + arithmeticShiftRight(b,x,n); + var a = new MutableBigInt_(); + arithmeticShiftLeft(a,b,n); + subtract(a,x,a); + var d = new MutableBigInt_(); + arithmeticShiftRight(d,y,n); + var c = new MutableBigInt_(); + arithmeticShiftLeft(c,d,n); + subtract(c,y,c); + var ac = new MutableBigInt_(); + multiplyKaratsuba(ac,a,c); + var bd = new MutableBigInt_(); + multiplyKaratsuba(bd,b,d); + var abcd = new MutableBigInt_(); + add(a,a,b); + add(c,c,d); + multiplyKaratsuba(abcd,a,c); + var op1 = new MutableBigInt_(); + arithmeticShiftLeft(op1,bd,2*n); + var op2 = new MutableBigInt_(); + subtract(op2,abcd,ac); + subtract(op2,op2,bd); + arithmeticShiftLeft(op2,op2,n); + add(op2,ac,op2); + add(result,op1,op2); + } //----------------------------------------------------------------------- // Private helpers diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 44c7faac177..8e0191e4c8a 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -358,6 +358,13 @@ class BigInt_ return bi; } + public function square():BigInt_ + { + var r:MutableBigInt_ = new MutableBigInt_(); + BigIntArithmetic.multiply(r,this,this); + return r; + } + public function modPow(exponent:BigInt_, modulus:BigInt_) : BigInt_ { if (BigIntArithmetic.compareInt(exponent,0) < 0) throw BigIntExceptions.NEGATIVE_EXPONENT; From 326d0262fa81d946b9fc686aa1ff2baf631e22eb Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 3 Sep 2022 22:07:45 +0300 Subject: [PATCH 047/134] Add test for Karatsuba square --- tests/unit/src/unit/TestBigInt.hx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 9742d6a9d52..8e469be9c60 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2892,6 +2892,18 @@ class TestBigInt extends Test { f(b.testBit(12345)); t(b.testBit(12347)); } + + public function testSquare():Void + { + var b:BigInt = "31289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095312899111185499677385095379916592335598588061783255927420803548214727728870207630191983948724376068401899627616123563545172204899055530302352272847778610639873706336353202093761877582737778967644388283980069216329164759974622415192924361423912834834097982572847229665289965486725933953557514921726179978395828682342961308195443724242730929928110631592986930117802707120080197203803352168090966852137865755500415252722786337003493152656342665044813201880867313011779208419714474015014448780182032616958398612905151589972853856670263969276968800487107824408674583370084303094968400391314759922362195986830202207596680332502343698371432493225860868672103795917753114605230060644403093508418935416904505089602088327325601412709663730602066474016981743423981229695359364504322373458499999084429970918315257406576639170288335216159597192504909615825763191413466758905361986953760342352846455046778423348196835629206819558975114241389728719748889950094477184342553768772940642849290238015121220983265906214423712649581203267665136745074202516467260825331767062907475837419769957088063227358080456524599640705221357017747930954881301847074664566735498598935477860222597799333432825231323448244500921120637415399726170951129421035380206210953128991111854996773850953799165923355985880617832559274208035482147277288702076301919839487243760684018996276161235635451722048990555303023522728477786106398737063363532020937618775827377789676443882839800692163291647599746224151929243614239128348340979825728472296652899654867259339535575149217261799783958286823429613081954437242427309299281106315929869301178027071200801972038033521680909668521378657555004152527227863370034931526563426650448132018808673130117792084197144740150144487801820326169583986129051515899728538566702639692769688004871078244086745833700843030949684003913147599223621959868302022075966803325023436983714324932258608686721037959177531146052300606444030935084189354169045050896020883273256014127096637306020664740169817434239812296953593645043223734584999990844299709183152574065766391702883352161595971925049096158257631914134667589053619869537603423528464550467784233481968356292068195589751142413897287197488899500944771843425537687729406428492902380151212209832659062144237126495812032676651367450742025164672608253317670629074758374197699570880632273580804565245996407052213570177479309548813018470746645667354985989354778602225977993334328252313234482445009211206374153997261709511294210353802062109531289911118549967738509537991659233559858806178325592742080354821472772887020763019198394872437606840189962761612356354517220489905553030235227284777861063987370633635320209376187758273777896764438828398006921632916475997462241519292436142391283483409798257284722966528996548672593395355751492172617997839582868234296130819544372424273092992811063159298693011780270712008019720380335216809096685213786575550041525272278633700349315265634266504481320188086731301177920841971447401501444878018203261695839861290515158997285385667026396927696880048710782440867458337008430309496840039131475992236219598683020220759668033250234369837143249322586086867210379591775311460523006064440309350841893541690450508960208832732560141270966373060206647401698174342398122969535936450432237345849999908442997091831525740657663917028833521615959719250490961582576319141346675890536198695376034235284645504677842334819683562920681955897511424138972871974888995009447718434255376877294064284929023801512122098326590621442371264958120326766513674507420251646726082533176706290747583741976995708806322735808045652459964070522135701774793095488130184707466456673549859893547786022259779933343282523132344824450092112063741539972617095112942103538020621095"; + eq(b.square().toString(),"979058537806756893235764283621924582421624967959196705564083760865282878022528107541866696789999935394715055870410306002387950402245568340192774553939964784785136787035734012929020031542885375787843603153559735941700261460304443075567543513333520762338421517475867224096445639606155592889669086721727997857312141851700193120492947139298141762261650624989441203684454733571273858218678419781871095287063187170220305598627305996931173474871683260238740358756331777477446041053891726564542483445966219729545222131712519817549673448935818892604478829972483257523220664889053686981485569952646163209531357683066245563257049257290320527044324067319043073011746430085797237805622069664157003517740615901207267842299601544397898380578066816137990306245652655168526632019958283225460517476594435652706609647029870409172355571128872501060775377848615950844966107944014008828433520438618661476482804692649631032580865675177913085826911130919185912284560057852718730476885523564039401019893536044992969889829486583733742979641766664498732850142086385975404324354631901442327591309984820899557314159969342026806890391805464777141402390942224468818370286189339496153617050553815039679012522805912033547445688105403239187775875234695574708938333630275401964101884672755647448401504106167065029833455420760044079588321937865328594849576565652107016941893441134441489443804881782134985154316330370659296182735277532522634915945354671652745525615738151340897705499294856121970124424262561578588661070768748543272426858577119516700312630657114436724547836855591208750226685060140040174125537545428385497463753943072571227529783378333550538113917364144160466355547190632269349246026760183016106138179385808844467631134147595861974359080407426949021054600827406974588925698075948850086018471308981465533181474754519822334992687302851294717402499224703819753452353952665382241366283063603874724557289535418803460892960913805996252420050456490043065470303385155367575762141894594926816357914610921880140706035292094245838934453097365588075603899819378216402761593808343896644462707142751099198293773175651073305368077604244261547846445304405563072251272763052240231016311108836221199803715720948798172146146822837581513933599860625531522416596165538352143985260629484252013240603746124859559804801379978198335907753720463429955164228727856745536104065928159895022176223424186676545666373418638624515974026952078389390603147781211534420797830979303858034305405963664641808204943737765697507602185501362004131536520605837623881178803800749437858792505505238150955053761142804861634042146799366363235647799188637302595418142869067049152019189445176191871946879297026005090278766372933530402711461980515815870976408958180928496880238421145181532819117861814761897826373390693324175380062318156951380609989834514389153506089552696574682402647450330958493005951193468281744803168784091237754176890610088913252782656385227417856173153796739713680301256174874938347811850314525153900194383799119062025926320526532206551632108138480165731746313415303742768329957794485047908468899083433663540940626762422522727602719098293608567645087759241483407201426209279494495557718081985308778026799719285340918877391360803048053840729645544493187813037548603853178682920950366515895564102068512725726599625068190958931320820002004036777484199104280379016410671705960669241533187095062758439830792180062352002958237102534913594033310904155723190519957657651063409063077922268057110521276843832626321784094221331838291720863598362201637482982557498487167128503528010841650137600621194618825718913787878637874158719897046754343494436690880586535743871385530923679862732430558987722978407824753264841508350145784200495705312694541403861480587124503513617051615355165667276602067006869573031643215099845702145930825314542363371139576115632234293137920599511834828365563730149358865909350003317859285250309685685322448925566338410052906109034239095149839766387933915982151176143681446909556796553781528029993609380244575797782603417796157573908355342053078921667619277056117773641377739105214399260243775552861901116387297062708321870433018669121765566223545992426192779945681105161465320976335025140676734385352196650808854595037261192773876921157777828951638074323437757154167756183736779714987927379914616922390432227884248509928423348348430559903215059285516157829243864992514282729100714602148178096293798530554736397701129911531687838676479862011069639846771617321911275098402664072736901473534364233835113885008174723233809864532594170861087659797792026735593810021274574062256230262763106103582405624406237587116610638356059536376119763753940718949067160997044098102742891715519335938406585897503407052001156147872384634992909881846670028110702885992070643183658137173695169489605344750236969441460956409016907469503728703722147166164667184895723312744451221079250974388851014976113215778389415709550864976338414714415282198899781199485143413547642073070333703453041991729851722204831893949661284948278952019511080557920516117663492394801410785471153142305358908430005926122088425456777703581015061172890411482084864438241187387006519018519275910817740324420828827644510756798743746171580678747205430023940914349021412922348648813690711415108878616582735938385145246351411703000579449900946625771746517557897313864023240171779661756642902980917766773849558999536597964746250315579594570258217076171836485913926745555332472687917200213209151831145639385355204417097626516952963946980108265813591932269507107101560962958228173321459342668360139766838080290225100612874548521822048912950051246755516443085776878657865951322820940997926521055322919755491720427953784844995505352482256716630626962365260947518734500150983169085369416384607241048573938054469346018079223454714934100062708452711675796747743061334696567353621054901052045563971433032825936923138111509516160074782990668727851860537550871639285515258390953003025377043760348813217411905320008316595565458523978429030228547755053027452998995175647639943390182154386587745054114420276029928192002183064155459505927825924761579454674977915931429123445912383711223199802040947961400754470453505830317493844788975124448221382310191952533682912781122146683082391476343476658971305372339703264307994088812368699633302945684255186725732149566605376689208649708557952071235063928208521921638706696956978895222709161811838140625659720965483125965649466305620990898284638221976728990986110673596024748603068820173274453290277719992553394376988087147536192699854703696831257004809823152987020172366759024877411215679846667947979625629206158992947430092382748449689237292162545063528868619202132002813473146939690670565728963371542027328203377969064564838223281496044438357883928062929973366523657541287665770728437725161128159572548336754811659677422647914446119472330449409152185942362464109300247247566241601010329150568050984755339721417405906913032262120848538170347935377515114091440534423595745973234353951904308633432470661288766005933908325052008189916021474966380674134932827403820468308320796110487662800348838804901944857674627156276552711225120265741479650321111046607622511421133615885466219848951124866271064232623319161702832620320985812565769534282355893996230694166186143435849907269168064034810754986647503829851613467173289068392573651838028922900314648377450393531143583816750062902886157099248004141517455567598675078129986917659553974623072881996532017303312951423269948489427346337474567050931279551592114178104089724635607643426578772606556619200412455441264533191560785328613363654343177058053149391625925452695753785715482584334910884922112645277220436430224875036739943591075606371659859276719819380485592830769141538584119994664043511989409613945923228426088712826794015991635045433619288407984613715948778173531046347421269068661500735906738223958994942051180343962226786386225079562960188735451247381713929691525021691293258352247725982625532038939581534112770333526190756331097202065372516619762994729457492597236608568955727177474282927067210683487165503436740184555313983058368167202940704498139158356192549926106790359255487403131245256305322759776145691881722537735295644854065755734058815021899821147778542096447711944544555831969873184076358578694692304910423228482342315118981773770275896509680560104263150802420378954735614559800229314380102608494927015762720221236167177065286299871146478614024094441318121290539962911275851233224992849873863853472487662792342374621868583424205303953003806365145842037440594321508048994039450143247474952305522443977985981848347500051216277479959331743762886935403161780865286690273664306622918530850353874293567047639319408911445092697967750333603130724172641250428389449056562149439457772098451500193607687895623323255051560597700216364754287016049618308265945915598140295299428864792348279417890496335999764799723377295880178138388616282678807101505063159043076029435424924434449983438966508307518404837610082324185448409740983426274119333595029404167113115571345781544510075027421837066648483090981306751619907006574990840580184247733926044068290871205886535700964967693443291378082148156471961404731219743349886722482388399453312965849803842174078285120894482557766035736617890804563860933609721423985565220653852601113466810124437810418123628866832608093735106338339281681197686377580906991909819386947372192208193807792914011052186195542268703604906783161391718242369214363051953508772528764914098124209883134840160988974375082206875752429698422869961586201438865137227466498780344632268877616455836955028195745432199012214566093788426734896427602881130895700657925091137063876782576805529321712228712412046942787237773316735567582106081198124968018422759524327594862650007755577313899017799238889835939210900477636509864421205366316945887920718051392657115460441707108460847476464658496375184681429018860147478916472622133059471957807878706723582473881788629449293192131183141381383255100303848368743038674886424218569631350744012169601301656150040411667906186126466240213067358779275164956727625356201271124037634481582421614520901026344285906407258219144968485453766872962047170767508345105097312558473235381855130609229850363238554647115223277709842816658505498263271711216973228823465919263339412938833019142547692355216394005235960151895301946938138439525275147705396962178617518897046756909784178570788086123644897401235813633836627013994252949644707204764909465367988926276571669599785516750087883455403706951252608219016723917761980351131178716191835706810278807060769342879988454378752614885205636350107221016905706593519588364424326380293124926984152797373115619712333464649984809290962210178283440940851583744148883240779537809363479701668431277094535940063256409207851734008457011686022301457866460799062788837512278476351191385837723684726370499480334642976528441236439506451335480344792804657735849831865698036435024341188410923606416113500691009420488030502017683305884129287111772392113118105299771643657823455593913888807935224033551492753626825190866319437505229406469526933182854232259117138420794309592767975765661091563926101109446375546249808276056926376765844205394328009108309263349755210400976963238022469204558553782707161547476995519474602463700797495652173588102086053896102656385344758908707574738477594082536001517861689859382656818044046913380398557146569060508080807456749090437099445859299158403758726019709293205961353845166781010084709885920713222757990542698031905931283922753264912183807112337251273918199144288998795229749429557212337248539854704750365732110349701110156451761724370838641426339242277953507657250751884243150702397551607636820152948812798713208923142370697019343943739933731428095880027617752931691192237935921833174221762512227642824270355163763778328703596790395576941218369535992958364386329638923149931697030069265708225083207138577837327908085523886178614683557013995007282129363623466154422006486255003169767873785577934471188033670031226022158341870038521548996347206723282507451181518028888988599985831521008142211253793305953380227850186040926064440677039456643814386742386767038738956761028557477615582563524193404544938340263430199152490227856864275406633309475961577261586548264042971376545222894683855068656717020043412951999872122737596678299448863678992619486373799097595121950036554336891372411335816530630374926714204977800384733267855177069495929023615252846972148680966069694029234375612509787303587011721373986404835988275089143850334909002304971423108431298031820971017250657655822007016261523607626593785638945491684270778303839017330417109466713313070772447685604024912166351472658343918673070647678606166153918299296346229486196086493470878145003410811791454556757742415897084215912803731595062068631010740382955588067548231555440602400281163362114692223482506911173482597712097137548366988480261540780525297561281650664288330753311108094505535497773231926048521312729711914820122953553129255011984363508563022857046044887286400137126681237301836422247394860497137647809066100949105902199295532277004491087892339281981764942881526472351650073141466820850148506490225828672659350803924624758928375237930065714836775985441576539363588522580632963947030514117525916615597030134225775532235504362377550454298896020771868995301024260452707393482017656523539423165677165169590143999328253255567269567189795948650767506049877532429391507449287416736167661934246754355368954919719737478341992333919920435303695061748558898502288220579611937045718983677314923368119989815466036626627159071442052756040188596921300127461029871660607174219997387589646544931026867059664465864805498041039504146108516638643800353782888363710003275290216361963711324980397167818041536506926948614828740618253563236350370780885869122282358966292565822218552380089543792971568003611161385442306752627532428215453334703278803036788298741099537326502500859442024251527187693849307825916118735329658547141763845798413045235962742879521826723303607022349504509421458191314928136136818395243397383958062535148230669082809499539122578293479517158078608333415541809880049885430762801317943046011454302540146595229430084143746206733356552659843922409085928252997097477911977002141233347328714428305826491310860463609692928571519377072393277141764324860281090386614809101456857865531792469932291931059706938712287605045603626194417741186655105097485616577764282242205158143159113648110019391854743408713977004493855911937487680134684145308088447784880789972381836502432857283089021555438796753919670987928768539045015107685769859220936859324098934322183626437106714639922023296912494373235992392235410808531254500697010218769686064321692670853731418619243688952239753879669604097316655680577378904726567038910038378346311255088640128479375846164643919480203675211044259743422347115531460192078561831336910259121510400840498867866503799589160367918428557637473117904779400106254843836638814527073968538102089100967459757533321815753505481396344315222760421597204233520615657379881597125149690292010284942412311964882191645145397324944402010839701892977759616820807500333274758186843480695658149881775717169927138485156226883699426086984521595747462415627179725573799181816194944757650549166616930682222300725224524427177561150044792135101010674848277170186967642531760448521330571951858411831611988171446919656085499898193794491396010719692122454035051905551731529814999780225686966169423209747016448359803189186522381241969799837476516113549085542010216346690901491734100761928676402295031587802742954328688048521401921200469344333041491539080744786765390438873504174710519234683777251162823168951265639070175701478522789292937214237920687831813821844046702190941091244602065942275038246224086293810902100231890829031589035548290993713304631432698536501361454867851020669522964286510847203185407336079460871073173136859732094601769065425696348340323438181969045850896957925102654624550674545652803034063022575771477223761318756036570147073628869199194732764960803588040913260630162482459868228616866335176316929564526216675510519204738466423465553523707290651363629405302657554264620738138610694231207966746808040361775963012457734565670649521309478368862282664377414766444012242629852108309047592323726235369396045873737223618350460839291860000487032541791807954657364954040795038009858866088269702986665289626915881262912911691311918245824000318193755082376648206724577200772863732702289987879709348371716222822650281097388162702300195372997674929869383476556104306213959982142476495458402896722951141078659723229307403290685582440933404578633717832081585226774784139827789557758029696660009922964340338529347082479871369640619219404866083516324290106524553918947673139895664479235034076666092127442687524397095559872522717393378176428075183874859177016157693554859136910386135230747446158028309375544874183926983365480035154804796967087602664759453846673269943887016056186890845687185275805353410361232474067012685927243542225974756276328914425087901035573852775473215774749469219258652111434926727458049392297998581419997475257597015091772213299871042652811840227660801516736767741762412310585769891416679950629089122017832085293293491105697878907168637230258746237581573546149263529790352058912880680596138857701176997051232900729184103879737378314302354200961078302557160030390095926240622208147137114293449558999025"); + b = -1; + eq("1",b.square().toString()); + b = 12; + eq("144",b.square().toString()); + b = "900638577896799483816152607866547736957740898853209483873285677143564366192332208307174317959001709443039404185797701672275527838488848483763636556445777023797930138165123350019004132380446348231021254368110746126663615959395864308678978278260535734556772116555567464463944778761494325692023874761887965433325891748738093112709958788369487884977010548779088188484331392128315526085363468945546963420585208800664404356458139205589044250148264071701123009387700818846733471543158424023118048291252187133437780648242543956566170672422350843150080779372519053879333392134884951949440626103615875779513578928323532154688532003749917394291989161377389875366073468404983368368097031044949613470296667047208143363341323720962260335461968963306358427170789478369967512574983206915797533599998535087953469304411850522622672461336345855355508007855385321221106261546814248579179126016547764554328074845477357114937006730911294360182786223565951598223920151163494948086030036705028558864380824193953573225449943077940239329925228264218792118724026347617320530827300651961339871631931340901163772928730439359425128354171228396689527810082955319463306776797758296764576356156478933492520370117517191201473793019864639561873521807073656608329937521"; + eq(b.square().toString(),"811149847995969351721277742900450882666128710880121943723033984496363909727632962176457328745441351015478577651463199674431737573765944282100259530965252603943339128013246587325032433979335734786504965901799889302406159701354628874288473762021809902804053601718275980939845906748371292333374386010272739798132621713025723929014161498355914599120590999020567498930685525496898528572272450620596571129956342956107921718415101699685615809685762171982015939351781590111612963744323021219017314395169101957513801384312440238545652940865450311026811203970970957029411203919505705426812806790770118405250890709523784587944630212866255970356938290335586926983865860825950787572716874669983883676778931308475575258301756972135670253797560275576412260135518662419116827857095886038355919354007003597455667513169127242846260995278068044555964903013553940393196332871118985123422282045524588981442057877700191236290306997574581238117918228368072872123983495741091953470906723396416933752597404582681058872156303027788029666728474877486709304615595192903559931696626288338307760680901186871217690767936503046402666623639181700299821260147573719588148214702677548426987049866959796951843501932327233549325130570874940881569441505740992412152163422139000345033086150490637830379626663095530609392696422973033783031490813002844626281482749160143146002262443245511657909938799353706943265245247971607714172276190975033083092323436499204422426985912227333265456839641376409257331923063349532372142400057625690712436017349830479014752049237163321310012828072244966656829228823891878508108627558804036584962958423530832782619333442944482366365076764192311978676820924849805425113873330915805633022353818149007166650579284997431056643960362882638106719229415840167611751425985456191915329684820329204462418286776934054555573154503205065497338435727750784376231689637383309663963162154399631027567945337979218900759282873105744106028948285791212405440632741973882786929715605978665500815612346882365153383022113445334714770937230143310380914232402858039429871518297820436033846958308390362520620180048952725186450999823465158343616672346992013811084929170401354704051849364793860083975422550113785138190483582776827060329176948827042813576191758992791063707390435752053126595798631052684617709069724195377659960922914914394808920839148428685275090182476586835424154247611667167737411950171729176182187724122365481161419269660486776280489015370727450596846878409032710715406436303763625441"); + } private static var bitcount_primeNumbers = [1,2,2,3,3,3,2,3,4,4,5,3,3,4,5,4,5,5,3,4,3,5,4,4,3,4,5,5,5,4,7,3,3,4,4,5,5,4,5,5,5,5,7,3,4,5,5,7,5,5,5,7,5,7,2,4,4,5,4,4,5,4,5,6,5,6,5,4,6,6,4,6,7,6,7,8,4,5,4,5,5,5,7,5,7,7,4,5,6,7,6,8,7,7,7,8,8,3,4,5,4,5,5,5,6,3,5,4,6,5,7,5,5,6,7,3,4,5,5,5,5,4,5,6,6,7,5,7,7,7,6,7,8,7,7,3,4,5,6,5,6,6,7,7,7,6,6,6,7,8,7,6,7,8,6,7,7,5,6,7,7,7,7,7,6,8,9,7]; From 8b65d53013ed8e8ee138f7c3129ee70c85a1a90d Mon Sep 17 00:00:00 2001 From: flashultra Date: Wed, 18 Jan 2023 09:26:57 +0200 Subject: [PATCH 048/134] Add divMod and hashCode functions.Auto convert to string --- std/haxe/math/bigint/BigInt.hx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 51ccd7174b7..7f9a5c88f1c 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -319,6 +319,17 @@ abstract BigInt(BigInt_) { return BigIntArithmetic.compare(a, b) >= 0; } + + // String conversions + @:op(A + B) @:noCompletion public static inline function toStr_left(a : String, b : BigInt) : String + { + return a+b.toString(); + } + + @:op(A + B) @:noCompletion public static inline function toStr_right(a : BigInt, b : String) : String + { + return a.toString()+b; + } // Binary addition @:op(A + B) @:noCompletion public static inline function addInt_(a : BigInt, b : Int) : BigInt From b030dec84f1de2ca000042ecd47eb7ebfcc52ccd Mon Sep 17 00:00:00 2001 From: flashultra Date: Wed, 18 Jan 2023 09:34:52 +0200 Subject: [PATCH 049/134] Fix last commit. --- std/haxe/math/bigint/BigInt.hx | 11 +++++++++++ std/haxe/math/bigint/BigInt_.hx | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 7f9a5c88f1c..565ae1609b7 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -149,6 +149,12 @@ abstract BigInt(BigInt_) { return new BigInt(BigInt_.randomPrime(bits,tolerance)); } + + public static function divMod(dividend:BigInt, divisor:BigInt):{quotient:BigInt, remainder:BigInt} + { + var result:{quotient:BigInt_, remainder:BigInt_} = BigInt_.divMod(dividend,divisor); + return {quotient:(new BigInt(result.quotient)), remainder:(new BigInt(result.remainder)) }; + } public inline function getBit(index : Int) : Int { @@ -219,6 +225,11 @@ abstract BigInt(BigInt_) { return this.testBit(n); } + + public function hashCode():Int + { + return this.hashCode(); + } //----------------------------------------------------------------------- // Operators diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 8e0191e4c8a..b822f81a691 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -146,6 +146,16 @@ class BigInt_ return ( ( m_data.get(chunk) & (1<<(n & 0x1f))) != 0); } + public function hashCode():Int + { + var hash:Int32 = 0; + for (n in 0 ... this.m_count) + { + hash = 31*hash + this.m_data.get(n); + } + return hash; + } + public function isProbablePrime(tolerance:UInt):Bool { if ( tolerance <= 0 ) return true; @@ -525,6 +535,14 @@ class BigInt_ r.compact(); return r; } + + public static function divMod(dividend:BigInt_, divisor:BigInt_):{quotient:BigInt_, remainder:BigInt_} + { + var q = new MutableBigInt_(); + var r = new MutableBigInt_(); + BigIntArithmetic.divide(dividend, divisor, q, r); + return {quotient:q, remainder:r}; + } //----------------------------------------------------------------------- // Private implementation From 21900e6cb31c858469707ce085101f05b3de56fb Mon Sep 17 00:00:00 2001 From: flashultra Date: Wed, 18 Jan 2023 21:26:16 +0200 Subject: [PATCH 050/134] Fix overflow behaviour --- std/haxe/math/bigint/BigIntArithmetic.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index c96683933ca..b91c1e1a341 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -132,7 +132,7 @@ class BigIntArithmetic public static function add(result : MutableBigInt_, operand1 : BigInt_, operand2 : BigInt_) : Void { var c : Int = 0; - var x : Int = 0, y : Int = 0, z : Int = 0; + var x : Int32 = 0, y : Int32 = 0, z : Int = 0; if (operand1.m_count == operand2.m_count) { result.ensureCapacity(operand1.m_count + 1, (result == operand1) || (result == operand2)); From 39038bf194232753a1099b06273ef4fd4e23e9cd Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 26 Jan 2023 23:35:38 +0200 Subject: [PATCH 051/134] Add negative base for modInverse --- std/haxe/math/bigint/BigInt_.hx | 6 +++++- tests/unit/src/unit/TestBigInt.hx | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index b822f81a691..250ec6244b8 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -417,7 +417,7 @@ class BigInt_ if ((BigIntArithmetic.bitwiseAndInt(this, 1) == 0) && isModulusEven || modulus.isZero()) return BigInt.ZERO; - var x:BigInt_ = MutableBigInt_.fromBigInt(this); + var x:BigInt_ = this.abs(); var y:BigInt_ = MutableBigInt_.fromBigInt(modulus); if (x.sign() == -1 || BigIntArithmetic.compare(x, modulus) >= 0) @@ -484,6 +484,10 @@ class BigInt_ while (BigIntArithmetic.compare(c, modulus) >= 0) { c = sub2(c, modulus); } + + if ( this.sign() < 0) { + c = sub2(modulus,c); + } return c; } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 8e469be9c60..83b7fb294e1 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2839,6 +2839,12 @@ class TestBigInt extends Test { pos++; } } + + // Negative base test + var a:BigInt = BigInt.fromString("-1000000007"); + var b:BigInt = BigInt.fromString("4294967296"); + var r = a.modInverse(b); + eq("2226617417",r.toString()); } public function testBitCount():Void From de89828057ece48e0eeb68db25209272532941e2 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 31 Jan 2023 11:39:43 +0200 Subject: [PATCH 052/134] Add OR and AND (bigint) operations --- std/haxe/math/bigint/BigInt.hx | 11 +++++++++++ std/haxe/math/bigint/BigIntArithmetic.hx | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 565ae1609b7..295ec19d13a 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -411,12 +411,23 @@ abstract BigInt(BigInt_) { return new BigInt(BigInt_.modulus2(a, b)); } + + // Binary OR + @:op(A | B) @:noCompletion public static inline function orInt_(a : BigInt, b : Int) : Int + { + return BigIntArithmetic.bitwiseOrInt(a, b); + } // Binary AND @:op(A & B) @:noCompletion public static inline function andInt_(a : BigInt, b : Int) : Int { return BigIntArithmetic.bitwiseAndInt(a, b); } + + @:op(A & B) @:noCompletion public static inline function and_(a : BigInt, b : BigInt) : BigInt + { + return new BigInt(BigIntArithmetic.bitwiseAnd(a, b)); + } // Binary shift left @:op(A << B) @:noCompletion public static inline function asl_(a : BigInt, b : Int) : BigInt diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index b91c1e1a341..aa8de795f9d 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -696,6 +696,26 @@ class BigIntArithmetic { return operand1.m_data.get(0) & operand2; } + + public static inline function bitwiseAnd(operand1:BigInt_, operand2:BigInt_):BigInt_ + { + var result:MutableBigInt_ = new MutableBigInt_(); + result.m_count = (operand1.m_count > operand2.m_count) ? operand2.m_count : operand1.m_count; + result.ensureCapacity(result.m_count, false); + for (i in 0...result.m_count) { + result.m_data.set(i, (operand1.m_data.get(i) & operand2.m_data.get(i))); + } + result.compact(); + return result; + } + + /** + Returns the bitwise OR of `operand1` with `operand2`. + **/ + public static inline function bitwiseOrInt(operand1 : BigInt_, operand2 : Int) : Int + { + return operand1.m_data.get(0) | operand2; + } /** Returns `floor(log2(input))`. From 786cbec461fd278f32ca6e90b775c8df0c82e4f7 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 31 Jan 2023 13:31:25 +0200 Subject: [PATCH 053/134] Fix for negative numbers --- std/haxe/math/bigint/BigIntArithmetic.hx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index aa8de795f9d..77edf927fe1 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -700,10 +700,20 @@ class BigIntArithmetic public static inline function bitwiseAnd(operand1:BigInt_, operand2:BigInt_):BigInt_ { var result:MutableBigInt_ = new MutableBigInt_(); - result.m_count = (operand1.m_count > operand2.m_count) ? operand2.m_count : operand1.m_count; + if ( (operand1.m_count > operand2.m_count)) { + result.m_count = (operand2.sign() == 0)?operand2.m_count : operand1.m_count; + } else { + result.m_count = (operand1.sign() == 0)?operand1.m_count : operand2.m_count; + } result.ensureCapacity(result.m_count, false); for (i in 0...result.m_count) { - result.m_data.set(i, (operand1.m_data.get(i) & operand2.m_data.get(i))); + if ( i > (operand1.m_count-1) ) { + result.m_data.set(i, operand2.m_data.get(i)); + } else if ( i > (operand2.m_count-1) ) { + result.m_data.set(i, operand1.m_data.get(i)); + } else { + result.m_data.set(i, (operand1.m_data.get(i) & operand2.m_data.get(i))); + } } result.compact(); return result; From d1a15f8424db2228ed795d4f2e5d64df6979ea29 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 31 Jan 2023 14:48:42 +0200 Subject: [PATCH 054/134] Correct OR for bigint --- std/haxe/math/bigint/BigInt.hx | 9 +++++++-- std/haxe/math/bigint/BigIntArithmetic.hx | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 295ec19d13a..105e45678d6 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -413,9 +413,14 @@ abstract BigInt(BigInt_) } // Binary OR - @:op(A | B) @:noCompletion public static inline function orInt_(a : BigInt, b : Int) : Int + @:op(A | B) @:noCompletion public static inline function orInt_(a : BigInt, b : Int) : BigInt { - return BigIntArithmetic.bitwiseOrInt(a, b); + return or_(a, b); + } + + @:op(A | B) @:noCompletion public static inline function or_(a : BigInt, b : BigInt) : BigInt + { + return new BigInt(BigIntArithmetic.bitwiseOr(a, b)); } // Binary AND diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 77edf927fe1..b27194f0fd0 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -722,9 +722,22 @@ class BigIntArithmetic /** Returns the bitwise OR of `operand1` with `operand2`. **/ - public static inline function bitwiseOrInt(operand1 : BigInt_, operand2 : Int) : Int + public static inline function bitwiseOr(operand1 : BigInt_, operand2 : BigInt_) : BigInt_ { - return operand1.m_data.get(0) | operand2; + var result:MutableBigInt_ = new MutableBigInt_(); + result.m_count = (operand1.m_count > operand2.m_count)?operand1.m_count : operand2.m_count; + result.ensureCapacity(result.m_count, false); + for (i in 0...result.m_count) { + if ( i > (operand1.m_count-1) ) { + result.m_data.set(i, ((operand1.sign()==0)?operand2.m_data.get(i):0xffffffff) ); + } else if ( i > (operand2.m_count-1) ) { + result.m_data.set(i, ((operand2.sign()==0)?operand1.m_data.get(i):0xffffffff)); + } else { + result.m_data.set(i, (operand1.m_data.get(i) | operand2.m_data.get(i))); + } + } + result.compact(); + return result; } /** From 3733409a62eff12b332eb2461e0f63e22d27c2b5 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 31 Jan 2023 15:51:54 +0200 Subject: [PATCH 055/134] For OR small optimization --- std/haxe/math/bigint/BigIntArithmetic.hx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index b27194f0fd0..cf9e5c21e80 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -727,11 +727,13 @@ class BigIntArithmetic var result:MutableBigInt_ = new MutableBigInt_(); result.m_count = (operand1.m_count > operand2.m_count)?operand1.m_count : operand2.m_count; result.ensureCapacity(result.m_count, false); + var operand1Positive:Bool = operand1.sign()==0; + var operand2Positive:Bool = operand2.sign()==0; for (i in 0...result.m_count) { if ( i > (operand1.m_count-1) ) { - result.m_data.set(i, ((operand1.sign()==0)?operand2.m_data.get(i):0xffffffff) ); + result.m_data.set(i, (operand1Positive?operand2.m_data.get(i):0xffffffff) ); } else if ( i > (operand2.m_count-1) ) { - result.m_data.set(i, ((operand2.sign()==0)?operand1.m_data.get(i):0xffffffff)); + result.m_data.set(i, (operand2Positive?operand1.m_data.get(i):0xffffffff)); } else { result.m_data.set(i, (operand1.m_data.get(i) | operand2.m_data.get(i))); } From aec1211316c8da9b9d4104bc5368349de376748b Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 31 Jan 2023 17:38:55 +0200 Subject: [PATCH 056/134] Add XOR and NOT bitwise operators --- std/haxe/math/bigint/BigInt.hx | 15 ++++++++++++ std/haxe/math/bigint/BigIntArithmetic.hx | 31 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 105e45678d6..5ead3be553d 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -422,6 +422,21 @@ abstract BigInt(BigInt_) { return new BigInt(BigIntArithmetic.bitwiseOr(a, b)); } + + @:op(A ^ B) @:noCompletion public static inline function xorInt_(a:BigInt, b:Int):BigInt + { + return xor_(a, b); + } + + @:op(A ^ B) @:noCompletion public static inline function xor_(a:BigInt, b:BigInt):BigInt + { + return new BigInt(BigIntArithmetic.bitwiseXor(a, b)); + } + + @:op(~A) @:noCompletion public static inline function not_(a:BigInt):BigInt + { + return new BigInt(BigIntArithmetic.bitwiseNot(a)); + } // Binary AND @:op(A & B) @:noCompletion public static inline function andInt_(a : BigInt, b : Int) : Int diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index cf9e5c21e80..655e4f26999 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -741,6 +741,37 @@ class BigIntArithmetic result.compact(); return result; } + + public static inline function bitwiseXor(operand1:BigInt_, operand2:BigInt_):BigInt_ + { + var result:MutableBigInt_ = new MutableBigInt_(); + result.m_count = (operand1.m_count > operand2.m_count) ? operand1.m_count : operand2.m_count; + result.ensureCapacity(result.m_count, false); + var operand1Positive:Bool = operand1.sign() == 0; + var operand2Positive:Bool = operand2.sign() == 0; + for (i in 0...result.m_count) { + if (i > (operand1.m_count - 1)) { + result.m_data.set(i, (operand1Positive ? operand2.m_data.get(i) : (operand2.m_data.get(i) ^ 0xffffffff))); + } else if (i > (operand2.m_count - 1)) { + result.m_data.set(i, (operand2Positive ? operand1.m_data.get(i) : (operand1.m_data.get(i) ^0xffffffff))); + } else { + result.m_data.set(i, (operand1.m_data.get(i) ^ operand2.m_data.get(i))); + } + } + result.compact(); + return result; + } + + public static inline function bitwiseNot(operand:BigInt_):BigInt_ + { + var result:MutableBigInt_ = new MutableBigInt_(); + result.copyFrom(operand); + for (i in 0...result.m_count) { + result.m_data.set(i, ~operand.m_data.get(i)); + } + result.compact(); + return result; + } /** Returns `floor(log2(input))`. From e76288c603099c95bb4de5ebc7e51ed2f7bac00e Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 26 Feb 2023 13:43:50 +0200 Subject: [PATCH 057/134] Add bit operations and powerOfTwo method --- std/haxe/math/bigint/BigInt.hx | 20 ++++++++++++++ std/haxe/math/bigint/BigInt_.hx | 38 ++++++++++++++++++++++++++ std/haxe/math/bigint/MutableBigInt_.hx | 20 ++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 5ead3be553d..b2e74efd8b9 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -226,6 +226,26 @@ abstract BigInt(BigInt_) return this.testBit(n); } + public function setBit(n:Int):BigInt + { + return new BigInt(this.setBit(n)); + } + + public function clearBit(n:Int):BigInt + { + return new BigInt(this.clearBit(n)); + } + + public function flipBit(n:Int):BigInt + { + return new BigInt(this.flipBit(n)); + } + + public static function getPowerOfTwo(exponent:Int):BigInt + { + return new BigInt(BigInt_.getPowerOfTwo(exponent)); + } + public function hashCode():Int { return this.hashCode(); diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 250ec6244b8..283ef3897f1 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -146,6 +146,44 @@ class BigInt_ return ( ( m_data.get(chunk) & (1<<(n & 0x1f))) != 0); } + public function setBit(n:Int):BigInt_ + { + return (testBit(n)) ? this : flipBit(n); + } + + public function clearBit(n:Int):BigInt_ + { + return (testBit(n)) ? flipBit(n) : this; + } + + public function flipBit(n:Int):BigInt_ + { + if (n < 0) throw BigIntExceptions.INVALID_ARGUMENT; + var isNegative:Bool = sign() < 0; + var chunk = (n >> 5) + 1; + var changeBit:Int = (n & 0x1f); + var r:MutableBigInt_ = new MutableBigInt_(); + if (chunk > m_count) { + r.fixedSizeCopyFrom(this, ((changeBit == 0x1f) ? (chunk + 1) : chunk), isNegative ? 0xffffffff : 0x0); + } else { + if (chunk == m_count && changeBit == 0x1f) { + r.fixedSizeCopyFrom(this, chunk + 1, (isNegative ? 0xffffffff : 0)); + } else { + r.fixedSizeCopyFrom(this, m_count, 0); + } + } + r.m_data.set(chunk - 1, r.m_data.get(chunk - 1) ^ (1 << changeBit)); + r.compact(); + return r; + } + + public static inline function getPowerOfTwo(exponent:Int):BigInt_ + { + var num = BigInt_.fromInt(1); + var r = arithmeticShiftLeft2(num,exponent); + return r; + } + public function hashCode():Int { var hash:Int32 = 0; diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index ce8c8965252..35e3e1b00d2 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -261,6 +261,26 @@ class MutableBigInt_ extends BigInt_ m_count = other.m_count; } } + + private function fixedSizeCopyFrom(other:BigInt_, size:Int, value:Int = 0):Void + { + if (other != this) + { + ensureCapacity(size, false); + var maxSize:Int = (size > other.m_count) ? other.m_count : size; + for (i in 0...maxSize) + { + m_data.set(i, other.m_data.get(i)); + } + var diffSize = size - maxSize; + while (diffSize > 0) + { + m_data.set(maxSize++, value); + diffSize--; + } + m_count = size; + } + } //----------------------------------------------------------------------- // Private implementation From c4fe08cd68168774a8594f4ba3173c82e47d685a Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 26 Feb 2023 16:21:06 +0200 Subject: [PATCH 058/134] Test bit for negative numbers --- std/haxe/math/bigint/BigInt_.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 283ef3897f1..24a6e75cd94 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -142,7 +142,7 @@ class BigInt_ { if ( n < 0 ) throw BigIntExceptions.INVALID_ARGUMENT; var chunk = n >> 5; //divide by 32 - if ( chunk >= m_count) return false; + if ( chunk >= m_count) return (sign()<0); return ( ( m_data.get(chunk) & (1<<(n & 0x1f))) != 0); } From b877aa963b9202601943555cdbf454acf5d4e566 Mon Sep 17 00:00:00 2001 From: flashultra Date: Wed, 1 Mar 2023 14:07:04 +0200 Subject: [PATCH 059/134] Use enum abstract for exception. Reformat the code --- std/haxe/math/bigint/BigInt.hx | 381 +++++-------- std/haxe/math/bigint/BigIntArithmetic.hx | 557 ++++++++---------- std/haxe/math/bigint/BigIntExceptions.hx | 21 +- std/haxe/math/bigint/BigIntHelper.hx | 77 +-- std/haxe/math/bigint/BigIntTools.hx | 48 +- std/haxe/math/bigint/BigInt_.hx | 598 +++++++++----------- std/haxe/math/bigint/MultiwordArithmetic.hx | 584 +++++++------------ std/haxe/math/bigint/MutableBigInt.hx | 321 +++++------ std/haxe/math/bigint/MutableBigInt_.hx | 287 ++++------ 9 files changed, 1151 insertions(+), 1723 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index b2e74efd8b9..f3e1ce1fde2 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package haxe.math.bigint; import haxe.ds.Vector; @@ -27,457 +27,391 @@ import haxe.io.Bytes; /* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(haxe.math.bigint) -abstract BigInt(BigInt_) -{ +abstract BigInt(BigInt_) { //----------------------------------------------------------------------- // Public constants //----------------------------------------------------------------------- - - public static var ZERO(default, null) : BigInt = new BigInt(BigInt_.fromInt(0)); - public static var ONE(default, null) : BigInt = new BigInt(BigInt_.fromInt(1)); - public static var TWO(default, null) : BigInt = new BigInt(BigInt_.fromInt(2)); - public static var NEGATIVE_ONE(default, null) : BigInt = new BigInt(BigInt_.fromInt(-1)); + public static var ZERO(default, null):BigInt = new BigInt(BigInt_.fromInt(0)); + public static var ONE(default, null):BigInt = new BigInt(BigInt_.fromInt(1)); + public static var TWO(default, null):BigInt = new BigInt(BigInt_.fromInt(2)); + public static var NEGATIVE_ONE(default, null):BigInt = new BigInt(BigInt_.fromInt(-1)); //----------------------------------------------------------------------- // Public interface //----------------------------------------------------------------------- - public inline function sign() : Int - { + public inline function sign():Int { return BigInt_.sign1(this); } - public inline function isZero() : Bool - { + public inline function isZero():Bool { return BigInt_.isZero1(this); } - public inline function isNegative() : Bool - { + public inline function isNegative():Bool { return BigInt_.isNegative1(this); } - - public inline function isPositive() : Bool - { + + public inline function isPositive():Bool { return BigInt_.isPositive1(this); } - - public inline function isOdd() : Bool - { + + public inline function isOdd():Bool { return BigInt_.isOdd1(this); } - - public inline function isEven() : Bool - { + + public inline function isEven():Bool { return BigInt_.isEven1(this); } - - public inline function min(other : BigInt ) : BigInt { + + public inline function min(other:BigInt):BigInt { return new BigInt(this.min(other)); } - public inline function max(other : BigInt) : BigInt { + public inline function max(other:BigInt):BigInt { return new BigInt(this.max(other)); } - public inline function toString() : String - { + public inline function toString():String { return BigInt_.toString1(this); } - public inline function toHex() : String - { + public inline function toHex():String { return BigInt_.toHex1(this); } - public inline function toBytes() : Bytes - { + public inline function toBytes():Bytes { return BigInt_.toBytes1(this); } - public inline function toInts(output : Vector) : Int - { + public inline function toInts(output:Vector):Int { return BigInt_.toInts1(this, output); } - public static inline function fromInt(value : Int) : BigInt - { + public static inline function fromInt(value:Int):BigInt { return new BigInt(BigInt_.fromInt(value)); } - public static inline function fromString(value : String) : BigInt - { + public static inline function fromString(value:String):BigInt { return new BigInt(BigInt_.fromString(value)); } - public static inline function fromHex(value : String) : BigInt - { + public static inline function fromHex(value:String):BigInt { return fromHexSigned(value); } - public static inline function fromHexSigned(value : String) : BigInt - { + public static inline function fromHexSigned(value:String):BigInt { return new BigInt(BigInt_.fromHexSigned(value)); } - public static inline function fromHexUnsigned(value : String) : BigInt - { + public static inline function fromHexUnsigned(value:String):BigInt { return new BigInt(BigInt_.fromHexUnsigned(value)); } - public static inline function fromUnsignedInts(value : Vector, length : Int = 0) : BigInt - { + public static inline function fromUnsignedInts(value:Vector, length:Int = 0):BigInt { return new BigInt(BigInt_.fromUnsignedInts(value, length)); } - - public static inline function fromBytes(value : Bytes, offset : Int = 0, length : Int = 0) : BigInt - { + + public static inline function fromBytes(value:Bytes, offset:Int = 0, length:Int = 0):BigInt { return new BigInt(BigInt_.fromBytes(value, offset, length)); } - - public static inline function random(bits : Int32) : BigInt - { + + public static inline function random(bits:Int32):BigInt { return new BigInt(BigInt_.random(bits)); } - - public static function randomInRange(min:BigInt, max:BigInt) : BigInt - { - return new BigInt(BigInt_.randomInRange(min,max)); + + public static function randomInRange(min:BigInt, max:BigInt):BigInt { + return new BigInt(BigInt_.randomInRange(min, max)); } - public static function randomPrime(bits:Int32 , tolerance:UInt) : BigInt - { - return new BigInt(BigInt_.randomPrime(bits,tolerance)); + public static function randomPrime(bits:Int32, tolerance:UInt):BigInt { + return new BigInt(BigInt_.randomPrime(bits, tolerance)); } - - public static function divMod(dividend:BigInt, divisor:BigInt):{quotient:BigInt, remainder:BigInt} - { - var result:{quotient:BigInt_, remainder:BigInt_} = BigInt_.divMod(dividend,divisor); - return {quotient:(new BigInt(result.quotient)), remainder:(new BigInt(result.remainder)) }; + + public static function divMod(dividend:BigInt, divisor:BigInt):{quotient:BigInt, remainder:BigInt} { + var result:{quotient:BigInt_, remainder:BigInt_} = BigInt_.divMod(dividend, divisor); + return {quotient: (new BigInt(result.quotient)), remainder: (new BigInt(result.remainder))}; } - public inline function getBit(index : Int) : Int - { + public inline function getBit(index:Int):Int { return BigIntArithmetic.getBit(this, index); } - - public function abs() : BigInt - { + + public function abs():BigInt { return new BigInt(this.abs()); } - - public function modInverse(modulus:BigInt_) : BigInt - { + + public function modInverse(modulus:BigInt_):BigInt { return new BigInt(this.modInverse(modulus)); } - + // Finds the greatest common denominator of this and b - public function gcd(b:BigInt) : BigInt - { + public function gcd(b:BigInt):BigInt { return new BigInt(this.gcd(b)); } - - public function lcm( b : BigInt) : BigInt - { + + public function lcm(b:BigInt):BigInt { return new BigInt(this.lcm(b)); } - - public function pow(exponent:UInt) : BigInt - { + + public function pow(exponent:UInt):BigInt { return new BigInt(this.pow(exponent)); } - public function modPow(exponent:BigInt, modulus:BigInt) : BigInt - { - return new BigInt(this.modPow(exponent,modulus)); + public function modPow(exponent:BigInt, modulus:BigInt):BigInt { + return new BigInt(this.modPow(exponent, modulus)); } - - public function square():BigInt - { + + public function square():BigInt { return new BigInt(this.square()); } - public function isProbablePrime(tolerance:UInt) : Bool - { + public function isProbablePrime(tolerance:UInt):Bool { return this.isProbablePrime(tolerance); } - - public function nextProbablePrime() : BigInt - { + + public function nextProbablePrime():BigInt { return new BigInt(this.nextProbablePrime()); } - public function getLowestSetBit():Int - { + public function getLowestSetBit():Int { return this.getLowestSetBit(); } public function bitLength():Int { return this.bitLength(); } - - public function bitCount():Int - { + + public function bitCount():Int { return this.bitCount(); } - - public function testBit(n:Int):Bool - { + + public function testBit(n:Int):Bool { return this.testBit(n); } - - public function setBit(n:Int):BigInt - { + + public function setBit(n:Int):BigInt { return new BigInt(this.setBit(n)); } - public function clearBit(n:Int):BigInt - { + public function clearBit(n:Int):BigInt { return new BigInt(this.clearBit(n)); } - public function flipBit(n:Int):BigInt - { + public function flipBit(n:Int):BigInt { return new BigInt(this.flipBit(n)); } - - public static function getPowerOfTwo(exponent:Int):BigInt - { + + public static function getPowerOfTwo(exponent:Int):BigInt { return new BigInt(BigInt_.getPowerOfTwo(exponent)); } - - public function hashCode():Int - { + + public function hashCode():Int { return this.hashCode(); } //----------------------------------------------------------------------- // Operators //----------------------------------------------------------------------- - // The declaration order of the operations is significant in Haxe. // Recommended order is: // * BigInt Int // * BigInt BigInt // * BigInt MutableBigInt - // Unary negation - @:op(-A) @:noCompletion public static inline function negate_(a : BigInt) : BigInt - { + @:op(-A) @:noCompletion public static inline function negate_(a:BigInt):BigInt { return new BigInt(BigInt_.negate1(a)); } // Binary equality - @:op(A == B) @:noCompletion public static inline function eqInt_(a : BigInt, b : Int) : Bool - { + @:op(A == B) @:noCompletion public static inline function eqInt_(a:BigInt, b:Int):Bool { return BigInt_.equals2Int(a, b); } - @:op(A == B) @:noCompletion public static inline function eq_(a : BigInt, b : BigInt) : Bool - { + + @:op(A == B) @:noCompletion public static inline function eq_(a:BigInt, b:BigInt):Bool { return BigInt_.equals2(a, b); } - @:op(A == B) @:noCompletion public static inline function eqMutable_(a : BigInt, b : MutableBigInt) : Bool - { + + @:op(A == B) @:noCompletion public static inline function eqMutable_(a:BigInt, b:MutableBigInt):Bool { return BigInt_.equals2(a, b); } // Binary inequality - @:op(A != B) @:noCompletion public static inline function ineqInt_(a : BigInt, b : Int) : Bool - { + @:op(A != B) @:noCompletion public static inline function ineqInt_(a:BigInt, b:Int):Bool { return !BigInt_.equals2Int(a, b); } - @:op(A != B) @:noCompletion public static inline function ineq_(a : BigInt, b : BigInt) : Bool - { + + @:op(A != B) @:noCompletion public static inline function ineq_(a:BigInt, b:BigInt):Bool { return !BigInt_.equals2(a, b); } - @:op(A != B) @:noCompletion public static inline function ineqMutable_(a : BigInt, b : MutableBigInt) : Bool - { + + @:op(A != B) @:noCompletion public static inline function ineqMutable_(a:BigInt, b:MutableBigInt):Bool { return !BigInt_.equals2(a, b); } // Binary less than - @:op(A < B) @:noCompletion public static inline function ltInt_(a : BigInt, b : Int) : Bool - { + @:op(A < B) @:noCompletion public static inline function ltInt_(a:BigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) < 0; } - @:op(A < B) @:noCompletion public static inline function lt_(a : BigInt, b : BigInt) : Bool - { + + @:op(A < B) @:noCompletion public static inline function lt_(a:BigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) < 0; } - @:op(A < B) @:noCompletion public static inline function ltMutable_(a : BigInt, b : MutableBigInt) : Bool - { + + @:op(A < B) @:noCompletion public static inline function ltMutable_(a:BigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) < 0; } // Binary less than or equal - @:op(A <= B) @:noCompletion public static inline function lteInt_(a : BigInt, b : Int) : Bool - { + @:op(A <= B) @:noCompletion public static inline function lteInt_(a:BigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) <= 0; } - @:op(A <= B) @:noCompletion public static inline function lte_(a : BigInt, b : BigInt) : Bool - { + + @:op(A <= B) @:noCompletion public static inline function lte_(a:BigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) <= 0; } - @:op(A <= B) @:noCompletion public static inline function lteMutable_(a : BigInt, b : MutableBigInt) : Bool - { + + @:op(A <= B) @:noCompletion public static inline function lteMutable_(a:BigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) <= 0; } // Binary greater than - @:op(A > B) @:noCompletion public static inline function gtInt_(a : BigInt, b : Int) : Bool - { + @:op(A > B) @:noCompletion public static inline function gtInt_(a:BigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) > 0; } - @:op(A > B) @:noCompletion public static inline function gt_(a : BigInt, b : BigInt) : Bool - { + + @:op(A > B) @:noCompletion public static inline function gt_(a:BigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) > 0; } - @:op(A > B) @:noCompletion public static inline function gtMutable_(a : BigInt, b : MutableBigInt) : Bool - { + + @:op(A > B) @:noCompletion public static inline function gtMutable_(a:BigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) > 0; } // Binary greater than or equal - @:op(A >= B) @:noCompletion public static inline function gteInt_(a : BigInt, b : Int) : Bool - { + @:op(A >= B) @:noCompletion public static inline function gteInt_(a:BigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) >= 0; } - @:op(A >= B) @:noCompletion public static inline function gte_(a : BigInt, b : BigInt) : Bool - { + + @:op(A >= B) @:noCompletion public static inline function gte_(a:BigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) >= 0; } - @:op(A >= B) @:noCompletion public static inline function gteMutable_(a : BigInt, b : MutableBigInt) : Bool - { + + @:op(A >= B) @:noCompletion public static inline function gteMutable_(a:BigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) >= 0; } - + // String conversions - @:op(A + B) @:noCompletion public static inline function toStr_left(a : String, b : BigInt) : String - { - return a+b.toString(); + @:op(A + B) @:noCompletion public static inline function toStr_left(a:String, b:BigInt):String { + return a + b.toString(); } - @:op(A + B) @:noCompletion public static inline function toStr_right(a : BigInt, b : String) : String - { - return a.toString()+b; + @:op(A + B) @:noCompletion public static inline function toStr_right(a:BigInt, b:String):String { + return a.toString() + b; } // Binary addition - @:op(A + B) @:noCompletion public static inline function addInt_(a : BigInt, b : Int) : BigInt - { + @:op(A + B) @:noCompletion public static inline function addInt_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.addInt2(a, b)); } - @:op(A + B) @:noCompletion public static inline function add_(a : BigInt, b : BigInt) : BigInt - { + + @:op(A + B) @:noCompletion public static inline function add_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.add2(a, b)); } - @:op(A + B) @:noCompletion public static inline function addMutable_(a : BigInt, b : MutableBigInt) : BigInt - { + + @:op(A + B) @:noCompletion public static inline function addMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.add2(a, b)); } // Binary subtraction - @:op(A - B) @:noCompletion public static inline function subInt_(a : BigInt, b : Int) : BigInt - { + @:op(A - B) @:noCompletion public static inline function subInt_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.subInt2(a, b)); } - @:op(A - B) @:noCompletion public static inline function sub_(a : BigInt, b : BigInt) : BigInt - { + + @:op(A - B) @:noCompletion public static inline function sub_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.sub2(a, b)); } - @:op(A - B) @:noCompletion public static inline function subMutable_(a : BigInt, b : MutableBigInt) : BigInt - { + + @:op(A - B) @:noCompletion public static inline function subMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.sub2(a, b)); } // Binary multiplication - @:op(A * B) @:noCompletion public static inline function mulInt_(a : BigInt, b : Int) : BigInt - { + @:op(A * B) @:noCompletion public static inline function mulInt_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.multiplyInt2(a, b)); } - @:op(A * B) @:noCompletion public static inline function mul_(a : BigInt, b : BigInt) : BigInt - { + + @:op(A * B) @:noCompletion public static inline function mul_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.multiply2(a, b)); } - @:op(A * B) @:noCompletion public static inline function mulMutable_(a : BigInt, b : MutableBigInt) : BigInt - { + + @:op(A * B) @:noCompletion public static inline function mulMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.multiply2(a, b)); } // Binary division - @:op(A / B) @:noCompletion public static inline function divInt_(a : BigInt, b : Int) : BigInt - { + @:op(A / B) @:noCompletion public static inline function divInt_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.divideInt2(a, b)); } - @:op(A / B) @:noCompletion public static inline function div_(a : BigInt, b : BigInt) : BigInt - { + + @:op(A / B) @:noCompletion public static inline function div_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.divide2(a, b)); } - @:op(A / B) @:noCompletion public static inline function divMutable_(a : BigInt, b : MutableBigInt) : BigInt - { + + @:op(A / B) @:noCompletion public static inline function divMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.divide2(a, b)); } // Binary modulus - @:op(A % B) @:noCompletion public static inline function modInt_(a : BigInt, b : Int) : Int - { + @:op(A % B) @:noCompletion public static inline function modInt_(a:BigInt, b:Int):Int { return BigInt_.modulusInt2(a, b); } - @:op(A % B) @:noCompletion public static inline function mod_(a : BigInt, b : BigInt) : BigInt - { + + @:op(A % B) @:noCompletion public static inline function mod_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.modulus2(a, b)); } - @:op(A % B) @:noCompletion public static inline function modMutable_(a : BigInt, b : MutableBigInt) : BigInt - { + + @:op(A % B) @:noCompletion public static inline function modMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.modulus2(a, b)); } - + // Binary OR - @:op(A | B) @:noCompletion public static inline function orInt_(a : BigInt, b : Int) : BigInt - { + @:op(A | B) @:noCompletion public static inline function orInt_(a:BigInt, b:Int):BigInt { return or_(a, b); } - @:op(A | B) @:noCompletion public static inline function or_(a : BigInt, b : BigInt) : BigInt - { + @:op(A | B) @:noCompletion public static inline function or_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigIntArithmetic.bitwiseOr(a, b)); } - - @:op(A ^ B) @:noCompletion public static inline function xorInt_(a:BigInt, b:Int):BigInt - { + + @:op(A ^ B) @:noCompletion public static inline function xorInt_(a:BigInt, b:Int):BigInt { return xor_(a, b); } - @:op(A ^ B) @:noCompletion public static inline function xor_(a:BigInt, b:BigInt):BigInt - { + @:op(A ^ B) @:noCompletion public static inline function xor_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigIntArithmetic.bitwiseXor(a, b)); } - - @:op(~A) @:noCompletion public static inline function not_(a:BigInt):BigInt - { + + @:op(~A) @:noCompletion public static inline function not_(a:BigInt):BigInt { return new BigInt(BigIntArithmetic.bitwiseNot(a)); } // Binary AND - @:op(A & B) @:noCompletion public static inline function andInt_(a : BigInt, b : Int) : Int - { + @:op(A & B) @:noCompletion public static inline function andInt_(a:BigInt, b:Int):Int { return BigIntArithmetic.bitwiseAndInt(a, b); } - - @:op(A & B) @:noCompletion public static inline function and_(a : BigInt, b : BigInt) : BigInt - { + + @:op(A & B) @:noCompletion public static inline function and_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigIntArithmetic.bitwiseAnd(a, b)); } // Binary shift left - @:op(A << B) @:noCompletion public static inline function asl_(a : BigInt, b : Int) : BigInt - { + @:op(A << B) @:noCompletion public static inline function asl_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.arithmeticShiftLeft2(a, b)); } // Binary shift right - @:op(A >> B) @:noCompletion public static inline function asr_(a : BigInt, b : Int) : BigInt - { + @:op(A >> B) @:noCompletion public static inline function asr_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.arithmeticShiftRight2(a, b)); } @@ -485,23 +419,19 @@ abstract BigInt(BigInt_) // Automatic conversions //----------------------------------------------------------------------- - @:from @:noCompletion public static inline function fromInt_(a : Int) : BigInt - { + @:from @:noCompletion public static inline function fromInt_(a:Int):BigInt { return new BigInt(BigInt_.fromInt(a)); } - - @:from @:noCompletion public static inline function fromString_(a : String) : BigInt - { + + @:from @:noCompletion public static inline function fromString_(a:String):BigInt { return new BigInt(BigInt_.fromString(a)); } - @:to @:noCompletion public inline function toBigInt_() : BigInt_ - { + @:to @:noCompletion public inline function toBigInt_():BigInt_ { return this; } - @:to @:noCompletion public inline function toMutableBigInt() : MutableBigInt - { + @:to @:noCompletion public inline function toMutableBigInt():MutableBigInt { return new MutableBigInt(MutableBigInt_.fromBigInt(this)); } @@ -509,15 +439,12 @@ abstract BigInt(BigInt_) // Private implementation //----------------------------------------------------------------------- - @:noCompletion private inline function new(a : BigInt_) - { + @:noCompletion private inline function new(a:BigInt_) { this = a; } - + //----------------------------------------------------------------------- // Private constants //----------------------------------------------------------------------- - - private static var SMALL_PRIMES_PRODUCT: BigInt = BigInt.fromString("1451887755777639901511587432083070202422614380984889313550570919659315177065956574359078912654149167643992684236991305777574330831666511589145701059710742276692757882915756220901998212975756543223550490431013061082131040808010565293748926901442915057819663730454818359472391642885328171302299245556663073719855"); - + private static var SMALL_PRIMES_PRODUCT:BigInt = BigInt.fromString("1451887755777639901511587432083070202422614380984889313550570919659315177065956574359078912654149167643992684236991305777574330831666511589145701059710742276692757882915756220901998212975756543223550490431013061082131040808010565293748926901442915057819663730454818359472391642885328171302299245556663073719855"); } diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 655e4f26999..fa8785e7ce8 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package haxe.math.bigint; import haxe.math.bigint.BigIntExceptions; @@ -27,8 +27,7 @@ import haxe.math.bigint.BigIntHelper; import haxe.ds.Vector; /* Original code courtesy Chuck Batson (github.com/cbatson) */ -class BigIntArithmetic -{ +class BigIntArithmetic { /** Compare a big integer with an Int. @@ -36,15 +35,13 @@ class BigIntArithmetic returns 1 if `a > b`; otherwise returns 0 (`a == b`). **/ - public static function compareInt(a : BigInt_, b : Int) : Int - { - if (a.m_count > 1) - { + public static function compareInt(a:BigInt_, b:Int):Int { + if (a.m_count > 1) { return (a.sign() << 1) + 1; } - var x : Int = a.m_data.get(0); - var lt : Int = (x - b) ^ ((x ^ b) & ((x - b) ^ x)); // "Hacker's Delight" p. 23 - var gt : Int = (b - x) ^ ((x ^ b) & ((b - x) ^ b)); + var x:Int = a.m_data.get(0); + var lt:Int = (x - b) ^ ((x ^ b) & ((x - b) ^ x)); // "Hacker's Delight" p. 23 + var gt:Int = (b - x) ^ ((x ^ b) & ((b - x) ^ b)); return (lt >> 31) | (gt >>> 31); } @@ -55,33 +52,26 @@ class BigIntArithmetic returns 1 if `a > b`; otherwise returns 0 (`a == b`). **/ - public static function compare(a : BigInt_, b : BigInt_) : Int - { - if (a != b) - { - var c : Int = (a.sign() & 2) + (b.sign() & 1); - switch (c) - { - case 0: // a and b are positive - if (a.m_count > b.m_count) - { + public static function compare(a:BigInt_, b:BigInt_):Int { + if (a != b) { + var c:Int = (a.sign() & 2) + (b.sign() & 1); + switch (c) { + case 0: // a and b are positive + if (a.m_count > b.m_count) { return 1; } - if (a.m_count < b.m_count) - { + if (a.m_count < b.m_count) { return -1; } - case 1: // a is positive, b is negative + case 1: // a is positive, b is negative return 1; - case 2: // a is negative, b is positive + case 2: // a is negative, b is positive return -1; - case 3: // a and b are negative - if (a.m_count > b.m_count) - { + case 3: // a and b are negative + if (a.m_count > b.m_count) { return -1; } - if (a.m_count < b.m_count) - { + if (a.m_count < b.m_count) { return 1; } } @@ -96,27 +86,22 @@ class BigIntArithmetic Ok for `result` and `operand` to be the same object. **/ - public static function negate(result : MutableBigInt_, operand : BigInt_) : Void - { - var c : Int = 1; - var x : Int32 = 0; - var z : Int = 0; - result.ensureCapacity(operand.m_count + 1, result == operand); // overflow may add a digit - for (i in 0 ... operand.m_count) - { + public static function negate(result:MutableBigInt_, operand:BigInt_):Void { + var c:Int = 1; + var x:Int32 = 0; + var z:Int = 0; + result.ensureCapacity(operand.m_count + 1, result == operand); // overflow may add a digit + for (i in 0...operand.m_count) { x = ~operand.m_data.get(i); z = x + c; result.m_data.set(i, z); - c = (x & ~z) >>> 31; // "Hacker's Delight" p. 38 + c = (x & ~z) >>> 31; // "Hacker's Delight" p. 38 } result.m_count = operand.m_count; // detect overflow; intuitively, this can only occur for inputs of 2 ^ (32 * N - 1). - if ((~x & z) < 0) - { + if ((~x & z) < 0) { result.m_data.set(result.m_count++, 0); - } - else - { + } else { // Handle compacting; intuitively, this can only occur for inputs of -[2 ^ (32 * N - 1)]. // TODO: good way to detect this specific scenario? result.compact(); @@ -129,56 +114,47 @@ class BigIntArithmetic Ok for `result`, `operand1`, and `operand2` to be the same object. **/ - public static function add(result : MutableBigInt_, operand1 : BigInt_, operand2 : BigInt_) : Void - { - var c : Int = 0; - var x : Int32 = 0, y : Int32 = 0, z : Int = 0; - if (operand1.m_count == operand2.m_count) - { + public static function add(result:MutableBigInt_, operand1:BigInt_, operand2:BigInt_):Void { + var c:Int = 0; + var x:Int32 = 0, y:Int32 = 0, z:Int = 0; + if (operand1.m_count == operand2.m_count) { result.ensureCapacity(operand1.m_count + 1, (result == operand1) || (result == operand2)); - for (i in 0 ... operand1.m_count) - { + for (i in 0...operand1.m_count) { x = operand1.m_data.get(i); y = operand2.m_data.get(i); z = x + y + c; result.m_data.set(i, z); - c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 } result.m_count = operand1.m_count; - } - else - { + } else { // longer operand is put into o1 var o1 = (operand1.m_count > operand2.m_count) ? operand1 : operand2; var o2 = (operand1.m_count > operand2.m_count) ? operand2 : operand1; result.ensureCapacity(o1.m_count + 1, (result == operand1) || (result == operand2)); - var s : Int = o2.sign(); - for (i in 0 ... o2.m_count) - { + var s:Int = o2.sign(); + for (i in 0...o2.m_count) { x = o1.m_data.get(i); y = o2.m_data.get(i); z = x + y + c; result.m_data.set(i, z); - c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 } y = s; - for (i in o2.m_count ... o1.m_count) - { + for (i in o2.m_count...o1.m_count) { x = o1.m_data.get(i); z = x + y + c; result.m_data.set(i, z); - c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 } result.m_count = o1.m_count; } - var o : Int = (z ^ x) & (z ^ y); // "Hacker's Delight" p. 29 - if (o < 0) // overflow flag is in sign bit + var o:Int = (z ^ x) & (z ^ y); // "Hacker's Delight" p. 29 + if (o < 0) // overflow flag is in sign bit { result.m_data.set(result.m_count++, ~(z >> 31)); - } - else - { - result.compact(); // TODO: True that this will only ever eliminate at most one digit? Lighter way to detect? + } else { + result.compact(); // TODO: True that this will only ever eliminate at most one digit? Lighter way to detect? } } @@ -188,42 +164,36 @@ class BigIntArithmetic Ok for `result` and `operand1` to be the same object. **/ - public static function addInt(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void - { - var c : Int = 0; - var x : Int32; - var y : Int = operand2; - var z : Int; + public static function addInt(result:MutableBigInt_, operand1:BigInt_, operand2:Int):Void { + var c:Int = 0; + var x:Int32; + var y:Int = operand2; + var z:Int; result.ensureCapacity(operand1.m_count + 1, result == operand1); - if (operand1.m_count > 1) - { + if (operand1.m_count > 1) { x = operand1.m_data.get(0); z = x + y; - c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 result.m_data.set(0, z); y >>= 31; - for (i in 1 ... operand1.m_count - 1) - { + for (i in 1...operand1.m_count - 1) { x = operand1.m_data.get(i); z = x + y + c; result.m_data.set(i, z); - c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 } } x = operand1.m_data.get(operand1.m_count - 1); z = x + y + c; result.m_data.set(operand1.m_count - 1, z); result.m_count = operand1.m_count; - var o : Int = (z ^ x) & (z ^ y); // "Hacker's Delight" p. 29 - if (o < 0) // overflow flag is in sign bit + var o:Int = (z ^ x) & (z ^ y); // "Hacker's Delight" p. 29 + if (o < 0) // overflow flag is in sign bit { result.m_data.set(result.m_count++, x >> 31); - } - else if (result.m_count > 1) - { - if (z == (result.m_data.get(result.m_count - 2) >> 31)) - { + } else if (result.m_count > 1) { + if (z == (result.m_data.get(result.m_count - 2) >> 31)) { --result.m_count; } } @@ -235,77 +205,64 @@ class BigIntArithmetic Ok for `result`, `operand1`, and `operand2` to be the same object. **/ - public static function subtract(result : MutableBigInt_, operand1 : BigInt_, operand2 : BigInt_) : Void - { - var c : Int32 = 0; - var x : Int = 0, y : Int = 0, z : Int = 0; - if (operand1.m_count == operand2.m_count) - { + public static function subtract(result:MutableBigInt_, operand1:BigInt_, operand2:BigInt_):Void { + var c:Int32 = 0; + var x:Int = 0, y:Int = 0, z:Int = 0; + if (operand1.m_count == operand2.m_count) { result.ensureCapacity(operand1.m_count + 1, (result == operand1) || (result == operand2)); - for (i in 0 ... operand1.m_count) - { + for (i in 0...operand1.m_count) { x = operand1.m_data.get(i); y = operand2.m_data.get(i); z = x - y - c; result.m_data.set(i, z); - c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 } result.m_count = operand1.m_count; - } - else if (operand1.m_count > operand2.m_count) - { + } else if (operand1.m_count > operand2.m_count) { // operand1 is longer result.ensureCapacity(operand1.m_count + 1, (result == operand1) || (result == operand2)); - var s : Int = operand2.sign(); - for (i in 0 ... operand2.m_count) - { + var s:Int = operand2.sign(); + for (i in 0...operand2.m_count) { x = operand1.m_data.get(i); y = operand2.m_data.get(i); z = x - y - c; result.m_data.set(i, z); - c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 } y = s; - for (i in operand2.m_count ... operand1.m_count) - { + for (i in operand2.m_count...operand1.m_count) { x = operand1.m_data.get(i); z = x - y - c; result.m_data.set(i, z); - c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 } result.m_count = operand1.m_count; - } - else - { + } else { // operand2 is longer result.ensureCapacity(operand2.m_count + 1, (result == operand1) || (result == operand2)); - var s : Int = operand1.sign(); - for (i in 0 ... operand1.m_count) - { + var s:Int = operand1.sign(); + for (i in 0...operand1.m_count) { x = operand1.m_data.get(i); y = operand2.m_data.get(i); z = x - y - c; result.m_data.set(i, z); - c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 } x = s; - for (i in operand1.m_count ... operand2.m_count) - { + for (i in operand1.m_count...operand2.m_count) { y = operand2.m_data.get(i); z = x - y - c; result.m_data.set(i, z); - c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 } result.m_count = operand2.m_count; } - var o : Int = (x ^ y) & (z ^ x); // "Hacker's Delight" p. 29 - if (o < 0) // overflow flag is in sign bit + var o:Int = (x ^ y) & (z ^ x); // "Hacker's Delight" p. 29 + if (o < 0) // overflow flag is in sign bit { result.m_data.set(result.m_count++, ~(z >> 31)); - } - else - { - result.compact(); // TODO: True that this will only ever eliminate at most one digit? Lighter way to detect? + } else { + result.compact(); // TODO: True that this will only ever eliminate at most one digit? Lighter way to detect? } } @@ -315,42 +272,36 @@ class BigIntArithmetic Ok for `result` and `operand1` to be the same object. **/ - public static function subtractInt(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void - { - var c : Int = 0; - var x : Int; - var y : Int = operand2; - var z : Int; + public static function subtractInt(result:MutableBigInt_, operand1:BigInt_, operand2:Int):Void { + var c:Int = 0; + var x:Int; + var y:Int = operand2; + var z:Int; result.ensureCapacity(operand1.m_count + 1, result == operand1); - if (operand1.m_count > 1) - { + if (operand1.m_count > 1) { x = operand1.m_data.get(0); z = x - y; - c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 result.m_data.set(0, z); y >>= 31; - for (i in 1 ... operand1.m_count - 1) - { + for (i in 1...operand1.m_count - 1) { x = operand1.m_data.get(i); z = x - y - c; result.m_data.set(i, z); - c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 } } x = operand1.m_data.get(operand1.m_count - 1); z = x - y - c; result.m_data.set(operand1.m_count - 1, z); result.m_count = operand1.m_count; - var o : Int = (x ^ y) & (z ^ x); // "Hacker's Delight" p. 29 - if (o < 0) // overflow flag is in sign bit + var o:Int = (x ^ y) & (z ^ x); // "Hacker's Delight" p. 29 + if (o < 0) // overflow flag is in sign bit { result.m_data.set(result.m_count++, x >> 31); - } - else if (result.m_count > 1) - { - if (z == (result.m_data.get(result.m_count - 2) >> 31)) - { + } else if (result.m_count > 1) { + if (z == (result.m_data.get(result.m_count - 2) >> 31)) { --result.m_count; } } @@ -364,8 +315,7 @@ class BigIntArithmetic or `operand2`; however, `operand1` and `operand2` may be the same object. **/ - public static function multiplyInt(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void - { + public static function multiplyInt(result:MutableBigInt_, operand1:BigInt_, operand2:Int):Void { // TODO: Optimize. multiply(result, operand1, BigInt_.fromInt(operand2)); } @@ -378,45 +328,39 @@ class BigIntArithmetic or `operand2`; however, `operand1` and `operand2` may be the same object. **/ - public static function multiply(result : MutableBigInt_, operand1 : BigInt_, operand2 : BigInt_) : Void - { + public static function multiply(result:MutableBigInt_, operand1:BigInt_, operand2:BigInt_):Void { // Implements Figure 8-1 (p. 172) from "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. - if ((operand1 == result) || (operand2 == result)) - { + if ((operand1 == result) || (operand2 == result)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if (operand1.isZero() || operand2.isZero()) - { + if (operand1.isZero() || operand2.isZero()) { result.setFromInt(0); return; } - + if ((operand1.bitLength() >= 2500) && (operand2.bitLength() >= 2500)) { - multiplyKaratsuba(result, operand1,operand2); + multiplyKaratsuba(result, operand1, operand2); return; } - var resultSize : Int = operand1.m_count + operand2.m_count; - result.ensureCapacity(resultSize, false); // always overwrite result - for (i in 0 ... resultSize) - { + var resultSize:Int = operand1.m_count + operand2.m_count; + result.ensureCapacity(resultSize, false); // always overwrite result + for (i in 0...resultSize) { result.m_data.set(i, 0); } result.m_count = resultSize; - var b : Int, k : Int, t : Int; - var u : Int, v : Int, w : Int; - var m : Int = operand1.m_count << 1; - var n : Int = operand2.m_count << 1; + var b:Int, k:Int, t:Int; + var u:Int, v:Int, w:Int; + var m:Int = operand1.m_count << 1; + var n:Int = operand2.m_count << 1; - for (j in 0 ... n) - { + for (j in 0...n) { v = operand2.getShort(j); k = 0; - for (i in 0 ... m) - { + for (i in 0...m) { u = operand1.getShort(i); w = result.getShort(i + j); t = u * v + w + k; @@ -430,11 +374,9 @@ class BigIntArithmetic // subtracting v * 2 ^ (16m) if u < 0, and // subtracting u * 2 ^ (16n) if v < 0. // TODO: Do these as 32-bit operations. - if (operand1.isNegative()) - { + if (operand1.isNegative()) { b = 0; - for (j in 0 ... n) - { + for (j in 0...n) { w = result.getShort(j + m); v = operand2.getShort(j); t = w - v - b; @@ -442,11 +384,9 @@ class BigIntArithmetic b = t >>> 31; } } - if (operand2.isNegative()) - { + if (operand2.isNegative()) { b = 0; - for (i in 0 ... m) - { + for (i in 0...m) { w = result.getShort(i + n); u = operand1.getShort(i); t = w - u - b; @@ -467,8 +407,7 @@ class BigIntArithmetic `work`, if supplied, must not refer to any of the inputs. **/ - public static function divideInt(dividend : BigInt_, divisor : Int, quotientOut : MutableBigInt_, work : MutableBigInt_ = null) : Int - { + public static function divideInt(dividend:BigInt_, divisor:Int, quotientOut:MutableBigInt_, work:MutableBigInt_ = null):Int { // TODO: Consider optimizing this case. var remainder = new MutableBigInt_(); var divisorBi = BigInt_.fromInt(divisor); @@ -491,28 +430,25 @@ class BigIntArithmetic `work`, if supplied, must not refer to any of the inputs. **/ - public static function divide(dividend : BigInt_, divisor : BigInt_, quotientOut : MutableBigInt_, remainderOut : MutableBigInt_, work : MutableBigInt_ = null) : Void - { - var c : Int = (dividend.sign() & 2) + (divisor.sign() & 1); - switch (c) - { - case 0: // dividend positive, divisor positive + public static function divide(dividend:BigInt_, divisor:BigInt_, quotientOut:MutableBigInt_, remainderOut:MutableBigInt_, + work:MutableBigInt_ = null):Void { + var c:Int = (dividend.sign() & 2) + (divisor.sign() & 1); + switch (c) { + case 0: // dividend positive, divisor positive multiwordUnsignedDivide(dividend, divisor, quotientOut, remainderOut, work); - case 1: // dividend positive, divisor negative + case 1: // dividend positive, divisor negative negate(quotientOut, divisor); multiwordUnsignedDivide(dividend, quotientOut, quotientOut, remainderOut, work); negate(quotientOut, quotientOut); - case 2: // dividend negative, divisor positive + case 2: // dividend negative, divisor positive negate(quotientOut, dividend); multiwordUnsignedDivide(quotientOut, divisor, quotientOut, remainderOut, work); negate(quotientOut, quotientOut); - if (remainderOut != null) - { + if (remainderOut != null) { negate(remainderOut, remainderOut); } - case 3: // dividend negative, divisor negative - if (remainderOut == null) - { + case 3: // dividend negative, divisor negative + if (remainderOut == null) { // TODO: use work buffer rather than creating an object here remainderOut = new MutableBigInt_(); } @@ -535,60 +471,49 @@ class BigIntArithmetic object; but either may refer to the inputs. `work`, if supplied, must not refer to any of the inputs. - */ - private static function multiwordUnsignedDivide(dividend : BigInt_, divisor : BigInt_, quotientOut : MutableBigInt_, remainderOut : MutableBigInt_, work : MutableBigInt_ = null) : Void - { - if ((quotientOut == null) || (dividend == null) || (divisor == null)) - { + */ + private static function multiwordUnsignedDivide(dividend:BigInt_, divisor:BigInt_, quotientOut:MutableBigInt_, remainderOut:MutableBigInt_, + work:MutableBigInt_ = null):Void { + if ((quotientOut == null) || (dividend == null) || (divisor == null)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if ((work == dividend) || (work == divisor) || (work == quotientOut)) - { + if ((work == dividend) || (work == divisor) || (work == quotientOut)) { throw BigIntExceptions.INVALID_ARGUMENT; } - var dividendInts : Int = dividend.getUnsignedDigitCount(); - var divisorInts : Int = divisor.getUnsignedDigitCount(); + var dividendInts:Int = dividend.getUnsignedDigitCount(); + var divisorInts:Int = divisor.getUnsignedDigitCount(); - var quotientLength : Int = MultiwordArithmetic.getDivisionQuotientLengthUnsigned(dividendInts, divisorInts); + var quotientLength:Int = MultiwordArithmetic.getDivisionQuotientLengthUnsigned(dividendInts, divisorInts); - if (remainderOut != null) - { - if (work == remainderOut) - { + if (remainderOut != null) { + if (work == remainderOut) { throw BigIntExceptions.INVALID_ARGUMENT; } remainderOut.ensureCapacity(divisor.m_count, (remainderOut == dividend) || (remainderOut == divisor)); } - quotientOut.ensureCapacity(quotientLength + 1, (quotientOut == dividend) || (quotientOut == divisor)); // +1 in case we need leading 0 digit + quotientOut.ensureCapacity(quotientLength + 1, (quotientOut == dividend) || (quotientOut == divisor)); // +1 in case we need leading 0 digit - if (work == null) - { + if (work == null) { work = new MutableBigInt_(); } work.ensureCapacity(dividendInts + divisorInts + 1, false); - MultiwordArithmetic.divideUnsigned(dividend.m_data, dividendInts, divisor.m_data, divisorInts, quotientOut.m_data, (remainderOut != null) ? remainderOut.m_data : null, work.m_data); + MultiwordArithmetic.divideUnsigned(dividend.m_data, dividendInts, divisor.m_data, divisorInts, quotientOut.m_data, + (remainderOut != null) ? remainderOut.m_data : null, work.m_data); quotientOut.m_count = quotientLength; - if (quotientOut.isNegative()) - { + if (quotientOut.isNegative()) { quotientOut.m_data.set(quotientOut.m_count++, 0); - } - else - { + } else { quotientOut.compact(); } - if (remainderOut != null) - { + if (remainderOut != null) { remainderOut.m_count = divisorInts; - if (remainderOut.isNegative()) - { + if (remainderOut.isNegative()) { remainderOut.m_data.set(remainderOut.m_count++, 0); - } - else - { + } else { remainderOut.compact(); } } @@ -600,39 +525,31 @@ class BigIntArithmetic Ok for `result` and `operand1` to be the same object. **/ - public static function arithmeticShiftLeft(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void - { - if (operand2 < 0) - { + public static function arithmeticShiftLeft(result:MutableBigInt_, operand1:BigInt_, operand2:Int):Void { + if (operand2 < 0) { throw BigIntExceptions.INVALID_ARGUMENT; } - if ((operand2 == 0) || operand1.isZero()) - { + if ((operand2 == 0) || operand1.isZero()) { result.copyFrom(operand1); return; } result.ensureCapacity(operand1.m_count + ((operand2 + 31) >> 5), result == operand1); - var whole : Int = operand2 >> 5; // whole digits portion - var n : Int = operand2 & 0x1f; // sub digit poortion - if (n > 0) - { + var whole:Int = operand2 >> 5; // whole digits portion + var n:Int = operand2 & 0x1f; // sub digit poortion + if (n > 0) { asl32(result.m_data, whole, operand1.m_data, operand1.m_count, n); result.m_count = operand1.m_count + whole + 1; result.compact(); - } - else if (whole > 0) - { - for (i in 0 ... operand1.m_count) - { + } else if (whole > 0) { + for (i in 0...operand1.m_count) { result.m_data.set(operand1.m_count - i - 1 + whole, operand1.m_data.get(operand1.m_count - i - 1)); } result.m_count = operand1.m_count + whole; } - for (i in 0 ... whole) - { + for (i in 0...whole) { result.m_data.set(i, 0); } } @@ -643,38 +560,29 @@ class BigIntArithmetic Ok for `result` and `operand1` to be the same object. **/ - public static function arithmeticShiftRight(result : MutableBigInt_, operand1 : BigInt_, operand2 : Int) : Void - { - if (operand2 < 0) - { + public static function arithmeticShiftRight(result:MutableBigInt_, operand1:BigInt_, operand2:Int):Void { + if (operand2 < 0) { throw BigIntExceptions.INVALID_ARGUMENT; } - if ((operand2 == 0) || operand1.isZero()) - { + if ((operand2 == 0) || operand1.isZero()) { result.copyFrom(operand1); return; } result.ensureCapacity(operand1.m_count, result == operand1); - var whole : Int = operand2 >> 5; // whole digits portion - var n : Int = operand2 & 0x1f; // sub digit poortion - if (whole >= operand1.m_count) - { + var whole:Int = operand2 >> 5; // whole digits portion + var n:Int = operand2 & 0x1f; // sub digit poortion + if (whole >= operand1.m_count) { result.m_data.set(0, operand1.sign()); result.m_count = 1; - } - else if (n > 0) - { + } else if (n > 0) { MultiwordArithmetic._asr32(result.m_data, operand1.m_data, operand1.m_count, whole, n); result.m_count = operand1.m_count - whole; result.compact(); - } - else if (whole > 0) - { - for (i in 0 ... operand1.m_count - whole) - { + } else if (whole > 0) { + for (i in 0...operand1.m_count - whole) { result.m_data.set(i, operand1.m_data.get(i + whole)); } result.m_count = operand1.m_count - whole; @@ -684,35 +592,32 @@ class BigIntArithmetic /** Returns the value, 0 or 1, of the bit at 2^`index` place. **/ - public static inline function getBit(value : BigInt_, index : Int) : Int - { + public static inline function getBit(value:BigInt_, index:Int):Int { return MultiwordArithmetic.getBitSigned(value.m_data, value.m_count, index); } /** Returns the bitwise AND of `operand1` with `operand2`. **/ - public static inline function bitwiseAndInt(operand1 : BigInt_, operand2 : Int) : Int - { + public static inline function bitwiseAndInt(operand1:BigInt_, operand2:Int):Int { return operand1.m_data.get(0) & operand2; } - - public static inline function bitwiseAnd(operand1:BigInt_, operand2:BigInt_):BigInt_ - { + + public static inline function bitwiseAnd(operand1:BigInt_, operand2:BigInt_):BigInt_ { var result:MutableBigInt_ = new MutableBigInt_(); - if ( (operand1.m_count > operand2.m_count)) { - result.m_count = (operand2.sign() == 0)?operand2.m_count : operand1.m_count; + if ((operand1.m_count > operand2.m_count)) { + result.m_count = (operand2.sign() == 0) ? operand2.m_count : operand1.m_count; } else { - result.m_count = (operand1.sign() == 0)?operand1.m_count : operand2.m_count; + result.m_count = (operand1.sign() == 0) ? operand1.m_count : operand2.m_count; } result.ensureCapacity(result.m_count, false); for (i in 0...result.m_count) { - if ( i > (operand1.m_count-1) ) { + if (i > (operand1.m_count - 1)) { result.m_data.set(i, operand2.m_data.get(i)); - } else if ( i > (operand2.m_count-1) ) { + } else if (i > (operand2.m_count - 1)) { result.m_data.set(i, operand1.m_data.get(i)); } else { - result.m_data.set(i, (operand1.m_data.get(i) & operand2.m_data.get(i))); + result.m_data.set(i, (operand1.m_data.get(i) & operand2.m_data.get(i))); } } result.compact(); @@ -722,28 +627,26 @@ class BigIntArithmetic /** Returns the bitwise OR of `operand1` with `operand2`. **/ - public static inline function bitwiseOr(operand1 : BigInt_, operand2 : BigInt_) : BigInt_ - { + public static inline function bitwiseOr(operand1:BigInt_, operand2:BigInt_):BigInt_ { var result:MutableBigInt_ = new MutableBigInt_(); - result.m_count = (operand1.m_count > operand2.m_count)?operand1.m_count : operand2.m_count; + result.m_count = (operand1.m_count > operand2.m_count) ? operand1.m_count : operand2.m_count; result.ensureCapacity(result.m_count, false); - var operand1Positive:Bool = operand1.sign()==0; - var operand2Positive:Bool = operand2.sign()==0; + var operand1Positive:Bool = operand1.sign() == 0; + var operand2Positive:Bool = operand2.sign() == 0; for (i in 0...result.m_count) { - if ( i > (operand1.m_count-1) ) { - result.m_data.set(i, (operand1Positive?operand2.m_data.get(i):0xffffffff) ); - } else if ( i > (operand2.m_count-1) ) { - result.m_data.set(i, (operand2Positive?operand1.m_data.get(i):0xffffffff)); + if (i > (operand1.m_count - 1)) { + result.m_data.set(i, (operand1Positive ? operand2.m_data.get(i) : 0xffffffff)); + } else if (i > (operand2.m_count - 1)) { + result.m_data.set(i, (operand2Positive ? operand1.m_data.get(i) : 0xffffffff)); } else { - result.m_data.set(i, (operand1.m_data.get(i) | operand2.m_data.get(i))); + result.m_data.set(i, (operand1.m_data.get(i) | operand2.m_data.get(i))); } } result.compact(); return result; } - - public static inline function bitwiseXor(operand1:BigInt_, operand2:BigInt_):BigInt_ - { + + public static inline function bitwiseXor(operand1:BigInt_, operand2:BigInt_):BigInt_ { var result:MutableBigInt_ = new MutableBigInt_(); result.m_count = (operand1.m_count > operand2.m_count) ? operand1.m_count : operand2.m_count; result.ensureCapacity(result.m_count, false); @@ -753,7 +656,7 @@ class BigIntArithmetic if (i > (operand1.m_count - 1)) { result.m_data.set(i, (operand1Positive ? operand2.m_data.get(i) : (operand2.m_data.get(i) ^ 0xffffffff))); } else if (i > (operand2.m_count - 1)) { - result.m_data.set(i, (operand2Positive ? operand1.m_data.get(i) : (operand1.m_data.get(i) ^0xffffffff))); + result.m_data.set(i, (operand2Positive ? operand1.m_data.get(i) : (operand1.m_data.get(i) ^ 0xffffffff))); } else { result.m_data.set(i, (operand1.m_data.get(i) ^ operand2.m_data.get(i))); } @@ -761,9 +664,8 @@ class BigIntArithmetic result.compact(); return result; } - - public static inline function bitwiseNot(operand:BigInt_):BigInt_ - { + + public static inline function bitwiseNot(operand:BigInt_):BigInt_ { var result:MutableBigInt_ = new MutableBigInt_(); result.copyFrom(operand); for (i in 0...result.m_count) { @@ -776,60 +678,55 @@ class BigIntArithmetic /** Returns `floor(log2(input))`. **/ - public static function floorLog2(input : BigInt_) : Int - { + public static function floorLog2(input:BigInt_):Int { return (input.m_count << 5) - BigIntHelper.nlz(input.m_data.get(input.m_count - 1)); } - - public static function multiplyKaratsuba(result:MutableBigInt_, x:BigInt_, y:BigInt_):Void - { - var n = (x.bitLength()>y.bitLength())?x.bitLength():y.bitLength(); - if ( n < 2500 ) { - multiply(result,x,y); + + public static function multiplyKaratsuba(result:MutableBigInt_, x:BigInt_, y:BigInt_):Void { + var n = (x.bitLength() > y.bitLength()) ? x.bitLength() : y.bitLength(); + if (n < 2500) { + multiply(result, x, y); return; } - n = (n+1) >> 1; + n = (n + 1) >> 1; var b = new MutableBigInt_(); - arithmeticShiftRight(b,x,n); + arithmeticShiftRight(b, x, n); var a = new MutableBigInt_(); - arithmeticShiftLeft(a,b,n); - subtract(a,x,a); + arithmeticShiftLeft(a, b, n); + subtract(a, x, a); var d = new MutableBigInt_(); - arithmeticShiftRight(d,y,n); + arithmeticShiftRight(d, y, n); var c = new MutableBigInt_(); - arithmeticShiftLeft(c,d,n); - subtract(c,y,c); + arithmeticShiftLeft(c, d, n); + subtract(c, y, c); var ac = new MutableBigInt_(); - multiplyKaratsuba(ac,a,c); + multiplyKaratsuba(ac, a, c); var bd = new MutableBigInt_(); - multiplyKaratsuba(bd,b,d); + multiplyKaratsuba(bd, b, d); var abcd = new MutableBigInt_(); - add(a,a,b); - add(c,c,d); - multiplyKaratsuba(abcd,a,c); + add(a, a, b); + add(c, c, d); + multiplyKaratsuba(abcd, a, c); var op1 = new MutableBigInt_(); - arithmeticShiftLeft(op1,bd,2*n); - var op2 = new MutableBigInt_(); - subtract(op2,abcd,ac); - subtract(op2,op2,bd); - arithmeticShiftLeft(op2,op2,n); - add(op2,ac,op2); - add(result,op1,op2); + arithmeticShiftLeft(op1, bd, 2 * n); + var op2 = new MutableBigInt_(); + subtract(op2, abcd, ac); + subtract(op2, op2, bd); + arithmeticShiftLeft(op2, op2, n); + add(op2, ac, op2); + add(result, op1, op2); } //----------------------------------------------------------------------- // Private helpers //----------------------------------------------------------------------- - // assumes 0 < shift < 32 // ok if output == input - private static inline function asl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int32) : Void - { - var x : Int = input.get(inputSize - 1) >> 31; // sign extend - var r : Int = 32 - shift; - var y : Int; - while (inputSize > 0) - { + private static inline function asl32(output:Vector, outputOffset:Int, input:Vector, inputSize:Int, shift:Int32):Void { + var x:Int = input.get(inputSize - 1) >> 31; // sign extend + var r:Int = 32 - shift; + var y:Int; + while (inputSize > 0) { y = input[inputSize - 1]; x = (x << shift) | (y >>> r); output.set(inputSize + outputOffset, x); @@ -841,13 +738,11 @@ class BigIntArithmetic // assumes 0 < shift < 32 // ok if output == input - private static inline function lsl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int32) : Void - { - var x : Int = 0; - var r : Int = 32 - shift; - var y : Int; - while (inputSize > 0) - { + private static inline function lsl32(output:Vector, outputOffset:Int, input:Vector, inputSize:Int, shift:Int32):Void { + var x:Int = 0; + var r:Int = 32 - shift; + var y:Int; + while (inputSize > 0) { y = input[inputSize - 1]; x = (x << shift) | (y >>> r); output.set(inputSize + outputOffset, x); @@ -859,22 +754,18 @@ class BigIntArithmetic // assumes 0 < shift < 32 // ok if output == input - private static inline function lsr32(output : Vector, input : Vector, inputSize : Int, inputOffset : Int, shift : Int32) : Void - { - var r : Int = 32 - shift; - var i : Int = 0; - while (i < inputSize - 1) - { + private static inline function lsr32(output:Vector, input:Vector, inputSize:Int, inputOffset:Int, shift:Int32):Void { + var r:Int = 32 - shift; + var i:Int = 0; + while (i < inputSize - 1) { output.set(i, (input.get(inputOffset + i) >>> shift) | (input.get(inputOffset + i + 1) << r)); ++i; } output.set(i, input.get(inputOffset + i) >>> shift); } - private static inline function copy(output : Vector, outputOffset : Int, input : Vector, inputOffset : Int, length : Int) : Void - { - for (i in 0 ... length) - { + private static inline function copy(output:Vector, outputOffset:Int, input:Vector, inputOffset:Int, length:Int):Void { + for (i in 0...length) { output.set(outputOffset + i, input.get(inputOffset + i)); } } diff --git a/std/haxe/math/bigint/BigIntExceptions.hx b/std/haxe/math/bigint/BigIntExceptions.hx index 8c008b31b2a..03b1d9361b7 100644 --- a/std/haxe/math/bigint/BigIntExceptions.hx +++ b/std/haxe/math/bigint/BigIntExceptions.hx @@ -19,17 +19,16 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package haxe.math.bigint; /* Original code courtesy Chuck Batson (github.com/cbatson) */ -class BigIntExceptions -{ - public static inline var INVALID_ARGUMENT = "Invalid argument"; - public static inline var BUFFER_TOO_SMALL = "Buffer too small"; - public static inline var DIVISION_BY_ZERO = "Division by zero"; - public static inline var NEGATIVE_EXPONENT = "Negative exponent"; - public static inline var INVALID_OPERATION = "Invalid operation"; - public static inline var NEGATIVE_MODULUS = "Modulus should be positive"; - public static inline var EVEN_VALUES = "Both values are even"; -} \ No newline at end of file +enum abstract BigIntExceptions(String) { + var INVALID_ARGUMENT = "Invalid argument"; + var BUFFER_TOO_SMALL = "Buffer too small"; + var DIVISION_BY_ZERO = "Division by zero"; + var NEGATIVE_EXPONENT = "Negative exponent"; + var INVALID_OPERATION = "Invalid operation"; + var NEGATIVE_MODULUS = "Modulus should be positive"; + var EVEN_VALUES = "Both values are even"; +} diff --git a/std/haxe/math/bigint/BigIntHelper.hx b/std/haxe/math/bigint/BigIntHelper.hx index 24b3a08111a..531ada6c673 100644 --- a/std/haxe/math/bigint/BigIntHelper.hx +++ b/std/haxe/math/bigint/BigIntHelper.hx @@ -19,21 +19,18 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package haxe.math.bigint; /* Original code courtesy Chuck Batson (github.com/cbatson) */ -class BigIntHelper -{ - +class BigIntHelper { /** "Numbler of leading zeros" - return the number of leading 0-value bits in the binary representation of `x`. **/ - public static function nlz(x : Int) : Int - { + public static function nlz(x:Int):Int { // From "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. Figure 5-15, p. 102. - var y : Int, m : Int, n : Int; + var y:Int, m:Int, n:Int; y = -(x >>> 16); m = (y >> 16) & 16; @@ -60,14 +57,12 @@ class BigIntHelper return n + 2 - m; } - /** "Ceiling power of two" -- round up to the least power of two greater than or equal to input `x`, which is interpreted as unsigned. **/ - public static function clp2(x : Int32) : Int - { + public static function clp2(x:Int32):Int { // From "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. Figure 3-3, p. 62. x = x - 1; x = x | (x >> 1); @@ -84,19 +79,16 @@ class BigIntHelper Returns `true` if `a > b` when both `a` and `b` are interpreted as unsigned integers; `false` otherwise. **/ - public static inline function u32gtu32(a : Int, b : Int) : Bool - { - return (a ^ -2147483648) > (b ^ -2147483648); // unsigned comparison, see "Hacker's Delight" p. 25. + public static inline function u32gtu32(a:Int, b:Int):Bool { + return (a ^ -2147483648) > (b ^ -2147483648); // unsigned comparison, see "Hacker's Delight" p. 25. } - /** Integer division of unsigned 32-bit integer by unsigned 16-bit integer. Result is undefined when `divisor` <= 0 or `divisor` >= 2^16. **/ - public static function u32divu16(dividend : Int32, divisor : Int32) : Int - { + public static function u32divu16(dividend:Int32, divisor:Int32):Int { /* Complicated because Haxe's division is always performed as floating-point. Here we rely on the ability to exactly represent @@ -105,13 +97,14 @@ class BigIntHelper TODO: Implement a method without this restriction. TODO: Consider C++-specific optimization here. - */ + */ + // From "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. Section 9-3, p. 192. - var t : Int = divisor >> 31; - var nprime : Int = dividend & ~t; - var q : Int32 = Std.int((nprime >>> 1) / divisor) << 1; - var r : Int = dividend - q * divisor; - var c : Int = u32geu32(r, divisor) ? 1 : 0; + var t:Int = divisor >> 31; + var nprime:Int = dividend & ~t; + var q:Int32 = Std.int((nprime >>> 1) / divisor) << 1; + var r:Int = dividend - q * divisor; + var c:Int = u32geu32(r, divisor) ? 1 : 0; return q + c; } @@ -120,25 +113,39 @@ class BigIntHelper Returns `true` if `a >= b` when both `a` and `b` are interpreted as unsigned integers; `false` otherwise. **/ - public static inline function u32geu32(a : Int, b : Int) : Bool - { - return (a ^ -2147483648) >= (b ^ -2147483648); // unsigned comparison, see "Hacker's Delight" p. 25. + public static inline function u32geu32(a:Int, b:Int):Bool { + return (a ^ -2147483648) >= (b ^ -2147483648); // unsigned comparison, see "Hacker's Delight" p. 25. } - + /** Number of trailing zeros - return the number of trailing 0-value bits **/ - public static function ntz( x : Int32 ):Int - { - if (x == 0) return 32; + public static function ntz(x:Int32):Int { + if (x == 0) + return 32; var y:Int; var n:Int = 31; - y = x << 16; if (y != 0) { n -= 16; x = y; } - y = x << 8; if (y != 0) { n -= 8; x = y; } - y = x << 4; if (y != 0) { n -= 4; x = y; } - y = x << 2; if (y != 0) { n -= 2; x = y; } - return (n - ((x << 1) >>> 31)); + y = x << 16; + if (y != 0) { + n -= 16; + x = y; + } + y = x << 8; + if (y != 0) { + n -= 8; + x = y; + } + y = x << 4; + if (y != 0) { + n -= 4; + x = y; + } + y = x << 2; + if (y != 0) { + n -= 2; + x = y; + } + return (n - ((x << 1) >>> 31)); } - } diff --git a/std/haxe/math/bigint/BigIntTools.hx b/std/haxe/math/bigint/BigIntTools.hx index 1beb3734d33..4291f975d99 100644 --- a/std/haxe/math/bigint/BigIntTools.hx +++ b/std/haxe/math/bigint/BigIntTools.hx @@ -19,66 +19,50 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package haxe.math.bigint; import haxe.math.bigint.BigIntExceptions; /* Original code courtesy Chuck Batson (github.com/cbatson) */ -class BigIntTools -{ - public static inline function isNull(value : BigInt) : Bool - { - var a : BigInt_ = value; +class BigIntTools { + public static inline function isNull(value:BigInt):Bool { + var a:BigInt_ = value; return a == null; } - public static inline function isBigInt(value : Dynamic) : Bool - { + public static inline function isBigInt(value:Dynamic):Bool { return Std.isOfType(value, BigInt_); } - public static inline function castFrom(value : Dynamic) : BigInt - { + public static inline function castFrom(value:Dynamic):BigInt { return new BigInt(Std.downcast(value, BigInt_)); } - public static function parseValueUnsigned(value : Dynamic) : BigInt - { - var bi : BigInt; - if (Std.isOfType(value, String)) - { + public static function parseValueUnsigned(value:Dynamic):BigInt { + var bi:BigInt; + if (Std.isOfType(value, String)) { bi = parseStringUnsigned(cast(value, String)); - } - else if (isBigInt(value)) - { + } else if (isBigInt(value)) { var t = new MutableBigInt_(); t.copyFrom(castFrom(value)); return new BigInt(t); - } - else if (Std.isOfType(value, Int)) - { + } else if (Std.isOfType(value, Int)) { bi = BigInt.fromInt(cast(value, Int)); - } - else - { + } else { throw BigIntExceptions.INVALID_ARGUMENT; } return bi; } - private static function parseStringUnsigned(value : String) : BigInt - { + private static function parseStringUnsigned(value:String):BigInt { var result = new MutableBigInt_(); - if (StringTools.startsWith(value, "0x")) - { + if (StringTools.startsWith(value, "0x")) { result.setFromHexUnsigned(value.substr(2)); - } - else - { + } else { result.setFromString(value); } - var result2 : MutableBigInt = result; + var result2:MutableBigInt = result; return result2; } } diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 24a6e75cd94..4736f09d8fc 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -28,102 +28,94 @@ import haxe.io.Bytes; /* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(unit) @:allow(haxe.math.bigint) -class BigInt_ -{ +class BigInt_ { //----------------------------------------------------------------------- // Public interface //----------------------------------------------------------------------- - - public inline function abs():BigInt_ - { - if ( this.sign() < 0) { + public inline function abs():BigInt_ { + if (this.sign() < 0) { return BigInt_.negate1(this); - } + } var r = new MutableBigInt_(); r.copyFrom(this); return r; } - - public function gcd( b : BigInt_) : BigInt_ - { + + public function gcd(b:BigInt_):BigInt_ { var m:BigInt_ = this.abs(); b = b.abs(); var t:BigInt_; - while ( !equals2Int(b, 0) ) { - t = m; - m = b; - b = modulus2(t , m); + while (!equals2Int(b, 0)) { + t = m; + m = b; + b = modulus2(t, m); } return m; } - + /** Calculates the least common multiple of the specified big integer numbers. **/ - public function lcm( b : BigInt_) : BigInt_ - { + public function lcm(b:BigInt_):BigInt_ { var m:BigInt_ = this.abs(); var n:BigInt_ = b.abs(); - return BigInt_.divide2(BigInt_.multiply2(m,n),m.gcd(n)); + return BigInt_.divide2(BigInt_.multiply2(m, n), m.gcd(n)); } - + /** Returns `true` if this big integer is equivalent to 0, otherwise returns `false`. **/ - public inline function isZero() : Bool - { + public inline function isZero():Bool { return (m_count == 1) && (m_data.get(0) == 0); } /** Returns `true` if this big integer is less than 0, otherwise returns `false`. **/ - public inline function isNegative() : Bool - { + public inline function isNegative():Bool { return m_data.get(m_count - 1) < 0; } - - public function isPositive():Bool - { + + public function isPositive():Bool { return m_data.get(m_count - 1) >= 0; } - public function isOdd():Bool - { - return ( ( m_data.get(0) & 1) == 1 ); + public function isOdd():Bool { + return ((m_data.get(0) & 1) == 1); } - - public function isEven():Bool - { - return ( (m_data.get(0) & 1) == 0); + + public function isEven():Bool { + return ((m_data.get(0) & 1) == 0); } /** Retrieve the sign value of this big integer; 0 if positive, -1 if negative. **/ - public inline function sign() : Int - { - return ( m_data.get(m_count - 1)>>31 !=0 )?-1:0; - } - - public function getLowestSetBit():Int - { - if ( this.isZero() ) return -1; + public inline function sign():Int { + return (m_data.get(m_count - 1) >> 31 != 0) ? -1 : 0; + } + + public function getLowestSetBit():Int { + if (this.isZero()) + return -1; var result:Int = -1; var i:Int = 0; var b = m_data.get(0); - while ( b == 0 ) { i++; b = m_data.get(i); } - result = (i<<5) +BigIntHelper.ntz(b); + while (b == 0) { + i++; + b = m_data.get(i); + } + result = (i << 5) + BigIntHelper.ntz(b); return result; } public function bitLength():Int { - if ( m_count <=0) return 0; - return ( 32 * m_count - BigIntHelper.nlz(m_data.get(m_count-1)^sign()) ); + if (m_count <= 0) + return 0; + return (32 * m_count - BigIntHelper.nlz(m_data.get(m_count - 1) ^ sign())); } - - public function bitCount():Int - { + + public function bitCount():Int { var totalBits:Int = 0; var x:Int32; for (n in 0...this.m_count) { @@ -137,28 +129,27 @@ class BigInt_ } return totalBits; } - - public function testBit(n:Int):Bool - { - if ( n < 0 ) throw BigIntExceptions.INVALID_ARGUMENT; - var chunk = n >> 5; //divide by 32 - if ( chunk >= m_count) return (sign()<0); - return ( ( m_data.get(chunk) & (1<<(n & 0x1f))) != 0); - } - - public function setBit(n:Int):BigInt_ - { + + public function testBit(n:Int):Bool { + if (n < 0) + throw BigIntExceptions.INVALID_ARGUMENT; + var chunk = n >> 5; // divide by 32 + if (chunk >= m_count) + return (sign() < 0); + return ((m_data.get(chunk) & (1 << (n & 0x1f))) != 0); + } + + public function setBit(n:Int):BigInt_ { return (testBit(n)) ? this : flipBit(n); } - public function clearBit(n:Int):BigInt_ - { + public function clearBit(n:Int):BigInt_ { return (testBit(n)) ? flipBit(n) : this; } - public function flipBit(n:Int):BigInt_ - { - if (n < 0) throw BigIntExceptions.INVALID_ARGUMENT; + public function flipBit(n:Int):BigInt_ { + if (n < 0) + throw BigIntExceptions.INVALID_ARGUMENT; var isNegative:Bool = sign() < 0; var chunk = (n >> 5) + 1; var changeBit:Int = (n & 0x1f); @@ -176,58 +167,58 @@ class BigInt_ r.compact(); return r; } - - public static inline function getPowerOfTwo(exponent:Int):BigInt_ - { + + public static inline function getPowerOfTwo(exponent:Int):BigInt_ { var num = BigInt_.fromInt(1); - var r = arithmeticShiftLeft2(num,exponent); + var r = arithmeticShiftLeft2(num, exponent); return r; } - - public function hashCode():Int - { + + public function hashCode():Int { var hash:Int32 = 0; - for (n in 0 ... this.m_count) - { - hash = 31*hash + this.m_data.get(n); + for (n in 0...this.m_count) { + hash = 31 * hash + this.m_data.get(n); } return hash; } - - public function isProbablePrime(tolerance:UInt):Bool - { - if ( tolerance <= 0 ) return true; + + public function isProbablePrime(tolerance:UInt):Bool { + if (tolerance <= 0) + return true; var b:BigInt_ = this.abs(); - if ( equals2Int(b,1) ) return false; - if ( equals2Int(b,2) ) return true; - if ( b.m_data.get(0) & 1 == 0 ) return false; + if (equals2Int(b, 1)) + return false; + if (equals2Int(b, 2)) + return true; + if (b.m_data.get(0) & 1 == 0) + return false; var rounds:UInt = 0; - if ( b.m_count <= 4) { - rounds = (tolerance>64)?64:tolerance; - } else if ( b.m_count < 8) { + if (b.m_count <= 4) { + rounds = (tolerance > 64) ? 64 : tolerance; + } else if (b.m_count < 8) { rounds = 32; - } else if ( b.m_count < 16) { + } else if (b.m_count < 16) { rounds = 16; - } else if ( b.m_count < 24) { + } else if (b.m_count < 24) { rounds = 8; - } else if ( b.m_count < 32) { + } else if (b.m_count < 32) { rounds = 4; } else { rounds = 2; } - rounds = (tolerance 0) ? this : other; + public function max(other:BigInt_):BigInt_ { + return (BigIntArithmetic.compare(this, other) > 0) ? this : other; } /** Get the value in decimal form. **/ - public inline function toString() : String - { + public inline function toString():String { return MultiwordArithmetic.toDecimalSigned(m_data, m_count); } /** Get the value in hexadecimal form. **/ - public function toHex() : String - { + public function toHex():String { var sb = new StringBuf(); - var i : Int = m_count; - while (--i >= 0) - { + var i:Int = m_count; + while (--i >= 0) { var v = m_data.get(i); - for (j in 0 ... 8) - { - var c : Int = (v >> 28) & 0x0f; + for (j in 0...8) { + var c:Int = (v >> 28) & 0x0f; v <<= 4; c = (c < 10) ? (c + 48) : (c - 10 + 97); sb.addChar(c); @@ -306,16 +287,14 @@ class BigInt_ /** Get the value as bytes, big endian order. **/ - public function toBytes() : Bytes - { + public function toBytes():Bytes { var result = Bytes.alloc(m_count << 2); - for (i in 0 ... m_count) - { - var v : Int = m_data.get(m_count - i - 1); + for (i in 0...m_count) { + var v:Int = m_data.get(m_count - i - 1); result.set((i << 2) + 0, (v >> 24) & 0xff); result.set((i << 2) + 1, (v >> 16) & 0xff); - result.set((i << 2) + 2, (v >> 8) & 0xff); - result.set((i << 2) + 3, (v >> 0) & 0xff); + result.set((i << 2) + 2, (v >> 8) & 0xff); + result.set((i << 2) + 3, (v >> 0) & 0xff); } return result; } @@ -328,13 +307,10 @@ class BigInt_ Returns the number of Ints required to store the value. **/ - public function toInts(output : Vector) : Int - { - if (output != null) - { - var n : Int = (m_count > output.length) ? output.length : m_count; - for (i in 0 ... n) - { + public function toInts(output:Vector):Int { + if (output != null) { + var n:Int = (m_count > output.length) ? output.length : m_count; + for (i in 0...n) { output.set(i, m_data.get(i)); } } @@ -344,11 +320,9 @@ class BigInt_ /** Creates a big integer with value `value`. **/ - public static function fromInt(value : Int) : BigInt_ - { + public static function fromInt(value:Int):BigInt_ { var c = getCachedValue(value); - if (c == null) - { + if (c == null) { c = newFromInt(value); } return c; @@ -357,8 +331,7 @@ class BigInt_ /** Creates a big integer with the value represented by the decimal string `value`. **/ - public static function fromString(value : String) : BigInt_ - { + public static function fromString(value:String):BigInt_ { var bi = new MutableBigInt_(); bi.setFromString(value); return bi; @@ -368,8 +341,7 @@ class BigInt_ Creates a big integer with the signed value represented by the hexadecimal string `value`. **/ - public static function fromHexSigned(value : String) : BigInt_ - { + public static function fromHexSigned(value:String):BigInt_ { var bi = new MutableBigInt_(); bi.setFromHexSigned(value); return bi; @@ -379,18 +351,16 @@ class BigInt_ Creates a big integer with the unsigned value represented by the hexadecimal string `value`. **/ - public static function fromHexUnsigned(value : String) : BigInt_ - { + public static function fromHexUnsigned(value:String):BigInt_ { var bi = new MutableBigInt_(); bi.setFromHexUnsigned(value); return bi; } - + /** Creates a big integer with the signed value represented by bytes **/ - public static function fromBytes(value : Bytes, offset : Int = 0, length : Int = 0) : BigInt_ - { + public static function fromBytes(value:Bytes, offset:Int = 0, length:Int = 0):BigInt_ { var bi = new MutableBigInt_(); bi.setFromBigEndianBytesSigned(value, offset, length); return bi; @@ -399,53 +369,56 @@ class BigInt_ /** Creates a big integer with the value represented by the integer vector `value`. **/ - public static function fromUnsignedInts(value : Vector, length : Int = 0) : BigInt_ - { + public static function fromUnsignedInts(value:Vector, length:Int = 0):BigInt_ { var bi = new MutableBigInt_(); bi.setFromUnsignedInts(value, length); return bi; } - - public function square():BigInt_ - { - var r:MutableBigInt_ = new MutableBigInt_(); - BigIntArithmetic.multiply(r,this,this); + + public function square():BigInt_ { + var r:MutableBigInt_ = new MutableBigInt_(); + BigIntArithmetic.multiply(r, this, this); return r; } - - public function modPow(exponent:BigInt_, modulus:BigInt_) : BigInt_ - { - if (BigIntArithmetic.compareInt(exponent,0) < 0) throw BigIntExceptions.NEGATIVE_EXPONENT; - if ( this.isZero() ) return ( BigIntArithmetic.compareInt(exponent,0) == 0 ? BigInt.fromInt(1) : this); + + public function modPow(exponent:BigInt_, modulus:BigInt_):BigInt_ { + if (BigIntArithmetic.compareInt(exponent, 0) < 0) + throw BigIntExceptions.NEGATIVE_EXPONENT; + if (this.isZero()) + return (BigIntArithmetic.compareInt(exponent, 0) == 0 ? BigInt.fromInt(1) : this); var r = BigInt_.newFromInt(1); var p:BigInt_ = this; - while(true) { - if ( BigIntArithmetic.bitwiseAndInt(exponent,1) == 1 ) r = modulus2(multiply2(p,r),modulus); - exponent= BigInt_.arithmeticShiftRight2(exponent, 1); - if (BigIntArithmetic.compareInt(exponent,0) == 0) break; - p = modulus2(multiply2(p,p),modulus); - } + while (true) { + if (BigIntArithmetic.bitwiseAndInt(exponent, 1) == 1) + r = modulus2(multiply2(p, r), modulus); + exponent = BigInt_.arithmeticShiftRight2(exponent, 1); + if (BigIntArithmetic.compareInt(exponent, 0) == 0) + break; + p = modulus2(multiply2(p, p), modulus); + } return r; } - - public function pow(exponent:UInt) : BigInt_ - { - if (exponent < 0) throw BigIntExceptions.NEGATIVE_EXPONENT; - if ( this.isZero() ) return ( exponent == 0 ? BigInt.fromInt(1) : this); + + public function pow(exponent:UInt):BigInt_ { + if (exponent < 0) + throw BigIntExceptions.NEGATIVE_EXPONENT; + if (this.isZero()) + return (exponent == 0 ? BigInt.fromInt(1) : this); var r = BigInt_.newFromInt(1); var p:BigInt_ = this; - while(true) { - if ( (exponent & 1) == 1 ) r = multiply2(p,r); - exponent= exponent >> 1; - if (exponent == 0) break; - p = multiply2(p,p); - } + while (true) { + if ((exponent & 1) == 1) + r = multiply2(p, r); + exponent = exponent >> 1; + if (exponent == 0) + break; + p = multiply2(p, p); + } return r; } - + /* hac 14.61, pp. 608 */ - public function modInverse(modulus:BigInt_):BigInt_ - { + public function modInverse(modulus:BigInt_):BigInt_ { if (modulus.sign() == -1 || modulus.isZero()) throw BigIntExceptions.NEGATIVE_MODULUS; if (equals2Int(modulus, 1)) @@ -522,149 +495,134 @@ class BigInt_ while (BigIntArithmetic.compare(c, modulus) >= 0) { c = sub2(c, modulus); } - - if ( this.sign() < 0) { - c = sub2(modulus,c); + + if (this.sign() < 0) { + c = sub2(modulus, c); } return c; } - - public static function randomPrime(bits:Int32 , tolerance:UInt):BigInt_ - { - if ( bits < 2 ) throw BigIntExceptions.INVALID_ARGUMENT; - if ( bits == 2 ) return ( (Math.random()<0.5)?BigInt.TWO:BigInt.fromInt(3)); + + public static function randomPrime(bits:Int32, tolerance:UInt):BigInt_ { + if (bits < 2) + throw BigIntExceptions.INVALID_ARGUMENT; + if (bits == 2) + return ((Math.random() < 0.5) ? BigInt.TWO : BigInt.fromInt(3)); var r = new MutableBigInt_(); do { var bytes = randomBytes(bits); - var excessBits = 8 * bytes.length - bits; - bytes.set(0,bytes.get(0)|(1 << (7 - excessBits))); - bytes.set(bytes.length-1,bytes.get(bytes.length-1)|1); + var excessBits = 8 * bytes.length - bits; + bytes.set(0, bytes.get(0) | (1 << (7 - excessBits))); + bytes.set(bytes.length - 1, bytes.get(bytes.length - 1) | 1); r.setFromBigEndianBytesSigned(bytes); - if ( bits > 10 ) { - while(!equals2Int(r.gcd(BigInt.SMALL_PRIMES_PRODUCT),1)) - { + if (bits > 10) { + while (!equals2Int(r.gcd(BigInt.SMALL_PRIMES_PRODUCT), 1)) { BigIntArithmetic.addInt(r, r, 2); } } } while (!r.isProbablePrime(tolerance)); - if ( r.sign() < 0) BigIntArithmetic.negate(r, r); + if (r.sign() < 0) + BigIntArithmetic.negate(r, r); return r; } - - public static function randomInRange(min:BigInt_, max:BigInt_):BigInt_ - { + + public static function randomInRange(min:BigInt_, max:BigInt_):BigInt_ { min = min.abs(); max = max.abs(); - var initCheck = BigIntArithmetic.compare(min,max); - if ( initCheck == 0) return min; - if ( initCheck > 0 ) throw BigIntExceptions.INVALID_ARGUMENT; - if ( min.bitLength() > (max.bitLength()>>1)) return add2(randomInRange(BigInt.ZERO,sub2(max,min)),min); - for(i in 0...1000) { + var initCheck = BigIntArithmetic.compare(min, max); + if (initCheck == 0) + return min; + if (initCheck > 0) + throw BigIntExceptions.INVALID_ARGUMENT; + if (min.bitLength() > (max.bitLength() >> 1)) + return add2(randomInRange(BigInt.ZERO, sub2(max, min)), min); + for (i in 0...1000) { var rnd = random(max.bitLength()); - if ( BigIntArithmetic.compare(rnd,min) >= 0 && BigIntArithmetic.compare(rnd,max) <= 0) { + if (BigIntArithmetic.compare(rnd, min) >= 0 && BigIntArithmetic.compare(rnd, max) <= 0) { return rnd; } } - return add2(random(sub2(max,min).bitLength()-1),min); + return add2(random(sub2(max, min).bitLength() - 1), min); } - - public static function random(bits:Int32 ):BigInt_ - { - if ( bits <= 0 ) return BigInt.ZERO; + + public static function random(bits:Int32):BigInt_ { + if (bits <= 0) + return BigInt.ZERO; var r = new MutableBigInt_(); r.setFromBigEndianBytesSigned(randomBytes(bits)); r.compact(); return r; } - - public static function divMod(dividend:BigInt_, divisor:BigInt_):{quotient:BigInt_, remainder:BigInt_} - { + + public static function divMod(dividend:BigInt_, divisor:BigInt_):{quotient:BigInt_, remainder:BigInt_} { var q = new MutableBigInt_(); var r = new MutableBigInt_(); BigIntArithmetic.divide(dividend, divisor, q, r); - return {quotient:q, remainder:r}; + return {quotient: q, remainder: r}; } //----------------------------------------------------------------------- // Private implementation //----------------------------------------------------------------------- - private inline function getUnsignedDigitCount() : Int - { - if ((m_count > 1) && (m_data.get(m_count - 1) == 0)) - { + private inline function getUnsignedDigitCount():Int { + if ((m_count > 1) && (m_data.get(m_count - 1) == 0)) { return m_count - 1; } return m_count; } - private inline function getShort(n : Int) : Int - { + private inline function getShort(n:Int):Int { return MultiwordArithmetic.getShort(m_data, n); } - private function compact() : Void - { - if (isNegative()) - { - while (m_count > 1) - { - if ((m_data.get(m_count - 1) == -1) && (m_data.get(m_count - 2) < 0)) - { + private function compact():Void { + if (isNegative()) { + while (m_count > 1) { + if ((m_data.get(m_count - 1) == -1) && (m_data.get(m_count - 2) < 0)) { --m_count; - } - else - { + } else { break; } } - } - else - { - while (m_count > 1) - { - if ((m_data.get(m_count - 1) == 0) && (m_data.get(m_count - 2) >= 0)) - { + } else { + while (m_count > 1) { + if ((m_data.get(m_count - 1) == 0) && (m_data.get(m_count - 2) >= 0)) { --m_count; - } - else - { + } else { break; } } } } - - private function millerRabin(rounds:UInt):Bool - { - var minusOne:BigInt_ = subInt2(this,1); - var m = subInt2(this,1); + + private function millerRabin(rounds:UInt):Bool { + var minusOne:BigInt_ = subInt2(this, 1); + var m = subInt2(this, 1); var lsb = m.getLowestSetBit(); - if ( lsb <=0 ) return false; - m = arithmeticShiftRight2(m,lsb); + if (lsb <= 0) + return false; + m = arithmeticShiftRight2(m, lsb); var num:BigInt_; - for(i in 0...rounds) { - num = randomInRange(BigInt.TWO,minusOne); - var z:BigInt_ = num.modPow(m,this); - if ( BigIntArithmetic.compare(z, BigInt.ONE) != 0 && BigIntArithmetic.compare(z, minusOne) != 0) { + for (i in 0...rounds) { + num = randomInRange(BigInt.TWO, minusOne); + var z:BigInt_ = num.modPow(m, this); + if (BigIntArithmetic.compare(z, BigInt.ONE) != 0 && BigIntArithmetic.compare(z, minusOne) != 0) { var j:Int = 1; - while ( j<=lsb && BigIntArithmetic.compare(z, minusOne) != 0) - { - if ( BigIntArithmetic.compare(z, BigInt.ONE) == 0 || j == lsb) { - return false; + while (j <= lsb && BigIntArithmetic.compare(z, minusOne) != 0) { + if (BigIntArithmetic.compare(z, BigInt.ONE) == 0 || j == lsb) { + return false; } - z = z.modPow(BigInt.TWO,this); + z = z.modPow(BigInt.TWO, this); j++; } } } return true; } - + /* hac 14.64, pp. 610 */ - private function modInverseOdd(y:BigInt_, x:BigInt_):BigInt_ - { + private function modInverseOdd(y:BigInt_, x:BigInt_):BigInt_ { var b:BigInt_ = fromInt(0); var d:BigInt_ = fromInt(1); var u:BigInt_ = MutableBigInt_.fromBigInt(x); @@ -707,158 +665,136 @@ class BigInt_ return d; } - private static function newFromInt(value : Int) : BigInt_ - { + private static function newFromInt(value:Int):BigInt_ { var bi = new MutableBigInt_(); bi.setFromInt(value); return bi; } - - private static function randomBytes(bits:Int32) : Bytes - { - var countBytes:Int = Std.int((bits+7)/8); + + private static function randomBytes(bits:Int32):Bytes { + var countBytes:Int = Std.int((bits + 7) / 8); var randomBytes = Bytes.alloc(countBytes); - for(j in 0...countBytes) { - var rndN = Math.floor( Math.random() * 256 ); - randomBytes.set(j,rndN); + for (j in 0...countBytes) { + var rndN = Math.floor(Math.random() * 256); + randomBytes.set(j, rndN); } var excessBits:Int = 8 * countBytes - bits; - if ( excessBits > 0) - randomBytes.set(0, randomBytes.get(0)&(255 >>> excessBits)); + if (excessBits > 0) + randomBytes.set(0, randomBytes.get(0) & (255 >>> excessBits)); return randomBytes; } - private function new() : Void - { - } + private function new():Void {} - private static function getCachedValue(value : Int) : BigInt_ - { - if ((s_firstCachedValue <= value) && (value <= s_lastCachedValue)) - { + private static function getCachedValue(value:Int):BigInt_ { + if ((s_firstCachedValue <= value) && (value <= s_lastCachedValue)) { initCache(); return s_cache[value - s_firstCachedValue]; } return null; } - private static function initCache() : Void - { - if (s_cache == null) - { + private static function initCache():Void { + if (s_cache == null) { s_cache = new Vector(s_lastCachedValue + 1 - s_firstCachedValue); - for (i in 0 ... s_cache.length) - { + for (i in 0...s_cache.length) { s_cache[i] = newFromInt(i + s_firstCachedValue); } } } - private var m_count : Int; - private var m_data : Vector; + private var m_count:Int; + private var m_data:Vector; - private static inline var s_firstCachedValue : Int = -16; - private static inline var s_lastCachedValue : Int = 16; - private static var s_cache : Vector = null; + private static inline var s_firstCachedValue:Int = -16; + private static inline var s_lastCachedValue:Int = 16; + private static var s_cache:Vector = null; //----------------------------------------------------------------------- // Static helpers //----------------------------------------------------------------------- @:noCompletion - private static inline function negate1(a : BigInt_) : BigInt_ - { + private static inline function negate1(a:BigInt_):BigInt_ { var r = new MutableBigInt_(); BigIntArithmetic.negate(r, a); return r; } @:noCompletion - private static inline function equals2Int(a : BigInt_, b : Int) : Bool - { + private static inline function equals2Int(a:BigInt_, b:Int):Bool { return a.equalsInt(b); } @:noCompletion - private static inline function equals2(a : BigInt_, b : BigInt_) : Bool - { + private static inline function equals2(a:BigInt_, b:BigInt_):Bool { return a.equals(b); } @:noCompletion - private static inline function addInt2(a : BigInt_, b : Int) : BigInt_ - { + private static inline function addInt2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); BigIntArithmetic.addInt(r, a, b); return r; } @:noCompletion - private static inline function add2(a : BigInt_, b : BigInt_) : BigInt_ - { + private static inline function add2(a:BigInt_, b:BigInt_):BigInt_ { var r = new MutableBigInt_(); BigIntArithmetic.add(r, a, b); return r; } @:noCompletion - private static inline function subInt2(a : BigInt_, b : Int) : BigInt_ - { + private static inline function subInt2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); BigIntArithmetic.subtractInt(r, a, b); return r; } @:noCompletion - private static inline function sub2(a : BigInt_, b : BigInt_) : BigInt_ - { + private static inline function sub2(a:BigInt_, b:BigInt_):BigInt_ { var r = new MutableBigInt_(); BigIntArithmetic.subtract(r, a, b); return r; } @:noCompletion - private static inline function multiplyInt2(a : BigInt_, b : Int) : BigInt_ - { + private static inline function multiplyInt2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); BigIntArithmetic.multiplyInt(r, a, b); return r; } @:noCompletion - private static inline function multiply2(a : BigInt_, b : BigInt_) : BigInt_ - { + private static inline function multiply2(a:BigInt_, b:BigInt_):BigInt_ { var r = new MutableBigInt_(); BigIntArithmetic.multiply(r, a, b); return r; } @:noCompletion - private static inline function divideInt2(a : BigInt_, b : Int) : BigInt_ - { + private static inline function divideInt2(a:BigInt_, b:Int):BigInt_ { var q = new MutableBigInt_(); BigIntArithmetic.divideInt(a, b, q); return q; } @:noCompletion - private static inline function divide2(a : BigInt_, b : BigInt_) : BigInt_ - { + private static inline function divide2(a:BigInt_, b:BigInt_):BigInt_ { var q = new MutableBigInt_(); BigIntArithmetic.divide(a, b, q, null); return q; } @:noCompletion - private static inline function modulusInt2(a : BigInt_, b : Int) : Int - { + private static inline function modulusInt2(a:BigInt_, b:Int):Int { var q = new MutableBigInt_(); return BigIntArithmetic.divideInt(a, b, q); } @:noCompletion - private static inline function modulus2(a : BigInt_, b : BigInt_) : BigInt_ - { + private static inline function modulus2(a:BigInt_, b:BigInt_):BigInt_ { var q = new MutableBigInt_(); var r = new MutableBigInt_(); BigIntArithmetic.divide(a, b, q, r); @@ -866,78 +802,66 @@ class BigInt_ } @:noCompletion - private static inline function arithmeticShiftLeft2(a : BigInt_, b : Int) : BigInt_ - { + private static inline function arithmeticShiftLeft2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); BigIntArithmetic.arithmeticShiftLeft(r, a, b); return r; } @:noCompletion - private static inline function arithmeticShiftRight2(a : BigInt_, b : Int) : BigInt_ - { + private static inline function arithmeticShiftRight2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); BigIntArithmetic.arithmeticShiftRight(r, a, b); return r; } @:noCompletion - private static inline function sign1(a : BigInt_) : Int - { + private static inline function sign1(a:BigInt_):Int { return a.sign(); } @:noCompletion - private static inline function isZero1(a : BigInt_) : Bool - { + private static inline function isZero1(a:BigInt_):Bool { return a.isZero(); } @:noCompletion - private static inline function isNegative1(a : BigInt_) : Bool - { + private static inline function isNegative1(a:BigInt_):Bool { return a.isNegative(); } - + @:noCompletion - private static inline function isPositive1(a : BigInt_) : Bool - { + private static inline function isPositive1(a:BigInt_):Bool { return a.isPositive(); } @:noCompletion - private static inline function isOdd1(a : BigInt_) : Bool - { + private static inline function isOdd1(a:BigInt_):Bool { return a.isOdd(); } @:noCompletion - private static inline function isEven1(a : BigInt_) : Bool - { + private static inline function isEven1(a:BigInt_):Bool { return a.isEven(); } @:noCompletion - private static inline function toString1(a : BigInt_) : String - { + private static inline function toString1(a:BigInt_):String { return a.toString(); } @:noCompletion - private static inline function toHex1(a : BigInt_) : String - { + private static inline function toHex1(a:BigInt_):String { return a.toHex(); } @:noCompletion - private static inline function toBytes1(a : BigInt_) : Bytes - { + private static inline function toBytes1(a:BigInt_):Bytes { return a.toBytes(); } @:noCompletion - private static inline function toInts1(a : BigInt_, v : Vector) : Int - { + private static inline function toInts1(a:BigInt_, v:Vector):Int { return a.toInts(v); } } diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 53af89bf354..3124e040327 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package haxe.math.bigint; import haxe.math.bigint.BigIntExceptions; @@ -28,39 +28,29 @@ import haxe.ds.Vector; /* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(haxe.math.bigint) -class MultiwordArithmetic -{ - public static function isZero(value : Vector, length : Int) : Bool - { - if (length < 1) - { +class MultiwordArithmetic { + public static function isZero(value:Vector, length:Int):Bool { + if (length < 1) { throw BigIntExceptions.INVALID_ARGUMENT; } - for (i in 0 ... length) - { - if (value.get(i) != 0) - { + for (i in 0...length) { + if (value.get(i) != 0) { return false; } } return true; } - public static inline function isNegative(value : Vector, length : Int) : Bool - { + public static inline function isNegative(value:Vector, length:Int):Bool { return value.get(length - 1) < 0; } - public static function getLengthUnsigned(value : Vector, length : Int) : Int - { - if (length < 1) - { + public static function getLengthUnsigned(value:Vector, length:Int):Int { + if (length < 1) { throw BigIntExceptions.INVALID_ARGUMENT; } - while (--length > 0) - { - if (value.get(length) != 0) - { + while (--length > 0) { + if (value.get(length) != 0) { break; } } @@ -72,30 +62,20 @@ class MultiwordArithmetic `input` and `result` may refer to the same object. **/ - public static function extendUnsigned(result : Vector, resultLength : Int, input : Vector, inputLength : Int) : Void - { - if (input == result) - { - if (resultLength > inputLength) - { - for (i in inputLength ... resultLength) - { + public static function extendUnsigned(result:Vector, resultLength:Int, input:Vector, inputLength:Int):Void { + if (input == result) { + if (resultLength > inputLength) { + for (i in inputLength...resultLength) { result.set(i, 0); } } - } - else - { - if (resultLength > inputLength) - { + } else { + if (resultLength > inputLength) { copy(result, input, inputLength); - for (i in inputLength ... resultLength) - { + for (i in inputLength...resultLength) { result.set(i, 0); } - } - else - { + } else { copy(result, input, resultLength); } } @@ -110,17 +90,15 @@ class MultiwordArithmetic Ok for `result` and `operand` to be the same object. **/ - public static function negate(result : Vector, operand : Vector, length : Int) : Bool - { - var c : Int = 1; - var x : Int = 0; - var z : Int = 0; - for (i in 0 ... length) - { + public static function negate(result:Vector, operand:Vector, length:Int):Bool { + var c:Int = 1; + var x:Int = 0; + var z:Int = 0; + for (i in 0...length) { x = ~operand.get(i); z = x + c; result.set(i, z); - c = (x & ~z) >>> 31; // "Hacker's Delight" p. 38 + c = (x & ~z) >>> 31; // "Hacker's Delight" p. 38 } // detect overflow; intuitively, this can only occur for inputs of 2 ^ (32 * N - 1). return (~x & z) < 0; @@ -134,21 +112,18 @@ class MultiwordArithmetic Returns the "carry" value of either 0 or 1. **/ - public static function add(result : Vector, operand1 : Vector, operand2 : Vector, length : Int) : Int - { - if ((length < 1) || (result.length < length) || (operand1.length < length) || (operand2.length < length)) - { + public static function add(result:Vector, operand1:Vector, operand2:Vector, length:Int):Int { + if ((length < 1) || (result.length < length) || (operand1.length < length) || (operand2.length < length)) { throw BigIntExceptions.INVALID_ARGUMENT; } - var c : Int = 0; - var x : Int = 0, y : Int = 0, z : Int = 0; - for (i in 0 ... length) - { + var c:Int = 0; + var x:Int = 0, y:Int = 0, z:Int = 0; + for (i in 0...length) { x = operand1.get(i); y = operand2.get(i); z = x + y + c; result.set(i, z); - c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((x & y) | ((x | y) & ~z)) >>> 31; // "Hacker's Delight" p. 38 } return c; } @@ -161,21 +136,18 @@ class MultiwordArithmetic Returns the "borrow" value of either 0 or 1. **/ - public static function subtract(result : Vector, operand1 : Vector, operand2 : Vector, length : Int) : Int - { - if ((length < 1) || (result.length < length) || (operand1.length < length) || (operand2.length < length)) - { + public static function subtract(result:Vector, operand1:Vector, operand2:Vector, length:Int):Int { + if ((length < 1) || (result.length < length) || (operand1.length < length) || (operand2.length < length)) { throw BigIntExceptions.INVALID_ARGUMENT; } - var c : Int = 0; - var x : Int = 0, y : Int = 0, z : Int = 0; - for (i in 0 ... length) - { + var c:Int = 0; + var x:Int = 0, y:Int = 0, z:Int = 0; + for (i in 0...length) { x = operand1.get(i); y = operand2.get(i); z = x - y - c; result.set(i, z); - c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 + c = ((~x & y) | (~(x ^ y) & z)) >>> 31; // "Hacker's Delight" p. 38 } return c; } @@ -190,8 +162,7 @@ class MultiwordArithmetic or `operand2`; however, `operand1` and `operand2` may be the same object. **/ - public static function multiplyIntUnsigned(result : Vector, operand1 : Vector, operand1Length : Int, operand2 : Int) : Void - { + public static function multiplyIntUnsigned(result:Vector, operand1:Vector, operand1Length:Int, operand2:Int):Void { // TODO: Optimize. var op2 = new Vector(1); op2.set(0, operand2); @@ -209,46 +180,38 @@ class MultiwordArithmetic or `operand2`; however, `operand1` and `operand2` may be the same object. **/ - public static function multiplyUnsigned(result : Vector, operand1 : Vector, operand1Length : Int, operand2 : Vector, operand2Length : Int) : Void - { + public static function multiplyUnsigned(result:Vector, operand1:Vector, operand1Length:Int, operand2:Vector, operand2Length:Int):Void { // Implements Figure 8-1 (p. 172) from "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. - if ((operand1 == result) || (operand2 == result)) - { + if ((operand1 == result) || (operand2 == result)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if ((operand1Length < 1) || (operand2Length < 1)) - { + if ((operand1Length < 1) || (operand2Length < 1)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if ((operand1.length < operand1Length) || (operand2.length < operand2Length)) - { + if ((operand1.length < operand1Length) || (operand2.length < operand2Length)) { throw BigIntExceptions.INVALID_ARGUMENT; } - var resultSize : Int = operand1Length + operand2Length; - if (result.length < resultSize) - { + var resultSize:Int = operand1Length + operand2Length; + if (result.length < resultSize) { throw BigIntExceptions.INVALID_ARGUMENT; } setZero(result, resultSize); - if (isZero(operand1, operand1Length) || isZero(operand2, operand2Length)) - { + if (isZero(operand1, operand1Length) || isZero(operand2, operand2Length)) { return; } - var b : Int, k : Int, t : Int; - var u : Int, v : Int, w : Int; - var m : Int = operand1Length << 1; - var n : Int = operand2Length << 1; + var b:Int, k:Int, t:Int; + var u:Int, v:Int, w:Int; + var m:Int = operand1Length << 1; + var n:Int = operand2Length << 1; - for (j in 0 ... n) - { + for (j in 0...n) { v = getShort(operand2, j); k = 0; - for (i in 0 ... m) - { + for (i in 0...m) { u = getShort(operand1, i); w = getShort(result, i + j); t = u * v + w + k; @@ -259,10 +222,9 @@ class MultiwordArithmetic } } - public static inline function getDivisionQuotientLengthUnsigned(dividendLength : Int, divisorLength : Int) : Int - { + public static inline function getDivisionQuotientLengthUnsigned(dividendLength:Int, divisorLength:Int):Int { var max:Int = dividendLength - divisorLength + 1; - return ((max>1)?max:1); + return ((max > 1) ? max : 1); } /** @@ -281,11 +243,10 @@ class MultiwordArithmetic The results are unspecified if `divisor` is negative. **/ - public static function divideIntUnsigned(dividend : Vector, dividendLength : Int, divisor : Int, quotientOut : Vector, work : Vector) : Int - { + public static function divideIntUnsigned(dividend:Vector, dividendLength:Int, divisor:Int, quotientOut:Vector, work:Vector):Int { // TODO: Consider optimizing this case. var remainder = new Vector(1); - var vDivisor = new Vector(1); + var vDivisor = new Vector(1); vDivisor.set(0, divisor); divideUnsigned(dividend, dividendLength, vDivisor, 1, quotientOut, remainder, work); return remainder.get(0); @@ -315,75 +276,61 @@ class MultiwordArithmetic `dividend` and `divisor` are not modified, unless they reference one of the outputs. **/ - public static function divideUnsigned(dividend : Vector, dividendLength : Int, divisor : Vector, divisorLength : Int, quotientOut : Vector, remainderOut : Vector, work : Vector) : Void - { - if ((quotientOut == null) || (work == null) || (quotientOut == remainderOut)) - { + public static function divideUnsigned(dividend:Vector, dividendLength:Int, divisor:Vector, divisorLength:Int, quotientOut:Vector, + remainderOut:Vector, work:Vector):Void { + if ((quotientOut == null) || (work == null) || (quotientOut == remainderOut)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if ((work == dividend) || (work == divisor) || (work == quotientOut) || (work == remainderOut)) - { + if ((work == dividend) || (work == divisor) || (work == quotientOut) || (work == remainderOut)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if ((divisorLength < 1) || (dividendLength < 1)) - { + if ((divisorLength < 1) || (dividendLength < 1)) { throw BigIntExceptions.INVALID_ARGUMENT; } - var quotientLength : Int = getDivisionQuotientLengthUnsigned(dividendLength, divisorLength); - if (quotientOut.length < quotientLength) - { + var quotientLength:Int = getDivisionQuotientLengthUnsigned(dividendLength, divisorLength); + if (quotientOut.length < quotientLength) { // quotient storage too small throw BigIntExceptions.INVALID_ARGUMENT; } - if ((remainderOut != null) && (remainderOut.length < divisorLength)) - { + if ((remainderOut != null) && (remainderOut.length < divisorLength)) { // remainder storage too small throw BigIntExceptions.INVALID_ARGUMENT; } - if (work.length < dividendLength + divisorLength + 1) - { + if (work.length < dividendLength + divisorLength + 1) { // quotient storage too small throw BigIntExceptions.INVALID_ARGUMENT; } // special cases - var dh : Int32 = divisor.get(divisorLength - 1); - if (divisorLength < 2) - { - switch (dh) - { + var dh:Int32 = divisor.get(divisorLength - 1); + if (divisorLength < 2) { + switch (dh) { case 0: throw BigIntExceptions.DIVISION_BY_ZERO; case 1: - copy(quotientOut, dividend, dividendLength); // quotientLength == dividendLength - if (remainderOut != null) - { + copy(quotientOut, dividend, dividendLength); // quotientLength == dividendLength + if (remainderOut != null) { setZero(remainderOut, divisorLength); } return; } - } - else if (dh == 0) - { + } else if (dh == 0) { // leading zero throw BigIntExceptions.INVALID_ARGUMENT; } // trim leading zeros /*while ((dividendLength > 1) && (dividend.get(dividendLength - 1) == 0)) - { - --dividendLength; + { + --dividendLength; }*/ - if (dividendLength < 2) - { - switch (dividend.get(0)) - { + if (dividendLength < 2) { + switch (dividend.get(0)) { case 0: setZero(quotientOut, quotientLength); - if (remainderOut != null) - { + if (remainderOut != null) { setZero(remainderOut, divisorLength); } return; @@ -391,13 +338,10 @@ class MultiwordArithmetic } // if dividend is shorter than divisor - if (dividendLength < divisorLength) - { - if (remainderOut != null) - { + if (dividendLength < divisorLength) { + if (remainderOut != null) { copy(remainderOut, dividend, dividendLength); - for (i in dividendLength ... divisorLength) - { + for (i in dividendLength...divisorLength) { remainderOut.set(i, 0); } } @@ -409,35 +353,30 @@ class MultiwordArithmetic // Based on Figure 9-1 (p. 185) from "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. - var j : Int, k : Int32, t : Int; - var m : Int = dividendLength << 1; - var un : Int = divisorLength << 1; - var n : Int = un; - if (getShort(divisor, n - 1) == 0) - { + var j:Int, k:Int32, t:Int; + var m:Int = dividendLength << 1; + var un:Int = divisorLength << 1; + var n:Int = un; + if (getShort(divisor, n - 1) == 0) { --n; } // Take care of the case of a single-digit divisor here. - if (n == 1) - { - var v0 : Int = divisor.get(0); - if (quotientOut != dividend) - { + if (n == 1) { + var v0:Int = divisor.get(0); + if (quotientOut != dividend) { setZero(quotientOut, quotientLength); } - var uj : Int; + var uj:Int; k = 0; j = m; - while (--j >= 0) - { + while (--j >= 0) { uj = getShort(dividend, j); t = BigIntHelper.u32divu16((k << 16) + uj, v0); setShort(quotientOut, j, t); k = (k << 16) + uj - t * v0; } - if (remainderOut != null) - { + if (remainderOut != null) { setFromIntUnsigned(remainderOut, divisorLength, k); } return; @@ -446,14 +385,11 @@ class MultiwordArithmetic // vn is work[0] through work[divisor.m_count - 1] or shorts [0, n) // un is work[divisor.m_count] through work[dividend.m_count + divisor.m_count] or shorts [n, n + m] - var s : Int = BigIntHelper.nlz(getShort(divisor, n - 1)) - 16; // 0 <= s < 16 - if (s > 0) - { + var s:Int = BigIntHelper.nlz(getShort(divisor, n - 1)) - 16; // 0 <= s < 16 + if (s > 0) { _lsl32x(work, 0, divisor, divisorLength, s); _lsl32x(work, divisorLength, dividend, dividendLength, s); - } - else - { + } else { Vector.blit(divisor, 0, work, 0, divisorLength); Vector.blit(dividend, 0, work, divisorLength, dividendLength); work.set(divisorLength + dividendLength, 0); @@ -462,29 +398,25 @@ class MultiwordArithmetic setZero(quotientOut, quotientLength); // Main loop. - var qhat : Int32, rhat : Int32, p : Int32, t : Int32; - var vn : Int = getShort(work, n - 1); + var qhat:Int32, rhat:Int32, p:Int32, t:Int32; + var vn:Int = getShort(work, n - 1); j = m - n + 1; - while (--j >= 0) - { + while (--j >= 0) { // Compute estimate qhat of q[j] t = (getShort(work, j + n + un) << 16) + getShort(work, j + n + un - 1); qhat = BigIntHelper.u32divu16(t, vn); rhat = t - qhat * vn; - while ((qhat >= 65536) || BigIntHelper.u32gtu32(qhat * getShort(work, n - 2), (rhat << 16) + getShort(work, j + n + un - 2))) - { + while ((qhat >= 65536) || BigIntHelper.u32gtu32(qhat * getShort(work, n - 2), (rhat << 16) + getShort(work, j + n + un - 2))) { qhat -= 1; rhat += vn; - if (rhat >= 65536) - { + if (rhat >= 65536) { break; } } // Multiply and subtract k = 0; - for (i in 0 ... n) - { + for (i in 0...n) { p = qhat * getShort(work, i); t = getShort(work, i + j + un) - k - (p & 0xffff); setShort(work, i + j + un, t); @@ -495,16 +427,12 @@ class MultiwordArithmetic // Store quotient digit. // If we subtracted too much, add back. - if (t >= 0) - { + if (t >= 0) { setShort(quotientOut, j, qhat); - } - else - { + } else { setShort(quotientOut, j, qhat - 1); k = 0; - for (i in 0 ... n) - { + for (i in 0...n) { t = getShort(work, i + j + un) + getShort(work, i) + k; setShort(work, i + j + un, t); k = t >> 16; @@ -515,14 +443,10 @@ class MultiwordArithmetic } // If the caller wants the remainder, unnormalize it and pass back. - if (remainderOut != null) - { - if (s > 0) - { + if (remainderOut != null) { + if (s > 0) { _lsr32(remainderOut, work, divisorLength, divisorLength, s); - } - else - { + } else { Vector.blit(work, divisorLength, remainderOut, 0, divisorLength); } } @@ -537,29 +461,19 @@ class MultiwordArithmetic `result` and `input` may be the same object. **/ - public static function arithmeticShiftRight(result : Vector, input : Vector, length : Int, shift : Int) : Void - { - if ((length < 1) || (result.length < length) || (input.length < length)) - { + public static function arithmeticShiftRight(result:Vector, input:Vector, length:Int, shift:Int):Void { + if ((length < 1) || (result.length < length) || (input.length < length)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if (shift < 0) - { + if (shift < 0) { throw BigIntExceptions.INVALID_ARGUMENT; - } - else if (shift == 0) - { - if (input != result) - { + } else if (shift == 0) { + if (input != result) { Vector.blit(input, 0, result, 0, length); } - } - else if (shift < 32) - { + } else if (shift < 32) { _asr32(result, input, length, 0, shift); - } - else - { + } else { throw BigIntExceptions.INVALID_ARGUMENT; } } @@ -573,29 +487,19 @@ class MultiwordArithmetic `result` and `input` may be the same object. **/ - public static function logicalShiftRight(result : Vector, input : Vector, length : Int, shift : Int) : Void - { - if ((length < 1) || (result.length < length) || (input.length < length)) - { + public static function logicalShiftRight(result:Vector, input:Vector, length:Int, shift:Int):Void { + if ((length < 1) || (result.length < length) || (input.length < length)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if (shift < 0) - { + if (shift < 0) { throw BigIntExceptions.INVALID_ARGUMENT; - } - else if (shift == 0) - { - if (input != result) - { + } else if (shift == 0) { + if (input != result) { Vector.blit(input, 0, result, 0, length); } - } - else if (shift < 32) - { + } else if (shift < 32) { _lsr32(result, input, length, 0, shift); - } - else - { + } else { throw BigIntExceptions.INVALID_ARGUMENT; } } @@ -609,29 +513,19 @@ class MultiwordArithmetic `result` and `input` may be the same object. **/ - public static function shiftLeft(result : Vector, input : Vector, length : Int, shift : Int) : Void - { - if ((length < 1) || (result.length < length) || (input.length < length)) - { + public static function shiftLeft(result:Vector, input:Vector, length:Int, shift:Int):Void { + if ((length < 1) || (result.length < length) || (input.length < length)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if (shift < 0) - { + if (shift < 0) { throw BigIntExceptions.INVALID_ARGUMENT; - } - else if (shift == 0) - { - if (input != result) - { + } else if (shift == 0) { + if (input != result) { Vector.blit(input, 0, result, 0, length); } - } - else if (shift < 32) - { + } else if (shift < 32) { _lsl32(result, 0, input, length, shift); - } - else - { + } else { throw BigIntExceptions.INVALID_ARGUMENT; } } @@ -643,14 +537,11 @@ class MultiwordArithmetic returns 1 if `a > b`; otherwise returns 0 (`a == b`). **/ - public static function compareSigned(a : Vector, b : Vector, length : Int) : Int - { - if (a != b) - { - var ah : Int = a.get(length - 1); - var bh : Int = b.get(length - 1); - if ((ah ^ bh) < 0) - { + public static function compareSigned(a:Vector, b:Vector, length:Int):Int { + if (a != b) { + var ah:Int = a.get(length - 1); + var bh:Int = b.get(length - 1); + if ((ah ^ bh) < 0) { // differing signs return (ah >> 30) | 1; } @@ -666,110 +557,84 @@ class MultiwordArithmetic returns 1 if `a > b`; otherwise returns 0 (`a == b`). **/ - public static function compareUnsigned(a : Vector, b : Vector, length : Int) : Int - { - if (a != b) - { - var an : Int, bn : Int, d : Int; - var x : Int32 = -2147483648; - while (--length >= 0) - { + public static function compareUnsigned(a:Vector, b:Vector, length:Int):Int { + if (a != b) { + var an:Int, bn:Int, d:Int; + var x:Int32 = -2147483648; + while (--length >= 0) { an = a.get(length) + x; bn = b.get(length) + x; - if (an > bn) return 1; - if (an < bn) return -1; + if (an > bn) + return 1; + if (an < bn) + return -1; } } return 0; } - public static function setZero(dest : Vector, length : Int) : Void - { - if (dest.length < length) - { + public static function setZero(dest:Vector, length:Int):Void { + if (dest.length < length) { throw BigIntExceptions.INVALID_ARGUMENT; } - for (i in 0 ... length) - { + for (i in 0...length) { dest.set(i, 0); } } - public static function setFromIntUnsigned(dest : Vector, length : Int, value : Int) : Void - { - if (dest.length < length) - { + public static function setFromIntUnsigned(dest:Vector, length:Int, value:Int):Void { + if (dest.length < length) { throw BigIntExceptions.INVALID_ARGUMENT; } dest.set(0, value); - for (i in 1 ... length) - { + for (i in 1...length) { dest.set(i, 0); } } - public static function setFromHexUnsigned(dest : Vector, length : Int, value : String) : Bool - { - if ((value == null) || (dest == null)) - { + public static function setFromHexUnsigned(dest:Vector, length:Int, value:String):Bool { + if ((value == null) || (dest == null)) { throw BigIntExceptions.INVALID_ARGUMENT; } - if (dest.length < length) - { + if (dest.length < length) { throw BigIntExceptions.INVALID_ARGUMENT; } var index = value.length; - if (index <= 0) - { + if (index <= 0) { throw BigIntExceptions.INVALID_ARGUMENT; } - if (length < 1) - { + if (length < 1) { return false; } - var c : Int; - var start : Int = 0; - while (start < index) - { + var c:Int; + var start:Int = 0; + while (start < index) { c = value.charCodeAt(start); - if ((c != 48) && (c != 32)) - { + if ((c != 48) && (c != 32)) { break; } ++start; } - var pos : Int = 0; - var bit : Int = 0; - var acc : Int32 = 0; - while (index > start) - { + var pos:Int = 0; + var bit:Int = 0; + var acc:Int32 = 0; + while (index > start) { c = value.charCodeAt(--index); - if ((48 <= c) && (c <= 57)) - { + if ((48 <= c) && (c <= 57)) { c -= 48; - } - else if ((65 <= c) && (c <= 70)) - { + } else if ((65 <= c) && (c <= 70)) { c -= 55; - } - else if ((97 <= c) && (c <= 102)) - { + } else if ((97 <= c) && (c <= 102)) { c -= 87; - } - else if (c == 32) - { + } else if (c == 32) { continue; - } - else - { + } else { throw BigIntExceptions.INVALID_ARGUMENT; } acc |= c << bit; bit += 4; - if (bit >= 32) - { - if (pos >= length) - { + if (bit >= 32) { + if (pos >= length) { return false; } dest.set(pos++, acc); @@ -777,30 +642,24 @@ class MultiwordArithmetic bit = 0; } } - if (bit > 0) - { - if (pos >= length) - { + if (bit > 0) { + if (pos >= length) { return false; } dest.set(pos++, acc); } - for (c in pos ... length) - { + for (c in pos...length) { dest.set(c, 0); } return true; } - public static function toHex(input : Vector, length : Int) : String - { + public static function toHex(input:Vector, length:Int):String { var sb = new StringBuf(); - while (--length >= 0) - { + while (--length >= 0) { var v = input.get(length); - for (j in 0 ... 8) - { - var c : Int = (v >> 28) & 0x0f; + for (j in 0...8) { + var c:Int = (v >> 28) & 0x0f; v <<= 4; c = (c < 10) ? (c + 48) : (c - 10 + 97); sb.addChar(c); @@ -812,17 +671,13 @@ class MultiwordArithmetic /** Get the value in decimal form. **/ - public static function toDecimalSigned(value : Vector, length : Int) : String - { + public static function toDecimalSigned(value:Vector, length:Int):String { var sb = new StringBuf(); var work = new Vector(length); - if (isNegative(value, length)) - { + if (isNegative(value, length)) { negate(work, value, length); - sb.addChar(45); // '-' - } - else - { + sb.addChar(45); // '-' + } else { copy(work, value, length); } return _toDecimal(sb, work, length); @@ -831,28 +686,23 @@ class MultiwordArithmetic /** Get the value in decimal form. **/ - public static function toDecimalUnsigned(value : Vector, length : Int) : String - { + public static function toDecimalUnsigned(value:Vector, length:Int):String { var sb = new StringBuf(); var work = new Vector(length); copy(work, value, length); return _toDecimal(sb, work, length); } - public static function copy(dest : Vector, source : Vector, length : Int) : Void - { - if (dest.length < length) - { + public static function copy(dest:Vector, source:Vector, length:Int):Void { + if (dest.length < length) { throw BigIntExceptions.INVALID_ARGUMENT; } Vector.blit(source, 0, dest, 0, length); } - public static function getBitSigned(value : Vector, length : Int, index : Int) : Int - { - var d : Int = index >> 5; - if (d >= length) - { + public static function getBitSigned(value:Vector, length:Int, index:Int):Int { + var d:Int = index >> 5; + if (d >= length) { return value.get(length - 1) >>> 31; } return (value.get(d) >> (index & 31)) & 1; @@ -861,16 +711,13 @@ class MultiwordArithmetic //----------------------------------------------------------------------- // Private helpers //----------------------------------------------------------------------- - // assumes 0 < shift < 32 // ok if output == input - private static function _lsl32(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int) : Void - { - var x : Int = input.get(inputSize - 1); - var r : Int = 32 - shift; - var y : Int; - while (--inputSize > 0) - { + private static function _lsl32(output:Vector, outputOffset:Int, input:Vector, inputSize:Int, shift:Int):Void { + var x:Int = input.get(inputSize - 1); + var r:Int = 32 - shift; + var y:Int; + while (--inputSize > 0) { y = input.get(inputSize - 1); x = (x << shift) | (y >>> r); output.set(inputSize + outputOffset, x); @@ -882,13 +729,11 @@ class MultiwordArithmetic // assumes 0 < shift < 32 // ok if output == input // note this writes inputSize + 1 words to output - private static function _lsl32x(output : Vector, outputOffset : Int, input : Vector, inputSize : Int, shift : Int) : Void - { - var x : Int = 0; - var r : Int = 32 - shift; - var y : Int; - while (inputSize > 0) - { + private static function _lsl32x(output:Vector, outputOffset:Int, input:Vector, inputSize:Int, shift:Int):Void { + var x:Int = 0; + var r:Int = 32 - shift; + var y:Int; + while (inputSize > 0) { y = input.get(inputSize - 1); x = (x << shift) | (y >>> r); output.set(inputSize + outputOffset, x); @@ -900,12 +745,10 @@ class MultiwordArithmetic // assumes 0 < shiftBits < 32 // assumes shiftDigits < length - private static function _asr32(result : Vector, input : Vector, length : Int, shiftDigits : Int, shiftBits : Int32) : Void - { - var r : Int = 32 - shiftBits; - var i : Int = 0; - while (i < length - shiftDigits - 1) - { + private static function _asr32(result:Vector, input:Vector, length:Int, shiftDigits:Int, shiftBits:Int32):Void { + var r:Int = 32 - shiftBits; + var i:Int = 0; + while (i < length - shiftDigits - 1) { result.set(i, (input.get(i + shiftDigits) >>> shiftBits) | (input.get(i + shiftDigits + 1) << r)); ++i; } @@ -914,12 +757,10 @@ class MultiwordArithmetic // assumes 0 < shift < 32 // ok if output == input - private static function _lsr32(output : Vector, input : Vector, inputSize : Int, inputOffset : Int, shift : Int32) : Void - { - var r : Int = 32 - shift; - var i : Int = 0; - while (i < inputSize - 1) - { + private static function _lsr32(output:Vector, input:Vector, inputSize:Int, inputOffset:Int, shift:Int32):Void { + var r:Int = 32 - shift; + var i:Int = 0; + while (i < inputSize - 1) { output.set(i, (input.get(inputOffset + i) >>> shift) | (input.get(inputOffset + i + 1) << r)); ++i; } @@ -927,35 +768,30 @@ class MultiwordArithmetic } @:noCompletion - private static function _toDecimal(sb : StringBuf, value : Vector, length : Int) : String - { + private static function _toDecimal(sb:StringBuf, value:Vector, length:Int):String { length = getLengthUnsigned(value, length); - var digits = new Vector(length * 10); // it is really log10 2^32 ~= 9.633, but this is close, simple, and never too little + var digits = new Vector(length * 10); // it is really log10 2^32 ~= 9.633, but this is close, simple, and never too little var work = new Vector(length + 1 + 1); - var pos : Int = digits.length; - var r : Int; - do - { + var pos:Int = digits.length; + var r:Int; + do { r = divideIntUnsigned(value, length, 10, value, work); length = getLengthUnsigned(value, length); digits.set(--pos, r + 48); } while (!isZero(value, length)); - for (i in pos ... digits.length) - { + for (i in pos...digits.length) { sb.addChar(digits.get(i)); } return sb.toString(); } - private static inline function getShort(v : Vector, n : Int) : Int - { + private static inline function getShort(v:Vector, n:Int):Int { return (v.get(n >> 1) >> ((n & 1) << 4)) & 0xffff; } - private static inline function setShort(a : Vector, n : Int, v : Int32) : Void - { - var s : Int = (n & 1) << 4; - var t : Int = a.get(n >> 1) & (~0xffff >>> s); + private static inline function setShort(a:Vector, n:Int, v:Int32):Void { + var s:Int = (n & 1) << 4; + var t:Int = a.get(n >> 1) & (~0xffff >>> s); a.set(n >> 1, t | ((v & 0xffff) << s)); } } diff --git a/std/haxe/math/bigint/MutableBigInt.hx b/std/haxe/math/bigint/MutableBigInt.hx index deb34d5ad9d..44bf0c25a14 100644 --- a/std/haxe/math/bigint/MutableBigInt.hx +++ b/std/haxe/math/bigint/MutableBigInt.hx @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package haxe.math.bigint; import haxe.ds.Vector; @@ -27,132 +27,108 @@ import haxe.io.Bytes; /* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(haxe.math.bigint) -abstract MutableBigInt(MutableBigInt_) -{ +abstract MutableBigInt(MutableBigInt_) { //----------------------------------------------------------------------- // Public interface //----------------------------------------------------------------------- - - public inline function sign() : Int - { + public inline function sign():Int { return BigInt_.sign1(this); } - public inline function isZero() : Bool - { + public inline function isZero():Bool { return BigInt_.isZero1(this); } - public inline function isNegative() : Bool - { + public inline function isNegative():Bool { return BigInt_.isNegative1(this); } - public inline function toString() : String - { + public inline function toString():String { return BigInt_.toString1(this); } - public inline function toHex() : String - { + public inline function toHex():String { return BigInt_.toHex1(this); } - public inline function toBytes() : Bytes - { + public inline function toBytes():Bytes { return BigInt_.toBytes1(this); } - public inline function toInts(output : Vector) : Int - { + public inline function toInts(output:Vector):Int { return BigInt_.toInts1(this, output); } - public inline function setFromInt(value : Int) : Void - { - var a : MutableBigInt_ = this; + public inline function setFromInt(value:Int):Void { + var a:MutableBigInt_ = this; a.setFromInt(value); } - public inline function setFromUnsignedInts(value : Vector, length : Int = 0) : Void - { - var a : MutableBigInt_ = this; + public inline function setFromUnsignedInts(value:Vector, length:Int = 0):Void { + var a:MutableBigInt_ = this; a.setFromUnsignedInts(value, length); } - public inline function setFromBigEndianBytesUnsigned(value : Bytes, offset : Int = 0, length : Int = 0) : Void - { - var a : MutableBigInt_ = this; + public inline function setFromBigEndianBytesUnsigned(value:Bytes, offset:Int = 0, length:Int = 0):Void { + var a:MutableBigInt_ = this; a.setFromBigEndianBytesUnsigned(value, offset, length); } - public inline function setFromLittleEndianBytesUnsigned(value : Bytes, offset : Int = 0, length : Int = 0) : Void - { - var a : MutableBigInt_ = this; + public inline function setFromLittleEndianBytesUnsigned(value:Bytes, offset:Int = 0, length:Int = 0):Void { + var a:MutableBigInt_ = this; a.setFromLittleEndianBytesUnsigned(value, offset, length); } - public inline function clear() : Void - { - var a : MutableBigInt_ = this; + public inline function clear():Void { + var a:MutableBigInt_ = this; a.clear(); } - public inline function copyFrom(other : BigInt) : Void - { - var a : MutableBigInt_ = this; + public inline function copyFrom(other:BigInt):Void { + var a:MutableBigInt_ = this; a.copyFrom(other); } - public inline function getBit(index : Int) : Int - { + public inline function getBit(index:Int):Int { return BigIntArithmetic.getBit(this, index); } - public static function fromBigEndianBytesUnsigned(value : Bytes) : MutableBigInt - { + public static function fromBigEndianBytesUnsigned(value:Bytes):MutableBigInt { var r = new MutableBigInt_(); r.setFromBigEndianBytesUnsigned(value); return new MutableBigInt(r); } - public static function fromLittleEndianBytesUnsigned(value : Bytes) : MutableBigInt - { + public static function fromLittleEndianBytesUnsigned(value:Bytes):MutableBigInt { var r = new MutableBigInt_(); r.setFromLittleEndianBytesUnsigned(value); return new MutableBigInt(r); } - - public function abs() : MutableBigInt - { + + public function abs():MutableBigInt { return this.abs(); } - - public function gcd(b:BigInt) : MutableBigInt - { + + public function gcd(b:BigInt):MutableBigInt { return this.gcd(b); } - - public function pow(exponent:UInt) : MutableBigInt - { + + public function pow(exponent:UInt):MutableBigInt { return this.pow(exponent); } - - public function modPow(exponent:BigInt, modulus:BigInt) : MutableBigInt - { - return this.modPow(exponent,modulus); + + public function modPow(exponent:BigInt, modulus:BigInt):MutableBigInt { + return this.modPow(exponent, modulus); } - - public function isProbablePrime(tolerance:UInt):Bool - { + + public function isProbablePrime(tolerance:UInt):Bool { return this.isProbablePrime(tolerance); } - - public function getLowestSetBit():Int - { + + public function getLowestSetBit():Int { return this.getLowestSetBit(); } - + public function bitLength():Int { return this.bitLength(); } @@ -160,7 +136,6 @@ abstract MutableBigInt(MutableBigInt_) //----------------------------------------------------------------------- // Operators //----------------------------------------------------------------------- - // The declaration order of the operations is significant in Haxe. // Recommended order is: // * MutableBigInt Int @@ -169,267 +144,251 @@ abstract MutableBigInt(MutableBigInt_) // * MutableBigInt Int // * MutableBigInt BigInt // * MutableBigInt MutableBigInt - // Unary negation - @:op(-A) @:noCompletion public static inline function negate_(a : MutableBigInt) : BigInt - { + @:op(-A) @:noCompletion public static inline function negate_(a:MutableBigInt):BigInt { return new BigInt(BigInt_.negate1(a)); } // Binary equality - @:op(A == B) @:noCompletion public static inline function eqInt_(a : MutableBigInt, b : Int) : Bool - { + @:op(A == B) @:noCompletion public static inline function eqInt_(a:MutableBigInt, b:Int):Bool { return BigInt_.equals2Int(a, b); } - @:op(A == B) @:noCompletion public static inline function eq_(a : MutableBigInt, b : BigInt) : Bool - { + + @:op(A == B) @:noCompletion public static inline function eq_(a:MutableBigInt, b:BigInt):Bool { return BigInt_.equals2(a, b); } - @:op(A == B) @:noCompletion public static inline function eqMutable_(a : MutableBigInt, b : MutableBigInt) : Bool - { + + @:op(A == B) @:noCompletion public static inline function eqMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigInt_.equals2(a, b); } // Binary inequality - @:op(A != B) @:noCompletion public static inline function ineqInt_(a : MutableBigInt, b : Int) : Bool - { + @:op(A != B) @:noCompletion public static inline function ineqInt_(a:MutableBigInt, b:Int):Bool { return !BigInt_.equals2Int(a, b); } - @:op(A != B) @:noCompletion public static inline function ineq_(a : MutableBigInt, b : BigInt) : Bool - { + + @:op(A != B) @:noCompletion public static inline function ineq_(a:MutableBigInt, b:BigInt):Bool { return !BigInt_.equals2(a, b); } - @:op(A != B) @:noCompletion public static inline function ineqMutable_(a : MutableBigInt, b : MutableBigInt) : Bool - { + + @:op(A != B) @:noCompletion public static inline function ineqMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return !BigInt_.equals2(a, b); } // Binary less than - @:op(A < B) @:noCompletion public static inline function ltInt_(a : MutableBigInt, b : Int) : Bool - { + @:op(A < B) @:noCompletion public static inline function ltInt_(a:MutableBigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) < 0; } - @:op(A < B) @:noCompletion public static inline function lt_(a : MutableBigInt, b : BigInt) : Bool - { + + @:op(A < B) @:noCompletion public static inline function lt_(a:MutableBigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) < 0; } - @:op(A < B) @:noCompletion public static inline function ltMutable_(a : MutableBigInt, b : MutableBigInt) : Bool - { + + @:op(A < B) @:noCompletion public static inline function ltMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) < 0; } // Binary less than or equal - @:op(A <= B) @:noCompletion public static inline function lteInt_(a : MutableBigInt, b : Int) : Bool - { + @:op(A <= B) @:noCompletion public static inline function lteInt_(a:MutableBigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) <= 0; } - @:op(A <= B) @:noCompletion public static inline function lte_(a : MutableBigInt, b : BigInt) : Bool - { + + @:op(A <= B) @:noCompletion public static inline function lte_(a:MutableBigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) <= 0; } - @:op(A <= B) @:noCompletion public static inline function lteMutable_(a : MutableBigInt, b : MutableBigInt) : Bool - { + + @:op(A <= B) @:noCompletion public static inline function lteMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) <= 0; } // Binary greater than - @:op(A > B) @:noCompletion public static inline function gtInt_(a : MutableBigInt, b : Int) : Bool - { + @:op(A > B) @:noCompletion public static inline function gtInt_(a:MutableBigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) > 0; } - @:op(A > B) @:noCompletion public static inline function gt_(a : MutableBigInt, b : BigInt) : Bool - { + + @:op(A > B) @:noCompletion public static inline function gt_(a:MutableBigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) > 0; } - @:op(A > B) @:noCompletion public static inline function gtMutable_(a : MutableBigInt, b : MutableBigInt) : Bool - { + + @:op(A > B) @:noCompletion public static inline function gtMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) > 0; } // Binary greater than or equal - @:op(A >= B) @:noCompletion public static inline function gteInt_(a : MutableBigInt, b : Int) : Bool - { + @:op(A >= B) @:noCompletion public static inline function gteInt_(a:MutableBigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) >= 0; } - @:op(A >= B) @:noCompletion public static inline function gte_(a : MutableBigInt, b : BigInt) : Bool - { + + @:op(A >= B) @:noCompletion public static inline function gte_(a:MutableBigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) >= 0; } - @:op(A >= B) @:noCompletion public static inline function gteMutable_(a : MutableBigInt, b : MutableBigInt) : Bool - { + + @:op(A >= B) @:noCompletion public static inline function gteMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) >= 0; } // Binary addition - @:op(A += B) @:noCompletion public static inline function addAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt - { + @:op(A += B) @:noCompletion public static inline function addAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { BigIntArithmetic.addInt(a, a, b); return a; } - @:op(A += B) @:noCompletion public static inline function addAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt - { + + @:op(A += B) @:noCompletion public static inline function addAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { BigIntArithmetic.add(a, a, b); return a; } - @:op(A += B) @:noCompletion public static inline function addAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt - { + + @:op(A += B) @:noCompletion public static inline function addAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { BigIntArithmetic.add(a, a, b); return a; } - @:op(A + B) @:noCompletion public static inline function addInt_(a : MutableBigInt, b : Int) : BigInt - { + + @:op(A + B) @:noCompletion public static inline function addInt_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.addInt2(a, b)); } - @:op(A + B) @:noCompletion public static inline function add_(a : MutableBigInt, b : BigInt) : BigInt - { + + @:op(A + B) @:noCompletion public static inline function add_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.add2(a, b)); } - @:op(A + B) @:noCompletion public static inline function addMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt - { + + @:op(A + B) @:noCompletion public static inline function addMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.add2(a, b)); } // Binary subtraction - @:op(A -= B) @:noCompletion public static inline function subAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt - { + @:op(A -= B) @:noCompletion public static inline function subAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { BigIntArithmetic.subtractInt(a, a, b); return a; } - @:op(A -= B) @:noCompletion public static inline function subAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt - { + + @:op(A -= B) @:noCompletion public static inline function subAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { BigIntArithmetic.subtract(a, a, b); return a; } - @:op(A -= B) @:noCompletion public static inline function subAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt - { + + @:op(A -= B) @:noCompletion public static inline function subAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { BigIntArithmetic.subtract(a, a, b); return a; } - @:op(A - B) @:noCompletion public static inline function subInt_(a : MutableBigInt, b : Int) : BigInt - { + + @:op(A - B) @:noCompletion public static inline function subInt_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.subInt2(a, b)); } - @:op(A - B) @:noCompletion public static inline function sub_(a : MutableBigInt, b : BigInt) : BigInt - { + + @:op(A - B) @:noCompletion public static inline function sub_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.sub2(a, b)); } - @:op(A - B) @:noCompletion public static inline function subMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt - { + + @:op(A - B) @:noCompletion public static inline function subMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.sub2(a, b)); } // Binary multiplication - @:op(A *= B) @:noCompletion public static inline function mulAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt - { + @:op(A *= B) @:noCompletion public static inline function mulAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.multiplyAssignInt2(a, b); return a; } - @:op(A *= B) @:noCompletion public static inline function mulAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt - { + + @:op(A *= B) @:noCompletion public static inline function mulAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { MutableBigInt_.multiplyAssign2(a, b); return a; } - @:op(A *= B) @:noCompletion public static inline function mulAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt - { + + @:op(A *= B) @:noCompletion public static inline function mulAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { MutableBigInt_.multiplyAssign2(a, b); return a; } - @:op(A * B) @:noCompletion public static inline function mulInt_(a : MutableBigInt, b : Int) : BigInt - { + + @:op(A * B) @:noCompletion public static inline function mulInt_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.multiplyInt2(a, b)); } - @:op(A * B) @:noCompletion public static inline function mul_(a : MutableBigInt, b : BigInt) : BigInt - { + + @:op(A * B) @:noCompletion public static inline function mul_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.multiply2(a, b)); } - @:op(A * B) @:noCompletion public static inline function mulMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt - { + + @:op(A * B) @:noCompletion public static inline function mulMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.multiply2(a, b)); } // Binary division - @:op(A /= B) @:noCompletion public static inline function divAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt - { + @:op(A /= B) @:noCompletion public static inline function divAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.divideAssignInt2(a, b); return a; } - @:op(A /= B) @:noCompletion public static inline function divAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt - { + + @:op(A /= B) @:noCompletion public static inline function divAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { MutableBigInt_.divideAssign2(a, b); return a; } - @:op(A /= B) @:noCompletion public static inline function divAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt - { + + @:op(A /= B) @:noCompletion public static inline function divAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { MutableBigInt_.divideAssign2(a, b); return a; } - @:op(A / B) @:noCompletion public static inline function divInt_(a : MutableBigInt, b : Int) : BigInt - { + + @:op(A / B) @:noCompletion public static inline function divInt_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.divideInt2(a, b)); } - @:op(A / B) @:noCompletion public static inline function div_(a : MutableBigInt, b : BigInt) : BigInt - { + + @:op(A / B) @:noCompletion public static inline function div_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.divide2(a, b)); } - @:op(A / B) @:noCompletion public static inline function divMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt - { + + @:op(A / B) @:noCompletion public static inline function divMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.divide2(a, b)); } // Binary modulus - @:op(A %= B) @:noCompletion public static inline function modAssignInt_(a : MutableBigInt, b : Int) : MutableBigInt - { + @:op(A %= B) @:noCompletion public static inline function modAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.modulusAssignInt2(a, b); return a; } - @:op(A %= B) @:noCompletion public static inline function modAssign_(a : MutableBigInt, b : BigInt) : MutableBigInt - { + + @:op(A %= B) @:noCompletion public static inline function modAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { MutableBigInt_.modulusAssign2(a, b); return a; } - @:op(A %= B) @:noCompletion public static inline function modAssignMutable_(a : MutableBigInt, b : MutableBigInt) : MutableBigInt - { + + @:op(A %= B) @:noCompletion public static inline function modAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { MutableBigInt_.modulusAssign2(a, b); return a; } - @:op(A % B) @:noCompletion public static inline function modInt_(a : MutableBigInt, b : Int) : Int - { + + @:op(A % B) @:noCompletion public static inline function modInt_(a:MutableBigInt, b:Int):Int { return BigInt_.modulusInt2(a, b); } - @:op(A % B) @:noCompletion public static inline function mod_(a : MutableBigInt, b : BigInt) : BigInt - { + + @:op(A % B) @:noCompletion public static inline function mod_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.modulus2(a, b)); } - @:op(A % B) @:noCompletion public static inline function modMutable_(a : MutableBigInt, b : MutableBigInt) : BigInt - { + + @:op(A % B) @:noCompletion public static inline function modMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.modulus2(a, b)); } // Binary AND - @:op(A & B) @:noCompletion public static inline function andInt_(a : MutableBigInt, b : Int) : Int - { + @:op(A & B) @:noCompletion public static inline function andInt_(a:MutableBigInt, b:Int):Int { return BigIntArithmetic.bitwiseAndInt(a, b); } // Binary shift left - @:op(A <<= B) @:noCompletion public static inline function arithmeticShiftLeftAssign_(a : MutableBigInt, b : Int) : MutableBigInt - { + @:op(A <<= B) @:noCompletion public static inline function arithmeticShiftLeftAssign_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.arithmeticShiftLeftAssign2(a, b); return a; } - @:op(A << B) @:noCompletion public static inline function asl_(a : MutableBigInt, b : Int) : BigInt - { + + @:op(A << B) @:noCompletion public static inline function asl_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.arithmeticShiftLeft2(a, b)); } // Binary shift right - @:op(A >>= B) @:noCompletion public static inline function arithmeticShiftRightAssign_(a : MutableBigInt, b : Int) : MutableBigInt - { + @:op(A >>= B) @:noCompletion public static inline function arithmeticShiftRightAssign_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.arithmeticShiftRightAssign2(a, b); return a; } - @:op(A >> B) @:noCompletion public static inline function asr_(a : MutableBigInt, b : Int) : BigInt - { + + @:op(A >> B) @:noCompletion public static inline function asr_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.arithmeticShiftRight2(a, b)); } @@ -437,28 +396,23 @@ abstract MutableBigInt(MutableBigInt_) // Automatic conversions //----------------------------------------------------------------------- - @:from @:noCompletion public static inline function fromInt_(a : Int) : MutableBigInt - { + @:from @:noCompletion public static inline function fromInt_(a:Int):MutableBigInt { return new MutableBigInt(MutableBigInt_.fromInt(a)); } - @:from @:noCompletion public static inline function fromBigInt_(a : BigInt_) : MutableBigInt - { + @:from @:noCompletion public static inline function fromBigInt_(a:BigInt_):MutableBigInt { return new MutableBigInt(MutableBigInt_.fromBigInt(a)); } - @:from @:noCompletion public static inline function fromMutableBigInt_(a : MutableBigInt_) : MutableBigInt - { + @:from @:noCompletion public static inline function fromMutableBigInt_(a:MutableBigInt_):MutableBigInt { return new MutableBigInt(MutableBigInt_.fromBigInt(a)); } - @:to @:noCompletion public inline function toMutableBigInt_() : MutableBigInt_ - { + @:to @:noCompletion public inline function toMutableBigInt_():MutableBigInt_ { return this; } - @:to @:noCompletion public inline function toBigInt() : BigInt - { + @:to @:noCompletion public inline function toBigInt():BigInt { return new BigInt(this); } @@ -466,8 +420,7 @@ abstract MutableBigInt(MutableBigInt_) // Private implementation //----------------------------------------------------------------------- - private inline function new(a : MutableBigInt_) - { + private inline function new(a:MutableBigInt_) { this = a; } } diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index 35e3e1b00d2..7822530427b 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -19,7 +19,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ - + package haxe.math.bigint; import haxe.math.bigint.BigIntExceptions; @@ -30,8 +30,7 @@ import haxe.io.Bytes; /* Original code courtesy Chuck Batson (github.com/cbatson) */ @:allow(unit) @:allow(haxe.math.bigint) -class MutableBigInt_ extends BigInt_ -{ +class MutableBigInt_ extends BigInt_ { //----------------------------------------------------------------------- // Public interface //----------------------------------------------------------------------- @@ -39,8 +38,7 @@ class MutableBigInt_ extends BigInt_ /** Set the value of this big int with an integer of value `value`. **/ - public function setFromInt(value : Int) : Void - { + public function setFromInt(value:Int):Void { ensureCapacity(1, false); m_data.set(0, value); m_count = 1; @@ -50,8 +48,7 @@ class MutableBigInt_ extends BigInt_ Set the value of this big integer with the signed value represented by the hexadecimal string `value`. **/ - public inline function setFromHexSigned(value : String) : Void - { + public inline function setFromHexSigned(value:String):Void { _setFromHex(value, true); } @@ -59,43 +56,34 @@ class MutableBigInt_ extends BigInt_ Set the value of this big integer with the unsigned value represented by the hexadecimal string `value`. **/ - public inline function setFromHexUnsigned(value : String) : Void - { + public inline function setFromHexUnsigned(value:String):Void { _setFromHex(value, false); } /** Set the value of this big integer with the value represented by the decimal string `value`. **/ - public function setFromString(value : String) : Void - { - if ((value == null) || (value.length < 1)) - { + public function setFromString(value:String):Void { + if ((value == null) || (value.length < 1)) { throw BigIntExceptions.INVALID_ARGUMENT; } var negate = value.charCodeAt(0) == 0x2d; var index = negate ? 1 : 0; - if (value.length <= index) - { + if (value.length <= index) { throw BigIntExceptions.INVALID_ARGUMENT; } this.setFromInt(0); var t = new MutableBigInt_(); - for (i in index ... value.length) - { + for (i in index...value.length) { var c = value.charCodeAt(i); - if ((48 <= c) && (c <= 57)) - { + if ((48 <= c) && (c <= 57)) { BigIntArithmetic.multiplyInt(t, this, 10); BigIntArithmetic.addInt(this, t, c - 48); - } - else - { + } else { throw BigIntExceptions.INVALID_ARGUMENT; } } - if (negate) - { + if (negate) { BigIntArithmetic.negate(this, this); } } @@ -104,10 +92,8 @@ class MutableBigInt_ extends BigInt_ Set the value of this big integer with the unsigned value represented by the integer vector `value`. **/ - public function setFromUnsignedInts(value : Vector, length : Int = 0) : Void - { - if (length <= 0) - { + public function setFromUnsignedInts(value:Vector, length:Int = 0):Void { + if (length <= 0) { length = value.length; } var neg = value.get(length - 1) >>> 31; @@ -117,10 +103,9 @@ class MutableBigInt_ extends BigInt_ m_count = length + neg; compact(); } - - public function setFromBigEndianBytesSigned(value:Bytes, offset:Int = 0, valueLength:Int = 0):Void - { - if ( value == null) { + + public function setFromBigEndianBytesSigned(value:Bytes, offset:Int = 0, valueLength:Int = 0):Void { + if (value == null) { throw BigIntExceptions.INVALID_ARGUMENT; } if (valueLength <= 0) { @@ -153,18 +138,14 @@ class MutableBigInt_ extends BigInt_ compact(); } - public function setFromBigEndianBytesUnsigned(value : Bytes, offset : Int = 0, valueLength : Int = 0) : Void - { - if (valueLength <= 0) - { + public function setFromBigEndianBytesUnsigned(value:Bytes, offset:Int = 0, valueLength:Int = 0):Void { + if (valueLength <= 0) { valueLength = value.length; } - if (offset + valueLength > value.length) - { + if (offset + valueLength > value.length) { throw BigIntExceptions.BUFFER_TOO_SMALL; } - if (valueLength < 1) - { + if (valueLength < 1) { setFromInt(0); return; } @@ -174,20 +155,13 @@ class MutableBigInt_ extends BigInt_ m_data.set(length + neg - 1, 0); var pos = 0; var i = offset + valueLength; - while (i >= offset + 4) - { - m_data.set(pos++, - (value.get(i - 1) << 0) | - (value.get(i - 2) << 8) | - (value.get(i - 3) << 16) | - (value.get(i - 4) << 24)); + while (i >= offset + 4) { + m_data.set(pos++, (value.get(i - 1) << 0) | (value.get(i - 2) << 8) | (value.get(i - 3) << 16) | (value.get(i - 4) << 24)); i -= 4; } - if (i > offset) - { - var x : Int = 0; - for (j in offset ... i) - { + if (i > offset) { + var x:Int = 0; + for (j in offset...i) { x = (x << 8) | value.get(j); } m_data.set(pos++, x); @@ -196,18 +170,14 @@ class MutableBigInt_ extends BigInt_ compact(); } - public function setFromLittleEndianBytesUnsigned(value : Bytes, offset : Int = 0, valueLength : Int = 0) : Void - { - if (valueLength <= 0) - { + public function setFromLittleEndianBytesUnsigned(value:Bytes, offset:Int = 0, valueLength:Int = 0):Void { + if (valueLength <= 0) { valueLength = value.length; } - if (offset + valueLength > value.length) - { + if (offset + valueLength > value.length) { throw BigIntExceptions.BUFFER_TOO_SMALL; } - if (valueLength < 1) - { + if (valueLength < 1) { setFromInt(0); return; } @@ -217,20 +187,13 @@ class MutableBigInt_ extends BigInt_ m_data.set(length + neg - 1, 0); var pos = 0; var i = offset; - while (i <= offset + valueLength - 4) - { - m_data.set(pos++, - (value.get(i + 0) << 0) | - (value.get(i + 1) << 8) | - (value.get(i + 2) << 16) | - (value.get(i + 3) << 24)); + while (i <= offset + valueLength - 4) { + m_data.set(pos++, (value.get(i + 0) << 0) | (value.get(i + 1) << 8) | (value.get(i + 2) << 16) | (value.get(i + 3) << 24)); i += 4; } - if (i < offset + valueLength) - { - var x : Int = 0; - for (j in i ... offset + valueLength) - { + if (i < offset + valueLength) { + var x:Int = 0; + for (j in i...offset + valueLength) { x |= value.get(j) << ((j - i) << 3); } m_data.set(pos++, x); @@ -239,8 +202,7 @@ class MutableBigInt_ extends BigInt_ compact(); } - public function clear() : Void - { + public function clear():Void { MultiwordArithmetic.setZero(m_data, m_data.length); m_count = 1; } @@ -249,32 +211,25 @@ class MutableBigInt_ extends BigInt_ Copy the value from big integer `other` into this big integer. **/ - private function copyFrom(other : BigInt_) : Void - { - if (other != this) - { + private function copyFrom(other:BigInt_):Void { + if (other != this) { ensureCapacity(other.m_count, false); - for (i in 0 ... other.m_count) - { + for (i in 0...other.m_count) { m_data.set(i, other.m_data.get(i)); } m_count = other.m_count; } } - - private function fixedSizeCopyFrom(other:BigInt_, size:Int, value:Int = 0):Void - { - if (other != this) - { + + private function fixedSizeCopyFrom(other:BigInt_, size:Int, value:Int = 0):Void { + if (other != this) { ensureCapacity(size, false); var maxSize:Int = (size > other.m_count) ? other.m_count : size; - for (i in 0...maxSize) - { + for (i in 0...maxSize) { m_data.set(i, other.m_data.get(i)); } var diffSize = size - maxSize; - while (diffSize > 0) - { + while (diffSize > 0) { m_data.set(maxSize++, value); diffSize--; } @@ -286,100 +241,79 @@ class MutableBigInt_ extends BigInt_ // Private implementation //----------------------------------------------------------------------- - private inline function setShort(n : Int32, v : Int32) : Void - { - var s : Int = (n & 1) << 4; - var t : Int = m_data.get(n >> 1) & (~0xffff >>> s); + private inline function setShort(n:Int32, v:Int32):Void { + var s:Int = (n & 1) << 4; + var t:Int = m_data.get(n >> 1) & (~0xffff >>> s); m_data.set(n >> 1, t | ((v & 0xffff) << s)); } - private function copy(other : MutableBigInt_) : Void - { + private function copy(other:MutableBigInt_):Void { this.m_data = other.m_data; this.m_count = other.m_count; this.m_owned = other.m_owned; } - private inline function ensureCapacity(n : Int, preserve : Bool) : Void - { + private inline function ensureCapacity(n:Int, preserve:Bool):Void { #if debug - if (s_testAllocation) - { - ensureCapacityDebug(n, preserve); - return; - } + if (s_testAllocation) { + ensureCapacityDebug(n, preserve); + return; + } #end ensureCapacityProd(n, preserve); } @:noCompletion - private function ensureCapacityDebug(n : Int, preserve : Bool) : Void - { + private function ensureCapacityDebug(n:Int, preserve:Bool):Void { // always allocate the minimum amount necessary, to catch // bounds edge cases as well as use of stale buffer data - if (preserve && (m_data != null) && (m_count > 0)) - { + if (preserve && (m_data != null) && (m_count > 0)) { n = (m_count > n) ? m_count : n; n += s_debugAllocationPadding; var newData = new Vector(n); - for (i in 0 ... m_count) - { + for (i in 0...m_count) { newData.set(i, m_data.get(i)); } - for (i in m_count ... n) - { + for (i in m_count...n) { newData.set(i, 0xdeadbeef); } m_data = newData; - } - else - { + } else { n += s_debugAllocationPadding; m_data = new Vector(n); - for (i in 0 ... n) - { + for (i in 0...n) { m_data.set(i, 0xdeadbeef); } } } @:noCompletion - private function ensureCapacityProd(n : Int, preserve : Bool) : Void - { - if (n < 1) - { + private function ensureCapacityProd(n:Int, preserve:Bool):Void { + if (n < 1) { throw BigIntExceptions.INVALID_ARGUMENT; } - if ((!m_owned) || (m_data == null) || (n > m_data.length)) - { + if ((!m_owned) || (m_data == null) || (n > m_data.length)) { n = BigIntHelper.clp2(n); - if (preserve && (m_data != null)) - { + if (preserve && (m_data != null)) { var newData = new Vector(n); - for (i in 0 ... m_count) - { + for (i in 0...m_count) { newData.set(i, m_data.get(i)); } m_data = newData; - } - else - { + } else { m_data = new Vector(n); } } m_owned = true; } - private function new() - { + private function new() { super(); } - private static function fromInt(other : Int) : MutableBigInt_ - { + private static function fromInt(other:Int):MutableBigInt_ { var c = BigInt_.getCachedValue(other); - if (c != null) - { + if (c != null) { return fromBigInt(c); } var r = new MutableBigInt_(); @@ -389,65 +323,50 @@ class MutableBigInt_ extends BigInt_ return r; } - private static function fromBigInt(other : BigInt_) : MutableBigInt_ - { + private static function fromBigInt(other:BigInt_):MutableBigInt_ { // TODO: this will be problematic if `other` is actually a MutableBigInt_ - var r = new MutableBigInt_(); // unowned + var r = new MutableBigInt_(); // unowned r.m_data = other.m_data; r.m_count = other.m_count; return r; } - private var m_owned : Bool = false; + private var m_owned:Bool = false; - private static var s_testAllocation : Bool = false; - private static var s_debugAllocationPadding : Int = 0; + private static var s_testAllocation:Bool = false; + private static var s_debugAllocationPadding:Int = 0; //----------------------------------------------------------------------- // Static helpers //----------------------------------------------------------------------- - private function _setFromHex(value : String, signed : Bool) : Void - { - if (value == null) - { + private function _setFromHex(value:String, signed:Bool):Void { + if (value == null) { throw BigIntExceptions.INVALID_ARGUMENT; } var index = value.length; - if (index <= 0) - { + if (index <= 0) { throw BigIntExceptions.INVALID_ARGUMENT; } - var extra : Int = signed ? 0 : 1; + var extra:Int = signed ? 0 : 1; ensureCapacity(((index + 7) >> 3) + extra, false); var pos = -1; - var bit : Int = 32; - var c : Int32 = 0; - while (index > 0) - { + var bit:Int = 32; + var c:Int32 = 0; + while (index > 0) { c = value.charCodeAt(--index); - if ((48 <= c) && (c <= 57)) - { + if ((48 <= c) && (c <= 57)) { c -= 48; - } - else if ((65 <= c) && (c <= 70)) - { + } else if ((65 <= c) && (c <= 70)) { c -= 55; - } - else if ((97 <= c) && (c <= 102)) - { + } else if ((97 <= c) && (c <= 102)) { c -= 87; - } - else if (c == 32) - { + } else if (c == 32) { continue; - } - else - { + } else { throw BigIntExceptions.INVALID_ARGUMENT; } - if (bit >= 32) - { + if (bit >= 32) { m_data.set(++pos, 0); bit = 0; } @@ -456,65 +375,55 @@ class MutableBigInt_ extends BigInt_ } // Sign extend m_count = pos + 1; - if (signed) - { + if (signed) { c = ((c & 8) != 0) ? 15 : 0; - while (bit < 32) - { + while (bit < 32) { m_data.set(pos, m_data.get(pos) | (c << bit)); bit += 4; } - } - else if (m_data.get(pos) < 0) - { + } else if (m_data.get(pos) < 0) { m_data.set(m_count++, 0); } compact(); } @:noCompletion - private static inline function multiplyAssignInt2(a : MutableBigInt_, b : Int) : Void - { + private static inline function multiplyAssignInt2(a:MutableBigInt_, b:Int):Void { var r = new MutableBigInt_(); BigIntArithmetic.multiplyInt(r, a, b); a.copy(r); } @:noCompletion - private static inline function multiplyAssign2(a : MutableBigInt_, b : BigInt_) : Void - { + private static inline function multiplyAssign2(a:MutableBigInt_, b:BigInt_):Void { var r = new MutableBigInt_(); BigIntArithmetic.multiply(r, a, b); a.copy(r); } @:noCompletion - private static inline function divideAssignInt2(a : MutableBigInt_, b : Int) : Void - { + private static inline function divideAssignInt2(a:MutableBigInt_, b:Int):Void { var q = new MutableBigInt_(); BigIntArithmetic.divideInt(a, b, q); a.copy(q); } @:noCompletion - private static inline function divideAssign2(a : MutableBigInt_, b : BigInt_) : Void - { + private static inline function divideAssign2(a:MutableBigInt_, b:BigInt_):Void { var q = new MutableBigInt_(); BigIntArithmetic.divide(a, b, q, null); a.copy(q); } @:noCompletion - private static inline function modulusAssignInt2(a : MutableBigInt_, b : Int) : Void - { + private static inline function modulusAssignInt2(a:MutableBigInt_, b:Int):Void { var q = new MutableBigInt_(); var r = BigIntArithmetic.divideInt(a, b, q); a.setFromInt(r); } @:noCompletion - private static inline function modulusAssign2(a : MutableBigInt_, b : BigInt_) : Void - { + private static inline function modulusAssign2(a:MutableBigInt_, b:BigInt_):Void { var q = new MutableBigInt_(); var r = new MutableBigInt_(); BigIntArithmetic.divide(a, b, q, r); @@ -522,14 +431,12 @@ class MutableBigInt_ extends BigInt_ } @:noCompletion - private static inline function arithmeticShiftLeftAssign2(a : MutableBigInt_, b : Int) : Void - { + private static inline function arithmeticShiftLeftAssign2(a:MutableBigInt_, b:Int):Void { BigIntArithmetic.arithmeticShiftLeft(a, a, b); } @:noCompletion - private static inline function arithmeticShiftRightAssign2(a : MutableBigInt_, b : Int) : Void - { + private static inline function arithmeticShiftRightAssign2(a:MutableBigInt_, b:Int):Void { BigIntArithmetic.arithmeticShiftRight(a, a, b); } } From 5fa6c53fc07c37b0d9d858ae9c51aadc930a2796 Mon Sep 17 00:00:00 2001 From: flashultra Date: Wed, 1 Mar 2023 21:21:02 +0200 Subject: [PATCH 060/134] Add missing tests --- tests/unit/src/unit/TestBigInt.hx | 110 +++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 3 deletions(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 83b7fb294e1..de53be29647 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2817,9 +2817,9 @@ class TestBigInt extends Test { } } - public function testModInverse():Void + public function testModInverse():Void { - var m:Array = [ "2885628006", "3452672361", "2693781441", "3446368347", "1495928706" , "3144152002", "1680946273"]; + var m:Array = [ "2885628006", "3452672361", "2693781441", "3446368347", "1495928706" , "3144152002", "1680946273","-9223372036854775808","-8192","-2147483648"]; var n:Array = [ "898595849", "2540385371", "1304452195", "2448267533", "2053023521", "4287024253", "1920144361", "504475217", "887965291", "300193913", "2394418165" ]; var mn:Array = ["681936597","980871030","323007506","112883568","683798641","1331447622","1514136460","438360889","585723972","102755466","818276521", "565144203","2230262406","55288816","1361792736","293899217","244543810","1508822196","237344825","670834209","151186306","1741057836", @@ -2827,7 +2827,10 @@ class TestBigInt extends Test { "500716917","910017586","666455683","1268170143","751080606","3325520905","1230560432","124770931","580887745","121788521","1422101743", "858074026","791210169","823419966","1678016129","1682774644","1196897481","244305979","462331726","867267019","166516939","1303195691", "712131840","2106472611","967422418","273950480","1682853299","4248168436","1597159081","254025827","233894683","63539412","736767788", - "279559525","387786944","1228135902","494650428","146720719","1425245481","1438770027","120084998","310304596","244283899","1212900932"]; + "279559525","387786944","1228135902","494650428","146720719","1425245481","1438770027","120084998","310304596","244283899","1212900932", + "493541265","1302212172","774141982","2347206816","1101394049","2159509590","1432890654","292669872","867212529","222172747","2347398892", + "386883247","331502925","1088688923","170649507","200239965","2567923341","699193192","83689187","270226742","133350299","1768630898", + "530941007","522306373","1263806667","20481954","1522248974","3285124637","954156434","247829081","734364965","178328821","1058287987"]; var pos = 0; for(i in 0...m.length) { @@ -2897,6 +2900,107 @@ class TestBigInt extends Test { t(b.testBit(200)); f(b.testBit(12345)); t(b.testBit(12347)); + var nb:BigInt = "-57406576"; + t(nb.testBit(350)); + nb = "57406576"; + f(nb.testBit(350)); + } + + public function testSetBit():Void + { + var b:BigInt = 0; + eq("1024",b.setBit(10).toString()); + b = "51929243614239128348340"; + eq("51929243614239136736948",b.setBit(23).toString()); + b = "-39972617095"; + eq("-39972617095",b.setBit(68).toString()); + } + + public function testClearBit():Void + { + var b:BigInt = 0; + eq("0",b.clearBit(10).toString()); + b = "51929243614239128348340"; + eq("51929243614236980864692",b.clearBit(31).toString()); + b = "-39972617095"; + eq("-295147905219325442951",b.clearBit(68).toString()); + } + + public function testFlipBit():Void + { + var b:BigInt ="-4611686018427387904"; + eq("-4611686016279904256",b.flipBit(31).toString()); + b = "-4611686018427387904"; + eq("-13835058055282163712",b.flipBit(63).toString()); + b = "-9223372036854775808"; + eq("-18446744073709551616",b.flipBit(63).toString()); + } + + public function testGetPowerOfTwo():Void + { + for (i in 0...96) { + eq(s_powersOfTwo[i], BigInt.getPowerOfTwo(i).toString()); + } + eq(s_powersOfTwo[96], BigInt.getPowerOfTwo(128).toString()); + eq(s_powersOfTwo[97], BigInt.getPowerOfTwo(256).toString()); + eq(s_powersOfTwo[98], BigInt.getPowerOfTwo(512).toString()); + } + + public function testStringConversion():Void + { + var b:BigInt ="-4611686018427387904"; + eq("-4611686018427387904",b); + eq("-46116860184273879041",(b+"1")); + b = "9876543210"; + eq("29876543210",("2"+b)); + } + + public function testDivMod():Void + { + var b:BigInt = BigInt.random(48); + var result = BigInt.divMod(b,b); + eq("1",result.quotient); + eq("0",result.remainder); + result = BigInt.divMod(b,1); + eq(b.toString(),result.quotient); + eq("0",result.remainder); + for(i in 0...10) { + var a:BigInt = BigInt.random(100-i).abs(); + var b:BigInt = BigInt.random(100+i).abs(); + var c:BigInt = BigInt.random(10+i).abs(); + var d:BigInt = (a*b)+c; + var result = BigInt.divMod(d,a); + eq(result.quotient.toString(),b.toString()); + eq(result.remainder.toString(),c.toString()); + } + } + + public function testHashCode():Void + { + var b:BigInt = "248576108700009"; + eq(845966795,b.hashCode()); + b = "101096178448040"; + eq(-269403574,b.hashCode()); + b = "1194923254814264634767542811261"; + eq(1465720594,b.hashCode()); + b = "2568876284867254520019857975684381983699779161674564743775191726214883120720241149248282662729370472124792889942528657175"; + eq(965626026,b.hashCode()); + } + + public function testBitwiseOperations():Void + { + var a:BigInt = "-4611686016279904256"; + var b:BigInt = "4611686023796097025"; + var result = a & b; + eq("4611686018427387904",result.toString()); + result = a | b; + eq("-4611686010911195135",result.toString()); + result = a ^ b; + eq("-9223372029338583039",result.toString()); + result = ~a; + eq("4611686016279904255",result.toString()); + result = ~b; + eq("-4611686023796097026",result.toString()); } public function testSquare():Void From b7626bc6ab2fe36c8ce30347d2e5652f6af4456d Mon Sep 17 00:00:00 2001 From: flashultra Date: Wed, 1 Mar 2023 22:10:05 +0200 Subject: [PATCH 061/134] Temp fix for BigIntException --- std/haxe/math/bigint/BigIntExceptions.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/haxe/math/bigint/BigIntExceptions.hx b/std/haxe/math/bigint/BigIntExceptions.hx index 03b1d9361b7..24677898dd4 100644 --- a/std/haxe/math/bigint/BigIntExceptions.hx +++ b/std/haxe/math/bigint/BigIntExceptions.hx @@ -23,7 +23,7 @@ package haxe.math.bigint; /* Original code courtesy Chuck Batson (github.com/cbatson) */ -enum abstract BigIntExceptions(String) { +enum abstract BigIntExceptions(String) to String { var INVALID_ARGUMENT = "Invalid argument"; var BUFFER_TOO_SMALL = "Buffer too small"; var DIVISION_BY_ZERO = "Division by zero"; @@ -31,4 +31,4 @@ enum abstract BigIntExceptions(String) { var INVALID_OPERATION = "Invalid operation"; var NEGATIVE_MODULUS = "Modulus should be positive"; var EVEN_VALUES = "Both values are even"; -} +} \ No newline at end of file From f9417ea4932d864df8da1f7704a7810124217ef3 Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 2 Mar 2023 10:10:19 +0200 Subject: [PATCH 062/134] Fix for BigIntExceptions --- std/haxe/math/bigint/BigIntExceptions.hx | 2 +- tests/unit/src/unit/TestBigInt.hx | 148 +++++++++++------------ 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/std/haxe/math/bigint/BigIntExceptions.hx b/std/haxe/math/bigint/BigIntExceptions.hx index 24677898dd4..bddfc94855d 100644 --- a/std/haxe/math/bigint/BigIntExceptions.hx +++ b/std/haxe/math/bigint/BigIntExceptions.hx @@ -23,7 +23,7 @@ package haxe.math.bigint; /* Original code courtesy Chuck Batson (github.com/cbatson) */ -enum abstract BigIntExceptions(String) to String { +enum abstract BigIntExceptions(String) { var INVALID_ARGUMENT = "Invalid argument"; var BUFFER_TOO_SMALL = "Buffer too small"; var DIVISION_BY_ZERO = "Division by zero"; diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index de53be29647..0a3414e956d 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -61,7 +61,7 @@ class TestBigInt extends Test { var remainder:MutableBigInt = 0; try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } eq("00000000", dividend.toHex()); @@ -390,23 +390,23 @@ class TestBigInt extends Test { var a:MutableBigInt = 2; try { BigIntArithmetic.multiply(a, a, BigInt.fromInt(2)); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { BigIntArithmetic.multiply(a, BigInt.fromInt(2), a); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } // division by zero should throw exception try { BigInt.fromInt(1) / 0; - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.DIVISION_BY_ZERO, e); } try { BigInt.fromInt(0) / 0; - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.DIVISION_BY_ZERO, e); } @@ -544,19 +544,19 @@ class TestBigInt extends Test { // quotient and remainder cannot be the same object try { BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), quotient, quotient); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } // quotient cannot be null try { BigIntArithmetic.divideInt(BigInt.fromInt(1), 10, null); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), null, remainder); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -573,22 +573,22 @@ class TestBigInt extends Test { // work may not overlap any input try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, divisor); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, quotient); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, remainder); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } } @@ -952,27 +952,27 @@ class TestBigInt extends Test { public function bigIntFromString():Void { try { var x = BigInt.fromString(null); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { var x = BigInt.fromString(""); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { var x = BigInt.fromString("-"); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { var x = BigInt.fromString(" 0"); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { var x = BigInt.fromString("0 "); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1000,7 +1000,7 @@ class TestBigInt extends Test { { try { var x = BigInt.fromBytes(null); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } eq("0", BigInt.fromBytes(Bytes.ofHex("00")).toString()); @@ -1038,17 +1038,17 @@ class TestBigInt extends Test { var a:MutableBigInt = BigInt.ZERO; try { a <<= -1; - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { a << -1; - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { BigInt.ONE << -1; - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1122,17 +1122,17 @@ class TestBigInt extends Test { try { var x = BigInt.fromHex(null); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { var x = BigInt.fromHex(""); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { var x = BigInt.fromHex("0q0"); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1265,30 +1265,30 @@ class TestBigInt extends Test { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 1); try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1325,30 +1325,30 @@ class TestBigInt extends Test { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 1); try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1417,22 +1417,22 @@ class TestBigInt extends Test { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 2); try { MultiwordArithmetic.subtract(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } } @@ -1463,23 +1463,23 @@ class TestBigInt extends Test { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 2); try { MultiwordArithmetic.add(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } } @@ -1636,27 +1636,27 @@ class TestBigInt extends Test { try { MultiwordArithmetic.setFromHexUnsigned(value, 1, null); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.setFromHexUnsigned(value, 1, ""); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.setFromHexUnsigned(null, 1, "0"); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.setFromHexUnsigned(value, 2, "0"); // buffer too small - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.setFromHexUnsigned(value, 1, "0g0"); // invalid char - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1707,18 +1707,18 @@ class TestBigInt extends Test { result = fromInt(2, 4); try { MultiwordArithmetic.multiplyUnsigned(result, result, 1, fromInt(2), 1); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.multiplyUnsigned(result, fromInt(2), 1, result, 1); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.multiplyIntUnsigned(result, result, 1, 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1731,29 +1731,29 @@ class TestBigInt extends Test { // check for result length too short try { MultiwordArithmetic.multiplyUnsigned(fromInt(0), fromInt(2), 1, fromInt(2), 1); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0), fromInt(2), 1, 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } // check input lengths try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 0, fromInt(2), 1); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 1, fromInt(2), 0); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 2), fromInt(2), 0, 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1761,17 +1761,17 @@ class TestBigInt extends Test { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 2), 2, fromInt(2, 2), 2); try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 1), 2, fromInt(2, 2), 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 2), 2, fromInt(2, 1), 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 4), fromInt(2, 1), 2, 2); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } } @@ -1915,32 +1915,32 @@ class TestBigInt extends Test { // quotient and remainder cannot be the same object try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, quotient, work); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } // quotient cannot be null try { MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, null, work); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, null, remainder, work); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } // work cannot be null try { MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, quotient, null); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, remainder, null); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1957,23 +1957,23 @@ class TestBigInt extends Test { // work may not overlap any input try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, dividend); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, divisor); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, quotient); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, remainder); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } @@ -1981,36 +1981,36 @@ class TestBigInt extends Test { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, work); try { MultiwordArithmetic.divideUnsigned(dividend, 0, divisor, divisor.length, quotient, remainder, work); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, 0, quotient, remainder, work); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, new Vector(0), remainder, work); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } // division by zero try { MultiwordArithmetic.divideIntUnsigned(dividend, dividend.length, 0, quotient, work); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.DIVISION_BY_ZERO, e); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromInt(0), 1, quotient, remainder, work); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.DIVISION_BY_ZERO, e); } // divisor with leading 0 try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromHex("1", 2), 2, quotient, remainder, work); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } } @@ -2812,7 +2812,7 @@ class TestBigInt extends Test { b = "604462909807314587353088"; try { randomBigInt = BigInt.randomInRange(a,b); - } catch (e:String) { + } catch (e) { eq(BigIntExceptions.INVALID_ARGUMENT, e); } } From 3ab653855eae9753c916bcebe5ad274610477bb4 Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 2 Mar 2023 14:30:18 +0200 Subject: [PATCH 063/134] Fix BigIntExceptions test --- tests/unit/src/unit/TestBigInt.hx | 148 +++++++++++++++--------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 0a3414e956d..e12c556973d 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -62,7 +62,7 @@ class TestBigInt extends Test { try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } eq("00000000", dividend.toHex()); } @@ -391,23 +391,23 @@ class TestBigInt extends Test { try { BigIntArithmetic.multiply(a, a, BigInt.fromInt(2)); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { BigIntArithmetic.multiply(a, BigInt.fromInt(2), a); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // division by zero should throw exception try { BigInt.fromInt(1) / 0; } catch (e) { - eq(BigIntExceptions.DIVISION_BY_ZERO, e); + eq(cast BigIntExceptions.DIVISION_BY_ZERO, e.message); } try { BigInt.fromInt(0) / 0; } catch (e) { - eq(BigIntExceptions.DIVISION_BY_ZERO, e); + eq(cast BigIntExceptions.DIVISION_BY_ZERO, e.message); } // Multiplication of same inputs is ok @@ -545,19 +545,19 @@ class TestBigInt extends Test { try { BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), quotient, quotient); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // quotient cannot be null try { BigIntArithmetic.divideInt(BigInt.fromInt(1), 10, null); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), null, remainder); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // remainder can be null @@ -574,22 +574,22 @@ class TestBigInt extends Test { try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, divisor); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, quotient); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, remainder); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } } @@ -953,27 +953,27 @@ class TestBigInt extends Test { try { var x = BigInt.fromString(null); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { var x = BigInt.fromString(""); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { var x = BigInt.fromString("-"); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { var x = BigInt.fromString(" 0"); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { var x = BigInt.fromString("0 "); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } eq("0", BigInt.fromString("0").toString()); @@ -1001,7 +1001,7 @@ class TestBigInt extends Test { try { var x = BigInt.fromBytes(null); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } eq("0", BigInt.fromBytes(Bytes.ofHex("00")).toString()); eq("1", BigInt.fromBytes(Bytes.ofHex("01")).toString()); @@ -1039,17 +1039,17 @@ class TestBigInt extends Test { try { a <<= -1; } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { a << -1; } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { BigInt.ONE << -1; } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } asl(BigInt.ONE, 1, BigInt.fromInt(2)); @@ -1123,17 +1123,17 @@ class TestBigInt extends Test { try { var x = BigInt.fromHex(null); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { var x = BigInt.fromHex(""); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { var x = BigInt.fromHex("0q0"); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } var sb = new StringBuf(); @@ -1266,30 +1266,30 @@ class TestBigInt extends Test { try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // result and input overlap @@ -1326,30 +1326,30 @@ class TestBigInt extends Test { try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // result and input overlap @@ -1418,22 +1418,22 @@ class TestBigInt extends Test { try { MultiwordArithmetic.subtract(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } } @@ -1464,23 +1464,23 @@ class TestBigInt extends Test { try { MultiwordArithmetic.add(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } } @@ -1637,27 +1637,27 @@ class TestBigInt extends Test { try { MultiwordArithmetic.setFromHexUnsigned(value, 1, null); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.setFromHexUnsigned(value, 1, ""); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.setFromHexUnsigned(null, 1, "0"); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.setFromHexUnsigned(value, 2, "0"); // buffer too small } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.setFromHexUnsigned(value, 1, "0g0"); // invalid char } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } value = new Vector(3); @@ -1708,18 +1708,18 @@ class TestBigInt extends Test { try { MultiwordArithmetic.multiplyUnsigned(result, result, 1, fromInt(2), 1); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.multiplyUnsigned(result, fromInt(2), 1, result, 1); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.multiplyIntUnsigned(result, result, 1, 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // Multiplication of same inputs is ok @@ -1732,29 +1732,29 @@ class TestBigInt extends Test { try { MultiwordArithmetic.multiplyUnsigned(fromInt(0), fromInt(2), 1, fromInt(2), 1); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0), fromInt(2), 1, 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // check input lengths try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 0, fromInt(2), 1); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 1, fromInt(2), 0); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 2), fromInt(2), 0, 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // check input bounds @@ -1762,17 +1762,17 @@ class TestBigInt extends Test { try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 1), 2, fromInt(2, 2), 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 2), 2, fromInt(2, 1), 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 4), fromInt(2, 1), 2, 2); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } } @@ -1916,32 +1916,32 @@ class TestBigInt extends Test { try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, quotient, work); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // quotient cannot be null try { MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, null, work); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, null, remainder, work); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // work cannot be null try { MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, quotient, null); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, remainder, null); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // remainder can be null @@ -1958,23 +1958,23 @@ class TestBigInt extends Test { try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, dividend); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, divisor); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, quotient); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, remainder); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // bounds @@ -1982,36 +1982,36 @@ class TestBigInt extends Test { try { MultiwordArithmetic.divideUnsigned(dividend, 0, divisor, divisor.length, quotient, remainder, work); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, 0, quotient, remainder, work); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, new Vector(0), remainder, work); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } // division by zero try { MultiwordArithmetic.divideIntUnsigned(dividend, dividend.length, 0, quotient, work); } catch (e) { - eq(BigIntExceptions.DIVISION_BY_ZERO, e); + eq(cast BigIntExceptions.DIVISION_BY_ZERO, e.message); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromInt(0), 1, quotient, remainder, work); } catch (e) { - eq(BigIntExceptions.DIVISION_BY_ZERO, e); + eq(cast BigIntExceptions.DIVISION_BY_ZERO, e.message); } // divisor with leading 0 try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromHex("1", 2), 2, quotient, remainder, work); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } } @@ -2813,7 +2813,7 @@ class TestBigInt extends Test { try { randomBigInt = BigInt.randomInRange(a,b); } catch (e) { - eq(BigIntExceptions.INVALID_ARGUMENT, e); + eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); } } From 3b87a7e3e614adc549ae8e72ad0650454e105d81 Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 2 Mar 2023 14:52:19 +0200 Subject: [PATCH 064/134] Fix tests for String conversion --- tests/unit/src/unit/TestBigInt.hx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index e12c556973d..64ff2c70483 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2949,7 +2949,7 @@ class TestBigInt extends Test { public function testStringConversion():Void { var b:BigInt ="-4611686018427387904"; - eq("-4611686018427387904",b); + eq("-4611686018427387904",b+""); eq("-46116860184273879041",(b+"1")); b = "9876543210"; eq("29876543210",("2"+b)); @@ -2959,11 +2959,11 @@ class TestBigInt extends Test { { var b:BigInt = BigInt.random(48); var result = BigInt.divMod(b,b); - eq("1",result.quotient); - eq("0",result.remainder); + eq("1",result.quotient.toString()); + eq("0",result.remainder.toString()); result = BigInt.divMod(b,1); - eq(b.toString(),result.quotient); - eq("0",result.remainder); + eq(b.toString(),result.quotient.toString()); + eq("0",result.remainder.toString()); for(i in 0...10) { var a:BigInt = BigInt.random(100-i).abs(); var b:BigInt = BigInt.random(100+i).abs(); From 1245ce82a32e05e2a651affc207b8a2154d74125 Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 2 Mar 2023 20:38:47 +0200 Subject: [PATCH 065/134] Temp fix for flipBit (python) --- std/haxe/math/bigint/BigInt_.hx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 4736f09d8fc..5fba3839587 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -163,7 +163,16 @@ class BigInt_ { r.fixedSizeCopyFrom(this, m_count, 0); } } + #if (python || php) + // Temp fix for issues #10995 + if ( changeBit == 31) { + r.m_data.set(chunk - 1, r.m_data.get(chunk - 1) ^ (1 << 31)); + } else { + r.m_data.set(chunk - 1, r.m_data.get(chunk - 1) ^ (1 << changeBit)); + } + #else r.m_data.set(chunk - 1, r.m_data.get(chunk - 1) ^ (1 << changeBit)); + #end r.compact(); return r; } From 704100c4a8c57ed417dfc3c2bcf688dae77ca15b Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 4 Mar 2023 20:11:01 +0200 Subject: [PATCH 066/134] Add @:noDoc and @:noCompletion .Fix for BigIntException and tests --- std/haxe/math/bigint/BigInt.hx | 102 ++++++++-------- std/haxe/math/bigint/BigIntExceptions.hx | 4 +- std/haxe/math/bigint/BigInt_.hx | 4 +- std/haxe/math/bigint/MutableBigInt.hx | 120 +++++++++--------- std/haxe/math/bigint/MutableBigInt_.hx | 4 +- tests/unit/src/unit/TestBigInt.hx | 148 +++++++++++------------ 6 files changed, 193 insertions(+), 189 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index f3e1ce1fde2..3e07bf14ffa 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2022 Haxe Foundation + * Copyright (C)2005-2023 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -219,199 +219,199 @@ abstract BigInt(BigInt_) { // * BigInt BigInt // * BigInt MutableBigInt // Unary negation - @:op(-A) @:noCompletion public static inline function negate_(a:BigInt):BigInt { + @:op(-A) @:noCompletion @:noDoc public static inline function negate_(a:BigInt):BigInt { return new BigInt(BigInt_.negate1(a)); } // Binary equality - @:op(A == B) @:noCompletion public static inline function eqInt_(a:BigInt, b:Int):Bool { + @:op(A == B) @:noCompletion @:noDoc public static inline function eqInt_(a:BigInt, b:Int):Bool { return BigInt_.equals2Int(a, b); } - @:op(A == B) @:noCompletion public static inline function eq_(a:BigInt, b:BigInt):Bool { + @:op(A == B) @:noCompletion @:noDoc public static inline function eq_(a:BigInt, b:BigInt):Bool { return BigInt_.equals2(a, b); } - @:op(A == B) @:noCompletion public static inline function eqMutable_(a:BigInt, b:MutableBigInt):Bool { + @:op(A == B) @:noCompletion @:noDoc public static inline function eqMutable_(a:BigInt, b:MutableBigInt):Bool { return BigInt_.equals2(a, b); } // Binary inequality - @:op(A != B) @:noCompletion public static inline function ineqInt_(a:BigInt, b:Int):Bool { + @:op(A != B) @:noCompletion @:noDoc public static inline function ineqInt_(a:BigInt, b:Int):Bool { return !BigInt_.equals2Int(a, b); } - @:op(A != B) @:noCompletion public static inline function ineq_(a:BigInt, b:BigInt):Bool { + @:op(A != B) @:noCompletion @:noDoc public static inline function ineq_(a:BigInt, b:BigInt):Bool { return !BigInt_.equals2(a, b); } - @:op(A != B) @:noCompletion public static inline function ineqMutable_(a:BigInt, b:MutableBigInt):Bool { + @:op(A != B) @:noCompletion @:noDoc public static inline function ineqMutable_(a:BigInt, b:MutableBigInt):Bool { return !BigInt_.equals2(a, b); } // Binary less than - @:op(A < B) @:noCompletion public static inline function ltInt_(a:BigInt, b:Int):Bool { + @:op(A < B) @:noCompletion @:noDoc public static inline function ltInt_(a:BigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) < 0; } - @:op(A < B) @:noCompletion public static inline function lt_(a:BigInt, b:BigInt):Bool { + @:op(A < B) @:noCompletion @:noDoc public static inline function lt_(a:BigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) < 0; } - @:op(A < B) @:noCompletion public static inline function ltMutable_(a:BigInt, b:MutableBigInt):Bool { + @:op(A < B) @:noCompletion @:noDoc public static inline function ltMutable_(a:BigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) < 0; } // Binary less than or equal - @:op(A <= B) @:noCompletion public static inline function lteInt_(a:BigInt, b:Int):Bool { + @:op(A <= B) @:noCompletion @:noDoc public static inline function lteInt_(a:BigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) <= 0; } - @:op(A <= B) @:noCompletion public static inline function lte_(a:BigInt, b:BigInt):Bool { + @:op(A <= B) @:noCompletion @:noDoc public static inline function lte_(a:BigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) <= 0; } - @:op(A <= B) @:noCompletion public static inline function lteMutable_(a:BigInt, b:MutableBigInt):Bool { + @:op(A <= B) @:noCompletion @:noDoc public static inline function lteMutable_(a:BigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) <= 0; } // Binary greater than - @:op(A > B) @:noCompletion public static inline function gtInt_(a:BigInt, b:Int):Bool { + @:op(A > B) @:noCompletion @:noDoc public static inline function gtInt_(a:BigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) > 0; } - @:op(A > B) @:noCompletion public static inline function gt_(a:BigInt, b:BigInt):Bool { + @:op(A > B) @:noCompletion @:noDoc public static inline function gt_(a:BigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) > 0; } - @:op(A > B) @:noCompletion public static inline function gtMutable_(a:BigInt, b:MutableBigInt):Bool { + @:op(A > B) @:noCompletion @:noDoc public static inline function gtMutable_(a:BigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) > 0; } // Binary greater than or equal - @:op(A >= B) @:noCompletion public static inline function gteInt_(a:BigInt, b:Int):Bool { + @:op(A >= B) @:noCompletion @:noDoc public static inline function gteInt_(a:BigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) >= 0; } - @:op(A >= B) @:noCompletion public static inline function gte_(a:BigInt, b:BigInt):Bool { + @:op(A >= B) @:noCompletion @:noDoc public static inline function gte_(a:BigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) >= 0; } - @:op(A >= B) @:noCompletion public static inline function gteMutable_(a:BigInt, b:MutableBigInt):Bool { + @:op(A >= B) @:noCompletion @:noDoc public static inline function gteMutable_(a:BigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) >= 0; } // String conversions - @:op(A + B) @:noCompletion public static inline function toStr_left(a:String, b:BigInt):String { + @:op(A + B) @:noCompletion @:noDoc public static inline function toStr_left(a:String, b:BigInt):String { return a + b.toString(); } - @:op(A + B) @:noCompletion public static inline function toStr_right(a:BigInt, b:String):String { + @:op(A + B) @:noCompletion @:noDoc public static inline function toStr_right(a:BigInt, b:String):String { return a.toString() + b; } // Binary addition - @:op(A + B) @:noCompletion public static inline function addInt_(a:BigInt, b:Int):BigInt { + @:op(A + B) @:noCompletion @:noDoc public static inline function addInt_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.addInt2(a, b)); } - @:op(A + B) @:noCompletion public static inline function add_(a:BigInt, b:BigInt):BigInt { + @:op(A + B) @:noCompletion @:noDoc public static inline function add_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.add2(a, b)); } - @:op(A + B) @:noCompletion public static inline function addMutable_(a:BigInt, b:MutableBigInt):BigInt { + @:op(A + B) @:noCompletion @:noDoc public static inline function addMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.add2(a, b)); } // Binary subtraction - @:op(A - B) @:noCompletion public static inline function subInt_(a:BigInt, b:Int):BigInt { + @:op(A - B) @:noCompletion @:noDoc public static inline function subInt_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.subInt2(a, b)); } - @:op(A - B) @:noCompletion public static inline function sub_(a:BigInt, b:BigInt):BigInt { + @:op(A - B) @:noCompletion @:noDoc public static inline function sub_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.sub2(a, b)); } - @:op(A - B) @:noCompletion public static inline function subMutable_(a:BigInt, b:MutableBigInt):BigInt { + @:op(A - B) @:noCompletion @:noDoc public static inline function subMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.sub2(a, b)); } // Binary multiplication - @:op(A * B) @:noCompletion public static inline function mulInt_(a:BigInt, b:Int):BigInt { + @:op(A * B) @:noCompletion @:noDoc public static inline function mulInt_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.multiplyInt2(a, b)); } - @:op(A * B) @:noCompletion public static inline function mul_(a:BigInt, b:BigInt):BigInt { + @:op(A * B) @:noCompletion @:noDoc public static inline function mul_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.multiply2(a, b)); } - @:op(A * B) @:noCompletion public static inline function mulMutable_(a:BigInt, b:MutableBigInt):BigInt { + @:op(A * B) @:noCompletion @:noDoc public static inline function mulMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.multiply2(a, b)); } // Binary division - @:op(A / B) @:noCompletion public static inline function divInt_(a:BigInt, b:Int):BigInt { + @:op(A / B) @:noCompletion @:noDoc public static inline function divInt_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.divideInt2(a, b)); } - @:op(A / B) @:noCompletion public static inline function div_(a:BigInt, b:BigInt):BigInt { + @:op(A / B) @:noCompletion @:noDoc public static inline function div_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.divide2(a, b)); } - @:op(A / B) @:noCompletion public static inline function divMutable_(a:BigInt, b:MutableBigInt):BigInt { + @:op(A / B) @:noCompletion @:noDoc public static inline function divMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.divide2(a, b)); } // Binary modulus - @:op(A % B) @:noCompletion public static inline function modInt_(a:BigInt, b:Int):Int { + @:op(A % B) @:noCompletion @:noDoc public static inline function modInt_(a:BigInt, b:Int):Int { return BigInt_.modulusInt2(a, b); } - @:op(A % B) @:noCompletion public static inline function mod_(a:BigInt, b:BigInt):BigInt { + @:op(A % B) @:noCompletion @:noDoc public static inline function mod_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigInt_.modulus2(a, b)); } - @:op(A % B) @:noCompletion public static inline function modMutable_(a:BigInt, b:MutableBigInt):BigInt { + @:op(A % B) @:noCompletion @:noDoc public static inline function modMutable_(a:BigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.modulus2(a, b)); } // Binary OR - @:op(A | B) @:noCompletion public static inline function orInt_(a:BigInt, b:Int):BigInt { + @:op(A | B) @:noCompletion @:noDoc public static inline function orInt_(a:BigInt, b:Int):BigInt { return or_(a, b); } - @:op(A | B) @:noCompletion public static inline function or_(a:BigInt, b:BigInt):BigInt { + @:op(A | B) @:noCompletion @:noDoc public static inline function or_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigIntArithmetic.bitwiseOr(a, b)); } - @:op(A ^ B) @:noCompletion public static inline function xorInt_(a:BigInt, b:Int):BigInt { + @:op(A ^ B) @:noCompletion @:noDoc public static inline function xorInt_(a:BigInt, b:Int):BigInt { return xor_(a, b); } - @:op(A ^ B) @:noCompletion public static inline function xor_(a:BigInt, b:BigInt):BigInt { + @:op(A ^ B) @:noCompletion @:noDoc public static inline function xor_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigIntArithmetic.bitwiseXor(a, b)); } - @:op(~A) @:noCompletion public static inline function not_(a:BigInt):BigInt { + @:op(~A) @:noCompletion @:noDoc public static inline function not_(a:BigInt):BigInt { return new BigInt(BigIntArithmetic.bitwiseNot(a)); } // Binary AND - @:op(A & B) @:noCompletion public static inline function andInt_(a:BigInt, b:Int):Int { + @:op(A & B) @:noCompletion @:noDoc public static inline function andInt_(a:BigInt, b:Int):Int { return BigIntArithmetic.bitwiseAndInt(a, b); } - @:op(A & B) @:noCompletion public static inline function and_(a:BigInt, b:BigInt):BigInt { + @:op(A & B) @:noCompletion @:noDoc public static inline function and_(a:BigInt, b:BigInt):BigInt { return new BigInt(BigIntArithmetic.bitwiseAnd(a, b)); } // Binary shift left - @:op(A << B) @:noCompletion public static inline function asl_(a:BigInt, b:Int):BigInt { + @:op(A << B) @:noCompletion @:noDoc public static inline function asl_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.arithmeticShiftLeft2(a, b)); } // Binary shift right - @:op(A >> B) @:noCompletion public static inline function asr_(a:BigInt, b:Int):BigInt { + @:op(A >> B) @:noCompletion @:noDoc public static inline function asr_(a:BigInt, b:Int):BigInt { return new BigInt(BigInt_.arithmeticShiftRight2(a, b)); } @@ -419,19 +419,19 @@ abstract BigInt(BigInt_) { // Automatic conversions //----------------------------------------------------------------------- - @:from @:noCompletion public static inline function fromInt_(a:Int):BigInt { + @:from @:noCompletion @:noDoc public static inline function fromInt_(a:Int):BigInt { return new BigInt(BigInt_.fromInt(a)); } - @:from @:noCompletion public static inline function fromString_(a:String):BigInt { + @:from @:noCompletion @:noDoc public static inline function fromString_(a:String):BigInt { return new BigInt(BigInt_.fromString(a)); } - @:to @:noCompletion public inline function toBigInt_():BigInt_ { + @:to @:noCompletion @:noDoc public inline function toBigInt_():BigInt_ { return this; } - @:to @:noCompletion public inline function toMutableBigInt():MutableBigInt { + @:to @:noCompletion @:noDoc public inline function toMutableBigInt():MutableBigInt { return new MutableBigInt(MutableBigInt_.fromBigInt(this)); } @@ -439,7 +439,7 @@ abstract BigInt(BigInt_) { // Private implementation //----------------------------------------------------------------------- - @:noCompletion private inline function new(a:BigInt_) { + @:noCompletion @:noDoc private inline function new(a:BigInt_) { this = a; } diff --git a/std/haxe/math/bigint/BigIntExceptions.hx b/std/haxe/math/bigint/BigIntExceptions.hx index bddfc94855d..fb06206f2cb 100644 --- a/std/haxe/math/bigint/BigIntExceptions.hx +++ b/std/haxe/math/bigint/BigIntExceptions.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2022 Haxe Foundation + * Copyright (C)2005-2023 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -23,7 +23,7 @@ package haxe.math.bigint; /* Original code courtesy Chuck Batson (github.com/cbatson) */ -enum abstract BigIntExceptions(String) { +enum abstract BigIntExceptions(String) to String { var INVALID_ARGUMENT = "Invalid argument"; var BUFFER_TOO_SMALL = "Buffer too small"; var DIVISION_BY_ZERO = "Division by zero"; diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 5fba3839587..2aa4b593ee8 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2022 Haxe Foundation + * Copyright (C)2005-2023 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,6 +26,8 @@ import haxe.ds.Vector; import haxe.io.Bytes; /* Original code courtesy Chuck Batson (github.com/cbatson) */ +@:noCompletion +@:noDoc @:allow(unit) @:allow(haxe.math.bigint) class BigInt_ { diff --git a/std/haxe/math/bigint/MutableBigInt.hx b/std/haxe/math/bigint/MutableBigInt.hx index 44bf0c25a14..2f63cff78b8 100644 --- a/std/haxe/math/bigint/MutableBigInt.hx +++ b/std/haxe/math/bigint/MutableBigInt.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2022 Haxe Foundation + * Copyright (C)2005-2023 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -145,250 +145,250 @@ abstract MutableBigInt(MutableBigInt_) { // * MutableBigInt BigInt // * MutableBigInt MutableBigInt // Unary negation - @:op(-A) @:noCompletion public static inline function negate_(a:MutableBigInt):BigInt { + @:op(-A) @:noCompletion @:noDoc public static inline function negate_(a:MutableBigInt):BigInt { return new BigInt(BigInt_.negate1(a)); } // Binary equality - @:op(A == B) @:noCompletion public static inline function eqInt_(a:MutableBigInt, b:Int):Bool { + @:op(A == B) @:noCompletion @:noDoc public static inline function eqInt_(a:MutableBigInt, b:Int):Bool { return BigInt_.equals2Int(a, b); } - @:op(A == B) @:noCompletion public static inline function eq_(a:MutableBigInt, b:BigInt):Bool { + @:op(A == B) @:noCompletion @:noDoc public static inline function eq_(a:MutableBigInt, b:BigInt):Bool { return BigInt_.equals2(a, b); } - @:op(A == B) @:noCompletion public static inline function eqMutable_(a:MutableBigInt, b:MutableBigInt):Bool { + @:op(A == B) @:noCompletion @:noDoc public static inline function eqMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigInt_.equals2(a, b); } // Binary inequality - @:op(A != B) @:noCompletion public static inline function ineqInt_(a:MutableBigInt, b:Int):Bool { + @:op(A != B) @:noCompletion @:noDoc public static inline function ineqInt_(a:MutableBigInt, b:Int):Bool { return !BigInt_.equals2Int(a, b); } - @:op(A != B) @:noCompletion public static inline function ineq_(a:MutableBigInt, b:BigInt):Bool { + @:op(A != B) @:noCompletion @:noDoc public static inline function ineq_(a:MutableBigInt, b:BigInt):Bool { return !BigInt_.equals2(a, b); } - @:op(A != B) @:noCompletion public static inline function ineqMutable_(a:MutableBigInt, b:MutableBigInt):Bool { + @:op(A != B) @:noCompletion @:noDoc public static inline function ineqMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return !BigInt_.equals2(a, b); } // Binary less than - @:op(A < B) @:noCompletion public static inline function ltInt_(a:MutableBigInt, b:Int):Bool { + @:op(A < B) @:noCompletion @:noDoc public static inline function ltInt_(a:MutableBigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) < 0; } - @:op(A < B) @:noCompletion public static inline function lt_(a:MutableBigInt, b:BigInt):Bool { + @:op(A < B) @:noCompletion @:noDoc public static inline function lt_(a:MutableBigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) < 0; } - @:op(A < B) @:noCompletion public static inline function ltMutable_(a:MutableBigInt, b:MutableBigInt):Bool { + @:op(A < B) @:noCompletion @:noDoc public static inline function ltMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) < 0; } // Binary less than or equal - @:op(A <= B) @:noCompletion public static inline function lteInt_(a:MutableBigInt, b:Int):Bool { + @:op(A <= B) @:noCompletion @:noDoc public static inline function lteInt_(a:MutableBigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) <= 0; } - @:op(A <= B) @:noCompletion public static inline function lte_(a:MutableBigInt, b:BigInt):Bool { + @:op(A <= B) @:noCompletion @:noDoc public static inline function lte_(a:MutableBigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) <= 0; } - @:op(A <= B) @:noCompletion public static inline function lteMutable_(a:MutableBigInt, b:MutableBigInt):Bool { + @:op(A <= B) @:noCompletion @:noDoc public static inline function lteMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) <= 0; } // Binary greater than - @:op(A > B) @:noCompletion public static inline function gtInt_(a:MutableBigInt, b:Int):Bool { + @:op(A > B) @:noCompletion @:noDoc public static inline function gtInt_(a:MutableBigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) > 0; } - @:op(A > B) @:noCompletion public static inline function gt_(a:MutableBigInt, b:BigInt):Bool { + @:op(A > B) @:noCompletion @:noDoc public static inline function gt_(a:MutableBigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) > 0; } - @:op(A > B) @:noCompletion public static inline function gtMutable_(a:MutableBigInt, b:MutableBigInt):Bool { + @:op(A > B) @:noCompletion @:noDoc public static inline function gtMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) > 0; } // Binary greater than or equal - @:op(A >= B) @:noCompletion public static inline function gteInt_(a:MutableBigInt, b:Int):Bool { + @:op(A >= B) @:noCompletion @:noDoc public static inline function gteInt_(a:MutableBigInt, b:Int):Bool { return BigIntArithmetic.compareInt(a, b) >= 0; } - @:op(A >= B) @:noCompletion public static inline function gte_(a:MutableBigInt, b:BigInt):Bool { + @:op(A >= B) @:noCompletion @:noDoc public static inline function gte_(a:MutableBigInt, b:BigInt):Bool { return BigIntArithmetic.compare(a, b) >= 0; } - @:op(A >= B) @:noCompletion public static inline function gteMutable_(a:MutableBigInt, b:MutableBigInt):Bool { + @:op(A >= B) @:noCompletion @:noDoc public static inline function gteMutable_(a:MutableBigInt, b:MutableBigInt):Bool { return BigIntArithmetic.compare(a, b) >= 0; } // Binary addition - @:op(A += B) @:noCompletion public static inline function addAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { + @:op(A += B) @:noCompletion @:noDoc public static inline function addAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { BigIntArithmetic.addInt(a, a, b); return a; } - @:op(A += B) @:noCompletion public static inline function addAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { + @:op(A += B) @:noCompletion @:noDoc public static inline function addAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { BigIntArithmetic.add(a, a, b); return a; } - @:op(A += B) @:noCompletion public static inline function addAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { + @:op(A += B) @:noCompletion @:noDoc public static inline function addAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { BigIntArithmetic.add(a, a, b); return a; } - @:op(A + B) @:noCompletion public static inline function addInt_(a:MutableBigInt, b:Int):BigInt { + @:op(A + B) @:noCompletion @:noDoc public static inline function addInt_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.addInt2(a, b)); } - @:op(A + B) @:noCompletion public static inline function add_(a:MutableBigInt, b:BigInt):BigInt { + @:op(A + B) @:noCompletion @:noDoc public static inline function add_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.add2(a, b)); } - @:op(A + B) @:noCompletion public static inline function addMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { + @:op(A + B) @:noCompletion @:noDoc public static inline function addMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.add2(a, b)); } // Binary subtraction - @:op(A -= B) @:noCompletion public static inline function subAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { + @:op(A -= B) @:noCompletion @:noDoc public static inline function subAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { BigIntArithmetic.subtractInt(a, a, b); return a; } - @:op(A -= B) @:noCompletion public static inline function subAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { + @:op(A -= B) @:noCompletion @:noDoc public static inline function subAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { BigIntArithmetic.subtract(a, a, b); return a; } - @:op(A -= B) @:noCompletion public static inline function subAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { + @:op(A -= B) @:noCompletion @:noDoc public static inline function subAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { BigIntArithmetic.subtract(a, a, b); return a; } - @:op(A - B) @:noCompletion public static inline function subInt_(a:MutableBigInt, b:Int):BigInt { + @:op(A - B) @:noCompletion @:noDoc public static inline function subInt_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.subInt2(a, b)); } - @:op(A - B) @:noCompletion public static inline function sub_(a:MutableBigInt, b:BigInt):BigInt { + @:op(A - B) @:noCompletion @:noDoc public static inline function sub_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.sub2(a, b)); } - @:op(A - B) @:noCompletion public static inline function subMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { + @:op(A - B) @:noCompletion @:noDoc public static inline function subMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.sub2(a, b)); } // Binary multiplication - @:op(A *= B) @:noCompletion public static inline function mulAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { + @:op(A *= B) @:noCompletion @:noDoc public static inline function mulAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.multiplyAssignInt2(a, b); return a; } - @:op(A *= B) @:noCompletion public static inline function mulAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { + @:op(A *= B) @:noCompletion @:noDoc public static inline function mulAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { MutableBigInt_.multiplyAssign2(a, b); return a; } - @:op(A *= B) @:noCompletion public static inline function mulAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { + @:op(A *= B) @:noCompletion @:noDoc public static inline function mulAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { MutableBigInt_.multiplyAssign2(a, b); return a; } - @:op(A * B) @:noCompletion public static inline function mulInt_(a:MutableBigInt, b:Int):BigInt { + @:op(A * B) @:noCompletion @:noDoc public static inline function mulInt_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.multiplyInt2(a, b)); } - @:op(A * B) @:noCompletion public static inline function mul_(a:MutableBigInt, b:BigInt):BigInt { + @:op(A * B) @:noCompletion @:noDoc public static inline function mul_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.multiply2(a, b)); } - @:op(A * B) @:noCompletion public static inline function mulMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { + @:op(A * B) @:noCompletion @:noDoc public static inline function mulMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.multiply2(a, b)); } // Binary division - @:op(A /= B) @:noCompletion public static inline function divAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { + @:op(A /= B) @:noCompletion @:noDoc public static inline function divAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.divideAssignInt2(a, b); return a; } - @:op(A /= B) @:noCompletion public static inline function divAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { + @:op(A /= B) @:noCompletion @:noDoc public static inline function divAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { MutableBigInt_.divideAssign2(a, b); return a; } - @:op(A /= B) @:noCompletion public static inline function divAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { + @:op(A /= B) @:noCompletion @:noDoc public static inline function divAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { MutableBigInt_.divideAssign2(a, b); return a; } - @:op(A / B) @:noCompletion public static inline function divInt_(a:MutableBigInt, b:Int):BigInt { + @:op(A / B) @:noCompletion @:noDoc public static inline function divInt_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.divideInt2(a, b)); } - @:op(A / B) @:noCompletion public static inline function div_(a:MutableBigInt, b:BigInt):BigInt { + @:op(A / B) @:noCompletion @:noDoc public static inline function div_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.divide2(a, b)); } - @:op(A / B) @:noCompletion public static inline function divMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { + @:op(A / B) @:noCompletion @:noDoc public static inline function divMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.divide2(a, b)); } // Binary modulus - @:op(A %= B) @:noCompletion public static inline function modAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { + @:op(A %= B) @:noCompletion @:noDoc public static inline function modAssignInt_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.modulusAssignInt2(a, b); return a; } - @:op(A %= B) @:noCompletion public static inline function modAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { + @:op(A %= B) @:noCompletion @:noDoc public static inline function modAssign_(a:MutableBigInt, b:BigInt):MutableBigInt { MutableBigInt_.modulusAssign2(a, b); return a; } - @:op(A %= B) @:noCompletion public static inline function modAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { + @:op(A %= B) @:noCompletion @:noDoc public static inline function modAssignMutable_(a:MutableBigInt, b:MutableBigInt):MutableBigInt { MutableBigInt_.modulusAssign2(a, b); return a; } - @:op(A % B) @:noCompletion public static inline function modInt_(a:MutableBigInt, b:Int):Int { + @:op(A % B) @:noCompletion @:noDoc public static inline function modInt_(a:MutableBigInt, b:Int):Int { return BigInt_.modulusInt2(a, b); } - @:op(A % B) @:noCompletion public static inline function mod_(a:MutableBigInt, b:BigInt):BigInt { + @:op(A % B) @:noCompletion @:noDoc public static inline function mod_(a:MutableBigInt, b:BigInt):BigInt { return new BigInt(BigInt_.modulus2(a, b)); } - @:op(A % B) @:noCompletion public static inline function modMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { + @:op(A % B) @:noCompletion @:noDoc public static inline function modMutable_(a:MutableBigInt, b:MutableBigInt):BigInt { return new BigInt(BigInt_.modulus2(a, b)); } // Binary AND - @:op(A & B) @:noCompletion public static inline function andInt_(a:MutableBigInt, b:Int):Int { + @:op(A & B) @:noCompletion @:noDoc public static inline function andInt_(a:MutableBigInt, b:Int):Int { return BigIntArithmetic.bitwiseAndInt(a, b); } // Binary shift left - @:op(A <<= B) @:noCompletion public static inline function arithmeticShiftLeftAssign_(a:MutableBigInt, b:Int):MutableBigInt { + @:op(A <<= B) @:noCompletion @:noDoc public static inline function arithmeticShiftLeftAssign_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.arithmeticShiftLeftAssign2(a, b); return a; } - @:op(A << B) @:noCompletion public static inline function asl_(a:MutableBigInt, b:Int):BigInt { + @:op(A << B) @:noCompletion @:noDoc public static inline function asl_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.arithmeticShiftLeft2(a, b)); } // Binary shift right - @:op(A >>= B) @:noCompletion public static inline function arithmeticShiftRightAssign_(a:MutableBigInt, b:Int):MutableBigInt { + @:op(A >>= B) @:noCompletion @:noDoc public static inline function arithmeticShiftRightAssign_(a:MutableBigInt, b:Int):MutableBigInt { MutableBigInt_.arithmeticShiftRightAssign2(a, b); return a; } - @:op(A >> B) @:noCompletion public static inline function asr_(a:MutableBigInt, b:Int):BigInt { + @:op(A >> B) @:noCompletion @:noDoc public static inline function asr_(a:MutableBigInt, b:Int):BigInt { return new BigInt(BigInt_.arithmeticShiftRight2(a, b)); } @@ -396,23 +396,23 @@ abstract MutableBigInt(MutableBigInt_) { // Automatic conversions //----------------------------------------------------------------------- - @:from @:noCompletion public static inline function fromInt_(a:Int):MutableBigInt { + @:from @:noCompletion @:noDoc public static inline function fromInt_(a:Int):MutableBigInt { return new MutableBigInt(MutableBigInt_.fromInt(a)); } - @:from @:noCompletion public static inline function fromBigInt_(a:BigInt_):MutableBigInt { + @:from @:noCompletion @:noDoc public static inline function fromBigInt_(a:BigInt_):MutableBigInt { return new MutableBigInt(MutableBigInt_.fromBigInt(a)); } - @:from @:noCompletion public static inline function fromMutableBigInt_(a:MutableBigInt_):MutableBigInt { + @:from @:noCompletion @:noDoc public static inline function fromMutableBigInt_(a:MutableBigInt_):MutableBigInt { return new MutableBigInt(MutableBigInt_.fromBigInt(a)); } - @:to @:noCompletion public inline function toMutableBigInt_():MutableBigInt_ { + @:to @:noCompletion @:noDoc public inline function toMutableBigInt_():MutableBigInt_ { return this; } - @:to @:noCompletion public inline function toBigInt():BigInt { + @:to @:noCompletion @:noDoc public inline function toBigInt():BigInt { return new BigInt(this); } diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index 7822530427b..82464f4b19c 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2022 Haxe Foundation + * Copyright (C)2005-2023 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,6 +28,8 @@ import haxe.ds.Vector; import haxe.io.Bytes; /* Original code courtesy Chuck Batson (github.com/cbatson) */ +@:noCompletion +@:noDoc @:allow(unit) @:allow(haxe.math.bigint) class MutableBigInt_ extends BigInt_ { diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 64ff2c70483..311c597f877 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -62,7 +62,7 @@ class TestBigInt extends Test { try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } eq("00000000", dividend.toHex()); } @@ -391,23 +391,23 @@ class TestBigInt extends Test { try { BigIntArithmetic.multiply(a, a, BigInt.fromInt(2)); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { BigIntArithmetic.multiply(a, BigInt.fromInt(2), a); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // division by zero should throw exception try { BigInt.fromInt(1) / 0; } catch (e) { - eq(cast BigIntExceptions.DIVISION_BY_ZERO, e.message); + eq( e.message, BigIntExceptions.DIVISION_BY_ZERO); } try { BigInt.fromInt(0) / 0; } catch (e) { - eq(cast BigIntExceptions.DIVISION_BY_ZERO, e.message); + eq( e.message, BigIntExceptions.DIVISION_BY_ZERO); } // Multiplication of same inputs is ok @@ -545,19 +545,19 @@ class TestBigInt extends Test { try { BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), quotient, quotient); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // quotient cannot be null try { BigIntArithmetic.divideInt(BigInt.fromInt(1), 10, null); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), null, remainder); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // remainder can be null @@ -574,22 +574,22 @@ class TestBigInt extends Test { try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, divisor); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, quotient); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, remainder); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } } @@ -953,27 +953,27 @@ class TestBigInt extends Test { try { var x = BigInt.fromString(null); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { var x = BigInt.fromString(""); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { var x = BigInt.fromString("-"); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { var x = BigInt.fromString(" 0"); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { var x = BigInt.fromString("0 "); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } eq("0", BigInt.fromString("0").toString()); @@ -1001,7 +1001,7 @@ class TestBigInt extends Test { try { var x = BigInt.fromBytes(null); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } eq("0", BigInt.fromBytes(Bytes.ofHex("00")).toString()); eq("1", BigInt.fromBytes(Bytes.ofHex("01")).toString()); @@ -1039,17 +1039,17 @@ class TestBigInt extends Test { try { a <<= -1; } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { a << -1; } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { BigInt.ONE << -1; } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } asl(BigInt.ONE, 1, BigInt.fromInt(2)); @@ -1123,17 +1123,17 @@ class TestBigInt extends Test { try { var x = BigInt.fromHex(null); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { var x = BigInt.fromHex(""); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { var x = BigInt.fromHex("0q0"); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } var sb = new StringBuf(); @@ -1266,30 +1266,30 @@ class TestBigInt extends Test { try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // result and input overlap @@ -1326,30 +1326,30 @@ class TestBigInt extends Test { try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // result and input overlap @@ -1418,22 +1418,22 @@ class TestBigInt extends Test { try { MultiwordArithmetic.subtract(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } } @@ -1464,23 +1464,23 @@ class TestBigInt extends Test { try { MultiwordArithmetic.add(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } } @@ -1637,27 +1637,27 @@ class TestBigInt extends Test { try { MultiwordArithmetic.setFromHexUnsigned(value, 1, null); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.setFromHexUnsigned(value, 1, ""); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.setFromHexUnsigned(null, 1, "0"); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.setFromHexUnsigned(value, 2, "0"); // buffer too small } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.setFromHexUnsigned(value, 1, "0g0"); // invalid char } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } value = new Vector(3); @@ -1708,18 +1708,18 @@ class TestBigInt extends Test { try { MultiwordArithmetic.multiplyUnsigned(result, result, 1, fromInt(2), 1); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyUnsigned(result, fromInt(2), 1, result, 1); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyIntUnsigned(result, result, 1, 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // Multiplication of same inputs is ok @@ -1732,29 +1732,29 @@ class TestBigInt extends Test { try { MultiwordArithmetic.multiplyUnsigned(fromInt(0), fromInt(2), 1, fromInt(2), 1); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0), fromInt(2), 1, 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // check input lengths try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 0, fromInt(2), 1); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 1, fromInt(2), 0); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 2), fromInt(2), 0, 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // check input bounds @@ -1762,17 +1762,17 @@ class TestBigInt extends Test { try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 1), 2, fromInt(2, 2), 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 2), 2, fromInt(2, 1), 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 4), fromInt(2, 1), 2, 2); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } } @@ -1916,32 +1916,32 @@ class TestBigInt extends Test { try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, quotient, work); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // quotient cannot be null try { MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, null, work); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, null, remainder, work); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // work cannot be null try { MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, quotient, null); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, remainder, null); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // remainder can be null @@ -1958,23 +1958,23 @@ class TestBigInt extends Test { try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, dividend); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, divisor); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, quotient); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, remainder); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // bounds @@ -1982,36 +1982,36 @@ class TestBigInt extends Test { try { MultiwordArithmetic.divideUnsigned(dividend, 0, divisor, divisor.length, quotient, remainder, work); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, 0, quotient, remainder, work); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, new Vector(0), remainder, work); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } // division by zero try { MultiwordArithmetic.divideIntUnsigned(dividend, dividend.length, 0, quotient, work); } catch (e) { - eq(cast BigIntExceptions.DIVISION_BY_ZERO, e.message); + eq( e.message, BigIntExceptions.DIVISION_BY_ZERO); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromInt(0), 1, quotient, remainder, work); } catch (e) { - eq(cast BigIntExceptions.DIVISION_BY_ZERO, e.message); + eq( e.message, BigIntExceptions.DIVISION_BY_ZERO); } // divisor with leading 0 try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromHex("1", 2), 2, quotient, remainder, work); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } } @@ -2813,7 +2813,7 @@ class TestBigInt extends Test { try { randomBigInt = BigInt.randomInRange(a,b); } catch (e) { - eq(cast BigIntExceptions.INVALID_ARGUMENT, e.message); + eq(e.message, BigIntExceptions.INVALID_ARGUMENT); } } From b4faf0a589effd6536099afb4b25e6ecaefc335c Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 4 Mar 2023 21:26:44 +0200 Subject: [PATCH 067/134] Change var NEGATIVE_ONE to MINUS_ONE --- std/haxe/math/bigint/BigInt.hx | 2 +- tests/unit/src/unit/TestBigInt.hx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 3e07bf14ffa..6939c507241 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -34,7 +34,7 @@ abstract BigInt(BigInt_) { public static var ZERO(default, null):BigInt = new BigInt(BigInt_.fromInt(0)); public static var ONE(default, null):BigInt = new BigInt(BigInt_.fromInt(1)); public static var TWO(default, null):BigInt = new BigInt(BigInt_.fromInt(2)); - public static var NEGATIVE_ONE(default, null):BigInt = new BigInt(BigInt_.fromInt(-1)); + public static var MINUS_ONE(default, null):BigInt = new BigInt(BigInt_.fromInt(-1)); //----------------------------------------------------------------------- // Public interface diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 311c597f877..07ece5de82f 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -1092,13 +1092,13 @@ class TestBigInt extends Test { public function bigIntIsZero():Void { t(BigInt.ZERO.isZero()); f(BigInt.ONE.isZero()); - f(BigInt.NEGATIVE_ONE.isZero()); + f(BigInt.MINUS_ONE.isZero()); } public function bigIntSign():Void { eq(0, BigInt.ZERO.sign()); eq(0, BigInt.ONE.sign()); - eq(-1, BigInt.NEGATIVE_ONE.sign()); + eq(-1, BigInt.MINUS_ONE.sign()); eq(0, BigInt.fromInt(2147483647).sign()); eq(-1, BigInt.fromInt(-2147483648).sign()); } @@ -1114,7 +1114,7 @@ class TestBigInt extends Test { public function bigIntHexStrings():Void { eq("00000000", BigInt.ZERO.toHex()); eq("00000001", BigInt.ONE.toHex()); - eq("ffffffff", BigInt.NEGATIVE_ONE.toHex()); + eq("ffffffff", BigInt.MINUS_ONE.toHex()); eq("0", BigInt.fromHex("0").toString()); eq("1", BigInt.fromHex("1").toString()); From f1f1e117f997c3d2518645c389eaccdeaefcee5b Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 4 Mar 2023 22:39:18 +0200 Subject: [PATCH 068/134] New implementation for BigIntException class --- std/haxe/math/bigint/BigIntArithmetic.hx | 17 +- .../{BigIntExceptions.hx => BigIntError.hx} | 3 +- std/haxe/math/bigint/BigIntException.hx | 29 ++++ std/haxe/math/bigint/BigIntTools.hx | 7 +- std/haxe/math/bigint/BigInt_.hx | 16 +- std/haxe/math/bigint/MultiwordArithmetic.hx | 69 ++++---- std/haxe/math/bigint/MutableBigInt_.hx | 25 +-- tests/unit/src/unit/TestBigInt.hx | 150 +++++++++--------- 8 files changed, 174 insertions(+), 142 deletions(-) rename std/haxe/math/bigint/{BigIntExceptions.hx => BigIntError.hx} (92%) create mode 100644 std/haxe/math/bigint/BigIntException.hx diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index fa8785e7ce8..c24778d2485 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2022 Haxe Foundation + * Copyright (C)2005-2023 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,7 +22,8 @@ package haxe.math.bigint; -import haxe.math.bigint.BigIntExceptions; +import haxe.math.bigint.BigIntException; +import haxe.math.bigint.BigIntError; import haxe.math.bigint.BigIntHelper; import haxe.ds.Vector; @@ -332,7 +333,7 @@ class BigIntArithmetic { // Implements Figure 8-1 (p. 172) from "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. if ((operand1 == result) || (operand2 == result)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if (operand1.isZero() || operand2.isZero()) { @@ -475,10 +476,10 @@ class BigIntArithmetic { private static function multiwordUnsignedDivide(dividend:BigInt_, divisor:BigInt_, quotientOut:MutableBigInt_, remainderOut:MutableBigInt_, work:MutableBigInt_ = null):Void { if ((quotientOut == null) || (dividend == null) || (divisor == null)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if ((work == dividend) || (work == divisor) || (work == quotientOut)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } var dividendInts:Int = dividend.getUnsignedDigitCount(); @@ -488,7 +489,7 @@ class BigIntArithmetic { if (remainderOut != null) { if (work == remainderOut) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } remainderOut.ensureCapacity(divisor.m_count, (remainderOut == dividend) || (remainderOut == divisor)); } @@ -527,7 +528,7 @@ class BigIntArithmetic { **/ public static function arithmeticShiftLeft(result:MutableBigInt_, operand1:BigInt_, operand2:Int):Void { if (operand2 < 0) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if ((operand2 == 0) || operand1.isZero()) { @@ -562,7 +563,7 @@ class BigIntArithmetic { **/ public static function arithmeticShiftRight(result:MutableBigInt_, operand1:BigInt_, operand2:Int):Void { if (operand2 < 0) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if ((operand2 == 0) || operand1.isZero()) { diff --git a/std/haxe/math/bigint/BigIntExceptions.hx b/std/haxe/math/bigint/BigIntError.hx similarity index 92% rename from std/haxe/math/bigint/BigIntExceptions.hx rename to std/haxe/math/bigint/BigIntError.hx index fb06206f2cb..edc14dfae0a 100644 --- a/std/haxe/math/bigint/BigIntExceptions.hx +++ b/std/haxe/math/bigint/BigIntError.hx @@ -22,8 +22,7 @@ package haxe.math.bigint; -/* Original code courtesy Chuck Batson (github.com/cbatson) */ -enum abstract BigIntExceptions(String) to String { +enum abstract BigIntError(String) to String { var INVALID_ARGUMENT = "Invalid argument"; var BUFFER_TOO_SMALL = "Buffer too small"; var DIVISION_BY_ZERO = "Division by zero"; diff --git a/std/haxe/math/bigint/BigIntException.hx b/std/haxe/math/bigint/BigIntException.hx new file mode 100644 index 00000000000..43fb17b21da --- /dev/null +++ b/std/haxe/math/bigint/BigIntException.hx @@ -0,0 +1,29 @@ +/* + * Copyright (C)2005-2023 Haxe Foundation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +package haxe.math.bigint; + +class BigIntException extends haxe.Exception { + public function new(error:BigIntError, ?previous:haxe.Exception) { + super( error, previous); + } +} \ No newline at end of file diff --git a/std/haxe/math/bigint/BigIntTools.hx b/std/haxe/math/bigint/BigIntTools.hx index 4291f975d99..86aa4cab7c7 100644 --- a/std/haxe/math/bigint/BigIntTools.hx +++ b/std/haxe/math/bigint/BigIntTools.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2022 Haxe Foundation + * Copyright (C)2005-2023 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,7 +22,8 @@ package haxe.math.bigint; -import haxe.math.bigint.BigIntExceptions; +import haxe.math.bigint.BigIntException; +import haxe.math.bigint.BigIntError; /* Original code courtesy Chuck Batson (github.com/cbatson) */ class BigIntTools { @@ -50,7 +51,7 @@ class BigIntTools { } else if (Std.isOfType(value, Int)) { bi = BigInt.fromInt(cast(value, Int)); } else { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } return bi; } diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 2aa4b593ee8..4d34c6acbcf 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -134,7 +134,7 @@ class BigInt_ { public function testBit(n:Int):Bool { if (n < 0) - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); var chunk = n >> 5; // divide by 32 if (chunk >= m_count) return (sign() < 0); @@ -151,7 +151,7 @@ class BigInt_ { public function flipBit(n:Int):BigInt_ { if (n < 0) - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); var isNegative:Bool = sign() < 0; var chunk = (n >> 5) + 1; var changeBit:Int = (n & 0x1f); @@ -394,7 +394,7 @@ class BigInt_ { public function modPow(exponent:BigInt_, modulus:BigInt_):BigInt_ { if (BigIntArithmetic.compareInt(exponent, 0) < 0) - throw BigIntExceptions.NEGATIVE_EXPONENT; + throw new BigIntException(BigIntError.NEGATIVE_EXPONENT); if (this.isZero()) return (BigIntArithmetic.compareInt(exponent, 0) == 0 ? BigInt.fromInt(1) : this); var r = BigInt_.newFromInt(1); @@ -412,7 +412,7 @@ class BigInt_ { public function pow(exponent:UInt):BigInt_ { if (exponent < 0) - throw BigIntExceptions.NEGATIVE_EXPONENT; + throw new BigIntException(BigIntError.NEGATIVE_EXPONENT); if (this.isZero()) return (exponent == 0 ? BigInt.fromInt(1) : this); var r = BigInt_.newFromInt(1); @@ -431,7 +431,7 @@ class BigInt_ { /* hac 14.61, pp. 608 */ public function modInverse(modulus:BigInt_):BigInt_ { if (modulus.sign() == -1 || modulus.isZero()) - throw BigIntExceptions.NEGATIVE_MODULUS; + throw new BigIntException(BigIntError.NEGATIVE_MODULUS); if (equals2Int(modulus, 1)) return BigInt.ZERO; @@ -448,7 +448,7 @@ class BigInt_ { return BigInt.ONE; if ((BigIntArithmetic.bitwiseAndInt(x, 1) == 0) && (BigIntArithmetic.bitwiseAndInt(y, 1) == 0)) - throw BigIntExceptions.EVEN_VALUES; + throw new BigIntException(BigIntError.EVEN_VALUES); if (!isModulusEven) { // fast odd calculation @@ -516,7 +516,7 @@ class BigInt_ { public static function randomPrime(bits:Int32, tolerance:UInt):BigInt_ { if (bits < 2) - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); if (bits == 2) return ((Math.random() < 0.5) ? BigInt.TWO : BigInt.fromInt(3)); var r = new MutableBigInt_(); @@ -544,7 +544,7 @@ class BigInt_ { if (initCheck == 0) return min; if (initCheck > 0) - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); if (min.bitLength() > (max.bitLength() >> 1)) return add2(randomInRange(BigInt.ZERO, sub2(max, min)), min); for (i in 0...1000) { diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 3124e040327..2f167342ead 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -1,5 +1,5 @@ /* - * Copyright (C)2005-2022 Haxe Foundation + * Copyright (C)2005-2023 Haxe Foundation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,7 +22,8 @@ package haxe.math.bigint; -import haxe.math.bigint.BigIntExceptions; +import haxe.math.bigint.BigIntException; +import haxe.math.bigint.BigIntError; import haxe.math.bigint.BigIntHelper; import haxe.ds.Vector; @@ -31,7 +32,7 @@ import haxe.ds.Vector; class MultiwordArithmetic { public static function isZero(value:Vector, length:Int):Bool { if (length < 1) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } for (i in 0...length) { if (value.get(i) != 0) { @@ -47,7 +48,7 @@ class MultiwordArithmetic { public static function getLengthUnsigned(value:Vector, length:Int):Int { if (length < 1) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } while (--length > 0) { if (value.get(length) != 0) { @@ -114,7 +115,7 @@ class MultiwordArithmetic { **/ public static function add(result:Vector, operand1:Vector, operand2:Vector, length:Int):Int { if ((length < 1) || (result.length < length) || (operand1.length < length) || (operand2.length < length)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } var c:Int = 0; var x:Int = 0, y:Int = 0, z:Int = 0; @@ -138,7 +139,7 @@ class MultiwordArithmetic { **/ public static function subtract(result:Vector, operand1:Vector, operand2:Vector, length:Int):Int { if ((length < 1) || (result.length < length) || (operand1.length < length) || (operand2.length < length)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } var c:Int = 0; var x:Int = 0, y:Int = 0, z:Int = 0; @@ -184,18 +185,18 @@ class MultiwordArithmetic { // Implements Figure 8-1 (p. 172) from "Hacker's Delight", Second Edition; Henry S. Warren, Jr.; 2013. if ((operand1 == result) || (operand2 == result)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if ((operand1Length < 1) || (operand2Length < 1)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if ((operand1.length < operand1Length) || (operand2.length < operand2Length)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } var resultSize:Int = operand1Length + operand2Length; if (result.length < resultSize) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } setZero(result, resultSize); @@ -279,27 +280,27 @@ class MultiwordArithmetic { public static function divideUnsigned(dividend:Vector, dividendLength:Int, divisor:Vector, divisorLength:Int, quotientOut:Vector, remainderOut:Vector, work:Vector):Void { if ((quotientOut == null) || (work == null) || (quotientOut == remainderOut)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if ((work == dividend) || (work == divisor) || (work == quotientOut) || (work == remainderOut)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if ((divisorLength < 1) || (dividendLength < 1)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } var quotientLength:Int = getDivisionQuotientLengthUnsigned(dividendLength, divisorLength); if (quotientOut.length < quotientLength) { // quotient storage too small - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if ((remainderOut != null) && (remainderOut.length < divisorLength)) { // remainder storage too small - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if (work.length < dividendLength + divisorLength + 1) { // quotient storage too small - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } // special cases @@ -307,7 +308,7 @@ class MultiwordArithmetic { if (divisorLength < 2) { switch (dh) { case 0: - throw BigIntExceptions.DIVISION_BY_ZERO; + throw new BigIntException(BigIntError.DIVISION_BY_ZERO); case 1: copy(quotientOut, dividend, dividendLength); // quotientLength == dividendLength if (remainderOut != null) { @@ -317,7 +318,7 @@ class MultiwordArithmetic { } } else if (dh == 0) { // leading zero - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } // trim leading zeros @@ -463,10 +464,10 @@ class MultiwordArithmetic { **/ public static function arithmeticShiftRight(result:Vector, input:Vector, length:Int, shift:Int):Void { if ((length < 1) || (result.length < length) || (input.length < length)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if (shift < 0) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } else if (shift == 0) { if (input != result) { Vector.blit(input, 0, result, 0, length); @@ -474,7 +475,7 @@ class MultiwordArithmetic { } else if (shift < 32) { _asr32(result, input, length, 0, shift); } else { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } } @@ -489,10 +490,10 @@ class MultiwordArithmetic { **/ public static function logicalShiftRight(result:Vector, input:Vector, length:Int, shift:Int):Void { if ((length < 1) || (result.length < length) || (input.length < length)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if (shift < 0) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } else if (shift == 0) { if (input != result) { Vector.blit(input, 0, result, 0, length); @@ -500,7 +501,7 @@ class MultiwordArithmetic { } else if (shift < 32) { _lsr32(result, input, length, 0, shift); } else { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } } @@ -515,10 +516,10 @@ class MultiwordArithmetic { **/ public static function shiftLeft(result:Vector, input:Vector, length:Int, shift:Int):Void { if ((length < 1) || (result.length < length) || (input.length < length)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if (shift < 0) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } else if (shift == 0) { if (input != result) { Vector.blit(input, 0, result, 0, length); @@ -526,7 +527,7 @@ class MultiwordArithmetic { } else if (shift < 32) { _lsl32(result, 0, input, length, shift); } else { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } } @@ -575,7 +576,7 @@ class MultiwordArithmetic { public static function setZero(dest:Vector, length:Int):Void { if (dest.length < length) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } for (i in 0...length) { dest.set(i, 0); @@ -584,7 +585,7 @@ class MultiwordArithmetic { public static function setFromIntUnsigned(dest:Vector, length:Int, value:Int):Void { if (dest.length < length) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } dest.set(0, value); for (i in 1...length) { @@ -594,14 +595,14 @@ class MultiwordArithmetic { public static function setFromHexUnsigned(dest:Vector, length:Int, value:String):Bool { if ((value == null) || (dest == null)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if (dest.length < length) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } var index = value.length; if (index <= 0) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if (length < 1) { return false; @@ -629,7 +630,7 @@ class MultiwordArithmetic { } else if (c == 32) { continue; } else { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } acc |= c << bit; bit += 4; @@ -695,7 +696,7 @@ class MultiwordArithmetic { public static function copy(dest:Vector, source:Vector, length:Int):Void { if (dest.length < length) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } Vector.blit(source, 0, dest, 0, length); } diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index 82464f4b19c..fabf7a57b4b 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -22,7 +22,8 @@ package haxe.math.bigint; -import haxe.math.bigint.BigIntExceptions; +import haxe.math.bigint.BigIntException; +import haxe.math.bigint.BigIntError; import haxe.math.bigint.BigIntHelper; import haxe.ds.Vector; import haxe.io.Bytes; @@ -67,12 +68,12 @@ class MutableBigInt_ extends BigInt_ { **/ public function setFromString(value:String):Void { if ((value == null) || (value.length < 1)) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } var negate = value.charCodeAt(0) == 0x2d; var index = negate ? 1 : 0; if (value.length <= index) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } this.setFromInt(0); var t = new MutableBigInt_(); @@ -82,7 +83,7 @@ class MutableBigInt_ extends BigInt_ { BigIntArithmetic.multiplyInt(t, this, 10); BigIntArithmetic.addInt(this, t, c - 48); } else { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } } if (negate) { @@ -108,13 +109,13 @@ class MutableBigInt_ extends BigInt_ { public function setFromBigEndianBytesSigned(value:Bytes, offset:Int = 0, valueLength:Int = 0):Void { if (value == null) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if (valueLength <= 0) { valueLength = value.length; } if (offset + valueLength > value.length) { - throw BigIntExceptions.BUFFER_TOO_SMALL; + throw new BigIntException(BigIntError.BUFFER_TOO_SMALL); } if (valueLength < 1) { setFromInt(0); @@ -145,7 +146,7 @@ class MutableBigInt_ extends BigInt_ { valueLength = value.length; } if (offset + valueLength > value.length) { - throw BigIntExceptions.BUFFER_TOO_SMALL; + throw new BigIntException(BigIntError.BUFFER_TOO_SMALL); } if (valueLength < 1) { setFromInt(0); @@ -177,7 +178,7 @@ class MutableBigInt_ extends BigInt_ { valueLength = value.length; } if (offset + valueLength > value.length) { - throw BigIntExceptions.BUFFER_TOO_SMALL; + throw new BigIntException(BigIntError.BUFFER_TOO_SMALL); } if (valueLength < 1) { setFromInt(0); @@ -292,7 +293,7 @@ class MutableBigInt_ extends BigInt_ { @:noCompletion private function ensureCapacityProd(n:Int, preserve:Bool):Void { if (n < 1) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if ((!m_owned) || (m_data == null) || (n > m_data.length)) { n = BigIntHelper.clp2(n); @@ -344,11 +345,11 @@ class MutableBigInt_ extends BigInt_ { private function _setFromHex(value:String, signed:Bool):Void { if (value == null) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } var index = value.length; if (index <= 0) { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } var extra:Int = signed ? 0 : 1; ensureCapacity(((index + 7) >> 3) + extra, false); @@ -366,7 +367,7 @@ class MutableBigInt_ extends BigInt_ { } else if (c == 32) { continue; } else { - throw BigIntExceptions.INVALID_ARGUMENT; + throw new BigIntException(BigIntError.INVALID_ARGUMENT); } if (bit >= 32) { m_data.set(++pos, 0); diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 07ece5de82f..018fda1a8ac 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -7,7 +7,7 @@ import haxe.math.bigint.BigInt_; import haxe.ds.Vector; import haxe.io.Bytes; import haxe.math.bigint.BigIntArithmetic; -import haxe.math.bigint.BigIntExceptions; +import haxe.math.bigint.BigIntError; import haxe.math.bigint.BigIntTools; import haxe.math.bigint.MutableBigInt; import haxe.math.bigint.BigInt; @@ -62,7 +62,7 @@ class TestBigInt extends Test { try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } eq("00000000", dividend.toHex()); } @@ -391,23 +391,23 @@ class TestBigInt extends Test { try { BigIntArithmetic.multiply(a, a, BigInt.fromInt(2)); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { BigIntArithmetic.multiply(a, BigInt.fromInt(2), a); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // division by zero should throw exception try { BigInt.fromInt(1) / 0; } catch (e) { - eq( e.message, BigIntExceptions.DIVISION_BY_ZERO); + eq( e.message, BigIntError.DIVISION_BY_ZERO); } try { BigInt.fromInt(0) / 0; } catch (e) { - eq( e.message, BigIntExceptions.DIVISION_BY_ZERO); + eq( e.message, BigIntError.DIVISION_BY_ZERO); } // Multiplication of same inputs is ok @@ -545,19 +545,19 @@ class TestBigInt extends Test { try { BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), quotient, quotient); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // quotient cannot be null try { BigIntArithmetic.divideInt(BigInt.fromInt(1), 10, null); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { BigIntArithmetic.divide(BigInt.fromInt(1), BigInt.fromInt(10), null, remainder); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // remainder can be null @@ -574,22 +574,22 @@ class TestBigInt extends Test { try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, dividend); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, divisor); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, quotient); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { BigIntArithmetic.divide(dividend, divisor, quotient, remainder, remainder); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } } @@ -953,27 +953,27 @@ class TestBigInt extends Test { try { var x = BigInt.fromString(null); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { var x = BigInt.fromString(""); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { var x = BigInt.fromString("-"); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { var x = BigInt.fromString(" 0"); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { var x = BigInt.fromString("0 "); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } eq("0", BigInt.fromString("0").toString()); @@ -1001,7 +1001,7 @@ class TestBigInt extends Test { try { var x = BigInt.fromBytes(null); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } eq("0", BigInt.fromBytes(Bytes.ofHex("00")).toString()); eq("1", BigInt.fromBytes(Bytes.ofHex("01")).toString()); @@ -1039,17 +1039,17 @@ class TestBigInt extends Test { try { a <<= -1; } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { a << -1; } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { BigInt.ONE << -1; } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } asl(BigInt.ONE, 1, BigInt.fromInt(2)); @@ -1123,17 +1123,17 @@ class TestBigInt extends Test { try { var x = BigInt.fromHex(null); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { var x = BigInt.fromHex(""); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { var x = BigInt.fromHex("0q0"); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } var sb = new StringBuf(); @@ -1266,30 +1266,30 @@ class TestBigInt extends Test { try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.arithmeticShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // result and input overlap @@ -1326,30 +1326,30 @@ class TestBigInt extends Test { try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, -1); // shift negative } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 2, 32); // shift 32 } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 1), fromInt(1, 2), 2, 1); // result too short } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 1), 2, 1); // input too short } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.logicalShiftRight(fromInt(0, 2), fromInt(1, 2), 0, 1); // length too short } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // result and input overlap @@ -1418,22 +1418,22 @@ class TestBigInt extends Test { try { MultiwordArithmetic.subtract(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.subtract(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } } @@ -1464,23 +1464,23 @@ class TestBigInt extends Test { try { MultiwordArithmetic.add(fromInt(0, 1), fromInt(0, 2), fromInt(0, 2), 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 1), fromInt(0, 2), 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 1), 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.add(fromInt(0, 2), fromInt(0, 2), fromInt(0, 2), 0); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } } @@ -1637,27 +1637,27 @@ class TestBigInt extends Test { try { MultiwordArithmetic.setFromHexUnsigned(value, 1, null); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.setFromHexUnsigned(value, 1, ""); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.setFromHexUnsigned(null, 1, "0"); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.setFromHexUnsigned(value, 2, "0"); // buffer too small } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.setFromHexUnsigned(value, 1, "0g0"); // invalid char } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } value = new Vector(3); @@ -1708,18 +1708,18 @@ class TestBigInt extends Test { try { MultiwordArithmetic.multiplyUnsigned(result, result, 1, fromInt(2), 1); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyUnsigned(result, fromInt(2), 1, result, 1); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyIntUnsigned(result, result, 1, 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // Multiplication of same inputs is ok @@ -1732,29 +1732,29 @@ class TestBigInt extends Test { try { MultiwordArithmetic.multiplyUnsigned(fromInt(0), fromInt(2), 1, fromInt(2), 1); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0), fromInt(2), 1, 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // check input lengths try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 0, fromInt(2), 1); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 2), fromInt(2), 1, fromInt(2), 0); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 2), fromInt(2), 0, 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // check input bounds @@ -1762,17 +1762,17 @@ class TestBigInt extends Test { try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 1), 2, fromInt(2, 2), 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyUnsigned(fromInt(0, 4), fromInt(2, 2), 2, fromInt(2, 1), 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.multiplyIntUnsigned(fromInt(0, 4), fromInt(2, 1), 2, 2); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } } @@ -1916,32 +1916,32 @@ class TestBigInt extends Test { try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, quotient, work); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // quotient cannot be null try { MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, null, work); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, null, remainder, work); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // work cannot be null try { MultiwordArithmetic.divideIntUnsigned(fromInt(1), 1, 10, quotient, null); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(fromInt(1), 1, fromInt(10), 1, quotient, remainder, null); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // remainder can be null @@ -1958,23 +1958,23 @@ class TestBigInt extends Test { try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, dividend); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, divisor); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, quotient); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, quotient, remainder, remainder); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // bounds @@ -1982,36 +1982,36 @@ class TestBigInt extends Test { try { MultiwordArithmetic.divideUnsigned(dividend, 0, divisor, divisor.length, quotient, remainder, work); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, 0, quotient, remainder, work); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, divisor, divisor.length, new Vector(0), remainder, work); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } // division by zero try { MultiwordArithmetic.divideIntUnsigned(dividend, dividend.length, 0, quotient, work); } catch (e) { - eq( e.message, BigIntExceptions.DIVISION_BY_ZERO); + eq( e.message, BigIntError.DIVISION_BY_ZERO); } try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromInt(0), 1, quotient, remainder, work); } catch (e) { - eq( e.message, BigIntExceptions.DIVISION_BY_ZERO); + eq( e.message, BigIntError.DIVISION_BY_ZERO); } // divisor with leading 0 try { MultiwordArithmetic.divideUnsigned(dividend, dividend.length, fromHex("1", 2), 2, quotient, remainder, work); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } } @@ -2813,7 +2813,7 @@ class TestBigInt extends Test { try { randomBigInt = BigInt.randomInRange(a,b); } catch (e) { - eq(e.message, BigIntExceptions.INVALID_ARGUMENT); + eq(e.message, BigIntError.INVALID_ARGUMENT); } } From e4c22e6d68f900d35fd4d40cb381bac369554d69 Mon Sep 17 00:00:00 2001 From: flashultra Date: Wed, 22 Mar 2023 22:00:24 +0200 Subject: [PATCH 069/134] Remove memory limit for PHP test --- tests/runci/targets/Php.hx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/runci/targets/Php.hx b/tests/runci/targets/Php.hx index e09a0a4a6a8..8ae601ebca1 100644 --- a/tests/runci/targets/Php.hx +++ b/tests/runci/targets/Php.hx @@ -85,14 +85,18 @@ class Php { deleteDirectoryRecursively(binDir); runCommand("haxe", ["compile-php.hxml"].concat(prefix).concat(args)); - runCommand("php", generateArgs(binDir + "/index.php")); + var arguments:Array = generateArgs(binDir + "/index.php"); + arguments.push("-d memory_limit=-1"); + runCommand("php", arguments); changeDirectory(sysDir); if(isCi()) deleteDirectoryRecursively(binDir); runCommand("haxe", ["compile-php.hxml"].concat(prefix).concat(args)); - runSysTest("php", generateArgs(binDir + "/Main/index.php")); + arguments = generateArgs(binDir + "/Main/index.php"); + arguments.push("-d memory_limit=-1"); + runSysTest("php", arguments); } } } From ec9646c2de1a77b2eaeebb5a2837749aeb9b792e Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 23 Mar 2023 07:46:16 +0200 Subject: [PATCH 070/134] Fix for php test --- tests/runci/targets/Php.hx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/runci/targets/Php.hx b/tests/runci/targets/Php.hx index 8ae601ebca1..d8baaf14d3d 100644 --- a/tests/runci/targets/Php.hx +++ b/tests/runci/targets/Php.hx @@ -22,12 +22,14 @@ class Php { static function generateArgs(file:String) { if (systemName != "Windows") - return [file]; + return ["-d","memory_limit=-1",file]; return [ "-c", windowsPhpIni, "-d", 'extension_dir=$windowsPhpExtPath', + "-d", + "memory_limit=-1", file ]; } @@ -85,18 +87,14 @@ class Php { deleteDirectoryRecursively(binDir); runCommand("haxe", ["compile-php.hxml"].concat(prefix).concat(args)); - var arguments:Array = generateArgs(binDir + "/index.php"); - arguments.push("-d memory_limit=-1"); - runCommand("php", arguments); + runCommand("php", generateArgs(binDir + "/index.php")); changeDirectory(sysDir); if(isCi()) deleteDirectoryRecursively(binDir); runCommand("haxe", ["compile-php.hxml"].concat(prefix).concat(args)); - arguments = generateArgs(binDir + "/Main/index.php"); - arguments.push("-d memory_limit=-1"); - runSysTest("php", arguments); + runSysTest("php", generateArgs(binDir + "/Main/index.php")); } } } From 51774494ae1887e474b850449c83aac2649ed66c Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 6 Apr 2023 12:58:37 +0300 Subject: [PATCH 071/134] Add from/to different base --- std/haxe/math/bigint/BigInt.hx | 8 ++-- std/haxe/math/bigint/BigInt_.hx | 15 +++++-- std/haxe/math/bigint/MultiwordArithmetic.hx | 45 +++++++++++++++++---- std/haxe/math/bigint/MutableBigInt_.hx | 37 +++++++++++++++-- 4 files changed, 85 insertions(+), 20 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 6939c507241..ca8ed6598a6 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -72,8 +72,8 @@ abstract BigInt(BigInt_) { return new BigInt(this.max(other)); } - public inline function toString():String { - return BigInt_.toString1(this); + public inline function toString(radix:Int=10):String { + return BigInt_.toString1(this,radix); } public inline function toHex():String { @@ -92,8 +92,8 @@ abstract BigInt(BigInt_) { return new BigInt(BigInt_.fromInt(value)); } - public static inline function fromString(value:String):BigInt { - return new BigInt(BigInt_.fromString(value)); + public static inline function fromString(value:String,radix:Int=10):BigInt { + return new BigInt(BigInt_.fromString(value,radix)); } public static inline function fromHex(value:String):BigInt { diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 4d34c6acbcf..c364a9ade95 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -276,6 +276,11 @@ class BigInt_ { public inline function toString():String { return MultiwordArithmetic.toDecimalSigned(m_data, m_count); } + + public inline function toBase(radix:Int):String + { + return MultiwordArithmetic.toBaseString(m_data, m_count,radix); + } /** Get the value in hexadecimal form. @@ -342,9 +347,9 @@ class BigInt_ { /** Creates a big integer with the value represented by the decimal string `value`. **/ - public static function fromString(value:String):BigInt_ { + public static function fromString(value:String,radix:Int=10):BigInt_ { var bi = new MutableBigInt_(); - bi.setFromString(value); + bi.setFromString(value,radix); return bi; } @@ -857,8 +862,10 @@ class BigInt_ { } @:noCompletion - private static inline function toString1(a:BigInt_):String { - return a.toString(); + private static inline function toString1(a:BigInt_, radix:Int):String { + if ((radix == 10 ) || ( radix <2 || radix >36 )) return a.toString(); + if (radix == 16 ) return a.toHex(); + return a.toBase(radix); } @:noCompletion diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 2f167342ead..3b9a2367116 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -683,6 +683,22 @@ class MultiwordArithmetic { } return _toDecimal(sb, work, length); } + + public static function toBaseString(value : Vector, length : Int, radix:Int) : String + { + var sb = new StringBuf(); + var work = new Vector(length); + if (isNegative(value, length)) + { + negate(work, value, length); + sb.addChar(45); // '-' + } + else + { + copy(work, value, length); + } + return _toBase(sb, work, length, radix); + } /** Get the value in decimal form. @@ -770,17 +786,30 @@ class MultiwordArithmetic { @:noCompletion private static function _toDecimal(sb:StringBuf, value:Vector, length:Int):String { + return _toBase(sb,value,length,10); + } + + @:noCompletion + private static function _toBase(sb : StringBuf, value : Vector, length : Int, radix:Int) : String + { length = getLengthUnsigned(value, length); - var digits = new Vector(length * 10); // it is really log10 2^32 ~= 9.633, but this is close, simple, and never too little - var work = new Vector(length + 1 + 1); - var pos:Int = digits.length; - var r:Int; - do { - r = divideIntUnsigned(value, length, 10, value, work); + var digits = new Vector(length * Math.ceil(Math.log(4294967296)/Math.log(radix))); + var work = new Vector(length + 1 + 1); + var pos : Int = digits.length; + var r : Int; + do + { + r = divideIntUnsigned(value, length, radix, value, work); length = getLengthUnsigned(value, length); - digits.set(--pos, r + 48); + if ( r < 10) { + digits.set(--pos, r + 48); + } else { + trace(r); + digits.set(--pos, r + 87); + } } while (!isZero(value, length)); - for (i in pos...digits.length) { + for (i in pos ... digits.length) + { sb.addChar(digits.get(i)); } return sb.toString(); diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index fabf7a57b4b..174b62a0397 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -66,7 +66,7 @@ class MutableBigInt_ extends BigInt_ { /** Set the value of this big integer with the value represented by the decimal string `value`. **/ - public function setFromString(value:String):Void { + public function setFromString(value:String, radix:Int = 10):Void { if ((value == null) || (value.length < 1)) { throw new BigIntException(BigIntError.INVALID_ARGUMENT); } @@ -75,13 +75,42 @@ class MutableBigInt_ extends BigInt_ { if (value.length <= index) { throw new BigIntException(BigIntError.INVALID_ARGUMENT); } + if ( value.charCodeAt(index) == 0x30) { + if ( value.charCodeAt(index+1) == 0x62 ) { // binary + radix = 2; + index +=2; + } else if ( value.charCodeAt(index+1) == 0x6F ) { //octal + radix = 8; + index +=2; + } else if ( value.charCodeAt(index+1) == 0x78 ) { // hex + setFromHexSigned((negate?"-":"")+value.substr(index+2)); + return; + } + } + if (radix == 16) { + setFromHexSigned(value); + return; + } this.setFromInt(0); var t = new MutableBigInt_(); + var endDigit:Int = 57; + var extraEndDigit:Int=0; + if ( radix <= 10 ) { + endDigit = 48 + radix-1; + } else { + extraEndDigit = radix-11; + } for (i in index...value.length) { var c = value.charCodeAt(i); - if ((48 <= c) && (c <= 57)) { - BigIntArithmetic.multiplyInt(t, this, 10); - BigIntArithmetic.addInt(this, t, c - 48); + if ( ((48 <= c) && (c <= endDigit)) || (radix > 10 && ( (65<=c && c<=(65+extraEndDigit)) || (97<=c && c<=(97+extraEndDigit)) ) ) ) { + BigIntArithmetic.multiplyInt(t, this, radix); + if ( c <= endDigit) { + BigIntArithmetic.addInt(this, t, c - 48); + } else if (c<=(65+extraEndDigit)) { + BigIntArithmetic.addInt(this, t, c - 55); + } else { + BigIntArithmetic.addInt(this, t, c - 87); + } } else { throw new BigIntException(BigIntError.INVALID_ARGUMENT); } From 0a7500c37358039e3e1a67aed131c0c2216b71ae Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 6 Apr 2023 13:04:24 +0300 Subject: [PATCH 072/134] Remove trace() --- std/haxe/math/bigint/MultiwordArithmetic.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/std/haxe/math/bigint/MultiwordArithmetic.hx b/std/haxe/math/bigint/MultiwordArithmetic.hx index 3b9a2367116..4fa68c30ae1 100644 --- a/std/haxe/math/bigint/MultiwordArithmetic.hx +++ b/std/haxe/math/bigint/MultiwordArithmetic.hx @@ -804,7 +804,6 @@ class MultiwordArithmetic { if ( r < 10) { digits.set(--pos, r + 48); } else { - trace(r); digits.set(--pos, r + 87); } } while (!isZero(value, length)); From b664dcc4fb3af8367f5aedf63366895a263099fd Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 6 Apr 2023 13:57:21 +0300 Subject: [PATCH 073/134] Fix for toString() --- std/haxe/math/bigint/MutableBigInt.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/std/haxe/math/bigint/MutableBigInt.hx b/std/haxe/math/bigint/MutableBigInt.hx index 2f63cff78b8..1f8f59fb21d 100644 --- a/std/haxe/math/bigint/MutableBigInt.hx +++ b/std/haxe/math/bigint/MutableBigInt.hx @@ -43,8 +43,8 @@ abstract MutableBigInt(MutableBigInt_) { return BigInt_.isNegative1(this); } - public inline function toString():String { - return BigInt_.toString1(this); + public inline function toString(radix:Int=10):String { + return BigInt_.toString1(this,radix); } public inline function toHex():String { From 5da8f75d82577c0a528643539a3eab4ee986cd15 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 6 Jan 2024 15:32:32 +0200 Subject: [PATCH 074/134] Add Montgomery and Barrett reduction for modPow --- std/haxe/math/bigint/BigInt_.hx | 460 ++++++++++++++++++++++++- std/haxe/math/bigint/MutableBigInt.hx | 6 + std/haxe/math/bigint/MutableBigInt_.hx | 7 + 3 files changed, 460 insertions(+), 13 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index c364a9ade95..f33c577b179 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -398,21 +398,29 @@ class BigInt_ { } public function modPow(exponent:BigInt_, modulus:BigInt_):BigInt_ { - if (BigIntArithmetic.compareInt(exponent, 0) < 0) - throw new BigIntException(BigIntError.NEGATIVE_EXPONENT); + if (BigIntArithmetic.compareInt(modulus, 0) < 0) + throw BigIntExceptions.NEGATIVE_MODULUS; + if (BigIntArithmetic.compareInt(modulus, 1) == 0) + return BigInt.fromInt(0); + if (BigIntArithmetic.compareInt(exponent, 0) == 0) + return BigInt.fromInt(1); if (this.isZero()) - return (BigIntArithmetic.compareInt(exponent, 0) == 0 ? BigInt.fromInt(1) : this); - var r = BigInt_.newFromInt(1); - var p:BigInt_ = this; - while (true) { - if (BigIntArithmetic.bitwiseAndInt(exponent, 1) == 1) - r = modulus2(multiply2(p, r), modulus); - exponent = BigInt_.arithmeticShiftRight2(exponent, 1); - if (BigIntArithmetic.compareInt(exponent, 0) == 0) - break; - p = modulus2(multiply2(p, p), modulus); + return BigInt.fromInt(0); + var negExponent:Bool = (BigIntArithmetic.compareInt(exponent, 0) < 0); + if (negExponent) + exponent = BigInt_.negate1(exponent); + var result:BigInt_ = modulus2(this, modulus); + if (BigIntArithmetic.compareInt(exponent, 1) != 0) { + if ((modulus.m_data.get(0) & 1) == 0) { + result = modPowBarrett(result, exponent, modulus); + } else { + result = modPowMonty(result, exponent, modulus, true); + } } - return r; + if (negExponent) { + result = result.modInverse(modulus); + } + return result; } public function pow(exponent:UInt):BigInt_ { @@ -681,6 +689,421 @@ class BigInt_ { return d; } + private function modPowMonty(b:BigInt_, _e:BigInt_, _m:BigInt_, convert:Bool):BigInt_ { + var n:Int, + powR:Int, + extraBits:Int, + expLength:Int, + numPowers:Int32, + i:Int, + window:Int32, + mult:Int, + lastZeroes:Int, + windowPos:Int, + bits:Int, + j:Int; + var smallMontyModulus:Bool; + var mDash:Int32; + var yAccum:Vector, + zVal:Vector, + tmp:Vector, + zSquared:Vector, + windowList:Vector, + yVal:Vector; + var oddPowers:Vector>; + var m:BigInt_ = _m, e:BigInt_ = _e; + n = m.m_count; + powR = 32 * n; + smallMontyModulus = (m.bitLength() + 2) <= powR; + mDash = m.getMQuote(); + if (convert) { + b = divMod(BigInt_.arithmeticShiftLeft2(b, powR), m).remainder; + } + yAccum = new Vector(n + 1); + zVal = b.m_data; + var zLen = b.m_count; + if (zLen < n) { + tmp = new Vector(n); + Vector.blit(zVal, 0, tmp, n - zLen, zLen); + zVal = tmp; + } + extraBits = 0; + if (e.m_count > 1 || e.bitCount() > 2) { + expLength = e.bitLength(); + while (expLength > expWindowThresholds[extraBits]) + extraBits++; + } + numPowers = 1 << extraBits; + oddPowers = new Vector>(numPowers); + oddPowers[0] = zVal; + zSquared = zVal.copy(); + squareMonty(yAccum, zSquared, m.m_data, m.m_count, mDash, smallMontyModulus); + for (i in 1...numPowers) { + oddPowers[i] = oddPowers[i - 1].copy(); + multiplyMonty(yAccum, oddPowers[i], zSquared, m.m_data, m.m_count, mDash, smallMontyModulus); + } + windowList = getWindowList(e.m_data, e.m_count, extraBits); + window = windowList[0]; + mult = window & 0xFF; + lastZeroes = window >> 8; + if (mult == 1) { + yVal = zSquared; + lastZeroes--; + } else { + yVal = oddPowers[mult >> 1].copy(); + } + windowPos = 1; + window = windowList[windowPos]; + windowPos++; + while (window != -1) { + mult = window & 0xFF; + bits = lastZeroes + BitLengthTable[mult]; + j = 0; + while (j < bits) { + squareMonty(yAccum, yVal, m.m_data, m.m_count, mDash, smallMontyModulus); + j++; + } + multiplyMonty(yAccum, yVal, oddPowers[mult >> 1], m.m_data, m.m_count, mDash, smallMontyModulus); + lastZeroes = window >> 8; + window = windowList[windowPos]; + windowPos++; + } + for (i in 0...lastZeroes) { + squareMonty(yAccum, yVal, m.m_data, m.m_count, mDash, smallMontyModulus); + } + if (convert) { + montgomeryReduce(yVal, m.m_data, m.m_count, mDash); + } else if (smallMontyModulus && MultiwordArithmetic.compareUnsigned(yVal, m.m_data, yVal.length) >= 0) { + var result:Vector = new Vector(yVal.length); + MultiwordArithmetic.subtract(result, yVal, m.m_data, result.length); // a = a-m; + Vector.blit(result, 0, yVal, 0, result.length); + } + var montResult:BigInt_ = BigInt_.fromUnsignedInts(yVal); + return montResult; + } + + private function squareMonty(a:Vector, x:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { + var n:Int, aMax:Int, j:Int, i:Int; + var xVal:Int, a0:Int; + var x0:Int64, carry:Int64, t:Int64, prod1:Int64, prod2:Int64, xi:Int64, u:Int64; + n = mLen; + x0 = Int64.make(0, x[0]); + carry = Int64.mul(x0, x0); + u = Int64.make(0, Int64.mul(carry.low, mDash).low); + prod2 = Int64.mul(u, Int64.make(0, m[0])); + carry = Int64.add(carry, Int64.make(0, prod2.low)); + carry = Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod2, 32)); + j = 1; + while (j < mLen) { + prod1 = Int64.mul(x0, Int64.make(0, x[j])); + prod2 = Int64.mul(u, Int64.make(0, m[j])); + carry = Int64.add(carry, Int64.add(Int64.make(0, Int64.shl(prod1, 1).low), Int64.make(0, prod2.low))); + a[j - 1] = carry.low; + carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod2, 32)), Int64.ushr(prod1, 31)); + j++; + } + a[mLen] = Int64.ushr(carry, 32).low; + a[mLen - 1] = carry.low; + i = 1; + while (i < mLen) { + a0 = a[0]; + u = Int64.make(0, Int64.mul(a0, mDash).low); + carry = Int64.add(Int64.mul(u, Int64.make(0, m[0])), Int64.make(0, a0)); + carry = Int64.ushr(carry, 32); + j = 1; + while (j < i) { + carry = Int64.add(carry, Int64.add(Int64.mul(u, Int64.make(0, m[j])), Int64.make(0, a[j]))); + a[j - 1] = carry.low; + carry = Int64.ushr(carry, 32); + j++; + } + xi = Int64.make(0, x[i]); + prod1 = Int64.mul(xi, xi); + prod2 = Int64.mul(u, Int64.make(0, m[i])); + carry += Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.make(0, a[i])); + a[i - 1] = carry.low; + carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 32)), Int64.ushr(prod2, 32)); + j = i + 1; + while (j < n) { + prod1 = Int64.mul(xi, Int64.make(0, x[j])); + prod2 = Int64.mul(u, Int64.make(0, m[j])); + carry = Int64.add(carry, Int64.add(Int64.add(Int64.make(0, Int64.shl(prod1, 1).low), Int64.make(0, prod2.low)), Int64.make(0, a[j]))); + a[j - 1] = carry.low; + carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 31)), Int64.ushr(prod2, 32)); + j++; + } + carry = Int64.add(carry, Int64.make(0, a[n])); + a[n] = Int64.ushr(carry, 32).low; + a[n - 1] = carry.low; + i++; + } + + if (!smallMontyModulus && MultiwordArithmetic.compareUnsigned(a, m, a.length) >= 0) { + var result:Vector = new Vector(a.length); + MultiwordArithmetic.subtract(result, a, m, result.length); + Vector.blit(result, 0, a, 0, result.length); + } + Vector.blit(a, 0, x, 0, n); + } + + private function multiplyMonty(a:Vector, x:Vector, y:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { + var n:Int, aMax:Int, j:Int, i:Int; + var a0:Int64, y0:Int64; + var carry:Int64, t:Int64, prod1:Int64, prod2:Int64, xi:Int64, u:Int64; + n = mLen; + y0 = Int64.make(0, y[0]); + i = 0; + while (i <= n) { + a[i] = 0; + i++; + } + i = 0; + while (i < n) { + a0 = Int64.make(0, a[0]); + xi = Int64.make(0, x[i]); + prod1 = Int64.mul(xi, y0); + carry = Int64.add(Int64.make(0, prod1.low), a0); + u = Int64.make(0, Int64.mul(carry.low, mDash).low); + prod2 = Int64.mul(u, Int64.make(0, m[0])); + carry = Int64.add(carry, Int64.make(0, prod2.low)); + carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 32)), Int64.ushr(prod2, 32)); + j = 1; + while (j <= (n - 1)) { + prod1 = Int64.mul(xi, Int64.make(0, y[j])); + prod2 = Int64.mul(u, Int64.make(0, m[j])); + carry = Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.add(Int64.make(0, a[j]), carry)); + a[j - 1] = carry.low; + carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 32)), Int64.ushr(prod2, 32)); + j++; + } + carry = Int64.add(carry, Int64.make(0, a[n])); + a[n] = Int64.ushr(carry, 32).low; + a[n - 1] = carry.low; + i++; + } + + if (!smallMontyModulus && MultiwordArithmetic.compareUnsigned(a, m, a.length) >= 0) { + var result:Vector = new Vector(a.length); + MultiwordArithmetic.subtract(result, a, m, result.length); + Vector.blit(result, 0, a, 0, result.length); + } + Vector.blit(a, 0, x, 0, n); + } + + private function montgomeryReduce(x:Vector, m:Vector, mLen:Int, mDash:Int32):Void { + var n:Int, i:Int, j:Int; + var x0:Int; + var t:Int64, carry:Int64; + n = mLen; + i = 0; + while (i < n) { + x0 = x[0]; + t = Int64.make(0, Int64.mul(x0, mDash).low); + carry = Int64.add(Int64.mul(t, Int64.make(0, m[0])), Int64.make(0, x0)); + carry = Int64.ushr(carry, 32); + j = 1; + while (j < n) { + carry = Int64.add(carry, Int64.add(Int64.mul(t, Int64.make(0, m[j])), Int64.make(0, x[j]))); + x[j - 1] = carry.low; + carry = Int64.ushr(carry, 32); + j++; + } + x[n - 1] = carry.low; + i++; + } + if (MultiwordArithmetic.compareUnsigned(x, m, x.length) >= 0) { + var result:Vector = new Vector(x.length); + MultiwordArithmetic.subtract(result, x, m, result.length); + Vector.blit(result, 0, x, 0, result.length); + } + } + + private function getMQuote():Int32 { + var d:Int = -m_data[0]; + var mQuote:Int32 = modInverse32(d); + return mQuote; + } + + private function modInverse32(d:Int):Int32 { + var x:Int32; + x = d + (((d + 1) & 4) << 1); + x = x * (2 - (d * x)); + x = x * (2 - (d * x)); + x = x * (2 - (d * x)); + return x; + } + + private function modPowBarrett(base:BigInt_, exponent:BigInt_, modulus:BigInt_):BigInt_ { + var i:Int, j:Int, k:Int; + var extraBits:Int, + expLength:Int, + numPowers:Int32, + window:Int32, + mult:Int, + lastZeroes:Int, + windowPos:Int, + bits:Int; + var mr:BigInt_, yu:BigInt_, b2:BigInt_, y:BigInt_; + var e:BigInt_ = exponent; + var m:BigInt_ = modulus; + var oddPowers:Vector; + var windowList:Vector; + + k = m.m_count; + mr = BigInt_.arithmeticShiftLeft2(BigInt.ONE, (k + 1) << 5); + yu = BigInt_.divide2(BigInt_.arithmeticShiftLeft2(BigInt.ONE, k << 6), m); + extraBits = 0; + expLength = e.bitLength(); + while (expLength > expWindowThresholds[extraBits]) + extraBits++; + numPowers = 1 << extraBits; + oddPowers = new Vector(numPowers); + oddPowers[0] = base; + b2 = reduceBarrett(base.square(), m, mr, yu); + for (i in 1...numPowers) { + oddPowers[i] = reduceBarrett(multiply2(oddPowers[i - 1], b2), m, mr, yu); + } + + windowList = getWindowList(e.m_data, e.m_count, extraBits); + window = windowList[0]; + mult = window & 0xFF; + lastZeroes = window >> 8; + if (mult == 1) { + y = b2; + lastZeroes--; + } else { + y = oddPowers[mult >> 1]; + } + + windowPos = 1; + window = windowList[windowPos]; + windowPos++; + while (window != -1) { + mult = window & 0xFF; + bits = lastZeroes + BitLengthTable[mult]; + j = 0; + while (j < bits) { + y = reduceBarrett(y.square(), m, mr, yu); + j++; + } + y = reduceBarrett(multiply2(y, (oddPowers[mult >> 1])), m, mr, yu); + lastZeroes = window >> 8; + window = windowList[windowPos]; + windowPos++; + } + i = 0; + while (i < lastZeroes) { + y = reduceBarrett(y.square(), m, mr, yu); + i++; + } + + return y; + } + + private function getWindowList(mag:Vector, magLen:Int, extraBits:Int):Vector { + var i:Int, + v:Int32, + leadingBits:Int, + resultSize:Int, + resultPos:Int, + bitPos:Int, + mult:Int32, + multLimit:Int32, + zeroes:Int32; + v = mag[magLen - 1]; + leadingBits = BigIntHelper.bitLen(v); + resultSize = Math.floor((((magLen - 1) << 5) + leadingBits) / (1 + extraBits) + 2); + var result:Vector = new Vector(resultSize); + resultPos = 0; + bitPos = 33 - leadingBits; + v = v << bitPos; + mult = 1; + multLimit = 1 << extraBits; + zeroes = 0; + i = magLen - 1; + while (i >= 0) { + while (bitPos < 32) { + if (mult < multLimit) { + mult = (mult << 1) | (v >>> 31); + } else if (v < 0) { + result[resultPos] = createWindowEntry(mult, zeroes); + resultPos++; + mult = 1; + zeroes = 0; + } else + zeroes++; + + v = v << 1; + bitPos++; + } + i--; + if (i < 0) { + result[resultPos] = createWindowEntry(mult, zeroes); + resultPos++; + break; + } + v = mag[i]; + bitPos = 0; + } + result[resultPos] = -1; + return result; + } + + private function createWindowEntry(mult:Int32, zeroes:Int32):Int32 { + while ((mult & 1) == 0) { + mult >>>= 1; + ++zeroes; + } + return mult | (zeroes << 8); + } + + private function reduceBarrett(x:BigInt_, m:BigInt_, mr:BigInt_, yu:BigInt_):BigInt_ { + var timestamp:Float = Timer.stamp(); + var xLen:Int, mLen:Int, k:Int; + var q1:BigInt_, q2:BigInt_, q3:BigInt_, r1:BigInt_, r2:BigInt_, r3:BigInt_; + xLen = x.bitLength(); + mLen = m.bitLength(); + if (xLen < mLen) { + return x; + } + if ((xLen - mLen) > 1) { + var k:Int = m.m_count; + var q1:BigInt_ = x.divideWords(k - 1); + var q2:BigInt_ = multiply2(yu, q1); + var q3:BigInt_ = q2.divideWords(k + 1); + var r1:BigInt_ = x.remainderWords(k + 1); + var r2:BigInt_ = multiply2(q3, m); + var r3:BigInt_ = r2.remainderWords(k + 1); + x = sub2(r1, r3); + if (x.sign() < 0) { + x = add2(x, mr); + } + } + + while (BigIntArithmetic.compare(x, m) >= 0) { + x = sub2(x, m); + } + return x; + } + + private function divideWords(w:Int):BigInt_ { + var n:Int = m_count; + if (w >= n) + return BigInt.ZERO; + var bi = new MutableBigInt_(); + bi.setFromVector(m_data, m_count - (n - w), n - w); + return bi; + } + + private function remainderWords(w:Int):BigInt_ { + var n:Int = m_count; + if (w >= n) + return this; + var bi = new MutableBigInt_(); + bi.setFromVector(m_data, 0, w); + return bi; + } + private static function newFromInt(value:Int):BigInt_ { var bi = new MutableBigInt_(); bi.setFromInt(value); @@ -882,4 +1305,15 @@ class BigInt_ { private static inline function toInts1(a:BigInt_, v:Vector):Int { return a.toInts(v); } + + static final BitLengthTable:Array = [ + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8 + ]; + + var expWindowThresholds:Vector = Vector.fromArrayCopy([7, 25, 81, 241, 673, 1793, 4609, 2147483647]); } diff --git a/std/haxe/math/bigint/MutableBigInt.hx b/std/haxe/math/bigint/MutableBigInt.hx index 1f8f59fb21d..e90ad426cc9 100644 --- a/std/haxe/math/bigint/MutableBigInt.hx +++ b/std/haxe/math/bigint/MutableBigInt.hx @@ -68,6 +68,12 @@ abstract MutableBigInt(MutableBigInt_) { var a:MutableBigInt_ = this; a.setFromUnsignedInts(value, length); } + + public inline function setFromVector(source : Vector, sourcePosition:Int, length : Int ) : Void + { + var a:MutableBigInt_ = this; + a.setFromVector(source,sourcePosition, length); + } public inline function setFromBigEndianBytesUnsigned(value:Bytes, offset:Int = 0, length:Int = 0):Void { var a:MutableBigInt_ = this; diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index 174b62a0397..ba479b464f4 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -135,6 +135,13 @@ class MutableBigInt_ extends BigInt_ { m_count = length + neg; compact(); } + + public function setFromVector(source : Vector, sourcePosition:Int, length : Int ) : Void + { + ensureCapacity(length , false); + Vector.blit(source, sourcePosition, m_data, 0, length); + m_count = length; + } public function setFromBigEndianBytesSigned(value:Bytes, offset:Int = 0, valueLength:Int = 0):Void { if (value == null) { From 0d6f5847ce1e1c1618b47f4eca33569251d0f56b Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 6 Jan 2024 15:39:03 +0200 Subject: [PATCH 075/134] Add bitlen() --- std/haxe/math/bigint/BigIntHelper.hx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/std/haxe/math/bigint/BigIntHelper.hx b/std/haxe/math/bigint/BigIntHelper.hx index 531ada6c673..39ff37fa7f1 100644 --- a/std/haxe/math/bigint/BigIntHelper.hx +++ b/std/haxe/math/bigint/BigIntHelper.hx @@ -56,6 +56,11 @@ class BigIntHelper { m = y & (~y >> 1); return n + 2 - m; } + + public static function bitLen(x:Int):Int { + var sign:Int = (x<0)?-1:0; + return ( 32 - BigIntHelper.nlz(x^sign) ); + } /** "Ceiling power of two" -- round up to the least power of two From 4cb131d9afddfe7f3c68f96911c858c7e95f1ff5 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 6 Jan 2024 15:45:19 +0200 Subject: [PATCH 076/134] Fix typo --- std/haxe/math/bigint/BigInt_.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index f33c577b179..ef99db6e1c1 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -399,7 +399,7 @@ class BigInt_ { public function modPow(exponent:BigInt_, modulus:BigInt_):BigInt_ { if (BigIntArithmetic.compareInt(modulus, 0) < 0) - throw BigIntExceptions.NEGATIVE_MODULUS; + throw BigIntError.NEGATIVE_MODULUS; if (BigIntArithmetic.compareInt(modulus, 1) == 0) return BigInt.fromInt(0); if (BigIntArithmetic.compareInt(exponent, 0) == 0) From 2173c8abec19cee64e17e3244dde5ed85d7db780 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 7 Jan 2024 07:58:12 +0200 Subject: [PATCH 077/134] Add compareMonty() and subtractMonty() --- std/haxe/math/bigint/BigInt_.hx | 68 +++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index ef99db6e1c1..532b2bc40c0 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -773,10 +773,8 @@ class BigInt_ { } if (convert) { montgomeryReduce(yVal, m.m_data, m.m_count, mDash); - } else if (smallMontyModulus && MultiwordArithmetic.compareUnsigned(yVal, m.m_data, yVal.length) >= 0) { - var result:Vector = new Vector(yVal.length); - MultiwordArithmetic.subtract(result, yVal, m.m_data, result.length); // a = a-m; - Vector.blit(result, 0, yVal, 0, result.length); + } else if (smallMontyModulus && compareMonty(yVal, m.m_data) >= 0) { + subtractMonty(yVal,m.m_data); } var montResult:BigInt_ = BigInt_.fromUnsignedInts(yVal); return montResult; @@ -838,10 +836,8 @@ class BigInt_ { i++; } - if (!smallMontyModulus && MultiwordArithmetic.compareUnsigned(a, m, a.length) >= 0) { - var result:Vector = new Vector(a.length); - MultiwordArithmetic.subtract(result, a, m, result.length); - Vector.blit(result, 0, a, 0, result.length); + if (!smallMontyModulus && compareMonty(a, m) >= 0) { + subtractMonty(a,m); } Vector.blit(a, 0, x, 0, n); } @@ -882,10 +878,8 @@ class BigInt_ { i++; } - if (!smallMontyModulus && MultiwordArithmetic.compareUnsigned(a, m, a.length) >= 0) { - var result:Vector = new Vector(a.length); - MultiwordArithmetic.subtract(result, a, m, result.length); - Vector.blit(result, 0, a, 0, result.length); + if (!smallMontyModulus && compareMonty(a, m) >= 0) { + subtractMonty(a,m); } Vector.blit(a, 0, x, 0, n); } @@ -911,12 +905,54 @@ class BigInt_ { x[n - 1] = carry.low; i++; } - if (MultiwordArithmetic.compareUnsigned(x, m, x.length) >= 0) { - var result:Vector = new Vector(x.length); - MultiwordArithmetic.subtract(result, x, m, result.length); - Vector.blit(result, 0, x, 0, result.length); + if (compareMonty(x, m) >= 0) { + subtractMonty(x,m); } } + + // x = x - y - where x is >= y + private function subtractMonty(x:Vector,y:Vector):Void { + var yIndex:Int = y.length-1; + while(yIndex>=0 && y[yIndex]==0) { + yIndex--; + } + var xn : Int, yn : Int, i:Int = 0; + var c : Int = 0, z : Int = 0; + while(i<=yIndex) + { + xn = x.get(i); + yn = y.get(i); + z = xn - yn - c; + x.set(i, z); + c = ((~xn & yn) | (~(xn ^ yn) & z)) >>> 31; + i++; + } + } + + private function compareMonty(x:Vector,y:Vector):Int { + var xIndex:Int = x.length-1; + var yIndex:Int = y.length-1; + while(xIndex>=0 && x[xIndex]==0) { + xIndex--; + } + while(yIndex>=0 && y[yIndex]==0) { + yIndex--; + } + var diff:Int = (x.length-y.length)-(xIndex-yIndex); + if (diff != 0) + { + return diff < 0 ? -1 : 1; + } + var xn : Int, yn : Int; + while(xIndex >=0) { + xn = x[xIndex--]; + yn = y[yIndex--]; + if ( xn != yn) { + return (xn ^ -2147483648) < (yn ^ -2147483648) ? -1 : 1; + } + } + return 0; + } private function getMQuote():Int32 { var d:Int = -m_data[0]; From 92935003ddae0686e3c79729da4ca46200a60738 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 7 Jan 2024 14:11:44 +0200 Subject: [PATCH 078/134] Change millerRabin().Fix compareMonty() --- std/haxe/math/bigint/BigInt_.hx | 69 +++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 532b2bc40c0..5718e1791fd 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -193,7 +193,7 @@ class BigInt_ { return hash; } - public function isProbablePrime(tolerance:UInt):Bool { + public function isProbablePrime(tolerance:Int):Bool { if (tolerance <= 0) return true; var b:BigInt_ = this.abs(); @@ -204,7 +204,7 @@ class BigInt_ { if (b.m_data.get(0) & 1 == 0) return false; - var rounds:UInt = 0; + var rounds:Int = 0; if (b.m_count <= 4) { rounds = (tolerance > 64) ? 64 : tolerance; } else if (b.m_count < 8) { @@ -527,7 +527,7 @@ class BigInt_ { return c; } - public static function randomPrime(bits:Int32, tolerance:UInt):BigInt_ { + public static function randomPrime(bits:Int32, tolerance:Int):BigInt_ { if (bits < 2) throw new BigIntException(BigIntError.INVALID_ARGUMENT); if (bits == 2) @@ -620,28 +620,36 @@ class BigInt_ { } } - private function millerRabin(rounds:UInt):Bool { - var minusOne:BigInt_ = subInt2(this, 1); + private function millerRabin(rounds:Int):Bool { var m = subInt2(this, 1); var lsb = m.getLowestSetBit(); if (lsb <= 0) return false; m = arithmeticShiftRight2(m, lsb); + var montyRadix:BigInt_ = divMod(arithmeticShiftLeft2(BigInt.ONE, 32 * this.m_count), this).remainder; + var minusMontyRadix:BigInt_ = sub2(this, montyRadix); var num:BigInt_; - for (i in 0...rounds) { - num = randomInRange(BigInt.TWO, minusOne); - var z:BigInt_ = num.modPow(m, this); - if (BigIntArithmetic.compare(z, BigInt.ONE) != 0 && BigIntArithmetic.compare(z, minusOne) != 0) { + do { + do { + num = random(this.bitLength()); + } while (BigIntArithmetic.compare(num, BigInt.ZERO) == 0 + || BigIntArithmetic.compare(num, montyRadix) == 0 + || BigIntArithmetic.compare(num, minusMontyRadix) == 0 + || BigIntArithmetic.compare(num, this) >= 0); + var y = modPowMonty(num, m, this, false); + if (BigIntArithmetic.compare(y, montyRadix) != 0) { var j:Int = 1; - while (j <= lsb && BigIntArithmetic.compare(z, minusOne) != 0) { - if (BigIntArithmetic.compare(z, BigInt.ONE) == 0 || j == lsb) { + while (BigIntArithmetic.compare(y, minusMontyRadix) != 0) { + if (j == lsb) + return false; + y = modPowMonty(y, BigInt.TWO, this, false); + if (BigIntArithmetic.compare(y, montyRadix) == 0) return false; - } - z = z.modPow(BigInt.TWO, this); j++; } } - } + rounds -= 2; + } while (rounds >= 0); return true; } @@ -929,25 +937,28 @@ class BigInt_ { } } - private function compareMonty(x:Vector,y:Vector):Int { - var xIndex:Int = x.length-1; - var yIndex:Int = y.length-1; - while(xIndex>=0 && x[xIndex]==0) { - xIndex--; + private function compareMonty(x:Vector, y:Vector):Int { + var xIndex:Int = 0; + var yIndex:Int = 0; + var xLen:Int = x.length - 1; + var yLen:Int = y.length - 1; + while (xIndex != x.length && x[xLen - xIndex] == 0) { + xIndex++; } - while(yIndex>=0 && y[yIndex]==0) { - yIndex--; + while (yIndex != y.length && y[yLen - yIndex] == 0) { + yIndex++; } - var diff:Int = (x.length-y.length)-(xIndex-yIndex); - if (diff != 0) - { + var diff:Int = (x.length - y.length) - (xIndex - yIndex); + if (diff != 0) { return diff < 0 ? -1 : 1; } - var xn : Int, yn : Int; - while(xIndex >=0) { - xn = x[xIndex--]; - yn = y[yIndex--]; - if ( xn != yn) { + var xn:Int, yn:Int; + while (xIndex >= 0) { + xn = x[xLen - xIndex]; + xIndex--; + yn = y[yLen - yIndex]; + yIndex--; + if (xn != yn) { return (xn ^ -2147483648) < (yn ^ -2147483648) ? -1 : 1; } } From 4a1b14956b96f6040925a3c4da209f88ca9b3d7a Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 7 Jan 2024 17:00:03 +0200 Subject: [PATCH 079/134] Prime check for small numbers --- std/haxe/math/bigint/BigInt_.hx | 66 +++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 5718e1791fd..665c7990849 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -621,6 +621,19 @@ class BigInt_ { } private function millerRabin(rounds:Int):Bool { + var numLists:Int = ((this.bitLength() - 1) < s_primeNumbers.length) ? (this.bitLength() - 1) : s_primeNumbers.length; + for (i in 0...numLists) { + var t:Int32 = divMod(this, BigInt_.fromInt(s_primeProduct[i])).remainder.m_data.get(0); + var primeNumbers = s_primeNumbers[i]; + for (j in 0...primeNumbers.length) { + var prime:Int = primeNumbers[j]; + var qRem:Int = t % prime; + if (qRem == 0) { + return (this.bitLength() < 16 && this.m_data.get(0) == prime); + } + } + } + var m = subInt2(this, 1); var lsb = m.getLowestSetBit(); if (lsb <= 0) @@ -1363,4 +1376,57 @@ class BigInt_ { ]; var expWindowThresholds:Vector = Vector.fromArrayCopy([7, 25, 81, 241, 673, 1793, 4609, 2147483647]); + + private static final s_primeProduct:Array = [ + 111546435, 58642669, 600662303, 33984931, 89809099, 167375713, 371700317, 645328247, 1070560157, 1596463769, 11592209, 13420567, 16965341, 20193023, + 23300239, 29884301, 35360399, 42749359, 49143869, 56466073, 65111573, 76027969, 84208541, 94593973, 103569859, 119319383, 133390067, 154769821, + 178433279, 193397129, 213479407, 229580147, 250367549, 271661713, 293158127, 319512181, 357349471, 393806449, 422400701, 452366557, 507436351, + 547978913, 575204137, 627947039, 666785731, 710381447, 777767161, 834985999, 894826021, 951747481, 1019050649, 1072651369, 1125878063, 1185362993, + 1267745273, 1322520163, 1391119619, 1498299287, 1608372013, 1700725291, 1805418283, 1871456063, 2008071007, 2115193573, -2116537769, -2048682597, + -1909179209, -1702980825, -1489962503, -1372818057, -1273647213, -1176554679, -1029034995, -962574873, -771748953, -583131125, -457088133, -303174767, + -155320833, -61811709, 118284847, 331869553, 586295383, 772701351, 975998995, 1184460183, 1405182073, 1650949557, 1998668581, -2047251531, + -1927652605, -1654913601, -1315052365, -972124375, -681632865, -537896625, -294451281, 45921629, 378607295, 561165965, 906561455, 1160065935, + 1380657927, 2004409167, -1889883587, -1580206561, -1192992209, -923130317, -627882485, -110329421, 120545641, 534097439, 738416003, 1094999525, + 1528839403, 1959463903, -1847439821, -979396295, -644014227, -93511911, 524494345, 1087323987, 1634127285, 2004297177, -2016987781, -1667747257, + -1343966817, -896726901, -320897353, 297288423, 657704777, 1374982823, 1828886847, -1690887095, -1136243417, -366760067, 243359903, 969193253, + 1709898031, -1905679739 + ]; + + private static final s_primeNumbers:Array> = [ + [3, 5, 7, 11, 13, 17, 19, 23], [29, 31, 37, 41, 43],[47, 53, 59, 61, 67],[71, 73, 79, 83], + [89, 97, 101, 103],[107, 109, 113, 127],[131, 137, 139, 149],[151, 157, 163, 167], + [173, 179, 181, 191],[193, 197, 199, 211],[223, 227, 229],[233, 239, 241], + [251, 257, 263],[269, 271, 277],[281, 283, 293],[307, 311, 313], + [317, 331, 337],[347, 349, 353],[359, 367, 373],[379, 383, 389], + [397, 401, 409],[419, 421, 431],[433, 439, 443],[449, 457, 461], + [463, 467, 479],[487, 491, 499],[503, 509, 521],[523, 541, 547], + [557, 563, 569],[571, 577, 587],[593, 599, 601],[607, 613, 617], + [619, 631, 641],[643, 647, 653],[659, 661, 673],[677, 683, 691], + [701, 709, 719],[727, 733, 739],[743, 751, 757],[761, 769, 773], + [787, 797, 809],[811, 821, 823],[827, 829, 839],[853, 857, 859], + [863, 877, 881],[883, 887, 907],[911, 919, 929],[937, 941, 947], + [953, 967, 971],[977, 983, 991],[997, 1009, 1013],[1019, 1021, 1031], + [1033, 1039, 1049],[1051, 1061, 1063],[1069, 1087, 1091],[1093, 1097, 1103], + [1109, 1117, 1123],[1129, 1151, 1153],[1163, 1171, 1181],[1187, 1193, 1201], + [1213, 1217, 1223],[1229, 1231, 1237],[1249, 1259, 1277],[1279, 1283, 1289], + [1291, 1297, 1301],[1303, 1307, 1319],[1321, 1327, 1361],[1367, 1373, 1381], + [1399, 1409, 1423],[1427, 1429, 1433],[1439, 1447, 1451],[1453, 1459, 1471], + [1481, 1483, 1487],[1489, 1493, 1499],[1511, 1523, 1531],[1543, 1549, 1553], + [1559, 1567, 1571],[1579, 1583, 1597],[1601, 1607, 1609],[1613, 1619, 1621], + [1627, 1637, 1657],[1663, 1667, 1669],[1693, 1697, 1699],[1709, 1721, 1723], + [1733, 1741, 1747],[1753, 1759, 1777],[1783, 1787, 1789],[1801, 1811, 1823], + [1831, 1847, 1861],[1867, 1871, 1873],[1877, 1879, 1889],[1901, 1907, 1913], + [1931, 1933, 1949],[1951, 1973, 1979],[1987, 1993, 1997],[1999, 2003, 2011], + [2017, 2027, 2029],[2039, 2053, 2063],[2069, 2081, 2083],[2087, 2089, 2099], + [2111, 2113, 2129],[2131, 2137, 2141],[2143, 2153, 2161],[2179, 2203, 2207], + [2213, 2221, 2237],[2239, 2243, 2251],[2267, 2269, 2273],[2281, 2287, 2293], + [2297, 2309, 2311],[2333, 2339, 2341],[2347, 2351, 2357],[2371, 2377, 2381], + [2383, 2389, 2393],[2399, 2411, 2417],[2423, 2437, 2441],[2447, 2459, 2467], + [2473, 2477, 2503],[2521, 2531, 2539],[2543, 2549, 2551],[2557, 2579, 2591], + [2593, 2609, 2617],[2621, 2633, 2647],[2657, 2659, 2663],[2671, 2677, 2683], + [2687, 2689, 2693],[2699, 2707, 2711],[2713, 2719, 2729],[2731, 2741, 2749], + [2753, 2767, 2777],[2789, 2791, 2797],[2801, 2803, 2819],[2833, 2837, 2843], + [2851, 2857, 2861],[2879, 2887, 2897],[2903, 2909, 2917],[2927, 2939, 2953], + [2957, 2963, 2969],[2971, 2999, 3001],[3011, 3019, 3023],[3037, 3041, 3049] + ]; } From bffa60efae88d7a29116c086f6e04b701e1cc45e Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 8 Jan 2024 09:46:59 +0200 Subject: [PATCH 080/134] Debug Lua --- std/haxe/math/bigint/BigInt_.hx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 665c7990849..c537dfc1a38 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -443,6 +443,10 @@ class BigInt_ { /* hac 14.61, pp. 608 */ public function modInverse(modulus:BigInt_):BigInt_ { + #if (lua) + trace("moduluse: "+toString1(modulus,10)); + trace("this: "+toString1(this,10)); + #end if (modulus.sign() == -1 || modulus.isZero()) throw new BigIntException(BigIntError.NEGATIVE_MODULUS); if (equals2Int(modulus, 1)) @@ -465,6 +469,9 @@ class BigInt_ { if (!isModulusEven) { // fast odd calculation + #if (lua) + trace("odd calculation"); + #end return modInverseOdd(x, y); } @@ -674,17 +681,29 @@ class BigInt_ { var v:BigInt_ = MutableBigInt_.fromBigInt(y); do { while ((BigIntArithmetic.bitwiseAndInt(u, 1) == 0)) { + #if (lua) + trace("u: "+toString1(u,10)); + #end u = arithmeticShiftRight2(u, 1); if (BigIntArithmetic.bitwiseAndInt(b, 1) == 1) b = sub2(b, x); b = arithmeticShiftRight2(b, 1); + #if (lua) + trace("b: "+toString1(b,10)); + #end } while ((BigIntArithmetic.bitwiseAndInt(v, 1) == 0)) { + #if (lua) + trace("v: "+toString1(v,10)); + #end v = arithmeticShiftRight2(v, 1); if (BigIntArithmetic.bitwiseAndInt(d, 1) == 1) d = sub2(d, x); d = arithmeticShiftRight2(d, 1); + #if (lua) + trace("d: "+toString1(d,10)); + #end } if (BigIntArithmetic.compare(u, v) >= 0) { u = sub2(u, v); From e4faadcc262089d16101d742057d04800af22dc5 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 8 Jan 2024 10:56:44 +0200 Subject: [PATCH 081/134] Always init m_data --- std/haxe/math/bigint/MutableBigInt_.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index ba479b464f4..f489830eaad 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -341,6 +341,9 @@ class MutableBigInt_ extends BigInt_ { m_data = newData; } else { m_data = new Vector(n); + for(i in 0...n) { + m_data.set(i,0); + } } } m_owned = true; From 7bc65dce1dbae7322b1ab8b3960eca846ed34346 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 13 Dec 2024 11:04:10 +0200 Subject: [PATCH 082/134] Trigger GitHub actions From 502f95086391cf15f4a6556c9f88fe1e6632d1b9 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 13 Dec 2024 14:11:04 +0200 Subject: [PATCH 083/134] Debug BigIntRandomPrime [php,python] --- tests/unit/src/unit/TestBigInt.hx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 018fda1a8ac..e4680af7aeb 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -291,7 +291,7 @@ class TestBigInt extends Test { } private function checkCompareSingle(expected:Int, a:BigInt, b:BigInt):Void { - eq(expected, BigIntArithmetic.compare(a, b)); + eq(expe cted, BigIntArithmetic.compare(a, b)); if (expected == 0) { eq(expected, BigIntArithmetic.compare(b, a)); } else { @@ -2779,18 +2779,25 @@ class TestBigInt extends Test { public function testBigIntRandomPrime():Void { var randomPrimeNumber = BigInt.randomPrime(5,5); + #if (php || python) trace("randomPrimeNumber(5): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(11,5); + #if (php || python) trace("randomPrimeNumber(11): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(16,5); + #if (php || python) trace("randomPrimeNumber(16): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(32,5); + #if (php || python) trace("randomPrimeNumber(32): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(55,5); + #if (php || python) trace("randomPrimeNumber(55): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(128,5); + #if (php || python) trace("randomPrimeNumber(128): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(156,5); + #if (php || python) trace("randomPrimeNumber(156): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); } From 8849e8bb4c9bfb31a9e1b8b87fdaf2bbab3841a5 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 13 Dec 2024 14:19:40 +0200 Subject: [PATCH 084/134] Fix syntax err --- tests/unit/src/unit/TestBigInt.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index e4680af7aeb..4f3d237c0fb 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -291,7 +291,7 @@ class TestBigInt extends Test { } private function checkCompareSingle(expected:Int, a:BigInt, b:BigInt):Void { - eq(expe cted, BigIntArithmetic.compare(a, b)); + eq(expected, BigIntArithmetic.compare(a, b)); if (expected == 0) { eq(expected, BigIntArithmetic.compare(b, a)); } else { From 422ec2d108e11be554f8c00fe7d5ac5969f68f04 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 13 Dec 2024 20:43:21 +0200 Subject: [PATCH 085/134] Lua test - modInverse --- tests/unit/src/unit/TestBigInt.hx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 4f3d237c0fb..5ad4673ab71 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2826,6 +2826,23 @@ class TestBigInt extends Test { public function testModInverse():Void { + #if (lua) + var m:Array = [ "2885628006"]; + var n:Array = [ "2448267533"]; + var mn:Array = ["112883568"]; + + var pos = 0; + for(i in 0...m.length) { + var a:BigInt = BigInt.fromString(m[i]); + for(j in 0...n.length) { + var b:BigInt = BigInt.fromString(n[j]); + var r = a.modInverse(b); + trace("r: "+r.toString()); + eq(mn[pos],r.toString()); + pos++; + } + } + #else var m:Array = [ "2885628006", "3452672361", "2693781441", "3446368347", "1495928706" , "3144152002", "1680946273","-9223372036854775808","-8192","-2147483648"]; var n:Array = [ "898595849", "2540385371", "1304452195", "2448267533", "2053023521", "4287024253", "1920144361", "504475217", "887965291", "300193913", "2394418165" ]; var mn:Array = ["681936597","980871030","323007506","112883568","683798641","1331447622","1514136460","438360889","585723972","102755466","818276521", @@ -2855,6 +2872,7 @@ class TestBigInt extends Test { var b:BigInt = BigInt.fromString("4294967296"); var r = a.modInverse(b); eq("2226617417",r.toString()); + #end } public function testBitCount():Void From 505196645ac2478d16ac614d94e2fafc790d5b4a Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 13 Dec 2024 21:58:50 +0200 Subject: [PATCH 086/134] Is toString() the problem ? --- tests/unit/src/unit/TestBigInt.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 5ad4673ab71..f611bbfbfda 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2837,7 +2837,7 @@ class TestBigInt extends Test { for(j in 0...n.length) { var b:BigInt = BigInt.fromString(n[j]); var r = a.modInverse(b); - trace("r: "+r.toString()); + trace("r: "+r.toBytes().toHex()); eq(mn[pos],r.toString()); pos++; } From 7452b85583f8799aeb263b99b35e60fa0a253907 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 13 Dec 2024 22:18:20 +0200 Subject: [PATCH 087/134] Debug Lua --- std/haxe/math/bigint/BigInt_.hx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index c537dfc1a38..4d41f1568a1 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -717,14 +717,27 @@ class BigInt_ { if (!equals2Int(v, 1)) { return BigInt.ZERO; } + + #if (lua) + trace("x: "+toString1(x,10)); + trace("d1: "+toString1(d,10)); + #end while (BigIntArithmetic.compareInt(d, 0) < 0) { d = add2(d, x); } + + #if (lua) + trace("d2: "+toString1(d,10)); + #end while (BigIntArithmetic.compare(d, x) >= 0) { d = sub2(d, x); } + + #if (lua) + trace("d3: "+toString1(d,10)); + #end return d; } From 44486686d8f59a018b9d881a49b891ea2fe3a17c Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 13 Dec 2024 22:34:18 +0200 Subject: [PATCH 088/134] Debug compare() --- std/haxe/math/bigint/BigInt_.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 4d41f1568a1..f0779b977a3 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -721,6 +721,7 @@ class BigInt_ { #if (lua) trace("x: "+toString1(x,10)); trace("d1: "+toString1(d,10)); + trace("Compare: "+BigIntArithmetic.compareInt(d, 0)); #end while (BigIntArithmetic.compareInt(d, 0) < 0) { From 274a2fd5d00e2f84aa46e152c20f5279d9e3cca3 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 00:05:13 +0200 Subject: [PATCH 089/134] Is the unsigned shift the problem ? --- std/haxe/math/bigint/BigIntArithmetic.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index c24778d2485..185b758e67e 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -37,12 +37,19 @@ class BigIntArithmetic { returns 0 (`a == b`). **/ public static function compareInt(a:BigInt_, b:Int):Int { + #if (lua) + trace("a.m_count: "+a.m_count); + #end if (a.m_count > 1) { return (a.sign() << 1) + 1; } var x:Int = a.m_data.get(0); var lt:Int = (x - b) ^ ((x ^ b) & ((x - b) ^ x)); // "Hacker's Delight" p. 23 var gt:Int = (b - x) ^ ((x ^ b) & ((b - x) ^ b)); + #if (lua) + trace("lt: "+(lt >> 31)); + trace("gt: "+(gt >>> 31)); + #end return (lt >> 31) | (gt >>> 31); } From bddad7005c9121fa304ad632e24954c29ca23392 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 08:04:52 +0200 Subject: [PATCH 090/134] Test sign() Lua --- std/haxe/math/bigint/BigIntArithmetic.hx | 3 +++ std/haxe/math/bigint/BigInt_.hx | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 185b758e67e..840a712c24f 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -41,6 +41,9 @@ class BigIntArithmetic { trace("a.m_count: "+a.m_count); #end if (a.m_count > 1) { + #if (lua) + trace("a.sign: "+a.sign(true)+" "+(a.sign() << 1)); + #end return (a.sign() << 1) + 1; } var x:Int = a.m_data.get(0); diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index f0779b977a3..7e2fbc10c8d 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -93,7 +93,14 @@ class BigInt_ { /** Retrieve the sign value of this big integer; 0 if positive, -1 if negative. **/ - public inline function sign():Int { + public inline function sign(?debug:Bool=false):Int { + #if (lua) + if (debug) { + trace("sign1: "+m_data.get(m_count - 1)); + trace("sign2: "+(m_data.get(m_count - 1) >> 31)); + trace("sign3: "+((m_data.get(m_count - 1) >> 31 != 0) ? -1 : 0)); + } + #end return (m_data.get(m_count - 1) >> 31 != 0) ? -1 : 0; } From 7c593279b2b680dedcb04097e3af5acca95c50d0 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 09:06:07 +0200 Subject: [PATCH 091/134] Lua clampInt32 for compareInt() --- std/haxe/math/bigint/BigIntArithmetic.hx | 8 +++++--- std/haxe/math/bigint/BigInt_.hx | 9 +-------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 840a712c24f..a21dafa90b2 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -41,10 +41,12 @@ class BigIntArithmetic { trace("a.m_count: "+a.m_count); #end if (a.m_count > 1) { - #if (lua) - trace("a.sign: "+a.sign(true)+" "+(a.sign() << 1)); + #if lua + trace("a.sign: "+a.sign()+" "+lua.Boot.clampInt32(a.sign() << 1)); + return lua.Boot.clampInt32(a.sign() << 1)+1; + #else + return (a.sign() << 1) + 1; #end - return (a.sign() << 1) + 1; } var x:Int = a.m_data.get(0); var lt:Int = (x - b) ^ ((x ^ b) & ((x - b) ^ x)); // "Hacker's Delight" p. 23 diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 7e2fbc10c8d..f0779b977a3 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -93,14 +93,7 @@ class BigInt_ { /** Retrieve the sign value of this big integer; 0 if positive, -1 if negative. **/ - public inline function sign(?debug:Bool=false):Int { - #if (lua) - if (debug) { - trace("sign1: "+m_data.get(m_count - 1)); - trace("sign2: "+(m_data.get(m_count - 1) >> 31)); - trace("sign3: "+((m_data.get(m_count - 1) >> 31 != 0) ? -1 : 0)); - } - #end + public inline function sign():Int { return (m_data.get(m_count - 1) >> 31 != 0) ? -1 : 0; } From 71a8da64e7de86e284e6da73db06dd32ca7cf387 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 09:47:01 +0200 Subject: [PATCH 092/134] Check compare() - Lua --- std/haxe/math/bigint/BigIntArithmetic.hx | 8 -------- std/haxe/math/bigint/BigInt_.hx | 26 ------------------------ tests/unit/src/unit/TestBigInt.hx | 9 ++++++++ 3 files changed, 9 insertions(+), 34 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index a21dafa90b2..cb3c1025a72 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -37,12 +37,8 @@ class BigIntArithmetic { returns 0 (`a == b`). **/ public static function compareInt(a:BigInt_, b:Int):Int { - #if (lua) - trace("a.m_count: "+a.m_count); - #end if (a.m_count > 1) { #if lua - trace("a.sign: "+a.sign()+" "+lua.Boot.clampInt32(a.sign() << 1)); return lua.Boot.clampInt32(a.sign() << 1)+1; #else return (a.sign() << 1) + 1; @@ -51,10 +47,6 @@ class BigIntArithmetic { var x:Int = a.m_data.get(0); var lt:Int = (x - b) ^ ((x ^ b) & ((x - b) ^ x)); // "Hacker's Delight" p. 23 var gt:Int = (b - x) ^ ((x ^ b) & ((b - x) ^ b)); - #if (lua) - trace("lt: "+(lt >> 31)); - trace("gt: "+(gt >>> 31)); - #end return (lt >> 31) | (gt >>> 31); } diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index f0779b977a3..56e6af41193 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -681,29 +681,17 @@ class BigInt_ { var v:BigInt_ = MutableBigInt_.fromBigInt(y); do { while ((BigIntArithmetic.bitwiseAndInt(u, 1) == 0)) { - #if (lua) - trace("u: "+toString1(u,10)); - #end u = arithmeticShiftRight2(u, 1); if (BigIntArithmetic.bitwiseAndInt(b, 1) == 1) b = sub2(b, x); b = arithmeticShiftRight2(b, 1); - #if (lua) - trace("b: "+toString1(b,10)); - #end } while ((BigIntArithmetic.bitwiseAndInt(v, 1) == 0)) { - #if (lua) - trace("v: "+toString1(v,10)); - #end v = arithmeticShiftRight2(v, 1); if (BigIntArithmetic.bitwiseAndInt(d, 1) == 1) d = sub2(d, x); d = arithmeticShiftRight2(d, 1); - #if (lua) - trace("d: "+toString1(d,10)); - #end } if (BigIntArithmetic.compare(u, v) >= 0) { u = sub2(u, v); @@ -717,28 +705,14 @@ class BigInt_ { if (!equals2Int(v, 1)) { return BigInt.ZERO; } - - #if (lua) - trace("x: "+toString1(x,10)); - trace("d1: "+toString1(d,10)); - trace("Compare: "+BigIntArithmetic.compareInt(d, 0)); - #end while (BigIntArithmetic.compareInt(d, 0) < 0) { d = add2(d, x); } - - #if (lua) - trace("d2: "+toString1(d,10)); - #end while (BigIntArithmetic.compare(d, x) >= 0) { d = sub2(d, x); } - - #if (lua) - trace("d3: "+toString1(d,10)); - #end return d; } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index f611bbfbfda..f5c23289f48 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -152,6 +152,9 @@ class TestBigInt extends Test { } public function bigIntCompare():Void { + #if (lua) + trace("bigIntCompare"); + #end // equality, single-word checkCompareInt(0, 0, 0); checkCompareInt(0, 1, 1); @@ -213,6 +216,9 @@ class TestBigInt extends Test { checkCompare(1, BigInt.fromHex("f2345678 9abcdef0"), BigInt.fromHex("fffffffe 12345678 9abcdef0")); checkCompare(1, BigInt.fromHex("00000001 ffffffff"), BigInt.fromHex("00000001 00000000")); + #if (lua) + trace("======END bigIntCompare======="); + #end } private function checkCompareInt(expected:Int, a:Int, b:Int):Void { @@ -291,6 +297,9 @@ class TestBigInt extends Test { } private function checkCompareSingle(expected:Int, a:BigInt, b:BigInt):Void { + #if (lua) + trace("expected: "+expected+ ","+BigIntArithmetic.compare(a, b)); + #end eq(expected, BigIntArithmetic.compare(a, b)); if (expected == 0) { eq(expected, BigIntArithmetic.compare(b, a)); From 9b376fc4a019da440e330c4e232b62e3ef1e4105 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 10:16:18 +0200 Subject: [PATCH 093/134] Clamp left shift - Lua --- std/haxe/math/bigint/BigIntArithmetic.hx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index cb3c1025a72..6e43cf4dbd5 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -38,11 +38,7 @@ class BigIntArithmetic { **/ public static function compareInt(a:BigInt_, b:Int):Int { if (a.m_count > 1) { - #if lua - return lua.Boot.clampInt32(a.sign() << 1)+1; - #else - return (a.sign() << 1) + 1; - #end + return (a.sign() << 1) + 1; } var x:Int = a.m_data.get(0); var lt:Int = (x - b) ^ ((x ^ b) & ((x - b) ^ x)); // "Hacker's Delight" p. 23 @@ -733,7 +729,11 @@ class BigIntArithmetic { var y:Int; while (inputSize > 0) { y = input[inputSize - 1]; + #if lua + x = lua.Boot.clampInt32((x << shift) | (y >>> r)); + #else x = (x << shift) | (y >>> r); + #end output.set(inputSize + outputOffset, x); x = y; --inputSize; From 8dcf4e542cfc8d7fc2d1419d50ff47341ab110e8 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 11:06:51 +0200 Subject: [PATCH 094/134] [lua] Shift left doesn't work correctly --- std/haxe/math/bigint/BigIntArithmetic.hx | 4 ---- std/haxe/math/bigint/BigInt_.hx | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 6e43cf4dbd5..c24778d2485 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -729,11 +729,7 @@ class BigIntArithmetic { var y:Int; while (inputSize > 0) { y = input[inputSize - 1]; - #if lua - x = lua.Boot.clampInt32((x << shift) | (y >>> r)); - #else x = (x << shift) | (y >>> r); - #end output.set(inputSize + outputOffset, x); x = y; --inputSize; diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 56e6af41193..cc140a0588b 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -93,7 +93,7 @@ class BigInt_ { /** Retrieve the sign value of this big integer; 0 if positive, -1 if negative. **/ - public inline function sign():Int { + public #if (!lua) inline #end function sign():Int { return (m_data.get(m_count - 1) >> 31 != 0) ? -1 : 0; } From f851be7a2eec6014a82c02213b713fb39f965028 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 11:39:11 +0200 Subject: [PATCH 095/134] Test left shift for Lua --- tests/unit/src/unit/TestBigInt.hx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index f5c23289f48..7118c0f8ba4 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -14,7 +14,23 @@ import haxe.math.bigint.BigInt; import haxe.math.bigint.BigIntHelper; class TestBigInt extends Test { - + + #if lua + public inline function sign(neg:Bool= true):Int { + return (neg) ? -1 : 0; + } + + public function testShiftLeft():Void { + trace("===> testShiftLeft()"); + trace("sign: "+bigIntShiftLeft()); + } + + public function bigIntShiftLeft():Int { + trace("sign: "+(sign() << 1)); + return (sign() << 1) + 1; + } + #end + public function testBigInt():Void { MutableBigInt_.s_testAllocation = false; bigIntAllChecks(); From ffec5476113a3a09ef7bde8879faad7b3cf96abc Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 12:03:04 +0200 Subject: [PATCH 096/134] Sign test - Lua --- tests/unit/src/unit/TestBigInt.hx | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 7118c0f8ba4..d426ce112c1 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -16,19 +16,12 @@ import haxe.math.bigint.BigIntHelper; class TestBigInt extends Test { #if lua - public inline function sign(neg:Bool= true):Int { - return (neg) ? -1 : 0; - } - public function testShiftLeft():Void { trace("===> testShiftLeft()"); - trace("sign: "+bigIntShiftLeft()); + var a:BigInt = "-2335383965"; + trace("sign: "+a.sign()+" , "+(a.sign() << 1)); } - public function bigIntShiftLeft():Int { - trace("sign: "+(sign() << 1)); - return (sign() << 1) + 1; - } #end public function testBigInt():Void { From 4bbf6489b9758f93e295024166a52e1808d163b9 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 14:28:22 +0200 Subject: [PATCH 097/134] Clamp lshift too, because -1 << 1 is 4294967294, but should be -2 --- std/lua/_lua/_hx_bit.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/std/lua/_lua/_hx_bit.lua b/std/lua/_lua/_hx_bit.lua index 0eef3f32479..327d830f379 100644 --- a/std/lua/_lua/_hx_bit.lua +++ b/std/lua/_lua/_hx_bit.lua @@ -19,3 +19,4 @@ end _hx_bit.bor = function(...) return _hx_bit_clamp(_hx_bit_raw.bor(...)) end _hx_bit.band = function(...) return _hx_bit_clamp(_hx_bit_raw.band(...)) end _hx_bit.arshift = function(...) return _hx_bit_clamp(_hx_bit_raw.arshift(...)) end +_hx_bit.lshift = function(...) return _hx_bit_clamp(_hx_bit_raw.lshift(...)) end From 6b634a2f487b507a5a48c05ac92ef7706798cc0d Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 14:54:08 +0200 Subject: [PATCH 098/134] Check for nil --- tests/unit/src/unit/TestBigInt.hx | 76 +++++++++++++------------------ 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index d426ce112c1..e6e878d4b1c 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -14,16 +14,7 @@ import haxe.math.bigint.BigInt; import haxe.math.bigint.BigIntHelper; class TestBigInt extends Test { - - #if lua - public function testShiftLeft():Void { - trace("===> testShiftLeft()"); - var a:BigInt = "-2335383965"; - trace("sign: "+a.sign()+" , "+(a.sign() << 1)); - } - - #end - + public function testBigInt():Void { MutableBigInt_.s_testAllocation = false; bigIntAllChecks(); @@ -161,9 +152,6 @@ class TestBigInt extends Test { } public function bigIntCompare():Void { - #if (lua) - trace("bigIntCompare"); - #end // equality, single-word checkCompareInt(0, 0, 0); checkCompareInt(0, 1, 1); @@ -225,9 +213,6 @@ class TestBigInt extends Test { checkCompare(1, BigInt.fromHex("f2345678 9abcdef0"), BigInt.fromHex("fffffffe 12345678 9abcdef0")); checkCompare(1, BigInt.fromHex("00000001 ffffffff"), BigInt.fromHex("00000001 00000000")); - #if (lua) - trace("======END bigIntCompare======="); - #end } private function checkCompareInt(expected:Int, a:Int, b:Int):Void { @@ -306,9 +291,6 @@ class TestBigInt extends Test { } private function checkCompareSingle(expected:Int, a:BigInt, b:BigInt):Void { - #if (lua) - trace("expected: "+expected+ ","+BigIntArithmetic.compare(a, b)); - #end eq(expected, BigIntArithmetic.compare(a, b)); if (expected == 0) { eq(expected, BigIntArithmetic.compare(b, a)); @@ -2769,18 +2751,39 @@ class TestBigInt extends Test { { var a:BigInt; a = "8329132432461"; + #if lua + trace("a: "+a); + #end eq("8329132432469",a.nextProbablePrime().toString()); a = 269234; + #if lua + trace("a: "+a); + #end eq("269237",a.nextProbablePrime().toString()); a = 409993; + #if lua + trace("a: "+a); + #end eq("409999",a.nextProbablePrime().toString()); a = 950091; + #if lua + trace("a: "+a); + #end eq("950099",a.nextProbablePrime().toString()); a = 141682; + #if lua + trace("a: "+a); + #end eq("141689",a.nextProbablePrime().toString()); a = 40870716; + #if lua + trace("a: "+a); + #end eq("40870721",a.nextProbablePrime().toString()); a = 32747015; + #if lua + trace("a: "+a); + #end eq("32747023",a.nextProbablePrime().toString()); } @@ -2796,26 +2799,29 @@ class TestBigInt extends Test { public function testBigIntRandomPrime():Void { + #if lua + trace("testBigIntRandomPrime"); + #end var randomPrimeNumber = BigInt.randomPrime(5,5); - #if (php || python) trace("randomPrimeNumber(5): " + randomPrimeNumber); #end + #if (php || python || lua) trace("randomPrimeNumber(5): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(11,5); - #if (php || python) trace("randomPrimeNumber(11): " + randomPrimeNumber); #end + #if (php || python || lua) trace("randomPrimeNumber(11): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(16,5); - #if (php || python) trace("randomPrimeNumber(16): " + randomPrimeNumber); #end + #if (php || python || lua) trace("randomPrimeNumber(16): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(32,5); - #if (php || python) trace("randomPrimeNumber(32): " + randomPrimeNumber); #end + #if (php || python || lua) trace("randomPrimeNumber(32): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(55,5); - #if (php || python) trace("randomPrimeNumber(55): " + randomPrimeNumber); #end + #if (php || python || lua) trace("randomPrimeNumber(55): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(128,5); - #if (php || python) trace("randomPrimeNumber(128): " + randomPrimeNumber); #end + #if (php || python || lua) trace("randomPrimeNumber(128): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(156,5); - #if (php || python) trace("randomPrimeNumber(156): " + randomPrimeNumber); #end + #if (php || python || lua) trace("randomPrimeNumber(156): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); } @@ -2844,23 +2850,6 @@ class TestBigInt extends Test { public function testModInverse():Void { - #if (lua) - var m:Array = [ "2885628006"]; - var n:Array = [ "2448267533"]; - var mn:Array = ["112883568"]; - - var pos = 0; - for(i in 0...m.length) { - var a:BigInt = BigInt.fromString(m[i]); - for(j in 0...n.length) { - var b:BigInt = BigInt.fromString(n[j]); - var r = a.modInverse(b); - trace("r: "+r.toBytes().toHex()); - eq(mn[pos],r.toString()); - pos++; - } - } - #else var m:Array = [ "2885628006", "3452672361", "2693781441", "3446368347", "1495928706" , "3144152002", "1680946273","-9223372036854775808","-8192","-2147483648"]; var n:Array = [ "898595849", "2540385371", "1304452195", "2448267533", "2053023521", "4287024253", "1920144361", "504475217", "887965291", "300193913", "2394418165" ]; var mn:Array = ["681936597","980871030","323007506","112883568","683798641","1331447622","1514136460","438360889","585723972","102755466","818276521", @@ -2890,7 +2879,6 @@ class TestBigInt extends Test { var b:BigInt = BigInt.fromString("4294967296"); var r = a.modInverse(b); eq("2226617417",r.toString()); - #end } public function testBitCount():Void From 0589e3d5ed8b90877b48dffe44c170c14c21aa9b Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 15:18:52 +0200 Subject: [PATCH 099/134] What is nil ? --- std/haxe/math/bigint/BigInt_.hx | 9 +-------- tests/unit/src/unit/TestBigInt.hx | 13 +++++++++++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index cc140a0588b..665c7990849 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -93,7 +93,7 @@ class BigInt_ { /** Retrieve the sign value of this big integer; 0 if positive, -1 if negative. **/ - public #if (!lua) inline #end function sign():Int { + public inline function sign():Int { return (m_data.get(m_count - 1) >> 31 != 0) ? -1 : 0; } @@ -443,10 +443,6 @@ class BigInt_ { /* hac 14.61, pp. 608 */ public function modInverse(modulus:BigInt_):BigInt_ { - #if (lua) - trace("moduluse: "+toString1(modulus,10)); - trace("this: "+toString1(this,10)); - #end if (modulus.sign() == -1 || modulus.isZero()) throw new BigIntException(BigIntError.NEGATIVE_MODULUS); if (equals2Int(modulus, 1)) @@ -469,9 +465,6 @@ class BigInt_ { if (!isModulusEven) { // fast odd calculation - #if (lua) - trace("odd calculation"); - #end return modInverseOdd(x, y); } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index e6e878d4b1c..e930717a8fe 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2632,12 +2632,18 @@ class TestBigInt extends Test { public function testPrimeNumber():Void { + #if lua + trace("testPrimeNumber"); + #end for(i in 0...s_primeNumbers.length) { var b:BigInt = s_primeNumbers[i]; var bm:MutableBigInt = s_primeNumbers[i]; t(b.isProbablePrime(10)); t(bm.isProbablePrime(10)); } + #if lua + trace("s_notPrimeNumbers"); + #end for(i in 0...s_notPrimeNumbers.length) { var b:BigInt = s_notPrimeNumbers[i]; var bm:MutableBigInt = s_notPrimeNumbers[i]; @@ -2749,10 +2755,13 @@ class TestBigInt extends Test { public function testNextProbablePrime():Void { + #if lua + trace("testNextProbablePrime"); + #end var a:BigInt; a = "8329132432461"; #if lua - trace("a: "+a); + trace("a: "+(a==null)); #end eq("8329132432469",a.nextProbablePrime().toString()); a = 269234; @@ -2802,7 +2811,7 @@ class TestBigInt extends Test { #if lua trace("testBigIntRandomPrime"); #end - var randomPrimeNumber = BigInt.randomPrime(5,5); + var randomPrimeNumber:BigInt = BigInt.randomPrime(5,5); #if (php || python || lua) trace("randomPrimeNumber(5): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(11,5); From ad29bc88de864917a469eb31f4fe7da0f7be6891 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 17:05:05 +0200 Subject: [PATCH 100/134] Check testPrimeNumber --- tests/unit/src/unit/TestBigInt.hx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index e930717a8fe..64783985f25 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2636,9 +2636,21 @@ class TestBigInt extends Test { trace("testPrimeNumber"); #end for(i in 0...s_primeNumbers.length) { + #if lua + trace("primeNumber: "+s_primeNumbers[i]); + #end var b:BigInt = s_primeNumbers[i]; + #if lua + trace("b: "+b); + #end var bm:MutableBigInt = s_primeNumbers[i]; + #if lua + trace("check b "); + #end t(b.isProbablePrime(10)); + #if lua + trace("check bm"); + #end t(bm.isProbablePrime(10)); } #if lua From dee19e9093411d9cf60a3a7dd623b21007c2ac93 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 19:34:19 +0200 Subject: [PATCH 101/134] Lua nil debug --- std/haxe/math/bigint/BigInt_.hx | 13 ++++++++++++- tests/unit/src/unit/TestBigInt.hx | 22 +++++++++------------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 665c7990849..18276063389 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -621,6 +621,9 @@ class BigInt_ { } private function millerRabin(rounds:Int):Bool { + #if lua + trace("millerRabin"); + #end var numLists:Int = ((this.bitLength() - 1) < s_primeNumbers.length) ? (this.bitLength() - 1) : s_primeNumbers.length; for (i in 0...numLists) { var t:Int32 = divMod(this, BigInt_.fromInt(s_primeProduct[i])).remainder.m_data.get(0); @@ -633,7 +636,9 @@ class BigInt_ { } } } - + #if lua + trace("step 1"); + #end var m = subInt2(this, 1); var lsb = m.getLowestSetBit(); if (lsb <= 0) @@ -642,6 +647,9 @@ class BigInt_ { var montyRadix:BigInt_ = divMod(arithmeticShiftLeft2(BigInt.ONE, 32 * this.m_count), this).remainder; var minusMontyRadix:BigInt_ = sub2(this, montyRadix); var num:BigInt_; + #if lua + trace("step 2"); + #end do { do { num = random(this.bitLength()); @@ -663,6 +671,9 @@ class BigInt_ { } rounds -= 2; } while (rounds >= 0); + #if lua + trace("END millerRabin"); + #end return true; } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 64783985f25..009d50e49fa 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2634,34 +2634,30 @@ class TestBigInt extends Test { { #if lua trace("testPrimeNumber"); - #end - for(i in 0...s_primeNumbers.length) { - #if lua + var i:Int = 35; trace("primeNumber: "+s_primeNumbers[i]); - #end var b:BigInt = s_primeNumbers[i]; - #if lua trace("b: "+b); - #end var bm:MutableBigInt = s_primeNumbers[i]; - #if lua trace("check b "); - #end t(b.isProbablePrime(10)); - #if lua trace("check bm"); - #end + t(bm.isProbablePrime(10)); + + #else + for(i in 0...s_primeNumbers.length) { + var b:BigInt = s_primeNumbers[i]; + var bm:MutableBigInt = s_primeNumbers[i]; + t(b.isProbablePrime(10)); t(bm.isProbablePrime(10)); } - #if lua - trace("s_notPrimeNumbers"); - #end for(i in 0...s_notPrimeNumbers.length) { var b:BigInt = s_notPrimeNumbers[i]; var bm:MutableBigInt = s_notPrimeNumbers[i]; f(b.isProbablePrime(10)); f(bm.isProbablePrime(10)); } + #end } public function testLowestSetBit():Void From d2bbbcd28573afbe873bb44890cf7282b3a1cec3 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 19:58:28 +0200 Subject: [PATCH 102/134] Debug --- std/haxe/math/bigint/BigInt_.hx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 18276063389..8acd1edc9f6 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -658,8 +658,14 @@ class BigInt_ { || BigIntArithmetic.compare(num, minusMontyRadix) == 0 || BigIntArithmetic.compare(num, this) >= 0); var y = modPowMonty(num, m, this, false); + #if lua + trace("modPowMonty"); + #end if (BigIntArithmetic.compare(y, montyRadix) != 0) { var j:Int = 1; + #if lua + trace("BigIntArithmetic.compare"); + #end while (BigIntArithmetic.compare(y, minusMontyRadix) != 0) { if (j == lsb) return false; @@ -670,6 +676,9 @@ class BigInt_ { } } rounds -= 2; + #if lua + trace("rounds: "+rounds); + #end } while (rounds >= 0); #if lua trace("END millerRabin"); From 1c418e5e811c01367fbec9451f0eae676e8d6ca2 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 20:34:51 +0200 Subject: [PATCH 103/134] Debug Lua --- std/haxe/math/bigint/BigInt_.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 8acd1edc9f6..6247e5ac82a 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -731,6 +731,9 @@ class BigInt_ { } private function modPowMonty(b:BigInt_, _e:BigInt_, _m:BigInt_, convert:Bool):BigInt_ { + #if lua + trace("_modPowMonty_"); + #end var n:Int, powR:Int, extraBits:Int, @@ -796,6 +799,7 @@ class BigInt_ { windowPos = 1; window = windowList[windowPos]; windowPos++; + trace("window: "+window); while (window != -1) { mult = window & 0xFF; bits = lastZeroes + BitLengthTable[mult]; @@ -809,14 +813,17 @@ class BigInt_ { window = windowList[windowPos]; windowPos++; } + trace("_squareMonty_"); for (i in 0...lastZeroes) { squareMonty(yAccum, yVal, m.m_data, m.m_count, mDash, smallMontyModulus); } + trace("montgomeryReduce "+convert); if (convert) { montgomeryReduce(yVal, m.m_data, m.m_count, mDash); } else if (smallMontyModulus && compareMonty(yVal, m.m_data) >= 0) { subtractMonty(yVal,m.m_data); } + trace("Result modPowMonty"); var montResult:BigInt_ = BigInt_.fromUnsignedInts(yVal); return montResult; } From 3c19c45434fce71a5535c6d5f700e42b033c5f4a Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 21:05:58 +0200 Subject: [PATCH 104/134] Dbg Lua --- std/haxe/math/bigint/BigInt_.hx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 6247e5ac82a..1ad106c6712 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -648,15 +648,20 @@ class BigInt_ { var minusMontyRadix:BigInt_ = sub2(this, montyRadix); var num:BigInt_; #if lua - trace("step 2"); + trace("step 2 : "+rounds); #end do { do { num = random(this.bitLength()); + trace("random num: "+num); } while (BigIntArithmetic.compare(num, BigInt.ZERO) == 0 || BigIntArithmetic.compare(num, montyRadix) == 0 || BigIntArithmetic.compare(num, minusMontyRadix) == 0 || BigIntArithmetic.compare(num, this) >= 0); + #if lua + trace("start check for modPowMonty"); + trace("num: "+num+" ,m: "+m+" ,this: "+this); + #end var y = modPowMonty(num, m, this, false); #if lua trace("modPowMonty"); From eb9bd4b22bc4fc30c21775bc2ee4b03ef31edfcc Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 21:24:23 +0200 Subject: [PATCH 105/134] Debug --- std/haxe/math/bigint/BigInt_.hx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 1ad106c6712..2bbf852d6a7 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -570,11 +570,17 @@ class BigInt_ { } public static function random(bits:Int32):BigInt_ { + #if lua + trace("random: "+bits); + #end if (bits <= 0) return BigInt.ZERO; var r = new MutableBigInt_(); r.setFromBigEndianBytesSigned(randomBytes(bits)); r.compact(); + #if lua + trace("_r_: "+r); + #end return r; } @@ -653,7 +659,9 @@ class BigInt_ { do { do { num = random(this.bitLength()); + #if lua trace("random num: "+num); + #end } while (BigIntArithmetic.compare(num, BigInt.ZERO) == 0 || BigIntArithmetic.compare(num, montyRadix) == 0 || BigIntArithmetic.compare(num, minusMontyRadix) == 0 From fd76eb968b563e479029a9b5ceb9704db6ef38a5 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 21:43:38 +0200 Subject: [PATCH 106/134] Remove debug ( failed) --- std/haxe/math/bigint/BigInt_.hx | 41 ------------------------------- tests/unit/src/unit/TestBigInt.hx | 24 ------------------ 2 files changed, 65 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 2bbf852d6a7..ffd441e69fe 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -570,17 +570,11 @@ class BigInt_ { } public static function random(bits:Int32):BigInt_ { - #if lua - trace("random: "+bits); - #end if (bits <= 0) return BigInt.ZERO; var r = new MutableBigInt_(); r.setFromBigEndianBytesSigned(randomBytes(bits)); r.compact(); - #if lua - trace("_r_: "+r); - #end return r; } @@ -627,9 +621,6 @@ class BigInt_ { } private function millerRabin(rounds:Int):Bool { - #if lua - trace("millerRabin"); - #end var numLists:Int = ((this.bitLength() - 1) < s_primeNumbers.length) ? (this.bitLength() - 1) : s_primeNumbers.length; for (i in 0...numLists) { var t:Int32 = divMod(this, BigInt_.fromInt(s_primeProduct[i])).remainder.m_data.get(0); @@ -642,9 +633,6 @@ class BigInt_ { } } } - #if lua - trace("step 1"); - #end var m = subInt2(this, 1); var lsb = m.getLowestSetBit(); if (lsb <= 0) @@ -653,32 +641,16 @@ class BigInt_ { var montyRadix:BigInt_ = divMod(arithmeticShiftLeft2(BigInt.ONE, 32 * this.m_count), this).remainder; var minusMontyRadix:BigInt_ = sub2(this, montyRadix); var num:BigInt_; - #if lua - trace("step 2 : "+rounds); - #end do { do { num = random(this.bitLength()); - #if lua - trace("random num: "+num); - #end } while (BigIntArithmetic.compare(num, BigInt.ZERO) == 0 || BigIntArithmetic.compare(num, montyRadix) == 0 || BigIntArithmetic.compare(num, minusMontyRadix) == 0 || BigIntArithmetic.compare(num, this) >= 0); - #if lua - trace("start check for modPowMonty"); - trace("num: "+num+" ,m: "+m+" ,this: "+this); - #end var y = modPowMonty(num, m, this, false); - #if lua - trace("modPowMonty"); - #end if (BigIntArithmetic.compare(y, montyRadix) != 0) { var j:Int = 1; - #if lua - trace("BigIntArithmetic.compare"); - #end while (BigIntArithmetic.compare(y, minusMontyRadix) != 0) { if (j == lsb) return false; @@ -689,13 +661,7 @@ class BigInt_ { } } rounds -= 2; - #if lua - trace("rounds: "+rounds); - #end } while (rounds >= 0); - #if lua - trace("END millerRabin"); - #end return true; } @@ -744,9 +710,6 @@ class BigInt_ { } private function modPowMonty(b:BigInt_, _e:BigInt_, _m:BigInt_, convert:Bool):BigInt_ { - #if lua - trace("_modPowMonty_"); - #end var n:Int, powR:Int, extraBits:Int, @@ -812,7 +775,6 @@ class BigInt_ { windowPos = 1; window = windowList[windowPos]; windowPos++; - trace("window: "+window); while (window != -1) { mult = window & 0xFF; bits = lastZeroes + BitLengthTable[mult]; @@ -826,17 +788,14 @@ class BigInt_ { window = windowList[windowPos]; windowPos++; } - trace("_squareMonty_"); for (i in 0...lastZeroes) { squareMonty(yAccum, yVal, m.m_data, m.m_count, mDash, smallMontyModulus); } - trace("montgomeryReduce "+convert); if (convert) { montgomeryReduce(yVal, m.m_data, m.m_count, mDash); } else if (smallMontyModulus && compareMonty(yVal, m.m_data) >= 0) { subtractMonty(yVal,m.m_data); } - trace("Result modPowMonty"); var montResult:BigInt_ = BigInt_.fromUnsignedInts(yVal); return montResult; } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 009d50e49fa..abd96abbc36 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2763,44 +2763,20 @@ class TestBigInt extends Test { public function testNextProbablePrime():Void { - #if lua - trace("testNextProbablePrime"); - #end var a:BigInt; a = "8329132432461"; - #if lua - trace("a: "+(a==null)); - #end eq("8329132432469",a.nextProbablePrime().toString()); a = 269234; - #if lua - trace("a: "+a); - #end eq("269237",a.nextProbablePrime().toString()); a = 409993; - #if lua - trace("a: "+a); - #end eq("409999",a.nextProbablePrime().toString()); a = 950091; - #if lua - trace("a: "+a); - #end eq("950099",a.nextProbablePrime().toString()); a = 141682; - #if lua - trace("a: "+a); - #end eq("141689",a.nextProbablePrime().toString()); a = 40870716; - #if lua - trace("a: "+a); - #end eq("40870721",a.nextProbablePrime().toString()); a = 32747015; - #if lua - trace("a: "+a); - #end eq("32747023",a.nextProbablePrime().toString()); } From 975ab178dfa31c5a1e977cd2623473a17e1a4255 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 22:11:52 +0200 Subject: [PATCH 107/134] Last chance Lua --- std/haxe/math/bigint/BigInt_.hx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index ffd441e69fe..791e838a081 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -641,6 +641,9 @@ class BigInt_ { var montyRadix:BigInt_ = divMod(arithmeticShiftLeft2(BigInt.ONE, 32 * this.m_count), this).remainder; var minusMontyRadix:BigInt_ = sub2(this, montyRadix); var num:BigInt_; + #if lua + trace("Debug - ignore all"); + #else do { do { num = random(this.bitLength()); @@ -662,6 +665,7 @@ class BigInt_ { } rounds -= 2; } while (rounds >= 0); + #end return true; } From e91d2d2c83a8ec0e6484688a7c001ae4d36f3dcd Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 22:37:46 +0200 Subject: [PATCH 108/134] Init m_count --- std/haxe/math/bigint/BigInt_.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 791e838a081..0e8d7c9460b 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -1205,7 +1205,7 @@ class BigInt_ { } } - private var m_count:Int; + private var m_count:Int = 0; private var m_data:Vector; private static inline var s_firstCachedValue:Int = -16; From 8fbfcdb9c675812d3ab97ac9412e08cf222ee610 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 22:55:49 +0200 Subject: [PATCH 109/134] Set m_data to null --- std/haxe/math/bigint/BigInt_.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 0e8d7c9460b..a399d6637b9 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -1206,7 +1206,7 @@ class BigInt_ { } private var m_count:Int = 0; - private var m_data:Vector; + private var m_data:Vector = null; private static inline var s_firstCachedValue:Int = -16; private static inline var s_lastCachedValue:Int = 16; From 83a3ae9d149ba006fd6bf7a9ee49112852bbaf0b Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 23:22:07 +0200 Subject: [PATCH 110/134] Debug --- std/haxe/math/bigint/BigInt_.hx | 76 ++++++++++++++++----------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index a399d6637b9..dff39930c37 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -641,9 +641,7 @@ class BigInt_ { var montyRadix:BigInt_ = divMod(arithmeticShiftLeft2(BigInt.ONE, 32 * this.m_count), this).remainder; var minusMontyRadix:BigInt_ = sub2(this, montyRadix); var num:BigInt_; - #if lua - trace("Debug - ignore all"); - #else + do { do { num = random(this.bitLength()); @@ -665,7 +663,7 @@ class BigInt_ { } rounds -= 2; } while (rounds >= 0); - #end + return true; } @@ -804,7 +802,7 @@ class BigInt_ { return montResult; } - private function squareMonty(a:Vector, x:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { + private function squareMonty(a2:Vector, x:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { var n:Int, aMax:Int, j:Int, i:Int; var xVal:Int, a0:Int; var x0:Int64, carry:Int64, t:Int64, prod1:Int64, prod2:Int64, xi:Int64, u:Int64; @@ -820,53 +818,53 @@ class BigInt_ { prod1 = Int64.mul(x0, Int64.make(0, x[j])); prod2 = Int64.mul(u, Int64.make(0, m[j])); carry = Int64.add(carry, Int64.add(Int64.make(0, Int64.shl(prod1, 1).low), Int64.make(0, prod2.low))); - a[j - 1] = carry.low; + a2[j - 1] = carry.low; carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod2, 32)), Int64.ushr(prod1, 31)); j++; } - a[mLen] = Int64.ushr(carry, 32).low; - a[mLen - 1] = carry.low; + a2[mLen] = Int64.ushr(carry, 32).low; + a2[mLen - 1] = carry.low; i = 1; while (i < mLen) { - a0 = a[0]; + a0 = a2[0]; u = Int64.make(0, Int64.mul(a0, mDash).low); carry = Int64.add(Int64.mul(u, Int64.make(0, m[0])), Int64.make(0, a0)); carry = Int64.ushr(carry, 32); j = 1; while (j < i) { - carry = Int64.add(carry, Int64.add(Int64.mul(u, Int64.make(0, m[j])), Int64.make(0, a[j]))); - a[j - 1] = carry.low; + carry = Int64.add(carry, Int64.add(Int64.mul(u, Int64.make(0, m[j])), Int64.make(0, a2[j]))); + a2[j - 1] = carry.low; carry = Int64.ushr(carry, 32); j++; } xi = Int64.make(0, x[i]); prod1 = Int64.mul(xi, xi); prod2 = Int64.mul(u, Int64.make(0, m[i])); - carry += Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.make(0, a[i])); - a[i - 1] = carry.low; + carry += Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.make(0, a2[i])); + a2[i - 1] = carry.low; carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 32)), Int64.ushr(prod2, 32)); j = i + 1; while (j < n) { prod1 = Int64.mul(xi, Int64.make(0, x[j])); prod2 = Int64.mul(u, Int64.make(0, m[j])); - carry = Int64.add(carry, Int64.add(Int64.add(Int64.make(0, Int64.shl(prod1, 1).low), Int64.make(0, prod2.low)), Int64.make(0, a[j]))); - a[j - 1] = carry.low; + carry = Int64.add(carry, Int64.add(Int64.add(Int64.make(0, Int64.shl(prod1, 1).low), Int64.make(0, prod2.low)), Int64.make(0, a2[j]))); + a2[j - 1] = carry.low; carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 31)), Int64.ushr(prod2, 32)); j++; } - carry = Int64.add(carry, Int64.make(0, a[n])); - a[n] = Int64.ushr(carry, 32).low; - a[n - 1] = carry.low; + carry = Int64.add(carry, Int64.make(0, a2[n])); + a2[n] = Int64.ushr(carry, 32).low; + a2[n - 1] = carry.low; i++; } - if (!smallMontyModulus && compareMonty(a, m) >= 0) { - subtractMonty(a,m); + if (!smallMontyModulus && compareMonty(a2, m) >= 0) { + subtractMonty(a2,m); } - Vector.blit(a, 0, x, 0, n); + Vector.blit(a2, 0, x, 0, n); } - private function multiplyMonty(a:Vector, x:Vector, y:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { + private function multiplyMonty(a3:Vector, x:Vector, y:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { var n:Int, aMax:Int, j:Int, i:Int; var a0:Int64, y0:Int64; var carry:Int64, t:Int64, prod1:Int64, prod2:Int64, xi:Int64, u:Int64; @@ -874,12 +872,12 @@ class BigInt_ { y0 = Int64.make(0, y[0]); i = 0; while (i <= n) { - a[i] = 0; + a3[i] = 0; i++; } i = 0; while (i < n) { - a0 = Int64.make(0, a[0]); + a0 = Int64.make(0, a3[0]); xi = Int64.make(0, x[i]); prod1 = Int64.mul(xi, y0); carry = Int64.add(Int64.make(0, prod1.low), a0); @@ -891,21 +889,21 @@ class BigInt_ { while (j <= (n - 1)) { prod1 = Int64.mul(xi, Int64.make(0, y[j])); prod2 = Int64.mul(u, Int64.make(0, m[j])); - carry = Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.add(Int64.make(0, a[j]), carry)); - a[j - 1] = carry.low; + carry = Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.add(Int64.make(0, a3[j]), carry)); + a3[j - 1] = carry.low; carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 32)), Int64.ushr(prod2, 32)); j++; } - carry = Int64.add(carry, Int64.make(0, a[n])); - a[n] = Int64.ushr(carry, 32).low; - a[n - 1] = carry.low; + carry = Int64.add(carry, Int64.make(0, a3[n])); + a3[n] = Int64.ushr(carry, 32).low; + a3[n - 1] = carry.low; i++; } - if (!smallMontyModulus && compareMonty(a, m) >= 0) { - subtractMonty(a,m); + if (!smallMontyModulus && compareMonty(a3, m) >= 0) { + subtractMonty(a3,m); } - Vector.blit(a, 0, x, 0, n); + Vector.blit(a3, 0, x, 0, n); } private function montgomeryReduce(x:Vector, m:Vector, mLen:Int, mDash:Int32):Void { @@ -1206,7 +1204,7 @@ class BigInt_ { } private var m_count:Int = 0; - private var m_data:Vector = null; + private var m_data:Vector; private static inline var s_firstCachedValue:Int = -16; private static inline var s_lastCachedValue:Int = 16; @@ -1217,9 +1215,9 @@ class BigInt_ { //----------------------------------------------------------------------- @:noCompletion - private static inline function negate1(a:BigInt_):BigInt_ { + private static inline function negate1(a1:BigInt_):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.negate(r, a); + BigIntArithmetic.negate(r, a1); return r; } @@ -1304,16 +1302,16 @@ class BigInt_ { } @:noCompletion - private static inline function arithmeticShiftLeft2(a:BigInt_, b:Int):BigInt_ { + private static inline function arithmeticShiftLeft2(a4:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.arithmeticShiftLeft(r, a, b); + BigIntArithmetic.arithmeticShiftLeft(r, a4, b); return r; } @:noCompletion - private static inline function arithmeticShiftRight2(a:BigInt_, b:Int):BigInt_ { + private static inline function arithmeticShiftRight2(a5:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.arithmeticShiftRight(r, a, b); + BigIntArithmetic.arithmeticShiftRight(r, a5, b); return r; } From 4a785f36ed5d62cbf1a683befd216e31746d954f Mon Sep 17 00:00:00 2001 From: flashultra Date: Sat, 14 Dec 2024 23:43:39 +0200 Subject: [PATCH 111/134] Debug --- std/haxe/math/bigint/BigIntArithmetic.hx | 24 +++---- std/haxe/math/bigint/BigInt_.hx | 92 ++++++++++++------------ std/haxe/math/bigint/MutableBigInt_.hx | 44 ++++++------ 3 files changed, 80 insertions(+), 80 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index c24778d2485..86bd3b4662f 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -36,11 +36,11 @@ class BigIntArithmetic { returns 1 if `a > b`; otherwise returns 0 (`a == b`). **/ - public static function compareInt(a:BigInt_, b:Int):Int { - if (a.m_count > 1) { - return (a.sign() << 1) + 1; + public static function compareInt(a5:BigInt_, b:Int):Int { + if (a5.m_count > 1) { + return (a5.sign() << 1) + 1; } - var x:Int = a.m_data.get(0); + var x:Int = a5.m_data.get(0); var lt:Int = (x - b) ^ ((x ^ b) & ((x - b) ^ x)); // "Hacker's Delight" p. 23 var gt:Int = (b - x) ^ ((x ^ b) & ((b - x) ^ b)); return (lt >> 31) | (gt >>> 31); @@ -53,15 +53,15 @@ class BigIntArithmetic { returns 1 if `a > b`; otherwise returns 0 (`a == b`). **/ - public static function compare(a:BigInt_, b:BigInt_):Int { - if (a != b) { - var c:Int = (a.sign() & 2) + (b.sign() & 1); + public static function compare(a6:BigInt_, b:BigInt_):Int { + if (a6 != b) { + var c:Int = (a6.sign() & 2) + (b.sign() & 1); switch (c) { case 0: // a and b are positive - if (a.m_count > b.m_count) { + if (a6.m_count > b.m_count) { return 1; } - if (a.m_count < b.m_count) { + if (a6.m_count < b.m_count) { return -1; } case 1: // a is positive, b is negative @@ -69,14 +69,14 @@ class BigIntArithmetic { case 2: // a is negative, b is positive return -1; case 3: // a and b are negative - if (a.m_count > b.m_count) { + if (a6.m_count > b.m_count) { return -1; } - if (a.m_count < b.m_count) { + if (a6.m_count < b.m_count) { return 1; } } - return MultiwordArithmetic.compareUnsigned(a.m_data, b.m_data, a.m_count); + return MultiwordArithmetic.compareUnsigned(a6.m_data, b.m_data, a6.m_count); } return 0; } diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index dff39930c37..f804725c933 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -1222,82 +1222,82 @@ class BigInt_ { } @:noCompletion - private static inline function equals2Int(a:BigInt_, b:Int):Bool { - return a.equalsInt(b); + private static inline function equals2Int(a15:BigInt_, b:Int):Bool { + return a15.equalsInt(b); } @:noCompletion - private static inline function equals2(a:BigInt_, b:BigInt_):Bool { - return a.equals(b); + private static inline function equals2(a16:BigInt_, b:BigInt_):Bool { + return a16.equals(b); } @:noCompletion - private static inline function addInt2(a:BigInt_, b:Int):BigInt_ { + private static inline function addInt2(a17:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.addInt(r, a, b); + BigIntArithmetic.addInt(r, a17, b); return r; } @:noCompletion - private static inline function add2(a:BigInt_, b:BigInt_):BigInt_ { + private static inline function add2(a18:BigInt_, b:BigInt_):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.add(r, a, b); + BigIntArithmetic.add(r, a18, b); return r; } @:noCompletion - private static inline function subInt2(a:BigInt_, b:Int):BigInt_ { + private static inline function subInt2(a19:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.subtractInt(r, a, b); + BigIntArithmetic.subtractInt(r, a19, b); return r; } @:noCompletion - private static inline function sub2(a:BigInt_, b:BigInt_):BigInt_ { + private static inline function sub2(a20:BigInt_, b:BigInt_):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.subtract(r, a, b); + BigIntArithmetic.subtract(r, a20, b); return r; } @:noCompletion - private static inline function multiplyInt2(a:BigInt_, b:Int):BigInt_ { + private static inline function multiplyInt2(a21:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.multiplyInt(r, a, b); + BigIntArithmetic.multiplyInt(r, a21, b); return r; } @:noCompletion - private static inline function multiply2(a:BigInt_, b:BigInt_):BigInt_ { + private static inline function multiply2(a22:BigInt_, b:BigInt_):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.multiply(r, a, b); + BigIntArithmetic.multiply(r, a22, b); return r; } @:noCompletion - private static inline function divideInt2(a:BigInt_, b:Int):BigInt_ { + private static inline function divideInt2(a23:BigInt_, b:Int):BigInt_ { var q = new MutableBigInt_(); - BigIntArithmetic.divideInt(a, b, q); + BigIntArithmetic.divideInt(a23, b, q); return q; } @:noCompletion - private static inline function divide2(a:BigInt_, b:BigInt_):BigInt_ { + private static inline function divide2(a24:BigInt_, b:BigInt_):BigInt_ { var q = new MutableBigInt_(); - BigIntArithmetic.divide(a, b, q, null); + BigIntArithmetic.divide(a24, b, q, null); return q; } @:noCompletion - private static inline function modulusInt2(a:BigInt_, b:Int):Int { + private static inline function modulusInt2(a25:BigInt_, b:Int):Int { var q = new MutableBigInt_(); - return BigIntArithmetic.divideInt(a, b, q); + return BigIntArithmetic.divideInt(a25, b, q); } @:noCompletion - private static inline function modulus2(a:BigInt_, b:BigInt_):BigInt_ { + private static inline function modulus2(a26:BigInt_, b:BigInt_):BigInt_ { var q = new MutableBigInt_(); var r = new MutableBigInt_(); - BigIntArithmetic.divide(a, b, q, r); + BigIntArithmetic.divide(a26, b, q, r); return r; } @@ -1316,55 +1316,55 @@ class BigInt_ { } @:noCompletion - private static inline function sign1(a:BigInt_):Int { - return a.sign(); + private static inline function sign1(a27:BigInt_):Int { + return a27.sign(); } @:noCompletion - private static inline function isZero1(a:BigInt_):Bool { - return a.isZero(); + private static inline function isZero1(a28:BigInt_):Bool { + return a28.isZero(); } @:noCompletion - private static inline function isNegative1(a:BigInt_):Bool { - return a.isNegative(); + private static inline function isNegative1(a29:BigInt_):Bool { + return a29.isNegative(); } @:noCompletion - private static inline function isPositive1(a:BigInt_):Bool { - return a.isPositive(); + private static inline function isPositive1(a30:BigInt_):Bool { + return a30.isPositive(); } @:noCompletion - private static inline function isOdd1(a:BigInt_):Bool { - return a.isOdd(); + private static inline function isOdd1(a31:BigInt_):Bool { + return a31.isOdd(); } @:noCompletion - private static inline function isEven1(a:BigInt_):Bool { - return a.isEven(); + private static inline function isEven1(a32:BigInt_):Bool { + return a32.isEven(); } @:noCompletion - private static inline function toString1(a:BigInt_, radix:Int):String { - if ((radix == 10 ) || ( radix <2 || radix >36 )) return a.toString(); - if (radix == 16 ) return a.toHex(); - return a.toBase(radix); + private static inline function toString1(a33:BigInt_, radix:Int):String { + if ((radix == 10 ) || ( radix <2 || radix >36 )) return a33.toString(); + if (radix == 16 ) return a33.toHex(); + return a33.toBase(radix); } @:noCompletion - private static inline function toHex1(a:BigInt_):String { - return a.toHex(); + private static inline function toHex1(a34:BigInt_):String { + return a34.toHex(); } @:noCompletion - private static inline function toBytes1(a:BigInt_):Bytes { - return a.toBytes(); + private static inline function toBytes1(a35:BigInt_):Bytes { + return a35.toBytes(); } @:noCompletion - private static inline function toInts1(a:BigInt_, v:Vector):Int { - return a.toInts(v); + private static inline function toInts1(a36:BigInt_, v:Vector):Int { + return a36.toInts(v); } static final BitLengthTable:Array = [ diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index f489830eaad..a76cace2fdf 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -430,55 +430,55 @@ class MutableBigInt_ extends BigInt_ { } @:noCompletion - private static inline function multiplyAssignInt2(a:MutableBigInt_, b:Int):Void { + private static inline function multiplyAssignInt2(a7:MutableBigInt_, b:Int):Void { var r = new MutableBigInt_(); - BigIntArithmetic.multiplyInt(r, a, b); - a.copy(r); + BigIntArithmetic.multiplyInt(r, a7, b); + a7.copy(r); } @:noCompletion - private static inline function multiplyAssign2(a:MutableBigInt_, b:BigInt_):Void { + private static inline function multiplyAssign2(a8:MutableBigInt_, b:BigInt_):Void { var r = new MutableBigInt_(); - BigIntArithmetic.multiply(r, a, b); - a.copy(r); + BigIntArithmetic.multiply(r, a8, b); + a8.copy(r); } @:noCompletion - private static inline function divideAssignInt2(a:MutableBigInt_, b:Int):Void { + private static inline function divideAssignInt2(a9:MutableBigInt_, b:Int):Void { var q = new MutableBigInt_(); - BigIntArithmetic.divideInt(a, b, q); - a.copy(q); + BigIntArithmetic.divideInt(a9, b, q); + a9.copy(q); } @:noCompletion - private static inline function divideAssign2(a:MutableBigInt_, b:BigInt_):Void { + private static inline function divideAssign2(a10:MutableBigInt_, b:BigInt_):Void { var q = new MutableBigInt_(); - BigIntArithmetic.divide(a, b, q, null); - a.copy(q); + BigIntArithmetic.divide(a10, b, q, null); + a10.copy(q); } @:noCompletion - private static inline function modulusAssignInt2(a:MutableBigInt_, b:Int):Void { + private static inline function modulusAssignInt2(a11:MutableBigInt_, b:Int):Void { var q = new MutableBigInt_(); - var r = BigIntArithmetic.divideInt(a, b, q); - a.setFromInt(r); + var r = BigIntArithmetic.divideInt(a11, b, q); + a11.setFromInt(r); } @:noCompletion - private static inline function modulusAssign2(a:MutableBigInt_, b:BigInt_):Void { + private static inline function modulusAssign2(a12:MutableBigInt_, b:BigInt_):Void { var q = new MutableBigInt_(); var r = new MutableBigInt_(); - BigIntArithmetic.divide(a, b, q, r); - a.copy(r); + BigIntArithmetic.divide(a12, b, q, r); + a12.copy(r); } @:noCompletion - private static inline function arithmeticShiftLeftAssign2(a:MutableBigInt_, b:Int):Void { - BigIntArithmetic.arithmeticShiftLeft(a, a, b); + private static inline function arithmeticShiftLeftAssign2(a13:MutableBigInt_, b:Int):Void { + BigIntArithmetic.arithmeticShiftLeft(a13, a13, b); } @:noCompletion - private static inline function arithmeticShiftRightAssign2(a:MutableBigInt_, b:Int):Void { - BigIntArithmetic.arithmeticShiftRight(a, a, b); + private static inline function arithmeticShiftRightAssign2(a14:MutableBigInt_, b:Int):Void { + BigIntArithmetic.arithmeticShiftRight(a14, a14, b); } } From 965a27473b665659a5c9f04da004754ad60c40ae Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 15 Dec 2024 00:02:18 +0200 Subject: [PATCH 112/134] Debug --- std/haxe/math/bigint/BigIntArithmetic.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 86bd3b4662f..dd383df4c45 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -54,6 +54,8 @@ class BigIntArithmetic { returns 0 (`a == b`). **/ public static function compare(a6:BigInt_, b:BigInt_):Int { + trace("______________Compare: "+b); + trace("______________Compare: "+a6); if (a6 != b) { var c:Int = (a6.sign() & 2) + (b.sign() & 1); switch (c) { From 380e0668ecd3188dcf8c7bfe3b407a43585e0ef6 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 15 Dec 2024 09:29:39 +0200 Subject: [PATCH 113/134] How num is null? --- std/haxe/math/bigint/BigIntArithmetic.hx | 4 ++-- std/haxe/math/bigint/BigInt_.hx | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index dd383df4c45..60eed8b61fc 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -54,8 +54,8 @@ class BigIntArithmetic { returns 0 (`a == b`). **/ public static function compare(a6:BigInt_, b:BigInt_):Int { - trace("______________Compare: "+b); - trace("______________Compare: "+a6); + trace("______________Compare(b): "+b); + trace("______________Compare(a): "+a6); if (a6 != b) { var c:Int = (a6.sign() & 2) + (b.sign() & 1); switch (c) { diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index f804725c933..a59b6a0aa87 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -570,6 +570,9 @@ class BigInt_ { } public static function random(bits:Int32):BigInt_ { + #if lua + trace("call random("+bits+")"); + #end if (bits <= 0) return BigInt.ZERO; var r = new MutableBigInt_(); @@ -645,6 +648,9 @@ class BigInt_ { do { do { num = random(this.bitLength()); + #if lua + trace("num: "+num); + #end } while (BigIntArithmetic.compare(num, BigInt.ZERO) == 0 || BigIntArithmetic.compare(num, montyRadix) == 0 || BigIntArithmetic.compare(num, minusMontyRadix) == 0 From 27e52a98b76583a11e1b9cddc3fbdfcb62798f22 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 16 Dec 2024 10:06:03 +0200 Subject: [PATCH 114/134] Trigger GitHub actions From 6596762999c661d330ae5fbc91ef8c4d03043e48 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 16 Dec 2024 10:51:06 +0200 Subject: [PATCH 115/134] Spooky compare call --- std/haxe/math/bigint/BigIntArithmetic.hx | 4 ++++ std/haxe/math/bigint/BigInt_.hx | 3 +++ 2 files changed, 7 insertions(+) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 60eed8b61fc..013abcf6e1c 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -54,8 +54,12 @@ class BigIntArithmetic { returns 0 (`a == b`). **/ public static function compare(a6:BigInt_, b:BigInt_):Int { + #if lua trace("______________Compare(b): "+b); trace("______________Compare(a): "+a6); + if (a6 == null) + haxe.CallStack.toString(haxe.CallStack.exceptionStack()); + #end if (a6 != b) { var c:Int = (a6.sign() & 2) + (b.sign() & 1); switch (c) { diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index a59b6a0aa87..df159ab2f07 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -647,6 +647,9 @@ class BigInt_ { do { do { + #if lua + trace("bitLength: "+this.bitLength()); + #end num = random(this.bitLength()); #if lua trace("num: "+num); From 008f6b0139e4fc9e44f780a00174e41b85822ffc Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 16 Dec 2024 13:54:43 +0200 Subject: [PATCH 116/134] wheel of fortune --- std/haxe/math/bigint/BigIntArithmetic.hx | 4 ++-- std/haxe/math/bigint/BigInt_.hx | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index 013abcf6e1c..fb11f6e24b4 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -55,8 +55,8 @@ class BigIntArithmetic { **/ public static function compare(a6:BigInt_, b:BigInt_):Int { #if lua - trace("______________Compare(b): "+b); - trace("______________Compare(a): "+a6); + trace("______________Compare(b-): "+b); + trace("______________Compare(a+): "+a6); if (a6 == null) haxe.CallStack.toString(haxe.CallStack.exceptionStack()); #end diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index df159ab2f07..efef643c3aa 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -644,11 +644,17 @@ class BigInt_ { var montyRadix:BigInt_ = divMod(arithmeticShiftLeft2(BigInt.ONE, 32 * this.m_count), this).remainder; var minusMontyRadix:BigInt_ = sub2(this, montyRadix); var num:BigInt_; - + #if lua + trace("1) bitLength: "+this.bitLength()); + trace("1.1) rounds: "+rounds); + #end + #if lua + num = random(this.bitLength()); + #end do { do { #if lua - trace("bitLength: "+this.bitLength()); + trace("2) bitLength: "+this.bitLength()); #end num = random(this.bitLength()); #if lua @@ -671,6 +677,9 @@ class BigInt_ { } } rounds -= 2; + #if lua + trace("--rounds--: "+rounds); + #end } while (rounds >= 0); return true; From abf4385fda172a1d21527555400a9625046607c3 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 16 Dec 2024 15:40:40 +0200 Subject: [PATCH 117/134] Check if this it the init poblem for Lua --- std/haxe/math/bigint/BigIntArithmetic.hx | 30 ++-- std/haxe/math/bigint/BigInt_.hx | 184 +++++++++++------------ 2 files changed, 99 insertions(+), 115 deletions(-) diff --git a/std/haxe/math/bigint/BigIntArithmetic.hx b/std/haxe/math/bigint/BigIntArithmetic.hx index fb11f6e24b4..c24778d2485 100644 --- a/std/haxe/math/bigint/BigIntArithmetic.hx +++ b/std/haxe/math/bigint/BigIntArithmetic.hx @@ -36,11 +36,11 @@ class BigIntArithmetic { returns 1 if `a > b`; otherwise returns 0 (`a == b`). **/ - public static function compareInt(a5:BigInt_, b:Int):Int { - if (a5.m_count > 1) { - return (a5.sign() << 1) + 1; + public static function compareInt(a:BigInt_, b:Int):Int { + if (a.m_count > 1) { + return (a.sign() << 1) + 1; } - var x:Int = a5.m_data.get(0); + var x:Int = a.m_data.get(0); var lt:Int = (x - b) ^ ((x ^ b) & ((x - b) ^ x)); // "Hacker's Delight" p. 23 var gt:Int = (b - x) ^ ((x ^ b) & ((b - x) ^ b)); return (lt >> 31) | (gt >>> 31); @@ -53,21 +53,15 @@ class BigIntArithmetic { returns 1 if `a > b`; otherwise returns 0 (`a == b`). **/ - public static function compare(a6:BigInt_, b:BigInt_):Int { - #if lua - trace("______________Compare(b-): "+b); - trace("______________Compare(a+): "+a6); - if (a6 == null) - haxe.CallStack.toString(haxe.CallStack.exceptionStack()); - #end - if (a6 != b) { - var c:Int = (a6.sign() & 2) + (b.sign() & 1); + public static function compare(a:BigInt_, b:BigInt_):Int { + if (a != b) { + var c:Int = (a.sign() & 2) + (b.sign() & 1); switch (c) { case 0: // a and b are positive - if (a6.m_count > b.m_count) { + if (a.m_count > b.m_count) { return 1; } - if (a6.m_count < b.m_count) { + if (a.m_count < b.m_count) { return -1; } case 1: // a is positive, b is negative @@ -75,14 +69,14 @@ class BigIntArithmetic { case 2: // a is negative, b is positive return -1; case 3: // a and b are negative - if (a6.m_count > b.m_count) { + if (a.m_count > b.m_count) { return -1; } - if (a6.m_count < b.m_count) { + if (a.m_count < b.m_count) { return 1; } } - return MultiwordArithmetic.compareUnsigned(a6.m_data, b.m_data, a6.m_count); + return MultiwordArithmetic.compareUnsigned(a.m_data, b.m_data, a.m_count); } return 0; } diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index efef643c3aa..4adce591739 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -533,6 +533,13 @@ class BigInt_ { if (bits == 2) return ((Math.random() < 0.5) ? BigInt.TWO : BigInt.fromInt(3)); var r = new MutableBigInt_(); + #if lua + var bytes = randomBytes(bits); + var excessBits = 8 * bytes.length - bits; + bytes.set(0, bytes.get(0) | (1 << (7 - excessBits))); + bytes.set(bytes.length - 1, bytes.get(bytes.length - 1) | 1); + r.setFromBigEndianBytesSigned(bytes); + #end do { var bytes = randomBytes(bits); var excessBits = 8 * bytes.length - bits; @@ -570,9 +577,6 @@ class BigInt_ { } public static function random(bits:Int32):BigInt_ { - #if lua - trace("call random("+bits+")"); - #end if (bits <= 0) return BigInt.ZERO; var r = new MutableBigInt_(); @@ -644,22 +648,12 @@ class BigInt_ { var montyRadix:BigInt_ = divMod(arithmeticShiftLeft2(BigInt.ONE, 32 * this.m_count), this).remainder; var minusMontyRadix:BigInt_ = sub2(this, montyRadix); var num:BigInt_; - #if lua - trace("1) bitLength: "+this.bitLength()); - trace("1.1) rounds: "+rounds); - #end #if lua num = random(this.bitLength()); #end do { do { - #if lua - trace("2) bitLength: "+this.bitLength()); - #end num = random(this.bitLength()); - #if lua - trace("num: "+num); - #end } while (BigIntArithmetic.compare(num, BigInt.ZERO) == 0 || BigIntArithmetic.compare(num, montyRadix) == 0 || BigIntArithmetic.compare(num, minusMontyRadix) == 0 @@ -677,11 +671,7 @@ class BigInt_ { } } rounds -= 2; - #if lua - trace("--rounds--: "+rounds); - #end } while (rounds >= 0); - return true; } @@ -820,7 +810,7 @@ class BigInt_ { return montResult; } - private function squareMonty(a2:Vector, x:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { + private function squareMonty(a:Vector, x:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { var n:Int, aMax:Int, j:Int, i:Int; var xVal:Int, a0:Int; var x0:Int64, carry:Int64, t:Int64, prod1:Int64, prod2:Int64, xi:Int64, u:Int64; @@ -836,53 +826,53 @@ class BigInt_ { prod1 = Int64.mul(x0, Int64.make(0, x[j])); prod2 = Int64.mul(u, Int64.make(0, m[j])); carry = Int64.add(carry, Int64.add(Int64.make(0, Int64.shl(prod1, 1).low), Int64.make(0, prod2.low))); - a2[j - 1] = carry.low; + a[j - 1] = carry.low; carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod2, 32)), Int64.ushr(prod1, 31)); j++; } - a2[mLen] = Int64.ushr(carry, 32).low; - a2[mLen - 1] = carry.low; + a[mLen] = Int64.ushr(carry, 32).low; + a[mLen - 1] = carry.low; i = 1; while (i < mLen) { - a0 = a2[0]; + a0 = a[0]; u = Int64.make(0, Int64.mul(a0, mDash).low); carry = Int64.add(Int64.mul(u, Int64.make(0, m[0])), Int64.make(0, a0)); carry = Int64.ushr(carry, 32); j = 1; while (j < i) { - carry = Int64.add(carry, Int64.add(Int64.mul(u, Int64.make(0, m[j])), Int64.make(0, a2[j]))); - a2[j - 1] = carry.low; + carry = Int64.add(carry, Int64.add(Int64.mul(u, Int64.make(0, m[j])), Int64.make(0, a[j]))); + a[j - 1] = carry.low; carry = Int64.ushr(carry, 32); j++; } xi = Int64.make(0, x[i]); prod1 = Int64.mul(xi, xi); prod2 = Int64.mul(u, Int64.make(0, m[i])); - carry += Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.make(0, a2[i])); - a2[i - 1] = carry.low; + carry += Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.make(0, a[i])); + a[i - 1] = carry.low; carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 32)), Int64.ushr(prod2, 32)); j = i + 1; while (j < n) { prod1 = Int64.mul(xi, Int64.make(0, x[j])); prod2 = Int64.mul(u, Int64.make(0, m[j])); - carry = Int64.add(carry, Int64.add(Int64.add(Int64.make(0, Int64.shl(prod1, 1).low), Int64.make(0, prod2.low)), Int64.make(0, a2[j]))); - a2[j - 1] = carry.low; + carry = Int64.add(carry, Int64.add(Int64.add(Int64.make(0, Int64.shl(prod1, 1).low), Int64.make(0, prod2.low)), Int64.make(0, a[j]))); + a[j - 1] = carry.low; carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 31)), Int64.ushr(prod2, 32)); j++; } - carry = Int64.add(carry, Int64.make(0, a2[n])); - a2[n] = Int64.ushr(carry, 32).low; - a2[n - 1] = carry.low; + carry = Int64.add(carry, Int64.make(0, a[n])); + a[n] = Int64.ushr(carry, 32).low; + a[n - 1] = carry.low; i++; } - if (!smallMontyModulus && compareMonty(a2, m) >= 0) { - subtractMonty(a2,m); + if (!smallMontyModulus && compareMonty(a, m) >= 0) { + subtractMonty(a,m); } - Vector.blit(a2, 0, x, 0, n); + Vector.blit(a, 0, x, 0, n); } - private function multiplyMonty(a3:Vector, x:Vector, y:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { + private function multiplyMonty(a:Vector, x:Vector, y:Vector, m:Vector, mLen:Int, mDash:Int32, smallMontyModulus:Bool):Void { var n:Int, aMax:Int, j:Int, i:Int; var a0:Int64, y0:Int64; var carry:Int64, t:Int64, prod1:Int64, prod2:Int64, xi:Int64, u:Int64; @@ -890,12 +880,12 @@ class BigInt_ { y0 = Int64.make(0, y[0]); i = 0; while (i <= n) { - a3[i] = 0; + a[i] = 0; i++; } i = 0; while (i < n) { - a0 = Int64.make(0, a3[0]); + a0 = Int64.make(0, a[0]); xi = Int64.make(0, x[i]); prod1 = Int64.mul(xi, y0); carry = Int64.add(Int64.make(0, prod1.low), a0); @@ -907,21 +897,21 @@ class BigInt_ { while (j <= (n - 1)) { prod1 = Int64.mul(xi, Int64.make(0, y[j])); prod2 = Int64.mul(u, Int64.make(0, m[j])); - carry = Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.add(Int64.make(0, a3[j]), carry)); - a3[j - 1] = carry.low; + carry = Int64.add(Int64.add(Int64.make(0, prod1.low), Int64.make(0, prod2.low)), Int64.add(Int64.make(0, a[j]), carry)); + a[j - 1] = carry.low; carry = Int64.add(Int64.add(Int64.ushr(carry, 32), Int64.ushr(prod1, 32)), Int64.ushr(prod2, 32)); j++; } - carry = Int64.add(carry, Int64.make(0, a3[n])); - a3[n] = Int64.ushr(carry, 32).low; - a3[n - 1] = carry.low; + carry = Int64.add(carry, Int64.make(0, a[n])); + a[n] = Int64.ushr(carry, 32).low; + a[n - 1] = carry.low; i++; } - if (!smallMontyModulus && compareMonty(a3, m) >= 0) { - subtractMonty(a3,m); + if (!smallMontyModulus && compareMonty(a, m) >= 0) { + subtractMonty(a,m); } - Vector.blit(a3, 0, x, 0, n); + Vector.blit(a, 0, x, 0, n); } private function montgomeryReduce(x:Vector, m:Vector, mLen:Int, mDash:Int32):Void { @@ -1233,156 +1223,156 @@ class BigInt_ { //----------------------------------------------------------------------- @:noCompletion - private static inline function negate1(a1:BigInt_):BigInt_ { + private static inline function negate1(a:BigInt_):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.negate(r, a1); + BigIntArithmetic.negate(r, a); return r; } @:noCompletion - private static inline function equals2Int(a15:BigInt_, b:Int):Bool { - return a15.equalsInt(b); + private static inline function equals2Int(a:BigInt_, b:Int):Bool { + return a.equalsInt(b); } @:noCompletion - private static inline function equals2(a16:BigInt_, b:BigInt_):Bool { - return a16.equals(b); + private static inline function equals2(a:BigInt_, b:BigInt_):Bool { + return a.equals(b); } @:noCompletion - private static inline function addInt2(a17:BigInt_, b:Int):BigInt_ { + private static inline function addInt2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.addInt(r, a17, b); + BigIntArithmetic.addInt(r, a, b); return r; } @:noCompletion - private static inline function add2(a18:BigInt_, b:BigInt_):BigInt_ { + private static inline function add2(a:BigInt_, b:BigInt_):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.add(r, a18, b); + BigIntArithmetic.add(r, a, b); return r; } @:noCompletion - private static inline function subInt2(a19:BigInt_, b:Int):BigInt_ { + private static inline function subInt2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.subtractInt(r, a19, b); + BigIntArithmetic.subtractInt(r, a, b); return r; } @:noCompletion - private static inline function sub2(a20:BigInt_, b:BigInt_):BigInt_ { + private static inline function sub2(a:BigInt_, b:BigInt_):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.subtract(r, a20, b); + BigIntArithmetic.subtract(r, a, b); return r; } @:noCompletion - private static inline function multiplyInt2(a21:BigInt_, b:Int):BigInt_ { + private static inline function multiplyInt2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.multiplyInt(r, a21, b); + BigIntArithmetic.multiplyInt(r, a, b); return r; } @:noCompletion - private static inline function multiply2(a22:BigInt_, b:BigInt_):BigInt_ { + private static inline function multiply2(a:BigInt_, b:BigInt_):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.multiply(r, a22, b); + BigIntArithmetic.multiply(r, a, b); return r; } @:noCompletion - private static inline function divideInt2(a23:BigInt_, b:Int):BigInt_ { + private static inline function divideInt2(a:BigInt_, b:Int):BigInt_ { var q = new MutableBigInt_(); - BigIntArithmetic.divideInt(a23, b, q); + BigIntArithmetic.divideInt(a, b, q); return q; } @:noCompletion - private static inline function divide2(a24:BigInt_, b:BigInt_):BigInt_ { + private static inline function divide2(a:BigInt_, b:BigInt_):BigInt_ { var q = new MutableBigInt_(); - BigIntArithmetic.divide(a24, b, q, null); + BigIntArithmetic.divide(a, b, q, null); return q; } @:noCompletion - private static inline function modulusInt2(a25:BigInt_, b:Int):Int { + private static inline function modulusInt2(a:BigInt_, b:Int):Int { var q = new MutableBigInt_(); - return BigIntArithmetic.divideInt(a25, b, q); + return BigIntArithmetic.divideInt(a, b, q); } @:noCompletion - private static inline function modulus2(a26:BigInt_, b:BigInt_):BigInt_ { + private static inline function modulus2(a:BigInt_, b:BigInt_):BigInt_ { var q = new MutableBigInt_(); var r = new MutableBigInt_(); - BigIntArithmetic.divide(a26, b, q, r); + BigIntArithmetic.divide(a, b, q, r); return r; } @:noCompletion - private static inline function arithmeticShiftLeft2(a4:BigInt_, b:Int):BigInt_ { + private static inline function arithmeticShiftLeft2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.arithmeticShiftLeft(r, a4, b); + BigIntArithmetic.arithmeticShiftLeft(r, a, b); return r; } @:noCompletion - private static inline function arithmeticShiftRight2(a5:BigInt_, b:Int):BigInt_ { + private static inline function arithmeticShiftRight2(a:BigInt_, b:Int):BigInt_ { var r = new MutableBigInt_(); - BigIntArithmetic.arithmeticShiftRight(r, a5, b); + BigIntArithmetic.arithmeticShiftRight(r, a, b); return r; } @:noCompletion - private static inline function sign1(a27:BigInt_):Int { - return a27.sign(); + private static inline function sign1(a:BigInt_):Int { + return a.sign(); } @:noCompletion - private static inline function isZero1(a28:BigInt_):Bool { - return a28.isZero(); + private static inline function isZero1(a:BigInt_):Bool { + return a.isZero(); } @:noCompletion - private static inline function isNegative1(a29:BigInt_):Bool { - return a29.isNegative(); + private static inline function isNegative1(a:BigInt_):Bool { + return a.isNegative(); } @:noCompletion - private static inline function isPositive1(a30:BigInt_):Bool { - return a30.isPositive(); + private static inline function isPositive1(a:BigInt_):Bool { + return a.isPositive(); } @:noCompletion - private static inline function isOdd1(a31:BigInt_):Bool { - return a31.isOdd(); + private static inline function isOdd1(a:BigInt_):Bool { + return a.isOdd(); } @:noCompletion - private static inline function isEven1(a32:BigInt_):Bool { - return a32.isEven(); + private static inline function isEven1(a:BigInt_):Bool { + return a.isEven(); } @:noCompletion - private static inline function toString1(a33:BigInt_, radix:Int):String { - if ((radix == 10 ) || ( radix <2 || radix >36 )) return a33.toString(); - if (radix == 16 ) return a33.toHex(); - return a33.toBase(radix); + private static inline function toString1(a:BigInt_, radix:Int):String { + if ((radix == 10 ) || ( radix <2 || radix >36 )) return a.toString(); + if (radix == 16 ) return a.toHex(); + return a.toBase(radix); } @:noCompletion - private static inline function toHex1(a34:BigInt_):String { - return a34.toHex(); + private static inline function toHex1(a:BigInt_):String { + return a.toHex(); } @:noCompletion - private static inline function toBytes1(a35:BigInt_):Bytes { - return a35.toBytes(); + private static inline function toBytes1(a:BigInt_):Bytes { + return a.toBytes(); } @:noCompletion - private static inline function toInts1(a36:BigInt_, v:Vector):Int { - return a36.toInts(v); + private static inline function toInts1(a:BigInt_, v:Vector):Int { + return a.toInts(v); } static final BitLengthTable:Array = [ From 5ee77da0f7aa117c4b94a75f972847a1c45fab89 Mon Sep 17 00:00:00 2001 From: flashultra Date: Mon, 16 Dec 2024 16:05:55 +0200 Subject: [PATCH 118/134] Remove trace() and workaround --- std/haxe/math/bigint/BigInt_.hx | 10 ---------- tests/unit/src/unit/TestBigInt.hx | 24 ------------------------ 2 files changed, 34 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 4adce591739..085d34fcbd7 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -533,13 +533,6 @@ class BigInt_ { if (bits == 2) return ((Math.random() < 0.5) ? BigInt.TWO : BigInt.fromInt(3)); var r = new MutableBigInt_(); - #if lua - var bytes = randomBytes(bits); - var excessBits = 8 * bytes.length - bits; - bytes.set(0, bytes.get(0) | (1 << (7 - excessBits))); - bytes.set(bytes.length - 1, bytes.get(bytes.length - 1) | 1); - r.setFromBigEndianBytesSigned(bytes); - #end do { var bytes = randomBytes(bits); var excessBits = 8 * bytes.length - bits; @@ -648,9 +641,6 @@ class BigInt_ { var montyRadix:BigInt_ = divMod(arithmeticShiftLeft2(BigInt.ONE, 32 * this.m_count), this).remainder; var minusMontyRadix:BigInt_ = sub2(this, montyRadix); var num:BigInt_; - #if lua - num = random(this.bitLength()); - #end do { do { num = random(this.bitLength()); diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index abd96abbc36..cf424e50116 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2632,19 +2632,6 @@ class TestBigInt extends Test { public function testPrimeNumber():Void { - #if lua - trace("testPrimeNumber"); - var i:Int = 35; - trace("primeNumber: "+s_primeNumbers[i]); - var b:BigInt = s_primeNumbers[i]; - trace("b: "+b); - var bm:MutableBigInt = s_primeNumbers[i]; - trace("check b "); - t(b.isProbablePrime(10)); - trace("check bm"); - t(bm.isProbablePrime(10)); - - #else for(i in 0...s_primeNumbers.length) { var b:BigInt = s_primeNumbers[i]; var bm:MutableBigInt = s_primeNumbers[i]; @@ -2657,7 +2644,6 @@ class TestBigInt extends Test { f(b.isProbablePrime(10)); f(bm.isProbablePrime(10)); } - #end } public function testLowestSetBit():Void @@ -2792,29 +2778,19 @@ class TestBigInt extends Test { public function testBigIntRandomPrime():Void { - #if lua - trace("testBigIntRandomPrime"); - #end var randomPrimeNumber:BigInt = BigInt.randomPrime(5,5); - #if (php || python || lua) trace("randomPrimeNumber(5): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(11,5); - #if (php || python || lua) trace("randomPrimeNumber(11): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(16,5); - #if (php || python || lua) trace("randomPrimeNumber(16): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(32,5); - #if (php || python || lua) trace("randomPrimeNumber(32): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(55,5); - #if (php || python || lua) trace("randomPrimeNumber(55): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(128,5); - #if (php || python || lua) trace("randomPrimeNumber(128): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(156,5); - #if (php || python || lua) trace("randomPrimeNumber(156): " + randomPrimeNumber); #end t(randomPrimeNumber.isProbablePrime(5)); } From 194cd6ffb97a6df8983e40be1efe8ad115a18b4c Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 17 Dec 2024 14:21:07 +0200 Subject: [PATCH 119/134] Remove Lua fix --- std/lua/_lua/_hx_bit.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/std/lua/_lua/_hx_bit.lua b/std/lua/_lua/_hx_bit.lua index 327d830f379..0eef3f32479 100644 --- a/std/lua/_lua/_hx_bit.lua +++ b/std/lua/_lua/_hx_bit.lua @@ -19,4 +19,3 @@ end _hx_bit.bor = function(...) return _hx_bit_clamp(_hx_bit_raw.bor(...)) end _hx_bit.band = function(...) return _hx_bit_clamp(_hx_bit_raw.band(...)) end _hx_bit.arshift = function(...) return _hx_bit_clamp(_hx_bit_raw.arshift(...)) end -_hx_bit.lshift = function(...) return _hx_bit_clamp(_hx_bit_raw.lshift(...)) end From bdf1e32ae56489b5ff740f85aa867e9f2f260839 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 17 Dec 2024 18:55:14 +0200 Subject: [PATCH 120/134] Add test for Python --- tests/unit/src/unit/TestBigInt.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index cf424e50116..1321ab338ec 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2779,18 +2779,25 @@ class TestBigInt extends Test { public function testBigIntRandomPrime():Void { var randomPrimeNumber:BigInt = BigInt.randomPrime(5,5); + #if (php || python) trace("randomPrimeNumber(5): " + randomPrimeNumber.toString()); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(11,5); + #if (php || python) trace("randomPrimeNumber(11): " + randomPrimeNumber.toString()); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(16,5); + #if (php || python) trace("randomPrimeNumber(16): " + randomPrimeNumber.toString()); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(32,5); + #if (php || python) trace("randomPrimeNumber(32): " + randomPrimeNumber.toString()); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(55,5); + #if (php || python) trace("randomPrimeNumber(55): " + randomPrimeNumber.toString()); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(128,5); + #if (php || python) trace("randomPrimeNumber(128): " + randomPrimeNumber.toString()); #end t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(156,5); + #if (php || python) trace("randomPrimeNumber(156): " + randomPrimeNumber.toString()); #end t(randomPrimeNumber.isProbablePrime(5)); } From ebfc73605aa4b82c7402f4f09c455472e1e1acd4 Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 17 Dec 2024 20:08:57 +0200 Subject: [PATCH 121/134] Check why Python failed --- std/haxe/math/bigint/BigInt_.hx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 085d34fcbd7..927edb0223e 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -219,7 +219,13 @@ class BigInt_ { rounds = 2; } rounds = (tolerance < rounds) ? tolerance : rounds; + #if python + var result:Bool = b.millerRabin(rounds); + if ( !result) trace("Failed: "+b.toString()); + return result; + #else return b.millerRabin(rounds); + #end } /** From 903db1e10b1ebba45e492f18d1fe5062c6cbe24d Mon Sep 17 00:00:00 2001 From: flashultra Date: Tue, 17 Dec 2024 21:00:33 +0200 Subject: [PATCH 122/134] Check Python --- std/haxe/math/bigint/BigInt_.hx | 6 ---- tests/unit/src/unit/TestBigInt.hx | 49 ++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 927edb0223e..085d34fcbd7 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -219,13 +219,7 @@ class BigInt_ { rounds = 2; } rounds = (tolerance < rounds) ? tolerance : rounds; - #if python - var result:Bool = b.millerRabin(rounds); - if ( !result) trace("Failed: "+b.toString()); - return result; - #else return b.millerRabin(rounds); - #end } /** diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index 1321ab338ec..ad0671642e5 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2779,26 +2779,61 @@ class TestBigInt extends Test { public function testBigIntRandomPrime():Void { var randomPrimeNumber:BigInt = BigInt.randomPrime(5,5); - #if (php || python) trace("randomPrimeNumber(5): " + randomPrimeNumber.toString()); #end + #if (php || python) + var result:Bool = randomPrimeNumber.isProbablePrime(5); + if (!result) trace("randomPrimeNumber(5): " + randomPrimeNumber.toString()); + t(result); + #else t(randomPrimeNumber.isProbablePrime(5)); + #end randomPrimeNumber = BigInt.randomPrime(11,5); - #if (php || python) trace("randomPrimeNumber(11): " + randomPrimeNumber.toString()); #end + #if (php || python) + var result:Bool = randomPrimeNumber.isProbablePrime(5); + if (!result) trace("randomPrimeNumber(11): " + randomPrimeNumber.toString()); + t(result); + #else t(randomPrimeNumber.isProbablePrime(5)); + #end randomPrimeNumber = BigInt.randomPrime(16,5); - #if (php || python) trace("randomPrimeNumber(16): " + randomPrimeNumber.toString()); #end + #if (php || python) + var result:Bool = randomPrimeNumber.isProbablePrime(5); + if (!result) trace("randomPrimeNumber(16): " + randomPrimeNumber.toString()); + t(result); + #else t(randomPrimeNumber.isProbablePrime(5)); + #end randomPrimeNumber = BigInt.randomPrime(32,5); - #if (php || python) trace("randomPrimeNumber(32): " + randomPrimeNumber.toString()); #end + #if (php || python) + var result:Bool = randomPrimeNumber.isProbablePrime(5); + if (!result) trace("randomPrimeNumber(32): " + randomPrimeNumber.toString()); + t(result); + #else t(randomPrimeNumber.isProbablePrime(5)); + #end randomPrimeNumber = BigInt.randomPrime(55,5); - #if (php || python) trace("randomPrimeNumber(55): " + randomPrimeNumber.toString()); #end + #if (php || python) + var result:Bool = randomPrimeNumber.isProbablePrime(5); + if (!result) trace("randomPrimeNumber(55): " + randomPrimeNumber.toString()); + t(result); + #else t(randomPrimeNumber.isProbablePrime(5)); + #end randomPrimeNumber = BigInt.randomPrime(128,5); - #if (php || python) trace("randomPrimeNumber(128): " + randomPrimeNumber.toString()); #end + #if (php || python) + var result:Bool = randomPrimeNumber.isProbablePrime(5); + if (!result) trace("randomPrimeNumber(128): " + randomPrimeNumber.toString()); + t(result); + #else t(randomPrimeNumber.isProbablePrime(5)); + #end randomPrimeNumber = BigInt.randomPrime(156,5); - #if (php || python) trace("randomPrimeNumber(156): " + randomPrimeNumber.toString()); #end + #if (php || python) + var result:Bool = randomPrimeNumber.isProbablePrime(5); + if (!result) trace("randomPrimeNumber(156): " + randomPrimeNumber.toString()); + t(result); + #else t(randomPrimeNumber.isProbablePrime(5)); + #end } public function testBigIntRandomInRange():Void From 428232eca17793e0024a17e1c83c79a37e160f79 Mon Sep 17 00:00:00 2001 From: flashultra Date: Wed, 18 Dec 2024 11:12:32 +0200 Subject: [PATCH 123/134] Fix Python target --- std/haxe/math/bigint/BigInt_.hx | 2 +- tests/unit/src/unit/TestBigInt.hx | 42 ------------------------------- 2 files changed, 1 insertion(+), 43 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 085d34fcbd7..2a40c66cfc0 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -937,7 +937,7 @@ class BigInt_ { yIndex--; } var xn : Int, yn : Int, i:Int = 0; - var c : Int = 0, z : Int = 0; + var c : Int32 = 0, z : Int = 0; while(i<=yIndex) { xn = x.get(i); diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index ad0671642e5..cf424e50116 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2779,61 +2779,19 @@ class TestBigInt extends Test { public function testBigIntRandomPrime():Void { var randomPrimeNumber:BigInt = BigInt.randomPrime(5,5); - #if (php || python) - var result:Bool = randomPrimeNumber.isProbablePrime(5); - if (!result) trace("randomPrimeNumber(5): " + randomPrimeNumber.toString()); - t(result); - #else t(randomPrimeNumber.isProbablePrime(5)); - #end randomPrimeNumber = BigInt.randomPrime(11,5); - #if (php || python) - var result:Bool = randomPrimeNumber.isProbablePrime(5); - if (!result) trace("randomPrimeNumber(11): " + randomPrimeNumber.toString()); - t(result); - #else t(randomPrimeNumber.isProbablePrime(5)); - #end randomPrimeNumber = BigInt.randomPrime(16,5); - #if (php || python) - var result:Bool = randomPrimeNumber.isProbablePrime(5); - if (!result) trace("randomPrimeNumber(16): " + randomPrimeNumber.toString()); - t(result); - #else t(randomPrimeNumber.isProbablePrime(5)); - #end randomPrimeNumber = BigInt.randomPrime(32,5); - #if (php || python) - var result:Bool = randomPrimeNumber.isProbablePrime(5); - if (!result) trace("randomPrimeNumber(32): " + randomPrimeNumber.toString()); - t(result); - #else t(randomPrimeNumber.isProbablePrime(5)); - #end randomPrimeNumber = BigInt.randomPrime(55,5); - #if (php || python) - var result:Bool = randomPrimeNumber.isProbablePrime(5); - if (!result) trace("randomPrimeNumber(55): " + randomPrimeNumber.toString()); - t(result); - #else t(randomPrimeNumber.isProbablePrime(5)); - #end randomPrimeNumber = BigInt.randomPrime(128,5); - #if (php || python) - var result:Bool = randomPrimeNumber.isProbablePrime(5); - if (!result) trace("randomPrimeNumber(128): " + randomPrimeNumber.toString()); - t(result); - #else t(randomPrimeNumber.isProbablePrime(5)); - #end randomPrimeNumber = BigInt.randomPrime(156,5); - #if (php || python) - var result:Bool = randomPrimeNumber.isProbablePrime(5); - if (!result) trace("randomPrimeNumber(156): " + randomPrimeNumber.toString()); - t(result); - #else t(randomPrimeNumber.isProbablePrime(5)); - #end } public function testBigIntRandomInRange():Void From 7778f199e883f8b49622c63933dd984220b45c97 Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 19 Dec 2024 19:20:36 +0200 Subject: [PATCH 124/134] Fix for Neko --- std/haxe/math/bigint/BigInt_.hx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 2a40c66cfc0..b1c7caa989e 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -397,6 +397,25 @@ class BigInt_ { return r; } + #if neko + public function modPow(exponent:BigInt_, modulus:BigInt_):BigInt_ { + if (BigIntArithmetic.compareInt(exponent, 0) < 0) + throw new BigIntException(BigIntError.NEGATIVE_EXPONENT); + if (this.isZero()) + return (BigIntArithmetic.compareInt(exponent, 0) == 0 ? BigInt.fromInt(1) : this); + var r = BigInt_.newFromInt(1); + var p:BigInt_ = this; + while (true) { + if (BigIntArithmetic.bitwiseAndInt(exponent, 1) == 1) + r = modulus2(multiply2(p, r), modulus); + exponent = BigInt_.arithmeticShiftRight2(exponent, 1); + if (BigIntArithmetic.compareInt(exponent, 0) == 0) + break; + p = modulus2(multiply2(p, p), modulus); + } + return r; + } + #else public function modPow(exponent:BigInt_, modulus:BigInt_):BigInt_ { if (BigIntArithmetic.compareInt(modulus, 0) < 0) throw BigIntError.NEGATIVE_MODULUS; @@ -422,6 +441,7 @@ class BigInt_ { } return result; } + #end public function pow(exponent:UInt):BigInt_ { if (exponent < 0) From 1fd473b2a8a278c328a253268eedce1d2bc0513f Mon Sep 17 00:00:00 2001 From: flashultra Date: Thu, 19 Dec 2024 19:54:36 +0200 Subject: [PATCH 125/134] Fix Neko II --- std/haxe/math/bigint/BigInt_.hx | 38 +++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index b1c7caa989e..e30d9bc20e6 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -640,6 +640,32 @@ class BigInt_ { } } + #if neko + private function millerRabin(rounds:UInt):Bool { + var minusOne:BigInt_ = subInt2(this, 1); + var m = subInt2(this, 1); + var lsb = m.getLowestSetBit(); + if (lsb <= 0) + return false; + m = arithmeticShiftRight2(m, lsb); + var num:BigInt_; + for (i in 0...rounds) { + num = randomInRange(BigInt.TWO, minusOne); + var z:BigInt_ = num.modPow(m, this); + if (BigIntArithmetic.compare(z, BigInt.ONE) != 0 && BigIntArithmetic.compare(z, minusOne) != 0) { + var j:Int = 1; + while (j <= lsb && BigIntArithmetic.compare(z, minusOne) != 0) { + if (BigIntArithmetic.compare(z, BigInt.ONE) == 0 || j == lsb) { + return false; + } + z = z.modPow(BigInt.TWO, this); + j++; + } + } + } + return true; + } + #else private function millerRabin(rounds:Int):Bool { var numLists:Int = ((this.bitLength() - 1) < s_primeNumbers.length) ? (this.bitLength() - 1) : s_primeNumbers.length; for (i in 0...numLists) { @@ -684,6 +710,7 @@ class BigInt_ { } while (rounds >= 0); return true; } + #end /* hac 14.64, pp. 610 */ private function modInverseOdd(y:BigInt_, x:BigInt_):BigInt_ { @@ -728,7 +755,8 @@ class BigInt_ { return d; } - + + #if !neko private function modPowMonty(b:BigInt_, _e:BigInt_, _m:BigInt_, convert:Bool):BigInt_ { var n:Int, powR:Int, @@ -996,7 +1024,7 @@ class BigInt_ { } return 0; } - + private function getMQuote():Int32 { var d:Int = -m_data[0]; var mQuote:Int32 = modInverse32(d); @@ -1164,7 +1192,7 @@ class BigInt_ { } return x; } - + private function divideWords(w:Int):BigInt_ { var n:Int = m_count; if (w >= n) @@ -1182,6 +1210,8 @@ class BigInt_ { bi.setFromVector(m_data, 0, w); return bi; } + + #end private static function newFromInt(value:Int):BigInt_ { var bi = new MutableBigInt_(); @@ -1448,4 +1478,4 @@ class BigInt_ { [2851, 2857, 2861],[2879, 2887, 2897],[2903, 2909, 2917],[2927, 2939, 2953], [2957, 2963, 2969],[2971, 2999, 3001],[3011, 3019, 3023],[3037, 3041, 3049] ]; -} +} \ No newline at end of file From 36966026a1825bbd4a1b8370dfd5f05d5cb257bf Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 20 Dec 2024 09:12:44 +0200 Subject: [PATCH 126/134] Remove prime test for Lua and Cppia --- tests/unit/src/unit/TestBigInt.hx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index cf424e50116..ee32e03a4c5 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2749,6 +2749,7 @@ class TestBigInt extends Test { public function testNextProbablePrime():Void { + #if (!lua && !cppia) var a:BigInt; a = "8329132432461"; eq("8329132432469",a.nextProbablePrime().toString()); @@ -2764,6 +2765,7 @@ class TestBigInt extends Test { eq("40870721",a.nextProbablePrime().toString()); a = 32747015; eq("32747023",a.nextProbablePrime().toString()); + #end } public function testBigIntRandom():Void @@ -2778,6 +2780,7 @@ class TestBigInt extends Test { public function testBigIntRandomPrime():Void { + #if (!lua && !cppia) var randomPrimeNumber:BigInt = BigInt.randomPrime(5,5); t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(11,5); @@ -2792,6 +2795,7 @@ class TestBigInt extends Test { t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(156,5); t(randomPrimeNumber.isProbablePrime(5)); + #end } public function testBigIntRandomInRange():Void From 3ec3f61bb91b47f9dedefdc0a57bee97b4f7cef9 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 20 Dec 2024 14:03:35 +0200 Subject: [PATCH 127/134] Fix for Cppia (see issue #11897) --- std/haxe/math/bigint/BigInt_.hx | 6 +++--- tests/unit/src/unit/TestBigInt.hx | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index e30d9bc20e6..f48f0befccd 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -1034,9 +1034,9 @@ class BigInt_ { private function modInverse32(d:Int):Int32 { var x:Int32; x = d + (((d + 1) & 4) << 1); - x = x * (2 - (d * x)); - x = x * (2 - (d * x)); - x = x * (2 - (d * x)); + x = (2 - (d * x)) * x; + x = (2 - (d * x)) * x; + x = (2 - (d * x)) * x; return x; } diff --git a/tests/unit/src/unit/TestBigInt.hx b/tests/unit/src/unit/TestBigInt.hx index ee32e03a4c5..c29cc807f05 100644 --- a/tests/unit/src/unit/TestBigInt.hx +++ b/tests/unit/src/unit/TestBigInt.hx @@ -2747,9 +2747,9 @@ class TestBigInt extends Test { eq("692421",a.max(b).toString()); } + #if (!lua && !cppia) public function testNextProbablePrime():Void { - #if (!lua && !cppia) var a:BigInt; a = "8329132432461"; eq("8329132432469",a.nextProbablePrime().toString()); @@ -2765,8 +2765,8 @@ class TestBigInt extends Test { eq("40870721",a.nextProbablePrime().toString()); a = 32747015; eq("32747023",a.nextProbablePrime().toString()); - #end } + #end public function testBigIntRandom():Void { @@ -2778,9 +2778,9 @@ class TestBigInt extends Test { } } + #if (!lua && !cppia) public function testBigIntRandomPrime():Void { - #if (!lua && !cppia) var randomPrimeNumber:BigInt = BigInt.randomPrime(5,5); t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(11,5); @@ -2795,8 +2795,8 @@ class TestBigInt extends Test { t(randomPrimeNumber.isProbablePrime(5)); randomPrimeNumber = BigInt.randomPrime(156,5); t(randomPrimeNumber.isProbablePrime(5)); - #end } + #end public function testBigIntRandomInRange():Void { From 4bf72517a7917cf5348b23732183f19bb838cb43 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 20 Dec 2024 15:01:12 +0200 Subject: [PATCH 128/134] Reorder const --- std/haxe/math/bigint/BigInt.hx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index ca8ed6598a6..60923a2402a 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -35,6 +35,11 @@ abstract BigInt(BigInt_) { public static var ONE(default, null):BigInt = new BigInt(BigInt_.fromInt(1)); public static var TWO(default, null):BigInt = new BigInt(BigInt_.fromInt(2)); public static var MINUS_ONE(default, null):BigInt = new BigInt(BigInt_.fromInt(-1)); + + //----------------------------------------------------------------------- + // Private constants + //----------------------------------------------------------------------- + private static var SMALL_PRIMES_PRODUCT:BigInt = BigInt.fromString("1451887755777639901511587432083070202422614380984889313550570919659315177065956574359078912654149167643992684236991305777574330831666511589145701059710742276692757882915756220901998212975756543223550490431013061082131040808010565293748926901442915057819663730454818359472391642885328171302299245556663073719855"); //----------------------------------------------------------------------- // Public interface @@ -441,10 +446,4 @@ abstract BigInt(BigInt_) { @:noCompletion @:noDoc private inline function new(a:BigInt_) { this = a; - } - - //----------------------------------------------------------------------- - // Private constants - //----------------------------------------------------------------------- - private static var SMALL_PRIMES_PRODUCT:BigInt = BigInt.fromString("1451887755777639901511587432083070202422614380984889313550570919659315177065956574359078912654149167643992684236991305777574330831666511589145701059710742276692757882915756220901998212975756543223550490431013061082131040808010565293748926901442915057819663730454818359472391642885328171302299245556663073719855"); } From 542d1bd5be96e318e370e895d72a7d138dd31772 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 20 Dec 2024 15:07:33 +0200 Subject: [PATCH 129/134] Fix typo --- std/haxe/math/bigint/BigInt.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 60923a2402a..8b2cd9db17d 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -446,4 +446,5 @@ abstract BigInt(BigInt_) { @:noCompletion @:noDoc private inline function new(a:BigInt_) { this = a; + } } From 51eaff108778eaa77ac02e1693e7f20ae7a50575 Mon Sep 17 00:00:00 2001 From: flashultra Date: Fri, 20 Dec 2024 20:14:42 +0200 Subject: [PATCH 130/134] Reorder static var --- std/haxe/math/bigint/BigInt_.hx | 15 ++++++++------- std/haxe/math/bigint/MutableBigInt_.hx | 11 ++++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index f48f0befccd..74ed5a12516 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -31,6 +31,14 @@ import haxe.io.Bytes; @:allow(unit) @:allow(haxe.math.bigint) class BigInt_ { + + private var m_count:Int = 0; + private var m_data:Vector; + + private static inline var s_firstCachedValue:Int = -16; + private static inline var s_lastCachedValue:Int = 16; + private static var s_cache:Vector = null; + //----------------------------------------------------------------------- // Public interface //----------------------------------------------------------------------- @@ -1251,13 +1259,6 @@ class BigInt_ { } } - private var m_count:Int = 0; - private var m_data:Vector; - - private static inline var s_firstCachedValue:Int = -16; - private static inline var s_lastCachedValue:Int = 16; - private static var s_cache:Vector = null; - //----------------------------------------------------------------------- // Static helpers //----------------------------------------------------------------------- diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index a76cace2fdf..056ce354d1b 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -34,6 +34,12 @@ import haxe.io.Bytes; @:allow(unit) @:allow(haxe.math.bigint) class MutableBigInt_ extends BigInt_ { + + private var m_owned:Bool = false; + + private static var s_testAllocation:Bool = false; + private static var s_debugAllocationPadding:Int = 0; + //----------------------------------------------------------------------- // Public interface //----------------------------------------------------------------------- @@ -373,11 +379,6 @@ class MutableBigInt_ extends BigInt_ { return r; } - private var m_owned:Bool = false; - - private static var s_testAllocation:Bool = false; - private static var s_debugAllocationPadding:Int = 0; - //----------------------------------------------------------------------- // Static helpers //----------------------------------------------------------------------- From 65f0dd723e69cf9ae50ffa500c47b10d56ebd54b Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 22 Dec 2024 11:43:50 +0200 Subject: [PATCH 131/134] Workaround Cppia --- std/haxe/math/bigint/MutableBigInt_.hx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index 056ce354d1b..2435c890f38 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -48,6 +48,9 @@ class MutableBigInt_ extends BigInt_ { Set the value of this big int with an integer of value `value`. **/ public function setFromInt(value:Int):Void { + #if cppia + if ( m_data == null) return; + #end ensureCapacity(1, false); m_data.set(0, value); m_count = 1; @@ -76,6 +79,9 @@ class MutableBigInt_ extends BigInt_ { if ((value == null) || (value.length < 1)) { throw new BigIntException(BigIntError.INVALID_ARGUMENT); } + #if cppia + if ( m_data == null) return; + #end var negate = value.charCodeAt(0) == 0x2d; var index = negate ? 1 : 0; if (value.length <= index) { From ab17d830d5502188f3b898d1b444e2e6f6145b2e Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 22 Dec 2024 14:11:12 +0200 Subject: [PATCH 132/134] Fix Cppia II --- std/haxe/math/bigint/MutableBigInt_.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index 2435c890f38..c1ed23670ba 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -48,10 +48,10 @@ class MutableBigInt_ extends BigInt_ { Set the value of this big int with an integer of value `value`. **/ public function setFromInt(value:Int):Void { + ensureCapacity(1, false); #if cppia if ( m_data == null) return; #end - ensureCapacity(1, false); m_data.set(0, value); m_count = 1; } @@ -79,9 +79,6 @@ class MutableBigInt_ extends BigInt_ { if ((value == null) || (value.length < 1)) { throw new BigIntException(BigIntError.INVALID_ARGUMENT); } - #if cppia - if ( m_data == null) return; - #end var negate = value.charCodeAt(0) == 0x2d; var index = negate ? 1 : 0; if (value.length <= index) { @@ -142,6 +139,9 @@ class MutableBigInt_ extends BigInt_ { } var neg = value.get(length - 1) >>> 31; ensureCapacity(length + neg, false); + #if cppia + if ( m_data == null) return; + #end m_data.set(length + neg - 1, 0); MultiwordArithmetic.copy(m_data, value, length); m_count = length + neg; From 432a3d1fef8b59d096ac001407ff12796327a072 Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 22 Dec 2024 17:52:11 +0200 Subject: [PATCH 133/134] Give up --- std/haxe/math/bigint/MutableBigInt_.hx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/std/haxe/math/bigint/MutableBigInt_.hx b/std/haxe/math/bigint/MutableBigInt_.hx index c1ed23670ba..056ce354d1b 100644 --- a/std/haxe/math/bigint/MutableBigInt_.hx +++ b/std/haxe/math/bigint/MutableBigInt_.hx @@ -49,9 +49,6 @@ class MutableBigInt_ extends BigInt_ { **/ public function setFromInt(value:Int):Void { ensureCapacity(1, false); - #if cppia - if ( m_data == null) return; - #end m_data.set(0, value); m_count = 1; } @@ -139,9 +136,6 @@ class MutableBigInt_ extends BigInt_ { } var neg = value.get(length - 1) >>> 31; ensureCapacity(length + neg, false); - #if cppia - if ( m_data == null) return; - #end m_data.set(length + neg - 1, 0); MultiwordArithmetic.copy(m_data, value, length); m_count = length + neg; From c188704123c01594375eb8a13d2579cacbd5d3af Mon Sep 17 00:00:00 2001 From: flashultra Date: Sun, 22 Dec 2024 21:31:16 +0200 Subject: [PATCH 134/134] I won't never give up, no, never give up, no --- std/haxe/math/bigint/BigInt.hx | 3 ++- std/haxe/math/bigint/BigInt_.hx | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/std/haxe/math/bigint/BigInt.hx b/std/haxe/math/bigint/BigInt.hx index 8b2cd9db17d..c925db75604 100644 --- a/std/haxe/math/bigint/BigInt.hx +++ b/std/haxe/math/bigint/BigInt.hx @@ -39,8 +39,9 @@ abstract BigInt(BigInt_) { //----------------------------------------------------------------------- // Private constants //----------------------------------------------------------------------- + #if !cppia private static var SMALL_PRIMES_PRODUCT:BigInt = BigInt.fromString("1451887755777639901511587432083070202422614380984889313550570919659315177065956574359078912654149167643992684236991305777574330831666511589145701059710742276692757882915756220901998212975756543223550490431013061082131040808010565293748926901442915057819663730454818359472391642885328171302299245556663073719855"); - + #end //----------------------------------------------------------------------- // Public interface //----------------------------------------------------------------------- diff --git a/std/haxe/math/bigint/BigInt_.hx b/std/haxe/math/bigint/BigInt_.hx index 74ed5a12516..ae55a76561d 100644 --- a/std/haxe/math/bigint/BigInt_.hx +++ b/std/haxe/math/bigint/BigInt_.hx @@ -567,11 +567,13 @@ class BigInt_ { bytes.set(0, bytes.get(0) | (1 << (7 - excessBits))); bytes.set(bytes.length - 1, bytes.get(bytes.length - 1) | 1); r.setFromBigEndianBytesSigned(bytes); + #if !cppia if (bits > 10) { while (!equals2Int(r.gcd(BigInt.SMALL_PRIMES_PRODUCT), 1)) { BigIntArithmetic.addInt(r, r, 2); } } + #end } while (!r.isProbablePrime(tolerance)); if (r.sign() < 0) BigIntArithmetic.negate(r, r);