Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Probably not something you want... #5

Open
wants to merge 75 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
3ac3221
(refactor) add bigint
mredig Oct 25, 2024
27562cc
(refactor) import BigInt to most files
mredig Oct 25, 2024
e3e0723
(refactor) replace generic T with BigInt - also allow non reduce values
mredig Oct 25, 2024
c505610
(fix) algebraic field tests
mredig Oct 25, 2024
892c108
(fix) fraction tests
mredig Oct 25, 2024
c88f0b9
(fix) tests without generic typing
mredig Oct 25, 2024
b10ec6f
(fix) rational tests
mredig Oct 25, 2024
c3a39ae
(fix) signed numeric tests
mredig Oct 25, 2024
ce40702
(fix) tests without generic typing
mredig Oct 25, 2024
233fe70
(feat) test equatable when not normalized
mredig Oct 25, 2024
6d51d97
(refactor) add Sign
mredig Oct 26, 2024
09ec8d0
(refactor) numerator and denominator are always positive. Use `sign` …
mredig Oct 26, 2024
26e2f03
(fix) test without @testable
mredig Oct 26, 2024
9fedc68
(refactor) targetted coverage
mredig Oct 26, 2024
08410aa
(nit) remove all references to normalization, as it's no longer an issue
mredig Oct 26, 2024
61412d2
(refactor) consolidate (and fix) multiplication sign calculation
mredig Oct 26, 2024
d64f48c
(feat) improved code coverage
mredig Oct 26, 2024
d06261f
(refactor) rename to swift-big-rational
mredig Oct 26, 2024
36c315c
(refactor) small tweaks
mredig Oct 26, 2024
d6dc7f4
(refactor) update Readme
mredig Oct 26, 2024
dbf984d
(refactor) make hashable and equatable consistent with each other
mredig Oct 26, 2024
a3baf64
(refactor) remove T typealias
mredig Oct 26, 2024
590ecb7
(refactor) consolidate multiplication methods into single file
mredig Oct 26, 2024
1fa8958
(feat) more robust lossless string convertible
mredig Oct 26, 2024
7c2c2dc
(feat) support for string init with radix
mredig Oct 26, 2024
8a15248
(fix) rounding
mredig Oct 26, 2024
1a61c06
(feat) sign debug string
mredig Oct 26, 2024
3cc944b
(refactor) remove extra dependency
mredig Oct 27, 2024
6e9ce37
(feat/refactor) add NaN functionality
mredig Oct 27, 2024
3acbb22
(fix) floor division correctly replicates python functionality + 100%…
mredig Oct 27, 2024
828087b
(nit) test throws
mredig Oct 28, 2024
64e7f5d
(refactor) mark package for swift 6.0 build tools
mredig Oct 28, 2024
ba054e7
(feat) added rational storage
mredig Oct 28, 2024
4f0f8fc
(feat) theoretically support rationals inside rationals
mredig Oct 28, 2024
33d13f2
(feat) additional initializers
mredig Oct 28, 2024
7a3a63b
(fix) correct sign when reducing
mredig Oct 28, 2024
17ae08e
(fix) resolve test crash by removing duplicate test cases
mredig Oct 28, 2024
432c845
(refactor) improved storage equatable
mredig Oct 28, 2024
bdd9c06
(feat) add bigint debug string
mredig Oct 28, 2024
394d53d
(refactor) cleaner zero check
mredig Oct 28, 2024
4b67401
(feat) identical operator
mredig Oct 28, 2024
dad7b15
(feat) identical tests
mredig Oct 29, 2024
cf2849c
(feat) add simplification tests
mredig Oct 29, 2024
25a17ef
(fix) incorrect results in some tests
mredig Oct 29, 2024
f5f1e55
(refactor) Simplified comments
mredig Oct 29, 2024
edb3b0a
(refactor) clearer simplifiedValues
mredig Oct 29, 2024
6a0182b
(refactor) added some initializer tests
mredig Oct 29, 2024
bedc90a
(feat) test simplification
mredig Oct 29, 2024
1e81a24
(feat) reduce tests, improved init determinism
mredig Oct 29, 2024
a54d634
(fix) NaN should always evaluate false in comparisons. Updated tests …
mredig Oct 29, 2024
44f870a
(feat) gcd tests
mredig Oct 29, 2024
35de20a
(refactor) removed optionality where unnecessary
mredig Oct 29, 2024
13bd520
(nit) resolve warning
mredig Oct 29, 2024
b127d5b
(feat) test reduce nan
mredig Oct 29, 2024
8c3829a
(refactor) swift testing
mredig Oct 29, 2024
3cf5e26
(refactor) improve value descriptions
mredig Oct 29, 2024
f0895f5
(refactor) rational storage debug description
mredig Oct 29, 2024
31d7ad0
(refactor) return to BigUInt as numerator/denominator storage
mredig Oct 29, 2024
7e47d96
(refactor) more swift testing
mredig Oct 29, 2024
fb1f591
(refactor) more swift testing
mredig Oct 29, 2024
a2c85d8
(feat) add decimal init
mredig Nov 6, 2024
724b541
(refactor) remove bigint custom debug string
mredig Nov 6, 2024
063b03f
(refactor) temporarily use custom branch of BigInt while waiting for …
mredig Nov 7, 2024
c81f402
(nit) test name
mredig Nov 7, 2024
c8571b6
(feat) add float initializer
mredig Nov 7, 2024
58e9151
(fix) String convertible when integer
mredig Nov 7, 2024
392f97b
(refactor) add big parameter label
mredig Nov 7, 2024
f066840
(refactor) cleaner decimal init
mredig Nov 7, 2024
e7368f4
(feat) additional float tests
mredig Nov 7, 2024
011ae60
(refactor) more big param labels
mredig Nov 7, 2024
ca9f335
(refactor) improve test coverage
mredig Nov 7, 2024
5b976fe
(refactor) more optimal equality
mredig Nov 7, 2024
450624c
(feat) can derive double value from rational
mredig Nov 8, 2024
cd0c29d
(feat) general floating point initializer
mredig Nov 8, 2024
a01563a
(feat) can convert to decimal from rational
mredig Nov 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .swiftpm/configuration/swift-big-rational.xctestplan
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"configurations" : [
{
"id" : "4C629411-DD95-4E44-BA54-03D8A93114DE",
"name" : "Test Scheme Action",
"options" : {

}
}
],
"defaultOptions" : {
"codeCoverage" : {
"targets" : [
{
"containerPath" : "container:",
"identifier" : "BigRationalModule",
"name" : "BigRationalModule"
}
]
}
},
"testTargets" : [
{
"target" : {
"containerPath" : "container:",
"identifier" : "BigRationalModuleTests",
"name" : "BigRationalModuleTests"
}
}
],
"version" : 2
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "swift-rational"
BuildableName = "swift-rational"
BlueprintName = "swift-rational"
BlueprintIdentifier = "swift-big-rational"
BuildableName = "swift-big-rational"
BlueprintName = "swift-big-rational"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
Expand Down Expand Up @@ -49,9 +49,9 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "swift-rational"
BuildableName = "swift-rational"
BlueprintName = "swift-rational"
BlueprintIdentifier = "swift-big-rational"
BuildableName = "swift-big-rational"
BlueprintName = "swift-big-rational"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "RationalModule"
BuildableName = "RationalModule"
BlueprintName = "RationalModule"
BlueprintIdentifier = "BigRationalModule"
BuildableName = "BigRationalModule"
BlueprintName = "BigRationalModule"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "RationalModuleTests"
BuildableName = "RationalModuleTests"
BlueprintName = "RationalModuleTests"
BlueprintIdentifier = "BigRationalModuleTests"
BuildableName = "BigRationalModuleTests"
BlueprintName = "BigRationalModuleTests"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
Expand All @@ -40,16 +40,21 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:.swiftpm/configuration/swift-big-rational.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "RationalModuleTests"
BuildableName = "RationalModuleTests"
BlueprintName = "RationalModuleTests"
BlueprintIdentifier = "BigRationalModuleTests"
BuildableName = "BigRationalModuleTests"
BlueprintName = "BigRationalModuleTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
Expand Down Expand Up @@ -77,9 +82,9 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "RationalModule"
BuildableName = "RationalModule"
BlueprintName = "RationalModule"
BlueprintIdentifier = "BigRationalModule"
BuildableName = "BigRationalModule"
BlueprintName = "BigRationalModule"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
Expand Down
47 changes: 6 additions & 41 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,39 +1,13 @@
{
"originHash" : "cd8d19bdb55976b9db20cb762f0b11fdde3c2f56978daafed6e9cb8906ee5b5b",
"pins" : [
{
"identity" : "swift-argument-parser",
"identity" : "bigint",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-argument-parser.git",
"location" : "https://github.com/mredig/BigInt.git",
"state" : {
"revision" : "c8ed701b513cf5177118a175d85fbbbcd707ab41",
"version" : "1.3.0"
}
},
{
"identity" : "swift-cmark",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-cmark.git",
"state" : {
"revision" : "f218e5d7691f78b55bfa39b367763f4612486c35",
"version" : "0.3.0"
}
},
{
"identity" : "swift-format",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-format.git",
"state" : {
"revision" : "83248b4fa37919f78ffbd4650946759bcc54c2b5",
"version" : "509.0.0"
}
},
{
"identity" : "swift-markdown",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-markdown.git",
"state" : {
"revision" : "e4f95e2dc23097a1a9a1dfdfe3fe3ee44de77378",
"version" : "0.3.0"
"branch" : "decimal-perf2",
"revision" : "9cd0c2721b5fbced5cdf65bb317f1bb8f9727ca6"
}
},
{
Expand All @@ -44,16 +18,7 @@
"revision" : "0a5bc04095a675662cf24757cc0640aa2204253b",
"version" : "1.0.2"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax.git",
"state" : {
"revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036",
"version" : "509.0.2"
}
}
],
"version" : 2
"version" : 3
}
31 changes: 18 additions & 13 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
// swift-tools-version: 5.9
// swift-tools-version: 6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "swift-rational",
name: "swift-big-rational",
products: [
.library(
name: "RationalModule",
targets: ["RationalModule"]
name: "BigRationalModule",
targets: ["BigRationalModule"]
)
],
dependencies: [
.package(
url: "https://github.com/apple/swift-format.git",
exact: "509.0.0"
),
.package(
url: "https://github.com/apple/swift-numerics",
from: "1.0.0"
)
),
// .package(
// url: "https://github.com/attaswift/BigInt.git",
// .upToNextMajor(from: "5.5.0")
// ),
.package(
url: "https://github.com/mredig/BigInt.git",
branch: "decimal-perf2"
),
],
targets: [
.target(
name: "RationalModule",
name: "BigRationalModule",
dependencies: [
.product(
name: "RealModule",
package: "swift-numerics"
)
),
"BigInt",
]
),
.testTarget(
name: "RationalModuleTests",
dependencies: ["RationalModule"]
name: "BigRationalModuleTests",
dependencies: ["BigRationalModule"]
)
]
)
49 changes: 34 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
# Swift Rational
# Swift Big Rational

