├── .codecov.yml
├── .github
└── workflows
│ ├── jazzy.yml
│ └── swift.yml
├── .gitignore
├── .jazzy.yml
├── .spi.yml
├── CHANGELOG.md
├── Demo.playground
├── Contents.o
├── Pages
│ ├── Digits of Pi.xcplaygroundpage
│ │ ├── Contents.swift
│ │ └── timeline.xctimeline
│ ├── Factorials.xcplaygroundpage
│ │ └── Contents.swift
│ ├── Generating Large Primes.xcplaygroundpage
│ │ └── Contents.swift
│ ├── Introduction.xcplaygroundpage
│ │ └── Contents.swift
│ └── The RSA algorithm.xcplaygroundpage
│ │ ├── Contents.swift
│ │ └── timeline.xctimeline
└── contents.xcplayground
├── LICENSE.md
├── Package.swift
├── README.md
├── Sources
├── Addition.swift
├── BigInt.swift
├── BigUInt.swift
├── Bitwise Ops.swift
├── Codable.swift
├── Comparable.swift
├── Data Conversion.swift
├── Division.swift
├── Exponentiation.swift
├── Floating Point Conversion.swift
├── GCD.swift
├── Hashable.swift
├── Integer Conversion.swift
├── Multiplication.swift
├── Prime Test.swift
├── Random.swift
├── Shifts.swift
├── Square Root.swift
├── Strideable.swift
├── String Conversion.swift
├── Subtraction.swift
└── Words and Bits.swift
├── Tests
└── BigIntTests
│ ├── BigIntTests.swift
│ ├── BigUIntTests.swift
│ ├── ProfileTests.swift
│ ├── Tools.swift
│ ├── Violet - Helpers
│ ├── BitWidthTestCases.swift
│ ├── GenerateValues.swift
│ ├── GlobalFunctions.swift
│ ├── StringTestCases.swift
│ └── WordsTestCases.swift
│ ├── Violet - Property testing
│ ├── ApplyA_ApplyB_Equals_ApplyAB.swift
│ └── ApplyA_UndoA.swift
│ ├── Violet
│ ├── BigIntCOWTests.swift
│ ├── BigIntHashTests.swift
│ ├── BigIntIntegerInitTests.swift
│ ├── BigIntPowerTests.swift
│ ├── BigIntPropertyTests.swift
│ └── BigIntStringInitTests.swift
│ └── WordTests.swift
├── docs
├── Extensions.html
├── Extensions
│ ├── BinaryFloatingPoint.html
│ └── String.html
├── Structs.html
├── Structs
│ ├── BigInt.html
│ ├── BigInt
│ │ ├── Sign.html
│ │ └── Words.html
│ ├── BigUInt.html
│ └── BigUInt
│ │ └── Words.html
├── badge.svg
├── css
│ ├── highlight.css
│ └── jazzy.css
├── docsets
│ ├── BigInt.docset
│ │ └── Contents
│ │ │ ├── Info.plist
│ │ │ └── Resources
│ │ │ ├── Documents
│ │ │ ├── Extensions.html
│ │ │ ├── Extensions
│ │ │ │ ├── BinaryFloatingPoint.html
│ │ │ │ └── String.html
│ │ │ ├── Structs.html
│ │ │ ├── Structs
│ │ │ │ ├── BigInt.html
│ │ │ │ ├── BigInt
│ │ │ │ │ ├── Sign.html
│ │ │ │ │ └── Words.html
│ │ │ │ ├── BigUInt.html
│ │ │ │ └── BigUInt
│ │ │ │ │ └── Words.html
│ │ │ ├── css
│ │ │ │ ├── highlight.css
│ │ │ │ └── jazzy.css
│ │ │ ├── img
│ │ │ │ ├── carat.png
│ │ │ │ ├── dash.png
│ │ │ │ ├── gh.png
│ │ │ │ └── spinner.gif
│ │ │ ├── index.html
│ │ │ ├── js
│ │ │ │ ├── jazzy.js
│ │ │ │ ├── jazzy.search.js
│ │ │ │ ├── jquery.min.js
│ │ │ │ ├── lunr.min.js
│ │ │ │ └── typeahead.jquery.js
│ │ │ └── search.json
│ │ │ └── docSet.dsidx
│ ├── BigInt.tgz
│ └── BigInt.xml
├── img
│ ├── carat.png
│ ├── dash.png
│ ├── gh.png
│ └── spinner.gif
├── index.html
├── js
│ ├── jazzy.js
│ ├── jazzy.search.js
│ ├── jquery.min.js
│ ├── lunr.min.js
│ └── typeahead.jquery.js
├── search.json
└── undocumented.json
└── images
├── BigInt.sketch
└── banner.png
/.codecov.yml:
--------------------------------------------------------------------------------
1 | ignore:
2 | - "/Tests/*"
3 | comment:
4 | layout: "header, diff"
5 | behavior: default
6 | require_changes: no
7 | coverage:
8 | status:
9 | project:
10 | default:
11 | target: auto
12 | threshold: null
13 | base: auto
14 | paths: "Sources/*"
15 |
--------------------------------------------------------------------------------
/.github/workflows/jazzy.yml:
--------------------------------------------------------------------------------
1 | name: Swift
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | macos:
10 | runs-on: macos-latest
11 | steps:
12 | - uses: actions/checkout@v2
13 | - name: Install jazzy
14 | run: gem install jazzy
15 | - name: Generate documentation
16 | run: |
17 | jazzy \
18 | --clean \
19 | --github-file-prefix "https://github.com/attaswift/$module/tree/${GITHUB_REF}" \
20 | --module-version "${{ github.event.release.tag_name }}" \
21 | --copyright "© $(date '+%Y') [Károly Lőrentey](https://twitter.com/lorentey). (Last updated: $(date '+%Y-%m-%d'))" \
22 | --config .jazzy.yml
23 | - name: Commit docs
24 | run: |
25 | git config --local user.email "bot@github.com"
26 | git config --local user.name "GitHub Actions"
27 | git add ./docs
28 | git commit -m "Update docs"
29 | git push origin HEAD:master
30 |
--------------------------------------------------------------------------------
/.github/workflows/swift.yml:
--------------------------------------------------------------------------------
1 | name: Swift
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 |
8 | jobs:
9 | macos:
10 | runs-on: macos-latest
11 | steps:
12 | - uses: actions/checkout@v4
13 | - name: Build
14 | run: swift build --build-tests
15 | - name: Run tests
16 | run: swift test --parallel
17 |
18 | linux:
19 | container:
20 | image: swift:${{ matrix.linux }}
21 | runs-on: ubuntu-latest
22 | strategy:
23 | matrix:
24 | linux: [focal, jammy, noble]
25 | steps:
26 | - uses: actions/checkout@v4
27 | - name: Build
28 | run: swift build --build-tests --enable-test-discovery
29 | - name: Test
30 | run: swift test --enable-test-discovery --parallel
31 |
32 | android:
33 | runs-on: macos-13
34 | steps:
35 | - name: Checkout
36 | uses: actions/checkout@v4
37 | - name: Setup Environment
38 | run: echo "ANDROID_NDK_HOME=${HOME}/Library/Android/sdk/ndk/27.2.12479018" >> $GITHUB_ENV
39 | - name: Test
40 | uses: skiptools/swift-android-action@v2
41 |
42 | # codecov:
43 | # runs-on: macos-latest
44 | # steps:
45 | # - uses: actions/checkout@v4
46 | # - name: Test and generate code coverage report
47 | # run: swift test --enable-code-coverage
48 | # - name: Upload coverage to Codecov
49 | # uses: codecov/codecov-action@v4
50 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /Carthage/Build
2 | /.build
3 | /Packages
4 | xcuserdata
5 | /Package.pins
6 | /Package.resolved
7 | .DS_Store
8 |
--------------------------------------------------------------------------------
/.jazzy.yml:
--------------------------------------------------------------------------------
1 | module: BigInt
2 | author: Károly Lőrentey
3 | theme: fullwidth
4 | output: ./docs
5 | author_url: "https://twitter.com/lorentey"
6 | github_url: "https://github.com/attaswift/BigInt"
7 | root_url: "https://attaswift.github.io/BigInt/reference/"
8 | xcodebuild_arguments: ["-workspace", "BigInt.xcworkspace", "-scheme", "BigInt-macOS"]
--------------------------------------------------------------------------------
/.spi.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 | external_links:
3 | documentation: "https://attaswift.github.io/BigInt/"
4 |
--------------------------------------------------------------------------------
/Demo.playground/Contents.o:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/Demo.playground/Contents.o
--------------------------------------------------------------------------------
/Demo.playground/Pages/Digits of Pi.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 | import BigInt
3 | //: ## Let's calculate the first thousand digits of π
4 | //:
5 | //: A fun application of BigInts is generating the digits of π.
6 | //: Let's implement [Jeremy Gibbon's spigot algorithm][spigot] as an infinite `GeneratorType`.
7 | //: This is a quite slow algorithm, but it makes up for it with its grooviness factor.
8 | //:
9 | //: [spigot]: http://www.cs.ox.ac.uk/jeremy.gibbons/publications/spigot.pdf
10 | func digitsOfPi() -> AnyIterator {
11 | var q: BigUInt = 1
12 | var r: BigUInt = 180
13 | var t: BigUInt = 60
14 | var i: UInt = 2 // Works until digit #826_566_842
15 | return AnyIterator {
16 | let u: UInt = 3 * (3 * i + 1) * (3 * i + 2)
17 | let y = (q.multiplied(byWord: 27 * i - 12) + 5 * r) / (5 * t)
18 | (q, r, t) = (
19 | 10 * q.multiplied(byWord: i * (2 * i - 1)),
20 | 10 * (q.multiplied(byWord: 5 * i - 2) + r - y * t).multiplied(byWord: u),
21 | t.multiplied(byWord: u))
22 | i += 1
23 | return Int(y.words[0])
24 | }
25 | }
26 | //: Well, that was surprisingly easy. Does it work? You bet:
27 | let digits = digitsOfPi().prefix(999).reduce("") { $0 + String($1) }
28 | //: [Next](@next)
29 |
--------------------------------------------------------------------------------
/Demo.playground/Pages/Digits of Pi.xcplaygroundpage/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
14 |
15 |
20 |
21 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Demo.playground/Pages/Factorials.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 | import Foundation
3 | import BigInt
4 | //: The canonical way to demo big integers is with the factorial function. Here is a fancy definition for it:
5 | func fact(_ n: Int) -> BigInt {
6 | return (1 ... n).map { BigInt($0) }.reduce(BigInt(1), *)
7 | }
8 |
9 | let f1 = fact(1)
10 | let f2 = fact(2)
11 | let f3 = fact(3)
12 | let f4 = fact(4)
13 | let f10 = fact(10)
14 | let f100 = fact(100)
15 | let f1000 = fact(1000)
16 | //: That last value seems quite large. Just how many decimal digits is it? Let's convert it to a `String` to find out.
17 | let decimal = String(f1000)
18 | let digitCount = decimal.count
19 | //: Wow. 2500 digits is peanuts for `BigInt`, but Xcode's playground tech isn't designed to perform well with much more loop iterations, so let's stay at this level for now.
20 | let ff2 = f1000 * f1000
21 | String(ff2).count
22 |
23 | let ff4 = ff2 * ff2
24 | String(ff4).count
25 |
26 | let ff8 = ff4 * ff4
27 | String(ff8).count
28 | //: That last operation multiplied two 10000-digit numbers; you may have noticed it took a couple of seconds to compute that value. Converting such huge values to decimal isn't particularly cheap, either.
29 | //:
30 | //: [Next](@next)
31 |
--------------------------------------------------------------------------------
/Demo.playground/Pages/Generating Large Primes.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 | import Foundation
3 | import BigInt
4 | //: # Generating Large Prime Numbers
5 | //:
6 | //: `BigUInt` has an `isPrime()` method that does a [Miller-Rabin Primality Test][mrpt]. Let's use
7 | //: this to create a function that finds the next prime number after any integer:
8 | //:
9 | //: [mrpt]: https://en.wikipedia.org/wiki/Miller%2dRabin_primality_test
10 | func findNextPrime(after integer: BigUInt) -> BigUInt {
11 | var candidate = integer
12 | repeat {
13 | candidate += 1
14 | } while !candidate.isPrime()
15 | return candidate
16 | }
17 |
18 | findNextPrime(after: 100)
19 | findNextPrime(after: 1000)
20 | findNextPrime(after: 10000)
21 | findNextPrime(after: 100000000000)
22 | findNextPrime(after: BigUInt(1) << 64)
23 | findNextPrime(after: BigUInt(1) << 128)
24 | findNextPrime(after: BigUInt(1) << 256)
25 | //: [Next](@next)
26 |
--------------------------------------------------------------------------------
/Demo.playground/Pages/Introduction.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: # Introduction
2 | //:
3 | //: The `BigInt` module provides a `BigInt` type that implements an [https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic](integer type of arbitrary width).
4 | //: These work much like `Int`s, but they don't have a preset maximum value---so they will never overflow.
5 | //: The only practical limit to their capacity is the amount of memory & address space that your computer has, and the
6 | //: amount of time you're willing to spend waiting for results---when their operands are truly huge,
7 | //: big integer operations can take a long time to execute.
8 | //: (`BigInt` represents integers in base 2^64, storing digits in an `Array`, so the theoretical
9 | //: maximum value it can store is (2^64)^`Int.max` - 1.)
10 | import Foundation
11 | import BigInt
12 | //: `BigInt` has several interesting initializers, but for now, the simplest way to create big integers is to use integer
13 | //: or string literals. The latter is useful when you want to create a number that's larger than `UIntMax.max`:
14 | let a: BigInt = 123
15 | let b: BigInt = 12345678
16 | let c: BigInt = 1234567890123456
17 | let d: BigInt = "12345678901234567890123456789012345678901234567890123456789012345678"
18 | //: To work with `BigInt`s, you use the same arithmetic operators as you do with everyday `Int` values:
19 | a + b
20 | b - a
21 | -b
22 | a * b
23 | a * b * c
24 | a * b * c * d
25 |
26 | d / c
27 | d % c
28 | d / (c * c)
29 | d / (c * c * c)
30 | d / (c * c * c * c)
31 | //: [Next](@next)
32 |
--------------------------------------------------------------------------------
/Demo.playground/Pages/The RSA algorithm.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 | import Foundation
3 | import BigInt
4 | //: # RSA cryptography
5 | //:
6 | //: Another useful thing to have is a function that finds a random n-bit prime number:
7 | func generatePrime(ofWidth width: Int) -> BigUInt {
8 | while true {
9 | var random = BigUInt.randomInteger(withExactWidth: width)
10 | random |= BigUInt(1)
11 | if random.isPrime() {
12 | return random
13 | }
14 | }
15 | }
16 | //: For instance, here are two random 1024-bit prime numbers:
17 | let p = generatePrime(ofWidth: 1024)
18 | let q = generatePrime(ofWidth: 1024)
19 | //: We know their product isn't prime, and `BigInt`'s primality test agrees:
20 | let n = p * q
21 | n.isPrime()
22 | //: But we'd be in serious trouble if we had to get `p` and `q` back by factoring `n`---and this observation is
23 | //: what makes RSA work.
24 | //:
25 | //: So let's derive a public/private RSA keypair out of these two primes:
26 | //:
27 | //: (Note though that in a real RSA cryptosystem, primes are chosen much more carefully.)
28 | let phi = (p - 1) * (q - 1)
29 | let e: BigUInt = 65537
30 | let d = e.inverse(phi)!
31 |
32 | d * e % phi
33 |
34 | typealias Key = (modulus: BigUInt, exponent: BigUInt)
35 |
36 | let publicKey: Key = (n, e)
37 | let privateKey: Key = (n, d)
38 | //: Given a key and a message, encryption is simply a modular exponentiation:
39 | //: (Again, this is an oversimplification. In the real RSA system, the message is first transformed by a
40 | //: [complex padding scheme][oaep].)
41 | //:
42 | //: [oaep]: https://en.wikipedia.org/wiki/Optimal_asymmetric_encryption_padding
43 | func encrypt(_ message: BigUInt, key: Key) -> BigUInt {
44 | return message.power(key.exponent, modulus: key.modulus)
45 | }
46 | //: Let's try encrypting some message with the public key.
47 | let secret: BigUInt = BigUInt("Arbitrary precision arithmetic is fun!".data(using: .utf8)!)
48 |
49 | let cyphertext = encrypt(secret, key: publicKey)
50 | //: Well that was easy. In theory, we can decrypt the cyphertext by simply encrypting it with the private key.
51 | //: But does it really work? Yep:
52 | let plaintext = encrypt(cyphertext, key: privateKey)
53 |
54 | let message = String(data: plaintext.serialize(), encoding: .utf8)
55 | //: Isn't that awesome?
56 | //:
57 | //: [Next](@next)
58 |
--------------------------------------------------------------------------------
/Demo.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) 2016-2017 Károly Lőrentey
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.9
2 | //
3 | // Package.swift
4 | // BigInt
5 | //
6 | // Created by Károly Lőrentey on 2016-01-12.
7 | // Copyright © 2016-2017 Károly Lőrentey.
8 | //
9 |
10 | import PackageDescription
11 |
12 | let package = Package(
13 | name: "BigInt",
14 | platforms: [
15 | .macOS(.v10_13),
16 | .iOS(.v12),
17 | .tvOS(.v12),
18 | .watchOS(.v4),
19 | .macCatalyst(.v13),
20 | .visionOS(.v1),
21 | ],
22 | products: [
23 | .library(name: "BigInt", targets: ["BigInt"])
24 | ],
25 | targets: [
26 | .target(name: "BigInt", path: "Sources"),
27 | .testTarget(name: "BigIntTests", dependencies: ["BigInt"], path: "Tests")
28 | ]
29 | )
30 |
--------------------------------------------------------------------------------
/Sources/Addition.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Addition.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt {
10 | //MARK: Addition
11 |
12 | /// Add `word` to this integer in place.
13 | /// `word` is shifted `shift` words to the left before being added.
14 | ///
15 | /// - Complexity: O(max(count, shift))
16 | internal mutating func addWord(_ word: Word, shiftedBy shift: Int = 0) {
17 | precondition(shift >= 0)
18 | var carry = word
19 | var i = shift
20 | while carry > 0 {
21 | let (d, c) = self[i].addingReportingOverflow(carry)
22 | self[i] = d
23 | carry = (c ? 1 : 0)
24 | i += 1
25 | }
26 | }
27 |
28 | /// Add the digit `d` to this integer and return the result.
29 | /// `d` is shifted `shift` words to the left before being added.
30 | ///
31 | /// - Complexity: O(max(count, shift))
32 | internal func addingWord(_ word: Word, shiftedBy shift: Int = 0) -> BigUInt {
33 | var r = self
34 | r.addWord(word, shiftedBy: shift)
35 | return r
36 | }
37 |
38 | /// Add `b` to this integer in place.
39 | /// `b` is shifted `shift` words to the left before being added.
40 | ///
41 | /// - Complexity: O(max(count, b.count + shift))
42 | internal mutating func add(_ b: BigUInt, shiftedBy shift: Int = 0) {
43 | precondition(shift >= 0)
44 | var carry = false
45 | var bi = 0
46 | let bc = b.count
47 | while bi < bc || carry {
48 | let ai = shift + bi
49 | let (d, c) = self[ai].addingReportingOverflow(b[bi])
50 | if carry {
51 | let (d2, c2) = d.addingReportingOverflow(1)
52 | self[ai] = d2
53 | carry = c || c2
54 | }
55 | else {
56 | self[ai] = d
57 | carry = c
58 | }
59 | bi += 1
60 | }
61 | }
62 |
63 | /// Add `b` to this integer and return the result.
64 | /// `b` is shifted `shift` words to the left before being added.
65 | ///
66 | /// - Complexity: O(max(count, b.count + shift))
67 | internal func adding(_ b: BigUInt, shiftedBy shift: Int = 0) -> BigUInt {
68 | var r = self
69 | r.add(b, shiftedBy: shift)
70 | return r
71 | }
72 |
73 | /// Increment this integer by one. If `shift` is non-zero, it selects
74 | /// the word that is to be incremented.
75 | ///
76 | /// - Complexity: O(count + shift)
77 | internal mutating func increment(shiftedBy shift: Int = 0) {
78 | self.addWord(1, shiftedBy: shift)
79 | }
80 |
81 | /// Add `a` and `b` together and return the result.
82 | ///
83 | /// - Complexity: O(max(a.count, b.count))
84 | public static func +(a: BigUInt, b: BigUInt) -> BigUInt {
85 | return a.adding(b)
86 | }
87 |
88 | /// Add `a` and `b` together, and store the sum in `a`.
89 | ///
90 | /// - Complexity: O(max(a.count, b.count))
91 | public static func +=(a: inout BigUInt, b: BigUInt) {
92 | a.add(b, shiftedBy: 0)
93 | }
94 | }
95 |
96 | extension BigInt {
97 | /// Add `a` to `b` and return the result.
98 | public static func +(a: BigInt, b: BigInt) -> BigInt {
99 | switch (a.sign, b.sign) {
100 | case (.plus, .plus):
101 | return BigInt(sign: .plus, magnitude: a.magnitude + b.magnitude)
102 | case (.minus, .minus):
103 | return BigInt(sign: .minus, magnitude: a.magnitude + b.magnitude)
104 | case (.plus, .minus):
105 | if a.magnitude >= b.magnitude {
106 | return BigInt(sign: .plus, magnitude: a.magnitude - b.magnitude)
107 | }
108 | else {
109 | return BigInt(sign: .minus, magnitude: b.magnitude - a.magnitude)
110 | }
111 | case (.minus, .plus):
112 | if b.magnitude >= a.magnitude {
113 | return BigInt(sign: .plus, magnitude: b.magnitude - a.magnitude)
114 | }
115 | else {
116 | return BigInt(sign: .minus, magnitude: a.magnitude - b.magnitude)
117 | }
118 | }
119 | }
120 |
121 | /// Add `b` to `a` in place.
122 | public static func +=(a: inout BigInt, b: BigInt) {
123 | a = a + b
124 | }
125 | }
126 |
127 |
--------------------------------------------------------------------------------
/Sources/BigInt.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BigInt.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2015-12-27.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | //MARK: BigInt
10 |
11 | /// An arbitary precision signed integer type, also known as a "big integer".
12 | ///
13 | /// Operations on big integers never overflow, but they might take a long time to execute.
14 | /// The amount of memory (and address space) available is the only constraint to the magnitude of these numbers.
15 | ///
16 | /// This particular big integer type uses base-2^64 digits to represent integers.
17 | ///
18 | /// `BigInt` is essentially a tiny wrapper that extends `BigUInt` with a sign bit and provides signed integer
19 | /// operations. Both the underlying absolute value and the negative/positive flag are available as read-write
20 | /// properties.
21 | ///
22 | /// Not all algorithms of `BigUInt` are available for `BigInt` values; for example, there is no square root or
23 | /// primality test for signed integers. When you need to call one of these, just extract the absolute value:
24 | ///
25 | /// ```Swift
26 | /// BigInt(255).magnitude.isPrime() // Returns false
27 | /// ```
28 | ///
29 | public struct BigInt: SignedInteger, Sendable {
30 | public enum Sign: Sendable {
31 | case plus
32 | case minus
33 | }
34 |
35 | public typealias Magnitude = BigUInt
36 |
37 | /// The type representing a digit in `BigInt`'s underlying number system.
38 | public typealias Word = BigUInt.Word
39 |
40 | public static var isSigned: Bool {
41 | return true
42 | }
43 |
44 | /// The absolute value of this integer.
45 | public var magnitude: BigUInt
46 |
47 | /// True iff the value of this integer is negative.
48 | public var sign: Sign
49 |
50 | /// Initializes a new big integer with the provided absolute number and sign flag.
51 | public init(sign: Sign, magnitude: BigUInt) {
52 | self.sign = (magnitude.isZero ? .plus : sign)
53 | self.magnitude = magnitude
54 | }
55 |
56 | /// Return true iff this integer is zero.
57 | ///
58 | /// - Complexity: O(1)
59 | public var isZero: Bool {
60 | return magnitude.isZero
61 | }
62 |
63 | /// Returns `-1` if this value is negative and `1` if it’s positive; otherwise, `0`.
64 | ///
65 | /// - Returns: The sign of this number, expressed as an integer of the same type.
66 | public func signum() -> BigInt {
67 | switch sign {
68 | case .plus:
69 | return isZero ? 0 : 1
70 | case .minus:
71 | return -1
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Sources/Bitwise Ops.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Bitwise Ops.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | //MARK: Bitwise Operations
10 |
11 | extension BigUInt {
12 | /// Return the ones' complement of `a`.
13 | ///
14 | /// - Complexity: O(a.count)
15 | public static prefix func ~(a: BigUInt) -> BigUInt {
16 | return BigUInt(words: a.words.map { ~$0 })
17 | }
18 |
19 | /// Calculate the bitwise OR of `a` and `b`, and store the result in `a`.
20 | ///
21 | /// - Complexity: O(max(a.count, b.count))
22 | public static func |= (a: inout BigUInt, b: BigUInt) {
23 | a.reserveCapacity(b.count)
24 | for i in 0 ..< b.count {
25 | a[i] |= b[i]
26 | }
27 | }
28 |
29 | /// Calculate the bitwise AND of `a` and `b` and return the result.
30 | ///
31 | /// - Complexity: O(max(a.count, b.count))
32 | public static func &= (a: inout BigUInt, b: BigUInt) {
33 | for i in 0 ..< Swift.max(a.count, b.count) {
34 | a[i] &= b[i]
35 | }
36 | }
37 |
38 | /// Calculate the bitwise XOR of `a` and `b` and return the result.
39 | ///
40 | /// - Complexity: O(max(a.count, b.count))
41 | public static func ^= (a: inout BigUInt, b: BigUInt) {
42 | a.reserveCapacity(b.count)
43 | for i in 0 ..< b.count {
44 | a[i] ^= b[i]
45 | }
46 | }
47 | }
48 |
49 | extension BigInt {
50 | public static prefix func ~(x: BigInt) -> BigInt {
51 | switch x.sign {
52 | case .plus:
53 | return BigInt(sign: .minus, magnitude: x.magnitude + 1)
54 | case .minus:
55 | return BigInt(sign: .plus, magnitude: x.magnitude - 1)
56 | }
57 | }
58 |
59 | public static func &(lhs: inout BigInt, rhs: BigInt) -> BigInt {
60 | let left = lhs.words
61 | let right = rhs.words
62 | // Note we aren't using left.count/right.count here; we account for the sign bit separately later.
63 | let count = Swift.max(lhs.magnitude.count, rhs.magnitude.count)
64 | var words: [UInt] = []
65 | words.reserveCapacity(count)
66 | for i in 0 ..< count {
67 | words.append(left[i] & right[i])
68 | }
69 | if lhs.sign == .minus && rhs.sign == .minus {
70 | words.twosComplement()
71 | return BigInt(sign: .minus, magnitude: BigUInt(words: words))
72 | }
73 | return BigInt(sign: .plus, magnitude: BigUInt(words: words))
74 | }
75 |
76 | public static func |(lhs: inout BigInt, rhs: BigInt) -> BigInt {
77 | let left = lhs.words
78 | let right = rhs.words
79 | // Note we aren't using left.count/right.count here; we account for the sign bit separately later.
80 | let count = Swift.max(lhs.magnitude.count, rhs.magnitude.count)
81 | var words: [UInt] = []
82 | words.reserveCapacity(count)
83 | for i in 0 ..< count {
84 | words.append(left[i] | right[i])
85 | }
86 | if lhs.sign == .minus || rhs.sign == .minus {
87 | words.twosComplement()
88 | return BigInt(sign: .minus, magnitude: BigUInt(words: words))
89 | }
90 | return BigInt(sign: .plus, magnitude: BigUInt(words: words))
91 | }
92 |
93 | public static func ^(lhs: inout BigInt, rhs: BigInt) -> BigInt {
94 | let left = lhs.words
95 | let right = rhs.words
96 | // Note we aren't using left.count/right.count here; we account for the sign bit separately later.
97 | let count = Swift.max(lhs.magnitude.count, rhs.magnitude.count)
98 | var words: [UInt] = []
99 | words.reserveCapacity(count)
100 | for i in 0 ..< count {
101 | words.append(left[i] ^ right[i])
102 | }
103 | if (lhs.sign == .minus) != (rhs.sign == .minus) {
104 | words.twosComplement()
105 | return BigInt(sign: .minus, magnitude: BigUInt(words: words))
106 | }
107 | return BigInt(sign: .plus, magnitude: BigUInt(words: words))
108 | }
109 |
110 | public static func &=(lhs: inout BigInt, rhs: BigInt) {
111 | lhs = lhs & rhs
112 | }
113 |
114 | public static func |=(lhs: inout BigInt, rhs: BigInt) {
115 | lhs = lhs | rhs
116 | }
117 |
118 | public static func ^=(lhs: inout BigInt, rhs: BigInt) {
119 | lhs = lhs ^ rhs
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/Sources/Codable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Codable.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2017-8-11.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 |
10 | // Little-endian to big-endian
11 | struct Units: RandomAccessCollection
12 | where Words.Element: FixedWidthInteger, Words.Index == Int {
13 | typealias Word = Words.Element
14 | let words: Words
15 | init(of type: Unit.Type, _ words: Words) {
16 | precondition(Word.bitWidth % Unit.bitWidth == 0 || Unit.bitWidth % Word.bitWidth == 0)
17 | self.words = words
18 | }
19 | var count: Int { return (words.count * Word.bitWidth + Unit.bitWidth - 1) / Unit.bitWidth }
20 | var startIndex: Int { return 0 }
21 | var endIndex: Int { return count }
22 | subscript(_ index: Int) -> Unit {
23 | let index = count - 1 - index
24 | if Unit.bitWidth == Word.bitWidth {
25 | return Unit(words[index])
26 | }
27 | else if Unit.bitWidth > Word.bitWidth {
28 | let c = Unit.bitWidth / Word.bitWidth
29 | var unit: Unit = 0
30 | var j = 0
31 | for i in (c * index) ..< Swift.min(c * (index + 1), words.endIndex) {
32 | unit |= Unit(words[i]) << j
33 | j += Word.bitWidth
34 | }
35 | return unit
36 | }
37 | // Unit.bitWidth < Word.bitWidth
38 | let c = Word.bitWidth / Unit.bitWidth
39 | let i = index / c
40 | let j = index % c
41 | return Unit(truncatingIfNeeded: words[i] >> (j * Unit.bitWidth))
42 | }
43 | }
44 |
45 | extension Array where Element: FixedWidthInteger {
46 | // Big-endian to little-endian
47 | init(count: Int?, generator: () throws -> Unit?) rethrows {
48 | typealias Word = Element
49 | precondition(Word.bitWidth % Unit.bitWidth == 0 || Unit.bitWidth % Word.bitWidth == 0)
50 | self = []
51 | if Unit.bitWidth == Word.bitWidth {
52 | if let count = count {
53 | self.reserveCapacity(count)
54 | }
55 | while let unit = try generator() {
56 | self.append(Word(unit))
57 | }
58 | }
59 | else if Unit.bitWidth > Word.bitWidth {
60 | let wordsPerUnit = Unit.bitWidth / Word.bitWidth
61 | if let count = count {
62 | self.reserveCapacity(count * wordsPerUnit)
63 | }
64 | while let unit = try generator() {
65 | var shift = Unit.bitWidth - Word.bitWidth
66 | while shift >= 0 {
67 | self.append(Word(truncatingIfNeeded: unit >> shift))
68 | shift -= Word.bitWidth
69 | }
70 | }
71 | }
72 | else {
73 | let unitsPerWord = Word.bitWidth / Unit.bitWidth
74 | if let count = count {
75 | self.reserveCapacity((count + unitsPerWord - 1) / unitsPerWord)
76 | }
77 | var word: Word = 0
78 | var c = 0
79 | while let unit = try generator() {
80 | word <<= Unit.bitWidth
81 | word |= Word(unit)
82 | c += Unit.bitWidth
83 | if c == Word.bitWidth {
84 | self.append(word)
85 | word = 0
86 | c = 0
87 | }
88 | }
89 | if c > 0 {
90 | self.append(word << c)
91 | var shifted: Word = 0
92 | for i in self.indices {
93 | let word = self[i]
94 | self[i] = shifted | (word >> c)
95 | shifted = word << (Word.bitWidth - c)
96 | }
97 | }
98 | }
99 | self.reverse()
100 | }
101 | }
102 |
103 | extension BigInt: Codable {
104 | public init(from decoder: Decoder) throws {
105 | if let container = try? decoder.singleValueContainer(), let stringValue = try? container.decode(String.self) {
106 | if stringValue.hasPrefix("0x") || stringValue.hasPrefix("0X") {
107 | guard let bigUInt = BigUInt(stringValue.dropFirst(2), radix: 16) else {
108 | throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid hexadecimal BigInt string")
109 | }
110 | self.init(sign: .plus, magnitude: bigUInt)
111 | } else {
112 | guard let bigInt = BigInt(stringValue) else {
113 | throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid decimal BigInt string")
114 | }
115 | self = bigInt
116 | }
117 | } else {
118 | var container = try decoder.unkeyedContainer()
119 |
120 | // Decode sign
121 | let sign: BigInt.Sign
122 | switch try container.decode(String.self) {
123 | case "+":
124 | sign = .plus
125 | case "-":
126 | sign = .minus
127 | default:
128 | throw DecodingError.dataCorrupted(.init(codingPath: container.codingPath,
129 | debugDescription: "Invalid big integer sign"))
130 | }
131 |
132 | // Decode magnitude
133 | let words = try [UInt](count: container.count?.advanced(by: -1)) { () -> UInt64? in
134 | guard !container.isAtEnd else { return nil }
135 | return try container.decode(UInt64.self)
136 | }
137 | let magnitude = BigUInt(words: words)
138 |
139 | self.init(sign: sign, magnitude: magnitude)
140 | }
141 | }
142 |
143 | public func encode(to encoder: Encoder) throws {
144 | var container = encoder.unkeyedContainer()
145 | try container.encode(sign == .plus ? "+" : "-")
146 | let units = Units(of: UInt64.self, self.magnitude.words)
147 | if units.isEmpty {
148 | try container.encode(0 as UInt64)
149 | }
150 | else {
151 | try container.encode(contentsOf: units)
152 | }
153 | }
154 | }
155 |
156 | extension BigUInt: Codable {
157 | public init(from decoder: Decoder) throws {
158 | let value = try BigInt(from: decoder)
159 | guard value.sign == .plus else {
160 | throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath,
161 | debugDescription: "BigUInt cannot hold a negative value"))
162 | }
163 | self = value.magnitude
164 | }
165 |
166 | public func encode(to encoder: Encoder) throws {
167 | try BigInt(sign: .plus, magnitude: self).encode(to: encoder)
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/Sources/Comparable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Comparable.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | #if canImport(Foundation)
10 | import Foundation
11 | #endif
12 |
13 | extension BigUInt: Comparable {
14 | #if !canImport(Foundation)
15 | public enum ComparisonResult: Sendable, Comparable, Hashable {
16 | case orderedDescending
17 | case orderedSame
18 | case orderedAscending
19 | }
20 | #endif
21 |
22 | //MARK: Comparison
23 |
24 | /// Compare `a` to `b` and return an `NSComparisonResult` indicating their order.
25 | ///
26 | /// - Complexity: O(count)
27 | public static func compare(_ a: BigUInt, _ b: BigUInt) -> ComparisonResult {
28 | if a.count != b.count { return a.count > b.count ? .orderedDescending : .orderedAscending }
29 | for i in (0 ..< a.count).reversed() {
30 | let ad = a[i]
31 | let bd = b[i]
32 | if ad != bd { return ad > bd ? .orderedDescending : .orderedAscending }
33 | }
34 | return .orderedSame
35 | }
36 |
37 | /// Return true iff `a` is equal to `b`.
38 | ///
39 | /// - Complexity: O(count)
40 | public static func ==(a: BigUInt, b: BigUInt) -> Bool {
41 | return BigUInt.compare(a, b) == .orderedSame
42 | }
43 |
44 | /// Return true iff `a` is less than `b`.
45 | ///
46 | /// - Complexity: O(count)
47 | public static func <(a: BigUInt, b: BigUInt) -> Bool {
48 | return BigUInt.compare(a, b) == .orderedAscending
49 | }
50 | }
51 |
52 | extension BigInt: Comparable {
53 | /// Return true iff `a` is equal to `b`.
54 | public static func ==(a: BigInt, b: BigInt) -> Bool {
55 | return a.sign == b.sign && a.magnitude == b.magnitude
56 | }
57 |
58 | /// Return true iff `a` is less than `b`.
59 | public static func <(a: BigInt, b: BigInt) -> Bool {
60 | switch (a.sign, b.sign) {
61 | case (.plus, .plus):
62 | return a.magnitude < b.magnitude
63 | case (.plus, .minus):
64 | return false
65 | case (.minus, .plus):
66 | return true
67 | case (.minus, .minus):
68 | return a.magnitude > b.magnitude
69 | }
70 | }
71 | }
72 |
73 |
74 |
--------------------------------------------------------------------------------
/Sources/Data Conversion.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Data Conversion.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-04.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | #if canImport(Foundation)
10 | import Foundation
11 | #endif
12 |
13 | extension BigUInt {
14 | //MARK: NSData Conversion
15 |
16 | /// Initialize a BigInt from bytes accessed from an UnsafeRawBufferPointer
17 | public init(_ buffer: UnsafeRawBufferPointer) {
18 | // This assumes Word is binary.
19 | precondition(Word.bitWidth % 8 == 0)
20 |
21 | self.init()
22 |
23 | let length = buffer.count
24 | guard length > 0 else { return }
25 | let bytesPerDigit = Word.bitWidth / 8
26 | var index = length / bytesPerDigit
27 | var c = bytesPerDigit - length % bytesPerDigit
28 | if c == bytesPerDigit {
29 | c = 0
30 | index -= 1
31 | }
32 |
33 | var word: Word = 0
34 | for byte in buffer {
35 | word <<= 8
36 | word += Word(byte)
37 | c += 1
38 | if c == bytesPerDigit {
39 | self[index] = word
40 | index -= 1
41 | c = 0
42 | word = 0
43 | }
44 | }
45 | assert(c == 0 && word == 0 && index == -1)
46 | }
47 |
48 | /// Return a `UnsafeRawBufferPointer` buffer that contains the base-256 representation of this integer, in network (big-endian) byte order.
49 | public func serializeToBuffer() -> UnsafeRawBufferPointer {
50 | // This assumes Digit is binary.
51 | precondition(Word.bitWidth % 8 == 0)
52 |
53 | let byteCount = (self.bitWidth + 7) / 8
54 |
55 | let buffer = UnsafeMutableBufferPointer.allocate(capacity: byteCount)
56 |
57 | guard byteCount > 0 else { return UnsafeRawBufferPointer(start: buffer.baseAddress, count: 0) }
58 |
59 | var i = byteCount - 1
60 | for var word in self.words {
61 | for _ in 0 ..< Word.bitWidth / 8 {
62 | buffer[i] = UInt8(word & 0xFF)
63 | word >>= 8
64 | if i == 0 {
65 | assert(word == 0)
66 | break
67 | }
68 | i -= 1
69 | }
70 | }
71 | let zeroOut = UnsafeMutableBufferPointer(start: buffer.baseAddress, count: i)
72 | zeroOut.initialize(repeating: 0)
73 | return UnsafeRawBufferPointer(start: buffer.baseAddress, count: byteCount)
74 | }
75 |
76 | #if canImport(Foundation)
77 | /// Initializes an integer from the bits stored inside a piece of `Data`.
78 | /// The data is assumed to be in network (big-endian) byte order.
79 | public init(_ data: Data) {
80 | self = data.withUnsafeBytes({ buffer in
81 | BigUInt(buffer)
82 | })
83 | }
84 |
85 | /// Return a `Data` value that contains the base-256 representation of this integer, in network (big-endian) byte order.
86 | public func serialize() -> Data {
87 | let buffer = serializeToBuffer()
88 | defer { buffer.deallocate() }
89 | guard
90 | let pointer = buffer.baseAddress.map(UnsafeMutableRawPointer.init(mutating:))
91 | else { return Data() }
92 |
93 | return Data(bytes: pointer, count: buffer.count)
94 | }
95 | #endif
96 | }
97 |
98 | extension BigInt {
99 |
100 | /// Initialize a BigInt from bytes accessed from an UnsafeRawBufferPointer,
101 | /// where the first byte indicates sign (0 for positive, 1 for negative)
102 | public init(_ buffer: UnsafeRawBufferPointer) {
103 | // This assumes Word is binary.
104 | precondition(Word.bitWidth % 8 == 0)
105 |
106 | self.init()
107 |
108 | let length = buffer.count
109 |
110 | // Serialized data for a BigInt should contain at least 2 bytes: one representing
111 | // the sign, and another for the non-zero magnitude. Zero is represented by an
112 | // empty Data struct, and negative zero is not supported.
113 | guard length > 1, let firstByte = buffer.first else { return }
114 |
115 | // The first byte gives the sign
116 | // This byte is compared to a bitmask to allow additional functionality to be added
117 | // to this byte in the future.
118 | self.sign = firstByte & 0b1 == 0 ? .plus : .minus
119 |
120 | self.magnitude = BigUInt(UnsafeRawBufferPointer(rebasing: buffer.dropFirst(1)))
121 | }
122 |
123 | /// Return a `Data` value that contains the base-256 representation of this integer, in network (big-endian) byte order and a prepended byte to indicate the sign (0 for positive, 1 for negative)
124 | public func serializeToBuffer() -> UnsafeRawBufferPointer {
125 | // Create a data object for the magnitude portion of the BigInt
126 | let magnitudeBuffer = self.magnitude.serializeToBuffer()
127 |
128 | // Similar to BigUInt, a value of 0 should return an empty buffer
129 | guard magnitudeBuffer.count > 0 else { return magnitudeBuffer }
130 |
131 | // Create a new buffer for the signed BigInt value
132 | let newBuffer = UnsafeMutableRawBufferPointer.allocate(byteCount: magnitudeBuffer.count + 1, alignment: 8)
133 | let magnitudeSection = UnsafeMutableRawBufferPointer(rebasing: newBuffer[1...])
134 | magnitudeSection.copyBytes(from: magnitudeBuffer)
135 | magnitudeBuffer.deallocate()
136 |
137 | // The first byte should be 0 for a positive value, or 1 for a negative value
138 | // i.e., the sign bit is the LSB
139 | newBuffer[0] = self.sign == .plus ? 0 : 1
140 |
141 | return UnsafeRawBufferPointer(start: newBuffer.baseAddress, count: newBuffer.count)
142 | }
143 |
144 | #if canImport(Foundation)
145 | /// Initializes an integer from the bits stored inside a piece of `Data`.
146 | /// The data is assumed to be in network (big-endian) byte order with a first
147 | /// byte to represent the sign (0 for positive, 1 for negative)
148 | public init(_ data: Data) {
149 | self = data.withUnsafeBytes({ buffer in
150 | BigInt(buffer)
151 | })
152 | }
153 |
154 | /// Return a `Data` value that contains the base-256 representation of this integer, in network (big-endian) byte order and a prepended byte to indicate the sign (0 for positive, 1 for negative)
155 | public func serialize() -> Data {
156 | let buffer = serializeToBuffer()
157 | defer { buffer.deallocate() }
158 | guard
159 | let pointer = buffer.baseAddress.map(UnsafeMutableRawPointer.init(mutating:))
160 | else { return Data() }
161 |
162 | return Data(bytes: pointer, count: buffer.count)
163 | }
164 | #endif
165 | }
166 |
--------------------------------------------------------------------------------
/Sources/Exponentiation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Exponentiation.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt {
10 | //MARK: Exponentiation
11 |
12 | /// Returns this integer raised to the power `exponent`.
13 | ///
14 | /// This function calculates the result by [successively squaring the base while halving the exponent][expsqr].
15 | ///
16 | /// [expsqr]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring
17 | ///
18 | /// - Note: This function can be unreasonably expensive for large exponents, which is why `exponent` is
19 | /// a simple integer value. If you want to calculate big exponents, you'll probably need to use
20 | /// the modulo arithmetic variant.
21 | /// - Returns: 1 if `exponent == 0`, otherwise `self` raised to `exponent`. (This implies that `0.power(0) == 1`.)
22 | /// - SeeAlso: `BigUInt.power(_:, modulus:)`
23 | /// - Complexity: O((exponent * self.count)^log2(3)) or somesuch. The result may require a large amount of memory, too.
24 | public func power(_ exponent: Int) -> BigUInt {
25 | if exponent == 0 { return 1 }
26 | if exponent == 1 { return self }
27 | if exponent < 0 {
28 | precondition(!self.isZero)
29 | return self == 1 ? 1 : 0
30 | }
31 | if self <= 1 { return self }
32 | var result = BigUInt(1)
33 | var b = self
34 | var e = exponent
35 | while e > 0 {
36 | if e & 1 == 1 {
37 | result *= b
38 | }
39 | e >>= 1
40 | b *= b
41 | }
42 | return result
43 | }
44 |
45 | /// Returns the remainder of this integer raised to the power `exponent` in modulo arithmetic under `modulus`.
46 | ///
47 | /// Uses the [right-to-left binary method][rtlb].
48 | ///
49 | /// [rtlb]: https://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method
50 | ///
51 | /// - Complexity: O(exponent.count * modulus.count^log2(3)) or somesuch
52 | public func power(_ exponent: BigUInt, modulus: BigUInt) -> BigUInt {
53 | precondition(!modulus.isZero)
54 | if modulus == (1 as BigUInt) { return 0 }
55 | let shift = modulus.leadingZeroBitCount
56 | let normalizedModulus = modulus << shift
57 | var result = BigUInt(1)
58 | var b = self
59 | b.formRemainder(dividingBy: normalizedModulus, normalizedBy: shift)
60 | for var e in exponent.words {
61 | for _ in 0 ..< Word.bitWidth {
62 | if e & 1 == 1 {
63 | result *= b
64 | result.formRemainder(dividingBy: normalizedModulus, normalizedBy: shift)
65 | }
66 | e >>= 1
67 | b *= b
68 | b.formRemainder(dividingBy: normalizedModulus, normalizedBy: shift)
69 | }
70 | }
71 | return result
72 | }
73 | }
74 |
75 | extension BigInt {
76 | /// Returns this integer raised to the power `exponent`.
77 | ///
78 | /// This function calculates the result by [successively squaring the base while halving the exponent][expsqr].
79 | ///
80 | /// [expsqr]: https://en.wikipedia.org/wiki/Exponentiation_by_squaring
81 | ///
82 | /// - Note: This function can be unreasonably expensive for large exponents, which is why `exponent` is
83 | /// a simple integer value. If you want to calculate big exponents, you'll probably need to use
84 | /// the modulo arithmetic variant.
85 | /// - Returns: 1 if `exponent == 0`, otherwise `self` raised to `exponent`. (This implies that `0.power(0) == 1`.)
86 | /// - SeeAlso: `BigUInt.power(_:, modulus:)`
87 | /// - Complexity: O((exponent * self.count)^log2(3)) or somesuch. The result may require a large amount of memory, too.
88 | public func power(_ exponent: Int) -> BigInt {
89 | return BigInt(sign: self.sign == .minus && exponent & 1 != 0 ? .minus : .plus,
90 | magnitude: self.magnitude.power(exponent))
91 | }
92 |
93 | /// Returns the remainder of this integer raised to the power `exponent` in modulo arithmetic under `modulus`.
94 | ///
95 | /// Uses the [right-to-left binary method][rtlb].
96 | ///
97 | /// [rtlb]: https://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method
98 | ///
99 | /// - Complexity: O(exponent.count * modulus.count^log2(3)) or somesuch
100 | public func power(_ exponent: BigInt, modulus: BigInt) -> BigInt {
101 | precondition(!modulus.isZero)
102 | if modulus.magnitude == 1 { return 0 }
103 | if exponent.isZero { return 1 }
104 | if exponent == 1 { return self.modulus(modulus) }
105 | if exponent < 0 {
106 | precondition(!self.isZero)
107 | guard magnitude == 1 else { return 0 }
108 | guard sign == .minus else { return 1 }
109 | guard exponent.magnitude[0] & 1 != 0 else { return 1 }
110 | return BigInt(modulus.magnitude - 1)
111 | }
112 | let power = self.magnitude.power(exponent.magnitude,
113 | modulus: modulus.magnitude)
114 | if self.sign == .plus || exponent.magnitude[0] & 1 == 0 || power.isZero {
115 | return BigInt(power)
116 | }
117 | return BigInt(modulus.magnitude - power)
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/Sources/Floating Point Conversion.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Floating Point Conversion.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2017-08-11.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | #if canImport(Foundation)
10 | import Foundation
11 | #endif
12 |
13 | extension BigUInt {
14 | public init?(exactly source: T) {
15 | guard source.isFinite else { return nil }
16 | guard !source.isZero else { self = 0; return }
17 | guard source.sign == .plus else { return nil }
18 | let value = source.rounded(.towardZero)
19 | guard value == source else { return nil }
20 | assert(value.floatingPointClass == .positiveNormal)
21 | assert(value.exponent >= 0)
22 | let significand = value.significandBitPattern
23 | self = (BigUInt(1) << value.exponent) + BigUInt(significand) >> (T.significandBitCount - Int(value.exponent))
24 | }
25 |
26 | public init(_ source: T) {
27 | self.init(exactly: source.rounded(.towardZero))!
28 | }
29 |
30 | #if canImport(Foundation)
31 | public init?(exactly source: Decimal) {
32 | guard source.exponent >= 0 else { return nil }
33 | self.init(commonDecimal: source)
34 | }
35 |
36 | public init?(truncating source: Decimal) {
37 | self.init(commonDecimal: source)
38 | }
39 |
40 | private init?(commonDecimal source: Decimal) {
41 | var integer = source
42 | if source.exponent < 0 {
43 | var source = source
44 | NSDecimalRound(&integer, &source, 0, .down)
45 | }
46 |
47 | guard !integer.isZero else { self = 0; return }
48 | guard integer.isFinite else { return nil }
49 | guard integer.sign == .plus else { return nil }
50 | assert(integer.floatingPointClass == .positiveNormal)
51 |
52 | #if os(Linux) || os(Android) || os(Windows)
53 | // `Decimal._mantissa` has an internal access level on linux, and it might get
54 | // deprecated in the future, so keeping the string implementation around for now.
55 | let significand = BigUInt("\(integer.significand)")!
56 | #else
57 | let significand = {
58 | var start = BigUInt(0)
59 | for (place, value) in integer.significand.mantissaParts.enumerated() {
60 | guard value > 0 else { continue }
61 | start += (1 << (place * 16)) * BigUInt(value)
62 | }
63 | return start
64 | }()
65 | #endif
66 | let exponent = BigUInt(10).power(integer.exponent)
67 |
68 | self = significand * exponent
69 | }
70 | #endif
71 | }
72 |
73 | extension BigInt {
74 | public init?(exactly source: T) {
75 | guard let magnitude = BigUInt(exactly: source.magnitude) else { return nil }
76 | let sign = BigInt.Sign(source.sign)
77 | self.init(sign: sign, magnitude: magnitude)
78 | }
79 |
80 | public init(_ source: T) {
81 | self.init(exactly: source.rounded(.towardZero))!
82 | }
83 |
84 | #if canImport(Foundation)
85 | public init?(exactly source: Decimal) {
86 | guard let magnitude = BigUInt(exactly: source.magnitude) else { return nil }
87 | let sign = BigInt.Sign(source.sign)
88 | self.init(sign: sign, magnitude: magnitude)
89 | }
90 |
91 | public init?(truncating source: Decimal) {
92 | guard let magnitude = BigUInt(truncating: source.magnitude) else { return nil }
93 | let sign = BigInt.Sign(source.sign)
94 | self.init(sign: sign, magnitude: magnitude)
95 | }
96 | #endif
97 | }
98 |
99 | extension BinaryFloatingPoint where RawExponent: FixedWidthInteger, RawSignificand: FixedWidthInteger {
100 | public init(_ value: BigInt) {
101 | guard !value.isZero else { self = 0; return }
102 | let v = value.magnitude
103 | let bitWidth = v.bitWidth
104 | var exponent = bitWidth - 1
105 | let shift = bitWidth - Self.significandBitCount - 1
106 | var significand = value.magnitude >> (shift - 1)
107 | if significand[0] & 3 == 3 { // Handle rounding
108 | significand >>= 1
109 | significand += 1
110 | if significand.trailingZeroBitCount >= Self.significandBitCount {
111 | exponent += 1
112 | }
113 | }
114 | else {
115 | significand >>= 1
116 | }
117 | let bias = 1 << (Self.exponentBitCount - 1) - 1
118 | guard exponent <= bias else { self = Self.infinity; return }
119 | significand &= 1 << Self.significandBitCount - 1
120 | self = Self.init(sign: value.sign == .plus ? .plus : .minus,
121 | exponentBitPattern: RawExponent(bias + exponent),
122 | significandBitPattern: RawSignificand(significand))
123 | }
124 |
125 | public init(_ value: BigUInt) {
126 | self.init(BigInt(sign: .plus, magnitude: value))
127 | }
128 | }
129 |
130 | extension BigInt.Sign {
131 | public init(_ sign: FloatingPointSign) {
132 | switch sign {
133 | case .plus:
134 | self = .plus
135 | case .minus:
136 | self = .minus
137 | }
138 | }
139 | }
140 |
141 | #if canImport(Foundation)
142 | public extension Decimal {
143 | init(_ value: BigUInt) {
144 | guard
145 | value < BigUInt(exactly: Decimal.greatestFiniteMagnitude)!
146 | else {
147 | self = .greatestFiniteMagnitude
148 | return
149 | }
150 | guard !value.isZero else { self = 0; return }
151 |
152 | self.init(string: "\(value)")!
153 | }
154 |
155 | init(_ value: BigInt) {
156 | if value >= 0 {
157 | self.init(BigUInt(value))
158 | } else {
159 | self.init(value.magnitude)
160 | self *= -1
161 | }
162 | }
163 | }
164 | #endif
165 |
166 | #if canImport(Foundation) && !(os(Linux) || os(Android) || os(Windows))
167 | private extension Decimal {
168 | var mantissaParts: [UInt16] {
169 | [
170 | _mantissa.0,
171 | _mantissa.1,
172 | _mantissa.2,
173 | _mantissa.3,
174 | _mantissa.4,
175 | _mantissa.5,
176 | _mantissa.6,
177 | _mantissa.7,
178 | ]
179 | }
180 | }
181 | #endif
182 |
--------------------------------------------------------------------------------
/Sources/GCD.swift:
--------------------------------------------------------------------------------
1 | //
2 | // GCD.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt {
10 | //MARK: Greatest Common Divisor
11 |
12 | /// Returns the greatest common divisor of `self` and `b`.
13 | ///
14 | /// - Complexity: O(count^2) where count = max(self.count, b.count)
15 | public func greatestCommonDivisor(with b: BigUInt) -> BigUInt {
16 | // This is Stein's algorithm: https://en.wikipedia.org/wiki/Binary_GCD_algorithm
17 | if self.isZero { return b }
18 | if b.isZero { return self }
19 |
20 | let az = self.trailingZeroBitCount
21 | let bz = b.trailingZeroBitCount
22 | let twos = Swift.min(az, bz)
23 |
24 | var (x, y) = (self >> az, b >> bz)
25 | if x < y { swap(&x, &y) }
26 |
27 | while !x.isZero {
28 | x >>= x.trailingZeroBitCount
29 | if x < y { swap(&x, &y) }
30 | x -= y
31 | }
32 | return y << twos
33 | }
34 |
35 | /// Returns the [multiplicative inverse of this integer in modulo `modulus` arithmetic][inverse],
36 | /// or `nil` if there is no such number.
37 | ///
38 | /// [inverse]: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers
39 | ///
40 | /// - Returns: If `gcd(self, modulus) == 1`, the value returned is an integer `a < modulus` such that `(a * self) % modulus == 1`. If `self` and `modulus` aren't coprime, the return value is `nil`.
41 | /// - Requires: modulus > 1
42 | /// - Complexity: O(count^3)
43 | public func inverse(_ modulus: BigUInt) -> BigUInt? {
44 | precondition(modulus > 1)
45 | var t1 = BigInt(0)
46 | var t2 = BigInt(1)
47 | var r1 = modulus
48 | var r2 = self
49 | while !r2.isZero {
50 | let quotient = r1 / r2
51 | (t1, t2) = (t2, t1 - BigInt(quotient) * t2)
52 | (r1, r2) = (r2, r1 - quotient * r2)
53 | }
54 | if r1 > 1 { return nil }
55 | if t1.sign == .minus { return modulus - t1.magnitude }
56 | return t1.magnitude
57 | }
58 | }
59 |
60 | extension BigInt {
61 | /// Returns the greatest common divisor of `a` and `b`.
62 | ///
63 | /// - Complexity: O(count^2) where count = max(a.count, b.count)
64 | public func greatestCommonDivisor(with b: BigInt) -> BigInt {
65 | return BigInt(self.magnitude.greatestCommonDivisor(with: b.magnitude))
66 | }
67 |
68 | /// Returns the [multiplicative inverse of this integer in modulo `modulus` arithmetic][inverse],
69 | /// or `nil` if there is no such number.
70 | ///
71 | /// [inverse]: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm#Modular_integers
72 | ///
73 | /// - Returns: If `gcd(self, modulus) == 1`, the value returned is an integer `a < modulus` such that `(a * self) % modulus == 1`. If `self` and `modulus` aren't coprime, the return value is `nil`.
74 | /// - Requires: modulus.magnitude > 1
75 | /// - Complexity: O(count^3)
76 | public func inverse(_ modulus: BigInt) -> BigInt? {
77 | guard let inv = self.magnitude.inverse(modulus.magnitude) else { return nil }
78 | return BigInt(self.sign == .plus || inv.isZero ? inv : modulus.magnitude - inv)
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Sources/Hashable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Hashable.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt: Hashable {
10 | //MARK: Hashing
11 |
12 | /// Append this `BigUInt` to the specified hasher.
13 | public func hash(into hasher: inout Hasher) {
14 | for word in self.words {
15 | hasher.combine(word)
16 | }
17 | }
18 | }
19 |
20 | extension BigInt: Hashable {
21 | /// Append this `BigInt` to the specified hasher.
22 | public func hash(into hasher: inout Hasher) {
23 | hasher.combine(sign)
24 | hasher.combine(magnitude)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Integer Conversion.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Integer Conversion.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2017-08-11.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt {
10 | public init?(exactly source: T) {
11 | guard source >= (0 as T) else { return nil }
12 | if source.bitWidth <= 2 * Word.bitWidth {
13 | var it = source.words.makeIterator()
14 | self.init(low: it.next() ?? 0, high: it.next() ?? 0)
15 | precondition(it.next() == nil, "Length of BinaryInteger.words is greater than its bitWidth")
16 | }
17 | else {
18 | self.init(words: source.words)
19 | }
20 | }
21 |
22 | public init(_ source: T) {
23 | precondition(source >= (0 as T), "BigUInt cannot represent negative values")
24 | self.init(exactly: source)!
25 | }
26 |
27 | public init(truncatingIfNeeded source: T) {
28 | self.init(words: source.words)
29 | }
30 |
31 | public init(clamping source: T) {
32 | if source <= (0 as T) {
33 | self.init()
34 | }
35 | else {
36 | self.init(words: source.words)
37 | }
38 | }
39 | }
40 |
41 | extension BigInt {
42 | public init() {
43 | self.init(sign: .plus, magnitude: 0)
44 | }
45 |
46 | /// Initializes a new signed big integer with the same value as the specified unsigned big integer.
47 | public init(_ integer: BigUInt) {
48 | self.magnitude = integer
49 | self.sign = .plus
50 | }
51 |
52 | public init(_ source: T) where T : BinaryInteger {
53 | if source >= (0 as T) {
54 | self.init(sign: .plus, magnitude: BigUInt(source))
55 | }
56 | else {
57 | var words = Array(source.words)
58 | words.twosComplement()
59 | self.init(sign: .minus, magnitude: BigUInt(words: words))
60 | }
61 | }
62 |
63 | public init?(exactly source: T) where T : BinaryInteger {
64 | self.init(source)
65 | }
66 |
67 | public init(clamping source: T) where T : BinaryInteger {
68 | self.init(source)
69 | }
70 |
71 | public init(truncatingIfNeeded source: T) where T : BinaryInteger {
72 | self.init(source)
73 | }
74 | }
75 |
76 | extension BigUInt: ExpressibleByIntegerLiteral {
77 | /// Initialize a new big integer from an integer literal.
78 | public init(integerLiteral value: UInt64) {
79 | self.init(value)
80 | }
81 | }
82 |
83 | extension BigInt: ExpressibleByIntegerLiteral {
84 | /// Initialize a new big integer from an integer literal.
85 | public init(integerLiteral value: Int64) {
86 | self.init(value)
87 | }
88 | }
89 |
90 |
--------------------------------------------------------------------------------
/Sources/Multiplication.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Multiplication.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt {
10 |
11 | //MARK: Multiplication
12 |
13 | /// Multiply this big integer by a single word, and store the result in place of the original big integer.
14 | ///
15 | /// - Complexity: O(count)
16 | public mutating func multiply(byWord y: Word) {
17 | guard y != 0 else { self = 0; return }
18 | guard y != 1 else { return }
19 | var carry: Word = 0
20 | let c = self.count
21 | for i in 0 ..< c {
22 | let (h, l) = self[i].multipliedFullWidth(by: y)
23 | let (low, o) = l.addingReportingOverflow(carry)
24 | self[i] = low
25 | carry = (o ? h + 1 : h)
26 | }
27 | self[c] = carry
28 | }
29 |
30 | /// Multiply this big integer by a single Word, and return the result.
31 | ///
32 | /// - Complexity: O(count)
33 | public func multiplied(byWord y: Word) -> BigUInt {
34 | var r = self
35 | r.multiply(byWord: y)
36 | return r
37 | }
38 |
39 | /// Multiply `x` by `y`, and add the result to this integer, optionally shifted `shift` words to the left.
40 | ///
41 | /// - Note: This is the fused multiply/shift/add operation; it is more efficient than doing the components
42 | /// individually. (The fused operation doesn't need to allocate space for temporary big integers.)
43 | /// `self` is set to `self + (x * y) << (shift * 2^Word.bitWidth)`
44 | /// - Complexity: O(count)
45 | public mutating func multiplyAndAdd(_ x: BigUInt, _ y: Word, shiftedBy shift: Int = 0) {
46 | precondition(shift >= 0)
47 | guard y != 0 && x.count > 0 else { return }
48 | guard y != 1 else { self.add(x, shiftedBy: shift); return }
49 | var mulCarry: Word = 0
50 | var addCarry = false
51 | let xc = x.count
52 | var xi = 0
53 | while xi < xc || addCarry || mulCarry > 0 {
54 | let (h, l) = x[xi].multipliedFullWidth(by: y)
55 | let (low, o) = l.addingReportingOverflow(mulCarry)
56 | mulCarry = (o ? h + 1 : h)
57 |
58 | let ai = shift + xi
59 | let (sum1, so1) = self[ai].addingReportingOverflow(low)
60 | if addCarry {
61 | let (sum2, so2) = sum1.addingReportingOverflow(1)
62 | self[ai] = sum2
63 | addCarry = so1 || so2
64 | }
65 | else {
66 | self[ai] = sum1
67 | addCarry = so1
68 | }
69 | xi += 1
70 | }
71 | }
72 |
73 | /// Multiply this integer by `y` and return the result.
74 | ///
75 | /// - Note: This uses the naive O(n^2) multiplication algorithm unless both arguments have more than
76 | /// `BigUInt.directMultiplicationLimit` words.
77 | /// - Complexity: O(n^log2(3))
78 | public func multiplied(by y: BigUInt) -> BigUInt {
79 | // This method is mostly defined for symmetry with the rest of the arithmetic operations.
80 | return self * y
81 | }
82 |
83 | /// Multiplication switches to an asymptotically better recursive algorithm when arguments have more words than this limit.
84 | public static let directMultiplicationLimit: Int = 1024
85 |
86 | /// Multiply `a` by `b` and return the result.
87 | ///
88 | /// - Note: This uses the naive O(n^2) multiplication algorithm unless both arguments have more than
89 | /// `BigUInt.directMultiplicationLimit` words.
90 | /// - Complexity: O(n^log2(3))
91 | public static func *(x: BigUInt, y: BigUInt) -> BigUInt {
92 | let xc = x.count
93 | let yc = y.count
94 | if xc == 0 { return BigUInt() }
95 | if yc == 0 { return BigUInt() }
96 | if yc == 1 { return x.multiplied(byWord: y[0]) }
97 | if xc == 1 { return y.multiplied(byWord: x[0]) }
98 |
99 | if Swift.min(xc, yc) <= BigUInt.directMultiplicationLimit {
100 | // Long multiplication.
101 | let left = (xc < yc ? y : x)
102 | let right = (xc < yc ? x : y)
103 | var result = BigUInt()
104 | for i in (0 ..< right.count).reversed() {
105 | result.multiplyAndAdd(left, right[i], shiftedBy: i)
106 | }
107 | return result
108 | }
109 |
110 | if yc < xc {
111 | let (xh, xl) = x.split
112 | var r = xl * y
113 | r.add(xh * y, shiftedBy: x.middleIndex)
114 | return r
115 | }
116 | else if xc < yc {
117 | let (yh, yl) = y.split
118 | var r = yl * x
119 | r.add(yh * x, shiftedBy: y.middleIndex)
120 | return r
121 | }
122 |
123 | let shift = x.middleIndex
124 |
125 | // Karatsuba multiplication:
126 | // x * y = * = (ignoring carry)
127 | let (a, b) = x.split
128 | let (c, d) = y.split
129 |
130 | let high = a * c
131 | let low = b * d
132 | let xp = a >= b
133 | let yp = c >= d
134 | let xm = (xp ? a - b : b - a)
135 | let ym = (yp ? c - d : d - c)
136 | let m = xm * ym
137 |
138 | var r = low
139 | r.add(high, shiftedBy: 2 * shift)
140 | r.add(low, shiftedBy: shift)
141 | r.add(high, shiftedBy: shift)
142 | if xp == yp {
143 | r.subtract(m, shiftedBy: shift)
144 | }
145 | else {
146 | r.add(m, shiftedBy: shift)
147 | }
148 | return r
149 | }
150 |
151 | /// Multiply `a` by `b` and store the result in `a`.
152 | public static func *=(a: inout BigUInt, b: BigUInt) {
153 | a = a * b
154 | }
155 | }
156 |
157 | extension BigInt {
158 | /// Multiply `a` with `b` and return the result.
159 | public static func *(a: BigInt, b: BigInt) -> BigInt {
160 | return BigInt(sign: a.sign == b.sign ? .plus : .minus, magnitude: a.magnitude * b.magnitude)
161 | }
162 |
163 | /// Multiply `a` with `b` in place.
164 | public static func *=(a: inout BigInt, b: BigInt) { a = a * b }
165 | }
166 |
--------------------------------------------------------------------------------
/Sources/Prime Test.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Prime Test.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-04.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | /// The first several [prime numbers][primes].
10 | ///
11 | /// [primes]: https://oeis.org/A000040
12 | let primes: [BigUInt.Word] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41]
13 |
14 | /// The ith element in this sequence is the smallest composite number that passes the strong probable prime test
15 | /// for all of the first (i+1) primes.
16 | ///
17 | /// This is sequence [A014233](http://oeis.org/A014233) on the [Online Encyclopaedia of Integer Sequences](http://oeis.org).
18 | let pseudoPrimes: [BigUInt] = [
19 | /* 2 */ 2_047,
20 | /* 3 */ 1_373_653,
21 | /* 5 */ 25_326_001,
22 | /* 7 */ 3_215_031_751,
23 | /* 11 */ 2_152_302_898_747,
24 | /* 13 */ 3_474_749_660_383,
25 | /* 17 */ 341_550_071_728_321,
26 | /* 19 */ 341_550_071_728_321,
27 | /* 23 */ 3_825_123_056_546_413_051,
28 | /* 29 */ 3_825_123_056_546_413_051,
29 | /* 31 */ 3_825_123_056_546_413_051,
30 | /* 37 */ "318665857834031151167461",
31 | /* 41 */ "3317044064679887385961981",
32 | ]
33 |
34 | extension BigUInt {
35 | //MARK: Primality Testing
36 |
37 | /// Returns true iff this integer passes the [strong probable prime test][sppt] for the specified base.
38 | ///
39 | /// [sppt]: https://en.wikipedia.org/wiki/Probable_prime
40 | public func isStrongProbablePrime(_ base: BigUInt) -> Bool {
41 | precondition(base > (1 as BigUInt))
42 | precondition(self > (0 as BigUInt))
43 | let dec = self - 1
44 |
45 | let r = dec.trailingZeroBitCount
46 | let d = dec >> r
47 |
48 | var test = base.power(d, modulus: self)
49 | if test == 1 || test == dec { return true }
50 |
51 | if r > 0 {
52 | let shift = self.leadingZeroBitCount
53 | let normalized = self << shift
54 | for _ in 1 ..< r {
55 | test *= test
56 | test.formRemainder(dividingBy: normalized, normalizedBy: shift)
57 | if test == 1 {
58 | return false
59 | }
60 | if test == dec { return true }
61 | }
62 | }
63 | return false
64 | }
65 |
66 | /// Returns true if this integer is probably prime. Returns false if this integer is definitely not prime.
67 | ///
68 | /// This function performs a probabilistic [Miller-Rabin Primality Test][mrpt], consisting of `rounds` iterations,
69 | /// each calculating the strong probable prime test for a random base. The number of rounds is 10 by default,
70 | /// but you may specify your own choice.
71 | ///
72 | /// To speed things up, the function checks if `self` is divisible by the first few prime numbers before
73 | /// diving into (slower) Miller-Rabin testing.
74 | ///
75 | /// Also, when `self` is less than 82 bits wide, `isPrime` does a deterministic test that is guaranteed to
76 | /// return a correct result.
77 | ///
78 | /// [mrpt]: https://en.wikipedia.org/wiki/Miller–Rabin_primality_test
79 | public func isPrime(rounds: Int = 10) -> Bool {
80 | if count <= 1 && self[0] < 2 { return false }
81 | if count == 1 && self[0] < 4 { return true }
82 |
83 | // Even numbers above 2 aren't prime.
84 | if self[0] & 1 == 0 { return false }
85 |
86 | // Quickly check for small primes.
87 | for i in 1 ..< primes.count {
88 | let p = primes[i]
89 | if self.count == 1 && self[0] == p {
90 | return true
91 | }
92 | if self.quotientAndRemainder(dividingByWord: p).remainder == 0 {
93 | return false
94 | }
95 | }
96 |
97 | /// Give an exact answer when we can.
98 | if self < pseudoPrimes.last! {
99 | for i in 0 ..< pseudoPrimes.count {
100 | guard isStrongProbablePrime(BigUInt(primes[i])) else {
101 | break
102 | }
103 | if self < pseudoPrimes[i] {
104 | // `self` is below the lowest pseudoprime corresponding to the prime bases we tested. It's a prime!
105 | return true
106 | }
107 | }
108 | return false
109 | }
110 |
111 | /// Otherwise do as many rounds of random SPPT as required.
112 | for _ in 0 ..< rounds {
113 | let random = BigUInt.randomInteger(lessThan: self - 2) + 2
114 | guard isStrongProbablePrime(random) else {
115 | return false
116 | }
117 | }
118 |
119 | // Well, it smells primey to me.
120 | return true
121 | }
122 | }
123 |
124 | extension BigInt {
125 | //MARK: Primality Testing
126 |
127 | /// Returns true iff this integer passes the [strong probable prime test][sppt] for the specified base.
128 | ///
129 | /// [sppt]: https://en.wikipedia.org/wiki/Probable_prime
130 | public func isStrongProbablePrime(_ base: BigInt) -> Bool {
131 | precondition(base.sign == .plus)
132 | if self.sign == .minus { return false }
133 | return self.magnitude.isStrongProbablePrime(base.magnitude)
134 | }
135 |
136 | /// Returns true if this integer is probably prime. Returns false if this integer is definitely not prime.
137 | ///
138 | /// This function performs a probabilistic [Miller-Rabin Primality Test][mrpt], consisting of `rounds` iterations,
139 | /// each calculating the strong probable prime test for a random base. The number of rounds is 10 by default,
140 | /// but you may specify your own choice.
141 | ///
142 | /// To speed things up, the function checks if `self` is divisible by the first few prime numbers before
143 | /// diving into (slower) Miller-Rabin testing.
144 | ///
145 | /// Also, when `self` is less than 82 bits wide, `isPrime` does a deterministic test that is guaranteed to
146 | /// return a correct result.
147 | ///
148 | /// [mrpt]: https://en.wikipedia.org/wiki/Miller–Rabin_primality_test
149 | public func isPrime(rounds: Int = 10) -> Bool {
150 | if self.sign == .minus { return false }
151 | return self.magnitude.isPrime(rounds: rounds)
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/Sources/Random.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Random.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-04.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt {
10 | /// Create a big unsigned integer consisting of `width` uniformly distributed random bits.
11 | ///
12 | /// - Parameter width: The maximum number of one bits in the result.
13 | /// - Parameter generator: The source of randomness.
14 | /// - Returns: A big unsigned integer less than `1 << width`.
15 | public static func randomInteger(withMaximumWidth width: Int, using generator: inout RNG) -> BigUInt {
16 | var result = BigUInt.zero
17 | var bitsLeft = width
18 | var i = 0
19 | let wordsNeeded = (width + Word.bitWidth - 1) / Word.bitWidth
20 | if wordsNeeded > 2 {
21 | result.reserveCapacity(wordsNeeded)
22 | }
23 | while bitsLeft >= Word.bitWidth {
24 | result[i] = generator.next()
25 | i += 1
26 | bitsLeft -= Word.bitWidth
27 | }
28 | if bitsLeft > 0 {
29 | let mask: Word = (1 << bitsLeft) - 1
30 | result[i] = (generator.next() as Word) & mask
31 | }
32 | return result
33 | }
34 |
35 | /// Create a big unsigned integer consisting of `width` uniformly distributed random bits.
36 | ///
37 | /// - Note: I use a `SystemRandomGeneratorGenerator` as the source of randomness.
38 | ///
39 | /// - Parameter width: The maximum number of one bits in the result.
40 | /// - Returns: A big unsigned integer less than `1 << width`.
41 | public static func randomInteger(withMaximumWidth width: Int) -> BigUInt {
42 | var rng = SystemRandomNumberGenerator()
43 | return randomInteger(withMaximumWidth: width, using: &rng)
44 | }
45 |
46 | /// Create a big unsigned integer consisting of `width-1` uniformly distributed random bits followed by a one bit.
47 | ///
48 | /// - Note: If `width` is zero, the result is zero.
49 | ///
50 | /// - Parameter width: The number of bits required to represent the answer.
51 | /// - Parameter generator: The source of randomness.
52 | /// - Returns: A random big unsigned integer whose width is `width`.
53 | public static func randomInteger(withExactWidth width: Int, using generator: inout RNG) -> BigUInt {
54 | // width == 0 -> return 0 because there is no room for a one bit.
55 | // width == 1 -> return 1 because there is no room for any random bits.
56 | guard width > 1 else { return BigUInt(width) }
57 | var result = randomInteger(withMaximumWidth: width - 1, using: &generator)
58 | result[(width - 1) / Word.bitWidth] |= 1 << Word((width - 1) % Word.bitWidth)
59 | return result
60 | }
61 |
62 | /// Create a big unsigned integer consisting of `width-1` uniformly distributed random bits followed by a one bit.
63 | ///
64 | /// - Note: If `width` is zero, the result is zero.
65 | /// - Note: I use a `SystemRandomGeneratorGenerator` as the source of randomness.
66 | ///
67 | /// - Returns: A random big unsigned integer whose width is `width`.
68 | public static func randomInteger(withExactWidth width: Int) -> BigUInt {
69 | var rng = SystemRandomNumberGenerator()
70 | return randomInteger(withExactWidth: width, using: &rng)
71 | }
72 |
73 | /// Create a uniformly distributed random unsigned integer that's less than the specified limit.
74 | ///
75 | /// - Precondition: `limit > 0`.
76 | ///
77 | /// - Parameter limit: The upper bound on the result.
78 | /// - Parameter generator: The source of randomness.
79 | /// - Returns: A random big unsigned integer that is less than `limit`.
80 | public static func randomInteger(lessThan limit: BigUInt, using generator: inout RNG) -> BigUInt {
81 | precondition(limit > 0, "\(#function): 0 is not a valid limit")
82 | let width = limit.bitWidth
83 | var random = randomInteger(withMaximumWidth: width, using: &generator)
84 | while random >= limit {
85 | random = randomInteger(withMaximumWidth: width, using: &generator)
86 | }
87 | return random
88 | }
89 |
90 | /// Create a uniformly distributed random unsigned integer that's less than the specified limit.
91 | ///
92 | /// - Precondition: `limit > 0`.
93 | /// - Note: I use a `SystemRandomGeneratorGenerator` as the source of randomness.
94 | ///
95 | /// - Parameter limit: The upper bound on the result.
96 | /// - Returns: A random big unsigned integer that is less than `limit`.
97 | public static func randomInteger(lessThan limit: BigUInt) -> BigUInt {
98 | var rng = SystemRandomNumberGenerator()
99 | return randomInteger(lessThan: limit, using: &rng)
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/Sources/Shifts.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Shifts.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt {
10 |
11 | //MARK: Shift Operators
12 |
13 | internal func shiftedLeft(by amount: Word) -> BigUInt {
14 | guard amount > 0 else { return self }
15 |
16 | let ext = Int(amount / Word(Word.bitWidth)) // External shift amount (new words)
17 | let up = Word(amount % Word(Word.bitWidth)) // Internal shift amount (subword shift)
18 | let down = Word(Word.bitWidth) - up
19 |
20 | var result = BigUInt()
21 | if up > 0 {
22 | var i = 0
23 | var lowbits: Word = 0
24 | while i < self.count || lowbits > 0 {
25 | let word = self[i]
26 | result[i + ext] = word << up | lowbits
27 | lowbits = word >> down
28 | i += 1
29 | }
30 | }
31 | else {
32 | for i in 0 ..< self.count {
33 | result[i + ext] = self[i]
34 | }
35 | }
36 | return result
37 | }
38 |
39 | internal mutating func shiftLeft(by amount: Word) {
40 | guard amount > 0 else { return }
41 |
42 | let ext = Int(amount / Word(Word.bitWidth)) // External shift amount (new words)
43 | let up = Word(amount % Word(Word.bitWidth)) // Internal shift amount (subword shift)
44 | let down = Word(Word.bitWidth) - up
45 |
46 | if up > 0 {
47 | var i = 0
48 | var lowbits: Word = 0
49 | while i < self.count || lowbits > 0 {
50 | let word = self[i]
51 | self[i] = word << up | lowbits
52 | lowbits = word >> down
53 | i += 1
54 | }
55 | }
56 | if ext > 0 && self.count > 0 {
57 | self.shiftLeft(byWords: ext)
58 | }
59 | }
60 |
61 | internal func shiftedRight(by amount: Word) -> BigUInt {
62 | guard amount > 0 else { return self }
63 | guard amount < self.bitWidth else { return 0 }
64 |
65 | let ext = Int(amount / Word(Word.bitWidth)) // External shift amount (new words)
66 | let down = Word(amount % Word(Word.bitWidth)) // Internal shift amount (subword shift)
67 | let up = Word(Word.bitWidth) - down
68 |
69 | var result = BigUInt()
70 | if down > 0 {
71 | var highbits: Word = 0
72 | for i in (ext ..< self.count).reversed() {
73 | let word = self[i]
74 | result[i - ext] = highbits | word >> down
75 | highbits = word << up
76 | }
77 | }
78 | else {
79 | for i in (ext ..< self.count).reversed() {
80 | result[i - ext] = self[i]
81 | }
82 | }
83 | return result
84 | }
85 |
86 | internal mutating func shiftRight(by amount: Word) {
87 | guard amount > 0 else { return }
88 | guard amount < self.bitWidth else { self.clear(); return }
89 |
90 | let ext = Int(amount / Word(Word.bitWidth)) // External shift amount (new words)
91 | let down = Word(amount % Word(Word.bitWidth)) // Internal shift amount (subword shift)
92 | let up = Word(Word.bitWidth) - down
93 |
94 | if ext > 0 {
95 | self.shiftRight(byWords: ext)
96 | }
97 | if down > 0 {
98 | var i = self.count - 1
99 | var highbits: Word = 0
100 | while i >= 0 {
101 | let word = self[i]
102 | self[i] = highbits | word >> down
103 | highbits = word << up
104 | i -= 1
105 | }
106 | }
107 | }
108 |
109 | public static func >>=(lhs: inout BigUInt, rhs: Other) {
110 | if rhs < (0 as Other) {
111 | lhs <<= (0 - rhs)
112 | }
113 | else if rhs >= lhs.bitWidth {
114 | lhs.clear()
115 | }
116 | else {
117 | lhs.shiftRight(by: UInt(rhs))
118 | }
119 | }
120 |
121 | public static func <<=(lhs: inout BigUInt, rhs: Other) {
122 | if rhs < (0 as Other) {
123 | lhs >>= (0 - rhs)
124 | return
125 | }
126 | lhs.shiftLeft(by: Word(exactly: rhs)!)
127 | }
128 |
129 | public static func >>(lhs: BigUInt, rhs: Other) -> BigUInt {
130 | if rhs < (0 as Other) {
131 | return lhs << (0 - rhs)
132 | }
133 | if rhs > Word.max {
134 | return 0
135 | }
136 | return lhs.shiftedRight(by: UInt(rhs))
137 | }
138 |
139 | public static func <<(lhs: BigUInt, rhs: Other) -> BigUInt {
140 | if rhs < (0 as Other) {
141 | return lhs >> (0 - rhs)
142 | }
143 | return lhs.shiftedLeft(by: Word(exactly: rhs)!)
144 | }
145 | }
146 |
147 | extension BigInt {
148 | func shiftedLeft(by amount: Word) -> BigInt {
149 | return BigInt(sign: self.sign, magnitude: self.magnitude.shiftedLeft(by: amount))
150 | }
151 |
152 | mutating func shiftLeft(by amount: Word) {
153 | self.magnitude.shiftLeft(by: amount)
154 | }
155 |
156 | func shiftedRight(by amount: Word) -> BigInt {
157 | let m = self.magnitude.shiftedRight(by: amount)
158 | return BigInt(sign: self.sign, magnitude: self.sign == .minus && m.isZero ? 1 : m)
159 | }
160 |
161 | mutating func shiftRight(by amount: Word) {
162 | magnitude.shiftRight(by: amount)
163 | if sign == .minus, magnitude.isZero {
164 | magnitude.load(1)
165 | }
166 | }
167 |
168 | public static func &<<(left: BigInt, right: BigInt) -> BigInt {
169 | return left.shiftedLeft(by: right.words[0])
170 | }
171 |
172 | public static func &<<=(left: inout BigInt, right: BigInt) {
173 | left.shiftLeft(by: right.words[0])
174 | }
175 |
176 | public static func &>>(left: BigInt, right: BigInt) -> BigInt {
177 | return left.shiftedRight(by: right.words[0])
178 | }
179 |
180 | public static func &>>=(left: inout BigInt, right: BigInt) {
181 | left.shiftRight(by: right.words[0])
182 | }
183 |
184 | public static func <<(lhs: BigInt, rhs: Other) -> BigInt {
185 | guard rhs >= (0 as Other) else { return lhs >> (0 - rhs) }
186 | return lhs.shiftedLeft(by: Word(rhs))
187 | }
188 |
189 | public static func <<=(lhs: inout BigInt, rhs: Other) {
190 | if rhs < (0 as Other) {
191 | lhs >>= (0 - rhs)
192 | }
193 | else {
194 | lhs.shiftLeft(by: Word(rhs))
195 | }
196 | }
197 |
198 | public static func >>(lhs: BigInt, rhs: Other) -> BigInt {
199 | guard rhs >= (0 as Other) else { return lhs << (0 - rhs) }
200 | return lhs.shiftedRight(by: Word(rhs))
201 | }
202 |
203 | public static func >>=(lhs: inout BigInt, rhs: Other) {
204 | if rhs < (0 as Other) {
205 | lhs <<= (0 - rhs)
206 | }
207 | else {
208 | lhs.shiftRight(by: Word(rhs))
209 | }
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/Sources/Square Root.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Square Root.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | //MARK: Square Root
10 |
11 | extension BigUInt {
12 | /// Returns the integer square root of a big integer; i.e., the largest integer whose square isn't greater than `value`.
13 | ///
14 | /// - Returns: floor(sqrt(self))
15 | public func squareRoot() -> BigUInt {
16 | // This implementation uses Newton's method.
17 | guard !self.isZero else { return BigUInt() }
18 | var x = BigUInt(1) << ((self.bitWidth + 1) / 2)
19 | var y: BigUInt = 0
20 | while true {
21 | y.load(self)
22 | y /= x
23 | y += x
24 | y >>= 1
25 | if x == y || x == y - 1 { break }
26 | x = y
27 | }
28 | return x
29 | }
30 | }
31 |
32 | extension BigInt {
33 | /// Returns the integer square root of a big integer; i.e., the largest integer whose square isn't greater than `value`.
34 | ///
35 | /// - Requires: self >= 0
36 | /// - Returns: floor(sqrt(self))
37 | public func squareRoot() -> BigInt {
38 | precondition(self.sign == .plus)
39 | return BigInt(sign: .plus, magnitude: self.magnitude.squareRoot())
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/Strideable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Strideable.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2017-08-11.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt: Strideable {
10 | /// A type that can represent the distance between two values ofa `BigUInt`.
11 | public typealias Stride = BigInt
12 |
13 | /// Adds `n` to `self` and returns the result. Traps if the result would be less than zero.
14 | public func advanced(by n: BigInt) -> BigUInt {
15 | return n.sign == .minus ? self - n.magnitude : self + n.magnitude
16 | }
17 |
18 | /// Returns the (potentially negative) difference between `self` and `other` as a `BigInt`. Never traps.
19 | public func distance(to other: BigUInt) -> BigInt {
20 | return BigInt(other) - BigInt(self)
21 | }
22 | }
23 |
24 | extension BigInt: Strideable {
25 | public typealias Stride = BigInt
26 |
27 | /// Returns `self + n`.
28 | public func advanced(by n: Stride) -> BigInt {
29 | return self + n
30 | }
31 |
32 | /// Returns `other - self`.
33 | public func distance(to other: BigInt) -> Stride {
34 | return other - self
35 | }
36 | }
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Sources/Subtraction.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Subtraction.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2016-01-03.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension BigUInt {
10 | //MARK: Subtraction
11 |
12 | /// Subtract `word` from this integer in place, returning a flag indicating if the operation
13 | /// caused an arithmetic overflow. `word` is shifted `shift` words to the left before being subtracted.
14 | ///
15 | /// - Note: If the result indicates an overflow, then `self` becomes the two's complement of the absolute difference.
16 | /// - Complexity: O(count)
17 | internal mutating func subtractWordReportingOverflow(_ word: Word, shiftedBy shift: Int = 0) -> Bool {
18 | precondition(shift >= 0)
19 | var carry: Word = word
20 | var i = shift
21 | let count = self.count
22 | while carry > 0 && i < count {
23 | let (d, c) = self[i].subtractingReportingOverflow(carry)
24 | self[i] = d
25 | carry = (c ? 1 : 0)
26 | i += 1
27 | }
28 | return carry > 0
29 | }
30 |
31 | /// Subtract `word` from this integer, returning the difference and a flag that is true if the operation
32 | /// caused an arithmetic overflow. `word` is shifted `shift` words to the left before being subtracted.
33 | ///
34 | /// - Note: If `overflow` is true, then the returned value is the two's complement of the absolute difference.
35 | /// - Complexity: O(count)
36 | internal func subtractingWordReportingOverflow(_ word: Word, shiftedBy shift: Int = 0) -> (partialValue: BigUInt, overflow: Bool) {
37 | var result = self
38 | let overflow = result.subtractWordReportingOverflow(word, shiftedBy: shift)
39 | return (result, overflow)
40 | }
41 |
42 | /// Subtract a digit `d` from this integer in place.
43 | /// `d` is shifted `shift` digits to the left before being subtracted.
44 | ///
45 | /// - Requires: self >= d * 2^shift
46 | /// - Complexity: O(count)
47 | internal mutating func subtractWord(_ word: Word, shiftedBy shift: Int = 0) {
48 | let overflow = subtractWordReportingOverflow(word, shiftedBy: shift)
49 | precondition(!overflow)
50 | }
51 |
52 | /// Subtract a digit `d` from this integer and return the result.
53 | /// `d` is shifted `shift` digits to the left before being subtracted.
54 | ///
55 | /// - Requires: self >= d * 2^shift
56 | /// - Complexity: O(count)
57 | internal func subtractingWord(_ word: Word, shiftedBy shift: Int = 0) -> BigUInt {
58 | var result = self
59 | result.subtractWord(word, shiftedBy: shift)
60 | return result
61 | }
62 |
63 | /// Subtract `other` from this integer in place, and return a flag indicating if the operation caused an
64 | /// arithmetic overflow. `other` is shifted `shift` digits to the left before being subtracted.
65 | ///
66 | /// - Note: If the result indicates an overflow, then `self` becomes the twos' complement of the absolute difference.
67 | /// - Complexity: O(count)
68 | public mutating func subtractReportingOverflow(_ b: BigUInt, shiftedBy shift: Int = 0) -> Bool {
69 | precondition(shift >= 0)
70 | var carry = false
71 | var bi = 0
72 | let bc = b.count
73 | let count = self.count
74 | while bi < bc || (shift + bi < count && carry) {
75 | let ai = shift + bi
76 | let (d, c) = self[ai].subtractingReportingOverflow(b[bi])
77 | if carry {
78 | let (d2, c2) = d.subtractingReportingOverflow(1)
79 | self[ai] = d2
80 | carry = c || c2
81 | }
82 | else {
83 | self[ai] = d
84 | carry = c
85 | }
86 | bi += 1
87 | }
88 | return carry
89 | }
90 |
91 | /// Subtract `other` from this integer, returning the difference and a flag indicating arithmetic overflow.
92 | /// `other` is shifted `shift` digits to the left before being subtracted.
93 | ///
94 | /// - Note: If `overflow` is true, then the result value is the twos' complement of the absolute value of the difference.
95 | /// - Complexity: O(count)
96 | public func subtractingReportingOverflow(_ other: BigUInt, shiftedBy shift: Int) -> (partialValue: BigUInt, overflow: Bool) {
97 | var result = self
98 | let overflow = result.subtractReportingOverflow(other, shiftedBy: shift)
99 | return (result, overflow)
100 | }
101 |
102 | /// Subtracts `other` from `self`, returning the result and a flag indicating arithmetic overflow.
103 | ///
104 | /// - Note: When the operation overflows, then `partialValue` is the twos' complement of the absolute value of the difference.
105 | /// - Complexity: O(count)
106 | public func subtractingReportingOverflow(_ other: BigUInt) -> (partialValue: BigUInt, overflow: Bool) {
107 | return self.subtractingReportingOverflow(other, shiftedBy: 0)
108 | }
109 |
110 | /// Subtract `other` from this integer in place.
111 | /// `other` is shifted `shift` digits to the left before being subtracted.
112 | ///
113 | /// - Requires: self >= other * 2^shift
114 | /// - Complexity: O(count)
115 | public mutating func subtract(_ other: BigUInt, shiftedBy shift: Int = 0) {
116 | let overflow = subtractReportingOverflow(other, shiftedBy: shift)
117 | precondition(!overflow)
118 | }
119 |
120 | /// Subtract `b` from this integer, and return the difference.
121 | /// `b` is shifted `shift` digits to the left before being subtracted.
122 | ///
123 | /// - Requires: self >= b * 2^shift
124 | /// - Complexity: O(count)
125 | public func subtracting(_ other: BigUInt, shiftedBy shift: Int = 0) -> BigUInt {
126 | var result = self
127 | result.subtract(other, shiftedBy: shift)
128 | return result
129 | }
130 |
131 | /// Decrement this integer by one.
132 | ///
133 | /// - Requires: !isZero
134 | /// - Complexity: O(count)
135 | public mutating func decrement(shiftedBy shift: Int = 0) {
136 | self.subtract(1, shiftedBy: shift)
137 | }
138 |
139 | /// Subtract `b` from `a` and return the result.
140 | ///
141 | /// - Requires: a >= b
142 | /// - Complexity: O(a.count)
143 | public static func -(a: BigUInt, b: BigUInt) -> BigUInt {
144 | return a.subtracting(b)
145 | }
146 |
147 | /// Subtract `b` from `a` and store the result in `a`.
148 | ///
149 | /// - Requires: a >= b
150 | /// - Complexity: O(a.count)
151 | public static func -=(a: inout BigUInt, b: BigUInt) {
152 | a.subtract(b)
153 | }
154 | }
155 |
156 | extension BigInt {
157 | public mutating func negate() {
158 | guard !magnitude.isZero else { return }
159 | self.sign = self.sign == .plus ? .minus : .plus
160 | }
161 |
162 | /// Subtract `b` from `a` and return the result.
163 | public static func -(a: BigInt, b: BigInt) -> BigInt {
164 | return a + -b
165 | }
166 |
167 | /// Subtract `b` from `a` in place.
168 | public static func -=(a: inout BigInt, b: BigInt) { a = a - b }
169 | }
170 |
--------------------------------------------------------------------------------
/Sources/Words and Bits.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Words and Bits.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2017-08-11.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | extension Array where Element == UInt {
10 | mutating func twosComplement() {
11 | var increment = true
12 | for i in 0 ..< self.count {
13 | if increment {
14 | (self[i], increment) = (~self[i]).addingReportingOverflow(1)
15 | }
16 | else {
17 | self[i] = ~self[i]
18 | }
19 | }
20 | }
21 | }
22 |
23 | extension BigUInt {
24 | public subscript(bitAt index: Int) -> Bool {
25 | get {
26 | precondition(index >= 0)
27 | let (i, j) = index.quotientAndRemainder(dividingBy: Word.bitWidth)
28 | return self[i] & (1 << j) != 0
29 | }
30 | set {
31 | precondition(index >= 0)
32 | let (i, j) = index.quotientAndRemainder(dividingBy: Word.bitWidth)
33 | if newValue {
34 | self[i] |= 1 << j
35 | }
36 | else {
37 | self[i] &= ~(1 << j)
38 | }
39 | }
40 | }
41 | }
42 |
43 | extension BigUInt {
44 | /// The minimum number of bits required to represent this integer in binary.
45 | ///
46 | /// - Returns: floor(log2(2 * self + 1))
47 | /// - Complexity: O(1)
48 | public var bitWidth: Int {
49 | guard count > 0 else { return 0 }
50 | return count * Word.bitWidth - self[count - 1].leadingZeroBitCount
51 | }
52 |
53 | /// The number of leading zero bits in the binary representation of this integer in base `2^(Word.bitWidth)`.
54 | /// This is useful when you need to normalize a `BigUInt` such that the top bit of its most significant word is 1.
55 | ///
56 | /// - Note: 0 is considered to have zero leading zero bits.
57 | /// - Returns: A value in `0...(Word.bitWidth - 1)`.
58 | /// - SeeAlso: width
59 | /// - Complexity: O(1)
60 | public var leadingZeroBitCount: Int {
61 | guard count > 0 else { return 0 }
62 | return self[count - 1].leadingZeroBitCount
63 | }
64 |
65 | /// The number of trailing zero bits in the binary representation of this integer.
66 | ///
67 | /// - Note: 0 is considered to have zero trailing zero bits.
68 | /// - Returns: A value in `0...width`.
69 | /// - Complexity: O(count)
70 | public var trailingZeroBitCount: Int {
71 | guard count > 0 else { return 0 }
72 | let i = self.words.firstIndex { $0 != 0 }!
73 | return i * Word.bitWidth + self[i].trailingZeroBitCount
74 | }
75 | }
76 |
77 | extension BigInt {
78 | public var bitWidth: Int {
79 | guard !magnitude.isZero else { return 0 }
80 | return magnitude.bitWidth + 1
81 | }
82 |
83 | public var trailingZeroBitCount: Int {
84 | // Amazingly, this works fine for negative numbers
85 | return magnitude.trailingZeroBitCount
86 | }
87 | }
88 |
89 | extension BigUInt {
90 | public struct Words: RandomAccessCollection {
91 | private let value: BigUInt
92 |
93 | fileprivate init(_ value: BigUInt) { self.value = value }
94 |
95 | public var startIndex: Int { return 0 }
96 | public var endIndex: Int { return value.count }
97 |
98 | public subscript(_ index: Int) -> Word {
99 | return value[index]
100 | }
101 | }
102 |
103 | public var words: Words { return Words(self) }
104 |
105 | public init(words: Words) where Words.Element == Word {
106 | let uc = words.underestimatedCount
107 | if uc > 2 {
108 | self.init(words: Array(words))
109 | }
110 | else {
111 | var it = words.makeIterator()
112 | guard let w0 = it.next() else {
113 | self.init()
114 | return
115 | }
116 | guard let w1 = it.next() else {
117 | self.init(word: w0)
118 | return
119 | }
120 | if let w2 = it.next() {
121 | var words: [UInt] = []
122 | words.reserveCapacity(Swift.max(3, uc))
123 | words.append(w0)
124 | words.append(w1)
125 | words.append(w2)
126 | while let word = it.next() {
127 | words.append(word)
128 | }
129 | self.init(words: words)
130 | }
131 | else {
132 | self.init(low: w0, high: w1)
133 | }
134 | }
135 | }
136 | }
137 |
138 | extension BigInt {
139 | public struct Words: RandomAccessCollection {
140 | public typealias Indices = CountableRange
141 |
142 | private let value: BigInt
143 | private let decrementLimit: Int
144 |
145 | fileprivate init(_ value: BigInt) {
146 | self.value = value
147 | switch value.sign {
148 | case .plus:
149 | self.decrementLimit = 0
150 | case .minus:
151 | assert(!value.magnitude.isZero)
152 | self.decrementLimit = value.magnitude.words.firstIndex(where: { $0 != 0 })!
153 | }
154 | }
155 |
156 | public var count: Int {
157 | switch value.sign {
158 | case .plus:
159 | if let high = value.magnitude.words.last, high >> (Word.bitWidth - 1) != 0 {
160 | return value.magnitude.count + 1
161 | }
162 | return value.magnitude.count
163 | case .minus:
164 | let high = value.magnitude.words.last!
165 | if high >> (Word.bitWidth - 1) != 0 {
166 | return value.magnitude.count + 1
167 | }
168 | return value.magnitude.count
169 | }
170 | }
171 |
172 | public var indices: Indices { return 0 ..< count }
173 | public var startIndex: Int { return 0 }
174 | public var endIndex: Int { return count }
175 |
176 | public subscript(_ index: Int) -> UInt {
177 | // Note that indices above `endIndex` are accepted.
178 | if value.sign == .plus {
179 | return value.magnitude[index]
180 | }
181 | if index <= decrementLimit {
182 | return ~(value.magnitude[index] &- 1)
183 | }
184 | return ~value.magnitude[index]
185 | }
186 | }
187 |
188 | public var words: Words {
189 | return Words(self)
190 | }
191 |
192 | public init(words: S) where S.Element == Word {
193 | var words = Array(words)
194 | if (words.last ?? 0) >> (Word.bitWidth - 1) == 0 {
195 | self.init(sign: .plus, magnitude: BigUInt(words: words))
196 | }
197 | else {
198 | words.twosComplement()
199 | self.init(sign: .minus, magnitude: BigUInt(words: words))
200 | }
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/ProfileTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ProfileTests.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2015-12-31.
6 | // Copyright © 2016-2017 Károly Lőrentey.
7 | //
8 |
9 | import XCTest
10 | import BigInt
11 |
12 | #if Profile
13 |
14 | func factorial(_ n: Int) -> BigUInt {
15 | var fact = BigUInt(1)
16 | for i in BigUInt.Word(1) ... BigUInt.Word(n) {
17 | fact.multiply(byWord: i)
18 | }
19 | return fact
20 | }
21 |
22 | class ProfileTests: XCTestCase {
23 | typealias Word = BigUInt.Word
24 |
25 | func measure_(autostart: Bool = true, block: @escaping ()->Void) {
26 | var round = 0
27 | self.measureMetrics(type(of: self).defaultPerformanceMetrics, automaticallyStartMeasuring: autostart) {
28 | print("Round \(round) started")
29 | block()
30 | round += 1
31 | }
32 | }
33 |
34 | func testFibonacciAddition() {
35 | var n1 = BigUInt(1)
36 | var n2 = BigUInt(1)
37 | self.measure {
38 | n1 = BigUInt(1)
39 | n2 = BigUInt(1)
40 | for i in 0..<200000 {
41 | if i & 1 == 0 {
42 | n1 += n2
43 | }
44 | else {
45 | n2 += n1
46 | }
47 | }
48 | }
49 | noop(n1)
50 | noop(n2)
51 | }
52 |
53 | func checkFactorial(fact: BigUInt, n: Int, file: StaticString = #file, line: UInt = #line) {
54 | var remaining = fact
55 | for i in 1...n {
56 | let (div, mod) = remaining.quotientAndRemainder(dividingBy: BigUInt(i))
57 | XCTAssertEqual(mod, 0, "for divisor = \(i)", file: file, line: line)
58 | remaining = div
59 | }
60 | XCTAssertEqual(remaining, 1, file: file, line: line)
61 | }
62 |
63 | func testDivisionOfFactorial() {
64 | let n = 32767
65 | let fact = factorial(n)
66 | self.measure {
67 | checkFactorial(fact: fact, n: n)
68 | }
69 | }
70 |
71 | func testPrintingFactorial() {
72 | let n = 32767
73 | let fact = factorial(n)
74 | var string: String = ""
75 | self.measure {
76 | string = String(fact, radix: 10)
77 | }
78 | XCTAssertEqual(BigUInt(string, radix: 10), fact)
79 | }
80 |
81 | func testReadingFactorial() {
82 | let n = 32767
83 | let fact = factorial(n)
84 | let string = String(fact, radix: 10)
85 | print(string)
86 | self.measure {
87 | XCTAssertEqual(BigUInt(string, radix: 10), fact)
88 | }
89 | }
90 |
91 | func testFactorial() {
92 | var fact = BigUInt()
93 | let n = 32767
94 | self.measure {
95 | fact = factorial(n)
96 | }
97 | checkFactorial(fact: fact, n: n)
98 | }
99 |
100 | func testBalancedFactorial() {
101 | func balancedFactorial(level: Int, offset: Int = 0) -> BigUInt {
102 | if level == 0 {
103 | return BigUInt(offset == 0 ? 1 : offset)
104 | }
105 | let a = balancedFactorial(level: level - 1, offset: 2 * offset)
106 | let b = balancedFactorial(level: level - 1, offset: 2 * offset + 1)
107 | return a * b
108 | }
109 |
110 | let power = 15
111 |
112 | var fact = BigUInt()
113 | self.measure {
114 | fact = balancedFactorial(level: power)
115 | }
116 | checkFactorial(fact: fact, n: ((1 as Int) << power) - 1)
117 | }
118 |
119 | func testDivision() {
120 | var divisors: [BigUInt] = []
121 | func balancedFactorial(level: Int, offset: Int = 0) -> BigUInt {
122 | if level == 0 {
123 | return BigUInt(offset == 0 ? 1 : offset)
124 | }
125 | let a = balancedFactorial(level: level - 1, offset: 2 * offset)
126 | let b = balancedFactorial(level: level - 1, offset: 2 * offset + 1)
127 | let p = a * b
128 | if level >= 10 { divisors.append(p) }
129 | return p
130 | }
131 |
132 | let power = 14
133 |
134 | let fact = balancedFactorial(level: power)
135 | print("Performing \(divisors.count) divisions with digit counts (\(fact.words.count) / (\(divisors[0].words.count)...\(divisors[divisors.count - 1].words.count))")
136 | var divs: [BigUInt] = []
137 | var mods: [BigUInt] = []
138 | divs.reserveCapacity(divisors.count)
139 | mods.reserveCapacity(divisors.count)
140 | self.measure_(autostart: false) {
141 | divs.removeAll()
142 | mods.removeAll()
143 | self.startMeasuring()
144 | for divisor in divisors {
145 | let (div, mod) = fact.quotientAndRemainder(dividingBy: divisor)
146 | divs.append(div)
147 | mods.append(mod)
148 | }
149 | self.stopMeasuring()
150 | }
151 | for i in 0.. [BigUInt] {
158 | var rnd = PseudoRandomNumbers(seed: seed)
159 | return (0 ..< count).map { _ in BigUInt(words: (0 ..< words).map { _ in rnd.next()! }) }
160 | }
161 |
162 | func testSquareRoot() {
163 | let numbers = randomBigUInts(1000, seed: 42, withMaxWords: 60)
164 | var roots: [BigUInt] = []
165 | self.measure {
166 | roots.removeAll()
167 | for number in numbers {
168 | let root = number.squareRoot()
169 | roots.append(root)
170 | }
171 | }
172 |
173 | for i in 0.. = [2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, 521, 607, 1279, 2203, 2281]
220 | for exp in 1...1000 {
221 | let mersenne = BigUInt(1) << exp - 1
222 | XCTAssertEqual(mersenne.isPrime(), exponents.contains(exp), "\(exp) smells fishy")
223 | }
224 | // Seems legit. You win this round, evil magmaticians
225 | }
226 | }
227 | }
228 | #endif
229 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/Tools.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Tools.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2017-7-23.
6 | // Copyright © 2017 Károly Lőrentey. All rights reserved.
7 | //
8 |
9 | import BigInt
10 |
11 | @inline(never)
12 | func noop(_ value: T) {
13 | _ = value
14 | }
15 |
16 | // A basic low-quality random number generator.
17 | struct PseudoRandomNumbers: Sequence, IteratorProtocol {
18 | typealias Element = BigUInt.Word
19 | var last: Element
20 |
21 | init(seed: Element) {
22 | self.last = seed
23 | }
24 |
25 | mutating func next() -> Element? {
26 | // Constants are from Knuth's MMIX and Numerical Recipes, respectively
27 | let a: Element = (Element.bitWidth == 8 ? 6364136223846793005 : 1664525)
28 | let c: Element = (Element.bitWidth == 8 ? 1442695040888963407 : 1013904223)
29 | last = a &* last &+ c
30 | return last
31 | }
32 | }
33 |
34 | func convertWords(_ wideWords: S) -> [UInt] where S.Element == UInt64 {
35 | return wideWords.flatMap { $0.words }
36 | }
37 |
38 | extension String {
39 | func repeated(_ count: Int) -> String {
40 | var result = ""
41 | for _ in 0 ..< count {
42 | result += self
43 | }
44 | return result
45 | }
46 | }
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/Violet - Helpers/BitWidthTestCases.swift:
--------------------------------------------------------------------------------
1 | // This file was written by LiarPrincess for Violet - Python VM written in Swift.
2 | // https://github.com/LiarPrincess/Violet
3 |
4 | @testable import BigInt
5 |
6 | internal enum BitWidthTestCases {
7 |
8 | // MARK: - Smi
9 |
10 | internal typealias SmiTestCase = (value: Int, expected: Int)
11 |
12 | internal static let smi: [SmiTestCase] = [
13 | // zero
14 | (0, 1),
15 | // positive
16 | (1, 2),
17 | (2, 3),
18 | (3, 3),
19 | (4, 4),
20 | (5, 4),
21 | (6, 4),
22 | (7, 4),
23 | (8, 5),
24 | (9, 5),
25 | (10, 5),
26 | (11, 5),
27 | (12, 5),
28 | (13, 5),
29 | (14, 5),
30 | (15, 5),
31 | // negative
32 | (-1, 1),
33 | (-2, 2),
34 | (-3, 3),
35 | (-4, 3),
36 | (-5, 4),
37 | (-6, 4),
38 | (-7, 4),
39 | (-8, 4),
40 | (-9, 5),
41 | (-10, 5),
42 | (-11, 5),
43 | (-12, 5),
44 | (-13, 5),
45 | (-14, 5),
46 | (-15, 5)
47 | ]
48 |
49 | // MARK: - Powers of 2
50 |
51 | internal typealias PowerTestCase = (value: Int, power: Int, expected: Int)
52 |
53 | // +-----+-----------+-------+-------+
54 | // | dec | bin | power | bit |
55 | // | | | | width |
56 | // +-----+-----------+-------+-------+
57 | // | 1 | 0001 | 0 | 2 |
58 | // | 2 | 0010 | 1 | 3 |
59 | // | 4 | 0100 | 2 | 4 |
60 | // | 8 | 0000 1000 | 3 | 5 |
61 | // +-----+-----------+-------+-------+
62 | // TLDR: bitWidth = power + 2
63 | internal static let positivePowersOf2Correction = 2
64 |
65 | internal static var positivePowersOf2: [PowerTestCase] = {
66 | var result = [PowerTestCase]()
67 |
68 | for (power, value) in allPositivePowersOf2(type: Int.self) {
69 | let bitWidth = power + Self.positivePowersOf2Correction
70 | let tuple = (value, power, bitWidth)
71 | result.append(tuple)
72 | }
73 |
74 | return result
75 | }()
76 |
77 | // +-----+------+-------+-------+
78 | // | dec | bin | power | bit |
79 | // | | | | width |
80 | // +-----+------+-------+-------+
81 | // | -1 | 1111 | 0 | 1 |
82 | // | -2 | 1110 | 1 | 2 |
83 | // | -4 | 1100 | 2 | 3 |
84 | // | -8 | 1000 | 3 | 4 |
85 | // +-----+------+-------+-------+
86 | // TLDR: bitWidth = power + 1
87 | internal static let negativePowersOf2Correction = 1
88 |
89 | internal static var negativePowersOf2: [PowerTestCase] = {
90 | var result = [PowerTestCase]()
91 |
92 | for (power, value) in allNegativePowersOf2(type: Int.self) {
93 | let bitWidth = power + Self.negativePowersOf2Correction
94 | let tuple = (value, power, bitWidth)
95 | result.append(tuple)
96 | }
97 |
98 | return result
99 | }()
100 | }
101 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/Violet - Helpers/GenerateValues.swift:
--------------------------------------------------------------------------------
1 | // This file was written by LiarPrincess for Violet - Python VM written in Swift.
2 | // https://github.com/LiarPrincess/Violet
3 |
4 | @testable import BigInt
5 |
6 | // MARK: - Int
7 |
8 | /// Will return `2 * countButNotReally + 3` values (don't ask).
9 | internal func generateIntValues(countButNotReally: Int) -> [Int] {
10 | return generateValues(
11 | countButNotReally: countButNotReally,
12 | type: Int.self
13 | )
14 | }
15 |
16 | private func generateValues(
17 | countButNotReally: Int,
18 | type: T.Type
19 | ) -> [T] {
20 | assert(countButNotReally > 0)
21 |
22 | var result = [T]()
23 | result.append(0)
24 | result.append(1)
25 | result.append(-1)
26 |
27 | let step = Int(T.max) / countButNotReally
28 |
29 | // 1st iteration will append 'T.min' and 'T.max'
30 | for i in 0.. BigInt {
63 | let sign: BigInt.Sign = self.isNegative ? .minus : .plus
64 | let magnitude = BigUInt(words: self.words)
65 | return BigInt(sign: sign, magnitude: magnitude)
66 | }
67 | }
68 |
69 | /// Will return `2 * countButNotReally + 5` values (don't ask).
70 | ///
71 | /// We do not return `BigInt` directly because in some cases
72 | /// (for example equality tests) you may want to create more than 1 value
73 | /// INDEPENDENTLY.
74 | internal func generateBigIntValues(countButNotReally: Int,
75 | maxWordCount: Int = 3) -> [BigIntPrototype] {
76 | var result = [BigIntPrototype]()
77 | result.append(BigIntPrototype(isNegative: false, words: [])) // 0
78 | result.append(BigIntPrototype(isNegative: false, words: [1])) // 1
79 | result.append(BigIntPrototype(isNegative: true, words: [1])) // -1
80 | result.append(BigIntPrototype(isNegative: false, words: [.max])) // Word.max
81 | result.append(BigIntPrototype(isNegative: true, words: [.max])) // -Word.max
82 |
83 | var word = BigInt.Word(2) // Start from '2' and go up
84 | for i in 0..: Sequence {
7 |
8 | internal typealias Element = (T, V)
9 |
10 | internal struct Iterator: IteratorProtocol {
11 |
12 | private let lhsValues: [T]
13 | private let rhsValues: [V]
14 |
15 | private var lhsIndex = 0
16 | private var rhsIndex = 0
17 |
18 | fileprivate init(lhs: [T], rhs: [V]) {
19 | self.lhsValues = lhs
20 | self.rhsValues = rhs
21 | }
22 |
23 | internal mutating func next() -> Element? {
24 | if self.lhsIndex == self.lhsValues.count {
25 | return nil
26 | }
27 |
28 | let lhs = self.lhsValues[self.lhsIndex]
29 | let rhs = self.rhsValues[self.rhsIndex]
30 |
31 | self.rhsIndex += 1
32 | if self.rhsIndex == self.rhsValues.count {
33 | self.lhsIndex += 1
34 | self.rhsIndex = 0
35 | }
36 |
37 | return (lhs, rhs)
38 | }
39 | }
40 |
41 | private let lhsValues: [T]
42 | private let rhsValues: [V]
43 |
44 | fileprivate init(lhs: [T], rhs: [V]) {
45 | self.lhsValues = lhs
46 | self.rhsValues = rhs
47 | }
48 |
49 | internal func makeIterator() -> Iterator {
50 | return Iterator(lhs: self.lhsValues, rhs: self.rhsValues)
51 | }
52 | }
53 |
54 | /// `[1, 2] -> [(1,1), (1,2), (2,1), (2,2)]`
55 | internal func allPossiblePairings(values: [T]) -> PossiblePairings {
56 | return PossiblePairings(lhs: values, rhs: values)
57 | }
58 |
59 | /// `[1, 2], [1, 2] -> [(1,1), (1,2), (2,1), (2,2)]`
60 | internal func allPossiblePairings(lhs: [T], rhs: [S]) -> PossiblePairings {
61 | return PossiblePairings(lhs: lhs, rhs: rhs)
62 | }
63 |
64 | // MARK: - Powers of 2
65 |
66 | internal typealias PowerOf2 = (power: Int, value: T)
67 |
68 | /// `1, 2, 4, 8, 16, 32, 64, 128, 256, 512, etc…`
69 | internal func allPositivePowersOf2(
70 | type: T.Type
71 | ) -> [PowerOf2] {
72 | var result = [PowerOf2]()
73 | result.reserveCapacity(T.bitWidth)
74 |
75 | var value = T(1)
76 | var power = 0
77 | result.append(PowerOf2(power: power, value: value))
78 |
79 | while true {
80 | let (newValue, overflow) = value.multipliedReportingOverflow(by: 2)
81 | if overflow {
82 | return result
83 | }
84 |
85 | value = newValue
86 | power += 1
87 | result.append(PowerOf2(power: power, value: value))
88 | }
89 | }
90 |
91 | /// `-1, -2, -4, -8, -16, -32, -64, -128, -256, -512, etc…`
92 | internal func allNegativePowersOf2(
93 | type: T.Type
94 | ) -> [PowerOf2] {
95 | assert(T.isSigned)
96 |
97 | var result = [PowerOf2]()
98 | result.reserveCapacity(T.bitWidth)
99 |
100 | var value = T(-1)
101 | var power = 0
102 | result.append(PowerOf2(power: power, value: value))
103 |
104 | while true {
105 | let (newValue, overflow) = value.multipliedReportingOverflow(by: 2)
106 | if overflow {
107 | return result
108 | }
109 |
110 | value = newValue
111 | power += 1
112 | result.append(PowerOf2(power: power, value: value))
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/Violet - Helpers/WordsTestCases.swift:
--------------------------------------------------------------------------------
1 | // This file was written by LiarPrincess for Violet - Python VM written in Swift.
2 | // https://github.com/LiarPrincess/Violet
3 |
4 | import XCTest
5 | @testable import BigInt
6 |
7 | // MARK: - Asserts
8 |
9 | internal func XCTAssertWords(_ value: BigInt,
10 | _ expected: [UInt],
11 | file: StaticString = #file,
12 | line: UInt = #line) {
13 | XCTAssertWords(
14 | value: String(value, radix: 10, uppercase: false),
15 | words: Array(value.words),
16 | expected: expected,
17 | file: file,
18 | line: line
19 | )
20 | }
21 |
22 | private func XCTAssertWords(value: String,
23 | words: [UInt],
24 | expected: [UInt],
25 | file: StaticString,
26 | line: UInt) {
27 | XCTAssertEqual(words.count, expected.count, "Count for \(value)", file: file, line: line)
28 | guard words.count == expected.count else {
29 | return
30 | }
31 |
32 | // deconstruction nested in deconstruction? eh…
33 | for (index, (w, e)) in zip(words, expected).enumerated() {
34 | XCTAssertEqual(w, e, "Word \(index) for \(value)", file: file, line: line)
35 | }
36 | }
37 |
38 | // MARK: - Test cases
39 |
40 | internal enum WordsTestCases {
41 |
42 | // MARK: - Zero
43 |
44 | internal static let zeroWords: [UInt] = [0]
45 |
46 | // MARK: - Int
47 |
48 | internal typealias IntTestCase = (value: Int, expected: [UInt])
49 |
50 | internal static let int: [IntTestCase] = {
51 | var result = [IntTestCase]()
52 |
53 | for int in generateIntValues(countButNotReally: 100) {
54 | let expected = Array(int.words)
55 | let tuple = IntTestCase(int, expected)
56 | result.append(tuple)
57 | }
58 |
59 | return result
60 | }()
61 |
62 | // MARK: - Heap positive
63 |
64 | internal typealias Word = BigInt.Word
65 |
66 | internal typealias HeapTestCase = (words: [Word], expected: [UInt])
67 |
68 | // words: 1000 0000
69 | internal static var heapPositive: [HeapTestCase] = {
70 | var result = [HeapTestCase]()
71 |
72 | for zeroWordCount in [1, 2] {
73 | let zeroWords = [Word](repeating: 0, count: zeroWordCount)
74 |
75 | for (_, value) in allPositivePowersOf2(type: Word.self) {
76 | let words = zeroWords + [value]
77 |
78 | let hasMsb1 = (value >> (Word.bitWidth - 1)) == 1
79 | let needsSignWord = hasMsb1
80 | let expectedWords = needsSignWord ? words + [0] : words
81 |
82 | let tuple = HeapTestCase(words, expectedWords)
83 | result.append(tuple)
84 | }
85 | }
86 |
87 | return result
88 | }()
89 |
90 | // MARK: - Heap negative
91 |
92 | // words: 1000 0000
93 | // invert: 0111 1111
94 | // complement: 1000 0000
95 | internal static var heapNegative_powerOf2: [HeapTestCase] = {
96 | var result = [HeapTestCase]()
97 |
98 | for zeroWordCount in [1, 2] {
99 | let zeroWords = [Word](repeating: 0, count: zeroWordCount)
100 |
101 | for (_, value) in allPositivePowersOf2(type: Word.self) {
102 | let words = zeroWords + [value]
103 |
104 | let valueCompliment = ~value + 1
105 | let expectedWords = zeroWords + [valueCompliment]
106 |
107 | let tuple = HeapTestCase(words, expectedWords)
108 | result.append(tuple)
109 | }
110 | }
111 |
112 | return result
113 | }()
114 |
115 | // case 1: most common
116 | // words: 0100 0001
117 | // invert: 1011 1110
118 | // complement: 1011 1111
119 | //
120 | // case 2: needs sign word
121 | // words: 1000 0001
122 | // invert: 0111 1110
123 | // complement: 1111 0111 1111
124 | internal static var heapNegative_notPowerOf2: [HeapTestCase] = {
125 | var result = [HeapTestCase]()
126 |
127 | for zeroWordCount in [1, 2] {
128 | // We are not power of '2', so we have to modify 'zeroWords'
129 | var zeroWords = [Word](repeating: 0, count: zeroWordCount)
130 | zeroWords[0] = 1
131 |
132 | let all1 = Word.max
133 | let complementWords = [Word](repeating: all1, count: zeroWordCount)
134 |
135 | for (_, value) in allPositivePowersOf2(type: Word.self) {
136 | let words = zeroWords + [value]
137 |
138 | let hasMsb1 = (value >> (Word.bitWidth - 1)) == 1
139 | let needsSignWord = hasMsb1
140 | let expectedWords = needsSignWord ?
141 | complementWords + [~value, all1] :
142 | complementWords + [~value]
143 |
144 | let tuple = HeapTestCase(words, expectedWords)
145 | result.append(tuple)
146 | }
147 | }
148 |
149 | return result
150 | }()
151 | }
152 |
153 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/Violet - Property testing/ApplyA_UndoA.swift:
--------------------------------------------------------------------------------
1 | // This file was written by LiarPrincess for Violet - Python VM written in Swift.
2 | // https://github.com/LiarPrincess/Violet
3 |
4 | import XCTest
5 | @testable import BigInt
6 |
7 | // swiftlint:disable type_name
8 |
9 | private typealias Word = BigInt.Word
10 |
11 | /// Operations for which exists 'reverse' operation that undoes its effect.
12 | /// For example for addition it is subtraction: `(n + x) - x = n`.
13 | class ApplyA_UndoA: XCTestCase {
14 |
15 | private lazy var values = generateBigIntValues(countButNotReally: 20)
16 | private lazy var pairs = allPossiblePairings(lhs: self.values, rhs: self.values)
17 |
18 | // MARK: - Tests
19 |
20 | func test_addSub() {
21 | for (lhsRaw, rhsRaw) in self.pairs {
22 | let lhs = self.create(lhsRaw)
23 | let rhs = self.create(rhsRaw)
24 |
25 | let expectedLhs = (lhs + rhs) - rhs
26 | XCTAssertEqual(lhs, expectedLhs, "\(lhs) +- \(rhs)")
27 | }
28 | }
29 |
30 | func test_mulDiv() {
31 | for (lhsRaw, rhsRaw) in self.pairs {
32 | if rhsRaw.isZero {
33 | continue
34 | }
35 |
36 | let lhs = self.create(lhsRaw)
37 | let rhs = self.create(rhsRaw)
38 |
39 | let expectedLhs = (lhs * rhs) / rhs
40 | XCTAssertEqual(lhs, expectedLhs, "\(lhs) */ \(rhs)")
41 | }
42 | }
43 |
44 | func test_shiftLeftRight() {
45 | for raw in self.values {
46 | let value = self.create(raw)
47 |
48 | let lessThanWord = 5
49 | let word = Word.bitWidth
50 | let moreThanWord = Word.bitWidth + Word.bitWidth - 7
51 |
52 | for count in [lessThanWord, word, moreThanWord] {
53 | let result = (value << count) >> count
54 | XCTAssertEqual(result, value, "\(value) <<>> \(count)")
55 | }
56 | }
57 | }
58 |
59 | func test_toStringInit() {
60 | for raw in self.values {
61 | let value = self.create(raw)
62 |
63 | for radix in [2, 5, 10, 16] {
64 | let string = String(value, radix: radix)
65 | guard let int = BigInt(string, radix: radix) else {
66 | XCTFail("string: \(string), radix: \(radix)")
67 | continue
68 | }
69 |
70 | XCTAssertEqual(int, value, "string: \(string)")
71 | }
72 | }
73 | }
74 |
75 | // MARK: - Helpers
76 |
77 | private func create(_ p: BigIntPrototype) -> BigInt {
78 | return p.create()
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/Violet/BigIntHashTests.swift:
--------------------------------------------------------------------------------
1 | // This file was written by LiarPrincess for Violet - Python VM written in Swift.
2 | // https://github.com/LiarPrincess/Violet
3 |
4 | import XCTest
5 | @testable import BigInt
6 |
7 | // Well… actually… hash and equatable
8 | class BigIntHashTests: XCTestCase {
9 |
10 | private let smis = generateIntValues(countButNotReally: 50)
11 | private let heaps = generateBigIntValues(countButNotReally: 50)
12 |
13 | // Values that are in both `smis` and `heaps`.
14 | private lazy var common: [BigInt] = {
15 | var result = [BigInt]()
16 | let smiSet = Set(self.smis)
17 |
18 | for p in self.heaps {
19 | let heap = p.create()
20 | if let int = Int(exactly: heap), smiSet.contains(int) {
21 | result.append(heap)
22 | }
23 | }
24 |
25 | return result
26 | }()
27 |
28 | private var scalars: [UnicodeScalar] = {
29 | let asciiStart: UInt8 = 0x21 // !
30 | let asciiEnd: UInt8 = 0x7e // ~
31 | let result = (asciiStart...asciiEnd).map { UnicodeScalar($0) }
32 | return result + result // to be sure that it is more than 'self.smis.count'
33 | }()
34 |
35 | // MARK: - Set
36 |
37 | func test_set_insertAndFind() {
38 | // Insert all of the values
39 | var set = Set()
40 | self.insert(&set, values: self.smis)
41 | self.insert(&set, values: self.heaps)
42 |
43 | let expectedCount = self.smis.count + self.heaps.count - self.common.count
44 | XCTAssertEqual(set.count, expectedCount)
45 |
46 | // Check if we can find them
47 | for value in self.smis {
48 | let int = self.create(value)
49 | XCTAssert(set.contains(int), "\(value)")
50 | }
51 |
52 | for value in self.heaps {
53 | let int = self.create(value)
54 | XCTAssert(set.contains(int), "\(int)")
55 | }
56 | }
57 |
58 | func test_set_insertAndRemove() {
59 | // Insert all of the values
60 | var set = Set()
61 | self.insert(&set, values: self.smis)
62 | self.insert(&set, values: self.heaps)
63 |
64 | let allCount = self.smis.count + self.heaps.count - self.common.count
65 | XCTAssertEqual(set.count, allCount)
66 |
67 | // And now remove them
68 | for value in self.smis {
69 | let int = self.create(value)
70 | let existing = set.remove(int)
71 | XCTAssertNotNil(existing, "Missing: \(value)")
72 | }
73 |
74 | let withoutSmiCount = self.heaps.count - self.common.count
75 | XCTAssertEqual(set.count, withoutSmiCount)
76 |
77 | for value in self.heaps {
78 | let int = self.create(value)
79 | let wasAlreadyRemoved = self.common.contains(int)
80 |
81 | if !wasAlreadyRemoved {
82 | let existing = set.remove(int)
83 | XCTAssertNotNil(existing, "Missing: \(int)")
84 | }
85 | }
86 |
87 | XCTAssert(set.isEmpty)
88 | }
89 |
90 | // MARK: - Dict
91 |
92 | func test_dict_insertAndFind() {
93 | // Insert all of the numbers to dict
94 | var dict = [BigInt: UnicodeScalar]()
95 | self.insert(&dict, values: zip(self.smis, self.scalars))
96 | self.insert(&dict, values: zip(self.heaps, self.scalars), excluding: self.common)
97 |
98 | let expectedCount = self.smis.count + self.heaps.count - self.common.count
99 | XCTAssertEqual(dict.count, expectedCount)
100 |
101 | // Check if we can find all of the elements
102 | for (value, char) in zip(self.smis, self.scalars) {
103 | let int = self.create(value)
104 |
105 | if let result = dict[int] {
106 | XCTAssertEqual(result, char, "key: \(int)")
107 | } else {
108 | XCTFail("missing: \(int)")
109 | }
110 | }
111 |
112 | for (value, char) in zip(self.heaps, self.scalars) {
113 | let int = self.create(value)
114 |
115 | if self.common.contains(int) {
116 | // It was already checked in 'smi' loop
117 | } else if let result = dict[int] {
118 | XCTAssertEqual(result, char, "key: \(int)")
119 | } else {
120 | XCTFail("missing: \(int)")
121 | }
122 | }
123 | }
124 |
125 | func test_dict_insertAndRemove() {
126 | // Insert all of the numbers to dict
127 | var dict = [BigInt: UnicodeScalar]()
128 | self.insert(&dict, values: zip(self.smis, self.scalars))
129 | self.insert(&dict, values: zip(self.heaps, self.scalars), excluding: self.common)
130 |
131 | let expectedCount = self.smis.count + self.heaps.count - self.common.count
132 | XCTAssertEqual(dict.count, expectedCount)
133 |
134 | // And now remove them
135 | for value in self.smis {
136 | let int = self.create(value)
137 | let existing = dict.removeValue(forKey: int)
138 | XCTAssertNotNil(existing, "Missing: \(value)")
139 | }
140 |
141 | let withoutSmiCount = self.heaps.count - self.common.count
142 | XCTAssertEqual(dict.count, withoutSmiCount)
143 |
144 | for value in self.heaps {
145 | let int = self.create(value)
146 | let wasAlreadyRemoved = self.common.contains(int)
147 |
148 | if !wasAlreadyRemoved {
149 | let existing = dict.removeValue(forKey: int)
150 | XCTAssertNotNil(existing, "Missing: \(int)")
151 | }
152 | }
153 |
154 | XCTAssert(dict.isEmpty)
155 | }
156 |
157 | func test_dict_insertReplaceAndFind() {
158 | // Insert all of the numbers to dict
159 | var dict = [BigInt: UnicodeScalar]()
160 | self.insert(&dict, values: zip(self.smis, self.scalars))
161 | self.insert(&dict, values: zip(self.heaps, self.scalars), excluding: self.common)
162 |
163 | let expectedCount = self.smis.count + self.heaps.count - self.common.count
164 | XCTAssertEqual(dict.count, expectedCount)
165 |
166 | // Replace the values
167 | let reversedScalars = self.scalars.reversed()
168 | self.insert(&dict, values: zip(self.smis, reversedScalars))
169 | self.insert(&dict, values: zip(self.heaps, reversedScalars), excluding: self.common)
170 |
171 | // Count should have not changed
172 | XCTAssertEqual(dict.count, expectedCount)
173 |
174 | // Check if we can find all of the elements
175 | for (value, char) in zip(self.smis, reversedScalars) {
176 | let int = self.create(value)
177 |
178 | if let result = dict[int] {
179 | XCTAssertEqual(result, char, "key: \(int)")
180 | } else {
181 | XCTFail("missing: \(int)")
182 | }
183 | }
184 |
185 | for (value, char) in zip(self.heaps, reversedScalars) {
186 | let int = self.create(value)
187 |
188 | if self.common.contains(int) {
189 | // It was already checked in 'smi' loop
190 | } else if let result = dict[int] {
191 | XCTAssertEqual(result, char, "key: \(int)")
192 | } else {
193 | XCTFail("missing: \(int)")
194 | }
195 | }
196 | }
197 |
198 | // MARK: - Helpers
199 |
200 | private func insert(_ set: inout Set, values: [Int]) {
201 | for value in values {
202 | let int = self.create(value)
203 | set.insert(int)
204 | }
205 | }
206 |
207 | private func insert(_ set: inout Set, values: [BigIntPrototype]) {
208 | for value in values {
209 | let int = self.create(value)
210 | set.insert(int)
211 | }
212 | }
213 |
214 | private func insert(
215 | _ dict: inout [BigInt: UnicodeScalar],
216 | values: S
217 | ) where S.Element == (Int, UnicodeScalar) {
218 | for (value, char) in values {
219 | let int = self.create(value)
220 | dict[int] = char
221 | }
222 | }
223 |
224 | private func insert(
225 | _ dict: inout [BigInt: UnicodeScalar],
226 | values: S,
227 | excluding: [BigInt]
228 | ) where S.Element == (BigIntPrototype, UnicodeScalar) {
229 | for (value, char) in values {
230 | let int = self.create(value)
231 | if !excluding.contains(int) {
232 | dict[int] = char
233 | }
234 | }
235 | }
236 |
237 | private func create(_ value: Int) -> BigInt {
238 | return BigInt(value)
239 | }
240 |
241 | private func create(_ p: BigIntPrototype) -> BigInt {
242 | let heap = p.create()
243 | return BigInt(heap)
244 | }
245 | }
246 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/Violet/BigIntPowerTests.swift:
--------------------------------------------------------------------------------
1 | // This file was written by LiarPrincess for Violet - Python VM written in Swift.
2 | // https://github.com/LiarPrincess/Violet
3 |
4 | import XCTest
5 | @testable import BigInt
6 |
7 | class BigIntPowerTests: XCTestCase {
8 |
9 | // MARK: - Trivial base
10 |
11 | /// 0 ^ n = 0 (or sometimes 1)
12 | // func test_base_zero() {
13 | // let zero = BigInt(0)
14 | // let one = BigInt(1)
15 | //
16 | // for exponent in generateIntValues(countButNotReally: 100) {
17 | // let result = zero.power(exponent)
18 | //
19 | // // 0 ^ 0 = 1, otherwise 0
20 | // let expected = exponent == 0 ? one : zero
21 | // XCTAssertEqual(result, expected, "0 ^ \(exponent)")
22 | // }
23 | // }
24 |
25 | /// 1 ^ n = 1
26 | func test_base_one() {
27 | let one = BigInt(1)
28 |
29 | for exponent in generateIntValues(countButNotReally: 100) {
30 | let result = one.power(exponent)
31 | let expected = one
32 | XCTAssertEqual(result, expected, "1 ^ \(exponent)")
33 | }
34 | }
35 |
36 | /// (-1) ^ n = (-1) or 1
37 | func test_base_minusOne() {
38 | let plusOne = BigInt(1)
39 | let minusOne = BigInt(-1)
40 |
41 | for exponent in generateIntValues(countButNotReally: 100) {
42 | let result = minusOne.power(exponent)
43 |
44 | let expected = exponent.isMultiple(of: 2) ? plusOne : minusOne
45 | XCTAssertEqual(result, expected, "(-1) ^ \(exponent)")
46 | }
47 | }
48 |
49 | // MARK: - Trivial exponent
50 |
51 | /// n ^ 0 = 1
52 | func test_exponent_zero() {
53 | let zero = 0
54 | let one = BigInt(1)
55 |
56 | for smi in generateIntValues(countButNotReally: 100) {
57 | let base = BigInt(smi)
58 | let result = base.power(zero)
59 |
60 | let expected = one
61 | XCTAssertEqual(result, expected, "\(smi) ^ 1")
62 | }
63 | }
64 |
65 | /// n ^ 1 = n
66 | func test_exponent_one() {
67 | let one = 1
68 |
69 | for smi in generateIntValues(countButNotReally: 100) {
70 | let base = BigInt(smi)
71 | let result = base.power(one)
72 |
73 | let expected = base
74 | XCTAssertEqual(result, expected, "\(smi) ^ 1")
75 | }
76 | }
77 |
78 | func test_exponent_two() {
79 | let two = 2
80 |
81 | for p in generateBigIntValues(countButNotReally: 2) {
82 | let baseHeap = BigIntPrototype(isNegative: false, words: p.words)
83 | let base = baseHeap.create()
84 | let result = base.power(two)
85 |
86 | let expected = base * base
87 | XCTAssertEqual(result, expected, "\(base) ^ 2")
88 | }
89 | }
90 |
91 | func test_exponent_three() {
92 | let three = 3
93 |
94 | for p in generateBigIntValues(countButNotReally: 2) {
95 | let baseHeap = BigIntPrototype(isNegative: false, words: p.words)
96 | let base = baseHeap.create()
97 | let result = base.power(three)
98 |
99 | let expected = base * base * base
100 | XCTAssertEqual(result, expected, "\(base) ^ 3")
101 | }
102 | }
103 |
104 | // MARK: - Smi
105 |
106 | func test_againstFoundationPow() {
107 | // THIS IS NOT A PERFECT TEST!
108 | // It is 'good enough' to be usable, but don't think about it too much!
109 | let mantissaCount = Double.significandBitCount // well… technically '+1'
110 | let maxExactlyRepresentable = UInt(pow(Double(2), Double(mantissaCount)))
111 |
112 | // 'Int32 ^ 2' has greater possibility of being in 'Double' range than 'Int'
113 | var values = [Int32]()
114 |
115 | for value in generateIntValues(countButNotReally: 20) {
116 | if let i32 = Int32(exactly: value) {
117 | values.append(i32)
118 | }
119 | }
120 |
121 | for i in -10...10 {
122 | values.append(Int32(i))
123 | }
124 |
125 | for (baseSmi, expSmiSigned) in allPossiblePairings(values: values) {
126 | let expSmi = expSmiSigned.magnitude
127 |
128 | guard let baseDouble = Double(exactly: baseSmi),
129 | let expDouble = Double(exactly: expSmi) else {
130 | continue
131 | }
132 |
133 | let expectedDouble = pow(baseDouble, expDouble)
134 | guard let expectedInt = Int(exactly: expectedDouble),
135 | expectedInt.magnitude < maxExactlyRepresentable else {
136 | continue
137 | }
138 |
139 | // Some tests will actually get here, not a lot, but some
140 | let base = BigInt(baseSmi)
141 | let exp = Int(expSmi)
142 | let result = base.power(exp)
143 |
144 | let expected = BigInt(expectedInt)
145 | XCTAssertEqual(result, expected, "\(baseSmi) ^ \(expSmi)")
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/Violet/BigIntPropertyTests.swift:
--------------------------------------------------------------------------------
1 | // This file was written by LiarPrincess for Violet - Python VM written in Swift.
2 | // https://github.com/LiarPrincess/Violet
3 |
4 | import XCTest
5 | @testable import BigInt
6 |
7 | private typealias Word = BigInt.Word
8 |
9 | class BigIntPropertyTests: XCTestCase {
10 |
11 | // MARK: - Description
12 |
13 | func test_description() {
14 | for int in generateIntValues(countButNotReally: 100) {
15 | let value = BigInt(int)
16 | XCTAssertEqual(value.description, int.description, "\(int)")
17 | }
18 | }
19 |
20 | // MARK: - Words
21 |
22 | // func test_words_zero() {
23 | // let value = BigInt(0)
24 | // XCTAssertWords(value, WordsTestCases.zeroWords)
25 | // }
26 | //
27 | // func test_words_int() {
28 | // for (value, expected) in WordsTestCases.int {
29 | // let bigInt = BigInt(value)
30 | // XCTAssertWords(bigInt, expected)
31 | // }
32 | // }
33 |
34 | func test_words_multipleWords_positive() {
35 | for (words, expected) in WordsTestCases.heapPositive {
36 | let heap = BigIntPrototype(isNegative: false, words: words)
37 | let bigInt = heap.create()
38 | XCTAssertWords(bigInt, expected)
39 | }
40 | }
41 |
42 | // func test_words_multipleWords_negative_powerOf2() {
43 | // for (words, expected) in WordsTestCases.heapNegative_powerOf2 {
44 | // let heap = BigIntPrototype(isNegative: true, words: words)
45 | // let bigInt = heap.create()
46 | // XCTAssertWords(bigInt, expected)
47 | // }
48 | // }
49 |
50 | func test_words_multipleWords_negative_notPowerOf2() {
51 | for (words, expected) in WordsTestCases.heapNegative_notPowerOf2 {
52 | let heap = BigIntPrototype(isNegative: true, words: words)
53 | let bigInt = heap.create()
54 | XCTAssertWords(bigInt, expected)
55 | }
56 | }
57 |
58 | // MARK: - Bit width
59 |
60 | // func test_bitWidth_trivial() {
61 | // let zero = BigInt(0)
62 | // XCTAssertEqual(zero.bitWidth, 1) // 0 is just 0
63 | //
64 | // let plus1 = BigInt(1)
65 | // XCTAssertEqual(plus1.bitWidth, 2) // 1 needs '0' prefix -> '01'
66 | //
67 | // let minus1 = BigInt(-1)
68 | // XCTAssertEqual(minus1.bitWidth, 1) // -1 is just 1
69 | // }
70 |
71 | func test_bitWidth_positivePowersOf2() {
72 | for (int, power, expected) in BitWidthTestCases.positivePowersOf2 {
73 | let bigInt = BigInt(int)
74 | XCTAssertEqual(bigInt.bitWidth, expected, "for \(int) (2^\(power))")
75 | }
76 | }
77 |
78 | // func test_bitWidth_negativePowersOf2() {
79 | // for (int, power, expected) in BitWidthTestCases.negativePowersOf2 {
80 | // let bigInt = BigInt(int)
81 | // XCTAssertEqual(bigInt.bitWidth, expected, "for \(int) (2^\(power))")
82 | // }
83 | // }
84 | //
85 | // func test_bitWidth_smiTestCases() {
86 | // for (value, expected) in BitWidthTestCases.smi {
87 | // let bigInt = BigInt(value)
88 | // XCTAssertEqual(bigInt.bitWidth, expected, "\(value)")
89 | // }
90 | // }
91 |
92 | func test_bitWidth_multipleWords_positivePowersOf2() {
93 | let correction = BitWidthTestCases.positivePowersOf2Correction
94 |
95 | for zeroWordCount in [1, 2] {
96 | let zeroWords = [Word](repeating: 0, count: zeroWordCount)
97 | let zeroWordsBitWidth = zeroWordCount * Word.bitWidth
98 |
99 | for (power, value) in allPositivePowersOf2(type: Word.self) {
100 | let words = zeroWords + [value]
101 | let heap = BigIntPrototype(isNegative: false, words: words)
102 | let bigInt = heap.create()
103 |
104 | let expected = power + correction + zeroWordsBitWidth
105 | XCTAssertEqual(bigInt.bitWidth, expected, "\(heap)")
106 | }
107 | }
108 | }
109 |
110 | // func test_bitWidth_multipleWords_negativePowersOf2() {
111 | // let correction = BitWidthTestCases.negativePowersOf2Correction
112 | //
113 | // for zeroWordCount in [1, 2] {
114 | // let zeroWords = [Word](repeating: 0, count: zeroWordCount)
115 | // let zeroWordsBitWidth = zeroWordCount * Word.bitWidth
116 | //
117 | // for (power, value) in allPositivePowersOf2(type: Word.self) {
118 | // let words = zeroWords + [value]
119 | // let heap = BigIntPrototype(isNegative: true, words: words)
120 | // let bigInt = heap.create()
121 | //
122 | // let expected = power + correction + zeroWordsBitWidth
123 | // XCTAssertEqual(bigInt.bitWidth, expected, "\(heap)")
124 | // }
125 | // }
126 | // }
127 |
128 | // MARK: - Trailing zero bit count
129 |
130 | func test_trailingZeroBitCount_zero() {
131 | let zero = BigInt(0)
132 | XCTAssertEqual(zero.trailingZeroBitCount, 0)
133 | }
134 |
135 | func test_trailingZeroBitCount_int() {
136 | for raw in generateIntValues(countButNotReally: 100) {
137 | if raw == 0 {
138 | continue
139 | }
140 |
141 | let int = BigInt(raw)
142 | let result = int.trailingZeroBitCount
143 |
144 | let expected = raw.trailingZeroBitCount
145 | XCTAssertEqual(result, expected)
146 | }
147 | }
148 |
149 | func test_trailingZeroBitCount_heap_nonZeroFirstWord() {
150 | for p in generateBigIntValues(countButNotReally: 100, maxWordCount: 3) {
151 | if p.isZero {
152 | continue
153 | }
154 |
155 | // We have separate test for numbers that have '0' last word
156 | if p.words[0] == 0 {
157 | continue
158 | }
159 |
160 | let int = p.create()
161 | let result = int.trailingZeroBitCount
162 |
163 | let expected = p.words[0].trailingZeroBitCount
164 | XCTAssertEqual(result, expected)
165 | }
166 | }
167 |
168 | func test_trailingZeroBitCount_heap_zeroFirstWord() {
169 | for p in generateBigIntValues(countButNotReally: 100, maxWordCount: 3) {
170 | if p.isZero {
171 | continue
172 | }
173 |
174 | guard p.words.count > 1 else {
175 | continue
176 | }
177 |
178 | var words = p.words
179 | words[0] = 0
180 |
181 | let heap = BigIntPrototype(isNegative: p.isNegative, words: words)
182 | let int = heap.create()
183 | let result = int.trailingZeroBitCount
184 |
185 | let expected = Word.bitWidth + p.words[1].trailingZeroBitCount
186 | XCTAssertEqual(result, expected)
187 | }
188 | }
189 |
190 | // MARK: - Magnitude
191 |
192 | func test_magnitude_int() {
193 | for raw in generateIntValues(countButNotReally: 100) {
194 | let int = BigInt(raw)
195 | let magnitude = int.magnitude
196 |
197 | let expected = raw.magnitude
198 | XCTAssert(magnitude == expected, "\(raw)")
199 | }
200 | }
201 |
202 | func test_magnitude_heap() {
203 | for p in generateBigIntValues(countButNotReally: 100) {
204 | if p.isZero {
205 | continue
206 | }
207 |
208 | let positiveHeap = BigIntPrototype(isNegative: false, words: p.words)
209 | let positive = positiveHeap.create()
210 |
211 | let negativeHeap = BigIntPrototype(isNegative: true, words: p.words)
212 | let negative = negativeHeap.create()
213 |
214 | XCTAssertEqual(positive.magnitude, negative.magnitude)
215 | }
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/Tests/BigIntTests/WordTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // WordTests.swift
3 | // BigInt
4 | //
5 | // Created by Károly Lőrentey on 2017-7-26.
6 | // Copyright © 2017 Károly Lőrentey. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import BigInt
11 |
12 | // TODO: Return to `where Word.Magnitude == Word` when SR-13491 is resolved
13 | struct TestDivision {
14 | static func testDivision(_ u: (high: Word, low: Word.Magnitude), _ v: Word) {
15 | let (div, mod) = v.fastDividingFullWidth(u)
16 | var (ph, pl) = div.multipliedFullWidth(by: v)
17 | let (s, o) = pl.addingReportingOverflow((mod as! Word.Magnitude))
18 | pl = s
19 | if o { ph += Word(1) }
20 |
21 | if mod >= v {
22 | XCTFail("For u = \(u), v = \(v): u mod v = \(mod), which is greater than v")
23 | }
24 |
25 | func message() -> String {
26 | let uhs = String(u.high, radix: 16)
27 | let uls = String(u.low, radix: 16)
28 | let vs = String(v, radix: 16)
29 | let divs = String(div, radix: 16)
30 | let mods = String(mod, radix: 16)
31 | let phs = String(ph, radix: 16)
32 | let pls = String(pl, radix: 16)
33 | return "(\(uhs),\(uls)) / \(vs) = (\(divs), \(mods)), but div * v + mod = (\(phs),\(pls))"
34 | }
35 | XCTAssertEqual(ph, u.high, message())
36 | XCTAssertEqual(pl, u.low, message())
37 | }
38 |
39 | static func test() {
40 | testDivision((0, 0), 2)
41 | testDivision((0, 1), 2)
42 | testDivision((1, 0), 2)
43 | testDivision((8, 0), 136)
44 | testDivision((128, 0), 136)
45 | testDivision((2, 0), 35)
46 | testDivision((7, 12), 19)
47 | }
48 | }
49 |
50 | class WordTests: XCTestCase {
51 | func testFullDivide() {
52 | TestDivision.test()
53 | TestDivision.test()
54 | TestDivision.test()
55 | TestDivision.test()
56 | TestDivision.test()
57 |
58 | #if false
59 | typealias Word = UInt8
60 | for v in 1 ... Word.max {
61 | for u1 in 0 ..< v {
62 | for u0 in 0 ..< Word.max {
63 | TestDivision.testDivision((u1, u0), v)
64 | }
65 | }
66 | }
67 | #endif
68 | }
69 |
70 | func testConversion() {
71 | enum Direction {
72 | case unitsToWords
73 | case wordsToUnits
74 | case both
75 | }
76 | func test
77 | (direction: Direction = .both,
78 | words: [Word], of wtype: Word.Type = Word.self,
79 | units: [Unit], of utype: Unit.Type = Unit.self,
80 | file: StaticString = #file, line: UInt = #line) {
81 | switch direction {
82 | case .wordsToUnits, .both:
83 | let actualUnits = [Unit](Units(of: Unit.self, words))
84 | XCTAssertEqual(actualUnits, units, "words -> units", file: file, line: line)
85 | default:
86 | break
87 | }
88 | switch direction {
89 | case .unitsToWords, .both:
90 | var it = units.makeIterator()
91 | let actualWords = [Word](count: units.count, generator: { () -> Unit? in it.next() })
92 | XCTAssertEqual(actualWords, words, "units -> words", file: file, line: line)
93 | default:
94 | break
95 | }
96 | }
97 |
98 |
99 | test(words: [], of: UInt8.self,
100 | units: [], of: UInt8.self)
101 | test(words: [0x01], of: UInt8.self,
102 | units: [0x01], of: UInt8.self)
103 | test(words: [0x01, 0x02], of: UInt8.self,
104 | units: [0x02, 0x01], of: UInt8.self)
105 |
106 | test(words: [], of: UInt8.self,
107 | units: [], of: UInt16.self)
108 | test(direction: .unitsToWords,
109 | words: [0x01, 0x00], of: UInt8.self,
110 | units: [0x0001], of: UInt16.self)
111 | test(direction: .wordsToUnits,
112 | words: [0x01], of: UInt8.self,
113 | units: [0x0001], of: UInt16.self)
114 | test(words: [0x01, 0x02], of: UInt8.self,
115 | units: [0x0201], of: UInt16.self)
116 | test(direction: .wordsToUnits,
117 | words: [0x01, 0x02, 0x03], of: UInt8.self,
118 | units: [0x0003, 0x0201], of: UInt16.self)
119 | test(direction: .unitsToWords,
120 | words: [0x01, 0x02, 0x03, 0x00], of: UInt8.self,
121 | units: [0x0003, 0x0201], of: UInt16.self)
122 |
123 | test(words: [], of: UInt16.self,
124 | units: [], of: UInt8.self)
125 | test(words: [0x1234], of: UInt16.self,
126 | units: [0x12, 0x34], of: UInt8.self)
127 | test(words: [0x5678, 0x1234], of: UInt16.self,
128 | units: [0x12, 0x34, 0x56, 0x78], of: UInt8.self)
129 | test(direction: .unitsToWords,
130 | words: [0x789A, 0x3456, 0x12], of: UInt16.self,
131 | units: [0x12, 0x34, 0x56, 0x78, 0x9A], of: UInt8.self)
132 | test(direction: .wordsToUnits,
133 | words: [0x789A, 0x3456, 0x12], of: UInt16.self,
134 | units: [0x00, 0x12, 0x34, 0x56, 0x78, 0x9A], of: UInt8.self)
135 | }
136 | }
137 |
138 |
139 |
--------------------------------------------------------------------------------
/docs/Extensions.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Extensions Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
34 |
35 |
41 |
42 |
48 |
49 |
50 |
51 | BigInt Reference
52 |
53 | Extensions Reference
54 |
55 |
56 |
57 |
92 |
93 |
94 |
95 |
96 |
Extensions
97 |
The following extensions are available globally.
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | -
107 |
114 |
115 |
116 |
117 |
118 |
122 |
123 |
Declaration
124 |
125 |
Swift
126 |
extension BinaryFloatingPoint where RawExponent: FixedWidthInteger, RawSignificand: FixedWidthInteger
127 |
128 |
129 |
130 |
131 |
132 |
133 | -
134 |
135 |
136 |
137 |
138 | String
139 |
140 |
141 |
142 |
143 |
144 |
145 |
149 |
150 |
Declaration
151 |
152 |
Swift
153 |
extension String
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/docs/Structs/BigInt/Sign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Sign Enumeration Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
49 |
50 |
51 | BigInt Reference
52 |
53 | Sign Enumeration Reference
54 |
55 |
56 |
57 |
92 |
93 |
94 |
95 |
96 |
Sign
97 |
98 |
99 |
100 |
public enum Sign
101 |
102 |
103 |
104 |
Undocumented
105 |
106 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 |
120 |
121 | plus
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
Undocumented
130 |
131 |
132 |
133 |
Declaration
134 |
135 |
Swift
136 |
case plus
137 |
138 |
139 |
140 |
143 |
144 |
145 |
146 | -
147 |
148 |
149 |
150 |
151 | minus
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
Undocumented
160 |
161 |
162 |
163 |
Declaration
164 |
165 |
Swift
166 |
case minus
167 |
168 |
169 |
170 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
187 |
188 |
189 |
190 |
--------------------------------------------------------------------------------
/docs/badge.svg:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/docs/css/highlight.css:
--------------------------------------------------------------------------------
1 | /*! Jazzy - https://github.com/realm/jazzy
2 | * Copyright Realm Inc.
3 | * SPDX-License-Identifier: MIT
4 | */
5 | /* Credit to https://gist.github.com/wataru420/2048287 */
6 | .highlight .c {
7 | color: #999988;
8 | font-style: italic; }
9 |
10 | .highlight .err {
11 | color: #a61717;
12 | background-color: #e3d2d2; }
13 |
14 | .highlight .k {
15 | color: #000000;
16 | font-weight: bold; }
17 |
18 | .highlight .o {
19 | color: #000000;
20 | font-weight: bold; }
21 |
22 | .highlight .cm {
23 | color: #999988;
24 | font-style: italic; }
25 |
26 | .highlight .cp {
27 | color: #999999;
28 | font-weight: bold; }
29 |
30 | .highlight .c1 {
31 | color: #999988;
32 | font-style: italic; }
33 |
34 | .highlight .cs {
35 | color: #999999;
36 | font-weight: bold;
37 | font-style: italic; }
38 |
39 | .highlight .gd {
40 | color: #000000;
41 | background-color: #ffdddd; }
42 |
43 | .highlight .gd .x {
44 | color: #000000;
45 | background-color: #ffaaaa; }
46 |
47 | .highlight .ge {
48 | color: #000000;
49 | font-style: italic; }
50 |
51 | .highlight .gr {
52 | color: #aa0000; }
53 |
54 | .highlight .gh {
55 | color: #999999; }
56 |
57 | .highlight .gi {
58 | color: #000000;
59 | background-color: #ddffdd; }
60 |
61 | .highlight .gi .x {
62 | color: #000000;
63 | background-color: #aaffaa; }
64 |
65 | .highlight .go {
66 | color: #888888; }
67 |
68 | .highlight .gp {
69 | color: #555555; }
70 |
71 | .highlight .gs {
72 | font-weight: bold; }
73 |
74 | .highlight .gu {
75 | color: #aaaaaa; }
76 |
77 | .highlight .gt {
78 | color: #aa0000; }
79 |
80 | .highlight .kc {
81 | color: #000000;
82 | font-weight: bold; }
83 |
84 | .highlight .kd {
85 | color: #000000;
86 | font-weight: bold; }
87 |
88 | .highlight .kp {
89 | color: #000000;
90 | font-weight: bold; }
91 |
92 | .highlight .kr {
93 | color: #000000;
94 | font-weight: bold; }
95 |
96 | .highlight .kt {
97 | color: #445588; }
98 |
99 | .highlight .m {
100 | color: #009999; }
101 |
102 | .highlight .s {
103 | color: #d14; }
104 |
105 | .highlight .na {
106 | color: #008080; }
107 |
108 | .highlight .nb {
109 | color: #0086B3; }
110 |
111 | .highlight .nc {
112 | color: #445588;
113 | font-weight: bold; }
114 |
115 | .highlight .no {
116 | color: #008080; }
117 |
118 | .highlight .ni {
119 | color: #800080; }
120 |
121 | .highlight .ne {
122 | color: #990000;
123 | font-weight: bold; }
124 |
125 | .highlight .nf {
126 | color: #990000; }
127 |
128 | .highlight .nn {
129 | color: #555555; }
130 |
131 | .highlight .nt {
132 | color: #000080; }
133 |
134 | .highlight .nv {
135 | color: #008080; }
136 |
137 | .highlight .ow {
138 | color: #000000;
139 | font-weight: bold; }
140 |
141 | .highlight .w {
142 | color: #bbbbbb; }
143 |
144 | .highlight .mf {
145 | color: #009999; }
146 |
147 | .highlight .mh {
148 | color: #009999; }
149 |
150 | .highlight .mi {
151 | color: #009999; }
152 |
153 | .highlight .mo {
154 | color: #009999; }
155 |
156 | .highlight .sb {
157 | color: #d14; }
158 |
159 | .highlight .sc {
160 | color: #d14; }
161 |
162 | .highlight .sd {
163 | color: #d14; }
164 |
165 | .highlight .s2 {
166 | color: #d14; }
167 |
168 | .highlight .se {
169 | color: #d14; }
170 |
171 | .highlight .sh {
172 | color: #d14; }
173 |
174 | .highlight .si {
175 | color: #d14; }
176 |
177 | .highlight .sx {
178 | color: #d14; }
179 |
180 | .highlight .sr {
181 | color: #009926; }
182 |
183 | .highlight .s1 {
184 | color: #d14; }
185 |
186 | .highlight .ss {
187 | color: #990073; }
188 |
189 | .highlight .bp {
190 | color: #999999; }
191 |
192 | .highlight .vc {
193 | color: #008080; }
194 |
195 | .highlight .vg {
196 | color: #008080; }
197 |
198 | .highlight .vi {
199 | color: #008080; }
200 |
201 | .highlight .il {
202 | color: #009999; }
203 |
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIdentifier
6 | com.jazzy.bigint
7 | CFBundleName
8 | BigInt
9 | DocSetPlatformFamily
10 | bigint
11 | isDashDocset
12 |
13 | dashIndexFilePath
14 | index.html
15 | isJavaScriptEnabled
16 |
17 | DashDocSetFamily
18 | dashtoc
19 | DashDocSetFallbackURL
20 | https://attaswift.github.io/BigInt/reference/
21 |
22 |
23 |
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/Documents/Extensions.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Extensions Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
49 |
50 |
51 | BigInt Reference
52 |
53 | Extensions Reference
54 |
55 |
56 |
57 |
92 |
93 |
94 |
95 |
96 |
Extensions
97 |
The following extensions are available globally.
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | -
107 |
114 |
115 |
116 |
117 |
118 |
122 |
123 |
Declaration
124 |
125 |
Swift
126 |
extension BinaryFloatingPoint where RawExponent: FixedWidthInteger, RawSignificand: FixedWidthInteger
127 |
128 |
129 |
130 |
131 |
132 |
133 | -
134 |
135 |
136 |
137 |
138 | String
139 |
140 |
141 |
142 |
143 |
144 |
145 |
149 |
150 |
Declaration
151 |
152 |
Swift
153 |
extension String
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
171 |
172 |
173 |
174 |
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/Documents/Structs/BigInt/Sign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Sign Enumeration Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
49 |
50 |
51 | BigInt Reference
52 |
53 | Sign Enumeration Reference
54 |
55 |
56 |
57 |
92 |
93 |
94 |
95 |
96 |
Sign
97 |
98 |
99 |
100 |
public enum Sign
101 |
102 |
103 |
104 |
Undocumented
105 |
106 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 |
120 |
121 | plus
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
Undocumented
130 |
131 |
132 |
133 |
Declaration
134 |
135 |
Swift
136 |
case plus
137 |
138 |
139 |
140 |
143 |
144 |
145 |
146 | -
147 |
148 |
149 |
150 |
151 | minus
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
Undocumented
160 |
161 |
162 |
163 |
Declaration
164 |
165 |
Swift
166 |
case minus
167 |
168 |
169 |
170 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
187 |
188 |
189 |
190 |
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/Documents/css/highlight.css:
--------------------------------------------------------------------------------
1 | /*! Jazzy - https://github.com/realm/jazzy
2 | * Copyright Realm Inc.
3 | * SPDX-License-Identifier: MIT
4 | */
5 | /* Credit to https://gist.github.com/wataru420/2048287 */
6 | .highlight .c {
7 | color: #999988;
8 | font-style: italic; }
9 |
10 | .highlight .err {
11 | color: #a61717;
12 | background-color: #e3d2d2; }
13 |
14 | .highlight .k {
15 | color: #000000;
16 | font-weight: bold; }
17 |
18 | .highlight .o {
19 | color: #000000;
20 | font-weight: bold; }
21 |
22 | .highlight .cm {
23 | color: #999988;
24 | font-style: italic; }
25 |
26 | .highlight .cp {
27 | color: #999999;
28 | font-weight: bold; }
29 |
30 | .highlight .c1 {
31 | color: #999988;
32 | font-style: italic; }
33 |
34 | .highlight .cs {
35 | color: #999999;
36 | font-weight: bold;
37 | font-style: italic; }
38 |
39 | .highlight .gd {
40 | color: #000000;
41 | background-color: #ffdddd; }
42 |
43 | .highlight .gd .x {
44 | color: #000000;
45 | background-color: #ffaaaa; }
46 |
47 | .highlight .ge {
48 | color: #000000;
49 | font-style: italic; }
50 |
51 | .highlight .gr {
52 | color: #aa0000; }
53 |
54 | .highlight .gh {
55 | color: #999999; }
56 |
57 | .highlight .gi {
58 | color: #000000;
59 | background-color: #ddffdd; }
60 |
61 | .highlight .gi .x {
62 | color: #000000;
63 | background-color: #aaffaa; }
64 |
65 | .highlight .go {
66 | color: #888888; }
67 |
68 | .highlight .gp {
69 | color: #555555; }
70 |
71 | .highlight .gs {
72 | font-weight: bold; }
73 |
74 | .highlight .gu {
75 | color: #aaaaaa; }
76 |
77 | .highlight .gt {
78 | color: #aa0000; }
79 |
80 | .highlight .kc {
81 | color: #000000;
82 | font-weight: bold; }
83 |
84 | .highlight .kd {
85 | color: #000000;
86 | font-weight: bold; }
87 |
88 | .highlight .kp {
89 | color: #000000;
90 | font-weight: bold; }
91 |
92 | .highlight .kr {
93 | color: #000000;
94 | font-weight: bold; }
95 |
96 | .highlight .kt {
97 | color: #445588; }
98 |
99 | .highlight .m {
100 | color: #009999; }
101 |
102 | .highlight .s {
103 | color: #d14; }
104 |
105 | .highlight .na {
106 | color: #008080; }
107 |
108 | .highlight .nb {
109 | color: #0086B3; }
110 |
111 | .highlight .nc {
112 | color: #445588;
113 | font-weight: bold; }
114 |
115 | .highlight .no {
116 | color: #008080; }
117 |
118 | .highlight .ni {
119 | color: #800080; }
120 |
121 | .highlight .ne {
122 | color: #990000;
123 | font-weight: bold; }
124 |
125 | .highlight .nf {
126 | color: #990000; }
127 |
128 | .highlight .nn {
129 | color: #555555; }
130 |
131 | .highlight .nt {
132 | color: #000080; }
133 |
134 | .highlight .nv {
135 | color: #008080; }
136 |
137 | .highlight .ow {
138 | color: #000000;
139 | font-weight: bold; }
140 |
141 | .highlight .w {
142 | color: #bbbbbb; }
143 |
144 | .highlight .mf {
145 | color: #009999; }
146 |
147 | .highlight .mh {
148 | color: #009999; }
149 |
150 | .highlight .mi {
151 | color: #009999; }
152 |
153 | .highlight .mo {
154 | color: #009999; }
155 |
156 | .highlight .sb {
157 | color: #d14; }
158 |
159 | .highlight .sc {
160 | color: #d14; }
161 |
162 | .highlight .sd {
163 | color: #d14; }
164 |
165 | .highlight .s2 {
166 | color: #d14; }
167 |
168 | .highlight .se {
169 | color: #d14; }
170 |
171 | .highlight .sh {
172 | color: #d14; }
173 |
174 | .highlight .si {
175 | color: #d14; }
176 |
177 | .highlight .sx {
178 | color: #d14; }
179 |
180 | .highlight .sr {
181 | color: #009926; }
182 |
183 | .highlight .s1 {
184 | color: #d14; }
185 |
186 | .highlight .ss {
187 | color: #990073; }
188 |
189 | .highlight .bp {
190 | color: #999999; }
191 |
192 | .highlight .vc {
193 | color: #008080; }
194 |
195 | .highlight .vg {
196 | color: #008080; }
197 |
198 | .highlight .vi {
199 | color: #008080; }
200 |
201 | .highlight .il {
202 | color: #009999; }
203 |
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/Documents/img/carat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/docsets/BigInt.docset/Contents/Resources/Documents/img/carat.png
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/Documents/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/docsets/BigInt.docset/Contents/Resources/Documents/img/dash.png
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/Documents/img/gh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/docsets/BigInt.docset/Contents/Resources/Documents/img/gh.png
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/Documents/img/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/docsets/BigInt.docset/Contents/Resources/Documents/img/spinner.gif
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/Documents/js/jazzy.js:
--------------------------------------------------------------------------------
1 | // Jazzy - https://github.com/realm/jazzy
2 | // Copyright Realm Inc.
3 | // SPDX-License-Identifier: MIT
4 |
5 | window.jazzy = {'docset': false}
6 | if (typeof window.dash != 'undefined') {
7 | document.documentElement.className += ' dash'
8 | window.jazzy.docset = true
9 | }
10 | if (navigator.userAgent.match(/xcode/i)) {
11 | document.documentElement.className += ' xcode'
12 | window.jazzy.docset = true
13 | }
14 |
15 | function toggleItem($link, $content) {
16 | var animationDuration = 300;
17 | $link.toggleClass('token-open');
18 | $content.slideToggle(animationDuration);
19 | }
20 |
21 | function itemLinkToContent($link) {
22 | return $link.parent().parent().next();
23 | }
24 |
25 | // On doc load + hash-change, open any targetted item
26 | function openCurrentItemIfClosed() {
27 | if (window.jazzy.docset) {
28 | return;
29 | }
30 | var $link = $(`a[name="${location.hash.substring(1)}"]`).nextAll('.token');
31 | $content = itemLinkToContent($link);
32 | if ($content.is(':hidden')) {
33 | toggleItem($link, $content);
34 | }
35 | }
36 |
37 | $(openCurrentItemIfClosed);
38 | $(window).on('hashchange', openCurrentItemIfClosed);
39 |
40 | // On item link ('token') click, toggle its discussion
41 | $('.token').on('click', function(event) {
42 | if (window.jazzy.docset) {
43 | return;
44 | }
45 | var $link = $(this);
46 | toggleItem($link, itemLinkToContent($link));
47 |
48 | // Keeps the document from jumping to the hash.
49 | var href = $link.attr('href');
50 | if (history.pushState) {
51 | history.pushState({}, '', href);
52 | } else {
53 | location.hash = href;
54 | }
55 | event.preventDefault();
56 | });
57 |
58 | // Clicks on links to the current, closed, item need to open the item
59 | $("a:not('.token')").on('click', function() {
60 | if (location == this.href) {
61 | openCurrentItemIfClosed();
62 | }
63 | });
64 |
65 | // KaTeX rendering
66 | if ("katex" in window) {
67 | $($('.math').each( (_, element) => {
68 | katex.render(element.textContent, element, {
69 | displayMode: $(element).hasClass('m-block'),
70 | throwOnError: false,
71 | trust: true
72 | });
73 | }))
74 | }
75 |
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/Documents/js/jazzy.search.js:
--------------------------------------------------------------------------------
1 | // Jazzy - https://github.com/realm/jazzy
2 | // Copyright Realm Inc.
3 | // SPDX-License-Identifier: MIT
4 |
5 | $(function(){
6 | var $typeahead = $('[data-typeahead]');
7 | var $form = $typeahead.parents('form');
8 | var searchURL = $form.attr('action');
9 |
10 | function displayTemplate(result) {
11 | return result.name;
12 | }
13 |
14 | function suggestionTemplate(result) {
15 | var t = '';
16 | t += '' + result.name + '';
17 | if (result.parent_name) {
18 | t += '' + result.parent_name + '';
19 | }
20 | t += '
';
21 | return t;
22 | }
23 |
24 | $typeahead.one('focus', function() {
25 | $form.addClass('loading');
26 |
27 | $.getJSON(searchURL).then(function(searchData) {
28 | const searchIndex = lunr(function() {
29 | this.ref('url');
30 | this.field('name');
31 | this.field('abstract');
32 | for (const [url, doc] of Object.entries(searchData)) {
33 | this.add({url: url, name: doc.name, abstract: doc.abstract});
34 | }
35 | });
36 |
37 | $typeahead.typeahead(
38 | {
39 | highlight: true,
40 | minLength: 3,
41 | autoselect: true
42 | },
43 | {
44 | limit: 10,
45 | display: displayTemplate,
46 | templates: { suggestion: suggestionTemplate },
47 | source: function(query, sync) {
48 | const lcSearch = query.toLowerCase();
49 | const results = searchIndex.query(function(q) {
50 | q.term(lcSearch, { boost: 100 });
51 | q.term(lcSearch, {
52 | boost: 10,
53 | wildcard: lunr.Query.wildcard.TRAILING
54 | });
55 | }).map(function(result) {
56 | var doc = searchData[result.ref];
57 | doc.url = result.ref;
58 | return doc;
59 | });
60 | sync(results);
61 | }
62 | }
63 | );
64 | $form.removeClass('loading');
65 | $typeahead.trigger('focus');
66 | });
67 | });
68 |
69 | var baseURL = searchURL.slice(0, -"search.json".length);
70 |
71 | $typeahead.on('typeahead:select', function(e, result) {
72 | window.location = baseURL + result.url;
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/docs/docsets/BigInt.docset/Contents/Resources/docSet.dsidx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/docsets/BigInt.docset/Contents/Resources/docSet.dsidx
--------------------------------------------------------------------------------
/docs/docsets/BigInt.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/docsets/BigInt.tgz
--------------------------------------------------------------------------------
/docs/docsets/BigInt.xml:
--------------------------------------------------------------------------------
1 | https://attaswift.github.io/BigInt/reference/docsets/BigInt.tgz
2 |
--------------------------------------------------------------------------------
/docs/img/carat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/img/carat.png
--------------------------------------------------------------------------------
/docs/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/img/dash.png
--------------------------------------------------------------------------------
/docs/img/gh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/img/gh.png
--------------------------------------------------------------------------------
/docs/img/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/docs/img/spinner.gif
--------------------------------------------------------------------------------
/docs/js/jazzy.js:
--------------------------------------------------------------------------------
1 | // Jazzy - https://github.com/realm/jazzy
2 | // Copyright Realm Inc.
3 | // SPDX-License-Identifier: MIT
4 |
5 | window.jazzy = {'docset': false}
6 | if (typeof window.dash != 'undefined') {
7 | document.documentElement.className += ' dash'
8 | window.jazzy.docset = true
9 | }
10 | if (navigator.userAgent.match(/xcode/i)) {
11 | document.documentElement.className += ' xcode'
12 | window.jazzy.docset = true
13 | }
14 |
15 | function toggleItem($link, $content) {
16 | var animationDuration = 300;
17 | $link.toggleClass('token-open');
18 | $content.slideToggle(animationDuration);
19 | }
20 |
21 | function itemLinkToContent($link) {
22 | return $link.parent().parent().next();
23 | }
24 |
25 | // On doc load + hash-change, open any targetted item
26 | function openCurrentItemIfClosed() {
27 | if (window.jazzy.docset) {
28 | return;
29 | }
30 | var $link = $(`a[name="${location.hash.substring(1)}"]`).nextAll('.token');
31 | $content = itemLinkToContent($link);
32 | if ($content.is(':hidden')) {
33 | toggleItem($link, $content);
34 | }
35 | }
36 |
37 | $(openCurrentItemIfClosed);
38 | $(window).on('hashchange', openCurrentItemIfClosed);
39 |
40 | // On item link ('token') click, toggle its discussion
41 | $('.token').on('click', function(event) {
42 | if (window.jazzy.docset) {
43 | return;
44 | }
45 | var $link = $(this);
46 | toggleItem($link, itemLinkToContent($link));
47 |
48 | // Keeps the document from jumping to the hash.
49 | var href = $link.attr('href');
50 | if (history.pushState) {
51 | history.pushState({}, '', href);
52 | } else {
53 | location.hash = href;
54 | }
55 | event.preventDefault();
56 | });
57 |
58 | // Clicks on links to the current, closed, item need to open the item
59 | $("a:not('.token')").on('click', function() {
60 | if (location == this.href) {
61 | openCurrentItemIfClosed();
62 | }
63 | });
64 |
65 | // KaTeX rendering
66 | if ("katex" in window) {
67 | $($('.math').each( (_, element) => {
68 | katex.render(element.textContent, element, {
69 | displayMode: $(element).hasClass('m-block'),
70 | throwOnError: false,
71 | trust: true
72 | });
73 | }))
74 | }
75 |
--------------------------------------------------------------------------------
/docs/js/jazzy.search.js:
--------------------------------------------------------------------------------
1 | // Jazzy - https://github.com/realm/jazzy
2 | // Copyright Realm Inc.
3 | // SPDX-License-Identifier: MIT
4 |
5 | $(function(){
6 | var $typeahead = $('[data-typeahead]');
7 | var $form = $typeahead.parents('form');
8 | var searchURL = $form.attr('action');
9 |
10 | function displayTemplate(result) {
11 | return result.name;
12 | }
13 |
14 | function suggestionTemplate(result) {
15 | var t = '';
16 | t += '' + result.name + '';
17 | if (result.parent_name) {
18 | t += '' + result.parent_name + '';
19 | }
20 | t += '
';
21 | return t;
22 | }
23 |
24 | $typeahead.one('focus', function() {
25 | $form.addClass('loading');
26 |
27 | $.getJSON(searchURL).then(function(searchData) {
28 | const searchIndex = lunr(function() {
29 | this.ref('url');
30 | this.field('name');
31 | this.field('abstract');
32 | for (const [url, doc] of Object.entries(searchData)) {
33 | this.add({url: url, name: doc.name, abstract: doc.abstract});
34 | }
35 | });
36 |
37 | $typeahead.typeahead(
38 | {
39 | highlight: true,
40 | minLength: 3,
41 | autoselect: true
42 | },
43 | {
44 | limit: 10,
45 | display: displayTemplate,
46 | templates: { suggestion: suggestionTemplate },
47 | source: function(query, sync) {
48 | const lcSearch = query.toLowerCase();
49 | const results = searchIndex.query(function(q) {
50 | q.term(lcSearch, { boost: 100 });
51 | q.term(lcSearch, {
52 | boost: 10,
53 | wildcard: lunr.Query.wildcard.TRAILING
54 | });
55 | }).map(function(result) {
56 | var doc = searchData[result.ref];
57 | doc.url = result.ref;
58 | return doc;
59 | });
60 | sync(results);
61 | }
62 | }
63 | );
64 | $form.removeClass('loading');
65 | $typeahead.trigger('focus');
66 | });
67 | });
68 |
69 | var baseURL = searchURL.slice(0, -"search.json".length);
70 |
71 | $typeahead.on('typeahead:select', function(e, result) {
72 | window.location = baseURL + result.url;
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/docs/undocumented.json:
--------------------------------------------------------------------------------
1 | {
2 | "warnings": [
3 | {
4 | "file": "/Users/runner/work/BigInt/BigInt/Sources/BigInt.swift",
5 | "line": 30,
6 | "symbol": "BigInt.Sign",
7 | "symbol_kind": "source.lang.swift.decl.enum",
8 | "warning": "undocumented"
9 | },
10 | {
11 | "file": "/Users/runner/work/BigInt/BigInt/Sources/BigInt.swift",
12 | "line": 31,
13 | "symbol": "BigInt.Sign.plus",
14 | "symbol_kind": "source.lang.swift.decl.enumelement",
15 | "warning": "undocumented"
16 | },
17 | {
18 | "file": "/Users/runner/work/BigInt/BigInt/Sources/BigInt.swift",
19 | "line": 32,
20 | "symbol": "BigInt.Sign.minus",
21 | "symbol_kind": "source.lang.swift.decl.enumelement",
22 | "warning": "undocumented"
23 | },
24 | {
25 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Bitwise Ops.swift",
26 | "line": 50,
27 | "symbol": "BigInt.~(_:)",
28 | "symbol_kind": "source.lang.swift.decl.function.method.static",
29 | "warning": "undocumented"
30 | },
31 | {
32 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Bitwise Ops.swift",
33 | "line": 59,
34 | "symbol": "BigInt.&(_:_:)",
35 | "symbol_kind": "source.lang.swift.decl.function.method.static",
36 | "warning": "undocumented"
37 | },
38 | {
39 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Bitwise Ops.swift",
40 | "line": 76,
41 | "symbol": "BigInt.|(_:_:)",
42 | "symbol_kind": "source.lang.swift.decl.function.method.static",
43 | "warning": "undocumented"
44 | },
45 | {
46 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Bitwise Ops.swift",
47 | "line": 93,
48 | "symbol": "BigInt.^(_:_:)",
49 | "symbol_kind": "source.lang.swift.decl.function.method.static",
50 | "warning": "undocumented"
51 | },
52 | {
53 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Bitwise Ops.swift",
54 | "line": 110,
55 | "symbol": "BigInt.&=(_:_:)",
56 | "symbol_kind": "source.lang.swift.decl.function.method.static",
57 | "warning": "undocumented"
58 | },
59 | {
60 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Bitwise Ops.swift",
61 | "line": 114,
62 | "symbol": "BigInt.|=(_:_:)",
63 | "symbol_kind": "source.lang.swift.decl.function.method.static",
64 | "warning": "undocumented"
65 | },
66 | {
67 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Bitwise Ops.swift",
68 | "line": 118,
69 | "symbol": "BigInt.^=(_:_:)",
70 | "symbol_kind": "source.lang.swift.decl.function.method.static",
71 | "warning": "undocumented"
72 | },
73 | {
74 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Floating Point Conversion.swift",
75 | "line": 45,
76 | "symbol": "BinaryFloatingPoint.init(_:)",
77 | "symbol_kind": "source.lang.swift.decl.function.method.instance",
78 | "warning": "undocumented"
79 | },
80 | {
81 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Floating Point Conversion.swift",
82 | "line": 70,
83 | "symbol": "BinaryFloatingPoint.init(_:)",
84 | "symbol_kind": "source.lang.swift.decl.function.method.instance",
85 | "warning": "undocumented"
86 | },
87 | {
88 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Integer Conversion.swift",
89 | "line": 42,
90 | "symbol": "BigInt.init()",
91 | "symbol_kind": "source.lang.swift.decl.function.method.instance",
92 | "warning": "undocumented"
93 | },
94 | {
95 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
96 | "line": 109,
97 | "symbol": "BigUInt.>>=(_:_:)",
98 | "symbol_kind": "source.lang.swift.decl.function.method.static",
99 | "warning": "undocumented"
100 | },
101 | {
102 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
103 | "line": 121,
104 | "symbol": "BigUInt.<<=(_:_:)",
105 | "symbol_kind": "source.lang.swift.decl.function.method.static",
106 | "warning": "undocumented"
107 | },
108 | {
109 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
110 | "line": 129,
111 | "symbol": "BigUInt.>>(_:_:)",
112 | "symbol_kind": "source.lang.swift.decl.function.method.static",
113 | "warning": "undocumented"
114 | },
115 | {
116 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
117 | "line": 139,
118 | "symbol": "BigUInt.<<(_:_:)",
119 | "symbol_kind": "source.lang.swift.decl.function.method.static",
120 | "warning": "undocumented"
121 | },
122 | {
123 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
124 | "line": 168,
125 | "symbol": "BigInt.&<<(_:_:)",
126 | "symbol_kind": "source.lang.swift.decl.function.method.static",
127 | "warning": "undocumented"
128 | },
129 | {
130 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
131 | "line": 172,
132 | "symbol": "BigInt.&<<=(_:_:)",
133 | "symbol_kind": "source.lang.swift.decl.function.method.static",
134 | "warning": "undocumented"
135 | },
136 | {
137 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
138 | "line": 176,
139 | "symbol": "BigInt.&>>(_:_:)",
140 | "symbol_kind": "source.lang.swift.decl.function.method.static",
141 | "warning": "undocumented"
142 | },
143 | {
144 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
145 | "line": 180,
146 | "symbol": "BigInt.&>>=(_:_:)",
147 | "symbol_kind": "source.lang.swift.decl.function.method.static",
148 | "warning": "undocumented"
149 | },
150 | {
151 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
152 | "line": 184,
153 | "symbol": "BigInt.<<(_:_:)",
154 | "symbol_kind": "source.lang.swift.decl.function.method.static",
155 | "warning": "undocumented"
156 | },
157 | {
158 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
159 | "line": 189,
160 | "symbol": "BigInt.<<=(_:_:)",
161 | "symbol_kind": "source.lang.swift.decl.function.method.static",
162 | "warning": "undocumented"
163 | },
164 | {
165 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
166 | "line": 198,
167 | "symbol": "BigInt.>>(_:_:)",
168 | "symbol_kind": "source.lang.swift.decl.function.method.static",
169 | "warning": "undocumented"
170 | },
171 | {
172 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Shifts.swift",
173 | "line": 203,
174 | "symbol": "BigInt.>>=(_:_:)",
175 | "symbol_kind": "source.lang.swift.decl.function.method.static",
176 | "warning": "undocumented"
177 | },
178 | {
179 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Subtraction.swift",
180 | "line": 157,
181 | "symbol": "BigInt.negate()",
182 | "symbol_kind": "source.lang.swift.decl.function.method.instance",
183 | "warning": "undocumented"
184 | },
185 | {
186 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Words and Bits.swift",
187 | "line": 24,
188 | "symbol": "BigUInt.subscript(bitAt:)",
189 | "symbol_kind": "source.lang.swift.decl.function.subscript",
190 | "warning": "undocumented"
191 | },
192 | {
193 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Words and Bits.swift",
194 | "line": 78,
195 | "symbol": "BigInt.bitWidth",
196 | "symbol_kind": "source.lang.swift.decl.var.instance",
197 | "warning": "undocumented"
198 | },
199 | {
200 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Words and Bits.swift",
201 | "line": 83,
202 | "symbol": "BigInt.trailingZeroBitCount",
203 | "symbol_kind": "source.lang.swift.decl.var.instance",
204 | "warning": "undocumented"
205 | },
206 | {
207 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Words and Bits.swift",
208 | "line": 105,
209 | "symbol": "BigUInt.init(words:)",
210 | "symbol_kind": "source.lang.swift.decl.function.method.instance",
211 | "warning": "undocumented"
212 | },
213 | {
214 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Words and Bits.swift",
215 | "line": 188,
216 | "symbol": "BigInt.words",
217 | "symbol_kind": "source.lang.swift.decl.var.instance",
218 | "warning": "undocumented"
219 | },
220 | {
221 | "file": "/Users/runner/work/BigInt/BigInt/Sources/Words and Bits.swift",
222 | "line": 192,
223 | "symbol": "BigInt.init(words:)",
224 | "symbol_kind": "source.lang.swift.decl.function.method.instance",
225 | "warning": "undocumented"
226 | }
227 | ],
228 | "source_directory": "/Users/runner/work/BigInt/BigInt"
229 | }
--------------------------------------------------------------------------------
/images/BigInt.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/images/BigInt.sketch
--------------------------------------------------------------------------------
/images/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/attaswift/BigInt/99c4b9fb0f52dc9182aee106b07c3d205583b98c/images/banner.png
--------------------------------------------------------------------------------