Skip to content

Commit

Permalink
Release 1.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
leif-ibsen committed Aug 6, 2022
1 parent 1536608 commit f1244f8
Show file tree
Hide file tree
Showing 22 changed files with 22,198 additions and 146 deletions.
138 changes: 93 additions & 45 deletions README.md

Large diffs are not rendered by default.

921 changes: 921 additions & 0 deletions Sources/BigInt/BigFrac.swift

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Sources/BigInt/BigInt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2097,11 +2097,11 @@ public struct BInt: CustomStringConvertible, Comparable, Equatable, Hashable {
var u = BInt.ZERO
var v = BInt.ONE
var w = x
while w.isPositive {
while w.isNotZero {
let q = g / w
(a, b, g, u, v, w) = (u, v, w, a - q * u, b - q * v, g - q * w)
}
return (g, a, b)
return g.isNegative ? (-g, -a, -b) : (g, a, b)
}

/*
Expand Down
222 changes: 222 additions & 0 deletions Tests/BigIntTests/FractionTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
//
// FractionTest.swift
// BigIntTests
//
// Created by Leif Ibsen on 28/06/2022.
//

import XCTest

class FractionTest: XCTestCase {

func doTestInit(_ n: Int, _ d: Int) {
XCTAssertEqual(BFraction(n, d), BFraction(BInt(n), BInt(d)))
XCTAssertEqual(BFraction(n, d), BFraction(n, BInt(d)))
XCTAssertEqual(BFraction(n, d), BFraction(BInt(n), d))
}

func testInit() {
doTestInit(0, 1)
doTestInit(1, 1)
doTestInit(-1, 1)
doTestInit(0, -1)
doTestInit(1, -1)
doTestInit(-1, -1)
doTestInit(Int.max, Int.max)
doTestInit(Int.max, Int.min)
doTestInit(Int.min, Int.max)
doTestInit(Int.min, Int.min)
for _ in 0 ..< 10 {
let n = BInt(bitWidth: 100)
let d = BInt(bitWidth: 100) + 1
let f1 = BFraction(n, d)
XCTAssertEqual(f1.numerator.gcd(f1.denominator), BInt.ONE)
XCTAssert(f1.denominator.isPositive)
let f2 = BFraction(0, d)
XCTAssertEqual(f2.numerator, BInt.ZERO)
XCTAssertEqual(f2.denominator, BInt.ONE)
}
for _ in 0 ..< 10 {
let d = Double.random(in: -100.0 ... 100.0)
let f = BFraction(d)!
XCTAssertEqual(f.numerator.gcd(f.denominator), BInt.ONE)
XCTAssert(f.denominator.isPositive)
XCTAssert(f.abs <= 100)
}
XCTAssertNil(BFraction(0.0 / 0.0))
XCTAssertNil(BFraction(1.0 / 0.0))
XCTAssertEqual(BFraction(0.1)!, BFraction(
BInt("1000000000000000055511151231257827021181583404541015625")!, BInt(10) ** 55))
XCTAssertEqual(BFraction(0.1)!, BFraction(3602879701896397, 36028797018963968))
XCTAssertTrue(BFraction(0.0)!.isZero)
XCTAssertTrue(BFraction(-0.0)!.isZero)
}

func testCompare() {
for _ in 0 ..< 10 {
let n = BInt(bitWidth: 100)
let d = BInt(bitWidth: 100)
let g = n.gcd(d)
let f = BFraction(n, d)
let x = BFraction(0.1)!
XCTAssertTrue(f == BFraction(n / g, d / g))
XCTAssertTrue(f < f + x)
XCTAssertTrue(f > f - x)
}
XCTAssertTrue(BFraction(1, 10) < BFraction(0.1)!)
}

func testRounding() {
XCTAssertTrue(BFraction.ZERO.round() == 0)
XCTAssertTrue(BFraction.ZERO.truncate() == 0)
XCTAssertTrue(BFraction.ZERO.ceil() == 0)
XCTAssertTrue(BFraction.ZERO.floor() == 0)
XCTAssertTrue(BFraction.ONE.round() == 1)
XCTAssertTrue(BFraction.ONE.truncate() == 1)
XCTAssertTrue(BFraction.ONE.ceil() == 1)
XCTAssertTrue(BFraction.ONE.floor() == 1)
XCTAssertTrue(BFraction(-1, 1).round() == -1)
XCTAssertTrue(BFraction(-1, 1).truncate() == -1)
XCTAssertTrue(BFraction(-1, 1).ceil() == -1)
XCTAssertTrue(BFraction(-1, 1).floor() == -1)
for _ in 0 ..< 1000 {
let n = BInt(bitWidth: 100)
let d = BInt(bitWidth: 100) + 1
let f1 = BFraction(n, d)
let f2 = -f1
let round1 = f1.round()
let round2 = f2.round()
let trunc1 = f1.truncate()
let trunc2 = f2.truncate()
let ceil1 = f1.ceil()
let ceil2 = f2.ceil()
let floor1 = f1.floor()
let floor2 = f2.floor()
XCTAssertTrue(round1 == ceil1 || round1 == floor1)
XCTAssertTrue(round2 == ceil2 || round2 == floor2)
XCTAssertTrue(trunc1 == floor1)
XCTAssertTrue(trunc2 == ceil2)
XCTAssertTrue(ceil1 >= round1)
XCTAssertTrue(ceil1 >= trunc1)
XCTAssertTrue(ceil1 >= floor1)
XCTAssertTrue(floor1 <= round1)
XCTAssertTrue(floor1 <= trunc1)
XCTAssertTrue(floor1 <= ceil1)
XCTAssertTrue((round1 - f1).abs < 1)
XCTAssertTrue((round2 - f2).abs < 1)
XCTAssertTrue((trunc1 - f1).abs < 1)
XCTAssertTrue((trunc2 - f2).abs < 1)
XCTAssertTrue((ceil1 - f1).abs < 1)
XCTAssertTrue((ceil2 - f2).abs < 1)
XCTAssertTrue((floor1 - f1).abs < 1)
XCTAssertTrue((floor2 - f2).abs < 1)
}
}

func testArithmetic() {
// (a + b) * c = a * c + b * c
// (a - b) * c = a * c - b * c
// (a + b) / c = a / c + b / c
// (a - b) / c = a / c - b / c
for _ in 0 ..< 1000 {
let na = BInt(bitWidth: 200)
let da = BInt(bitWidth: 200) + 1
let nb = BInt(bitWidth: 200)
let db = BInt(bitWidth: 200) + 1
let nc = BInt(bitWidth: 100)
let dc = BInt(bitWidth: 100) + 1
let fa = BFraction(na, da)
let fb = BFraction(nb, db)
let fc = BFraction(nc, dc)
XCTAssertEqual((fa + fb) * fc, fa * fc + fb * fc)
XCTAssertEqual((fa - fb) * fc, fa * fc - fb * fc)
XCTAssertEqual((fa + fb) / fc, fa / fc + fb / fc)
XCTAssertEqual((fa - fb) / fc, fa / fc - fb / fc)
}
}

func testExp() {
// a ** 10 = a * a * a * a * a * a * a * a * a * a
let a = BFraction(BInt(bitWidth: 100), BInt(bitWidth: 100) + 1)
var x1 = a ** 10
var x2 = BFraction(1, 1)
for _ in 0 ..< 10 {
x2 *= a
}
XCTAssertEqual(x1, x2)
x1 = (-a) ** 10
x2 = BFraction(1, 1)
for _ in 0 ..< 10 {
x2 *= (-a)
}
XCTAssertEqual(x1, x2)
}

func doTestInt2(_ f: BFraction, _ x: Int) {
let fx = BFraction(x, 1)
let X = BInt(x)
XCTAssertEqual(f + fx, f + x)
XCTAssertEqual(f + fx, x + f)
XCTAssertEqual(f + fx, f + X)
XCTAssertEqual(f + fx, X + f)
XCTAssertEqual(f - fx, f - x)
XCTAssertEqual(f - fx, f - X)
XCTAssertEqual(f * fx, f * x)
XCTAssertEqual(f * fx, x * f)
XCTAssertEqual(f * fx, f * X)
XCTAssertEqual(f * fx, X * f)
if x != 0 {
XCTAssertEqual(f / fx, f / x)
XCTAssertEqual(f / fx, f / X)
}
XCTAssertEqual(f == fx, f == x)
XCTAssertEqual(f == fx, f == X)
XCTAssertEqual(f == fx, x == f)
XCTAssertEqual(f == fx, X == f)
XCTAssertEqual(f != fx, f != x)
XCTAssertEqual(f != fx, f != X)
XCTAssertEqual(f != fx, x != f)
XCTAssertEqual(f != fx, X != f)
XCTAssertEqual(f < fx, f < x)
XCTAssertEqual(f < fx, f < X)
XCTAssertEqual(f < fx, x > f)
XCTAssertEqual(f < fx, X > f)
XCTAssertEqual(f > fx, f > x)
XCTAssertEqual(f > fx, f > X)
XCTAssertEqual(f > fx, x < f)
XCTAssertEqual(f > fx, X < f)
XCTAssertEqual(f <= fx, f <= x)
XCTAssertEqual(f <= fx, f <= X)
XCTAssertEqual(f <= fx, x >= f)
XCTAssertEqual(f <= fx, X >= f)
XCTAssertEqual(f >= fx, f >= x)
XCTAssertEqual(f >= fx, f >= X)
XCTAssertEqual(f >= fx, x <= f)
XCTAssertEqual(f >= fx, X <= f)
}

func doTestInt1(_ f: BFraction) {
doTestInt2(f, 0)
doTestInt2(f, 1)
doTestInt2(f, -1)
doTestInt2(f, Int.max)
doTestInt2(f, Int.min)
}

func testInt() {
doTestInt1(BFraction.ZERO)
doTestInt1(BFraction.ONE)
doTestInt1(-BFraction.ONE)
doTestInt1(BFraction(Int.max, 1))
doTestInt1(BFraction(Int.min, 1))
}

func testConversion() {
let f1 = BFraction(1, 10)
let f2 = BFraction(0.1)!
XCTAssertEqual(f1.asDecimalString(digits: 1), "0.1")
XCTAssertEqual(f1.asDecimalString(digits: 55), "0.1000000000000000000000000000000000000000000000000000000")
XCTAssertEqual(f2.asDecimalString(digits: 1), "0.1")
XCTAssertEqual(f2.asDecimalString(digits: 55), "0.1000000000000000055511151231257827021181583404541015625")
}
}
55 changes: 55 additions & 0 deletions Tests/BigIntTests/GcdExtendedTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// GcdExtendedTest.swift
// BigIntTests
//
// Created by Leif Ibsen on 05/08/2022.
//

import XCTest

class GcdExtendedTest: XCTestCase {

override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}

override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}

func doTest(_ a: BInt, _ b: BInt) {
let g1 = a.gcd(b)
let g2 = a.gcd(-b)
let g3 = (-a).gcd(b)
let g4 = (-a).gcd(-b)
let (ge1, x1, y1) = a.gcdExtended(b)
let (ge2, x2, y2) = a.gcdExtended(-b)
let (ge3, x3, y3) = (-a).gcdExtended(b)
let (ge4, x4, y4) = (-a).gcdExtended(-b)
XCTAssertEqual(g1, ge1)
XCTAssertEqual(g2, ge2)
XCTAssertEqual(g3, ge3)
XCTAssertEqual(g4, ge4)
XCTAssertEqual(g1, a * x1 + b * y1)
XCTAssertEqual(g2, a * x2 + (-b) * y2)
XCTAssertEqual(g3, (-a) * x3 + b * y3)
XCTAssertEqual(g4, (-a) * x4 + (-b) * y4)
}

func test1() {
doTest(BInt.ZERO, BInt.ZERO)
doTest(BInt.ZERO, BInt.ONE)
doTest(BInt.ONE, BInt.ZERO)
doTest(BInt.ONE, BInt.ONE)
for _ in 0 ..< 100 {
let a = BInt(bitWidth: 100)
doTest(a, BInt.ONE)
doTest(a, BInt.TWO)
for _ in 0 ..< 100 {
let b = BInt(bitWidth: 100)
doTest(a, b)
}
}
}

}
2 changes: 1 addition & 1 deletion Tests/BigIntTests/PerformanceTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class PerformanceTest: XCTestCase {
let a1000 = BInt("3187705437890850041662973758105262878153514794996698172406519277876060364087986868049465132757493318066301987043192958841748826350731448419937544810921786918975580180410200630645469411588934094075222404396990984350815153163569041641732160380739556436955287671287935796642478260435292021117614349253825")!
let b1000 = BInt("9159373012373110951130589007821321098436345855865428979299172149373720601254669552044211236974571462005332583657082428026625366060511329189733296464187785766230514564038057370938741745651937465362625449921195096442684523511715110908407508139315000469851121118117438147266381183636498494901233452870695")!
let c2000 = BInt("1190583332681083129323588684910845359379915367459759242106618067261956856381281184752008892106576666833853411939711280970145570546868549934865719229538926506588929417873149597614787608112658086250354719939407543740242931571462165384138560315454455247539461818779966171917173966217706187439870264672508450210272481951994459523586160979759782950984370978171111340529321052541588344733968902238813379990628157732181128074253104347868153860527298911917508606081710893794973605227829729403843750412766366804402629686458092685235454222856584200220355212623917637542398554907364450159627359316156463617143173")!

override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
Expand Down
36 changes: 35 additions & 1 deletion docs/Structs.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
<li class="nav-group-name">
<a href="Structs.html">Structures</a>
<ul class="nav-group-tasks">
<li class="nav-group-task">
<a href="Structs/BFraction.html">BFraction</a>
</li>
<li class="nav-group-task">
<a href="Structs/BInt.html">BInt</a>
</li>
Expand Down Expand Up @@ -72,6 +75,37 @@ <h1>Structures</h1>
<section class="section task-group-section">
<div class="task-group">
<ul>
<li class="item">
<div>
<code>
<a name="/s:6BigInt9BFractionV"></a>
<a name="//apple_ref/swift/Struct/BFraction" class="dashAnchor"></a>
<a class="token" href="#/s:6BigInt9BFractionV">BFraction</a>
</code>
</div>
<div class="height-container">
<div class="pointer-container"></div>
<section class="section">
<div class="pointer"></div>
<div class="abstract">
<p>A signed fraction with numerator and denominator of unbounded size.
A BFraction value is represented by a BInt numerator and a BInt denominator.
The representation is normalized, so that numerator and denominator has no common divisors except 1.
The denominator is always positive, 0 has the representation 0/1</p>

<a href="Structs/BFraction.html" class="slightly-smaller">See more</a>
</div>
<div class="declaration">
<h4>Declaration</h4>
<div class="language">
<p class="aside-title">Swift</p>
<pre class="highlight swift"><code><span class="kd">public</span> <span class="kd">struct</span> <span class="kt">BFraction</span> <span class="p">:</span> <span class="kt">CustomStringConvertible</span><span class="p">,</span> <span class="kt">Comparable</span><span class="p">,</span> <span class="kt">Equatable</span></code></pre>

</div>
</div>
</section>
</div>
</li>
<li class="item">
<div>
<code>
Expand Down Expand Up @@ -111,7 +145,7 @@ <h4>Declaration</h4>
</section>
</section>
<section id="footer">
<p>&copy; 2022 <a class="link" href="" target="_blank" rel="external noopener"></a>. All rights reserved. (Last updated: 2022-06-17)</p>
<p>&copy; 2022 <a class="link" href="" target="_blank" rel="external noopener"></a>. All rights reserved. (Last updated: 2022-08-06)</p>
<p>Generated by <a class="link" href="https://github.com/realm/jazzy" target="_blank" rel="external noopener">jazzy ♪♫ v0.14.2</a>, a <a class="link" href="https://realm.io" target="_blank" rel="external noopener">Realm</a> project.</p>
</section>
</article>
Expand Down
Loading

0 comments on commit f1244f8

Please sign in to comment.