## Introduction

Swift Rational provides the `RationalModule` module for working with rational numbers in Swift.
Swift Big Rational provides the `BigRationalModule` module for working with rational numbers with fraction components that might normally overflow in Swift.
```swift
import RationalModule
import BigRationalModule

let half = Rational<Int>(1, 2)
let half = Rational(1, 2)
let tooBig = Rational(UInt.max) * Rational(4, 3)
```

`RationalModule` has only a single dependency, [swift-numerics](https://github.com/apple/swift-numerics/tree/main).
It was forked from [Swift Rational](https://github.com/abdel-17/swift-rational) and amended to accommodate numbers beyond what fits in 64 bits and also allow control over whether fractions are reduced or not.

## Using Swift Rational in your project
`BigRationalModule` has only two dependencies, [swift-numerics](https://github.com/apple/swift-numerics/tree/main) and [BigInt](https://github.com/attaswift/BigInt).

To use Swift Rational in a SwiftPM project:
## Using Swift Big Rational in your project

To use Swift Big Rational in a SwiftPM project:

1. Add the following line to the dependencies in your `Package.swift` file:

```swift
.package(url: "https://github.com/abdel-17/swift-rational", from: "1.0.0")
.package(url: "https://github.com/mredig/swift-big-rational.git", .upToNextMinor("1.1.0"))
```

2. Add `RationalModule` as a dependency for your target:
2. Add `BigRationalModule` as a dependency for your target:

```swift
.target(
name: "TargetName",
dependencies: [
.product(name: "RationalModule", package: "swift-rational")
.product(name: "BigRationalModule", package: "swift-big-rational")
]
)
```

3. Add `import RationalModule` in your source code.
3. Add `import BigRationalModule` in your source code.

## API

`RationalModule` exports the `Rational` struct. It conforms to standard Swift protocols like `AdditiveArithmetic`, `Numeric`, `Hashable`, `Comparable`, and more.
`BigRationalModule` exports the `Rational` struct. It conforms to standard Swift protocols like `AdditiveArithmetic`, `Numeric`, `Hashable`, `Comparable`, and more.

You can create a `Rational` value using the fraction initializer.
```swift
let half = Rational(2, 4)
print(x.numerator) // 1
print(x.denominator) // 2
print(x.numerator) // 2
print(x.denominator) // 4
```

You can also use the integer initializer.
Expand All @@ -52,7 +55,7 @@ let one = Rational(1)

Or simply an integer literal.
```swift
let two: Rational<Int> = 2
let two: Rational = 2
```

`Rational` supports the standard arithmetic and comparison operators.
Expand All @@ -64,5 +67,21 @@ Rational(1) / Rational(1, 2) // Rational(2, 1)
Rational(1, 2) < Rational(3, 4) // true
```

It also provides equivalence when comparing or hashing equal values with different multiples of one:
```swift
Rational(1, 2) == Rational(2, 4) // true
Rational(1, 2).hashValue == Rational(2, 4).hashValue // true
```

If you want the reduced value of a fraction, just use the `.reduced` property:
```swift
Rational(2, 4).reduced // Rational(1, 2)
```
Or pass `true` into the reduced argument when initializing:
```swift
Rational(2, 4, reduced: true) // Rational(1, 2)
```


## Attributions
A lot of the implementations were ported over to Swift from Python's [fractions](https://github.com/python/cpython/blob/main/Lib/fractions.py) module.
13 changes: 13 additions & 0 deletions Sources/BigRationalModule/BigInt+FixedIntEquatable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import BigInt

public extension BigInt {
static func == <N: FixedWidthInteger>(lhs: Self, rhs: N) -> Bool {
rhs == lhs
}
}

public extension FixedWidthInteger {
static func == (lhs: Self, rhs: BigInt) -> Bool {
BigInt(lhs) == rhs
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ internal func gcd<T: BinaryInteger>(_ a: T, _ b: T) -> T {
var x = a.magnitude
var y = b.magnitude

if x == 0 { return T(y) }
if y == 0 { return T(x) }
guard x != 0 else { return T(y) }
guard y != 0 else { return T(x) }

let xtz = x.trailingZeroBitCount
let ytz = y.trailingZeroBitCount
Expand Down
Loading