Skip to content

Commit

Permalink
Add sketch for BigIntModule.
Browse files Browse the repository at this point in the history
  • Loading branch information
xwu committed Jun 8, 2020
1 parent 593946d commit d91a39c
Show file tree
Hide file tree
Showing 10 changed files with 1,916 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,22 @@ import PackageDescription
let package = Package(
name: "swift-numerics",
products: [
.library(name: "BigIntModule", targets: ["BigIntModule"]),
.library(name: "ComplexModule", targets: ["ComplexModule"]),
.library(name: "Numerics", targets: ["Numerics"]),
.library(name: "RealModule", targets: ["RealModule"]),
],
dependencies: [
.package(url: "https://github.com/attaswift/BigInt.git", from: "3.0.0")
],
targets: [
.target(name: "BigIntModule", dependencies: []),
.target(name: "ComplexModule", dependencies: ["RealModule"]),
.target(name: "Numerics", dependencies: ["ComplexModule", "RealModule"]),
.target(name: "_NumericsShims", dependencies: []),
.target(name: "RealModule", dependencies: ["_NumericsShims"]),

.testTarget(name: "BigIntTests", dependencies: ["BigIntModule", "BigInt"]),
.testTarget(name: "ComplexTests", dependencies: ["ComplexModule", "_NumericsShims"]),
.testTarget(name: "RealTests", dependencies: ["RealModule"]),
]
Expand Down
76 changes: 76 additions & 0 deletions Sources/BigIntModule/BigInt.Words.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
extension BigInt {
/// The words of an arbitrarily large signed integer.
///
/// For a negative value, words are of the two’s complement representation.
@frozen
public struct Words {
/// The arbitrarily large signed integer.
@usableFromInline
internal var _value: BigInt

/// Creates a `BigInt.Words` from the given arbitrarily large signed
/// integer.
///
/// - Parameter value: The arbitrarily large signed integer.
@inlinable
public init(_ value: BigInt) {
_value = value
}
}
}

extension BigInt.Words: RandomAccessCollection {
@inlinable
public var count: Int {
if _value._combination == 0 { return 1 }
let temporary = _value._exponent + _value._significand.count
let lastIndex = _value._significand.count &- 1
let highWord = _value._significand[lastIndex]
guard Int(bitPattern: highWord) < 0 else {
return temporary
}
// If the leading bit is set, then--
//
// For a positive value:
// We need to add at least one leading zero bit (and therefore one
// additional word) for a signed representation.
if _value._combination > 0 { return temporary + 1 }
// For a negative value:
// The two's complement of a magnitude has the same bit width as that of
// the magnitude itself if and only if the magnitude is a power of two.
// Otherwise, we need one additional bit (and therefore one additional
// word) to fit the two's complement.
//
// (Note that `(x & (x &- 1)) == 0` is a method of determining if `x` is
// a power of two.)
return lastIndex == 0 && (highWord & (highWord &- 1)) == 0
? temporary
: temporary + 1
}

@inlinable
public var startIndex: Int { 0 }

@inlinable
public var endIndex: Int { count }

@inlinable
public func index(before i: Int) -> Int { i - 1 }

@inlinable
public func index(after i: Int) -> Int { i + 1 }

@inlinable
public subscript(position: Int) -> UInt {
precondition(position >= 0, "Index out of bounds")
guard position >= _value._exponent else { return 0 }
let idx = position &- _value._exponent
guard idx < _value._significand.count else {
return _value._combination < 0 ? UInt.max : 0
}
let word = _value._significand[idx]
return _value._combination < 0
? idx == 0 ? ~word &+ 1 : ~word
: word
}
}
Loading

0 comments on commit d91a39c

Please sign in to comment.