Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BigInt #120

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//
// This source file is part of the Swift Numerics open source project
//
// Copyright (c) 2019 Apple Inc. and the Swift Numerics project authors
// Copyright (c) 2019-2020 Apple Inc. and the Swift Numerics project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
Expand All @@ -15,20 +15,24 @@ 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: "Numerics", dependencies: ["BigIntModule", "ComplexModule", "RealModule"]),
.target(name: "RealModule", dependencies: ["_NumericsShims"]),

.target(name: "_NumericsShims", dependencies: []),
.target(name: "_TestSupport", dependencies: ["Numerics"]),

.testTarget(name: "BigIntTests", dependencies: ["_TestSupport", "BigInt"]),
.testTarget(name: "ComplexTests", dependencies: ["_TestSupport"]),
.testTarget(name: "RealTests", dependencies: ["_TestSupport"]),
]
Expand Down
85 changes: 85 additions & 0 deletions Sources/BigIntModule/BigInt.Words.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//===--- BigInt.Words.swift -----------------------------------*- swift -*-===//
//
// This source file is part of the Swift Numerics open source project
//
// Copyright (c) 2020 Apple Inc. and the Swift Numerics project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//

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
internal init(_ value: BigInt) {
_value = value
}
}
}

extension BigInt.Words: RandomAccessCollection {
@inlinable
public var count: Int {
guard !_value._isZero else { 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