├── NumberKit.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcshareddata
│ └── xcschemes
│ │ ├── NumberKit iOS.xcscheme
│ │ └── NumberKit.xcscheme
└── project.pbxproj
├── Tests
├── LinuxMain.swift
└── NumberKitTests
│ ├── Info.plist
│ ├── ComplexTests.swift
│ ├── NumberUtilTests.swift
│ ├── CodableTests.swift
│ ├── RationalTests.swift
│ ├── IntegerNumberTests.swift
│ ├── IntegerTests.swift
│ └── BigIntTests.swift
├── NumberKit.podspec
├── Sources
├── NumberKit
│ ├── Info.plist
│ ├── NumberKit.h
│ ├── NumberUtil.swift
│ ├── FloatingPointNumber.swift
│ ├── IntegerNumber.swift
│ ├── Integer.swift
│ ├── Complex.swift
│ └── Rational.swift
└── NumberKit iOS
│ ├── Info.plist
│ └── NumberKit_iOS.h
├── Package.swift
├── .gitignore
├── README.md
├── CHANGELOG.md
└── LICENSE
/NumberKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/NumberKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | #if os(Linux)
2 |
3 | import XCTest
4 | @testable import NumberKitTests
5 |
6 | XCTMain(
7 | [
8 | testCase(BigIntTests.allTests),
9 | testCase(ComplexTests.allTests),
10 | testCase(RationalTests.allTests),
11 | testCase(NumberUtilTests.allTests),
12 | testCase(CodableTests.allTests),
13 | ]
14 | )
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/NumberKit.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'NumberKit'
3 | s.module_name = 'NumberKit'
4 | s.version = '2.4.2'
5 | s.summary = 'Advanced numeric data types for Swift 5, including BigInt, Rational, and Complex numbers.'
6 | s.homepage = 'https://github.com/objecthub/swift-numberkit'
7 | s.license = 'Apache License 2.0'
8 | s.author = { 'Matthias Zenger' => 'matthias@objecthub.com' }
9 | s.source = { :git => 'https://github.com/objecthub/swift-numberkit.git', :tag => s.version }
10 | s.ios.deployment_target = '12.0'
11 | s.tvos.deployment_target = '12.0'
12 | s.osx.deployment_target = '10.12'
13 | s.swift_version = '5.4'
14 | s.source_files = 'Sources/NumberKit/**/*.{swift}'
15 | end
--------------------------------------------------------------------------------
/Sources/NumberKit/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSHumanReadableCopyright
22 | Copyright © 2015–2023 Matthias Zenger. All rights reserved.
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Sources/NumberKit iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSHumanReadableCopyright
22 | Copyright © 2015–2023 Matthias Zenger. All rights reserved.
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Tests/NumberKitTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | $(MARKETING_VERSION)
19 | CFBundleVersion
20 | $(CURRENT_PROJECT_VERSION)
21 | NSHumanReadableCopyright
22 | Copyright © 2015–2023 Matthias Zenger. All rights reserved.
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Sources/NumberKit/NumberKit.h:
--------------------------------------------------------------------------------
1 | //
2 | // NumberKit.h
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 11/08/2015.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | #import
22 |
23 | //! Project version number for NumberKit.
24 | FOUNDATION_EXPORT double NumberKitVersionNumber;
25 |
26 | //! Project version string for NumberKit.
27 | FOUNDATION_EXPORT const unsigned char NumberKitVersionString[];
28 |
29 | // In this header, you should import all the public headers of your framework using
30 | // statements like #import
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Sources/NumberKit iOS/NumberKit_iOS.h:
--------------------------------------------------------------------------------
1 | //
2 | // NumberKit_iOS.h
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 10/02/2020.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | #import
22 |
23 | //! Project version number for NumberKit_iOS.
24 | FOUNDATION_EXPORT double NumberKit_iOSVersionNumber;
25 |
26 | //! Project version string for NumberKit_iOS.
27 | FOUNDATION_EXPORT const unsigned char NumberKit_iOSVersionString[];
28 |
29 | // In this header, you should import all the public headers of your framework using statements like #import
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.4
2 | //
3 | // Package.swift
4 | // NumberKit
5 | //
6 | // Created by Matthias Zenger on 01/05/2017.
7 | // Copyright © 2015-2024 Matthias Zenger. All rights reserved.
8 | //
9 | // Licensed under the Apache License, Version 2.0 (the "License");
10 | // you may not use this file except in compliance with the License.
11 | // You may obtain a copy of the License at
12 | //
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | //
15 | // Unless required by applicable law or agreed to in writing, software
16 | // distributed under the License is distributed on an "AS IS" BASIS,
17 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | // See the License for the specific language governing permissions and
19 | // limitations under the License.
20 | //
21 |
22 | import PackageDescription
23 |
24 | let package = Package(
25 | name: "NumberKit",
26 | products: [
27 | .library(name: "NumberKit", targets: ["NumberKit"]),
28 | ],
29 | dependencies: [
30 | ],
31 | targets: [
32 | .target(name: "NumberKit",
33 | dependencies: [],
34 | exclude: ["Info.plist"]),
35 | .testTarget(name: "NumberKitTests",
36 | dependencies: ["NumberKit"],
37 | exclude: ["Info.plist"]),
38 | ],
39 | swiftLanguageVersions: [.v5]
40 | )
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 | *.xcuserstate
25 |
26 | ## Obj-C/Swift specific
27 | *.hmap
28 | *.ipa
29 | *.dSYM.zip
30 | *.dSYM
31 |
32 | ## Playgrounds
33 | timeline.xctimeline
34 | playground.xcworkspace
35 |
36 | # Swift Package Manager
37 | #
38 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
39 | # Packages/
40 | # Package.pins
41 | # Package.resolved
42 | .build/
43 | Packages
44 |
45 | # CocoaPods
46 | #
47 | # We recommend against adding the Pods directory to your .gitignore. However
48 | # you should judge for yourself, the pros and cons are mentioned at:
49 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
50 | #
51 | # Pods/
52 |
53 | # Carthage
54 | #
55 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
56 | # Carthage/Checkouts
57 |
58 | Carthage/Build
59 |
60 | # fastlane
61 | #
62 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
63 | # screenshots whenever they are needed.
64 | # For more information about the recommended setup visit:
65 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
66 |
67 | fastlane/report.xml
68 | fastlane/Preview.html
69 | fastlane/screenshots/**/*.png
70 | fastlane/test_output
71 |
72 | # Code Injection
73 | #
74 | # After new code Injection tools there's a generated folder /iOSInjectionProject
75 | # https://github.com/johnno1962/injectionforxcode
76 |
77 | iOSInjectionProject/
78 |
79 | # macOS
80 | .DS_Store
81 |
--------------------------------------------------------------------------------
/Tests/NumberKitTests/ComplexTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ComplexTests.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 16/08/2015.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import XCTest
22 | @testable import NumberKit
23 |
24 | class ComplexTests: XCTestCase {
25 |
26 | func testConstructors() {
27 | let c1: Complex = 2.0 + 3.0.i
28 | XCTAssertEqual(c1, Complex(2.0, 3.0))
29 | let c2 = -1.0 - 2.0.i
30 | XCTAssertEqual(c2, Complex(-1.0, -2.0))
31 | let c3: Complex = 7
32 | XCTAssertEqual(c3, Complex(7.0))
33 | }
34 |
35 | func testImaginaryInvariant() {
36 | let c = 1.0.i
37 | XCTAssertEqual(c * c, -1)
38 | }
39 |
40 | func testSpecialCases() {
41 | let c1: Complex = Complex(.infinity, 12.0)
42 | XCTAssertTrue(c1.isInfinite)
43 | XCTAssertFalse(c1.isNaN)
44 | let c2: Complex = Complex(.infinity, -7.3)
45 | XCTAssertEqual(c1, c2)
46 | let c3: Complex = Complex(.nan, -1.2)
47 | XCTAssertTrue(c3.isNaN)
48 | XCTAssertFalse(c3.isInfinite)
49 | XCTAssertEqual(c3.im, 0.0)
50 | let c4: Complex = Complex(3.4, .nan)
51 | XCTAssertTrue(c4.isNaN)
52 | XCTAssertFalse(c4.isInfinite)
53 | XCTAssertEqual(c4.im, 0.0)
54 | XCTAssertNotEqual(c3, c4)
55 | XCTAssertTrue(c4.abs.isNaN)
56 | let c5: Complex = Complex(1.234, .infinity)
57 | XCTAssertTrue(c5.isNaN)
58 | XCTAssertFalse(c5.isInfinite)
59 | XCTAssertTrue(c5.magnitude.isNaN)
60 | let c6: Complex = .zero
61 | XCTAssertTrue(c6.reciprocal.isInfinite)
62 | XCTAssertTrue(c1.reciprocal.isZero)
63 | }
64 |
65 | static let allTests = [
66 | ("testConstructors", testConstructors),
67 | ("testImaginaryInvariant", testImaginaryInvariant),
68 | ("testSpecialCases", testSpecialCases),
69 | ]
70 | }
71 |
--------------------------------------------------------------------------------
/Tests/NumberKitTests/NumberUtilTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NumberUtilTests.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 12/08/2015.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import XCTest
22 | @testable import NumberKit
23 |
24 | class NumberUtilTests: XCTestCase {
25 |
26 | func testPow() {
27 | XCTAssertEqual(1.toPower(of: 1), 1)
28 | XCTAssertEqual(1.toPower(of: 9), 1)
29 | XCTAssertEqual(7.toPower(of: 3), 7 * 7 * 7)
30 | XCTAssertEqual(31.toPower(of: 7), 27512614111)
31 | XCTAssertEqual((-5).toPower(of: 2), 25)
32 | XCTAssertEqual((-5).toPower(of: 3), -125)
33 | XCTAssertEqual((-5).toPower(of: 0), 1)
34 | XCTAssertEqual(5.toPower(of: 0), 1)
35 | }
36 |
37 | func testPowOperator() {
38 | XCTAssertEqual(1 ** 1, 1)
39 | XCTAssertEqual(1 ** 9, 1)
40 | XCTAssertEqual(7 ** 3, 7 * 7 * 7)
41 | let many = 31 * 31 * 31 * 31
42 | XCTAssertEqual((29 + 2) ** 7, many * 31 * 31 * 31)
43 | XCTAssertEqual(-5 ** (1 + 1), 25)
44 | XCTAssertEqual(-5 ** 3, -125)
45 | XCTAssertEqual(-5 ** 0, 1)
46 | XCTAssertEqual(5 ** 0, 1)
47 | }
48 |
49 | func testMinMax() {
50 | XCTAssertEqual(min(0, 1), 0)
51 | XCTAssertEqual(min(1, 0), 0)
52 | XCTAssertEqual(min(-1, 0), -1)
53 | XCTAssertEqual(min(0, -1), -1)
54 | XCTAssertEqual(max(0, 1), 1)
55 | XCTAssertEqual(max(1, 0), 1)
56 | XCTAssertEqual(max(-1, 0), 0)
57 | XCTAssertEqual(max(0, -1), 0)
58 | }
59 |
60 | func testBitCount() {
61 | XCTAssertEqual(bitcount(0), 0)
62 | XCTAssertEqual(bitcount(1), 1)
63 | XCTAssertEqual(bitcount(2), 1)
64 | XCTAssertEqual(bitcount(3), 2)
65 | XCTAssertEqual(bitcount(Int.max), 63)
66 | XCTAssertEqual(bitcount(Int(-1)), 64)
67 | XCTAssertEqual(bitcount(UInt.min), 0)
68 | XCTAssertEqual(bitcount(UInt.max), 64)
69 | }
70 |
71 | static let allTests = [
72 | ("testPow", testPow),
73 | ("testPowOperator", testPowOperator),
74 | ("testMinMax", testMinMax),
75 | ]
76 | }
77 |
--------------------------------------------------------------------------------
/Tests/NumberKitTests/CodableTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CodableTests.swift
3 | // NumberKitTests
4 | //
5 | // Created by Matthias Zenger on 08/02/2020.
6 | // Copyright © 2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import XCTest
22 | @testable import NumberKit
23 |
24 | class CodableTests: XCTestCase {
25 |
26 | func testComplexCodable() {
27 | let c1: Complex = 987654.41 - 2.0.i
28 | XCTAssertEqual(self.recodeJSON(c1), c1)
29 | let c2: Complex = 1.5.i
30 | XCTAssertEqual(self.recodeJSON(c2), c2)
31 | let c3: Complex = 0.0
32 | XCTAssertEqual(self.recodeJSON(c3), c3)
33 | }
34 |
35 | func testRationalCodable() {
36 | let r1: Rational = 7/2
37 | XCTAssertEqual(self.recodeJSON(r1), r1)
38 | let r2: Rational = 7654321
39 | XCTAssertEqual(self.recodeJSON(r2), r2)
40 | let r3: Rational = 0
41 | XCTAssertEqual(self.recodeJSON(r3), r3)
42 | }
43 |
44 | func testBigIntCodable() {
45 | let x1: BigInt = "811248574598402980294572048572242498127"
46 | XCTAssertEqual(self.recodeJSON(x1), x1)
47 | let x2: BigInt = "847597200"
48 | XCTAssertEqual(self.recodeJSON(x2), x2)
49 | let x3: BigInt = "-75537574353998534693615828134454330968785329792741330257228043492082567"
50 | XCTAssertEqual(self.recodeJSON(x3), x3)
51 | }
52 |
53 | private func recodeJSON(_ obj: T) -> T? {
54 | guard let encodedObj = self.encodeJSON(obj) else {
55 | return nil
56 | }
57 | return self.decodeJSON(type(of: obj), encodedObj)
58 | }
59 |
60 | private func encodeJSON(_ obj: T) -> String? {
61 | guard let encodedObj = try? JSONEncoder().encode(obj) else {
62 | return nil
63 | }
64 | guard let res = String(data: encodedObj, encoding: .utf8) else {
65 | return nil
66 | }
67 | return res
68 | }
69 |
70 | private func decodeJSON(_ type: T.Type, _ str: String) -> T? {
71 | return try? JSONDecoder().decode(type, from: str.data(using: .utf8)!)
72 | }
73 |
74 | static let allTests = [
75 | ("testComplexCodable", testComplexCodable),
76 | ("testRationalCodable", testRationalCodable),
77 | ("testBigIntCodable", testBigIntCodable),
78 | ]
79 | }
80 |
--------------------------------------------------------------------------------
/NumberKit.xcodeproj/xcshareddata/xcschemes/NumberKit iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
54 |
60 |
61 |
67 |
68 |
69 |
70 |
72 |
73 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/Sources/NumberKit/NumberUtil.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NumberUtil.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 12/08/2015.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 |
22 | /// Provide power operator for all integers
23 | precedencegroup ExponentiativePrecedence {
24 | associativity: left
25 | higherThan: MultiplicationPrecedence
26 | }
27 |
28 | infix operator ** : ExponentiativePrecedence
29 | infix operator **= : AssignmentPrecedence
30 |
31 | /// Implements power function for all integer types.
32 | public func ** (_ lhs: T, _ rhs: T) -> T {
33 | return lhs.toPower(of: rhs)
34 | }
35 |
36 | /// Implements power-assignment function for all integer types.
37 | public func **= (_ lhs: inout T, _ rhs: T) {
38 | lhs = lhs.toPower(of: rhs)
39 | }
40 |
41 | /// Implements minimum function for all integer types.
42 | public func min(_ fst: T, _ snd: T) -> T {
43 | return fst < snd ? fst : snd
44 | }
45 |
46 | /// Implements maximum function for all integer types.
47 | public func max(_ fst: T, _ snd: T) -> T {
48 | return fst > snd ? fst : snd
49 | }
50 |
51 | private let bitCounts: [Int] =
52 | [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3,
53 | 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4,
54 | 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4,
55 | 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,
56 | 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2,
57 | 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5,
58 | 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4,
59 | 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6,
60 | 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8]
61 |
62 | // `bitCount` computes the number of bits set in the given `UInt32` value.
63 | public func bitcount(_ num: UInt32) -> Int {
64 | var res = bitCounts[Int(num & 0xff)]
65 | res = res &+ bitCounts[Int((num >> 8) & 0xff)]
66 | res = res &+ bitCounts[Int((num >> 16) & 0xff)]
67 | return res &+ bitCounts[Int(num >> 24)]
68 | }
69 |
70 | // `bitCount` computes the number of bits set in the given `UInt64` value.
71 | public func bitcount(_ num: UInt64) -> Int {
72 | return bitcount(UInt32((num >> 32) & 0xffffffff)) + bitcount(UInt32(num & 0xffffffff))
73 | }
74 |
75 | // `bitCount` computes the number of bits set in the given `Int32` value.
76 | public func bitcount(_ num: Int32) -> Int {
77 | return bitcount(UInt32(bitPattern: num))
78 | }
79 |
80 | // `bitCount` computes the number of bits set in the given `Int32` value.
81 | public func bitcount(_ num: Int64) -> Int {
82 | return bitcount(UInt64(bitPattern: num))
83 | }
84 |
85 | // `bitCount` computes the number of bits set in the given `UInt` value.
86 | public func bitcount(_ num: UInt) -> Int {
87 | return bitcount(UInt64(num))
88 | }
89 |
90 | // `bitCount` computes the number of bits set in the given `Int` value.
91 | public func bitcount(_ num: Int) -> Int {
92 | return bitcount(UInt(bitPattern: num))
93 | }
94 |
--------------------------------------------------------------------------------
/NumberKit.xcodeproj/xcshareddata/xcschemes/NumberKit.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
63 |
69 |
70 |
71 |
72 |
78 |
79 |
85 |
86 |
87 |
88 |
90 |
91 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/Sources/NumberKit/FloatingPointNumber.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FloatingPointNumber.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 23/09/2017.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import Foundation
22 |
23 |
24 | /// Protocol `FloatingPointNumber` is used in combination with struct
25 | /// `Complex`. It defines the functionality needed for a floating point
26 | /// implementation to build complex numbers on top. The `FloatingPoint`
27 | /// protocol from the Swift 4 standard library is not sufficient currently.
28 | ///
29 | /// - Note: For some reason, `_ExpressibleByBuiltinFloatLiteral` is needed here to
30 | /// allow `Complex` to implement protocol `ExpressibleByFloatLiteral`.
31 | /// Replacing it with `ExpressibleByFloatLiteral` does not work either.
32 | public protocol FloatingPointNumber: FloatingPoint, _ExpressibleByBuiltinFloatLiteral {
33 | var i: Complex { get }
34 | var abs: Self { get }
35 | var sqrt: Self { get }
36 | var sin: Self { get }
37 | var cos: Self { get }
38 | var exp: Self { get }
39 | var log: Self { get }
40 | func pow(_ ex: Self) -> Self
41 | func hypot(_ y: Self) -> Self
42 | func atan2(_ y: Self) -> Self
43 | static func random(in range: Range,
44 | using generator: inout T) -> Self
45 | }
46 |
47 | /// Make `Float` implement protocol `FloatingPointNumber`.
48 | extension Float: FloatingPointNumber {
49 | public var i: Complex {
50 | return Complex(0.0, self)
51 | }
52 | public var abs: Float {
53 | return Swift.abs(self)
54 | }
55 | public var sqrt: Float {
56 | return Foundation.sqrt(self)
57 | }
58 | public var sin: Float {
59 | return Foundation.sin(self)
60 | }
61 | public var cos: Float {
62 | return Foundation.cos(self)
63 | }
64 | public var exp: Float {
65 | return Foundation.exp(self)
66 | }
67 | public var log: Float {
68 | return Foundation.log(self)
69 | }
70 | public func pow(_ ex: Float) -> Float {
71 | return Foundation.pow(self, ex)
72 | }
73 | public func hypot(_ y: Float) -> Float {
74 | return Foundation.hypot(self, y)
75 | }
76 | public func atan2(_ y: Float) -> Float {
77 | return Foundation.atan2(self, y)
78 | }
79 | }
80 |
81 | /// Make `Double` implement protocol `FloatingPointNumber`.
82 | extension Double: FloatingPointNumber {
83 | public var i: Complex {
84 | return Complex(0.0, self)
85 | }
86 | public var abs: Double {
87 | return Swift.abs(self)
88 | }
89 | public var sqrt: Double {
90 | return Foundation.sqrt(self)
91 | }
92 | public var sin: Double {
93 | return Foundation.sin(self)
94 | }
95 | public var cos: Double {
96 | return Foundation.cos(self)
97 | }
98 | public var exp: Double {
99 | return Foundation.exp(self)
100 | }
101 | public var log: Double {
102 | return Foundation.log(self)
103 | }
104 | public func pow(_ ex: Double) -> Double {
105 | return Foundation.pow(self, ex)
106 | }
107 | public func hypot(_ y: Double) -> Double {
108 | return Foundation.hypot(self, y)
109 | }
110 | public func atan2(_ y: Double) -> Double {
111 | return Foundation.atan2(self, y)
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Swift NumberKit
2 |
3 | [](https://developer.apple.com/osx/) [](https://developer.apple.com/swift/) [](https://developer.apple.com/xcode/) [](https://github.com/Carthage/Carthage) [](https://raw.githubusercontent.com/objecthub/swift-numberkit/master/LICENSE)
4 |
5 | ## Overview
6 |
7 | This is a framework implementing advanced numeric data types for the Swift programming
8 | language on macOS, iOS and Linux. Currently, the framework provides four new numeric types,
9 | each represented as a struct or enumeration:
10 |
11 | 1. `BigInt`: arbitrary-size signed integers
12 | 2. `Integer`: arbitrary-size signed integers whose implementation depends on the size
13 | of the represented value.
14 | 2. `Rational`: signed rational numbers
15 | 3. `Complex`: complex floating-point numbers
16 |
17 | **Note**: So far, with every major version of Swift, Apple decided to change the foundational APIs of the numeric
18 | types in Swift significantly and consistently in a backward incompatible way. In order to be more isolated from
19 | such changes in future, with Swift 3, I decided to introduce a distinct integer type used in NumberKit based on a
20 | new protocol `IntegerNumber`. All standard numeric integer types implement this protocol. This is now consistent
21 | with the usage of protocol `FloatingPointNumber` for floating point numbers, where there was, so far, never a
22 | real, generic enough foundation (and still isn't).
23 |
24 | ## BigInt
25 |
26 | `BigInt` values are immutable, signed, arbitrary-size integers that can be used as a
27 | drop-in replacement for the existing binary integer types of Swift 5.
28 | [Struct `BigInt`](https://github.com/objecthub/swift-numberkit/blob/master/Sources/NumberKit/BigInt.swift) defines all
29 | the standard arithmetic integer operations and implements the corresponding numeric
30 | protocols of Swift.
31 |
32 | ## Integer
33 |
34 | `Integer` values are immutable, signed, arbitrary-size integers that can be used as a
35 | drop-in replacement for the existing binary integer types of Swift 5. As opposed to `BigInt`,
36 | the representation of values is chosen to optimize for memory size and performance of
37 | arithmetic operations. [Enum `Integer`](https://github.com/objecthub/swift-numberkit/blob/master/Sources/NumberKit/Integer.swift)
38 | defines all the standard arithmetic integer operations and implements the corresponding
39 | numeric protocols of Swift.
40 |
41 | ## Rational
42 |
43 | [Struct `Rational`](https://github.com/objecthub/swift-numberkit/blob/master/Sources/NumberKit/Rational.swift)
44 | defines immutable, rational numbers based on an existing signed integer
45 | type `T`, like `Int32`, `Int64`, or `BigInt`. A rational number is a signed number that can
46 | be expressed as the quotient of two integers _a_ and _b_: _a / b_.
47 |
48 | ## Complex
49 |
50 | [Struct `Complex`](https://github.com/objecthub/swift-numberkit/blob/master/Sources/NumberKit/Complex.swift)
51 | defines complex numbers based on an existing floating point type `T`, like `Float` or `Double`. A complex number
52 | consists of two components, a real part _re_ and an imaginary part _im_ and is typically written as: _re + im * i_
53 | where _i_ is the _imaginary unit_.
54 |
55 | ## Requirements
56 |
57 | The following technologies are needed to build the components of the _Swift NumberKit_ framework:
58 |
59 | - [Xcode 15 or Xcode 16](https://developer.apple.com/xcode/)
60 | - [Swift 5 or Swift 6](https://developer.apple.com/swift/)
61 | - [Swift Package Manager](https://swift.org/package-manager/)
62 | - macOS, iOS or Linux
63 |
64 | ## Copyright
65 |
66 | Author: Matthias Zenger ()
67 | Copyright © 2016-2024 Matthias Zenger. All rights reserved.
68 |
--------------------------------------------------------------------------------
/Tests/NumberKitTests/RationalTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RationalTests.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 16/08/2015.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import XCTest
22 |
23 | @testable import NumberKit
24 |
25 | class RationalTests: XCTestCase {
26 |
27 | func testConstructors() {
28 | let r0: Rational = 8
29 | XCTAssert(r0.numerator == 8 && r0.denominator == 1)
30 | XCTAssert(r0 == 8)
31 | let r1: Rational = 7/2
32 | XCTAssert(r1.numerator == 7 && r1.denominator == 2)
33 | XCTAssert(r1.floatValue == 7.0/2.0)
34 | let r2 = Rational(43, 7)
35 | XCTAssert(r2.numerator == 43 && r2.denominator == 7)
36 | let r3 = Rational(19 * 3 * 5 * 7, 2 * 5 * 7)
37 | XCTAssert(r3.numerator == 19 * 3 && r3.denominator == 2)
38 | let r4: Rational? = Rational(from: "172346/254")
39 | if let r4u = r4 {
40 | XCTAssertEqual(r4u.numerator, 86173)
41 | XCTAssertEqual(r4u.denominator, 127)
42 | } else {
43 | XCTFail("cannot parse r4 string")
44 | }
45 | let r5: Rational? = Rational(from: "-128/64")
46 | if let r5u = r5 {
47 | XCTAssertEqual(r5u.numerator, -2)
48 | XCTAssertEqual(r5u.denominator, 1)
49 | } else {
50 | XCTFail("cannot parse r5 string")
51 | }
52 | }
53 |
54 | func testPlus() {
55 | let r1 = Rational(16348, 343).plus(24/7)
56 | XCTAssertEqual(r1, 17524/343)
57 | XCTAssert(r1 == Rational(from: "17524/343"))
58 | XCTAssert(r1 == 17524/343)
59 | let r2: Rational = (74433/215).plus(312/15)
60 | XCTAssert(r2 == 367)
61 | let r3: Rational = (458200/50).plus(3440/17)
62 | XCTAssert(r3 == 159228/17)
63 | let x = Rational(BigInt(458200)/BigInt(50))
64 | let r4: Rational = x.plus(Rational(BigInt(3440)/BigInt(17)))
65 | XCTAssert(r4 == Rational(BigInt(159228)/BigInt(17)))
66 | }
67 |
68 | func testMinus() {
69 | let r1 = Rational(123, 5).minus(247/10)
70 | XCTAssertEqual(r1, Rational(1, 10).negate)
71 | let r2 = Rational(0).minus(72372/30)
72 | XCTAssertEqual(r2, -Rational(72372, 30))
73 | let r3 = Rational(98232, 536).minus(123/12)
74 | XCTAssertEqual(r3, Rational(46369, 268))
75 | }
76 |
77 | func testTimes() {
78 | let r1 = Rational(4, 8).times(2)
79 | XCTAssertEqual(r1, 1)
80 | let r2 = Rational(83987, 12).times(48/42)
81 | XCTAssertEqual(r2, Rational(83987 * 48, 12 * 42))
82 | let r3 = Rational(170, 9).times(-17/72)
83 | XCTAssertEqual(r3, Rational(-170 * 17, 9 * 72))
84 | }
85 |
86 | func testDividedBy() {
87 | let r1 = Rational(10, -3).divided(by: -31/49)
88 | XCTAssertEqual(r1, Rational(10 * 49, 3 * 31))
89 | }
90 |
91 | func testRationalize() {
92 | let r1 = Rational(1.0/3.0)
93 | XCTAssertEqual(r1, Rational(1, 3))
94 | let r2 = Rational(1931.0 / 9837491.0, precision: 1.0e-14)
95 | XCTAssertEqual(r2, Rational(1931, 9837491))
96 | let r3 = Rational(-17.0/3.0)
97 | XCTAssertEqual(r3, -Rational(17, 3))
98 | let r4 = Rational(1931.0 / 9837491.0, precision: 1.0e-14)
99 | XCTAssertEqual(r4, Rational(BigInt(1931), BigInt(9837491)))
100 | }
101 |
102 | static let allTests = [
103 | ("testConstructors", testConstructors),
104 | ("testPlus", testPlus),
105 | ("testMinus", testMinus),
106 | ("testTimes", testTimes),
107 | ("testDividedBy", testDividedBy),
108 | ("testRationalize", testRationalize),
109 | ]
110 | }
111 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 2.6 (2024-08-18)
4 | - Fixes a serious bug which made unsigned integers implement the `IntegerNumber` protocol (which is designed for signed integers only)
5 | - Enabled `IntegerNumberTests` also for Xcode
6 | - Ready for usage with Swift 6
7 |
8 | ## 2.5.1 (2024-04-17)
9 | - Reduce minimum deployment targets down to macOS 10.13 and iOS 11.
10 | - Include `StaticBigInt` only when available.
11 |
12 | ## 2.5 (2024-04-12)
13 | - Support arbitrary length integer literals via `StaticBigInt`. This requires at least macOS 13.3.
14 | - Make `Codable` implementation of `BigInt` compatible to JSON use cases
15 | - Introduce enum `Integer` wrapping `BigInt` and the native `Int64` implementation
16 | - Migrate project to Xcode 15
17 |
18 | ## 2.4.2 (2023-01-01)
19 | - Support random number generation for Complex
20 | - Migrated project to Swift 5.7 and Xcode 14
21 |
22 | ## 2.4.1 (2022-01-04)
23 | - Support random number generation for BigInt
24 | - Migrated project to Swift 5.5 and Xcode 13.2
25 |
26 | ## 2.4.0 (2021-05-12)
27 | - Several enhancements of the `Complex` type
28 | - Migrated project to Swift 5.4 and Xcode 12.5
29 |
30 | ## 2.3.9 (2020-10-04)
31 | - Port to Swift 5.3
32 | - Migrated project to Xcode 12.0
33 |
34 | ## 2.3.7 (2020-05-01)
35 | - Fixed serious bug that was leading to a stack overflow if zero was added to a negative `BigInt` number
36 | - Introduced new `Rational` constructor for approximating a `Double` number as a `Rational`
37 |
38 | ## 2.3.6 (2020-04-10)
39 | - Cleaned up Xcode project
40 |
41 | ## 2.3.5 (2020-04-05)
42 | - Port to Swift 5.2
43 | - Migrated project to Xcode 11.4
44 |
45 | ## 2.3.4 (2020-02-11)
46 | - Include iOS build target
47 |
48 | ## 2.3.3 (2020-02-09)
49 | - Made all numeric types support protocol `Codable`
50 | - Migrated project to Xcode 11.3
51 |
52 | ## 2.3.2 (2019-10-20)
53 | - Migrated project to Xcode 11.1
54 | - Removed non-shared scheme from project
55 |
56 | ## 2.3.1 (2019-09-23)
57 | - Port to Swift 5.1
58 | - Migrated project to Xcode 11
59 |
60 | ## 2.3 (2019-03-30)
61 | - Port to Swift 5
62 | - Migrated project to Xcode 10.2
63 | - Use new hashing API to improve hashing algorithm and to speed up hashing compound data structures
64 |
65 | ## 2.2 (2018-03-30)
66 | - Port to Swift 4.1
67 | - Migrated project to Xcode 9.3
68 |
69 | ## 2.1 (2018-01-24)
70 | - Port to Swift 4.0.2
71 | - Bug fix to support the Swift Package Manager for Swift 4
72 | - Makes `BigInt` a fully integrated `SignedInteger` in Swift 4
73 | - Re-introduces operations with overflow for `Rational` (which got lost in the Swift 4 migration)
74 | - Optimize performance of `BigInt`
75 | - Comprehensive support for bit operations on `BigInt` numbers
76 | - Several bug fixes for existing bit operations
77 | - Fixes numerous bugs in bit shifting logic
78 | - Fixes serious bug in division and remainder logic for `BigInt` numbers
79 |
80 | ## 2.0 (2017-09-24)
81 | - Ported NumberKit to Swift 4. This is a major change that might break existing clients
82 | - Added support for `toPower(of:)` for all integer types
83 | - Added new operators to `BigInt`: `<<`, `>>`, `<<=`, `>>=`, `%`, `%=`
84 | - Introduced new integer protocol: `IntegerNumber`
85 | - Renamed `FloatNumber` into `FloatingPointNumber`
86 |
87 | ## 1.6 (2017-05-01)
88 | - Refactored directory structure
89 | - Support for Swift Package Manager
90 |
91 | ## 1.5 (2016-09-03)
92 | - Migrated library to Xcode 8.0, Swift 3.0
93 | - Renamed protocols to match the Swift 3 style guidelines
94 | - Simplified a few implementations, making use of new Swift 3 APIs
95 |
96 | ## 1.4 (2016-03-28)
97 | - Code now compatible with Xcode 7.3, Swift 2.2
98 | - Turned `BigInt` into a struct to avoid garbage collection overhead
99 |
100 | ## 1.3 (2016-02-09)
101 | - Significant performance improvements to speed up the BigInt/String conversion method
102 | - Minor feature additions to rational numbers
103 | - Playground (created by Dan Kogai)
104 |
105 | ## 1.2 (2016-01-17)
106 | - Added arithmetic operations to `Rational` which keep track of overflows
107 | - Simplified implementation of `BigInt`
108 | - Included new `BigInt` operations, e.g. a computed property for coercions to `Double`
109 |
110 | ## 1.1 (2015-10-19)
111 | - Completed implementation of `Complex`
112 |
113 | ## 1.0 (2015-08-24)
114 | - Completed implementation of `BigInt`
115 | - Completed implementation of `Rational`
116 | - `Complex` still missing a large range of functions and tests
117 |
--------------------------------------------------------------------------------
/Tests/NumberKitTests/IntegerNumberTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // IntegerNumberTests.swift
3 | // NumberKit
4 | //
5 | // Created by John DeTreville on 25/06/2023.
6 | // Copyright © 2023 John DeTreville. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
9 | // the license. You may obtain a copy of the License at
10 | //
11 | // http://www.apache.org/licenses/LICENSE-2.0
12 | //
13 | // Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
14 | // an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
15 | // specific language governing permissions and limitations under the License.
16 | //
17 |
18 | import XCTest
19 |
20 | @testable import NumberKit
21 |
22 | class IntegerNumberTest: XCTestCase {
23 |
24 | func testGcd() {
25 | XCTAssert(Int32.gcdWithOverflow(1, 1) == (1, false))
26 | XCTAssert(Int32.gcdWithOverflow(1, 0) == (1, false))
27 | XCTAssert(Int32.gcdWithOverflow(0, 1) == (1, false))
28 | XCTAssert(Int32.gcdWithOverflow(0, 0) == (0, false))
29 | XCTAssert(Int32.gcdWithOverflow(1, -1) == (1, false))
30 | XCTAssert(Int32.gcdWithOverflow(-1, 1) == (1, false))
31 | XCTAssert(Int32.gcdWithOverflow(-1, -1) == (1, false))
32 |
33 | let factorial: Int64 = 2_432_902_008_176_640_000 // 20!
34 | let lcm: Int64 = 232_792_560 // lcm[1..20]
35 | XCTAssert(Int64.gcdWithOverflow(factorial, lcm) == (lcm, false))
36 | XCTAssert(Int64.gcdWithOverflow(factorial, lcm + 1) == (1, false))
37 |
38 | let fibonaccis: [UInt64] = [
39 | 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765,
40 | 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1_346_269,
41 | 2_178_309, 3_524_578, 5_702_887, 9_227_465, 14_930_352, 24_157_817, 39_088_169, 63_245_986,
42 | 102_334_155, 165_580_141, 267_914_296, 433_494_437, 701_408_733, 1_134_903_170,
43 | 1_836_311_903, 2_971_215_073, 4_807_526_976, 7_778_742_049, 12_586_269_025, 20_365_011_074,
44 | 32_951_280_099, 53_316_291_173, 86_267_571_272, 139_583_862_445, 225_851_433_717,
45 | 365_435_296_162, 591_286_729_879, 956_722_026_041, 1_548_008_755_920, 2_504_730_781_961,
46 | 4_052_739_537_881, 6_557_470_319_842, 10_610_209_857_723, 17_167_680_177_565,
47 | 27_777_890_035_288, 44_945_570_212_853, 72_723_460_248_141, 117_669_030_460_994,
48 | 190_392_490_709_135, 308_061_521_170_129, 498_454_011_879_264, 806_515_533_049_393,
49 | 1_304_969_544_928_657, 2_111_485_077_978_050, 3_416_454_622_906_707, 5_527_939_700_884_757,
50 | 8_944_394_323_791_464, 14_472_334_024_676_221, 23_416_728_348_467_685,
51 | 37_889_062_373_143_906, 61_305_790_721_611_591, 99_194_853_094_755_497,
52 | 160_500_643_816_367_088, 259_695_496_911_122_585, 420_196_140_727_489_673,
53 | 679_891_637_638_612_258, 1_100_087_778_366_101_931, 1_779_979_416_004_714_189,
54 | 2_880_067_194_370_816_120, 4_660_046_610_375_530_309, 7_540_113_804_746_346_429,
55 | 12_200_160_415_121_876_738,
56 | ]
57 | for i in fibonaccis.indices.dropLast(1) {
58 | let (gcd, overflow) = UInt64.gcdWithOverflow(fibonaccis[i + 1], fibonaccis[i])
59 | XCTAssert((gcd == 1) != overflow) // The Fibonacci numbers are relatively prime.
60 | }
61 |
62 | XCTAssert(Int64.gcdWithOverflow(Int64.min, Int64.min) == (Int64.min, true))
63 | XCTAssert(Int64.gcdWithOverflow(Int64.max, Int64.max) == (Int64.max, false))
64 |
65 | XCTAssert(UInt64.gcdWithOverflow(UInt64.min, UInt64.min) == (UInt64.min, false))
66 | XCTAssert(UInt64.gcdWithOverflow(UInt64.max, UInt64.max) == (UInt64.max, false))
67 | }
68 |
69 | func testLcm() {
70 | XCTAssert(Int32.lcmWithOverflow(1, 1) == (1, false))
71 | XCTAssert(Int32.lcmWithOverflow(1, 0) == (0, false))
72 | XCTAssert(Int32.lcmWithOverflow(0, 1) == (0, false))
73 | XCTAssert(Int32.lcmWithOverflow(0, 0) == (0, false))
74 | XCTAssert(Int32.lcmWithOverflow(1, -1) == (1, false))
75 | XCTAssert(Int32.lcmWithOverflow(-1, 1) == (1, false))
76 | XCTAssert(Int32.lcmWithOverflow(-1, -1) == (1, false))
77 |
78 | let factorial: Int64 = 2_432_902_008_176_640_000 // 20!
79 | let lcm: Int64 = 232_792_560 // lcm[1..20]
80 | XCTAssert(Int64.lcmWithOverflow(factorial, lcm) == (factorial, false))
81 |
82 | XCTAssert(Int64.lcmWithOverflow(Int64.min, Int64.min) == (Int64.min, true))
83 | XCTAssert(Int64.lcmWithOverflow(Int64.max, Int64.max) == (Int64.max, false))
84 |
85 | XCTAssert(UInt64.lcmWithOverflow(UInt64.min, UInt64.min) == (UInt64.min, false))
86 | XCTAssert(UInt64.lcmWithOverflow(UInt64.max, UInt64.max) == (UInt64.max, false))
87 | }
88 |
89 | static let allTests = [
90 | ("testGcd", testGcd),
91 | ("testLcm", testLcm),
92 | ]
93 | }
94 |
--------------------------------------------------------------------------------
/Sources/NumberKit/IntegerNumber.swift:
--------------------------------------------------------------------------------
1 | //
2 | // IntegerNumber.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 23/09/2017.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import Foundation
22 |
23 | /// Protocol `IntegerNumber` is used in combination with struct `Rational`.
24 | /// It defines the functionality needed for a signed integer implementation to
25 | /// build rational numbers on top. The `SignedInteger` protocol from the Swift 6
26 | /// standard library is unfortunately not sufficient as it doesn't provide access
27 | /// to methods reporting overflows explicitly.
28 | public protocol IntegerNumber: SomeIntegerNumber, SignedInteger {
29 | }
30 |
31 | /// Protocol `SomeIntegerNumber` defines new numeric functionality for all
32 | /// integer types, including unsigned integer types.
33 | public protocol SomeIntegerNumber: Numeric,
34 | Comparable,
35 | Hashable,
36 | CustomStringConvertible {
37 |
38 | /// Value zero
39 | static var zero: Self { get }
40 |
41 | /// Value one
42 | static var one: Self { get }
43 |
44 | /// Value two
45 | static var two: Self { get }
46 |
47 | /// Division operation.
48 | static func /(lhs: Self, rhs: Self) -> Self
49 |
50 | /// Division operation.
51 | static func /=(lhs: inout Self, rhs: Self)
52 |
53 | /// Remainder operation.
54 | static func %(lhs: Self, rhs: Self) -> Self
55 |
56 | /// Constructs an `IntegerNumber` from an `Int64` value. This constructor might crash if
57 | /// the value cannot be converted to this type.
58 | ///
59 | /// - Note: This is a hack right now.
60 | init(_ value: Int64)
61 |
62 | /// Constructs an `IntegerNumber` from a `Double` value. This constructor might crash if
63 | /// the value cannot be converted to this type.
64 | init(_ value: Double)
65 |
66 | /// Returns the integer as a `Double`.
67 | var doubleValue: Double { get }
68 |
69 | /// Computes the power of `self` with exponent `exp`.
70 | func toPower(of exp: Self) -> Self
71 |
72 | /// Returns true if this is an odd number.
73 | var isOdd: Bool { get }
74 |
75 | /// Adds `rhs` to `self` and reports the result together with a boolean indicating an overflow.
76 | func addingReportingOverflow(_ rhs: Self) -> (partialValue: Self, overflow: Bool)
77 |
78 | /// Subtracts `rhs` from `self` and reports the result together with a boolean indicating
79 | /// an overflow.
80 | func subtractingReportingOverflow(_ rhs: Self) -> (partialValue: Self, overflow: Bool)
81 |
82 | /// Multiplies `rhs` with `self` and reports the result together with a boolean indicating
83 | /// an overflow.
84 | func multipliedReportingOverflow(by rhs: Self) -> (partialValue: Self, overflow: Bool)
85 |
86 | /// Divides `self` by `rhs` and reports the result together with a boolean indicating
87 | /// an overflow.
88 | func dividedReportingOverflow(by rhs: Self) -> (partialValue: Self, overflow: Bool)
89 |
90 | /// Computes the remainder from dividing `self` by `rhs` and reports the result together
91 | /// with a boolean indicating an overflow.
92 | func remainderReportingOverflow(dividingBy rhs: Self) -> (partialValue: Self, overflow: Bool)
93 | }
94 |
95 | /// Provide default implementations of this protocol
96 | extension SomeIntegerNumber {
97 | public func toPower(of exp: Self) -> Self {
98 | precondition(exp >= 0, "IntegerNumber.toPower(of:) with negative exponent")
99 | var (expo, radix) = (exp, self)
100 | var res = Self.one
101 | while expo != 0 {
102 | if expo.isOdd {
103 | res *= radix
104 | }
105 | expo /= Self.two
106 | radix *= radix
107 | }
108 | return res
109 | }
110 |
111 | /// Returns the (non-negative) Greatest Common Divisor (GCD) of `x` and `y`. Any overflow
112 | /// occurring during the computation is ignored, iff the result cannot be represented in
113 | /// this type.
114 | public static func gcd(_ x: Self, _ y: Self) -> Self {
115 | return gcdWithOverflow(x, y).0
116 | }
117 |
118 | /// Compute the (non-negative) Least Common Multiple (LCM) of `x` and `y`. Any overflow
119 | /// occurring during the computation is ignored, iff the result cannot be represented
120 | /// in this type.
121 | public static func lcm(_ x: Self, _ y: Self) -> Self {
122 | return lcmWithOverflow(x, y).0
123 | }
124 |
125 | /// Returns the (non-negative) Greatest Common Divisor (GCD) of `x` and `y`, with a Boolean
126 | /// indicating whether overflow occurred in the computation, iff the result cannot be
127 | /// represented in this type.
128 | public static func gcdWithOverflow(_ x: Self, _ y: Self) -> (Self, Bool) {
129 | var (x, y, gcdOverflow) = (x, y, false)
130 | while y != 0 {
131 | let (remainder, remainderOverflow) = x.remainderReportingOverflow(dividingBy: y)
132 | (x, y, gcdOverflow) = (y, remainder, gcdOverflow || remainderOverflow)
133 | }
134 | let (absGcd, absOverflow) = absWithOverflow(x)
135 | return (absGcd, gcdOverflow || absOverflow)
136 | }
137 |
138 | /// Returns the (non-negative) Least Common Multiple (LCM) of `x` and `y`, with a Boolean
139 | /// indicating whether overflow occurred in the computation, iff the result cannot be
140 | /// represented in this type.
141 | public static func lcmWithOverflow(_ x: Self, _ y: Self) -> (Self, Bool) {
142 | if (x, y) == (0, 0) {
143 | return (0, false)
144 | }
145 | let (gcd, gcdOverflow) = gcdWithOverflow(x, y)
146 | let (lcm, lcmOverflow) = x.multipliedReportingOverflow(by: y / gcd)
147 | let (absLcm, absOverflow) = absWithOverflow(lcm)
148 | return (absLcm, gcdOverflow || lcmOverflow || absOverflow)
149 | }
150 |
151 | /// Returns the absolute value of `num`, along with a Boolean indicating whether overflow occurred in the operation,
152 | /// iff the absolute value cannot be represented in this type.
153 | static func absWithOverflow(_ num: Self) -> (value: Self, overflow: Bool) {
154 | return num < 0 ? Self.zero.subtractingReportingOverflow(num) : (num, false)
155 | }
156 | }
157 |
158 | /// Provide default implementations of fields needed by this protocol in all the fixed
159 | /// width numeric types.
160 | extension FixedWidthInteger {
161 | public static var zero: Self {
162 | return 0
163 | }
164 |
165 | public static var one: Self {
166 | return 1
167 | }
168 |
169 | public static var two: Self {
170 | return 2
171 | }
172 |
173 | public var isOdd: Bool {
174 | return (self & 1) == 1
175 | }
176 | }
177 |
178 | extension Int: IntegerNumber {
179 | public var doubleValue: Double {
180 | return Double(self)
181 | }
182 | }
183 |
184 | extension UInt: SomeIntegerNumber {
185 | public var doubleValue: Double {
186 | return Double(self)
187 | }
188 | }
189 |
190 | extension Int8: IntegerNumber {
191 | public var doubleValue: Double {
192 | return Double(self)
193 | }
194 | }
195 |
196 | extension UInt8: SomeIntegerNumber {
197 | public var doubleValue: Double {
198 | return Double(self)
199 | }
200 | }
201 |
202 | extension Int16: IntegerNumber {
203 | public var doubleValue: Double {
204 | return Double(self)
205 | }
206 | }
207 |
208 | extension UInt16: SomeIntegerNumber {
209 | public var doubleValue: Double {
210 | return Double(self)
211 | }
212 | }
213 |
214 | extension Int32: IntegerNumber {
215 | public var doubleValue: Double {
216 | return Double(self)
217 | }
218 | }
219 |
220 | extension UInt32: SomeIntegerNumber {
221 | public var doubleValue: Double {
222 | return Double(self)
223 | }
224 | }
225 |
226 | extension Int64: IntegerNumber {
227 | public var doubleValue: Double {
228 | return Double(self)
229 | }
230 | }
231 |
232 | extension UInt64: SomeIntegerNumber {
233 | public var doubleValue: Double {
234 | return Double(self)
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/Tests/NumberKitTests/IntegerTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // IntegerTests.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 12/04/2024.
6 | // Copyright © 2024 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import XCTest
22 | @testable import NumberKit
23 |
24 | @available(macOS 13.3, macCatalyst 16.4, iOS 16.4, watchOS 9.4, tvOS 9.4, *)
25 | class IntegerTests: XCTestCase {
26 |
27 | func testConstructors() {
28 | XCTAssert(Integer(0).intValue == 0)
29 | XCTAssert(Integer(1).intValue == 1)
30 | XCTAssert(Integer(-1).intValue == -1)
31 | XCTAssert(Integer(Int32.max / 3).intValue == Int64(Int32.max / 3))
32 | XCTAssert(Integer(Int64(Int32.max) * 3).intValue == Int64(Int32.max) * 3)
33 | XCTAssert(Integer(Int64(Int32.max) * Int64(Int32.max - 17)).intValue ==
34 | Int64(Int32.max) * Int64(Int32.max - 17))
35 | }
36 |
37 | #if canImport(Swift.StaticBigInt)
38 | func testPlus() {
39 | let x1: Integer = 314159265358979323846264338328
40 | XCTAssertEqual(x1 + x1, 628318530717958647692528676656)
41 | XCTAssertEqual(x1 + x1 + x1, 942477796076937971538793014984)
42 | XCTAssertEqual(x1 + x1 + x1 + x1, 1256637061435917295385057353312)
43 | XCTAssertEqual(x1 + x1 + x1 + 0 + x1, 1256637061435917295385057353312)
44 | XCTAssertEqual(x1 + x1 + x1 + 1 + x1, 1256637061435917295385057353313)
45 | let x2: Integer = 99564370914876591721233850654538777
46 | XCTAssertEqual(x2 + x2, 199128741829753183442467701309077554)
47 | XCTAssertEqual(x2 + x2 + 9234567890123456789012345678901234567890,
48 | 9234767018865286542195788146602543645444)
49 | }
50 | #endif
51 |
52 | #if canImport(Swift.StaticBigInt)
53 | func testPlusLiteral() {
54 | let x1: Integer = 31415926535897932384626433832809454874529274584894502801830108383756373931835
55 | XCTAssertEqual(x1 + x1, 62831853071795864769252867665618909749058549169789005603660216767512747863670)
56 | XCTAssertEqual(x1 + x1 + x1, 94247779607693797153879301498428364623587823754683508405490325151269121795505)
57 | XCTAssertEqual(x1 + x1 + x1 + x1, 125663706143591729538505735331237819498117098339578011207320433535025495727340)
58 | }
59 | #endif
60 |
61 | #if canImport(Swift.StaticBigInt)
62 | func testMinus() {
63 | let x1: Integer = 1134345924505409852113434
64 | let x2: Integer = 38274945700000001034304000024002450
65 | XCTAssertEqual(x1 - x2, -38274945698865655109798590171889016)
66 | XCTAssertEqual(x1 - 17 - x1, -17)
67 | XCTAssertEqual(x2 - x2, 0)
68 | XCTAssertEqual(x2 - 517 - x2, -517)
69 | XCTAssertEqual(x2 + 1 - x2, 1)
70 | let x3: Integer = 38274945700000001034304000024002449
71 | XCTAssertEqual(x2 - x3, 1)
72 | XCTAssertEqual(x3 - x2 + 18, 17)
73 | }
74 | #endif
75 |
76 | #if canImport(Swift.StaticBigInt)
77 | func testMinusLiteral() {
78 | let x1: Integer = -9999998765438765432131415926535897932384626433832809454874529274584894502801830108383756373931835
79 | let x2: Integer = -19999998765438765432131415926535897932384626433832809454874529274584894502801830108383756373931835
80 | XCTAssertEqual(1 + x1 - x2, 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001)
81 | XCTAssertEqual(x1 + x1 + x1, -29999996296316296296394247779607693797153879301498428364623587823754683508405490325151269121795505)
82 | XCTAssertEqual(-10 + x1 + x1 + x1 + x2, -49999995061755061728525663706143591729538505735331237819498117098339578011207320433535025495727350)
83 | }
84 | #endif
85 |
86 | #if canImport(Swift.StaticBigInt)
87 | func testTimes() {
88 | let x1: Integer = 89248574598402980294572048572242498123
89 | let x2: Integer = 84759720710000012134
90 | XCTAssertEqual(10 * x1 * x2, 75646842567262381047417645429775912936354166029204722244820)
91 | let x3: Integer = -846372893840594837726622221119029
92 | XCTAssertEqual(x1 * x3,
93 | -75537574353998534693615828134454330968785329792741330257228043492082567)
94 | }
95 | #endif
96 |
97 | #if canImport(Swift.StaticBigInt)
98 | func testTimesLiteral() {
99 | let x1: Integer = 89248574598402980294572048572242498123
100 | let x2: Integer = 84759720710000012134
101 | XCTAssertEqual(x1 * x2, 7564684256726238104741764542977591293635416602920472224482)
102 | let x3: Integer = -846372893840594837726622221119029
103 | XCTAssertEqual(-100 * x1 * 1 * x3,
104 | 7553757435399853469361582813445433096878532979274133025722804349208256700)
105 | }
106 | #endif
107 |
108 | #if canImport(Swift.StaticBigInt)
109 | func testDividedBy() {
110 | let x1: Integer = 38274945700000001034304000022452452525224002449
111 | let x2: Integer = 1234567890123456789
112 | let r1 = x1.divided(by: x2)
113 | XCTAssertEqual(r1.quotient, 31002706296024357530217920519)
114 | XCTAssertEqual(r1.remainder, 654242677691048958)
115 | let x3: Integer = 3827494570900000103430410002245245252522400244999
116 | let x4: Integer = 12345678901234567892344542545242452245
117 | let r2 = x3.divided(by: x4)
118 | XCTAssertEqual(r2.quotient, 310027063033)
119 | XCTAssertEqual(r2.remainder, 1772541951990552417813256094292885914)
120 | XCTAssertEqual(x3 / x3, 1)
121 | XCTAssertEqual(x3 / (x3 * 10), 0)
122 | }
123 | #endif
124 |
125 | #if canImport(Swift.StaticBigInt)
126 | func testRemainder() {
127 | let qp: Integer = 76292485249
128 | let qn: Integer = -76292485249
129 | let x1p: Integer = 12
130 | let x1n: Integer = -12
131 | let x2p: Integer = 7629248524991
132 | let x2n: Integer = -7629248524991
133 | XCTAssert(x1p % qp == x1p)
134 | XCTAssert(x1n % qp == x1n)
135 | XCTAssert(x1p % qn == x1p)
136 | XCTAssert(x1n % qn == x1n)
137 | let rp: Integer = 91
138 | let rn: Integer = -91
139 | XCTAssertEqual(x2p % qp, rp)
140 | XCTAssertEqual(x2n % qp, rn)
141 | XCTAssertEqual(x2p % qn, rp)
142 | XCTAssertEqual(x2n % qn, rn)
143 | }
144 | #endif
145 |
146 | #if canImport(Swift.StaticBigInt)
147 | func testSqrt() {
148 | let x1: Integer = 987248974087420857240857208746297469247698798798798700
149 | XCTAssertEqual(x1.sqrt, 993604032845791572092520365)
150 | let x2: Integer = 785035630596835096835069835069385609358603956830596835096835069835608390000
151 | XCTAssertEqual(x2.sqrt, 28018487300295765553963049921800641599)
152 | let x3: Integer = 1000000000000
153 | XCTAssertEqual(x3.sqrt, 1000000)
154 | }
155 | #endif
156 |
157 | #if canImport(Swift.StaticBigInt)
158 | func testPowerOf() {
159 | let x1: Integer = 84570248572048572408572048572048
160 | let y1 = x1 * x1 * x1 * x1
161 | XCTAssert(x1.toPower(of: Integer(4)) == y1)
162 | }
163 | #endif
164 |
165 | func testDoubleConversion() {
166 | let x1: Double = 34134342324888777666555444333.1343141341341 * 10000000000000000.0
167 | let y1 = Integer(x1)
168 | XCTAssertEqual(x1, y1.doubleValue)
169 | let x2: Double = -998877665544332211.123456789 * 10000000000000000.0
170 | let y2 = Integer(x2)
171 | XCTAssertEqual(x2, y2.doubleValue)
172 | let x3 = Double(UInt64.max)
173 | let y3 = Integer(x3)
174 | XCTAssertEqual(x3, y3.doubleValue)
175 | let x4 = Double(UInt64.max)
176 | let y4 = Integer(x4)
177 | let z4 = Integer(UInt64.max)
178 | XCTAssertEqual(y4.doubleValue, z4.doubleValue)
179 | }
180 |
181 | func testFloatConversion() {
182 | let x0: Float = 34133.134314134134132
183 | let y0 = Integer(exactly: x0)
184 | XCTAssertEqual(y0, nil)
185 | let x1: Float = 34134342324888777633.1343141341341 * 1000000000000.0
186 | let y1 = Integer(exactly: x1)
187 | XCTAssertEqual(Double(x1), (y1 ?? Integer.zero).doubleValue)
188 | let x2: Float = -998877665544332211.123456789 * 10000000000000000.0
189 | let y2 = Integer(x2)
190 | XCTAssertEqual(Double(x2), y2.doubleValue)
191 | let x3 = Float(Int64.min)
192 | let y3 = Integer(x3)
193 | XCTAssertEqual(Double(x3), y3.doubleValue)
194 | }
195 |
196 | #if canImport(Swift.StaticBigInt)
197 | func testAnd() {
198 | let x0: Integer = 13
199 | let y0: Integer = -234245400000000001111
200 | XCTAssertEqual(x0 & y0, Integer(9))
201 | let x1: Integer = 234245400000000001111
202 | let y1: Integer = -9846504850258720458
203 | let z1: Integer = 224984655330917548054
204 | XCTAssertEqual(x1 & y1, z1)
205 | XCTAssertEqual(Integer(-1) & Integer(-2), Integer(-2))
206 | let x2: Integer = -542455245094524566901
207 | let y2: Integer = -542455245094524566900
208 | let z2: Integer = -542455245094524566904
209 | XCTAssertEqual(x2 & y2, z2)
210 | let x3: Integer = 9087536870576087630587630586735
211 | let y3: Integer = -783098795876350358367035603567035670358
212 | let z3: Integer = 8879166037613449274055524745258
213 | XCTAssertEqual(x3 & y3, z3)
214 | let x4: Integer = -98040972987924857928456297456297659276249762976245659762459
215 | let y4: Integer = 9864520842504292089860983506873560870
216 | let z4: Integer = 58540432875177786070779388280897572
217 | XCTAssertEqual(x4 & y4, z4)
218 | let x5: Integer = -31
219 | let y5: Integer = -4444335366627281172636646645342263748485595
220 | let z5: Integer = -4444335366627281172636646645342263748485599
221 | XCTAssertEqual(x5 & y5, z5)
222 | let x6: Integer = -3453452461354444335366627281172636646645342263748485599
223 | let y6: Integer = 1023
224 | let z6: Integer = 545
225 | XCTAssertEqual(x6 & y6, z6)
226 | }
227 | #endif
228 |
229 | #if canImport(Swift.StaticBigInt)
230 | func testShifts() {
231 | let x1: Integer = 987248974087420857
232 | XCTAssertEqual(x1 << 1, x1 * 2)
233 | let x2: Integer = 9872489740874208572408572
234 | XCTAssertEqual(x2 << 1, x2 * 2)
235 | let x3: Integer = 98724897408742085724085724524524524524524522454525245999
236 | XCTAssertEqual(x3 << 9, x3 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2)
237 | let x4: Integer = 987248974087420857
238 | XCTAssertEqual(x4 >> 1, x4 / 2)
239 | let x5: Integer = 9872489740874208572408572
240 | XCTAssertEqual(x5 >> 1, x5 / 2)
241 | let x6: Integer = 98724897408742085724085724524524524524524522454525245999098037580357603865
242 | XCTAssertEqual(x6 >> 5, x6 / 32)
243 | let x7: Integer = -234245400000000001111
244 | let r7: Integer = -1830042187500000009
245 | XCTAssertEqual(x7 >> 7, r7)
246 | let x8: Integer = -987248974087420857240857245245245245245245224545252459990980375803576038650
247 | let r8: Integer = -28732726760424582090952237056488091045910411763041410012839489378
248 | XCTAssertEqual(x8 >> 35, r8)
249 | let x9: Integer = -1
250 | XCTAssertEqual(x9 >> 1, x9)
251 | let x10: Integer = -2
252 | XCTAssertEqual(x10 >> 1, x9)
253 | let x11: Integer = -3
254 | XCTAssertEqual(x11 >> 1, x10)
255 | let x12: Integer = -4
256 | XCTAssertEqual(x12 >> 1, x10)
257 | let x13: Integer = -100000000000000000000000000000000
258 | let r13: Integer = -79
259 | XCTAssertEqual(x13 >> 100, r13)
260 | let r14: Integer = -126765060022822940149670320537600000000000000000000000000000000
261 | XCTAssertEqual(x13 << 100, r14)
262 | let x15: Integer = -9872489740874208572408572
263 | let r15: Integer = -1356864658148807688588085270081961984
264 | XCTAssertEqual(x15 << 37, r15)
265 | let x16: Integer = -111308731087301939383033999999
266 | let r16: Integer = -131410155234356299897170703642124868710991004696576
267 | XCTAssertEqual(x16 << 70, r16)
268 | }
269 | #endif
270 |
271 | #if canImport(Swift.StaticBigInt)
272 | func testBitCount() {
273 | let x0: Integer = 172
274 | XCTAssertEqual(x0.bitCount, 4)
275 | let x1: Integer = 4285720457204597
276 | XCTAssertEqual(x1.bitCount, 31)
277 | let x2: Integer = 8708356703856085653607835677770
278 | XCTAssertEqual(x2.bitCount, 55)
279 | let x3: Integer = 98724897408742085724085724524524524524524522454525245999
280 | XCTAssertEqual(x3.bitCount, 100)
281 | let x4: Integer = 9872489740874208572408572452452452452452452245452524599909803758035760386501
282 | XCTAssertEqual(x4.bitCount, 120)
283 | let x5: Integer = -127
284 | XCTAssertEqual(x5.bitCount, -7)
285 | let x6: Integer = -4285720457204597
286 | XCTAssertEqual(x6.bitCount, -31)
287 | let x7: Integer = -8708356703856085653607835677770
288 | XCTAssertEqual(x7.bitCount, -56)
289 | let x8: Integer = -98724897408742085724085724524524524524524522454525245999
290 | XCTAssertEqual(x8.bitCount, -100)
291 | let x9: Integer = -987248974087420857240857245245245245245245224545252459990980375803576038650
292 | XCTAssertEqual(x9.bitCount, -115)
293 | }
294 | #endif
295 |
296 | #if canImport(Swift.StaticBigInt)
297 | func testWords() {
298 | let x1: Integer = 39998740587340080087986767562130873870358038157034635280980314708375001
299 | XCTAssertEqual(x1.words, [17444856893563336153,
300 | 10071105391305811219,
301 | 12534310513326413052,
302 | 6372167008517,
303 | 0])
304 | let x2: Integer = -x1
305 | XCTAssertEqual(x2.words, [1001887180146215463,
306 | 8375638682403740396,
307 | 5912433560383138563,
308 | 18446737701542543098,
309 | 18446744073709551615])
310 | let x3: Integer = x1 >> 64
311 | XCTAssertEqual(x3.words, [10071105391305811219,
312 | 12534310513326413052,
313 | 6372167008517,
314 | 0])
315 | let x4: Integer = Integer(UInt.max)
316 | XCTAssertEqual(x4.words, [18446744073709551615, 0])
317 | let x5: Integer = -x4
318 | XCTAssertEqual(x5.words, [1,18446744073709551615])
319 | let x6: Integer = -x5
320 | XCTAssertEqual(x6.words, [18446744073709551615, 0])
321 | let x7: Integer = Integer(UInt.max) + 1
322 | XCTAssertEqual(x7.words, [0, 1, 0])
323 | }
324 | #endif
325 |
326 | #if canImport(Swift.StaticBigInt)
327 | func testRandom() {
328 | let rnd1 = Integer.random(withMaxBits: 218)
329 | XCTAssert(rnd1.bitCount <= 218)
330 | XCTAssert(rnd1.bitSize < 218 + UInt32.bitWidth)
331 | let rnd2 = Integer.random(withMaxBits: 22)
332 | XCTAssert(rnd2.bitCount <= 22)
333 | XCTAssert(rnd2.bitSize < 22 + UInt32.bitWidth)
334 | let bound: Integer = 9856024857249581231765137423436847588346498948545927456
335 | let rnd3 = Integer.random(below: bound)
336 | XCTAssert(rnd3 < bound)
337 | let bound2: Integer = 123123
338 | let rnd4 = Integer.random(below: bound2)
339 | XCTAssert(rnd4 < bound2)
340 | }
341 | #endif
342 |
343 | func testBasicOpWithZero() {
344 | let x1: Integer = 0
345 | let x2: Integer = -1
346 | XCTAssertFalse(x1.isNegative)
347 | XCTAssertFalse(x1.negate.isNegative)
348 | XCTAssertEqual(x2 + x1, x2)
349 | XCTAssertEqual(x2 - x1, x2)
350 | }
351 |
352 | #if canImport(Swift.StaticBigInt)
353 | static let allTests = [
354 | ("testConstructors", testConstructors),
355 | ("testPlus", testPlus),
356 | ("testMinus", testMinus),
357 | ("testTimes", testTimes),
358 | ("testDividedBy", testDividedBy),
359 | ("testRemainder", testRemainder),
360 | ("testSqrt", testSqrt),
361 | ("testPowerOf", testPowerOf),
362 | ("testDoubleConversion", testDoubleConversion),
363 | ("testFloatConversion", testFloatConversion),
364 | ("testAnd", testAnd),
365 | ("testShifts", testShifts),
366 | ("testBitCount", testBitCount),
367 | ("testWords", testWords)
368 | ]
369 | #else
370 | static let allTests = [
371 | ("testConstructors", testConstructors),
372 | ("testDoubleConversion", testDoubleConversion),
373 | ("testFloatConversion", testFloatConversion),
374 | ("testBasicOpWithZero", testBasicOpWithZero)
375 | ]
376 | #endif
377 | }
378 |
--------------------------------------------------------------------------------
/Sources/NumberKit/Integer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Integer.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 11/04/2024.
6 | // Copyright © 2024 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,x either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import Foundation
22 |
23 | /// `Integer` implements signed, arbitrary-size integers. As opposed to `BigInt`,
24 | /// the representation of `Integer` numbers falls back to `Int64` when possible,
25 | /// minimizing memory overhead and increasing the performance of arithmetic operations.
26 | /// `Integer` supports `StaticBigInt`literals, i.e. is is possible to use arbitrary
27 | /// length integer literals.
28 | public enum Integer: IntegerNumber,
29 | SignedInteger,
30 | Hashable,
31 | Codable,
32 | Sendable,
33 | CustomStringConvertible,
34 | CustomDebugStringConvertible {
35 | case int(Int64)
36 | case bigInt(BigInt)
37 |
38 | public static var zero: Integer {
39 | return .int(0)
40 | }
41 |
42 | public static var one: Integer {
43 | return .int(1)
44 | }
45 |
46 | public static var two: Integer {
47 | return .int(2)
48 | }
49 |
50 | public init(from decoder: Decoder) throws {
51 | let container = try decoder.singleValueContainer()
52 | if let intNum = try? container.decode(Int64.self) {
53 | self = .int(intNum)
54 | } else if let bigIntNum = try? container.decode(BigInt.self) {
55 | self = .bigInt(bigIntNum)
56 | } else {
57 | throw DecodingError.dataCorrupted(
58 | DecodingError.Context(codingPath: decoder.codingPath,
59 | debugDescription: "Invalid Integer encoding"))
60 | }
61 | }
62 |
63 | public func encode(to encoder: Encoder) throws {
64 | var container = encoder.singleValueContainer()
65 | switch self {
66 | case .int(let num):
67 | try container.encode(num)
68 | case .bigInt(let num):
69 | try container.encode(num)
70 | }
71 | }
72 |
73 | public var description: String {
74 | switch self {
75 | case .int(let num):
76 | return num.description
77 | case .bigInt(let num):
78 | return num.description
79 | }
80 | }
81 |
82 | public var debugDescription: String {
83 | switch self {
84 | case .int(let num):
85 | return num.description
86 | case .bigInt(let num):
87 | return num.debugDescription
88 | }
89 | }
90 |
91 | public var isBigInt: Bool {
92 | guard case .bigInt(_) = self else {
93 | return false
94 | }
95 | return true
96 | }
97 |
98 | public var doubleValue: Double {
99 | switch self {
100 | case .int(let num):
101 | return num.doubleValue
102 | case .bigInt(let num):
103 | return num.doubleValue
104 | }
105 | }
106 |
107 | public var isOdd: Bool {
108 | switch self {
109 | case .int(let num):
110 | return num.isOdd
111 | case .bigInt(let num):
112 | return num.isOdd
113 | }
114 | }
115 |
116 | public init(_ value: Int64) {
117 | self = .int(value)
118 | }
119 |
120 | public init(_ value: BigInt) {
121 | if let intNum = value.intValue {
122 | self = .int(intNum)
123 | } else {
124 | self = .bigInt(value)
125 | }
126 | }
127 |
128 | public init(_ value: Double) {
129 | let bigIntNum = BigInt(value)
130 | if let intNum = bigIntNum.intValue {
131 | self = .int(intNum)
132 | } else {
133 | self = .bigInt(bigIntNum)
134 | }
135 | }
136 |
137 | public init(_ source: T) {
138 | if let value = Int64(exactly: source) {
139 | self = .int(value)
140 | } else {
141 | self = Integer(BigInt(source))
142 | }
143 | }
144 |
145 | public init?(exactly: T) {
146 | self.init(exactly)
147 | }
148 |
149 | public init(clamping: T) {
150 | self.init(clamping)
151 | }
152 |
153 | public init(truncatingIfNeeded: T) {
154 | self.init(truncatingIfNeeded)
155 | }
156 |
157 | public init(_ source: T) {
158 | if let intNum = Int64(exactly: source) {
159 | self = .int(intNum)
160 | } else if let bigIntNum = BigInt(exactly: source) {
161 | self = .bigInt(bigIntNum)
162 | } else {
163 | self = .int(Int64(source))
164 | }
165 | }
166 |
167 | public init?(exactly source: T) {
168 | if let intNum = Int64(exactly: source) {
169 | self = .int(intNum)
170 | } else if let bigIntNum = BigInt(exactly: source) {
171 | self = .bigInt(bigIntNum)
172 | } else {
173 | return nil
174 | }
175 | }
176 |
177 | public var intValue: Int64? {
178 | switch self {
179 | case .int(let num):
180 | return num
181 | case .bigInt(_):
182 | return nil
183 | }
184 | }
185 |
186 | public var bigIntValue: BigInt {
187 | switch self {
188 | case .int(let num):
189 | return BigInt(num)
190 | case .bigInt(let num):
191 | return num
192 | }
193 | }
194 |
195 | public var words: [UInt] {
196 | switch self {
197 | case .int(let num):
198 | return BigInt(num).words
199 | case .bigInt(let num):
200 | return num.words
201 | }
202 | }
203 |
204 | public var magnitude: Integer {
205 | switch self {
206 | case .int(let num):
207 | return Integer(BigInt(num.magnitude))
208 | case .bigInt(let num):
209 | return Integer(num.magnitude)
210 | }
211 | }
212 |
213 | public var bitWidth: Int {
214 | switch self {
215 | case .int(let num):
216 | return num.bitWidth
217 | case .bigInt(let num):
218 | return num.bitWidth
219 | }
220 | }
221 |
222 | public var trailingZeroBitCount: Int {
223 | switch self {
224 | case .int(let num):
225 | return num.trailingZeroBitCount
226 | case .bigInt(let num):
227 | return num.trailingZeroBitCount
228 | }
229 | }
230 |
231 | public var isNegative: Bool {
232 | switch self {
233 | case .int(let num):
234 | return num < 0
235 | case .bigInt(let num):
236 | return num.isNegative
237 | }
238 | }
239 |
240 | public var isZero: Bool {
241 | switch self {
242 | case .int(let num):
243 | return num == 0
244 | case .bigInt(let num):
245 | return num.isZero
246 | }
247 | }
248 |
249 | public var negate: Integer {
250 | switch self {
251 | case .int(let num):
252 | if num == .min {
253 | return Integer(BigInt(num).negate)
254 | } else {
255 | return .int(-num)
256 | }
257 | case .bigInt(let num):
258 | return Integer(BigInt(num).negate)
259 | }
260 | }
261 |
262 | public var abs: Integer {
263 | switch self {
264 | case .int(let num):
265 | if num == .min {
266 | return .bigInt(BigInt(num).abs)
267 | } else {
268 | return .int(Swift.abs(num))
269 | }
270 | case .bigInt(let num):
271 | return Integer(num.abs)
272 | }
273 | }
274 |
275 | public func divided(by rhs: Integer) -> (quotient: Integer, remainder: Integer) {
276 | let (q, r) = self.bigIntValue.divided(by: rhs.bigIntValue)
277 | return (Integer(q), Integer(r))
278 | }
279 |
280 | public func toPower(of exp: Integer) -> Integer {
281 | return Integer(self.bigIntValue.toPower(of: exp.bigIntValue))
282 | }
283 |
284 | public var sqrt: Integer {
285 | return Integer(self.bigIntValue.sqrt)
286 | }
287 |
288 | /// Adds `n` and returns the result.
289 | public func advanced(by n: Integer) -> Integer {
290 | return self + n
291 | }
292 |
293 | /// Computes the distance to `other` and returns the result.
294 | public func distance(to other: Integer) -> Integer {
295 | return other - self
296 | }
297 |
298 | /// Returns -1 if `self` is less than `rhs`,
299 | /// 0 if `self` is equals to `rhs`,
300 | /// +1 if `self` is greater than `rhs`
301 | public func compare(to rhs: Integer) -> Int {
302 | switch self {
303 | case .int(let lval):
304 | switch rhs {
305 | case .int(let rval):
306 | return lval == rval ? 0 : lval < rval ? -1 : 1
307 | case .bigInt(let rval):
308 | return BigInt(lval).compare(to: rval)
309 | }
310 | case .bigInt(let lval):
311 | switch rhs {
312 | case .int(let rval):
313 | return lval.compare(to: BigInt(rval))
314 | case .bigInt(let rval):
315 | return lval.compare(to: rval)
316 | }
317 | }
318 | }
319 |
320 | /// Number of bits used to represent the (unsigned) `Integer` number.
321 | public var bitSize: Int {
322 | return self.bigIntValue.bitSize
323 | }
324 |
325 | /// Number of bits set in this `Integer` number. For negative numbers, `n.bigCount` returns
326 | /// `~n.not.bigCount`.
327 | public var bitCount: Int {
328 | return self.bigIntValue.bitCount
329 | }
330 |
331 | /// Returns a random non-negative `Integer` with up to `bitWidth` bits using the random number
332 | /// generator `generator`.
333 | public static func random(withMaxBits bitWidth: Int,
334 | using generator: inout R) -> Integer {
335 | return Integer(BigInt.random(withMaxBits: bitWidth, using: &generator))
336 | }
337 |
338 | /// Returns a random non-negative `Integer` with up to `bitWidth` bits using the system
339 | /// random number generator.
340 | public static func random(withMaxBits bitWidth: Int) -> Integer {
341 | return Integer(BigInt.random(withMaxBits: bitWidth))
342 | }
343 |
344 | /// Returns a random non-negative `Integer` below the given upper bound `bound` using the
345 | /// random number generator `generator`.
346 | public static func random(below bound: Integer,
347 | using generator: inout R) -> Integer {
348 | return Integer(BigInt.random(below: bound.bigIntValue, using: &generator))
349 | }
350 |
351 | /// Returns a random non-negative `Integer` below the given upper bound `bound` using
352 | /// the system random number generator.
353 | public static func random(below bound: Integer) -> Integer {
354 | return Integer(BigInt.random(below: bound.bigIntValue))
355 | }
356 |
357 | public static prefix func -(x: Integer) -> Integer {
358 | return x.negate
359 | }
360 |
361 | public static prefix func ~(x: Integer) -> Integer {
362 | switch x {
363 | case .int(let num):
364 | return .int(~num)
365 | case .bigInt(let num):
366 | return .bigInt(~num)
367 | }
368 | }
369 |
370 | public static func +(lhs: Integer, rhs: Integer) -> Integer {
371 | switch lhs {
372 | case .int(let lval):
373 | switch rhs {
374 | case .int(let rval):
375 | let (res, overflow) = lval.addingReportingOverflow(rval)
376 | if overflow {
377 | return .bigInt(BigInt(lval) + BigInt(rval))
378 | } else {
379 | return .int(res)
380 | }
381 | case .bigInt(let rval):
382 | return Integer(BigInt(lval) + rval)
383 | }
384 | case .bigInt(let lval):
385 | switch rhs {
386 | case .int(let rval):
387 | return Integer(lval + BigInt(rval))
388 | case .bigInt(let rval):
389 | return Integer(lval + rval)
390 | }
391 | }
392 | }
393 |
394 | public static func -(lhs: Integer, rhs: Integer) -> Integer {
395 | switch lhs {
396 | case .int(let lval):
397 | switch rhs {
398 | case .int(let rval):
399 | let (res, overflow) = lval.subtractingReportingOverflow(rval)
400 | if overflow {
401 | return Integer(BigInt(lval) - BigInt(rval))
402 | } else {
403 | return .int(res)
404 | }
405 | case .bigInt(let rval):
406 | return Integer(BigInt(lval) - rval)
407 | }
408 | case .bigInt(let lval):
409 | switch rhs {
410 | case .int(let rval):
411 | return Integer(lval - BigInt(rval))
412 | case .bigInt(let rval):
413 | return Integer(lval - rval)
414 | }
415 | }
416 | }
417 |
418 | public static func *(lhs: Integer, rhs: Integer) -> Integer {
419 | switch lhs {
420 | case .int(let lval):
421 | switch rhs {
422 | case .int(let rval):
423 | let (res, overflow) = lval.multipliedReportingOverflow(by: rval)
424 | if overflow {
425 | return Integer(BigInt(lval) * BigInt(rval))
426 | } else {
427 | return .int(res)
428 | }
429 | case .bigInt(let rval):
430 | return Integer(BigInt(lval) * rval)
431 | }
432 | case .bigInt(let lval):
433 | switch rhs {
434 | case .int(let rval):
435 | return Integer(lval * BigInt(rval))
436 | case .bigInt(let rval):
437 | return Integer(lval * rval)
438 | }
439 | }
440 | }
441 |
442 | public static func /(lhs: Integer, rhs: Integer) -> Integer {
443 | switch lhs {
444 | case .int(let lval):
445 | switch rhs {
446 | case .int(let rval):
447 | let (res, overflow) = lval.dividedReportingOverflow(by: rval)
448 | if overflow {
449 | return Integer(BigInt(lval) / BigInt(rval))
450 | } else {
451 | return .int(res)
452 | }
453 | case .bigInt(let rval):
454 | return Integer(BigInt(lval) / rval)
455 | }
456 | case .bigInt(let lval):
457 | switch rhs {
458 | case .int(let rval):
459 | return Integer(lval / BigInt(rval))
460 | case .bigInt(let rval):
461 | return Integer(lval / rval)
462 | }
463 | }
464 | }
465 |
466 | public static func %(lhs: Integer, rhs: Integer) -> Integer {
467 | switch lhs {
468 | case .int(let lval):
469 | switch rhs {
470 | case .int(let rval):
471 | let (res, overflow) = lval.remainderReportingOverflow(dividingBy: rval)
472 | if overflow {
473 | return Integer(BigInt(lval) % BigInt(rval))
474 | } else {
475 | return .int(res)
476 | }
477 | case .bigInt(let rval):
478 | return Integer(BigInt(lval) % rval)
479 | }
480 | case .bigInt(let lval):
481 | switch rhs {
482 | case .int(let rval):
483 | return Integer(lval % BigInt(rval))
484 | case .bigInt(let rval):
485 | return Integer(lval % rval)
486 | }
487 | }
488 | }
489 |
490 | public static func &(lhs: Integer, rhs: Integer) -> Integer {
491 | switch lhs {
492 | case .int(let lval):
493 | switch rhs {
494 | case .int(let rval):
495 | return .int(lval & rval)
496 | case .bigInt(let rval):
497 | return Integer(BigInt(lval) & rval)
498 | }
499 | case .bigInt(let lval):
500 | switch rhs {
501 | case .int(let rval):
502 | return Integer(lval & BigInt(rval))
503 | case .bigInt(let rval):
504 | return Integer(lval & rval)
505 | }
506 | }
507 | }
508 |
509 | public static func |(lhs: Integer, rhs: Integer) -> Integer {
510 | switch lhs {
511 | case .int(let lval):
512 | switch rhs {
513 | case .int(let rval):
514 | return .int(lval | rval)
515 | case .bigInt(let rval):
516 | return Integer(BigInt(lval) | rval)
517 | }
518 | case .bigInt(let lval):
519 | switch rhs {
520 | case .int(let rval):
521 | return Integer(lval | BigInt(rval))
522 | case .bigInt(let rval):
523 | return Integer(lval | rval)
524 | }
525 | }
526 | }
527 |
528 | public static func ^(lhs: Integer, rhs: Integer) -> Integer {
529 | switch lhs {
530 | case .int(let lval):
531 | switch rhs {
532 | case .int(let rval):
533 | return .int(lval ^ rval)
534 | case .bigInt(let rval):
535 | return Integer(BigInt(lval) ^ rval)
536 | }
537 | case .bigInt(let lval):
538 | switch rhs {
539 | case .int(let rval):
540 | return Integer(lval ^ BigInt(rval))
541 | case .bigInt(let rval):
542 | return Integer(lval ^ rval)
543 | }
544 | }
545 | }
546 |
547 | public static func << (lhs: Integer, rhs: T) -> Integer {
548 | return Integer(lhs.bigIntValue << rhs)
549 | }
550 |
551 | public static func >> (lhs: Integer, rhs: T) -> Integer {
552 | return Integer(lhs.bigIntValue >> rhs)
553 | }
554 |
555 | public static func +=(lhs: inout Integer, rhs: Integer) {
556 | lhs = lhs + rhs
557 | }
558 |
559 | public static func -=(lhs: inout Integer, rhs: Integer) {
560 | lhs = lhs - rhs
561 | }
562 |
563 | public static func *=(lhs: inout Integer, rhs: Integer) {
564 | lhs = lhs * rhs
565 | }
566 |
567 | public static func /=(lhs: inout Integer, rhs: Integer) {
568 | lhs = lhs / rhs
569 | }
570 |
571 | public static func %= (lhs: inout Integer, rhs: Integer) {
572 | lhs = lhs % rhs
573 | }
574 |
575 | public static func &= (lhs: inout Integer, rhs: Integer) {
576 | lhs = lhs & rhs
577 | }
578 |
579 | public static func |= (lhs: inout Integer, rhs: Integer) {
580 | lhs = lhs | rhs
581 | }
582 |
583 | public static func ^=(lhs: inout Integer, rhs: Integer) {
584 | lhs = lhs ^ rhs
585 | }
586 |
587 | public static func <<=(lhs: inout Integer, rhs: T) {
588 | lhs = lhs << rhs
589 | }
590 |
591 | public static func >>=(lhs: inout Integer, rhs: T) {
592 | lhs = lhs >> rhs
593 | }
594 |
595 | public static func <(lhs: Integer, rhs: Integer) -> Bool {
596 | return lhs.compare(to: rhs) < 0
597 | }
598 |
599 | public static func <=(lhs: Integer, rhs: Integer) -> Bool {
600 | return lhs.compare(to: rhs) <= 0
601 | }
602 |
603 | public static func >=(lhs: Integer, rhs: Integer) -> Bool {
604 | return lhs.compare(to: rhs) >= 0
605 | }
606 |
607 | public static func >(lhs: Integer, rhs: Integer) -> Bool {
608 | return lhs.compare(to: rhs) > 0
609 | }
610 |
611 | public static func ==(lhs: Integer, rhs: Integer) -> Bool {
612 | return lhs.compare(to: rhs) == 0
613 | }
614 |
615 | public static func !=(lhs: Integer, rhs: Integer) -> Bool {
616 | return lhs.compare(to: rhs) != 0
617 | }
618 |
619 | public func addingReportingOverflow(_ rhs: Integer) -> (partialValue: Integer, overflow: Bool) {
620 | return (self + rhs, false)
621 | }
622 |
623 | public func subtractingReportingOverflow(_ rhs: Integer) -> (partialValue: Integer, overflow: Bool) {
624 | return (self - rhs, false)
625 | }
626 |
627 | public func multipliedReportingOverflow(by rhs: Integer) -> (partialValue: Integer, overflow: Bool) {
628 | return (self * rhs, false)
629 | }
630 |
631 | public func dividedReportingOverflow(by rhs: Integer) -> (partialValue: Integer, overflow: Bool) {
632 | return (self / rhs, false)
633 | }
634 |
635 | public func remainderReportingOverflow(dividingBy rhs: Integer) -> (partialValue: Integer, overflow: Bool) {
636 | return (self % rhs, false)
637 | }
638 | }
639 |
640 | #if canImport(Swift.StaticBigInt)
641 | extension Integer: ExpressibleByIntegerLiteral {
642 | public init(integerLiteral value: StaticBigInt) {
643 | self = Integer(BigInt(integerLiteral: value))
644 | }
645 | }
646 | #else
647 | extension Integer: ExpressibleByIntegerLiteral {
648 | public init(integerLiteral value: Int64) {
649 | self.init(value)
650 | }
651 | }
652 | #endif
653 |
654 | /// Returns the maximum of `fst` and `snd`.
655 | public func max(_ fst: Integer, _ snd: Integer) -> Integer {
656 | return fst.compare(to: snd) >= 0 ? fst : snd
657 | }
658 |
659 | /// Returns the minimum of `fst` and `snd`.
660 | public func min(_ fst: Integer, _ snd: Integer) -> Integer {
661 | return fst.compare(to: snd) <= 0 ? fst : snd
662 | }
663 |
--------------------------------------------------------------------------------
/Tests/NumberKitTests/BigIntTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BigIntTests.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 11/08/2015.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import XCTest
22 | @testable import NumberKit
23 |
24 | class BigIntTests: XCTestCase {
25 |
26 | func testConstructors() {
27 | XCTAssert(BigInt(0).intValue == 0)
28 | XCTAssert(BigInt(1).intValue == 1)
29 | XCTAssert(BigInt(-1).intValue == -1)
30 | XCTAssert(BigInt(Int32.max / 3).intValue == Int64(Int32.max / 3))
31 | XCTAssert(BigInt(Int64(Int32.max) * 3).intValue == Int64(Int32.max) * 3)
32 | XCTAssert(BigInt(Int64(Int32.max) * Int64(Int32.max - 17)).intValue ==
33 | Int64(Int32.max) * Int64(Int32.max - 17))
34 | XCTAssert(BigInt(Int64(Int32.max) * Int64(Int32.max - 17)).uintValue ==
35 | UInt64(Int32.max) * UInt64(Int32.max - 17))
36 | }
37 |
38 | func testPlus() {
39 | let x1: BigInt = "314159265358979323846264338328"
40 | XCTAssert(x1.plus(x1) == "628318530717958647692528676656")
41 | XCTAssert(x1.plus(x1).plus(x1) == "942477796076937971538793014984")
42 | XCTAssert(x1.plus(x1).plus(x1).plus(x1) == "1256637061435917295385057353312")
43 | XCTAssert(x1.plus(x1).plus(x1).plus(0).plus(x1) == "1256637061435917295385057353312")
44 | XCTAssert(x1.plus(x1).plus(x1).plus(1).plus(x1) == "1256637061435917295385057353313")
45 | let x2: BigInt = "99564370914876591721233850654538777"
46 | XCTAssert(x2.plus(x2) == "199128741829753183442467701309077554")
47 | XCTAssert(x2.plus(x2).plus("9234567890123456789012345678901234567890") ==
48 | "9234767018865286542195788146602543645444")
49 | }
50 |
51 | #if canImport(Swift.StaticBigInt)
52 | func testPlusLiteral() {
53 | let x1: BigInt = 31415926535897932384626433832809454874529274584894502801830108383756373931835
54 | XCTAssertEqual(x1.plus(x1), 62831853071795864769252867665618909749058549169789005603660216767512747863670)
55 | XCTAssertEqual(x1.plus(x1).plus(x1), 94247779607693797153879301498428364623587823754683508405490325151269121795505)
56 | XCTAssertEqual(x1.plus(x1).plus(x1).plus(x1), 125663706143591729538505735331237819498117098339578011207320433535025495727340)
57 | }
58 | #endif
59 |
60 | func testMinus() {
61 | let x1: BigInt = "1134345924505409852113434"
62 | let x2: BigInt = "38274945700000001034304000024002450"
63 | XCTAssert(x1.minus(x2) == "-38274945698865655109798590171889016")
64 | XCTAssert(x1.minus(x1) == 0)
65 | XCTAssert(x2.minus(x2) == 0)
66 | XCTAssert(x2.plus(1).minus(x2) == 1)
67 | let x3: BigInt = "38274945700000001034304000024002449"
68 | XCTAssert(x2.minus(x3) == 1)
69 | XCTAssert(x3.minus(x2) == -1)
70 | }
71 |
72 | #if canImport(Swift.StaticBigInt)
73 | func testMinusLiteral() {
74 | let x1: BigInt = -9999998765438765432131415926535897932384626433832809454874529274584894502801830108383756373931835
75 | let x2: BigInt = -19999998765438765432131415926535897932384626433832809454874529274584894502801830108383756373931835
76 | XCTAssertEqual(x1.minus(x2), 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)
77 | XCTAssertEqual(x1.plus(x1).plus(x1), -29999996296316296296394247779607693797153879301498428364623587823754683508405490325151269121795505)
78 | XCTAssertEqual(x1.plus(x1).plus(x1).plus(x2), -49999995061755061728525663706143591729538505735331237819498117098339578011207320433535025495727340)
79 | }
80 | #endif
81 |
82 | func testTimes() {
83 | let x1: BigInt = "89248574598402980294572048572242498123"
84 | let x2: BigInt = "84759720710000012134"
85 | XCTAssert(x1.times(x2) == "7564684256726238104741764542977591293635416602920472224482")
86 | let x3: BigInt = "-846372893840594837726622221119029"
87 | XCTAssert(x1.times(x3) ==
88 | "-75537574353998534693615828134454330968785329792741330257228043492082567")
89 | }
90 |
91 | #if canImport(Swift.StaticBigInt)
92 | func testTimesLiteral() {
93 | let x1: BigInt = 89248574598402980294572048572242498123
94 | let x2: BigInt = 84759720710000012134
95 | XCTAssert(x1.times(x2) == 7564684256726238104741764542977591293635416602920472224482)
96 | let x3: BigInt = -846372893840594837726622221119029
97 | XCTAssert(x1.times(x3) ==
98 | -75537574353998534693615828134454330968785329792741330257228043492082567)
99 | }
100 | #endif
101 |
102 | func testDividedBy() {
103 | let x1: BigInt = "38274945700000001034304000022452452525224002449"
104 | let x2: BigInt = "1234567890123456789"
105 | let r1 = x1.divided(by: x2)
106 | XCTAssert(r1.quotient == "31002706296024357530217920519")
107 | XCTAssert(r1.remainder == "654242677691048958")
108 | let x3: BigInt = "3827494570900000103430410002245245252522400244999"
109 | let x4: BigInt = "12345678901234567892344542545242452245"
110 | let r2 = x3.divided(by: x4)
111 | XCTAssert(r2.quotient == "310027063033")
112 | XCTAssert(r2.remainder == "1772541951990552417813256094292885914")
113 | XCTAssert((x3 / x3) == BigInt(1))
114 | XCTAssert((x3 / (x3.times(10))) == BigInt(0))
115 | }
116 |
117 | func testRemainder() {
118 | let qp: BigInt = "76292485249"
119 | let qn: BigInt = "-76292485249"
120 | let x1p: BigInt = "12"
121 | let x1n: BigInt = "-12"
122 | let x2p: BigInt = "7629248524991"
123 | let x2n: BigInt = "-7629248524991"
124 | XCTAssert(x1p % qp == x1p)
125 | XCTAssert(x1n % qp == x1n)
126 | XCTAssert(x1p % qn == x1p)
127 | XCTAssert(x1n % qn == x1n)
128 | let rp: BigInt = "91"
129 | let rn: BigInt = "-91"
130 | XCTAssertEqual(x2p % qp, rp)
131 | XCTAssertEqual(x2n % qp, rn)
132 | XCTAssertEqual(x2p % qn, rp)
133 | XCTAssertEqual(x2n % qn, rn)
134 | }
135 |
136 | func testSqrt() {
137 | let x1: BigInt = "987248974087420857240857208746297469247698798798798700"
138 | XCTAssert(x1.sqrt == "993604032845791572092520365")
139 | let x2: BigInt = "785035630596835096835069835069385609358603956830596835096835069835608390000"
140 | XCTAssert(x2.sqrt == "28018487300295765553963049921800641599")
141 | let x3: BigInt = "1000000000000"
142 | XCTAssert(x3.sqrt == "1000000")
143 | }
144 |
145 | func testPowerOf() {
146 | let x1: BigInt = "84570248572048572408572048572048"
147 | let y1 = x1 * x1 * x1 * x1
148 | XCTAssert(x1.toPower(of: BigInt(4)) == y1)
149 | }
150 |
151 | func testDoubleConversion() {
152 | let x1: Double = 34134342324888777666555444333.1343141341341 * 10000000000000000.0
153 | let y1 = BigInt(x1)
154 | XCTAssertEqual(x1, y1.doubleValue)
155 | let x2: Double = -998877665544332211.123456789 * 10000000000000000.0
156 | let y2 = BigInt(x2)
157 | XCTAssertEqual(x2, y2.doubleValue)
158 | let x3 = Double(UInt64.max)
159 | let y3 = BigInt(x3)
160 | XCTAssertEqual(x3, y3.doubleValue)
161 | let x4 = Double(UInt64.max)
162 | let y4 = BigInt(x4)
163 | let z4 = BigInt(UInt64.max)
164 | XCTAssertEqual(y4.doubleValue, z4.doubleValue)
165 | }
166 |
167 | func testFloatConversion() {
168 | let x0: Float = 34133.134314134134132
169 | let y0 = BigInt(exactly: x0)
170 | XCTAssertEqual(y0, nil)
171 | let x1: Float = 34134342324888777633.1343141341341 * 1000000000000.0
172 | let y1 = BigInt(exactly: x1)
173 | XCTAssertEqual(Double(x1), (y1 ?? BigInt.zero).doubleValue)
174 | let x2: Float = -998877665544332211.123456789 * 10000000000000000.0
175 | let y2 = BigInt(x2)
176 | XCTAssertEqual(Double(x2), y2.doubleValue)
177 | let x3 = Float(Int64.min)
178 | let y3 = BigInt(x3)
179 | XCTAssertEqual(Double(x3), y3.doubleValue)
180 | }
181 |
182 | func testAnd() {
183 | let x0: BigInt = "13"
184 | let y0: BigInt = "-234245400000000001111"
185 | XCTAssertEqual(x0.and(y0), BigInt(9))
186 | let x1: BigInt = "234245400000000001111"
187 | let y1: BigInt = "-9846504850258720458"
188 | let z1: BigInt = "224984655330917548054"
189 | XCTAssertEqual(x1.and(y1), z1)
190 | XCTAssertEqual(BigInt(-1).and(BigInt(-2)), BigInt(-2))
191 | let x2: BigInt = "-542455245094524566901"
192 | let y2: BigInt = "-542455245094524566900"
193 | let z2: BigInt = "-542455245094524566904"
194 | XCTAssertEqual(x2.and(y2), z2)
195 | let x3: BigInt = "9087536870576087630587630586735"
196 | let y3: BigInt = "-783098795876350358367035603567035670358"
197 | let z3: BigInt = "8879166037613449274055524745258"
198 | XCTAssertEqual(x3.and(y3), z3)
199 | let x4: BigInt = "-98040972987924857928456297456297659276249762976245659762459"
200 | let y4: BigInt = "9864520842504292089860983506873560870"
201 | let z4: BigInt = "58540432875177786070779388280897572"
202 | XCTAssertEqual(x4.and(y4), z4)
203 | let x5: BigInt = "-31"
204 | let y5: BigInt = "-4444335366627281172636646645342263748485595"
205 | let z5: BigInt = "-4444335366627281172636646645342263748485599"
206 | XCTAssertEqual(x5.and(y5), z5)
207 | let x6: BigInt = "-3453452461354444335366627281172636646645342263748485599"
208 | let y6: BigInt = "1023"
209 | let z6: BigInt = "545"
210 | XCTAssertEqual(x6.and(y6), z6)
211 | }
212 |
213 | func testShifts() {
214 | let x1: BigInt = "987248974087420857"
215 | XCTAssertEqual(x1 << 1, x1 * 2)
216 | let x2: BigInt = "9872489740874208572408572"
217 | XCTAssertEqual(x2 << 1, x2 * 2)
218 | let x3: BigInt = "98724897408742085724085724524524524524524522454525245999"
219 | XCTAssertEqual(x3 << 9, x3 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2)
220 | let x4: BigInt = "987248974087420857"
221 | XCTAssertEqual(x4 >> 1, x4 / 2)
222 | let x5: BigInt = "9872489740874208572408572"
223 | XCTAssertEqual(x5 >> 1, x5 / 2)
224 | let x6: BigInt = "98724897408742085724085724524524524524524522454525245999098037580357603865"
225 | XCTAssertEqual(x6 >> 5, x6 / 32)
226 | let x7: BigInt = "-234245400000000001111"
227 | let r7: BigInt = "-1830042187500000009"
228 | XCTAssertEqual(x7 >> 7, r7)
229 | let x8: BigInt = "-987248974087420857240857245245245245245245224545252459990980375803576038650"
230 | let r8: BigInt = "-28732726760424582090952237056488091045910411763041410012839489378"
231 | XCTAssertEqual(x8 >> 35, r8)
232 | let x9: BigInt = "-1"
233 | XCTAssertEqual(x9 >> 1, x9)
234 | let x10: BigInt = "-2"
235 | XCTAssertEqual(x10 >> 1, x9)
236 | let x11: BigInt = "-3"
237 | XCTAssertEqual(x11 >> 1, x10)
238 | let x12: BigInt = "-4"
239 | XCTAssertEqual(x12 >> 1, x10)
240 | let x13: BigInt = "-100000000000000000000000000000000"
241 | let r13: BigInt = "-79"
242 | XCTAssertEqual(x13 >> 100, r13)
243 | let r14: BigInt = "-126765060022822940149670320537600000000000000000000000000000000"
244 | XCTAssertEqual(x13 << 100, r14)
245 | let x15: BigInt = "-9872489740874208572408572"
246 | let r15: BigInt = "-1356864658148807688588085270081961984"
247 | XCTAssertEqual(x15 << 37, r15)
248 | let x16: BigInt = "-111308731087301939383033999999"
249 | let r16: BigInt = "-131410155234356299897170703642124868710991004696576"
250 | XCTAssertEqual(x16 << 70, r16)
251 | }
252 |
253 | func testBitCount() {
254 | let x0: BigInt = "172"
255 | XCTAssertEqual(x0.bitCount, 4)
256 | let x1: BigInt = "4285720457204597"
257 | XCTAssertEqual(x1.bitCount, 31)
258 | let x2: BigInt = "8708356703856085653607835677770"
259 | XCTAssertEqual(x2.bitCount, 55)
260 | let x3: BigInt = "98724897408742085724085724524524524524524522454525245999"
261 | XCTAssertEqual(x3.bitCount, 100)
262 | let x4: BigInt = "9872489740874208572408572452452452452452452245452524599909803758035760386501"
263 | XCTAssertEqual(x4.bitCount, 120)
264 | let x5: BigInt = "-127"
265 | XCTAssertEqual(x5.bitCount, -7)
266 | let x6: BigInt = "-4285720457204597"
267 | XCTAssertEqual(x6.bitCount, -31)
268 | let x7: BigInt = "-8708356703856085653607835677770"
269 | XCTAssertEqual(x7.bitCount, -56)
270 | let x8: BigInt = "-98724897408742085724085724524524524524524522454525245999"
271 | XCTAssertEqual(x8.bitCount, -100)
272 | let x9: BigInt = "-987248974087420857240857245245245245245245224545252459990980375803576038650"
273 | XCTAssertEqual(x9.bitCount, -115)
274 | }
275 |
276 | func testZeroBits() {
277 | let x0: BigInt = "170"
278 | XCTAssertEqual(x0.bitSize, 32)
279 | XCTAssertEqual(x0.trailingZeroBitCount, 1)
280 | XCTAssertEqual(x0.firstBitSet, 1)
281 | let x1: BigInt = "4285720457200"
282 | XCTAssertEqual(x1.bitSize, 64)
283 | XCTAssertEqual(x1.trailingZeroBitCount, 4)
284 | XCTAssertEqual(x1.firstBitSet, 4)
285 | let x2: BigInt = "-4"
286 | XCTAssertEqual(x2.trailingZeroBitCount, 2)
287 | XCTAssertEqual(x2.firstBitSet, 2)
288 | let x3: BigInt = "81623247908021670355559786741760"
289 | XCTAssertEqual(x3.trailingZeroBitCount, 74)
290 | XCTAssertEqual(x3.firstBitSet, 74)
291 | let x4: BigInt = "-157334116307980970279619537141760"
292 | XCTAssertEqual(x4.trailingZeroBitCount, 74)
293 | XCTAssertEqual(x4.firstBitSet, 74)
294 | XCTAssertEqual(BigInt.zero.trailingZeroBitCount, BigInt.zero.bitWidth)
295 | XCTAssertEqual(BigInt.zero.firstBitSet, -1)
296 | }
297 |
298 | func testBitTest() {
299 | let x0: BigInt = "2863311530"
300 | for i in 0..<32 {
301 | XCTAssertEqual(x0.isBitSet(i), i.isOdd)
302 | }
303 | XCTAssertEqual(x0.isBitSet(32), false)
304 | XCTAssertEqual(x0.isBitSet(33), false)
305 | XCTAssertEqual(x0.isBitSet(34), false)
306 | XCTAssertEqual(x0.isBitSet(35), false)
307 | XCTAssertEqual(x0.lastBitSet, 32)
308 | let x1: BigInt = "64942224592110934030034938344746347339829000900128380"
309 | let bits1: Set =
310 | [2, 3, 4, 5, 6, 9, 10, 11, 13, 16, 17, 20, 22, 23, 24, 26, 27, 31, 33, 34, 35, 37,
311 | 38, 39, 41, 43, 44, 47, 48, 49, 50, 52, 54, 55, 59, 65, 68, 71, 72, 75, 77, 78,
312 | 79, 80, 82, 83, 84, 85, 87, 90, 91, 92, 94, 95, 100, 102, 103, 110, 111, 112,
313 | 113, 114, 123, 124, 127, 129, 130, 135, 136, 137, 138, 141, 142, 143, 145,
314 | 148, 149, 150, 151, 152, 154, 158, 160, 161, 164, 167, 168, 170, 171, 173, 175]
315 | for i in 0..<300 {
316 | XCTAssertEqual(x1.isBitSet(i), bits1.contains(i))
317 | }
318 | XCTAssertEqual(x1.lastBitSet, 176)
319 | let x2: BigInt = "-1234567894257563210000294749382000039387453720000987383000032"
320 | let zeros1: Set =
321 | [0, 1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 14, 15, 19, 20, 21, 23, 24, 27, 28, 32, 34, 35,
322 | 36, 37, 38, 40, 41, 42, 43, 44, 48, 49, 53, 58, 65, 66, 68, 71, 73, 75, 77, 79,
323 | 80, 81, 82, 85, 86, 88, 90, 92, 95, 96, 98, 99, 101, 102, 105, 106, 107, 108,
324 | 110, 111, 118, 121, 122, 123, 125, 130, 132, 135, 136, 139, 141, 144, 145,
325 | 146, 147, 150, 151, 154, 162, 163, 164, 165, 166, 167, 168, 169, 171, 172,
326 | 173, 177, 180, 183, 184, 186, 187, 189, 191, 194, 198, 199]
327 | for i in 0..<400 {
328 | XCTAssertEqual(x2.isBitSet(i), !zeros1.contains(i))
329 | }
330 | XCTAssertEqual(x2.lastBitSet, 200)
331 | }
332 |
333 | func testBitSet() {
334 | var x1 = BigInt.zero
335 | for i in [2, 3, 4, 5, 6, 9, 10, 11, 13, 16, 17, 20, 22, 23, 24, 26, 27, 31, 33, 34, 35, 37,
336 | 38, 39, 41, 43, 44, 47, 48, 49, 50, 52, 54, 55, 59, 65, 68, 71, 72, 75, 77, 78,
337 | 79, 80, 82, 83, 84, 85, 87, 90, 91, 92, 94, 95, 100, 102, 103, 110, 111, 112,
338 | 113, 114, 123, 124, 127, 129, 130, 135, 136, 137, 138, 141, 142, 143, 145,
339 | 148, 149, 150, 151, 152, 154, 158, 160, 161, 164, 167, 168, 170, 171, 173, 175] {
340 | x1 = x1.set(bit: i, to: true)
341 | }
342 | let y1: BigInt = "64942224592110934030034938344746347339829000900128380"
343 | XCTAssertEqual(x1, y1)
344 | XCTAssertEqual(x1.bitSize, y1.bitSize)
345 | }
346 |
347 | func testWords() {
348 | let x1: BigInt = "39998740587340080087986767562130873870358038157034635280980314708375001"
349 | XCTAssertEqual(x1.words, [17444856893563336153,
350 | 10071105391305811219,
351 | 12534310513326413052,
352 | 6372167008517,
353 | 0])
354 | let x2: BigInt = -x1
355 | XCTAssertEqual(x2.words, [1001887180146215463,
356 | 8375638682403740396,
357 | 5912433560383138563,
358 | 18446737701542543098,
359 | 18446744073709551615])
360 | let x3: BigInt = x1 >> 64
361 | XCTAssertEqual(x3.words, [10071105391305811219,
362 | 12534310513326413052,
363 | 6372167008517,
364 | 0])
365 | let x4: BigInt = BigInt(UInt.max)
366 | XCTAssertEqual(x4.words, [18446744073709551615, 0])
367 | let x5: BigInt = -x4
368 | XCTAssertEqual(x5.words, [1,18446744073709551615])
369 | let x6: BigInt = -x5
370 | XCTAssertEqual(x6.words, [18446744073709551615, 0])
371 | let x7: BigInt = BigInt(UInt.max) + 1
372 | XCTAssertEqual(x7.words, [0, 1, 0])
373 | }
374 |
375 | func testRandom() {
376 | let rnd1 = BigInt.random(withMaxBits: 218)
377 | XCTAssert(rnd1.bitCount <= 218)
378 | XCTAssert(rnd1.bitSize < 218 + UInt32.bitWidth)
379 | let rnd2 = BigInt.random(withMaxBits: 22)
380 | XCTAssert(rnd2.bitCount <= 22)
381 | XCTAssert(rnd2.bitSize < 22 + UInt32.bitWidth)
382 | let bound: BigInt = "9856024857249581231765137423436847588346498948545927456"
383 | let rnd3 = BigInt.random(below: bound)
384 | XCTAssert(rnd3 < bound)
385 | let bound2: BigInt = "123123"
386 | let rnd4 = BigInt.random(below: bound2)
387 | XCTAssert(rnd4 < bound2)
388 | }
389 |
390 | func testDescription() {
391 | let x1s = "1234"
392 | let x1n = BigInt(stringLiteral: x1s)
393 | XCTAssertEqual(x1n.description, x1s)
394 | let x2s =
395 | "9475620485742095824587024587249578098356095863059683095683560358605398039524642958276579245"
396 | let x2n = BigInt(stringLiteral: x2s)
397 | XCTAssertEqual(x2n.description, x2s)
398 | let x3s =
399 | "-495874504574059783459734085730678509678305968735867305978630697350673056497624524"
400 | let x3n = BigInt(stringLiteral: x3s)
401 | XCTAssertEqual(x3n.description, x3s)
402 | }
403 |
404 | func testToString() {
405 | let x0 = BigInt(stringLiteral: "1234")
406 | XCTAssertEqual(x0.toString(base: .bin), "10011010010")
407 | XCTAssertEqual(x0.toString(base: .oct), "2322")
408 | XCTAssertEqual(x0.toString(base: .dec), "1234")
409 | XCTAssertEqual(x0.toString(base: .hex), "4D2")
410 | XCTAssertEqual(x0.toString(base: .dec, forceSign: true), "+1234")
411 | let x1 = BigInt(stringLiteral: "9876543210")
412 | XCTAssertEqual(x1.toString(groupSep: ","), "9,876,543,210")
413 | XCTAssertEqual(x1.toString(groupSep: ":", groupSize: 2), "98:76:54:32:10")
414 | XCTAssertEqual(x1.toString(base: .hex, groupSep: ".", groupSize: 1), "2.4.C.B.0.1.6.E.A")
415 | XCTAssertEqual(BigInt(stringLiteral: "-9876543210").toString(groupSep: ","), "-9,876,543,210")
416 | let x2s =
417 | "9475620485742095824587024587249578098356095863059683095683560358605398039524642958276579245"
418 | let x2 = BigInt(stringLiteral: x2s)
419 | XCTAssertEqual(x2.toString(base: .bin),
420 | "10010100110110100111110001101101111000111111110101000101001111000111111100000" +
421 | "11101000001000100001110110111010110001011001110100010011010101010101100101010" +
422 | "11100100010011000000101000110100010010000011001111011100100111111001000011111" +
423 | "000111001010111010100001100110000100100000110011111110000100111110101101")
424 | XCTAssertEqual(x2.toString(base: .oct),
425 | "45155076155707762424743760324042073353026350465251452710460110642203173223744" +
426 | "174342565031411006376047655")
427 | XCTAssertEqual(x2.toString(base: .dec), x2s)
428 | XCTAssertEqual(x2.toString(base: .hex),
429 | "4A6D3E36F1FEA29E3F83A08876EB16744D55655C89814689067B93F21F1CAEA1984833F84FAD")
430 | XCTAssertEqual(x2.toString(base: .dec, forceSign: true), "+\(x2s)")
431 | let x3s =
432 | "-495874504574059783459734085730678509678305968735867305978630697350673056497624524"
433 | let x3 = BigInt(stringLiteral: x3s)
434 | XCTAssertEqual(x3.toString(base: .bin),
435 | "-1000010111010011101001010111110001100101101111100110111011110111110011110111" +
436 | "11001110110000001100001110001011110010011000010110101110101011010001001000100" +
437 | "10100100101000000001010101111100111001001010010000010111111000101000001101001" +
438 | "100110001001011110110110110010111001100")
439 | XCTAssertEqual(x3.toString(base: .oct),
440 | "-10272164537062673156757475723540303427223026565320442244500112763445101176120" +
441 | "3231411366662714")
442 | XCTAssertEqual(x3.toString(base: .dec), x3s)
443 | XCTAssertEqual(x3.toString(base: .hex),
444 | "-10BA74AF8CB7CDDEF9EF9D818717930B5D5A244A4A0157CE4A417E2834CC4BDB65CC")
445 | XCTAssertEqual(x3.toString(base: .dec, forceSign: true), x3s)
446 | }
447 |
448 | func testBasicOpWithZero() {
449 | let x1: BigInt = "0"
450 | let x2: BigInt = "-1"
451 | XCTAssertFalse(x1.isNegative)
452 | XCTAssertFalse(x1.negate.isNegative)
453 | XCTAssertEqual(x2.plus(x1), x2)
454 | XCTAssertEqual(x2.minus(x1), x2)
455 | }
456 |
457 | static let allTests = [
458 | ("testConstructors", testConstructors),
459 | ("testPlus", testPlus),
460 | ("testMinus", testMinus),
461 | ("testTimes", testTimes),
462 | ("testDividedBy", testDividedBy),
463 | ("testRemainder", testRemainder),
464 | ("testSqrt", testSqrt),
465 | ("testPowerOf", testPowerOf),
466 | ("testDoubleConversion", testDoubleConversion),
467 | ("testFloatConversion", testFloatConversion),
468 | ("testAnd", testAnd),
469 | ("testShifts", testShifts),
470 | ("testBitCount", testBitCount),
471 | ("testZeroBits", testZeroBits),
472 | ("testBitTest", testBitTest),
473 | ("testBitSet", testBitSet),
474 | ("testWords", testWords),
475 | ("testDescription", testDescription),
476 | ]
477 | }
478 |
--------------------------------------------------------------------------------
/Sources/NumberKit/Complex.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Complex.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 15/08/2015.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import Foundation
22 |
23 |
24 | /// The `ComplexNumber` protocol defines an interface for complex numbers. A complex
25 | /// number consists of two floating point components: a real part `re` and an imaginary
26 | /// part `im`. It is typically expressed as: re + im * i where i is the imaginary unit.
27 | /// i satisfies the equation i * i = -1.
28 | ///
29 | /// - Note: The `ComplexNumber` protocol abstracts over the floating point type on which
30 | /// the complex type implementation is based on.
31 | /// - Todo: Implement the `Arithmetic` protocol. This requires that complex numbers are
32 | /// mutable.
33 | public protocol ComplexNumber: Hashable,
34 | CustomStringConvertible {
35 |
36 | /// The floating point number type on which this complex number is based.
37 | associatedtype Float: FloatingPoint
38 |
39 | /// Creates a complex number without imaginary part from the given real part.
40 | init(_ re: Float)
41 |
42 | /// The real part of the complex number.
43 | var re: Float { get }
44 |
45 | /// The imaginary part of the complex number.
46 | var im: Float { get }
47 |
48 | /// Returns the real part of the complex number if the number has no complex
49 | /// part, nil otherwise
50 | var realValue: Float? { get }
51 |
52 | /// Returns true if this complex number has no imaginary part.
53 | var isReal: Bool { get }
54 |
55 | /// Returns true if this complex number is zero.
56 | var isZero: Bool { get }
57 |
58 | /// Returns true if either real or imaginary parts are not a number.
59 | var isNaN: Bool { get }
60 |
61 | /// Returns true if both real and imaginary parts are finite.
62 | var isFinite: Bool { get }
63 |
64 | /// Returns true if either real or imaginary parts are infinite.
65 | var isInfinite: Bool { get }
66 |
67 | /// Returns the ∞-norm of this complex number. Use `norm` if the Euclidean norm
68 | /// is needed.
69 | var magnitude: Float { get }
70 |
71 | /// Returns the absolute value of this complex number.
72 | var abs: Float { get }
73 |
74 | /// Returns the argument/phase of this complex number.
75 | var arg: Float { get }
76 |
77 | /// Returns the negated complex number.
78 | var negate: Self { get }
79 |
80 | /// Multiplies `self` by i.
81 | var i: Self { get }
82 |
83 | /// Returns the conjugate of this complex number.
84 | var conjugate: Self { get }
85 |
86 | /// Returns the reciprocal of this complex number.
87 | var reciprocal: Self { get }
88 |
89 | /// Returns the norm of this complex number.
90 | var norm: Float { get }
91 |
92 | /// Returns the square root of this complex number
93 | var sqrt: Self { get }
94 |
95 | /// Returns the natural exponential of this complex number.
96 | var exp: Self { get }
97 |
98 | /// Returns the natural logarithm of this complex number.
99 | var log: Self { get }
100 |
101 | /// Returns the sum of `self` and `rhs` as a complex number.
102 | func plus(_ rhs: Self) -> Self
103 |
104 | /// Returns the difference between `self` and `rhs` as a complex number.
105 | func minus(_ rhs: Self) -> Self
106 |
107 | /// Returns the result of multiplying `self` with `rhs` as a complex number.
108 | func times(_ rhs: Self) -> Self
109 |
110 | /// Returns the result of multiplying `self` with scalar `rhs` as a complex number.
111 | func times(_ rhs: Float) -> Self
112 |
113 | /// Returns the result of dividing `self` by `rhs` as a complex number.
114 | func divided(by rhs: Self) -> Self
115 |
116 | /// Returns the result of dividing `self` by scalar `rhs` as a complex number.
117 | func divided(by rhs: Float) -> Self
118 |
119 | /// Returns this complex number taken to the power of `ex`.
120 | func toPower(of ex: Self) -> Self
121 | }
122 |
123 |
124 | /// Struct `Complex` implements the `ComplexNumber` interface on top of the
125 | /// floating point type `T`; i.e. both the rational and the imaginary part of the
126 | /// complex number are represented as values of type `T`.
127 | ///
128 | /// - Note: `T` needs to implement the `FloatingPointNumber` protocol. The `FloatingPoint`
129 | /// protocol that is defined in the Swift standard library is not sufficient to
130 | /// implement a complex number as it does not define interfaces for trigonometric
131 | /// functions.
132 | public struct Complex: ComplexNumber,
133 | Hashable,
134 | ExpressibleByIntegerLiteral,
135 | ExpressibleByFloatLiteral,
136 | CustomStringConvertible {
137 |
138 | /// The real part of thix complex number.
139 | public let re: T
140 |
141 | /// The imaginary part of this complex number.
142 | public let im: T
143 |
144 | /// Creates a complex number with the given real part and no imaginary part.
145 | public init(_ re: T) {
146 | self.re = re
147 | self.im = T(0)
148 | }
149 |
150 | /// Creates a complex number with the given real and integer imaginary parts.
151 | public init(_ re: T, _ im: Int64) {
152 | self.init(re, T(im))
153 | }
154 |
155 | /// Creates a complex number with the given real and imaginary parts.
156 | public init(_ re: T, _ im: T) {
157 | // Normalize complex numbers involving NaN
158 | if re.isNaN {
159 | self.re = re
160 | self.im = T(0)
161 | } else if im.isNaN {
162 | self.re = im
163 | self.im = T(0)
164 | // Normalize infinite complex numbers
165 | } else if re.isInfinite {
166 | self.re = re
167 | self.im = T(0)
168 | } else if im.isInfinite { // imaginary parts are never infinity
169 | self.re = .nan
170 | self.im = T(0)
171 | } else {
172 | self.re = re
173 | self.im = im
174 | }
175 | }
176 |
177 | /// Creates a complex number from polar coordinates
178 | public init(abs: T, arg: T) {
179 | self.init(abs * arg.cos, abs * arg.sin)
180 | }
181 |
182 | /// Creates a real number initialized to integer `value`.
183 | public init(integerLiteral value: Int64) {
184 | self.init(T(value))
185 | }
186 |
187 | /// Creates a real number initialized to floating point number `value`.
188 | public init(floatLiteral value: T) {
189 | self.init(value)
190 | }
191 |
192 | /// Returns a textual representation of this complex number
193 | public var description: String {
194 | if im.isZero || re.isNaN || re.isInfinite {
195 | return String(describing: re)
196 | } else if re.isZero {
197 | return String(describing: im) + "i"
198 | } else {
199 | return (im.sign == .minus) ? "\(re)\(im)i" : "\(re)+\(im)i"
200 | }
201 | }
202 |
203 | /// For hashing values.
204 | public func hash(into hasher: inout Hasher) {
205 | hasher.combine(re)
206 | hasher.combine(im)
207 | }
208 |
209 | /// Returns the real part of the complex number if the number has no complex
210 | /// part, nil otherwise
211 | public var realValue: T? {
212 | return im.isZero ? re : nil
213 | }
214 |
215 | /// Returns true if this complex number has no imaginary part.
216 | public var isReal: Bool {
217 | return im.isZero
218 | }
219 |
220 | /// Returns true if this complex number is zero.
221 | public var isZero: Bool {
222 | return re.isZero && im.isZero
223 | }
224 |
225 | /// Returns true if either real or imaginary parts are not a number.
226 | public var isNaN: Bool {
227 | return re.isNaN || im.isNaN
228 | }
229 |
230 | /// Returns true if both real and imaginary parts are finite.
231 | public var isFinite: Bool {
232 | return re.isFinite && im.isFinite
233 | }
234 |
235 | /// Returns true if either real or imaginary parts are infinite.
236 | public var isInfinite: Bool {
237 | return re.isInfinite || im.isInfinite
238 | }
239 |
240 | /// Returns the ∞-norm of this complex number. Use `norm` if the Euclidean norm
241 | /// is needed.
242 | public var magnitude: T {
243 | if self.isNaN {
244 | return .nan
245 | } else if self.isFinite {
246 | return max(self.re.abs, self.im.abs)
247 | } else {
248 | return .infinity
249 | }
250 | }
251 |
252 | /// Returns the absolute value of this complex number.
253 | public var abs: T {
254 | return re.hypot(im)
255 | }
256 |
257 | /// Returns the argument/phase of this complex number.
258 | public var arg: T {
259 | return im.atan2(re)
260 | }
261 |
262 | /// Returns the negated complex number.
263 | public var negate: Complex {
264 | return Complex(-re, -im)
265 | }
266 |
267 | /// Multiplies `self` by i.
268 | public var i: Complex {
269 | return Complex(-im, re)
270 | }
271 |
272 | /// Returns the conjugate of this complex number.
273 | public var conjugate: Complex {
274 | return Complex(re, -im)
275 | }
276 |
277 | /// Returns the reciprocal of this complex number.
278 | public var reciprocal: Complex {
279 | if self.isNaN {
280 | return self
281 | } else if self.isZero {
282 | return .infinity
283 | } else if self.isInfinite {
284 | return .zero
285 | } else {
286 | let s = re * re + im * im
287 | return Complex(re / s, -im / s)
288 | }
289 | }
290 |
291 | /// Returns the norm of this complex number.
292 | public var norm: T {
293 | return re.hypot(im)
294 | }
295 |
296 | /// exp(x) function for complex numbers x.
297 | public var exp: Complex {
298 | let abs = re.exp
299 | return Complex(abs * im.cos, abs * im.sin)
300 | }
301 |
302 | /// log(x) function for complex numbers x.
303 | public var log: Complex {
304 | return Complex(abs.log, arg)
305 | }
306 |
307 | /// Returns the square root of this complex number
308 | public var sqrt: Complex {
309 | let r = ((re + abs) / T(2)).sqrt
310 | let i = ((-re + abs) / T(2)).sqrt
311 | return Complex(r, (im.sign == .minus) ? -i : i)
312 | }
313 |
314 | /// Returns this complex number taken to the power of `ex`.
315 | public func toPower(of ex: Complex) -> Complex {
316 | return isZero ? (ex.isZero ? 1 : 0) : log.times(ex).exp
317 | }
318 |
319 | /// Returns the sum of `self` and `rhs` as a complex number.
320 | public func plus(_ rhs: Complex) -> Complex {
321 | return Complex(self.re + rhs.re, self.im + rhs.im);
322 | }
323 |
324 | /// Returns the difference between `self` and `rhs` as a complex number.
325 | public func minus(_ rhs: Complex) -> Complex {
326 | return Complex(self.re - rhs.re, self.im - rhs.im);
327 | }
328 |
329 | /// Returns the result of multiplying `self` with `rhs` as a complex number.
330 | public func times(_ rhs: Complex) -> Complex {
331 | return Complex(self.re * rhs.re - self.im * rhs.im, self.re * rhs.im + self.im * rhs.re);
332 | }
333 |
334 | /// Returns the result of multiplying `self` with scalar `rhs` as a complex number.
335 | public func times(_ rhs: T) -> Complex {
336 | return Complex(self.re * rhs, self.im * rhs);
337 | }
338 |
339 | /// Returns the result of dividing `self` by `rhs` as a complex number.
340 | public func divided(by rhs: Complex) -> Complex {
341 | return times(rhs.reciprocal)
342 | }
343 |
344 | /// Returns the result of dividing `self` by scalar `rhs` as a complex number.
345 | public func divided(by rhs: T) -> Complex {
346 | return Complex(self.re / rhs, self.im / rhs);
347 | }
348 |
349 | /// Returns a random complex number given a real and imaginary range.
350 | public static func random(realRange: Range,
351 | imaginaryRange: Range,
352 | using generator: inout R) -> Self where R: RandomNumberGenerator {
353 | return Complex(T.random(in: realRange, using: &generator),
354 | T.random(in: imaginaryRange, using: &generator))
355 | }
356 | }
357 |
358 | // Implement equality
359 |
360 | public func == (lhs: C, rhs: C) -> Bool {
361 | return lhs.re == rhs.re && lhs.im == rhs.im
362 | }
363 |
364 | public func == (lhs: C.Float, rhs: C) -> Bool {
365 | return rhs.re == lhs && rhs.im.isZero
366 | }
367 |
368 | public func == (lhs: C, rhs: C.Float) -> Bool {
369 | return lhs.re == rhs && lhs.im.isZero
370 | }
371 |
372 | public func != (lhs: C, rhs: C) -> Bool {
373 | return lhs.re != rhs.re || lhs.im != rhs.im
374 | }
375 |
376 | public func != (lhs: C.Float, rhs: C) -> Bool {
377 | return rhs.re != lhs || !rhs.im.isZero
378 | }
379 |
380 | public func != (lhs: C, rhs: C.Float) -> Bool {
381 | return lhs.re != rhs || !lhs.im.isZero
382 | }
383 |
384 |
385 | /// Negates complex number `z`.
386 | public prefix func - (z: C) -> C {
387 | return z.negate
388 | }
389 |
390 | /// Returns the sum of `lhs` and `rhs`.
391 | public func + (lhs: C, rhs: C) -> C {
392 | return lhs.plus(rhs)
393 | }
394 |
395 | /// Returns the sum of `lhs` and `rhs`.
396 | public func + (lhs: C, rhs: C.Float) -> C {
397 | return lhs.plus(C(rhs))
398 | }
399 |
400 | /// Returns the sum of `lhs` and `rhs`.
401 | public func + (lhs: C.Float, rhs: C) -> C {
402 | return C(lhs).plus(rhs)
403 | }
404 |
405 | /// Returns the difference between `lhs` and `rhs`.
406 | public func - (lhs: C, rhs: C) -> C {
407 | return lhs.minus(rhs)
408 | }
409 |
410 | /// Returns the difference between `lhs` and `rhs`.
411 | public func - (lhs: C, rhs: C.Float) -> C {
412 | return lhs.minus(C(rhs))
413 | }
414 |
415 | /// Returns the difference between `lhs` and `rhs`.
416 | public func - (lhs: C.Float, rhs: C) -> C {
417 | return C(lhs).minus(rhs)
418 | }
419 |
420 | /// Multiplies `lhs` with `rhs` and returns the result.
421 | public func * (lhs: C, rhs: C) -> C {
422 | return lhs.times(rhs)
423 | }
424 |
425 | /// Multiplies complex number `lhs` with scalar `rhs` and returns the result.
426 | public func * (lhs: C, rhs: C.Float) -> C {
427 | return lhs.times(rhs)
428 | }
429 |
430 | /// Multiplies scalar `lhs` with complex number `rhs` and returns the result.
431 | public func * (lhs: C.Float, rhs: C) -> C {
432 | return rhs.times(lhs)
433 | }
434 |
435 | /// Divides `lhs` by `rhs` and returns the result.
436 | public func / (lhs: C, rhs: C) -> C {
437 | return lhs.divided(by: rhs)
438 | }
439 |
440 | /// Divides complex number `lhs` by scalar `rhs` and returns the result.
441 | public func / (lhs: C, rhs: C.Float) -> C {
442 | return lhs.divided(by: rhs)
443 | }
444 |
445 | /// Divides complex number `lhs` by scalar `rhs` and returns the result.
446 | public func / (lhs: C.Float, rhs: C) -> C {
447 | return C(lhs).divided(by: rhs)
448 | }
449 |
450 | /// Assigns `lhs` the sum of `lhs` and `rhs`.
451 | public func += (lhs: inout C, rhs: C) {
452 | lhs = lhs.plus(rhs)
453 | }
454 |
455 | /// Assigns `lhs` the sum of `lhs` and `rhs`.
456 | public func += (lhs: inout C, rhs: C.Float) {
457 | lhs = lhs.plus(C(rhs))
458 | }
459 |
460 | /// Assigns `lhs` the difference between `lhs` and `rhs`.
461 | public func -= (lhs: inout C, rhs: C) {
462 | lhs = lhs.minus(rhs)
463 | }
464 |
465 | /// Assigns `lhs` the difference between `lhs` and `rhs`.
466 | public func -= (lhs: inout C, rhs: C.Float) {
467 | lhs = lhs.minus(C(rhs))
468 | }
469 |
470 | /// Assigns `lhs` the result of multiplying `lhs` with `rhs`.
471 | public func *= (lhs: inout C, rhs: C) {
472 | lhs = lhs.times(rhs)
473 | }
474 |
475 | /// Assigns `lhs` the result of multiplying `lhs` with scalar `rhs`.
476 | public func *= (lhs: inout C, rhs: C.Float) {
477 | lhs = lhs.times(rhs)
478 | }
479 |
480 | /// Assigns `lhs` the result of dividing `lhs` by `rhs`.
481 | public func /= (lhs: inout C, rhs: C) {
482 | lhs = lhs.divided(by: rhs)
483 | }
484 |
485 | /// Assigns `lhs` the result of dividing `lhs` by scalar `rhs`.
486 | public func /= (lhs: inout C, rhs: C.Float) {
487 | lhs = lhs.divided(by: rhs)
488 | }
489 |
490 | /// Returns the absolute value of the given complex number `z`.
491 | public func abs(_ z: C) -> C.Float {
492 | return z.abs
493 | }
494 |
495 | /// Returns the argument/phase of the given complex number `z`.
496 | public func arg(_ z: C) -> C.Float {
497 | return z.arg
498 | }
499 |
500 | /// Returns the real part of the given complex number `z`.
501 | public func real(_ z: C) -> C.Float {
502 | return z.re
503 | }
504 |
505 | /// Returns the imaginary part of the given complex number `z`.
506 | public func imag(_ z: C) -> C.Float {
507 | return z.im
508 | }
509 |
510 | /// Returns the norm of the given complex number `z`.
511 | public func norm(_ z: C) -> C.Float {
512 | return z.norm
513 | }
514 |
515 | /// Returns the conjugate of the given complex number `z`.
516 | public func conj(_ z: C) -> C {
517 | return z.conjugate
518 | }
519 |
520 | /// Returns the exponential of the given complex number `z`.
521 | public func exp(_ z: C) -> C {
522 | return z.exp
523 | }
524 |
525 | /// Returns the logarithm of the given complex number `z`.
526 | public func log(_ z: C) -> C {
527 | return z.log
528 | }
529 |
530 | /// Returns `base` to the power of `ex`.
531 | public func pow(_ base: C, _ ex: C) -> C {
532 | return base.toPower(of: ex)
533 | }
534 |
535 | /// Returns `base` to the power of `ex`.
536 | public func pow(_ base: C.Float, _ ex: C) -> C {
537 | return C(base).toPower(of: ex)
538 | }
539 |
540 | /// Returns `base` to the power of `ex`.
541 | public func pow(_ base: C, _ ex: C.Float) -> C {
542 | return base.toPower(of: C(ex))
543 | }
544 |
545 | /// Returns the square root of the given complex number `z`.
546 | public func sqrt(_ z: C) -> C {
547 | return z.sqrt
548 | }
549 |
550 | /// Returns `sin(z)` for the given complex number `z`.
551 | public func sin(_ z: C) -> C {
552 | return exp(-z.i).minus(exp(z.i)).i.divided(by: C.Float(2))
553 | }
554 |
555 | /// Returns `cos(z)` for the given complex number `z`.
556 | public func cos(_ z: C) -> C {
557 | return exp(z.i).plus(exp(-z.i)).divided(by: C.Float(2))
558 | }
559 |
560 | /// Returns `tan(z)` for the given complex number `z`.
561 | public func tan(_ z: C) -> C {
562 | let x = exp(z.i)
563 | let y = exp(-z.i)
564 | return x.minus(y).divided(by: x.plus(y).i)
565 | }
566 |
567 | /// Returns `asin(z)` for the given complex number `z`.
568 | public func asin(_ z: C) -> C {
569 | return -log(z.i.plus(sqrt(C(C.Float(1)).minus(z.times(z))))).i
570 | }
571 |
572 | /// Returns `acos(z)` for the given complex number `z`.
573 | public func acos(_ z: C) -> C {
574 | return log(z.minus(sqrt(C(C.Float(1)).minus(z.times(z))).i)).i
575 | }
576 |
577 | /// Returns `atan(z)` for the given complex number `z`.
578 | public func atan(_ z: C) -> C {
579 | let x = log(C(C.Float(1)).minus(z.i))
580 | let y = log(C(C.Float(1)).plus(z.i))
581 | return x.minus(y).i.divided(by: C.Float(2))
582 | }
583 |
584 | /// Returns `cos(r)` for the given floating point number `r`.
585 | public func atan(_ r: T) -> T {
586 | return atan(Complex(r)).re
587 | }
588 |
589 | /// Returns `atan2(z1, z2)` for the given complex numbers `z1` and `z2`.
590 | public func atan2(_ z1: C, _ z2: C) -> C {
591 | return atan(z1.divided(by: z2))
592 | }
593 |
594 | /// Returns `sinh(z)` for the given complex number `z`.
595 | public func sinh(_ z: C) -> C {
596 | return exp(z).minus(exp(-z)).divided(by: C.Float(2))
597 | }
598 |
599 | /// Returns `cosh(z)` for the given complex number `z`.
600 | public func cosh(_ z: C) -> C {
601 | return exp(z).plus(exp(-z)).divided(by: C.Float(2))
602 | }
603 |
604 | /// Returns `tanh(z)` for the given complex number `z`.
605 | public func tanh(_ z: C) -> C {
606 | let x = exp(z)
607 | let y = exp(-z)
608 | return x.minus(y).divided(by: x.plus(y))
609 | }
610 |
611 | /// Returns `asinh(z)` for the given complex number `z`.
612 | public func asinh(_ z: C) -> C {
613 | return log(z.plus(sqrt(z.times(z).plus(C(C.Float(1))))))
614 | }
615 |
616 | /// Returns `acosh(z)` for the given complex number `z`.
617 | public func acosh(_ z: C) -> C {
618 | return log(z.plus(sqrt(z.times(z).minus(C(C.Float(1))))))
619 | }
620 |
621 | /// Returns `atanh(z)` for the given complex number `z`.
622 | public func atanh(_ z: C) -> C {
623 | let x = C(C.Float(1)).plus(z)
624 | let y = C(C.Float(1)).minus(z)
625 | return log(x.divided(by: y)).divided(by: C.Float(2))
626 | }
627 |
628 | /// This extensions provides access to a few complex constants.
629 | extension Complex {
630 |
631 | /// The additive identity for complex numbers.
632 | public static var zero: Complex {
633 | Complex(0, 0)
634 | }
635 |
636 | /// The multiplicative identity for complex numbers.
637 | public static var one: Complex {
638 | Complex(1, 0)
639 | }
640 |
641 | /// The imaginary unit.
642 | public static var i: Complex {
643 | Complex(0, 1)
644 | }
645 |
646 | /// One representation of infinity.
647 | public static var infinity: Complex {
648 | Complex(.infinity, 0)
649 | }
650 | }
651 |
652 | /// This extension implements the logic to make `Complex` codable if `T` is codable.
653 | extension Complex: Codable where T: Codable {
654 |
655 | // Make coding key names explicit to avoid automatic extension.
656 | enum CodingKeys: String, CodingKey {
657 | case re = "real"
658 | case im = "imaginary"
659 | }
660 |
661 | }
662 |
663 | /// This extension implements the logic to make `Complex` sendable if `T` is sendable.
664 | extension Complex: Sendable where T: Sendable {
665 | }
666 |
--------------------------------------------------------------------------------
/Sources/NumberKit/Rational.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Rational.swift
3 | // NumberKit
4 | //
5 | // Created by Matthias Zenger on 04/08/2015.
6 | // Copyright © 2015-2020 Matthias Zenger. All rights reserved.
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,x either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 | //
20 |
21 | import Foundation
22 |
23 | // There are many places in this package where overflow can cause incorrect
24 | // results. TODO: Eliminate these bugs!
25 |
26 | /// The `RationalNumber` protocol defines an interface for rational numbers. A rational
27 | /// number is a signed number that can be expressed as the quotient of two integers
28 | /// a and b: a / b. a is called the numerator, b is called the denominator. b must
29 | /// not be zero.
30 | public protocol RationalNumber: SignedNumeric,
31 | Comparable,
32 | Hashable,
33 | CustomStringConvertible {
34 |
35 | /// The integer type on which this rational number is based.
36 | associatedtype Integer: IntegerNumber
37 |
38 | /// The numerator of this rational number.
39 | var numerator: Integer { get }
40 |
41 | /// The denominator of this rational number.
42 | var denominator: Integer { get }
43 |
44 | /// Returns the `Rational` as a value of type `Integer` if this is possible. If the number
45 | /// cannot be expressed as a `Integer`, this property returns `nil`.
46 | var intValue: Integer? { get }
47 |
48 | /// Returns the `Rational` value as a float value
49 | var floatValue: Float { get }
50 |
51 | /// Returns the `Rational` value as a double value
52 | var doubleValue: Double { get }
53 |
54 | /// Is true if the rational value is negative.
55 | var isNegative: Bool { get }
56 |
57 | /// Is true if the rational value is zero.
58 | var isZero: Bool { get }
59 |
60 | /// The absolute rational value (without sign).
61 | var abs: Self { get }
62 |
63 | /// The negated rational value.
64 | var negate: Self { get }
65 |
66 | /// Returns -1 if `self` is less than `rhs`,
67 | /// 0 if `self` is equals to `rhs`,
68 | /// +1 if `self` is greater than `rhs`
69 | func compare(to rhs: Self) -> Int
70 |
71 | /// Returns the sum of this rational value and `rhs`.
72 | func plus(_ rhs: Self) -> Self
73 |
74 | /// Returns the difference between this rational value and `rhs`.
75 | func minus(_ rhs: Self) -> Self
76 |
77 | /// Multiplies this rational value with `rhs` and returns the result.
78 | func times(_ rhs: Self) -> Self
79 |
80 | /// Divides this rational value by `rhs` and returns the result.
81 | func divided(by rhs: Self) -> Self
82 |
83 | /// Raises this rational value to the power of `exp`.
84 | func toPower(of exp: Integer) -> Self
85 |
86 | /// Adds `rhs` to `self` and reports the result together with a boolean indicating an overflow.
87 | func addingReportingOverflow(_ rhs: Self) -> (partialValue: Self, overflow: Bool)
88 |
89 | /// Subtracts `rhs` from `self` and reports the result together with a boolean indicating
90 | /// an overflow.
91 | func subtractingReportingOverflow(_ rhs: Self) -> (partialValue: Self, overflow: Bool)
92 |
93 | /// Multiplies `rhs` with `self` and reports the result together with a boolean indicating
94 | /// an overflow.
95 | func multipliedReportingOverflow(by rhs: Self) -> (partialValue: Self, overflow: Bool)
96 |
97 | /// Divides `self` by `rhs` and reports the result together with a boolean indicating
98 | /// an overflow.
99 | func dividedReportingOverflow(by rhs: Self) -> (partialValue: Self, overflow: Bool)
100 |
101 | /// Returns the greatest common denominator for `self` and `y` and a boolean which indicates
102 | /// whether there was an overflow.
103 | func gcdReportingOverflow(with y: Self) -> (partialValue: Self, overflow: Bool)
104 |
105 | /// Returns the least common multiplier for `self` and `y` and a boolean which indicates
106 | /// whether there was an overflow.
107 | func lcmReportingOverflow(with y: Self) -> (partialValue: Self, overflow: Bool)
108 | }
109 |
110 | /// Struct `Rational` implements the `RationalNumber` interface on top of the
111 | /// integer type `T`. `Rational` always represents rational numbers in normalized
112 | /// form such that the greatest common divisor of the numerator and the denominator
113 | /// is always 1. In addition, the sign of the rational number is defined by the
114 | /// numerator. The denominator is always positive.
115 | public struct Rational: RationalNumber, CustomStringConvertible {
116 |
117 | /// The numerator of this rational number. This is a signed integer.
118 | public let numerator: T
119 |
120 | /// The denominator of this rational number. This integer is always positive.
121 | public let denominator: T
122 |
123 | /// Sets numerator and denominator without normalization. This function must not be called
124 | /// outside of the NumberKit framework.
125 | private init(numerator: T, denominator: T) {
126 | self.numerator = numerator
127 | self.denominator = denominator
128 | }
129 |
130 | /// Creates a rational number from a given numerator and denominator, ignoring overflow;
131 | /// it creates an incorrect result iff the correct result is not expressible in the given type.
132 | public init(_ numerator: T, _ denominator: T) {
133 | precondition(denominator != 0, "rational with zero denominator")
134 | self = Rational.rationalWithOverflow(numerator, denominator).0 // Ignore overflow
135 | }
136 |
137 | /// Creates a `Rational` from the given integer value of type `T`
138 | public init(_ value: T) {
139 | self.init(numerator: value, denominator: T.one)
140 | }
141 |
142 | /// Creates a rational number by rationalizing a `Double` value.
143 | public init(_ value: Double, precision: Double = 1.0e-8) {
144 | var x = value
145 | var a = Foundation.floor(x)
146 | var (h1, k1, h, k) = (T.one, T.zero, T(a), T.one)
147 | while x - a > precision * k.doubleValue * k.doubleValue {
148 | x = 1.0/(x - a)
149 | a = Foundation.floor(x)
150 | (h1, k1, h, k) = (h, k, h1 + T(a) * h, k1 + T(a) * k)
151 | }
152 | self.init(numerator: h, denominator: k)
153 | }
154 |
155 | /// Create an instance initialized to `value`.
156 | public init(integerLiteral value: Int64) {
157 | self.init(T(value))
158 | }
159 |
160 | public init?(exactly source: S) {
161 | if let numerator = T(exactly: source) {
162 | self.init(numerator)
163 | } else {
164 | return nil
165 | }
166 | }
167 |
168 | /// Creates a `Rational` from a string containing a rational number using the base
169 | /// defined by parameter `radix`. The syntax of the rational number is defined as follows:
170 | ///
171 | /// Rational = Numerator '/' Denominator
172 | /// | SignedInteger
173 | /// Numerator = SignedInteger
174 | /// Denominator = SignedInteger
175 | public init?(from str: String, radix: Int = 10) {
176 | precondition(radix >= 2, "radix >= 2 required")
177 | if let idx = str.firstIndex(of: rationalSeparator) {
178 | if let numVal = Int64(str[..` number using base 10.
211 | public var description: String {
212 | return self.denominator == 1 || self.numerator == 0 ?
213 | self.numerator.description :
214 | self.numerator.description + String(rationalSeparator) + self.denominator.description
215 | }
216 |
217 | /// Returns the (non-negative) Greatest Common Divisor (GCD) of two `T: IntegerNumber`
218 | /// values `x` and `y`. Any overflow occurring during the gcd( is ignored.
219 | @available(*, deprecated, message: "moved to IntegerNumber.gcd")
220 | public static func gcd(_ x: T, _ y: T) -> T { T.gcd(x, y) }
221 |
222 | /// Compute the (non-negative) Least Common Multiple (LCM) of two `T: IntegerNumber`
223 | /// values `x` and `y`. Any overflow during the computation is ignored.
224 | @available(*, deprecated, message: "moved to IntegerNumber.lcm")
225 | public static func lcm(_ x: T, _ y: T) -> T { T.lcm(x, y) }
226 |
227 | /// Given two rational values `this` and `that`, return the two equivalent (but possibly
228 | /// not normalized) values `num0 / denom` and `num1 / denom`, where `denom` is the LCM of
229 | /// the two denominators. In case of overflow, the wrong result may be returned.
230 | private func commonDenomWith(_ other: Rational) -> (num0: T, num1: T, denom: T) {
231 | let (num0, num1, denom, _) = Rational.commonDenomWithOverflow(self, other) // Ignore overflow.
232 | return (num0, num1, denom)
233 | }
234 |
235 | /// For hashing values.
236 | public func hash(into hasher: inout Hasher) {
237 | hasher.combine(numerator)
238 | hasher.combine(denominator)
239 | }
240 |
241 | /// The absolute rational value (without sign).
242 | public var abs: Rational {
243 | return self.magnitude
244 | }
245 |
246 | /// The magnitude of the rational value.
247 | public var magnitude: Rational {
248 | return Rational(numerator < 0 ? -numerator : numerator, denominator)
249 | }
250 |
251 | /// The negated rational value.
252 | public var negate: Rational {
253 | return Rational(-numerator, denominator)
254 | }
255 |
256 | /// Is true if the rational value is negative.
257 | public var isNegative: Bool {
258 | return numerator < 0
259 | }
260 |
261 | /// Is true if the rational value is zero.
262 | public var isZero: Bool {
263 | return numerator == 0
264 | }
265 |
266 | /// Returns -1 if `self` is less than `rhs`,
267 | /// 0 if `self` is equals to `rhs`,
268 | /// +1 if `self` is greater than `rhs`
269 | public func compare(to rhs: Rational) -> Int {
270 | let (n1, n2, _) = self.commonDenomWith(rhs)
271 | return n1 == n2 ? 0 : (n1 < n2 ? -1 : 1)
272 | }
273 |
274 | /// Returns the sum of this rational value and `rhs`.
275 | public func plus(_ rhs: Rational) -> Rational {
276 | let (n1, n2, denom) = self.commonDenomWith(rhs)
277 | return Rational(n1 + n2, denom)
278 | }
279 |
280 | /// Returns the difference between this rational value and `rhs`.
281 | public func minus(_ rhs: Rational) -> Rational {
282 | let (n1, n2, denom) = self.commonDenomWith(rhs)
283 | return Rational(n1 - n2, denom)
284 | }
285 |
286 | /// Multiplies this rational value with `rhs` and returns the result.
287 | public func times(_ rhs: Rational) -> Rational {
288 | return Rational(self.numerator * rhs.numerator, self.denominator * rhs.denominator)
289 | }
290 |
291 | /// Divides this rational value by `rhs` and returns the result.
292 | public func divided(by rhs: Rational) -> Rational {
293 | return Rational(self.numerator * rhs.denominator, self.denominator * rhs.numerator)
294 | }
295 |
296 | /// Raises this rational value to the power of `exp`.
297 | public func toPower(of exp: T) -> Rational {
298 | if (exp < 0) {
299 | return Rational(denominator.toPower(of: -exp), numerator.toPower(of: -exp))
300 | } else {
301 | return Rational(numerator.toPower(of: exp), denominator.toPower(of: exp))
302 | }
303 | }
304 |
305 | /// Returns the greatest common denominator (GCD) of the two given rational numbers, ignoring
306 | /// overflow; it may return an incorrect result if overflow occurs during the computation.
307 | public static func gcd(_ x: Rational, _ y: Rational) -> Rational {
308 | return Rational(T.gcd(x.numerator, y.numerator), T.lcm(x.denominator, y.denominator))
309 | }
310 |
311 | /// Returns the least common multiple (LCM) of the two given rational numbers, ignoring
312 | /// overflow; it may return an incorrect result if overflow occurs during the computation.
313 | public static func lcm(_ x: Rational, _ y: Rational) -> Rational {
314 | let (xn, yn, denom) = x.commonDenomWith(y)
315 | return Rational(T.lcm(xn, yn), denom)
316 | }
317 | }
318 |
319 | /// This extension implements the boilerplate to make `Rational` compatible
320 | /// to the applicable Swift 4 protocols. `Rational` is convertible from Strings and
321 | /// implements basic arithmetic operations which keep track of overflows.
322 | extension Rational: ExpressibleByStringLiteral {
323 |
324 | public init(stringLiteral value: String) {
325 | if let rat = Rational(from: value) {
326 | self.init(numerator: rat.numerator, denominator: rat.denominator)
327 | } else {
328 | self.init(0)
329 | }
330 | }
331 |
332 | public init(extendedGraphemeClusterLiteral value: String) {
333 | self.init(stringLiteral: value)
334 | }
335 |
336 | public init(unicodeScalarLiteral value: String) {
337 | self.init(stringLiteral: value)
338 | }
339 |
340 | /// Creates a rational number from a given numerator and denominator, along with a Boolean
341 | /// indicating whether overflow occurred in the operation, iff the correct value is not
342 | /// representable in the given type.
343 | public static func rationalWithOverflow(_ numerator: T, _ denominator: T) ->
344 | (value: Rational, overflow: Bool) {
345 | guard denominator != 0 else {
346 | return (0, true)
347 | }
348 | // Eliminate special cases early that might otherwise report overflow.
349 | if denominator == 1 {
350 | return (Rational(numerator), false)
351 | } else if numerator == 0 {
352 | return (0, false)
353 | } else if numerator == denominator {
354 | return (1, false)
355 | }
356 | // Numerator and denominator are now both non-zero.
357 | let gcd = T.gcd(numerator, denominator) // Safe: numerator != denominator.
358 | let normalizedNumerator = numerator / gcd // Safe: gcd is positive and divides numerator.
359 | let normalizedDenominator = denominator / gcd // Safe: gcd is positive and divides denominator.
360 | // Overflows if numerator == T.min and denominator is odd.
361 | let (absNumerator, numeratorOverflow) = T.absWithOverflow(normalizedNumerator)
362 | // Overflows if denominator == T.min and numerator is odd.
363 | let (absDenominator, denominatorOverflow) = T.absWithOverflow(normalizedDenominator)
364 | // The rational value `absNumerator / absDenominator` is already normalized.
365 | let resultNumerator = (numerator > 0) == (denominator > 0) ? absNumerator : -absNumerator
366 | let resultOverflow = numeratorOverflow || denominatorOverflow
367 | return (Rational(numerator: resultNumerator, denominator: absDenominator), resultOverflow)
368 | }
369 |
370 | /// Given two rational values `this` and `that`, return the two equivalent (but possibly not
371 | /// normalized) values `num0 / denom` and `num1 / denom`, where `denom` is the LCM is the two
372 | /// denominators, together with a Boolean indicating whether overflow occurred during the
373 | /// computation, iff the result cannot be represented in this type.
374 | private static func commonDenomWithOverflow(_ this: Rational, _ that: Rational) ->
375 | (num0: T, num1: T, denom: T, overflow: Bool) {
376 | let (lcmOfDenominators, lcmOverflow) = T.lcmWithOverflow(this.denominator, that.denominator)
377 | let (num0, num0Overflow) = this.numerator.multipliedReportingOverflow(
378 | by: lcmOfDenominators / this.denominator)
379 | let (num1, num1Overflow) = that.numerator.multipliedReportingOverflow(
380 | by: lcmOfDenominators / that.denominator)
381 | return (num0, num1, lcmOfDenominators, lcmOverflow || num0Overflow || num1Overflow)
382 | }
383 |
384 | /// Returns the (non-negative) Greatest Common Divisor (GCD) of two `T: IntegerNumber`
385 | /// values `x` and `y`, together with a Boolean indicating whether overflow occurred
386 | /// during the computation, in which case the result may be wrong.
387 | @available(*, deprecated, message: "moved to IntegerNumber.gcdWithOverflow")
388 | public static func gcdWithOverflow(_ x: T, _ y: T) -> (T, Bool) {
389 | return T.gcdWithOverflow(x, y)
390 | }
391 |
392 | /// Returns the (non-negative) Least Common Multiple (LCM) of two `T: IntegerNumber`
393 | /// values `x` and `y`, together with a Boolean indicating whether overflow occurred
394 | /// during the computation, in which case the result may be wrong.
395 | @available(*, deprecated, message: "moved to IntegerNumber.lcmWithOverflow")
396 | public static func lcmWithOverflow(_ x: T, _ y: T) -> (T, Bool) {
397 | return T.lcmWithOverflow(x, y)
398 | }
399 |
400 | /// Add `self` and `rhs` and return a tuple consisting of the result and a boolean which
401 | /// indicates whether there was an overflow.
402 | public func addingReportingOverflow(_ rhs: Rational)
403 | -> (partialValue: Rational, overflow: Bool) {
404 | let (n1, n2, denom, overflow1) = Rational.commonDenomWithOverflow(self, rhs)
405 | let (numer, overflow2) = n1.addingReportingOverflow(n2)
406 | let (res, overflow3) = Rational.rationalWithOverflow(numer, denom)
407 | return (res, overflow1 || overflow2 || overflow3)
408 | }
409 |
410 | /// Subtract `rhs` from `self` and return a tuple consisting of the result and a boolean which
411 | /// indicates whether there was an overflow.
412 | public func subtractingReportingOverflow(_ rhs: Rational)
413 | -> (partialValue: Rational, overflow: Bool) {
414 | let (n1, n2, denom, overflow1) = Rational.commonDenomWithOverflow(self, rhs)
415 | let (numer, overflow2) = n1.subtractingReportingOverflow(n2)
416 | let (res, overflow3) = Rational.rationalWithOverflow(numer, denom)
417 | return (res, overflow1 || overflow2 || overflow3)
418 | }
419 |
420 | /// Multiply `self` and `rhs` and return a tuple consisting of the result and a boolean which
421 | /// indicates whether there was an overflow.
422 | public func multipliedReportingOverflow(by rhs: Rational)
423 | -> (partialValue: Rational, overflow: Bool) {
424 | let (numer, overflow1) = self.numerator.multipliedReportingOverflow(by: rhs.numerator)
425 | let (denom, overflow2) = self.denominator.multipliedReportingOverflow(by: rhs.denominator)
426 | let (res, overflow3) = Rational.rationalWithOverflow(numer, denom)
427 | return (res, overflow1 || overflow2 || overflow3)
428 | }
429 |
430 | /// Divide `lhs` by `rhs` and return a tuple consisting of the result and a boolean which
431 | /// indicates whether there was an overflow.
432 | public func dividedReportingOverflow(by rhs: Rational)
433 | -> (partialValue: Rational, overflow: Bool) {
434 | let (numer, overflow1) = self.numerator.multipliedReportingOverflow(by: rhs.denominator)
435 | let (denom, overflow2) = self.denominator.multipliedReportingOverflow(by: rhs.numerator)
436 | let (res, overflow3) = Rational.rationalWithOverflow(numer, denom)
437 | return (res, overflow1 || overflow2 || overflow3)
438 | }
439 |
440 | /// Returns the greatest common denominator for `self` and `y` and a boolean which indicates
441 | /// whether there was an overflow.
442 | public func gcdReportingOverflow(with y: Rational)
443 | -> (partialValue: Rational, overflow: Bool) {
444 | let (numer, overflow1) = T.gcdWithOverflow(self.numerator, y.numerator)
445 | let (denom, overflow2) = T.lcmWithOverflow(self.denominator, y.denominator)
446 | return (Rational(numer, denom), overflow1 || overflow2)
447 | }
448 |
449 | /// Returns the least common multiplier for `self` and `y` and a boolean which indicates
450 | /// whether there was an overflow.
451 | public func lcmReportingOverflow(with y: Rational)
452 | -> (partialValue: Rational, overflow: Bool) {
453 | let (xn, yn, denom, overflow1) = Rational.commonDenomWithOverflow(self, y)
454 | let (numer, overflow2) = T.lcmWithOverflow(xn, yn)
455 | return (Rational(numer, denom), overflow1 || overflow2)
456 | }
457 | }
458 |
459 | /// Negates `num`.
460 | public prefix func - (num: R) -> R {
461 | return num.negate
462 | }
463 |
464 | /// Returns the sum of `lhs` and `rhs`.
465 | public func + (lhs: R, rhs: R) -> R {
466 | return lhs.plus(rhs)
467 | }
468 |
469 | /// Returns the difference between `lhs` and `rhs`.
470 | public func - (lhs: R, rhs: R) -> R {
471 | return lhs.minus(rhs)
472 | }
473 |
474 | /// Multiplies `lhs` with `rhs` and returns the result.
475 | public func * (lhs: R, rhs: R) -> R {
476 | return lhs.times(rhs)
477 | }
478 |
479 | /// Divides `lhs` by `rhs` and returns the result.
480 | public func / (lhs: R, rhs: R) -> R {
481 | return lhs.divided(by: rhs)
482 | }
483 |
484 | /// Divides `lhs` by `rhs` and returns the result.
485 | public func / (lhs: T, rhs: T) -> Rational {
486 | return Rational(lhs, rhs)
487 | }
488 |
489 | /// Raises rational value `lhs` to the power of `exp`.
490 | public func ** (lhs: R, exp: R.Integer) -> R {
491 | return lhs.toPower(of: exp)
492 | }
493 |
494 | /// Assigns `lhs` the sum of `lhs` and `rhs`.
495 | public func += (lhs: inout R, rhs: R) {
496 | lhs = lhs.plus(rhs)
497 | }
498 |
499 | /// Assigns `lhs` the difference between `lhs` and `rhs`.
500 | public func -= (lhs: inout R, rhs: R) {
501 | lhs = lhs.minus(rhs)
502 | }
503 |
504 | /// Assigns `lhs` the result of multiplying `lhs` with `rhs`.
505 | public func *= (lhs: inout R, rhs: R) {
506 | lhs = lhs.times(rhs)
507 | }
508 |
509 | /// Assigns `lhs` the result of dividing `lhs` by `rhs`.
510 | public func /= (lhs: inout R, rhs: R) {
511 | lhs = lhs.divided(by: rhs)
512 | }
513 |
514 | /// Assigns `lhs` the result of raising rational value `lhs` to the power of `exp`.
515 | public func **= (lhs: inout R, exp: R.Integer) {
516 | lhs = lhs.toPower(of: exp)
517 | }
518 |
519 | /// Returns the sum of `lhs` and `rhs`.
520 | public func &+ (lhs: R, rhs: R) -> R {
521 | return lhs.addingReportingOverflow(rhs).partialValue
522 | }
523 |
524 | /// Returns the difference between `lhs` and `rhs`.
525 | public func &- (lhs: R, rhs: R) -> R {
526 | return lhs.subtractingReportingOverflow(rhs).partialValue
527 | }
528 |
529 | /// Multiplies `lhs` with `rhs` and returns the result.
530 | public func &* (lhs: R, rhs: R) -> R {
531 | return lhs.multipliedReportingOverflow(by: rhs).partialValue
532 | }
533 |
534 | /// Returns true if `lhs` is less than `rhs`, false otherwise.
535 | public func < (lhs: R, rhs: R) -> Bool {
536 | return lhs.compare(to: rhs) < 0
537 | }
538 |
539 | /// Returns true if `lhs` is less than or equals `rhs`, false otherwise.
540 | public func <= (lhs: R, rhs: R) -> Bool {
541 | return lhs.compare(to: rhs) <= 0
542 | }
543 |
544 | /// Returns true if `lhs` is greater or equals `rhs`, false otherwise.
545 | public func >= (lhs: R, rhs: R) -> Bool {
546 | return lhs.compare(to: rhs) >= 0
547 | }
548 |
549 | /// Returns true if `lhs` is greater than equals `rhs`, false otherwise.
550 | public func > (lhs: R, rhs: R) -> Bool {
551 | return lhs.compare(to: rhs) > 0
552 | }
553 |
554 | /// Returns true if `lhs` is equals `rhs`, false otherwise.
555 | public func == (lhs: R, rhs: R) -> Bool {
556 | return lhs.compare(to: rhs) == 0
557 | }
558 |
559 | /// Returns true if `lhs` is not equals `rhs`, false otherwise.
560 | public func != (lhs: R, rhs: R) -> Bool {
561 | return lhs.compare(to: rhs) != 0
562 | }
563 |
564 | /// This extension implements the logic to make `Rational` codable if `T` is codable.
565 | extension Rational: Codable where T: Codable {
566 |
567 | // Make coding key names explicit to avoid automatic extension.
568 | enum CodingKeys: String, CodingKey {
569 | case numerator
570 | case denominator
571 | }
572 |
573 | }
574 |
575 | /// This extension implements the logic to make `Rational` sendable if `T` is sendable.
576 | extension Rational: Sendable where T: Sendable {
577 | }
578 |
579 | // TODO: make this a static member of `Rational` once this is supported
580 | private let rationalSeparator: Character = "/"
581 |
--------------------------------------------------------------------------------
/NumberKit.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | CC0741571B81269200406A43 /* Rational.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0741561B81269200406A43 /* Rational.swift */; };
11 | CC0741591B8127B600406A43 /* Complex.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0741581B8127B600406A43 /* Complex.swift */; };
12 | CC07415B1B813A0600406A43 /* RationalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC07415A1B813A0600406A43 /* RationalTests.swift */; };
13 | CC07415D1B813B0300406A43 /* ComplexTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC07415C1B813B0300406A43 /* ComplexTests.swift */; };
14 | CC0A59F62BC889DF00F155FE /* Integer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0A59F52BC8891800F155FE /* Integer.swift */; };
15 | CC0A59F72BC889E000F155FE /* Integer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0A59F52BC8891800F155FE /* Integer.swift */; };
16 | CC0A59F92BC990FA00F155FE /* IntegerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0A59F82BC990AF00F155FE /* IntegerTests.swift */; };
17 | CC50F66A2C722A140071A563 /* IntegerNumberTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC50F6692C722A140071A563 /* IntegerNumberTests.swift */; };
18 | CC99F5531B7AA6E200355E1E /* NumberKit.h in Headers */ = {isa = PBXBuildFile; fileRef = CC99F5521B7AA6E200355E1E /* NumberKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
19 | CC99F55A1B7AA6E200355E1E /* NumberKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CC99F54F1B7AA6E200355E1E /* NumberKit.framework */; };
20 | CC99F56A1B7AA76600355E1E /* BigIntTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC99F5691B7AA76600355E1E /* BigIntTests.swift */; };
21 | CC99F56C1B7AA81500355E1E /* BigInt.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC99F56B1B7AA81500355E1E /* BigInt.swift */; };
22 | CC99F56E1B7AAAA300355E1E /* NumberUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC99F56D1B7AAAA300355E1E /* NumberUtil.swift */; };
23 | CC99F5701B7AAB5300355E1E /* NumberUtilTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC99F56F1B7AAB5300355E1E /* NumberUtilTests.swift */; };
24 | CCA2651723EF73B700483329 /* CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCA2651623EF73B700483329 /* CodableTests.swift */; };
25 | CCA8E8111F7780C800927A41 /* FloatingPointNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCA8E8101F7780C800927A41 /* FloatingPointNumber.swift */; };
26 | CCA8E8131F77814F00927A41 /* IntegerNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCA8E8121F77814F00927A41 /* IntegerNumber.swift */; };
27 | CCD2603D23F20F7200DFE5A4 /* NumberKit_iOS.h in Headers */ = {isa = PBXBuildFile; fileRef = CCD2603B23F20F7200DFE5A4 /* NumberKit_iOS.h */; platformFilter = ios; settings = {ATTRIBUTES = (Public, ); }; };
28 | CCD2604123F2119900DFE5A4 /* NumberUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC99F56D1B7AAAA300355E1E /* NumberUtil.swift */; };
29 | CCD2604223F2119C00DFE5A4 /* IntegerNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCA8E8121F77814F00927A41 /* IntegerNumber.swift */; };
30 | CCD2604323F2119F00DFE5A4 /* FloatingPointNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCA8E8101F7780C800927A41 /* FloatingPointNumber.swift */; };
31 | CCD2604423F211A200DFE5A4 /* BigInt.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC99F56B1B7AA81500355E1E /* BigInt.swift */; };
32 | CCD2604523F211A500DFE5A4 /* Rational.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0741561B81269200406A43 /* Rational.swift */; };
33 | CCD2604623F211A800DFE5A4 /* Complex.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0741581B8127B600406A43 /* Complex.swift */; };
34 | /* End PBXBuildFile section */
35 |
36 | /* Begin PBXContainerItemProxy section */
37 | CC99F55B1B7AA6E200355E1E /* PBXContainerItemProxy */ = {
38 | isa = PBXContainerItemProxy;
39 | containerPortal = CC99F5461B7AA6E200355E1E /* Project object */;
40 | proxyType = 1;
41 | remoteGlobalIDString = CC99F54E1B7AA6E200355E1E;
42 | remoteInfo = NumberKit;
43 | };
44 | /* End PBXContainerItemProxy section */
45 |
46 | /* Begin PBXFileReference section */
47 | CC0741561B81269200406A43 /* Rational.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rational.swift; sourceTree = ""; };
48 | CC0741581B8127B600406A43 /* Complex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Complex.swift; sourceTree = ""; };
49 | CC07415A1B813A0600406A43 /* RationalTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RationalTests.swift; sourceTree = ""; };
50 | CC07415C1B813B0300406A43 /* ComplexTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ComplexTests.swift; sourceTree = ""; };
51 | CC0A59F52BC8891800F155FE /* Integer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Integer.swift; sourceTree = ""; wrapsLines = 0; };
52 | CC0A59F82BC990AF00F155FE /* IntegerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerTests.swift; sourceTree = ""; };
53 | CC50F6692C722A140071A563 /* IntegerNumberTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerNumberTests.swift; sourceTree = ""; };
54 | CC5E473320C428D500F21B03 /* LinuxMain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LinuxMain.swift; path = Tests/LinuxMain.swift; sourceTree = SOURCE_ROOT; };
55 | CC99F54F1B7AA6E200355E1E /* NumberKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NumberKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
56 | CC99F5521B7AA6E200355E1E /* NumberKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NumberKit.h; sourceTree = ""; };
57 | CC99F5541B7AA6E200355E1E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
58 | CC99F5591B7AA6E200355E1E /* NumberKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NumberKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
59 | CC99F5601B7AA6E200355E1E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
60 | CC99F5691B7AA76600355E1E /* BigIntTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BigIntTests.swift; sourceTree = ""; };
61 | CC99F56B1B7AA81500355E1E /* BigInt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BigInt.swift; sourceTree = ""; };
62 | CC99F56D1B7AAAA300355E1E /* NumberUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberUtil.swift; sourceTree = ""; };
63 | CC99F56F1B7AAB5300355E1E /* NumberUtilTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumberUtilTests.swift; sourceTree = ""; };
64 | CC99F5711B7AB5E600355E1E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
65 | CC99F5721B7AB66E00355E1E /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; };
66 | CCA2651623EF73B700483329 /* CodableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableTests.swift; sourceTree = ""; };
67 | CCA8E8101F7780C800927A41 /* FloatingPointNumber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPointNumber.swift; sourceTree = ""; };
68 | CCA8E8121F77814F00927A41 /* IntegerNumber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerNumber.swift; sourceTree = ""; };
69 | CCB691501EB7710700B32D55 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; };
70 | CCD2603923F20F7200DFE5A4 /* NumberKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NumberKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
71 | CCD2603B23F20F7200DFE5A4 /* NumberKit_iOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NumberKit_iOS.h; sourceTree = ""; };
72 | CCD2603C23F20F7200DFE5A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
73 | CCE9DD301B8BB4A600340DD1 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = ""; };
74 | /* End PBXFileReference section */
75 |
76 | /* Begin PBXFrameworksBuildPhase section */
77 | CC99F54B1B7AA6E200355E1E /* Frameworks */ = {
78 | isa = PBXFrameworksBuildPhase;
79 | buildActionMask = 2147483647;
80 | files = (
81 | );
82 | runOnlyForDeploymentPostprocessing = 0;
83 | };
84 | CC99F5561B7AA6E200355E1E /* Frameworks */ = {
85 | isa = PBXFrameworksBuildPhase;
86 | buildActionMask = 2147483647;
87 | files = (
88 | CC99F55A1B7AA6E200355E1E /* NumberKit.framework in Frameworks */,
89 | );
90 | runOnlyForDeploymentPostprocessing = 0;
91 | };
92 | CCD2603623F20F7200DFE5A4 /* Frameworks */ = {
93 | isa = PBXFrameworksBuildPhase;
94 | buildActionMask = 2147483647;
95 | files = (
96 | );
97 | runOnlyForDeploymentPostprocessing = 0;
98 | };
99 | /* End PBXFrameworksBuildPhase section */
100 |
101 | /* Begin PBXGroup section */
102 | CC99F5451B7AA6E200355E1E = {
103 | isa = PBXGroup;
104 | children = (
105 | CC99F5711B7AB5E600355E1E /* README.md */,
106 | CCE9DD301B8BB4A600340DD1 /* CHANGELOG.md */,
107 | CC99F5721B7AB66E00355E1E /* LICENSE */,
108 | CCB691501EB7710700B32D55 /* Package.swift */,
109 | CC99F5511B7AA6E200355E1E /* NumberKit */,
110 | CCD2603A23F20F7200DFE5A4 /* NumberKit iOS */,
111 | CC99F55D1B7AA6E200355E1E /* NumberKitTests */,
112 | CC99F5501B7AA6E200355E1E /* Products */,
113 | );
114 | indentWidth = 2;
115 | sourceTree = "";
116 | tabWidth = 2;
117 | };
118 | CC99F5501B7AA6E200355E1E /* Products */ = {
119 | isa = PBXGroup;
120 | children = (
121 | CC99F54F1B7AA6E200355E1E /* NumberKit.framework */,
122 | CC99F5591B7AA6E200355E1E /* NumberKitTests.xctest */,
123 | CCD2603923F20F7200DFE5A4 /* NumberKit.framework */,
124 | );
125 | name = Products;
126 | sourceTree = "";
127 | };
128 | CC99F5511B7AA6E200355E1E /* NumberKit */ = {
129 | isa = PBXGroup;
130 | children = (
131 | CC99F56D1B7AAAA300355E1E /* NumberUtil.swift */,
132 | CCA8E8121F77814F00927A41 /* IntegerNumber.swift */,
133 | CCA8E8101F7780C800927A41 /* FloatingPointNumber.swift */,
134 | CC99F56B1B7AA81500355E1E /* BigInt.swift */,
135 | CC0A59F52BC8891800F155FE /* Integer.swift */,
136 | CC0741561B81269200406A43 /* Rational.swift */,
137 | CC0741581B8127B600406A43 /* Complex.swift */,
138 | CC99F5521B7AA6E200355E1E /* NumberKit.h */,
139 | CC99F5541B7AA6E200355E1E /* Info.plist */,
140 | );
141 | indentWidth = 2;
142 | name = NumberKit;
143 | path = Sources/NumberKit;
144 | sourceTree = "";
145 | tabWidth = 2;
146 | };
147 | CC99F55D1B7AA6E200355E1E /* NumberKitTests */ = {
148 | isa = PBXGroup;
149 | children = (
150 | CC99F56F1B7AAB5300355E1E /* NumberUtilTests.swift */,
151 | CC50F6692C722A140071A563 /* IntegerNumberTests.swift */,
152 | CC99F5691B7AA76600355E1E /* BigIntTests.swift */,
153 | CC0A59F82BC990AF00F155FE /* IntegerTests.swift */,
154 | CC07415A1B813A0600406A43 /* RationalTests.swift */,
155 | CC07415C1B813B0300406A43 /* ComplexTests.swift */,
156 | CCA2651623EF73B700483329 /* CodableTests.swift */,
157 | CC5E473320C428D500F21B03 /* LinuxMain.swift */,
158 | CC99F5601B7AA6E200355E1E /* Info.plist */,
159 | );
160 | indentWidth = 2;
161 | name = NumberKitTests;
162 | path = Tests/NumberKitTests;
163 | sourceTree = "";
164 | tabWidth = 2;
165 | };
166 | CCD2603A23F20F7200DFE5A4 /* NumberKit iOS */ = {
167 | isa = PBXGroup;
168 | children = (
169 | CCD2603B23F20F7200DFE5A4 /* NumberKit_iOS.h */,
170 | CCD2603C23F20F7200DFE5A4 /* Info.plist */,
171 | );
172 | name = "NumberKit iOS";
173 | path = "Sources/NumberKit iOS";
174 | sourceTree = "";
175 | };
176 | /* End PBXGroup section */
177 |
178 | /* Begin PBXHeadersBuildPhase section */
179 | CC99F54C1B7AA6E200355E1E /* Headers */ = {
180 | isa = PBXHeadersBuildPhase;
181 | buildActionMask = 2147483647;
182 | files = (
183 | CC99F5531B7AA6E200355E1E /* NumberKit.h in Headers */,
184 | );
185 | runOnlyForDeploymentPostprocessing = 0;
186 | };
187 | CCD2603423F20F7200DFE5A4 /* Headers */ = {
188 | isa = PBXHeadersBuildPhase;
189 | buildActionMask = 2147483647;
190 | files = (
191 | CCD2603D23F20F7200DFE5A4 /* NumberKit_iOS.h in Headers */,
192 | );
193 | runOnlyForDeploymentPostprocessing = 0;
194 | };
195 | /* End PBXHeadersBuildPhase section */
196 |
197 | /* Begin PBXNativeTarget section */
198 | CC99F54E1B7AA6E200355E1E /* NumberKit */ = {
199 | isa = PBXNativeTarget;
200 | buildConfigurationList = CC99F5631B7AA6E200355E1E /* Build configuration list for PBXNativeTarget "NumberKit" */;
201 | buildPhases = (
202 | CC99F54C1B7AA6E200355E1E /* Headers */,
203 | CC99F54A1B7AA6E200355E1E /* Sources */,
204 | CC99F54B1B7AA6E200355E1E /* Frameworks */,
205 | CC99F54D1B7AA6E200355E1E /* Resources */,
206 | );
207 | buildRules = (
208 | );
209 | dependencies = (
210 | );
211 | name = NumberKit;
212 | productName = NumberKit;
213 | productReference = CC99F54F1B7AA6E200355E1E /* NumberKit.framework */;
214 | productType = "com.apple.product-type.framework";
215 | };
216 | CC99F5581B7AA6E200355E1E /* NumberKitTests */ = {
217 | isa = PBXNativeTarget;
218 | buildConfigurationList = CC99F5661B7AA6E200355E1E /* Build configuration list for PBXNativeTarget "NumberKitTests" */;
219 | buildPhases = (
220 | CC99F5551B7AA6E200355E1E /* Sources */,
221 | CC99F5561B7AA6E200355E1E /* Frameworks */,
222 | CC99F5571B7AA6E200355E1E /* Resources */,
223 | );
224 | buildRules = (
225 | );
226 | dependencies = (
227 | CC99F55C1B7AA6E200355E1E /* PBXTargetDependency */,
228 | );
229 | name = NumberKitTests;
230 | productName = NumberKitTests;
231 | productReference = CC99F5591B7AA6E200355E1E /* NumberKitTests.xctest */;
232 | productType = "com.apple.product-type.bundle.unit-test";
233 | };
234 | CCD2603823F20F7200DFE5A4 /* NumberKit iOS */ = {
235 | isa = PBXNativeTarget;
236 | buildConfigurationList = CCD2604023F20F7200DFE5A4 /* Build configuration list for PBXNativeTarget "NumberKit iOS" */;
237 | buildPhases = (
238 | CCD2603423F20F7200DFE5A4 /* Headers */,
239 | CCD2603523F20F7200DFE5A4 /* Sources */,
240 | CCD2603623F20F7200DFE5A4 /* Frameworks */,
241 | CCD2603723F20F7200DFE5A4 /* Resources */,
242 | );
243 | buildRules = (
244 | );
245 | dependencies = (
246 | );
247 | name = "NumberKit iOS";
248 | productName = "NumberKit-iOS";
249 | productReference = CCD2603923F20F7200DFE5A4 /* NumberKit.framework */;
250 | productType = "com.apple.product-type.framework";
251 | };
252 | /* End PBXNativeTarget section */
253 |
254 | /* Begin PBXProject section */
255 | CC99F5461B7AA6E200355E1E /* Project object */ = {
256 | isa = PBXProject;
257 | attributes = {
258 | BuildIndependentTargetsInParallel = YES;
259 | LastSwiftUpdateCheck = 0700;
260 | LastUpgradeCheck = 1530;
261 | ORGANIZATIONNAME = ObjectHub;
262 | TargetAttributes = {
263 | CC99F54E1B7AA6E200355E1E = {
264 | CreatedOnToolsVersion = 7.0;
265 | LastSwiftMigration = 1020;
266 | };
267 | CC99F5581B7AA6E200355E1E = {
268 | CreatedOnToolsVersion = 7.0;
269 | LastSwiftMigration = 1020;
270 | };
271 | CCD2603823F20F7200DFE5A4 = {
272 | CreatedOnToolsVersion = 11.3.1;
273 | DevelopmentTeam = C72Z63N8M5;
274 | ProvisioningStyle = Automatic;
275 | };
276 | };
277 | };
278 | buildConfigurationList = CC99F5491B7AA6E200355E1E /* Build configuration list for PBXProject "NumberKit" */;
279 | compatibilityVersion = "Xcode 3.2";
280 | developmentRegion = en;
281 | hasScannedForEncodings = 0;
282 | knownRegions = (
283 | en,
284 | Base,
285 | );
286 | mainGroup = CC99F5451B7AA6E200355E1E;
287 | productRefGroup = CC99F5501B7AA6E200355E1E /* Products */;
288 | projectDirPath = "";
289 | projectRoot = "";
290 | targets = (
291 | CC99F54E1B7AA6E200355E1E /* NumberKit */,
292 | CCD2603823F20F7200DFE5A4 /* NumberKit iOS */,
293 | CC99F5581B7AA6E200355E1E /* NumberKitTests */,
294 | );
295 | };
296 | /* End PBXProject section */
297 |
298 | /* Begin PBXResourcesBuildPhase section */
299 | CC99F54D1B7AA6E200355E1E /* Resources */ = {
300 | isa = PBXResourcesBuildPhase;
301 | buildActionMask = 2147483647;
302 | files = (
303 | );
304 | runOnlyForDeploymentPostprocessing = 0;
305 | };
306 | CC99F5571B7AA6E200355E1E /* Resources */ = {
307 | isa = PBXResourcesBuildPhase;
308 | buildActionMask = 2147483647;
309 | files = (
310 | );
311 | runOnlyForDeploymentPostprocessing = 0;
312 | };
313 | CCD2603723F20F7200DFE5A4 /* Resources */ = {
314 | isa = PBXResourcesBuildPhase;
315 | buildActionMask = 2147483647;
316 | files = (
317 | );
318 | runOnlyForDeploymentPostprocessing = 0;
319 | };
320 | /* End PBXResourcesBuildPhase section */
321 |
322 | /* Begin PBXSourcesBuildPhase section */
323 | CC99F54A1B7AA6E200355E1E /* Sources */ = {
324 | isa = PBXSourcesBuildPhase;
325 | buildActionMask = 2147483647;
326 | files = (
327 | CC0741591B8127B600406A43 /* Complex.swift in Sources */,
328 | CC99F56E1B7AAAA300355E1E /* NumberUtil.swift in Sources */,
329 | CCA8E8111F7780C800927A41 /* FloatingPointNumber.swift in Sources */,
330 | CCA8E8131F77814F00927A41 /* IntegerNumber.swift in Sources */,
331 | CC0A59F62BC889DF00F155FE /* Integer.swift in Sources */,
332 | CC99F56C1B7AA81500355E1E /* BigInt.swift in Sources */,
333 | CC0741571B81269200406A43 /* Rational.swift in Sources */,
334 | );
335 | runOnlyForDeploymentPostprocessing = 0;
336 | };
337 | CC99F5551B7AA6E200355E1E /* Sources */ = {
338 | isa = PBXSourcesBuildPhase;
339 | buildActionMask = 2147483647;
340 | files = (
341 | CCA2651723EF73B700483329 /* CodableTests.swift in Sources */,
342 | CC07415D1B813B0300406A43 /* ComplexTests.swift in Sources */,
343 | CC50F66A2C722A140071A563 /* IntegerNumberTests.swift in Sources */,
344 | CC0A59F92BC990FA00F155FE /* IntegerTests.swift in Sources */,
345 | CC99F5701B7AAB5300355E1E /* NumberUtilTests.swift in Sources */,
346 | CC99F56A1B7AA76600355E1E /* BigIntTests.swift in Sources */,
347 | CC07415B1B813A0600406A43 /* RationalTests.swift in Sources */,
348 | );
349 | runOnlyForDeploymentPostprocessing = 0;
350 | };
351 | CCD2603523F20F7200DFE5A4 /* Sources */ = {
352 | isa = PBXSourcesBuildPhase;
353 | buildActionMask = 2147483647;
354 | files = (
355 | CCD2604423F211A200DFE5A4 /* BigInt.swift in Sources */,
356 | CCD2604323F2119F00DFE5A4 /* FloatingPointNumber.swift in Sources */,
357 | CCD2604523F211A500DFE5A4 /* Rational.swift in Sources */,
358 | CCD2604123F2119900DFE5A4 /* NumberUtil.swift in Sources */,
359 | CC0A59F72BC889E000F155FE /* Integer.swift in Sources */,
360 | CCD2604623F211A800DFE5A4 /* Complex.swift in Sources */,
361 | CCD2604223F2119C00DFE5A4 /* IntegerNumber.swift in Sources */,
362 | );
363 | runOnlyForDeploymentPostprocessing = 0;
364 | };
365 | /* End PBXSourcesBuildPhase section */
366 |
367 | /* Begin PBXTargetDependency section */
368 | CC99F55C1B7AA6E200355E1E /* PBXTargetDependency */ = {
369 | isa = PBXTargetDependency;
370 | target = CC99F54E1B7AA6E200355E1E /* NumberKit */;
371 | targetProxy = CC99F55B1B7AA6E200355E1E /* PBXContainerItemProxy */;
372 | };
373 | /* End PBXTargetDependency section */
374 |
375 | /* Begin XCBuildConfiguration section */
376 | CC99F5611B7AA6E200355E1E /* Debug */ = {
377 | isa = XCBuildConfiguration;
378 | buildSettings = {
379 | ALWAYS_SEARCH_USER_PATHS = NO;
380 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
382 | CLANG_CXX_LIBRARY = "libc++";
383 | CLANG_ENABLE_MODULES = YES;
384 | CLANG_ENABLE_OBJC_ARC = YES;
385 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
386 | CLANG_WARN_BOOL_CONVERSION = YES;
387 | CLANG_WARN_COMMA = YES;
388 | CLANG_WARN_CONSTANT_CONVERSION = YES;
389 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
390 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
391 | CLANG_WARN_EMPTY_BODY = YES;
392 | CLANG_WARN_ENUM_CONVERSION = YES;
393 | CLANG_WARN_INFINITE_RECURSION = YES;
394 | CLANG_WARN_INT_CONVERSION = YES;
395 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
396 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
397 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
398 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
399 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
400 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
401 | CLANG_WARN_STRICT_PROTOTYPES = YES;
402 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
403 | CLANG_WARN_UNREACHABLE_CODE = YES;
404 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
405 | COPY_PHASE_STRIP = NO;
406 | CURRENT_PROJECT_VERSION = 1;
407 | DEAD_CODE_STRIPPING = YES;
408 | DEBUG_INFORMATION_FORMAT = dwarf;
409 | ENABLE_STRICT_OBJC_MSGSEND = YES;
410 | ENABLE_TESTABILITY = YES;
411 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
412 | GCC_C_LANGUAGE_STANDARD = gnu99;
413 | GCC_DYNAMIC_NO_PIC = NO;
414 | GCC_NO_COMMON_BLOCKS = YES;
415 | GCC_OPTIMIZATION_LEVEL = 0;
416 | GCC_PREPROCESSOR_DEFINITIONS = (
417 | "DEBUG=1",
418 | "$(inherited)",
419 | );
420 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
421 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
422 | GCC_WARN_UNDECLARED_SELECTOR = YES;
423 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
424 | GCC_WARN_UNUSED_FUNCTION = YES;
425 | GCC_WARN_UNUSED_VARIABLE = YES;
426 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
427 | MACOSX_DEPLOYMENT_TARGET = 10.13;
428 | MTL_ENABLE_DEBUG_INFO = YES;
429 | ONLY_ACTIVE_ARCH = YES;
430 | SDKROOT = macosx;
431 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
432 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
433 | SWIFT_VERSION = 5.0;
434 | TARGETED_DEVICE_FAMILY = "1,2";
435 | VERSIONING_SYSTEM = "apple-generic";
436 | VERSION_INFO_PREFIX = "";
437 | };
438 | name = Debug;
439 | };
440 | CC99F5621B7AA6E200355E1E /* Release */ = {
441 | isa = XCBuildConfiguration;
442 | buildSettings = {
443 | ALWAYS_SEARCH_USER_PATHS = NO;
444 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
445 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
446 | CLANG_CXX_LIBRARY = "libc++";
447 | CLANG_ENABLE_MODULES = YES;
448 | CLANG_ENABLE_OBJC_ARC = YES;
449 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
450 | CLANG_WARN_BOOL_CONVERSION = YES;
451 | CLANG_WARN_COMMA = YES;
452 | CLANG_WARN_CONSTANT_CONVERSION = YES;
453 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
454 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
455 | CLANG_WARN_EMPTY_BODY = YES;
456 | CLANG_WARN_ENUM_CONVERSION = YES;
457 | CLANG_WARN_INFINITE_RECURSION = YES;
458 | CLANG_WARN_INT_CONVERSION = YES;
459 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
460 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
461 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
462 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
463 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
464 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
465 | CLANG_WARN_STRICT_PROTOTYPES = YES;
466 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
467 | CLANG_WARN_UNREACHABLE_CODE = YES;
468 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
469 | COPY_PHASE_STRIP = NO;
470 | CURRENT_PROJECT_VERSION = 1;
471 | DEAD_CODE_STRIPPING = YES;
472 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
473 | ENABLE_NS_ASSERTIONS = NO;
474 | ENABLE_STRICT_OBJC_MSGSEND = YES;
475 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
476 | GCC_C_LANGUAGE_STANDARD = gnu99;
477 | GCC_NO_COMMON_BLOCKS = YES;
478 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
479 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
480 | GCC_WARN_UNDECLARED_SELECTOR = YES;
481 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
482 | GCC_WARN_UNUSED_FUNCTION = YES;
483 | GCC_WARN_UNUSED_VARIABLE = YES;
484 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
485 | MACOSX_DEPLOYMENT_TARGET = 10.13;
486 | MTL_ENABLE_DEBUG_INFO = NO;
487 | SDKROOT = macosx;
488 | SWIFT_COMPILATION_MODE = wholemodule;
489 | SWIFT_OPTIMIZATION_LEVEL = "-O";
490 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
491 | SWIFT_VERSION = 5.0;
492 | TARGETED_DEVICE_FAMILY = "1,2";
493 | VERSIONING_SYSTEM = "apple-generic";
494 | VERSION_INFO_PREFIX = "";
495 | };
496 | name = Release;
497 | };
498 | CC99F5641B7AA6E200355E1E /* Debug */ = {
499 | isa = XCBuildConfiguration;
500 | buildSettings = {
501 | CLANG_ENABLE_MODULES = YES;
502 | COMBINE_HIDPI_IMAGES = YES;
503 | CURRENT_PROJECT_VERSION = 3;
504 | DEAD_CODE_STRIPPING = YES;
505 | DEFINES_MODULE = YES;
506 | DYLIB_COMPATIBILITY_VERSION = 1;
507 | DYLIB_CURRENT_VERSION = 1;
508 | DYLIB_INSTALL_NAME_BASE = "@rpath";
509 | ENABLE_MODULE_VERIFIER = YES;
510 | FRAMEWORK_VERSION = A;
511 | INFOPLIST_FILE = "$(SRCROOT)/Sources/NumberKit/Info.plist";
512 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
513 | LD_RUNPATH_SEARCH_PATHS = (
514 | "$(inherited)",
515 | "@executable_path/../Frameworks",
516 | "@loader_path/Frameworks",
517 | );
518 | MARKETING_VERSION = 2.4.0;
519 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11";
520 | PRODUCT_BUNDLE_IDENTIFIER = net.objecthub.NumberKit;
521 | PRODUCT_NAME = "$(TARGET_NAME)";
522 | SKIP_INSTALL = YES;
523 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
524 | SWIFT_VERSION = 5.0;
525 | };
526 | name = Debug;
527 | };
528 | CC99F5651B7AA6E200355E1E /* Release */ = {
529 | isa = XCBuildConfiguration;
530 | buildSettings = {
531 | CLANG_ENABLE_MODULES = YES;
532 | COMBINE_HIDPI_IMAGES = YES;
533 | CURRENT_PROJECT_VERSION = 3;
534 | DEAD_CODE_STRIPPING = YES;
535 | DEFINES_MODULE = YES;
536 | DYLIB_COMPATIBILITY_VERSION = 1;
537 | DYLIB_CURRENT_VERSION = 1;
538 | DYLIB_INSTALL_NAME_BASE = "@rpath";
539 | ENABLE_MODULE_VERIFIER = YES;
540 | FRAMEWORK_VERSION = A;
541 | INFOPLIST_FILE = "$(SRCROOT)/Sources/NumberKit/Info.plist";
542 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
543 | LD_RUNPATH_SEARCH_PATHS = (
544 | "$(inherited)",
545 | "@executable_path/../Frameworks",
546 | "@loader_path/Frameworks",
547 | );
548 | MARKETING_VERSION = 2.4.0;
549 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu99 gnu++11";
550 | PRODUCT_BUNDLE_IDENTIFIER = net.objecthub.NumberKit;
551 | PRODUCT_NAME = "$(TARGET_NAME)";
552 | SKIP_INSTALL = YES;
553 | SWIFT_VERSION = 5.0;
554 | };
555 | name = Release;
556 | };
557 | CC99F5671B7AA6E200355E1E /* Debug */ = {
558 | isa = XCBuildConfiguration;
559 | buildSettings = {
560 | COMBINE_HIDPI_IMAGES = YES;
561 | DEAD_CODE_STRIPPING = YES;
562 | INFOPLIST_FILE = Tests/NumberKitTests/Info.plist;
563 | LD_RUNPATH_SEARCH_PATHS = (
564 | "$(inherited)",
565 | "@executable_path/../Frameworks",
566 | "@loader_path/../Frameworks",
567 | );
568 | MACOSX_DEPLOYMENT_TARGET = 10.13;
569 | PRODUCT_BUNDLE_IDENTIFIER = net.objecthub.NumberKitTests;
570 | PRODUCT_NAME = "$(TARGET_NAME)";
571 | SWIFT_VERSION = 5.0;
572 | };
573 | name = Debug;
574 | };
575 | CC99F5681B7AA6E200355E1E /* Release */ = {
576 | isa = XCBuildConfiguration;
577 | buildSettings = {
578 | COMBINE_HIDPI_IMAGES = YES;
579 | DEAD_CODE_STRIPPING = YES;
580 | INFOPLIST_FILE = Tests/NumberKitTests/Info.plist;
581 | LD_RUNPATH_SEARCH_PATHS = (
582 | "$(inherited)",
583 | "@executable_path/../Frameworks",
584 | "@loader_path/../Frameworks",
585 | );
586 | MACOSX_DEPLOYMENT_TARGET = 10.13;
587 | PRODUCT_BUNDLE_IDENTIFIER = net.objecthub.NumberKitTests;
588 | PRODUCT_NAME = "$(TARGET_NAME)";
589 | SWIFT_VERSION = 5.0;
590 | };
591 | name = Release;
592 | };
593 | CCD2603E23F20F7200DFE5A4 /* Debug */ = {
594 | isa = XCBuildConfiguration;
595 | buildSettings = {
596 | CLANG_ANALYZER_NONNULL = YES;
597 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
598 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
599 | CLANG_ENABLE_OBJC_WEAK = YES;
600 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
601 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
602 | CODE_SIGN_IDENTITY = "";
603 | CODE_SIGN_STYLE = Automatic;
604 | CURRENT_PROJECT_VERSION = 3;
605 | DEFINES_MODULE = YES;
606 | DEVELOPMENT_TEAM = C72Z63N8M5;
607 | DYLIB_COMPATIBILITY_VERSION = 1;
608 | DYLIB_CURRENT_VERSION = 1;
609 | DYLIB_INSTALL_NAME_BASE = "@rpath";
610 | ENABLE_MODULE_VERIFIER = YES;
611 | GCC_C_LANGUAGE_STANDARD = gnu11;
612 | INFOPLIST_FILE = "Sources/NumberKit iOS/Info.plist";
613 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
614 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
615 | LD_RUNPATH_SEARCH_PATHS = (
616 | "$(inherited)",
617 | "@executable_path/Frameworks",
618 | "@loader_path/Frameworks",
619 | );
620 | MARKETING_VERSION = 2.4.0;
621 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
622 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
623 | MTL_FAST_MATH = YES;
624 | PRODUCT_BUNDLE_IDENTIFIER = net.objecthub.NumberKit;
625 | PRODUCT_NAME = NumberKit;
626 | SDKROOT = iphoneos;
627 | SKIP_INSTALL = YES;
628 | SUPPORTS_MACCATALYST = YES;
629 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
630 | SWIFT_VERSION = 5.0;
631 | TARGETED_DEVICE_FAMILY = "1,2";
632 | };
633 | name = Debug;
634 | };
635 | CCD2603F23F20F7200DFE5A4 /* Release */ = {
636 | isa = XCBuildConfiguration;
637 | buildSettings = {
638 | CLANG_ANALYZER_NONNULL = YES;
639 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
640 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
641 | CLANG_ENABLE_OBJC_WEAK = YES;
642 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
643 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
644 | CODE_SIGN_IDENTITY = "";
645 | CODE_SIGN_STYLE = Automatic;
646 | CURRENT_PROJECT_VERSION = 3;
647 | DEFINES_MODULE = YES;
648 | DEVELOPMENT_TEAM = C72Z63N8M5;
649 | DYLIB_COMPATIBILITY_VERSION = 1;
650 | DYLIB_CURRENT_VERSION = 1;
651 | DYLIB_INSTALL_NAME_BASE = "@rpath";
652 | ENABLE_MODULE_VERIFIER = YES;
653 | GCC_C_LANGUAGE_STANDARD = gnu11;
654 | INFOPLIST_FILE = "Sources/NumberKit iOS/Info.plist";
655 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
656 | IPHONEOS_DEPLOYMENT_TARGET = 13.0;
657 | LD_RUNPATH_SEARCH_PATHS = (
658 | "$(inherited)",
659 | "@executable_path/Frameworks",
660 | "@loader_path/Frameworks",
661 | );
662 | MARKETING_VERSION = 2.4.0;
663 | MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++14";
664 | MTL_FAST_MATH = YES;
665 | PRODUCT_BUNDLE_IDENTIFIER = net.objecthub.NumberKit;
666 | PRODUCT_NAME = NumberKit;
667 | SDKROOT = iphoneos;
668 | SKIP_INSTALL = YES;
669 | SUPPORTS_MACCATALYST = YES;
670 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
671 | SWIFT_VERSION = 5.0;
672 | TARGETED_DEVICE_FAMILY = "1,2";
673 | VALIDATE_PRODUCT = YES;
674 | };
675 | name = Release;
676 | };
677 | /* End XCBuildConfiguration section */
678 |
679 | /* Begin XCConfigurationList section */
680 | CC99F5491B7AA6E200355E1E /* Build configuration list for PBXProject "NumberKit" */ = {
681 | isa = XCConfigurationList;
682 | buildConfigurations = (
683 | CC99F5611B7AA6E200355E1E /* Debug */,
684 | CC99F5621B7AA6E200355E1E /* Release */,
685 | );
686 | defaultConfigurationIsVisible = 0;
687 | defaultConfigurationName = Release;
688 | };
689 | CC99F5631B7AA6E200355E1E /* Build configuration list for PBXNativeTarget "NumberKit" */ = {
690 | isa = XCConfigurationList;
691 | buildConfigurations = (
692 | CC99F5641B7AA6E200355E1E /* Debug */,
693 | CC99F5651B7AA6E200355E1E /* Release */,
694 | );
695 | defaultConfigurationIsVisible = 0;
696 | defaultConfigurationName = Release;
697 | };
698 | CC99F5661B7AA6E200355E1E /* Build configuration list for PBXNativeTarget "NumberKitTests" */ = {
699 | isa = XCConfigurationList;
700 | buildConfigurations = (
701 | CC99F5671B7AA6E200355E1E /* Debug */,
702 | CC99F5681B7AA6E200355E1E /* Release */,
703 | );
704 | defaultConfigurationIsVisible = 0;
705 | defaultConfigurationName = Release;
706 | };
707 | CCD2604023F20F7200DFE5A4 /* Build configuration list for PBXNativeTarget "NumberKit iOS" */ = {
708 | isa = XCConfigurationList;
709 | buildConfigurations = (
710 | CCD2603E23F20F7200DFE5A4 /* Debug */,
711 | CCD2603F23F20F7200DFE5A4 /* Release */,
712 | );
713 | defaultConfigurationIsVisible = 0;
714 | defaultConfigurationName = Release;
715 | };
716 | /* End XCConfigurationList section */
717 | };
718 | rootObject = CC99F5461B7AA6E200355E1E /* Project object */;
719 | }
720 |
--------------------------------------------------------------------------------