diff --git a/Sources/NBKCoreKit/Private/NBK.swift b/Sources/NBKCoreKit/Private/NBK.swift index 525332c4..5d60f7b6 100644 --- a/Sources/NBKCoreKit/Private/NBK.swift +++ b/Sources/NBKCoreKit/Private/NBK.swift @@ -65,15 +65,9 @@ public typealias Wide3 = (high: T, mid: T.Magnitude, low: T.Magnitude) where T: NBKFixedWidthInteger //=------------------------------------------------------------------------= - // MARK: Namespaces + // MARK: Namespaces x Binary Integer //=------------------------------------------------------------------------= - /// A namespace for `Numberick` development. - /// - /// - Warning: Do not use this namespace outside of `Numberick` development. - /// - public typealias SAM = NBK.SignAndMagnitude where Magnitude: NBKUnsignedInteger - /// A namespace for `Numberick` development. /// /// - Warning: Do not use this namespace outside of `Numberick` development. @@ -115,4 +109,28 @@ /// public typealias SUISS = NBK.StrictUnsignedInteger.SubSequence where Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger + + //=------------------------------------------------------------------------= + // MARK: Namespaces x Sign & Magnitude + //=------------------------------------------------------------------------= + + /// A namespace for `Numberick` development. + /// + /// - Warning: Do not use this namespace outside of `Numberick` development. + /// + public typealias ISM = NBK.IntegerSignMagnitude where Magnitude: NBKUnsignedInteger + + /// A namespace for `Numberick` development. + /// + /// - Warning: Do not use this namespace outside of `Numberick` development. + /// + public typealias SSM = NBK.StrictSignMagnitude where + Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger + + /// A namespace for `Numberick` development. + /// + /// - Warning: Do not use this namespace outside of `Numberick` development. + /// + public typealias SSMSS = NBK.StrictSignMagnitude.SubSequence where + Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger } diff --git a/Sources/NBKCoreKit/Private/NBKIntegerDescription+Decoding.swift b/Sources/NBKCoreKit/Private/NBKIntegerDescription+Decoding.swift index 2cc151df..7afa7bed 100644 --- a/Sources/NBKCoreKit/Private/NBKIntegerDescription+Decoding.swift +++ b/Sources/NBKCoreKit/Private/NBKIntegerDescription+Decoding.swift @@ -38,8 +38,6 @@ extension NBK.IntegerDescription { /// @frozen public struct Decoder { - public typealias Components = (sign: NBK.Sign, magnitude: Magnitude) - //=--------------------------------------------------------------------= // MARK: State //=--------------------------------------------------------------------= @@ -58,19 +56,19 @@ extension NBK.IntegerDescription { // MARK: Utilities //=--------------------------------------------------------------------= - @inlinable public func decode(_ description: some StringProtocol) -> Components? { - var description = String(description); return description.withUTF8(self.decode) - } - - @inlinable public func decode(_ description: StaticString) -> Components? { + @inlinable public func decode(_ description: StaticString) -> SM? { description.withUTF8Buffer(self.decode) } - @inlinable public func decode(_ description: NBK.UnsafeUTF8) -> Components? { - let components = NBK.IntegerDescription.makeSignBody(from: description) - let digits = NBK.UnsafeUTF8(rebasing: components.body) - guard let magnitude: Magnitude = NBK.IntegerDescription.decode(digits: digits, solution: self.solution) else { return nil } - return SM(sign: components.sign, magnitude: magnitude) + @inlinable public func decode(_ description: some StringProtocol) -> SM? { + var description = String(description); return description.withUTF8(self.decode) + } + + @inlinable public func decode(_ description: NBK.UnsafeUTF8) -> SM? { + let inputs = NBK.IntegerDescription.makeSignBody(from: description) + let digits = NBK.UnsafeUTF8(rebasing: inputs.body) + guard let magnitude: Magnitude = NBK.IntegerDescription.decode(digits: digits, solution: self.solution) else { return nil } + return SM(sign: inputs.sign, magnitude: magnitude) } } @@ -100,8 +98,6 @@ extension NBK.IntegerDescription { /// @frozen public struct DecoderDecodingRadix where Magnitude: NBKUnsignedInteger { - public typealias Components = (sign: NBK.Sign, radix: Int, magnitude: Magnitude) - //=--------------------------------------------------------------------= // MARK: Initializers //=--------------------------------------------------------------------= @@ -112,20 +108,20 @@ extension NBK.IntegerDescription { // MARK: Utilities //=--------------------------------------------------------------------= - @inlinable public func decode(_ description: some StringProtocol) -> Components? { - var description = String(description); return description.withUTF8(self.decode) + @inlinable public func decode(_ description: StaticString) -> SM? { + description.withUTF8Buffer(self.decode) } - @inlinable public func decode(_ description: StaticString) -> Components? { - description.withUTF8Buffer(self.decode) + @inlinable public func decode(_ description: some StringProtocol) -> SM? { + var description = String(description); return description.withUTF8(self.decode) } - @inlinable public func decode(_ description: NBK.UnsafeUTF8) -> Components? { - let components = NBK.IntegerDescription.makeSignRadixBody(from: description) - let solution = AnyRadixSolution(components.radix) - let digits = NBK.UnsafeUTF8(rebasing: components.body ) - guard let magnitude: Magnitude = NBK.IntegerDescription.decode(digits: digits, solution: solution) else { return nil } - return (sign: components.sign, radix: components.radix, magnitude: magnitude) + @inlinable public func decode(_ description: NBK.UnsafeUTF8) -> SM? { + let inputs = NBK.IntegerDescription.makeSignRadixBody(from: description) + let solution = NBK.IntegerDescription.AnyRadixSolution(inputs.radix) + let digits = NBK.UnsafeUTF8(rebasing: inputs.body) + guard let magnitude: Magnitude = NBK.IntegerDescription.decode(digits: digits, solution: solution) else { return nil } + return SM(sign: inputs.sign, magnitude: magnitude) } } } diff --git a/Sources/NBKCoreKit/Private/NBKIntegerDescription+Encoding.swift b/Sources/NBKCoreKit/Private/NBKIntegerDescription+Encoding.swift index 6f3fc829..b5d79b0b 100644 --- a/Sources/NBKCoreKit/Private/NBKIntegerDescription+Encoding.swift +++ b/Sources/NBKCoreKit/Private/NBKIntegerDescription+Encoding.swift @@ -55,35 +55,35 @@ extension NBK.IntegerDescription { //=--------------------------------------------------------------------= @inlinable public func encode(_ integer: some NBKBinaryInteger) -> String { - let isLessThanZero: Bool = integer.isLessThanZero + let isLessThanZero = integer.isLessThanZero return NBK.withUnsafeTemporaryAllocation(copying: integer.magnitude.words) { - self.encode(minus: isLessThanZero, magnitude: &$0) + NBK.IntegerDescription.encode( + magnitude: &$0, + solution: solution as AnyRadixSolution, + alphabet: alphabet as MaxRadixAlphabetEncoder, + minus: isLessThanZero as Bool) } } - @inlinable public func encode(sign: FloatingPointSign, magnitude: some RandomAccessCollection) -> String { - let isLessThanZero: Bool = (sign == FloatingPointSign.minus) && !magnitude.allSatisfy({ $0.isZero }) - return NBK.withUnsafeTemporaryAllocation(copying: magnitude) { - self.encode(minus: isLessThanZero, magnitude: &$0) + @inlinable public func encode(_ components: SM) -> String { + let isLessThanZero = NBK.ISM.isLessThanZero(components) + return NBK.withUnsafeTemporaryAllocation(copying: components.magnitude.words) { + NBK.IntegerDescription.encode( + magnitude: &$0, + solution: solution as AnyRadixSolution, + alphabet: alphabet as MaxRadixAlphabetEncoder, + minus: isLessThanZero as Bool) } } - //=--------------------------------------------------------------------= - // MARK: Utilities x Private - //=--------------------------------------------------------------------= - - /// ### Development - /// - /// - `@inlinable` is not required (nongeneric algorithm). - /// - @usableFromInline func encode(minus: Bool, magnitude: inout NBK.UnsafeMutableWords) -> String { - NBK.IntegerDescription.withUnsafeTemporarySignPrefix(minus: minus) { prefix in + @_disfavoredOverload @inlinable public func encode(_ components: SM>) -> String { + let isLessThanZero = NBK.SSMSS.isLessThanZero(components) + return NBK.withUnsafeTemporaryAllocation(copying: components.magnitude) { NBK.IntegerDescription.encode( - magnitude: &magnitude, + magnitude: &$0, solution: solution as AnyRadixSolution, alphabet: alphabet as MaxRadixAlphabetEncoder, - prefix: prefix as NBK.UnsafeUTF8, - suffix: NBK.UnsafeUTF8(start: nil, count: 0 as Int)) + minus: isLessThanZero as Bool) } } } @@ -99,6 +99,29 @@ extension NBK.IntegerDescription { // MARK: Utilities //=------------------------------------------------------------------------= + /// Encodes the magnitude, with or without a minus sign, using the given UTF-8 format. + /// + /// ### Development + /// + /// - `@inlinable` is not required (nongeneric algorithm). + /// + @usableFromInline static func encode( + magnitude: inout NBK.UnsafeMutableWords, solution: AnyRadixSolution, alphabet: MaxRadixAlphabetEncoder, + minus: Bool) -> String { + NBK.IntegerDescription.withUnsafeTemporarySignPrefix(minus: minus) { prefix in + NBK.IntegerDescription.encode( + magnitude: &magnitude, + solution: solution as AnyRadixSolution, + alphabet: alphabet as MaxRadixAlphabetEncoder, + prefix: prefix as NBK.UnsafeUTF8, + suffix: NBK.UnsafeUTF8(start: nil, count: 0 as Int)) + } + } + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + @inlinable static func encode( magnitude: inout NBK.UnsafeMutableWords, solution: AnyRadixSolution, alphabet: MaxRadixAlphabetEncoder, prefix: NBK.UnsafeUTF8, suffix: NBK.UnsafeUTF8) -> String { diff --git a/Sources/NBKCoreKit/Private/NBKSignAndMagnitude+Comparisons.swift b/Sources/NBKCoreKit/Private/NBKIntegerSignMagnitude+Comparisons.swift similarity index 53% rename from Sources/NBKCoreKit/Private/NBKSignAndMagnitude+Comparisons.swift rename to Sources/NBKCoreKit/Private/NBKIntegerSignMagnitude+Comparisons.swift index bc972164..5246ceb9 100644 --- a/Sources/NBKCoreKit/Private/NBKSignAndMagnitude+Comparisons.swift +++ b/Sources/NBKCoreKit/Private/NBKIntegerSignMagnitude+Comparisons.swift @@ -9,10 +9,36 @@ //=----------------------------------------------------------------------------= //*============================================================================* -// MARK: * NBK x Sign & Magnitude x Comparisons +// MARK: * NBK x Integer Sign Magnitude x Comparisons //*============================================================================* -extension NBK.SignAndMagnitude { +extension NBK.IntegerSignMagnitude { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns whether `components` is less than `zero`. + @inlinable public static func isLessThanZero(_ components: Components) -> Bool { + components.sign == Sign.minus && !components.magnitude.isZero + } + + /// Returns whether `components` is more than `zero`. + @inlinable public static func isMoreThanZero(_ components: Components) -> Bool { + components.sign == Sign.plus && !components.magnitude.isZero + } + + /// A three-way comparison of `components` against `zero`. + @inlinable public static func signum(_ components: Components) -> Int { + components.magnitude.isZero ? 0 : components.sign == Sign.plus ? 1 : -1 + } +} + +//=----------------------------------------------------------------------------= +// MARK: + Composition +//=----------------------------------------------------------------------------= + +extension NBK.IntegerSignMagnitude { //=------------------------------------------------------------------------= // MARK: Utilities @@ -26,7 +52,7 @@ extension NBK.SignAndMagnitude { /// - Returns: One of the following values: -1 (less), 0 (same), or 1 (more). /// @inlinable public static func compare( - _ lhs: Components, to rhs: NBK.SignAndMagnitude.Components, using compare: (Magnitude, Other) -> Int) -> Int { + _ lhs: Components, to rhs: NBK.IntegerSignMagnitude.Components, using compare: (Magnitude, Other) -> Int) -> Int { let absoluteValue: Int if lhs.sign == rhs.sign { diff --git a/Sources/NBKCoreKit/Private/NBKSignAndMagnitude.swift b/Sources/NBKCoreKit/Private/NBKIntegerSignMagnitude.swift similarity index 80% rename from Sources/NBKCoreKit/Private/NBKSignAndMagnitude.swift rename to Sources/NBKCoreKit/Private/NBKIntegerSignMagnitude.swift index 22ac4cc6..bb68648e 100644 --- a/Sources/NBKCoreKit/Private/NBKSignAndMagnitude.swift +++ b/Sources/NBKCoreKit/Private/NBKIntegerSignMagnitude.swift @@ -8,13 +8,13 @@ //=----------------------------------------------------------------------------= //*============================================================================* -// MARK: * NBK x Sign & Magnitude +// MARK: * NBK x Integer Sign Magnitude //*============================================================================* extension NBK { - /// A namespace for sign and magnitude algorithms. - @frozen public enum SignAndMagnitude where Magnitude: NBKUnsignedInteger { + /// A namespace for integer sign-magnitude algorithms. + @frozen public enum IntegerSignMagnitude where Magnitude: NBKUnsignedInteger { /// The sign and of this type. public typealias Sign = NBK.Sign diff --git a/Sources/NBKCoreKit/Private/NBKStrictSignMagnitude+Comparisons.swift b/Sources/NBKCoreKit/Private/NBKStrictSignMagnitude+Comparisons.swift new file mode 100644 index 00000000..046f93e0 --- /dev/null +++ b/Sources/NBKCoreKit/Private/NBKStrictSignMagnitude+Comparisons.swift @@ -0,0 +1,34 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Strict Sign Magnitude x Comparisons x Sub Sequence +//*============================================================================* + +extension NBK.StrictSignMagnitude.SubSequence { + + //=------------------------------------------------------------------------= + // MARK: Utilities + //=------------------------------------------------------------------------= + + /// Returns whether `components` is less than `zero`. + @inlinable public static func isLessThanZero(_ components: Components) -> Bool { + components.sign == Sign.minus && !components.magnitude.allSatisfy({ $0.isZero }) + } + + /// Returns whether `components` is more than `zero`. + @inlinable public static func isMoreThanZero(_ components: Components) -> Bool { + components.sign == Sign.plus && !components.magnitude.allSatisfy({ $0.isZero }) + } + + /// A three-way comparison of `components` against `zero`. + @inlinable public static func signum(_ components: Components) -> Int { + components.magnitude.allSatisfy({ $0.isZero }) ? 0 : components.sign == Sign.plus ? 1 : -1 + } +} diff --git a/Sources/NBKCoreKit/Private/NBKStrictSignMagnitude.swift b/Sources/NBKCoreKit/Private/NBKStrictSignMagnitude.swift new file mode 100644 index 00000000..2bf17e46 --- /dev/null +++ b/Sources/NBKCoreKit/Private/NBKStrictSignMagnitude.swift @@ -0,0 +1,53 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +//*============================================================================* +// MARK: * NBK x Strict Sign Magnitude +//*============================================================================* + +extension NBK { + + /// A namespace for strict sign-magnitude algorithms. + /// + /// The `base` must be `nonempty` at the start and end of each access. + /// + /// ```swift + /// static func algorithm(_ base: inout Base, input: Input) -> Output + /// ``` + /// + /// ### Development + /// + /// Remaking this as a view when Swift gets view types might be neat. + /// + @frozen public enum StrictSignMagnitude where Base: RandomAccessCollection, Base.Element: NBKCoreInteger & NBKUnsignedInteger { + + /// The sign and of this type. + public typealias Sign = NBK.Sign + + /// The sign and a magnitude of this type. + public typealias Components = SM + + //*====================================================================* + // MARK: * Sub Sequence + //*====================================================================* + + /// The sub sequence namespace of this type. + /// + /// The `base` may be `empty` at the start and end of each access. + /// + @frozen public enum SubSequence { + + /// The sign and of this type. + public typealias Sign = NBK.Sign + + /// The sign and a magnitude of this type. + public typealias Components = SM + } + } +} diff --git a/Tests/NBKCoreKitTests/Private/NBKIntegerDescription+Decoding.swift b/Tests/NBKCoreKitTests/Private/NBKIntegerDescription+Decoding.swift index f54a0188..4b57dcf8 100644 --- a/Tests/NBKCoreKitTests/Private/NBKIntegerDescription+Decoding.swift +++ b/Tests/NBKCoreKitTests/Private/NBKIntegerDescription+Decoding.swift @@ -33,15 +33,15 @@ final class NBKIntegerDescriptionTestsOnDecoding: XCTestCase { NBKAssertDecoding(.plus, UInt32 .max, 016, "+00ffffffff") NBKAssertDecoding( nil, UInt32?(nil), 016, "+0100000000") - NBKAssertDecodingByDecodingRadix( nil, nil, UInt32?(nil), "-004294967296") - NBKAssertDecodingByDecodingRadix(.minus, 010, UInt32 .max, "-004294967295") - NBKAssertDecodingByDecodingRadix(.plus, 010, UInt32 .max, "+004294967295") - NBKAssertDecodingByDecodingRadix( nil, nil, UInt32?(nil), "+004294967296") - - NBKAssertDecodingByDecodingRadix( nil, nil, UInt32?(nil), "-0x0100000000") - NBKAssertDecodingByDecodingRadix(.minus, 016, UInt32 .max, "-0x00ffffffff") - NBKAssertDecodingByDecodingRadix(.plus, 016, UInt32 .max, "+0x00ffffffff") - NBKAssertDecodingByDecodingRadix( nil, nil, UInt32?(nil), "+0x0100000000") + NBKAssertDecodingByDecodingRadix( nil, UInt32?(nil), "-004294967296") + NBKAssertDecodingByDecodingRadix(.minus, UInt32 .max, "-004294967295") + NBKAssertDecodingByDecodingRadix(.plus, UInt32 .max, "+004294967295") + NBKAssertDecodingByDecodingRadix( nil, UInt32?(nil), "+004294967296") + + NBKAssertDecodingByDecodingRadix( nil, UInt32?(nil), "-0x0100000000") + NBKAssertDecodingByDecodingRadix(.minus, UInt32 .max, "-0x00ffffffff") + NBKAssertDecodingByDecodingRadix(.plus, UInt32 .max, "+0x00ffffffff") + NBKAssertDecodingByDecodingRadix( nil, UInt32?(nil), "+0x0100000000") } func testDecodingUInt64() { @@ -55,21 +55,28 @@ final class NBKIntegerDescriptionTestsOnDecoding: XCTestCase { NBKAssertDecoding(.plus, UInt64 .max, 016, "+0000ffffffffffffffff") NBKAssertDecoding( nil, UInt64?(nil), 016, "+00010000000000000000") - NBKAssertDecodingByDecodingRadix( nil, nil, UInt64?(nil), "-0018446744073709551616") - NBKAssertDecodingByDecodingRadix(.minus, 010, UInt64 .max, "-0018446744073709551615") - NBKAssertDecodingByDecodingRadix(.plus, 010, UInt64 .max, "+0018446744073709551615") - NBKAssertDecodingByDecodingRadix( nil, nil, UInt64?(nil), "+0018446744073709551616") + NBKAssertDecodingByDecodingRadix( nil, UInt64?(nil), "-0018446744073709551616") + NBKAssertDecodingByDecodingRadix(.minus, UInt64 .max, "-0018446744073709551615") + NBKAssertDecodingByDecodingRadix(.plus, UInt64 .max, "+0018446744073709551615") + NBKAssertDecodingByDecodingRadix( nil, UInt64?(nil), "+0018446744073709551616") - NBKAssertDecodingByDecodingRadix( nil, nil, UInt64?(nil), "-0x00010000000000000000") - NBKAssertDecodingByDecodingRadix(.minus, 016, UInt64 .max, "-0x0000ffffffffffffffff") - NBKAssertDecodingByDecodingRadix(.plus, 016, UInt64 .max, "+0x0000ffffffffffffffff") - NBKAssertDecodingByDecodingRadix( nil, nil, UInt64?(nil), "+0x00010000000000000000") + NBKAssertDecodingByDecodingRadix( nil, UInt64?(nil), "-0x00010000000000000000") + NBKAssertDecodingByDecodingRadix(.minus, UInt64 .max, "-0x0000ffffffffffffffff") + NBKAssertDecodingByDecodingRadix(.plus, UInt64 .max, "+0x0000ffffffffffffffff") + NBKAssertDecodingByDecodingRadix( nil, UInt64?(nil), "+0x00010000000000000000") } //=------------------------------------------------------------------------= // MARK: Tests x Miscellaneous //=------------------------------------------------------------------------= + func testDecodingInvalidInputsReturnsNil() { + NBKAssertDecoding(nil, UInt64?(nil), 010, "!0000000000000000001") + NBKAssertDecoding(nil, UInt64?(nil), 010, "1000000000000000000!") + NBKAssertDecoding(nil, UInt64?(nil), 016, "!0000000000000000001") + NBKAssertDecoding(nil, UInt64?(nil), 016, "1000000000000000000!") + } + func testDecodingStringWithoutDigitsReturnsNil() { NBKAssertDecoding(nil, UInt32?(nil), 010, "+") NBKAssertDecoding(nil, UInt32?(nil), 016, "+") @@ -89,37 +96,31 @@ final class NBKIntegerDescriptionTestsOnDecodingAsCoreInteger: XCTestCase { //=------------------------------------------------------------------------= func testDecodingRadix10AsUInt32() { - typealias T = UInt32 + NBKAssertDecodingDigitsByTruncating(UInt32(1234567890), 010, "1234567890") + NBKAssertDecodingDigitsByTruncating(UInt32(4294967295), 010, "4294967295") - NBKAssertDecodingDigitsByTruncating(T(1234567890), 010, "1234567890") - NBKAssertDecodingDigitsByTruncating(T(4294967295), 010, "4294967295") - - NBKAssertDecodingDigitsByTruncating(T(0000000000), 010, "4294967296" ) // + 01 - NBKAssertDecodingDigitsByTruncating(T(4294967286), 010, "42949672950") // * 10 + NBKAssertDecodingDigitsByTruncating(UInt32(0000000000), 010, "4294967296" ) // + 01 + NBKAssertDecodingDigitsByTruncating(UInt32(4294967286), 010, "42949672950") // * 10 } func testDecodingRadix16AsUInt32() { - typealias T = UInt32 - - NBKAssertDecodingDigitsByTruncating(T(0x12345678), 016, "12345678") - NBKAssertDecodingDigitsByTruncating(T(0xffffffff), 016, "ffffffff") + NBKAssertDecodingDigitsByTruncating(UInt32(0x12345678), 016, "12345678") + NBKAssertDecodingDigitsByTruncating(UInt32(0xffffffff), 016, "ffffffff") - NBKAssertDecodingDigitsByTruncating(T(0x00000000), 016, "100000000") // + 01 - NBKAssertDecodingDigitsByTruncating(T(0xfffffff0), 016, "ffffffff0") // * 16 + NBKAssertDecodingDigitsByTruncating(UInt32(0x00000000), 016, "100000000") // + 01 + NBKAssertDecodingDigitsByTruncating(UInt32(0xfffffff0), 016, "ffffffff0") // * 16 } func testDecodingStringWithoutDigitsReturnsNilAsUInt32() { - typealias T = UInt32 - - NBKAssertDecodingDigitsByTruncating(T?.none, 010, "") - NBKAssertDecodingDigitsByTruncating(T?.none, 010, "+") - NBKAssertDecodingDigitsByTruncating(T?.none, 010, "-") - NBKAssertDecodingDigitsByTruncating(T?.none, 010, "~") - - NBKAssertDecodingDigitsByTruncating(T?.none, 016, "") - NBKAssertDecodingDigitsByTruncating(T?.none, 016, "+") - NBKAssertDecodingDigitsByTruncating(T?.none, 016, "-") - NBKAssertDecodingDigitsByTruncating(T?.none, 016, "~") + NBKAssertDecodingDigitsByTruncating(UInt32?.none, 010, "") + NBKAssertDecodingDigitsByTruncating(UInt32?.none, 010, "+") + NBKAssertDecodingDigitsByTruncating(UInt32?.none, 010, "-") + NBKAssertDecodingDigitsByTruncating(UInt32?.none, 010, "~") + + NBKAssertDecodingDigitsByTruncating(UInt32?.none, 016, "") + NBKAssertDecodingDigitsByTruncating(UInt32?.none, 016, "+") + NBKAssertDecodingDigitsByTruncating(UInt32?.none, 016, "-") + NBKAssertDecodingDigitsByTruncating(UInt32?.none, 016, "~") } //=------------------------------------------------------------------------= @@ -127,37 +128,31 @@ final class NBKIntegerDescriptionTestsOnDecodingAsCoreInteger: XCTestCase { //=------------------------------------------------------------------------= func testDecodingRadix10AsUInt64() { - typealias T = UInt64 - - NBKAssertDecodingDigitsByTruncating(T(12345678901234567890), 010, "12345678901234567890") - NBKAssertDecodingDigitsByTruncating(T(18446744073709551615), 010, "18446744073709551615") + NBKAssertDecodingDigitsByTruncating(UInt64(12345678901234567890), 010, "12345678901234567890") + NBKAssertDecodingDigitsByTruncating(UInt64(18446744073709551615), 010, "18446744073709551615") - NBKAssertDecodingDigitsByTruncating(T(00000000000000000000), 010, "18446744073709551616" ) // + 01 - NBKAssertDecodingDigitsByTruncating(T(18446744073709551606), 010, "184467440737095516150") // * 10 + NBKAssertDecodingDigitsByTruncating(UInt64(00000000000000000000), 010, "18446744073709551616" ) // + 01 + NBKAssertDecodingDigitsByTruncating(UInt64(18446744073709551606), 010, "184467440737095516150") // * 10 } func testDecodingRadix16AsUInt64() { - typealias T = UInt64 - - NBKAssertDecodingDigitsByTruncating(T(0x123456789abcdef0), 016, "123456789abcdef0") - NBKAssertDecodingDigitsByTruncating(T(0xffffffffffffffff), 016, "ffffffffffffffff") + NBKAssertDecodingDigitsByTruncating(UInt64(0x123456789abcdef0), 016, "123456789abcdef0") + NBKAssertDecodingDigitsByTruncating(UInt64(0xffffffffffffffff), 016, "ffffffffffffffff") - NBKAssertDecodingDigitsByTruncating(T(0x0000000000000000), 016, "10000000000000000") // + 01 - NBKAssertDecodingDigitsByTruncating(T(0xfffffffffffffff0), 016, "ffffffffffffffff0") // * 16 + NBKAssertDecodingDigitsByTruncating(UInt64(0x0000000000000000), 016, "10000000000000000") // + 01 + NBKAssertDecodingDigitsByTruncating(UInt64(0xfffffffffffffff0), 016, "ffffffffffffffff0") // * 16 } func testDecodingStringWithoutDigitsReturnsNilAsUInt64() { - typealias T = UInt64 - - NBKAssertDecodingDigitsByTruncating(T?.none, 010, "") - NBKAssertDecodingDigitsByTruncating(T?.none, 010, "+") - NBKAssertDecodingDigitsByTruncating(T?.none, 010, "-") - NBKAssertDecodingDigitsByTruncating(T?.none, 010, "~") - - NBKAssertDecodingDigitsByTruncating(T?.none, 016, "") - NBKAssertDecodingDigitsByTruncating(T?.none, 016, "+") - NBKAssertDecodingDigitsByTruncating(T?.none, 016, "-") - NBKAssertDecodingDigitsByTruncating(T?.none, 016, "~") + NBKAssertDecodingDigitsByTruncating(UInt64?.none, 010, "") + NBKAssertDecodingDigitsByTruncating(UInt64?.none, 010, "+") + NBKAssertDecodingDigitsByTruncating(UInt64?.none, 010, "-") + NBKAssertDecodingDigitsByTruncating(UInt64?.none, 010, "~") + + NBKAssertDecodingDigitsByTruncating(UInt64?.none, 016, "") + NBKAssertDecodingDigitsByTruncating(UInt64?.none, 016, "+") + NBKAssertDecodingDigitsByTruncating(UInt64?.none, 016, "-") + NBKAssertDecodingDigitsByTruncating(UInt64?.none, 016, "~") } } @@ -185,7 +180,7 @@ file: StaticString = #file, line: UInt = #line) { } private func NBKAssertDecodingByDecodingRadix( -_ sign: FloatingPointSign?, _ radix: Int?, _ magnitude: Magnitude?, _ description: StaticString, +_ sign: FloatingPointSign?, _ magnitude: Magnitude?, _ description: StaticString, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= let decoder = NBK.IntegerDescription.DecoderDecodingRadix() @@ -193,14 +188,12 @@ file: StaticString = #file, line: UInt = #line) { brr: do { let components = decoder.decode(description) XCTAssertEqual(sign, components?.sign, file: file, line: line) - XCTAssertEqual(radix, components?.radix, file: file, line: line) XCTAssertEqual(magnitude, components?.magnitude, file: file, line: line) } brr: do { let components = decoder.decode(description.description) XCTAssertEqual(sign, components?.sign, file: file, line: line) - XCTAssertEqual(radix, components?.radix, file: file, line: line) XCTAssertEqual(magnitude, components?.magnitude, file: file, line: line) } } diff --git a/Tests/NBKCoreKitTests/Private/NBKIntegerDescription+Encoding.swift b/Tests/NBKCoreKitTests/Private/NBKIntegerDescription+Encoding.swift index 4b59305c..cd64d09c 100644 --- a/Tests/NBKCoreKitTests/Private/NBKIntegerDescription+Encoding.swift +++ b/Tests/NBKCoreKitTests/Private/NBKIntegerDescription+Encoding.swift @@ -43,7 +43,13 @@ file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= let encoder = NBK.IntegerDescription.Encoder(radix: radix, uppercase: uppercase) //=------------------------------------------= - XCTAssertEqual(encoder.encode(sign: sign, magnitude: magnitude), result, file: file, line: line) + brr: do { + XCTAssertEqual(encoder.encode((sign: sign, magnitude: magnitude)), result, file: file, line: line) + } + + if magnitude.count <= 1 { + XCTAssertEqual(encoder.encode((sign: sign, magnitude: magnitude.first ?? 0)), result, file: file, line: line) + } } #endif diff --git a/Tests/NBKCoreKitTests/Private/NBKSignAndMagnitude+Comparisons.swift b/Tests/NBKCoreKitTests/Private/NBKIntegerSignMagnitude+Comparisons.swift similarity index 65% rename from Tests/NBKCoreKitTests/Private/NBKSignAndMagnitude+Comparisons.swift rename to Tests/NBKCoreKitTests/Private/NBKIntegerSignMagnitude+Comparisons.swift index 2bf5e50c..6ec3897b 100644 --- a/Tests/NBKCoreKitTests/Private/NBKSignAndMagnitude+Comparisons.swift +++ b/Tests/NBKCoreKitTests/Private/NBKIntegerSignMagnitude+Comparisons.swift @@ -17,10 +17,10 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Sign & Magnitude x Comparisons +// MARK: * NBK x Integer Sign Magnitude x Comparisons //*============================================================================* -final class NBKSignAndMagnitudeTestsOnComparisons: XCTestCase { +final class NBKIntegerSignMagnitudeTestsOnComparisons: XCTestCase { //=------------------------------------------------------------------------= // MARK: Tests @@ -47,17 +47,36 @@ final class NBKSignAndMagnitudeTestsOnComparisons: XCTestCase { NBKAssertCompareTo(SM(.minus, UInt(3)), SM(.plus, UInt(2)), -Int(1)) NBKAssertCompareTo(SM(.minus, UInt(3)), SM(.minus, UInt(2)), -Int(1)) } + + func testCompareToZero() { + NBKAssertCompareToZero(SM(.plus, UInt(0)), Int(0)) + NBKAssertCompareToZero(SM(.plus, UInt(1)), Int(1)) + NBKAssertCompareToZero(SM(.plus, UInt(2)), Int(1)) + + NBKAssertCompareToZero(SM(.minus, UInt(0)), Int(0)) + NBKAssertCompareToZero(SM(.minus, UInt(1)), -Int(1)) + NBKAssertCompareToZero(SM(.minus, UInt(2)), -Int(1)) + } } //*============================================================================* -// MARK: * NBK x Sign & Magnitude x Comparisons x Assertions +// MARK: * NBK x Integer Sign Magnitude x Comparisons x Assertions //*============================================================================* -private func NBKAssertCompareTo( -_ lhs: SM, _ rhs: SM, _ signum: Int, +private func NBKAssertCompareTo( +_ lhs: SM, _ rhs: SM, _ signum: Int, +file: StaticString = #file, line: UInt = #line) { + //=------------------------------------------= + XCTAssertEqual(NBK.ISM.compare(lhs, to: rhs, using:{ $0.compared(to: $1) }), signum, file: file, line: line) +} + +private func NBKAssertCompareToZero( +_ components: SM, _ signum: Int, file: StaticString = #file, line: UInt = #line) { //=------------------------------------------= - XCTAssertEqual(NBK.SAM.compare(lhs, to: rhs, using:{ $0.compared(to: $1) }), signum, file: file, line: line) + XCTAssert(NBK.ISM.signum/*----*/(components) == signum, file: file, line: line) + XCTAssert(NBK.ISM.isLessThanZero(components) == signum.isLessThanZero, file: file, line: line) + XCTAssert(NBK.ISM.isMoreThanZero(components) == signum.isMoreThanZero, file: file, line: line) } #endif diff --git a/Tests/NBKCoreKitTests/Private/NBKStrictSignMagnitude+Comparisons.swift b/Tests/NBKCoreKitTests/Private/NBKStrictSignMagnitude+Comparisons.swift new file mode 100644 index 00000000..27e3b492 --- /dev/null +++ b/Tests/NBKCoreKitTests/Private/NBKStrictSignMagnitude+Comparisons.swift @@ -0,0 +1,59 @@ +//=----------------------------------------------------------------------------= +// This source file is part of the Numberick open source project. +// +// Copyright (c) 2023 Oscar Byström Ericsson +// Licensed under Apache License, Version 2.0 +// +// See http://www.apache.org/licenses/LICENSE-2.0 for license information. +//=----------------------------------------------------------------------------= + +#if DEBUG + +import NBKCoreKit +import XCTest + +private typealias W = [UInt] +private typealias X = [UInt64] +private typealias Y = [UInt32] + +//*============================================================================* +// MARK: * NBK x Strict Sign Magnitude x Comparisons x Sub Sequence +//*============================================================================* + +final class NBKStrictSignMagnitudeTestsOnComparisonsAsSubSequence: XCTestCase { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + func testCompareToZero() { + NBKAssertSubSequenceCompareToZero(SM(.plus, [ ] as W), Int(0)) + NBKAssertSubSequenceCompareToZero(SM(.plus, [0, 0, 0, 0] as W), Int(0)) + NBKAssertSubSequenceCompareToZero(SM(.plus, [1, 0, 0, 0] as W), Int(1)) + NBKAssertSubSequenceCompareToZero(SM(.plus, [0, 1, 0, 0] as W), Int(1)) + NBKAssertSubSequenceCompareToZero(SM(.plus, [0, 0, 1, 0] as W), Int(1)) + NBKAssertSubSequenceCompareToZero(SM(.plus, [0, 0, 0, 1] as W), Int(1)) + + NBKAssertSubSequenceCompareToZero(SM(.minus, [ ] as W), Int(0)) + NBKAssertSubSequenceCompareToZero(SM(.minus, [0, 0, 0, 0] as W), Int(0)) + NBKAssertSubSequenceCompareToZero(SM(.minus, [1, 0, 0, 0] as W), -Int(1)) + NBKAssertSubSequenceCompareToZero(SM(.minus, [0, 1, 0, 0] as W), -Int(1)) + NBKAssertSubSequenceCompareToZero(SM(.minus, [0, 0, 1, 0] as W), -Int(1)) + NBKAssertSubSequenceCompareToZero(SM(.minus, [0, 0, 0, 1] as W), -Int(1)) + } +} + +//*============================================================================* +// MARK: * NBK x Strict Sign Magnitude x Comparisons x Assertions +//*============================================================================* + +private func NBKAssertSubSequenceCompareToZero( +_ components: SM, _ signum: Int, +file: StaticString = #file, line: UInt = #line) where Magnitude.Element: NBKCoreInteger & NBKUnsignedInteger { + //=------------------------------------------= + XCTAssert(NBK.SSMSS.signum/*----*/(components) == signum, file: file, line: line) + XCTAssert(NBK.SSMSS.isLessThanZero(components) == signum.isLessThanZero, file: file, line: line) + XCTAssert(NBK.SSMSS.isMoreThanZero(components) == signum.isMoreThanZero, file: file, line: line) +} + +#endif diff --git a/Tests/NBKCoreKitTests/Private/NBKStrictUnsignedInteger+Addition.swift b/Tests/NBKCoreKitTests/Private/NBKStrictUnsignedInteger+Addition.swift index 9b4502ce..9688c356 100644 --- a/Tests/NBKCoreKitTests/Private/NBKStrictUnsignedInteger+Addition.swift +++ b/Tests/NBKCoreKitTests/Private/NBKStrictUnsignedInteger+Addition.swift @@ -17,7 +17,7 @@ private typealias X = [UInt64] private typealias Y = [UInt32] //*============================================================================* -// MARK: * NBK x Strict Unsigned Integer x Addition +// MARK: * NBK x Strict Unsigned Integer x Addition x Sub Sequence //*============================================================================* final class NBKStrictUnsignedIntegerTestsOnAdditionAsSubSequence: XCTestCase {