diff --git a/Sources/CoreIop/BinaryInteger.swift b/Sources/CoreIop/BinaryInteger.swift index 207b151b..3f740cdb 100644 --- a/Sources/CoreIop/BinaryInteger.swift +++ b/Sources/CoreIop/BinaryInteger.swift @@ -13,14 +13,22 @@ import CoreKit // MARK: * Binary Integer //*============================================================================* -extension IX: CompactIntegerInteroperable { } -extension I8: CompactIntegerInteroperable { } -extension I16: CompactIntegerInteroperable { } -extension I32: CompactIntegerInteroperable { } -extension I64: CompactIntegerInteroperable { } +extension IX: CompactIntegerInteroperable { } +extension I8: CompactIntegerInteroperable { } +extension I16: CompactIntegerInteroperable { } +extension I32: CompactIntegerInteroperable { } +extension I64: CompactIntegerInteroperable { } -extension UX: NaturalIntegerInteroperable { } -extension U8: NaturalIntegerInteroperable { } -extension U16: NaturalIntegerInteroperable { } -extension U32: NaturalIntegerInteroperable { } -extension U64: NaturalIntegerInteroperable { } +@available(*, unavailable) +@available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) +extension I128: CompactIntegerInteroperable { } + +extension UX: NaturalIntegerInteroperable { } +extension U8: NaturalIntegerInteroperable { } +extension U16: NaturalIntegerInteroperable { } +extension U32: NaturalIntegerInteroperable { } +extension U64: NaturalIntegerInteroperable { } + +@available(*, unavailable) +@available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) +extension U128: NaturalIntegerInteroperable { } diff --git a/Sources/CoreKit/Models/CoreInt.swift b/Sources/CoreKit/Models/CoreInt.swift index 59eacdc5..99588e35 100644 --- a/Sources/CoreKit/Models/CoreInt.swift +++ b/Sources/CoreKit/Models/CoreInt.swift @@ -234,6 +234,57 @@ } } +//*============================================================================* +// MARK: * Core Int x I128 +//*============================================================================* + +/// A 128-bit signed binary integer. +/// +/// ### Development +/// +/// - Todo: Remove `typealias I128 = DoubleInt` in `DoubleIntKit`. +/// +@available(*, unavailable) +@available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) +@frozen public struct I128: CoreInteger, SignedInteger, CoreIntegerWhereIsNotByte, CoreIntegerWhereIsNotToken { + + public typealias Stdlib = Swift.Int128 + + public typealias BitPattern = Stdlib.BitPattern + + public typealias Element = Self + + public typealias Signitude = Self + + public typealias Magnitude = U128 + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline var base: Stdlib + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: Stdlib) { + self.base = source + } + + @inlinable public init(raw source: BitPattern) { + self.base = Stdlib(bitPattern: source) + } + + @inlinable public init(integerLiteral source: Stdlib) { + self.base = source + } + + @inlinable public consuming func stdlib() -> Stdlib { + self.base + } +} + //*============================================================================* // MARK: * Core Int x UX //*============================================================================* @@ -453,3 +504,54 @@ self.base } } + +//*============================================================================* +// MARK: * Core Int x U128 +//*============================================================================* + +/// A 128-bit unsigned binary integer. +/// +/// ### Development +/// +/// - Todo: Remove `typealias U128 = DoubleInt` in `DoubleIntKit`. +/// +@available(*, unavailable) +@available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) +@frozen public struct U128: CoreInteger, UnsignedInteger, CoreIntegerWhereIsNotByte, CoreIntegerWhereIsNotToken { + + public typealias Stdlib = Swift.UInt128 + + public typealias BitPattern = Stdlib.BitPattern + + public typealias Element = Self + + public typealias Signitude = I128 + + public typealias Magnitude = Self + + //=------------------------------------------------------------------------= + // MARK: State + //=------------------------------------------------------------------------= + + @usableFromInline var base: Stdlib + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(_ source: Stdlib) { + self.base = source + } + + @inlinable public init(raw source: BitPattern) { + self.base = source + } + + @inlinable public init(integerLiteral source: Stdlib) { + self.base = source + } + + @inlinable public consuming func stdlib() -> Stdlib { + self.base + } +} diff --git a/Sources/CoreKit/Stdlib/Swift+Int.swift b/Sources/CoreKit/Stdlib/Swift+Int.swift index 0b531498..b15cf13c 100644 --- a/Sources/CoreKit/Stdlib/Swift+Int.swift +++ b/Sources/CoreKit/Stdlib/Swift+Int.swift @@ -101,3 +101,24 @@ extension Int64: BitCastable { Magnitude(bitPattern: self) } } + +//*============================================================================* +// MARK: * Swift x Int128 +//*============================================================================* + +@available(*, unavailable) +@available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) +extension Int128: BitCastable { + + //=------------------------------------------------------------------------= + // MARK: Initializers + //=------------------------------------------------------------------------= + + @inlinable public init(raw source: consuming Magnitude) { + self.init(bitPattern: source) + } + + @inlinable public consuming func load(as type: Magnitude.Type) -> Magnitude { + Magnitude(bitPattern: self) + } +} diff --git a/Sources/CoreKit/Stdlib/Swift+UInt.swift b/Sources/CoreKit/Stdlib/Swift+UInt.swift index a016ea70..5af9b4d4 100644 --- a/Sources/CoreKit/Stdlib/Swift+UInt.swift +++ b/Sources/CoreKit/Stdlib/Swift+UInt.swift @@ -36,3 +36,11 @@ extension UInt32: BitCastable { public typealias BitPattern = Magnitude } //*============================================================================* extension UInt64: BitCastable { public typealias BitPattern = Magnitude } + +//*============================================================================* +// MARK: * Swift x UInt128 +//*============================================================================* + +@available(*, unavailable) +@available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) +extension UInt128: BitCastable { public typealias BitPattern = Magnitude } diff --git a/Sources/TestKit/Global+Types.swift b/Sources/TestKit/Global+Types.swift index 05e451c2..d90e80d9 100644 --- a/Sources/TestKit/Global+Types.swift +++ b/Sources/TestKit/Global+Types.swift @@ -26,13 +26,33 @@ public let typesAsCoreIntegerAsByte: [any CoreInteger.Type] = [ U8.self, ] -public let typesAsCoreIntegerAsSigned: [any CoreIntegerAsSigned.Type] = [ - IX.self, I8.self, I16.self, I32.self, I64.self, -] +public let typesAsCoreIntegerAsSigned: [any CoreIntegerAsSigned.Type] = reduce([]) { + $0.append(IX .self) + $0.append(I8 .self) + $0.append(I16.self) + $0.append(I32.self) + $0.append(I64.self) + + #if false + if #available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) { + $0.append(CoreKit.I128.self) + } + #endif +} -public let typesAsCoreIntegerAsUnsigned: [any CoreIntegerAsUnsigned.Type] = [ - UX.self, U8.self, U16.self, U32.self, U64.self, -] +public let typesAsCoreIntegerAsUnsigned: [any CoreIntegerAsUnsigned.Type] = reduce([]) { + $0.append(UX .self) + $0.append(U8 .self) + $0.append(U16.self) + $0.append(U32.self) + $0.append(U64.self) + + #if false + if #available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) { + $0.append(CoreKit.U128.self) + } + #endif +} //=----------------------------------------------------------------------------= // MARK: + Floats diff --git a/Tests/UltimathiopTests/Utilities/Globals.swift b/Tests/UltimathiopTests/Utilities/Globals.swift index d962b847..c0828e46 100644 --- a/Tests/UltimathiopTests/Utilities/Globals.swift +++ b/Tests/UltimathiopTests/Utilities/Globals.swift @@ -42,14 +42,40 @@ let typesAsLenientIntegerInteroperable: [any LenientIntegerInteroperable.Type] = InfiniInt.self, ] -let typesAsCompactIntegerInteroperable: [any CompactIntegerInteroperable.Type] = [ - IX.self, I8 .self, I16.self, I32.self, I64 .self, - DoubleInt.self, DoubleInt>.self, - DoubleInt.self, DoubleInt>.self, -] +let typesAsCompactIntegerInteroperable: [any CompactIntegerInteroperable.Type] = reduce([]) { + $0.append(IX .self) + $0.append(I8 .self) + $0.append(I16.self) + $0.append(I32.self) + $0.append(I64.self) + + #if false + if #available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) { + $0.append(CoreKit.I128.self) + } + #endif + + $0.append(DoubleInt.self) + $0.append(DoubleInt.self) + $0.append(DoubleInt>.self) + $0.append(DoubleInt>.self) +} -let typesAsNaturalIntegerInteroperable: [any NaturalIntegerInteroperable.Type] = [ - UX.self, U8 .self, U16.self, U32.self, U64 .self, - DoubleInt.self, DoubleInt>.self, - DoubleInt.self, DoubleInt>.self, -] +let typesAsNaturalIntegerInteroperable: [any NaturalIntegerInteroperable.Type] = reduce([]) { + $0.append(UX .self) + $0.append(U8 .self) + $0.append(U16.self) + $0.append(U32.self) + $0.append(U64.self) + + #if false + if #available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) { + $0.append(CoreKit.U128.self) + } + #endif + + $0.append(DoubleInt.self) + $0.append(DoubleInt.self) + $0.append(DoubleInt>.self) + $0.append(DoubleInt>.self) +} diff --git a/Tests/UltimathnumTests/BinaryInteger+Metadata.swift b/Tests/UltimathnumTests/BinaryInteger+Metadata.swift index c66e90ee..a56ddb5e 100644 --- a/Tests/UltimathnumTests/BinaryInteger+Metadata.swift +++ b/Tests/UltimathnumTests/BinaryInteger+Metadata.swift @@ -16,7 +16,7 @@ import TestKit // MARK: * Binary Integer x Metadata //*============================================================================* -@Suite(.tags(.documentation)) struct BinaryIntegerTestsOnMetadata { +@Suite struct BinaryIntegerTestsOnMetadata { //=------------------------------------------------------------------------= // MARK: Tests @@ -24,7 +24,7 @@ import TestKit @Test( "BinaryInteger/metadata: mode", - Tag.List.tags(.generic), + Tag.List.tags(.documentation, .generic), arguments: typesAsBinaryInteger ) func modes(type: any BinaryInteger.Type) throws { @@ -37,7 +37,7 @@ import TestKit @Test( "BinaryInteger/metadata: size", - Tag.List.tags(.generic), + Tag.List.tags(.documentation, .generic), arguments: typesAsBinaryInteger ) func sizes(type: any BinaryInteger.Type) throws { @@ -66,7 +66,7 @@ import TestKit @Test( "BinaryInteger/metadata: quadrants", - Tag.List.tags(.generic), + Tag.List.tags(.documentation, .generic), arguments: typesAsBinaryInteger ) func quadrants(type: any BinaryInteger.Type) throws { @@ -94,3 +94,39 @@ import TestKit } } } + +//*============================================================================* +// MARK: * Binary Integer x Metadata x Elements +//*============================================================================* + +@Suite struct BinaryIntegerTestsOnMetadataAboutElements { + + //=------------------------------------------------------------------------= + // MARK: Tests + //=------------------------------------------------------------------------= + + /// - Seealso: https://github.com/oscbyspro/Ultimathnum/pull/152 + @Test( + "BinaryInteger/metadata/elements: A.alignment vs B.alignment", + Tag.List.tags(.documentation, .generic), + arguments: CollectionOfOne(typesAsCoreInteger) + ) func heterogeneousAlignmentComparisons(list: [any CoreInteger.Type]) throws { + + for type in list { + for other in list { + try whereIs(type, versus: other) + } + } + + func whereIs(_ type: A.Type, versus other: B.Type) throws where A: CoreInteger, B: CoreInteger { + let a = MemoryLayout.self + let b = MemoryLayout.self + + switch A.size.compared(to: B.size) { + case Signum.negative: try #require(a.alignment <= b.alignment) + case Signum.zero: try #require(a.alignment == b.alignment) + case Signum.positive: try #require(a.alignment >= b.alignment) + } + } + } +} diff --git a/Tests/UltimathnumTests/Utilities/Globals.swift b/Tests/UltimathnumTests/Utilities/Globals.swift index 65dd9413..e32f09be 100644 --- a/Tests/UltimathnumTests/Utilities/Globals.swift +++ b/Tests/UltimathnumTests/Utilities/Globals.swift @@ -102,14 +102,41 @@ let typesAsSystemsInteger: [any SystemsInteger.Type] = { typesAsSystemsIntegerAsUnsigned }() -let typesAsSystemsIntegerAsSigned: [any SystemsIntegerAsSigned.Type] = [ - IX.self, I8 .self, I16.self, I32.self, I64 .self, - DoubleInt.self, DoubleInt>.self, - DoubleInt.self, DoubleInt>.self, -] - -let typesAsSystemsIntegerAsUnsigned: [any SystemsIntegerAsUnsigned.Type] = [ - UX.self, U8 .self, U16.self, U32.self, U64 .self, - DoubleInt.self, DoubleInt>.self, - DoubleInt.self, DoubleInt>.self, -] +let typesAsSystemsIntegerAsSigned: [any SystemsIntegerAsSigned.Type] = reduce([]) { + $0.append(IX .self) + $0.append(I8 .self) + $0.append(I16.self) + $0.append(I32.self) + $0.append(I64.self) + + #if false + if #available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) { + $0.append(CoreKit.I128.self) + } + #endif + + $0.append(DoubleInt.self) + $0.append(DoubleInt.self) + + $0.append(DoubleInt>.self) + $0.append(DoubleInt>.self) +} + +let typesAsSystemsIntegerAsUnsigned: [any SystemsIntegerAsUnsigned.Type] = reduce([]) { + $0.append(UX .self) + $0.append(U8 .self) + $0.append(U16.self) + $0.append(U32.self) + $0.append(U64.self) + + #if false + if #available(iOS 18.0, macOS 15.0, tvOS 18.0, visionOS 2.0, watchOS 11.0, *) { + $0.append(CoreKit.U128.self) + } + #endif + + $0.append(DoubleInt.self) + $0.append(DoubleInt.self) + $0.append(DoubleInt>.self) + $0.append(DoubleInt>.self) +}