diff --git a/Sources/BigInt/BigFrac.swift b/Sources/BigInt/BigFrac.swift index 4e8cdc3..47bb2ac 100644 --- a/Sources/BigInt/BigFrac.swift +++ b/Sources/BigInt/BigFrac.swift @@ -7,13 +7,14 @@ /// A signed fraction with numerator and denominator of unbounded size. /// A BFraction value is represented by a BInt numerator and a BInt denominator. -/// The representation is normalized, so that numerator and denominator has no common divisors except 1. -/// The denominator is always positive, 0 has the representation 0/1 +/// The representation is normalized, so that numerator and denominator has no +/// common divisors except 1. The denominator is always positive, 0 has the +/// representation 0/1. public struct BFraction: CustomStringConvertible, Comparable, Equatable { mutating func normalize() { let g = self.numerator.gcd(self.denominator) - if g.magnitude.compare(1) > 0 { + if g.words.compare(1) > 0 { self.numerator = self.numerator.quotientExact(dividingBy: g) self.denominator = self.denominator.quotientExact(dividingBy: g) } diff --git a/Sources/BigInt/BigInt-Extensions.swift b/Sources/BigInt/BigInt-Extensions.swift new file mode 100644 index 0000000..a143e2c --- /dev/null +++ b/Sources/BigInt/BigInt-Extensions.swift @@ -0,0 +1,126 @@ +// +// BigInt-Extensions.swift +// +// Created by Mike Griebling on 13.07.2023. +// +/// Added `SignedInteger`, `BinaryInteger`, and `Numeric` protocol compliance. +/// Optional support for `StaticBigInt`. Note: These extensions require +/// renaming `magnitude` to `words` to avoid conflict with the +/// `Numeric` protocol variable also called `magnitude`. +/// +/// Why support protocols? By supporting them you have the ability to +/// formulate generic algorithms and make use of algorithms from others +/// that use the protocol type(s) you support. For example, `Strideable` +/// compliance is free (with `BinaryInteger`) and lets you do things like +/// +/// ```swift +/// for i in BInt(1)...10 { +/// print(i.words) +/// } +/// ``` +/// +/// The main header also +/// includes `Codable` compliance conformity (for free). `Codable` +/// compliance allows `BInt`s to be distributed/received or stored/read as +/// JSONs. +/// +/// Protocols mean you can support generic arguments: +/// (e.g., `func * (_ lhs: Self, rhs: T) -> Self`) +/// which works with all `BinaryIntegers`, including `BigInt`s instead of +/// just `Int`s or a single integer type. +/// + +extension BInt : SignedInteger { + public static var isSigned: Bool { true } + + public init(integerLiteral value: Int) { + self.init(value) + } + + public init(_ source: T) where T : BinaryInteger { + if let int = BInt(exactly: source) { + self = int + } else { + self.init(0) + } + } + + public init(clamping source: T) where T : BinaryInteger { + self.init(source) + } + + public init(truncatingIfNeeded source: T) where T : BinaryInteger { + self.init(source) + } + + public init?(exactly source: T) where T : BinaryInteger { + var isNegative = false + if source.signum() < 0 { + isNegative = true + } + let words = source.words + var bwords = Limbs() + for word in words { + if isNegative { bwords.append(UInt(~word)) } + else { bwords.append(UInt(word)) } + } + self.init(bwords, false) + if isNegative { self += 1; self.negate() } + } + + public init?(exactly source: T) where T : BinaryFloatingPoint { + guard source.isFinite else { return nil } + if source.rounded() != source { return nil } + if source.isZero { self.init(0); return } + self.init(source) + } + + public init(_ source: T) where T : BinaryFloatingPoint { + // FIXME: - Support other types of BinaryFloatingPoint + if let bint = BInt(Double(source)) { + self = bint + } else { + self.init(0) + } + } +} + +extension BInt : Numeric { + public var magnitude: BInt { BInt(words) } +} + +extension BInt : BinaryInteger { + public static func <<= (lhs: inout BInt, rhs: RHS) { + lhs = lhs << Int(rhs) + } + + public static func >>= (lhs: inout BInt, rhs: RHS) { + lhs = lhs >> Int(rhs) + } +} + +/// Add support for `StaticBigInt` - 24 Jun 2023 - MG +/// Currently disabled due to Swift Playground incompatiblity +/// Uncomment to enable `StaticBigInt` support (i.e., huge integer literals). +//@available(macOS 13.3, *) +//extension BInt : ExpressibleByIntegerLiteral { +// public init(integerLiteral value: StaticBigInt) { +// let isNegative = value.signum() < 0 +// let bitWidth = value.bitWidth +// if bitWidth < Int.bitWidth { +// self.init(Int(bitPattern: value[0])) +// } else { +// precondition(value[0].bitWidth == 64, "Requires 64-bit Ints!") +// let noOfWords = (bitWidth / 64) + 1 // must be 64-bit system +// var words = Limbs() +// for index in 0..(_ lhs: Self, rhs: T) -> Self`) +/// which works with all `BinaryIntegers`, including `BigInt`s instead of +/// just `Int`s or a single integer type. +/// +public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable, Codable { // MARK: - Constants @@ -66,11 +92,12 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// Constructs a BInt from magnitude and sign /// /// - Parameters: - /// - magnitude: magnitude of value + /// - words: unsigned value array /// - isNegative: *true* means negative value, *false* means 0 or positive value, default is *false* - public init(_ magnitude: Limbs, _ isNegative : Bool = false) { - self.magnitude = magnitude - self.magnitude.normalize() + public init(_ words: Limbs, _ isNegative : Bool = false) { + precondition(Limb.bitWidth == 64, "64-bit UInt REQUIRED!") + self.words = words + self.words.normalize() self.isNegative = isNegative if self.isZero { self.isNegative = false @@ -101,7 +128,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { } let bits = d.bitPattern let exponent = Int(bits >> 52) & 0x7ff - 1075 - let significand = exponent == -1075 ? bits & 0xfffffffffffff << 1 : bits & 0xfffffffffffff | (1 << 52) + let significand = UInt(exponent == -1075 ? bits & 0xfffffffffffff << 1 : bits & 0xfffffffffffff | (1 << 52)) if exponent < 0 { self.init([significand].shiftedRight(-exponent), d < 0.0) } else { @@ -253,22 +280,22 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { } let chunks = bb.count / 8 let remaining = bb.count - chunks * 8 - self.magnitude = Limbs(repeating: 0, count: chunks + (remaining == 0 ? 0 : 1)) + self.words = Limbs(repeating: 0, count: chunks + (remaining == 0 ? 0 : 1)) var bi = 0 - var li = self.magnitude.count + var li = self.words.count if remaining > 0 { li -= 1 } for _ in 0 ..< remaining { - self.magnitude[li] <<= 8 - self.magnitude[li] |= Limb(bb[bi]) + self.words[li] <<= 8 + self.words[li] |= Limb(bb[bi]) bi += 1 } for _ in 0 ..< chunks { li -= 1 for _ in 0 ..< 8 { - self.magnitude[li] <<= 8 - self.magnitude[li] |= Limb(bb[bi]) + self.words[li] <<= 8 + self.words[li] |= Limb(bb[bi]) bi += 1 } } @@ -281,19 +308,19 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { public internal(set) var isNegative: Bool /// The magnitude limb array - public internal(set) var magnitude: Limbs + public internal(set) var words: Limbs // MARK: Computed properties /// The absolute value of *self* public var abs: BInt { - return BInt(self.magnitude) + return BInt(self.words) } /// The number of bits in the binary representation of the magnitude of *self*. 0 if *self* = 0 public var bitWidth: Int { - return self.magnitude.bitWidth + return self.words.bitWidth } /// Base 10 string value of *self* @@ -303,22 +330,22 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// Is *true* if *self* is even, *false* if *self* is odd public var isEven: Bool { - return self.magnitude[0] & 1 == 0 + return self.words[0] & 1 == 0 } /// Is *false* if *self* = 0, *true* otherwise public var isNotZero: Bool { - return self.magnitude.count > 1 || self.magnitude[0] > 0 + return self.words.count > 1 || self.words[0] > 0 } /// Is *true* if *self* is odd, *false* if *self* is even public var isOdd: Bool { - return self.magnitude[0] & 1 == 1 + return self.words[0] & 1 == 1 } /// Is *true* if *self* = 1, *false* otherwise public var isOne: Bool { - return self.magnitude.count == 1 && self.magnitude[0] == 1 && !self.isNegative + return self.words.count == 1 && self.words[0] == 1 && !self.isNegative } /// Is *true* if *self* > 0, *false* otherwise @@ -328,18 +355,18 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// Is *true* if *self* = 0, *false* otherwise public var isZero: Bool { - return self.magnitude.count == 1 && self.magnitude[0] == 0 + return self.words.count == 1 && self.words[0] == 0 } /// The number of leading zero bits in the magnitude of *self*. 0 if *self* = 0 public var leadingZeroBitCount: Int { - return self.isZero ? 0 : self.magnitude.last!.leadingZeroBitCount + return self.isZero ? 0 : self.words.last!.leadingZeroBitCount } /// The number of 1 bits in the magnitude of *self* public var population: Int { var p = 0 - for m in self.magnitude { + for m in self.words { p += BInt.population(m) } return p @@ -352,7 +379,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// The number of trailing zero bits in the magnitude of *self*. 0 if *self* = 0 public var trailingZeroBitCount: Int { - return self.magnitude.trailingZeroBitCount() + return self.words.trailingZeroBitCount() } /* @@ -383,7 +410,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - Returns: *self* as a Double or *Infinity* if *self* is not representable as a Double public func asDouble() -> Double { var d = 0.0 - for m in self.magnitude.reversed() { + for m in self.words.reversed() { d *= BInt.d264 d += Double(m) } @@ -394,10 +421,10 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// /// - Returns: *self* as an Int or *nil* if *self* is not representable as an Int public func asInt() -> Int? { - if self.magnitude.count > 1 { + if self.words.count > 1 { return nil } - let mag0 = self.magnitude[0] + let mag0 = self.words[0] if self.isNegative { return mag0 > 0x8000000000000000 ? nil : (mag0 == 0x8000000000000000 ? Int.min : -Int(mag0)) } else { @@ -471,7 +498,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// * BInt(1).asSignedBytes() = [1] /// * BInt(-1).asSignedBytes() = [255] public func asSignedBytes() -> Bytes { - var xl = self.magnitude + var xl = self.words if self.isNegative { var carry = true for i in 0 ..< xl.count { @@ -528,7 +555,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { } let d = BInt.limbRadix[radix] var digitGroups = [String]() - var tmp = self.magnitude + var tmp = self.words while !tmp.equalTo(0) { let (q, r) = tmp.divMod(d) digitGroups.append(String(r, radix: radix, uppercase: uppercase)) @@ -545,8 +572,8 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { } static func toSignedLimbsPair(_ x: BInt, _ y: BInt) -> (bx: Limbs, by: Limbs) { - var bx = x.magnitude - var by = y.magnitude + var bx = x.words + var by = y.words if x.isNegative { invert(&bx) if bx.last! & 0x8000000000000000 == 0 { @@ -698,21 +725,21 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// /// - Parameter n: Bit number public mutating func clearBit(_ n: Int) { - self.magnitude.clearBitAt(n) + self.words.clearBitAt(n) } /// Invert a specified bit - a no-op if bit number < 0 /// /// - Parameter n: Bit number public mutating func flipBit(_ n: Int) { - self.magnitude.flipBitAt(n) + self.words.flipBitAt(n) } /// Set a specified bit - a no-op if bit number < 0 /// /// - Parameter n: Bit number public mutating func setBit(_ n: Int) { - self.magnitude.setBitAt(n) + self.words.setBitAt(n) } /// Test a specified bit - *false* if bit number < 0 @@ -720,7 +747,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - Parameter n: Bit number /// - Returns: *true* if bit is set, *false* otherwise public func testBit(_ n: Int) -> Bool { - return self.magnitude.testBitAt(n) + return self.words.testBitAt(n) } @@ -777,9 +804,9 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - y: Right hand addend public static func +=(x: inout BInt, y: BInt) { if x.isNegative == y.isNegative { - x.magnitude.add(y.magnitude) + x.words.add(y.words) } else { - let cmp = x.magnitude.difference(y.magnitude) + let cmp = x.words.difference(y.words) if cmp < 0 { x.isNegative = !x.isNegative } else if cmp == 0 { @@ -800,18 +827,18 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if y > 0 { if x.isNegative { - if x.magnitude.difference(Limb(y)) <= 0 { + if x.words.difference(Limb(y)) <= 0 { x.setSign(false) } } else { - x.magnitude.add(Limb(y)) + x.words.add(Limb(y)) } } else if y < 0 { let yy = y == Int.min ? 0x8000000000000000 : Limb(-y) if x.isNegative { - x.magnitude.add(yy) + x.words.add(yy) } else { - if x.magnitude.difference(yy) < 0 { + if x.words.difference(yy) < 0 { x.setSign(true) } } @@ -884,14 +911,14 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - y: Right hand subtrahend public static func -=(x: inout BInt, y: BInt) { if x.isNegative == y.isNegative { - let cmp = x.magnitude.difference(y.magnitude) + let cmp = x.words.difference(y.words) if cmp < 0 { x.isNegative = !x.isNegative } else if cmp == 0 { x.isNegative = false } } else { - x.magnitude.add(y.magnitude) + x.words.add(y.words) } } @@ -907,18 +934,18 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if y > 0 { if x.isNegative { - x.magnitude.add(Limb(y)) + x.words.add(Limb(y)) } else { - if x.magnitude.difference(Limb(y)) < 0 { + if x.words.difference(Limb(y)) < 0 { x.setSign(true) } } } else if y < 0 { let yy = y == Int.min ? 0x8000000000000000 : Limb(-y) if x.isPositive { - x.magnitude.add(yy) + x.words.add(yy) } else { - if x.magnitude.difference(yy) <= 0 { + if x.words.difference(yy) <= 0 { x.setSign(false) } } @@ -970,7 +997,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - x: Left hand multiplier /// - y: Right hand multiplicand public static func *=(x: inout BInt, y: BInt) { - x.magnitude.multiply(y.magnitude) + x.words.multiply(y.words) x.setSign(x.isNegative != y.isNegative) } @@ -981,12 +1008,12 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - y: Right hand multiplicand public static func *=(x: inout BInt, y: Int) { if y > 0 { - x.magnitude.multiply(Limb(y)) + x.words.multiply(Limb(y)) } else if y < 0 { if y == Int.min { - x.magnitude.shiftLeft(63) + x.words.shiftLeft(63) } else { - x.magnitude.multiply(Limb(-y)) + x.words.multiply(Limb(-y)) } x.setSign(!x.isNegative) } else { @@ -1005,10 +1032,10 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { public func quotientAndRemainder(dividingBy x: BInt) -> (quotient: BInt, remainder: BInt) { var quotient = BInt.ZERO var remainder = BInt.ZERO - if x.magnitude.count > BInt.BZ_DIV_LIMIT && self.magnitude.count > x.magnitude.count + BInt.BZ_DIV_LIMIT { + if x.words.count > BInt.BZ_DIV_LIMIT && self.words.count > x.words.count + BInt.BZ_DIV_LIMIT { (quotient, remainder) = self.bzDivMod(x) } else { - (quotient.magnitude, remainder.magnitude) = self.magnitude.divMod(x.magnitude) + (quotient.words, remainder.words) = self.words.divMod(x.words) } quotient.setSign(self.isNegative != x.isNegative) remainder.setSign(self.isNegative) @@ -1040,7 +1067,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { } var quotient = BInt.ZERO var r: Limb - (quotient.magnitude, r) = self.magnitude.divMod(divisor) + (quotient.words, r) = self.words.divMod(divisor) quotient.setSign(self.isNegative && x > 0 || self.isPositive && x < 0) let remainder = self.isNegative ? -Int(r) : Int(r) return (quotient, remainder) @@ -1063,7 +1090,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - Parameter x: Divisor - a BInt value /// - Returns: Quotient of *self* / x - undefined if the remainder is in fact not 0 public func quotientExact(dividingBy x: BInt) -> BInt { - return BInt(self.magnitude.divExact(x.magnitude), self.isNegative != x.isNegative) + return BInt(self.words.divExact(x.words), self.isNegative != x.isNegative) } /// Division @@ -1196,11 +1223,11 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - Returns: *self* *mod* x, a non-negative value public func mod(_ x: Int) -> Int { if x == Int.min { - let r = Int(self.magnitude[0] & 0x7fffffffffffffff) + let r = Int(self.words[0] & 0x7fffffffffffffff) return self.isNegative && r > 0 ? -(Int.min + r) : r } let absx = Limb(Swift.abs(x)) - let (_, r) = self.magnitude.divMod(absx) + let (_, r) = self.words.divMod(absx) return Int(self.isNegative && r > 0 ? absx - r : r) } @@ -1218,7 +1245,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { return BInt.ZERO } let tb = m.trailingZeroBitCount - if tb <= 1024 && tb + m.leadingZeroBitCount == m.magnitude.count << 6 - 1 { + if tb <= 1024 && tb + m.leadingZeroBitCount == m.words.count << 6 - 1 { precondition(self.isOdd, "No inverse modulus") @@ -1231,7 +1258,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { var x = BInt.ZERO var b = BInt.ONE for i in 0 ..< tb { - if b.magnitude[0] & 1 == 1 { + if b.words[0] & 1 == 1 { x.setBit(i) b -= selfr } @@ -1263,7 +1290,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { // [KOC] - section 7 // Reduce mod m - let m = self.magnitude[0] & (1 << tb - 1) + let m = self.words[0] & (1 << tb - 1) let selfr = self.isNegative ? -Int(m) : Int(m) var x = 0 @@ -1301,7 +1328,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - Returns: a^x public static func **(a: BInt, x: Int) -> BInt { precondition(x >= 0, "Exponent must be non-negative") - return x == 2 ? (a.magnitude.count > 16 ? BInt(a.magnitude.squared()) : a * a) : BInt(a.magnitude.raisedTo(x), a.isNegative && (x & 1 == 1)) + return x == 2 ? (a.words.count > 16 ? BInt(a.words.squared()) : a * a) : BInt(a.words.raisedTo(x), a.isNegative && (x & 1 == 1)) } /* @@ -1323,7 +1350,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { } let exponent = x.isNegative ? -x : x var result: BInt - if exponent.magnitude.count <= 32 { + if exponent.words.count <= 32 { result = BarrettModulus(self, m).expMod(exponent) } else if m.isOdd { result = MontgomeryModulus(self, m).expMod(exponent) @@ -1409,7 +1436,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - y: Second operand /// - Returns: *true* if x = y, *false* otherwise public static func ==(x: BInt, y: BInt) -> Bool { - return x.magnitude == y.magnitude && x.isNegative == y.isNegative + return x.words == y.words && x.isNegative == y.isNegative } /// Equal @@ -1439,7 +1466,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - y: Second operand /// - Returns: *true* if x != y, *false* otherwise public static func !=(x: BInt, y: BInt) -> Bool { - return x.magnitude != y.magnitude || x.isNegative != y.isNegative + return x.words != y.words || x.isNegative != y.isNegative } /// Not equal @@ -1471,7 +1498,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { public static func <(x: BInt, y: BInt) -> Bool { if x.isNegative { if y.isNegative { - return y.magnitude.compare(x.magnitude) < 0 + return y.words.compare(x.words) < 0 } else { return true } @@ -1479,7 +1506,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if y.isNegative { return false } else { - return x.magnitude.compare(y.magnitude) < 0 + return x.words.compare(y.words) < 0 } } } @@ -1493,7 +1520,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { public static func <(x: BInt, y: Int) -> Bool { if x.isNegative { if y < 0 { - return y == Int.min ? x < BInt(y) : x.magnitude.compare(Limb(-y)) > 0 + return y == Int.min ? x < BInt(y) : x.words.compare(Limb(-y)) > 0 } else { return true } @@ -1501,7 +1528,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if y < 0 { return false } else { - return x.magnitude.compare(Limb(y)) < 0 + return x.words.compare(Limb(y)) < 0 } } } @@ -1515,7 +1542,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { public static func <(x: Int, y: BInt) -> Bool { if y.isNegative { if x < 0 { - return x == Int.min ? BInt(x) < y : y.magnitude.compare(Limb(-x)) <= 0 + return x == Int.min ? BInt(x) < y : y.words.compare(Limb(-x)) <= 0 } else { return false } @@ -1523,7 +1550,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if x < 0 { return true } else { - return y.magnitude.compare(Limb(x)) > 0 + return y.words.compare(Limb(x)) > 0 } } } @@ -1634,7 +1661,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if n < 0 { return n == Int.min ? (x >> Int.max) >> 1 : x >> -n } - return BInt(n == 1 ? x.magnitude.shifted1Left() : x.magnitude.shiftedLeft(n), x.isNegative) + return BInt(n == 1 ? x.words.shifted1Left() : x.words.shiftedLeft(n), x.isNegative) } /// x = x << n @@ -1645,15 +1672,15 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { public static func <<=(x: inout BInt, n: Int) { if n < 0 { if n == Int.min { - x.magnitude.shiftRight(Int.max) - x.magnitude.shift1Right() + x.words.shiftRight(Int.max) + x.words.shift1Right() } else { - x.magnitude.shiftRight(-n) + x.words.shiftRight(-n) } } else if n == 1 { - x.magnitude.shift1Left() + x.words.shift1Left() } else { - x.magnitude.shiftLeft(n) + x.words.shiftLeft(n) } } @@ -1670,7 +1697,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if n < 0 { return n == Int.min ? (x << Int.max) << 1 : x << -n } - return BInt(n == 1 ? x.magnitude.shifted1Right() : x.magnitude.shiftedRight(n), x.isNegative) + return BInt(n == 1 ? x.words.shifted1Right() : x.words.shiftedRight(n), x.isNegative) } /// x = x >> n @@ -1681,15 +1708,15 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { public static func >>=(x: inout BInt, n: Int) { if n < 0 { if n == Int.min { - x.magnitude.shiftLeft(Int.max) - x.magnitude.shift1Left() + x.words.shiftLeft(Int.max) + x.words.shift1Left() } else { - x.magnitude.shiftLeft(-n) + x.words.shiftLeft(-n) } } else if n == 1 { - x.magnitude.shift1Right() + x.words.shift1Right() } else { - x.magnitude.shiftRight(n) + x.words.shiftRight(n) } if x.isZero { x.isNegative = false @@ -2020,16 +2047,16 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { /// - Returns: root = the integer part of the square root of *self*, rem = *self* - root^2 public func sqrtRemainder() -> (root: BInt, rem: BInt) { precondition(!self.isNegative, "Square root of negative number") - let l = (self.magnitude.count - 1) >> 2 + let l = (self.words.count - 1) >> 2 if l == 0 { let sq = self.basicSqrt() return (sq, self - sq ** 2) } let shifts = l * 64 - let a0 = BInt(Limbs(self.magnitude[0 ..< l])) - let a1 = BInt(Limbs(self.magnitude[l ..< 2 * l])) - let a2 = BInt(Limbs(self.magnitude[2 * l ..< 3 * l])) - let a3 = BInt(Limbs(self.magnitude[3 * l ..< self.magnitude.count])) + let a0 = BInt(Limbs(self.words[0 ..< l])) + let a1 = BInt(Limbs(self.words[l ..< 2 * l])) + let a2 = BInt(Limbs(self.words[2 * l ..< 3 * l])) + let a3 = BInt(Limbs(self.words[3 * l ..< self.words.count])) let (s1, r1) = (a3 << shifts + a2).sqrtRemainder() let (q, u) = (r1 << shifts + a1).quotientAndRemainder(dividingBy: s1 << 1) var s = s1 << shifts + q @@ -2066,7 +2093,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if self.isNegative { return false } else { - return BInt.maybeSquare[Int(self.magnitude[0] & 0xff)] ? self.sqrtRemainder().rem.isZero : false + return BInt.maybeSquare[Int(self.words[0] & 0xff)] ? self.sqrtRemainder().rem.isZero : false } } @@ -2347,7 +2374,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if v.isZero { return u } - if u.magnitude.count > 1 { + if u.words.count > 1 { let r = u.quotientAndRemainder(dividingBy: v).remainder u = v v = r @@ -2358,7 +2385,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { // u and v are one-limb values assert(u < BInt.ONE << 64) assert(v < BInt.ONE << 64) - return BInt([Limbs.binaryGcd(u.magnitude[0], v.magnitude[0])]) + return BInt([Limbs.binaryGcd(u.words[0], v.words[0])]) } /* @@ -2466,7 +2493,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { while a.isNotZero { while a.isEven { a >>= 1 - let x = m1.magnitude[0] & 7 + let x = m1.words[0] & 7 if x == 3 || x == 5 { t = -t } @@ -2474,7 +2501,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { let x = a a = m1 m1 = x - if a.magnitude[0] & 3 == 3 && m1.magnitude[0] & 3 == 3 { + if a.words[0] & 3 == 3 && m1.words[0] & 3 == 3 { t = -t } a = a.mod(m1) @@ -2525,7 +2552,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if self.isEven { return 0 } else { - let r = self.magnitude[0] & 7 + let r = self.words[0] & 7 return r == 1 || r == 7 ? self.kroneckerSymbol(m >> 1) : -self.kroneckerSymbol(m >> 1) } } @@ -2549,7 +2576,7 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable { if self.isEven { return 0 } else { - let r = self.magnitude[0] & 7 + let r = self.words[0] & 7 return r == 1 || r == 7 ? self.kroneckerSymbol(m >> 1) : -self.kroneckerSymbol(m >> 1) } } diff --git a/Sources/BigInt/BitSieve.swift b/Sources/BigInt/BitSieve.swift index 87a187d..1787f24 100755 --- a/Sources/BigInt/BitSieve.swift +++ b/Sources/BigInt/BitSieve.swift @@ -63,7 +63,7 @@ class BitSieve { // Construct the large sieve at an even offset specified by base repeat { // Calculate base mod convertedStep - let (_, r) = self.base.magnitude.divMod(UInt64(convertedStep)) + let (_, r) = self.base.words.divMod(UInt(convertedStep)) start = Int(r) // Take each multiple of step out of sieve @@ -83,14 +83,14 @@ class BitSieve { * Get the value of the bit at the specified index. */ func get(_ bitIndex: Int) -> Bool { - return (self.bits[bitIndex >> 6] & Limbs.UMasks[bitIndex & 0x3f]) != 0 + (self.bits[bitIndex >> 6] & UInt64(Limbs.UMasks[bitIndex & 0x3f])) != 0 } /** * Set the bit at the specified index. */ func set(_ bitIndex: Int) { - self.bits[bitIndex >> 6] |= Limbs.UMasks[bitIndex & 0x3f] + self.bits[bitIndex >> 6] |= UInt64(Limbs.UMasks[bitIndex & 0x3f]) } /** @@ -134,7 +134,7 @@ class BitSieve { for i in 0 ..< bits.count { let nextWord = ~bits[i] for j in 0 ..< 64 { - if nextWord & Limbs.UMasks[j] != 0 { + if nextWord & UInt64(Limbs.UMasks[j]) != 0 { let candidate = self.base + offset if candidate.isProbablyPrime(prob) { return candidate diff --git a/Sources/BigInt/BurnikelZiegler.swift b/Sources/BigInt/BurnikelZiegler.swift index bfd7a4b..ce1000d 100644 --- a/Sources/BigInt/BurnikelZiegler.swift +++ b/Sources/BigInt/BurnikelZiegler.swift @@ -16,7 +16,7 @@ extension BInt { func bzDivMod(_ v: BInt) -> (q: BInt, r: BInt) { var A = self.abs var B = v.abs - let s = B.magnitude.count + let s = B.words.count let m = 1 << (64 - (s / BInt.BZ_DIV_LIMIT).leadingZeroBitCount) let j = (s + m - 1) / m let n = j * m @@ -41,12 +41,12 @@ extension BInt { } func blockA(_ n: Int, _ i: Int) -> BInt { - let mc = self.magnitude.count + let mc = self.words.count assert(i * n <= mc) if (i + 1) * n < mc { - return BInt(Limbs(self.magnitude[i * n ..< (i + 1) * n])) + return BInt(Limbs(self.words[i * n ..< (i + 1) * n])) } else { - return BInt(Limbs(self.magnitude[i * n ..< mc])) + return BInt(Limbs(self.words[i * n ..< mc])) } } @@ -54,11 +54,11 @@ extension BInt { * [BURNIKEL] - algorithm 1 */ func bzDiv2n1n(_ n: Int, _ B: BInt) -> (q: BInt, r: BInt) { - if n & 1 == 1 || B.magnitude.count < BInt.BZ_DIV_LIMIT { + if n & 1 == 1 || B.words.count < BInt.BZ_DIV_LIMIT { // Base case - let (q, r) = self.magnitude.divMod(B.magnitude) + let (q, r) = self.words.divMod(B.words) return (BInt(q), BInt(r)) } let n2 = n >> 1 @@ -96,9 +96,9 @@ extension BInt { } func split(_ n: Int) -> (BInt, BInt) { - let mc = self.magnitude.count + let mc = self.words.count if mc > n { - return (BInt(Limbs(self.magnitude[n ..< mc])), BInt(Limbs(self.magnitude[0 ..< n]))) + return (BInt(Limbs(self.words[n ..< mc])), BInt(Limbs(self.words[0 ..< n]))) } else { return (BInt.ZERO, self) } diff --git a/Sources/BigInt/ExpMod.swift b/Sources/BigInt/ExpMod.swift index 59a4c34..a31245f 100755 --- a/Sources/BigInt/ExpMod.swift +++ b/Sources/BigInt/ExpMod.swift @@ -14,8 +14,8 @@ extension BInt { let base: Limbs init(_ a: BInt, _ modulus: BInt) { - self.modulus = modulus.magnitude - self.base = a.magnitude.divMod(self.modulus).remainder + self.modulus = modulus.words + self.base = a.words.divMod(self.modulus).remainder } func toMspace(_ x: Limbs) -> Limbs { diff --git a/Sources/BigInt/ToomCook.swift b/Sources/BigInt/ToomCook.swift index 567d9f3..d958bb7 100755 --- a/Sources/BigInt/ToomCook.swift +++ b/Sources/BigInt/ToomCook.swift @@ -13,10 +13,10 @@ extension Array where Element == Limb { // Works only when the remainder of the division is known to be 0 static func divideBy3(_ d: BInt) -> BInt { - var quotient = Limbs(repeating: 0, count: d.magnitude.count) + var quotient = Limbs(repeating: 0, count: d.words.count) var remainder = Limb(0) for i in 0 ..< quotient.count { - let w = remainder > d.magnitude[i] ? remainder - d.magnitude[i] : d.magnitude[i] - remainder + let w = remainder > d.words[i] ? remainder - d.words[i] : d.words[i] - remainder let x = w &* 0xaaaaaaaaaaaaaaab quotient[i] = x remainder = x < 0x5555555555555556 ? 0 : (x < 0xaaaaaaaaaaaaaaab ? 1 : 2) @@ -72,13 +72,13 @@ extension Array where Element == Limb { var result = Limbs(repeating: 0, count: 6 * k) var offset = k << 2 - result.add(rinf.magnitude, offset) + result.add(rinf.words, offset) offset -= k - result.add(rr3.magnitude, offset) + result.add(rr3.words, offset) offset -= k - result.add(rr2.magnitude, offset) - result.add(rr1.magnitude, k) - result.add(r0.magnitude, 0) + result.add(rr2.words, offset) + result.add(rr1.words, k) + result.add(r0.words, 0) return result } @@ -105,13 +105,13 @@ extension Array where Element == Limb { var result = Limbs(repeating: 0, count: 6 * k) var offset = k << 2 - result.add(vinf.magnitude, offset) + result.add(vinf.words, offset) offset -= k - result.add(t2.magnitude, offset) + result.add(t2.words, offset) offset -= k - result.add(t1.magnitude, offset) - result.add(tm1.magnitude, k) - result.add(v0.magnitude, 0) + result.add(t1.words, offset) + result.add(tm1.words, k) + result.add(v0.words, 0) return result } diff --git a/Tests/BigIntTests/BitTest.swift b/Tests/BigIntTests/BitTest.swift index 8ec1af5..7383640 100755 --- a/Tests/BigIntTests/BitTest.swift +++ b/Tests/BigIntTests/BitTest.swift @@ -111,6 +111,9 @@ class BitTest: XCTestCase { } func test7() { + + + let x = BInt(bitWidth: 50) var y = x y.setBit(-1) @@ -122,11 +125,11 @@ class BitTest: XCTestCase { XCTAssertFalse(y.testBit(-1)) y = BInt(0) y.setBit(200) - XCTAssertEqual(y.magnitude.count, 4) + XCTAssertEqual(y.words.count, 4) XCTAssertEqual(y, BInt.ONE << 200) XCTAssertTrue(y.testBit(200)) y.clearBit(200) - XCTAssertEqual(y.magnitude.count, 1) + XCTAssertEqual(y.words.count, 1) XCTAssertFalse(y.testBit(200)) XCTAssertEqual(y, BInt.ZERO) y.flipBit(200) diff --git a/Tests/BigIntTests/ConstructorTest.swift b/Tests/BigIntTests/ConstructorTest.swift index 1c6515d..873f284 100755 --- a/Tests/BigIntTests/ConstructorTest.swift +++ b/Tests/BigIntTests/ConstructorTest.swift @@ -20,10 +20,10 @@ class ConstructorTest: XCTestCase { func test1() { let x1 = BInt("123", radix: 10)! - XCTAssertEqual(x1.magnitude.count, 1) + XCTAssertEqual(x1.words.count, 1) XCTAssertFalse((x1.isNegative)) let x2 = BInt("-0", radix: 10)! - XCTAssertEqual(x2.magnitude.count, 1) + XCTAssertEqual(x2.words.count, 1) XCTAssertFalse((x2.isNegative)) let b: Bytes = [0, 0, 0, 123] let x3 = BInt(signed: b) @@ -33,7 +33,7 @@ class ConstructorTest: XCTestCase { let x5 = BInt(bitWidth: 100) XCTAssertTrue(x5.bitWidth <= 100) let x6 = BInt("-123")! - XCTAssertEqual(x6.magnitude[0], 123) + XCTAssertEqual(x6.words[0], 123) let x71 = BInt(bitWidth: 100) let x72 = BInt(signed: x71.asSignedBytes()) XCTAssertEqual(x71, x72) @@ -72,9 +72,9 @@ class ConstructorTest: XCTestCase { let x0 = BInt(0) let x1 = BInt(1) let xm1 = BInt(-1) - XCTAssertEqual(x0.magnitude.count, 1) - XCTAssertEqual(x1.magnitude.count, 1) - XCTAssertEqual(xm1.magnitude.count, 1) + XCTAssertEqual(x0.words.count, 1) + XCTAssertEqual(x1.words.count, 1) + XCTAssertEqual(xm1.words.count, 1) XCTAssertFalse(x0.isNegative) XCTAssertFalse(x1.isNegative) XCTAssertTrue(xm1.isNegative) diff --git a/Tests/BigIntTests/DivModBZTest.swift b/Tests/BigIntTests/DivModBZTest.swift index a2db5ac..a8bc66e 100644 --- a/Tests/BigIntTests/DivModBZTest.swift +++ b/Tests/BigIntTests/DivModBZTest.swift @@ -22,10 +22,10 @@ class DivModBZTest: XCTestCase { var r1: Limbs = [] var q2: BInt var r2: BInt - (q1, r1) = dividend.magnitude.divMod(divisor.magnitude) + (q1, r1) = dividend.words.divMod(divisor.words) (q2, r2) = dividend.bzDivMod(divisor) - XCTAssertEqual(q1, q2.magnitude) - XCTAssertEqual(r1, r2.magnitude) + XCTAssertEqual(q1, q2.words) + XCTAssertEqual(r1, r2.words) } func doTest2(_ dividend: BInt, _ divisor: BInt) { @@ -43,7 +43,7 @@ class DivModBZTest: XCTestCase { doTest2(-x, y) doTest2(-x, -y) } - doTest1(BInt(Limbs(repeating: UInt64.max, count: 2 * (BInt.BZ_DIV_LIMIT + 1))), BInt(Limbs(repeating: UInt64.max, count: BInt.BZ_DIV_LIMIT + 1))) + doTest1(BInt(Limbs(repeating: UInt.max, count: 2 * (BInt.BZ_DIV_LIMIT + 1))), BInt(Limbs(repeating: UInt.max, count: BInt.BZ_DIV_LIMIT + 1))) } func test2() { diff --git a/Tests/BigIntTests/DivModTest.swift b/Tests/BigIntTests/DivModTest.swift index 6d34216..30acaee 100755 --- a/Tests/BigIntTests/DivModTest.swift +++ b/Tests/BigIntTests/DivModTest.swift @@ -86,7 +86,7 @@ class DivModTest: XCTestCase { doTest2(BInt(-7), BInt(4)) doTest2(BInt(7), BInt(-4)) doTest2(BInt(-7), BInt(-4)) - doTest2(BInt(Limbs(repeating: UInt64.max, count: 50)), BInt(Limbs(repeating: UInt64.max, count: 35))) + doTest2(BInt(Limbs(repeating: UInt.max, count: 50)), BInt(Limbs(repeating: UInt.max, count: 35))) } func test3() { @@ -108,7 +108,7 @@ class DivModTest: XCTestCase { // a BInt modulo an Int for _ in 0 ..< 100 { let x = BInt(bitWidth: 1000) - let m = x.magnitude[0] == 0 ? 1 : Int(x.magnitude[0] & 0x7fffffffffffffff) + let m = x.words[0] == 0 ? 1 : Int(x.words[0] & 0x7fffffffffffffff) XCTAssertEqual(x.mod(m), x.mod(BInt(m)).asInt()!) XCTAssertEqual(x.mod(-m), x.mod(-BInt(m)).asInt()!) } diff --git a/Tests/BigIntTests/FFTTest.swift b/Tests/BigIntTests/FFTTest.swift index a6a1e86..a3655ab 100644 --- a/Tests/BigIntTests/FFTTest.swift +++ b/Tests/BigIntTests/FFTTest.swift @@ -61,13 +61,13 @@ class FFTTest: XCTestCase { let a = BInt(bitWidth: (Limbs.FFT_THR + 1) * 64) let b = BInt(bitWidth: (Limbs.FFT_THR + 1) * 64) let p = a * b - let pTC = BInt(a.magnitude.toomCookTimes(b.magnitude)) + let pTC = BInt(a.words.toomCookTimes(b.words)) XCTAssertEqual(p, pTC) } for _ in 0 ..< 10 { let a = BInt(bitWidth: (Limbs.FFT_THR + 1) * 64) let p = a ** 2 - let pTC = BInt(a.magnitude.toomCookSquare()) + let pTC = BInt(a.words.toomCookSquare()) XCTAssertEqual(p, pTC) } } diff --git a/Tests/BigIntTests/KaratsubaTest.swift b/Tests/BigIntTests/KaratsubaTest.swift index 1bbfd67..f970c6e 100755 --- a/Tests/BigIntTests/KaratsubaTest.swift +++ b/Tests/BigIntTests/KaratsubaTest.swift @@ -61,13 +61,13 @@ class KaratsubaTest: XCTestCase { let a = BInt(bitWidth: (Limbs.KA_THR + 1) * 64) let b = BInt(bitWidth: (Limbs.KA_THR + 1) * 64) let p = a * b - let pTC = BInt(a.magnitude.toomCookTimes(b.magnitude)) + let pTC = BInt(a.words.toomCookTimes(b.words)) XCTAssertEqual(p, pTC) } for _ in 0 ..< 10 { let a = BInt(bitWidth: (Limbs.KA_THR + 1) * 64) let p = a ** 2 - let pTC = BInt(a.magnitude.toomCookSquare()) + let pTC = BInt(a.words.toomCookSquare()) XCTAssertEqual(p, pTC) } } diff --git a/Tests/BigIntTests/MultiplicationTest.swift b/Tests/BigIntTests/MultiplicationTest.swift index 46a0a73..d9adfef 100755 --- a/Tests/BigIntTests/MultiplicationTest.swift +++ b/Tests/BigIntTests/MultiplicationTest.swift @@ -28,7 +28,7 @@ class MultiplicationTest: XCTestCase { let (q1, r1) = c.quotientAndRemainder(dividingBy: b) XCTAssertEqual(r1, BInt(0)) XCTAssertEqual(q1, a) - var am = a.magnitude + var am = a.words am = am.times(am) XCTAssertEqual(a * a, BInt(am)) } diff --git a/Tests/BigIntTests/ToomCookTest.swift b/Tests/BigIntTests/ToomCookTest.swift index d85980c..2de9ae7 100755 --- a/Tests/BigIntTests/ToomCookTest.swift +++ b/Tests/BigIntTests/ToomCookTest.swift @@ -61,13 +61,13 @@ class ToomCookTest: XCTestCase { let a = BInt(bitWidth: (Limbs.TC_THR + 1) * 64) let b = BInt(bitWidth: (Limbs.TC_THR + 1) * 64) let p = a * b - let pK = BInt(a.magnitude.karatsubaTimes(b.magnitude)) + let pK = BInt(a.words.karatsubaTimes(b.words)) XCTAssertEqual(p, pK) } for _ in 0 ..< 10 { let a = BInt(bitWidth: (Limbs.TC_THR + 1) * 64) let p = a ** 2 - let pK = BInt(a.magnitude.karatsubaSquare()) + let pK = BInt(a.words.karatsubaSquare()) XCTAssertEqual(p, pK) } }