├── 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 | [![Platforms: macOS, iOS, Linux](https://img.shields.io/badge/Platforms-macOS,%20iOS,%20Linux-blue.svg?style=flat)](https://developer.apple.com/osx/) [![Language: Swift 5/6](https://img.shields.io/badge/Language-Swift%206-green.svg?style=flat)](https://developer.apple.com/swift/) [![IDE: Xcode 15/16](https://img.shields.io/badge/IDE-Xcode%2016-orange.svg?style=flat)](https://developer.apple.com/xcode/) [![Package managers: SwiftPM, Carthage](https://img.shields.io/badge/Package%20managers-SwiftPM,%20Carthage-8E64B0.svg?style=flat)](https://github.com/Carthage/Carthage) [![License: Apache](http://img.shields.io/badge/License-Apache-lightgrey.svg?style=flat)](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 | --------------------------------------------------------------------------------