From 6a379be3125065d50bf15648f7223be351721ca8 Mon Sep 17 00:00:00 2001 From: Zachary Gorak Date: Mon, 2 Dec 2019 15:01:41 -0500 Subject: [PATCH] Added nthroot and square root function to BDouble --- Sources/Swift-Big-Number-Core.swift | 125 ++++++++++++++++++++-- Swift-BigNumber.xcodeproj/project.pbxproj | 10 +- Tests/BDoubleTests.swift | 10 +- 3 files changed, 130 insertions(+), 15 deletions(-) diff --git a/Sources/Swift-Big-Number-Core.swift b/Sources/Swift-Big-Number-Core.swift index f80159f..15391d0 100644 --- a/Sources/Swift-Big-Number-Core.swift +++ b/Sources/Swift-Big-Number-Core.swift @@ -2219,7 +2219,12 @@ public struct BDouble: public init?(exactly source: T) where T : BinaryInteger { - self.init(0.0) + let i = BInt(source) + self.init(i) + } + + public init(_ src: BInt) { + self.init(src, over: BInt(1)) } /** @@ -2589,8 +2594,17 @@ public struct BDouble: return (self.sign, self.numerator, self.denominator) } + /** + * - returns: `True` if positive, `False` otherwise + */ public func isPositive() -> Bool { return !self.sign } + /** + * - returns: `True` if negative, `False` otherwise + */ public func isNegative() -> Bool { return self.sign } + /** + * - returns: `True` if 0, `False` otherwise + */ public func isZero() -> Bool { return self.numerator.equalTo(0) } public mutating func minimize() @@ -2647,12 +2661,25 @@ public struct BDouble: return retVal } - // public func sqrt(precision digits: Int) -> BDouble - // { - // // let self = v - // // Find x such that x*x=v <==> x = v/x - // - // } + /** + * The power of 1/root + * + * - warning: This may take a while. This is only precise up until precision. When comparing results after this function ` use` nearlyEqual` + */ + public func nthroot(_ root: Int) -> BDouble + { + return self ** BDouble(BInt(1), over: BInt(root)) + } + + /** + * The square root + * + * - warning: This may take a while. This is only precise up until precision. When comparing results after this function ` use` nearlyEqual` + */ + public func squareRoot() -> BDouble + { + return self ** BDouble(BInt(1), over: BInt(2)) + } // // @@ -2682,7 +2709,9 @@ public struct BDouble: public static func +(lhs: BDouble, rhs: Double) -> BDouble { return lhs + BDouble(rhs) } public static func +(lhs: Double, rhs: BDouble) -> BDouble { return BDouble(lhs) + rhs } - + public static func +(lhs: BDouble, rhs: BInt) -> BDouble { return lhs + BDouble(rhs) } + public static func +(lhs: BInt, rhs: BDouble) -> BDouble { return BDouble(lhs) + rhs } + public static func +=(lhs: inout BDouble, rhs: BDouble) { let res = lhs + rhs lhs = res @@ -2735,7 +2764,7 @@ public struct BDouble: } public static func -(lhs: BDouble, rhs: Double) -> BDouble { return lhs - BDouble(rhs) } public static func -(lhs: Double, rhs: BDouble) -> BDouble { return BDouble(lhs) - rhs } - + public static func -(lhs: BDouble, rhs: BInt) -> BDouble { return lhs - BDouble(rhs) } public static func -=(lhs: inout BDouble, rhs: BDouble) { let res = lhs - rhs lhs = res @@ -2766,6 +2795,8 @@ public struct BDouble: } public static func *(lhs: BDouble, rhs: Double) -> BDouble { return lhs * BDouble(rhs) } public static func *(lhs: Double, rhs: BDouble) -> BDouble { return BDouble(lhs) * rhs } + public static func *(lhs: BDouble, rhs: BInt) -> BDouble { return lhs * BDouble(rhs) } + public static func *(lhs: BInt, rhs: BDouble) -> BDouble { return BDouble(lhs) * rhs } public static func *=(lhs: inout BDouble, rhs: BDouble) { let res = lhs * rhs @@ -2784,7 +2815,6 @@ public struct BDouble: // // - // TODO: Exponentiation function that supports Double/BDouble in the exponent public static func **(_ base : BDouble, _ exponent : Int) -> BDouble { if exponent == 0 @@ -2802,6 +2832,64 @@ public struct BDouble: return base * (base ** (exponent - 1)) } + + public static func **(_ base: BDouble, _ exponent: BInt) -> BDouble + { + if exponent == 0 + { + return BDouble(1) + } + if exponent == 1 + { + return base + } + if exponent < 0 + { + return BDouble(1) / (base ** -exponent) + } + + return base * (base ** (exponent - 1)) + } + + /** + * - reference: http://rosettacode.org/wiki/Nth_root + */ + public static func **(_ base: BDouble, _ exponent: BDouble) -> BDouble + { + var count = base.precision + + // something over 1 + if BInt(limbs: exponent.denominator) == 1 { + return base**BInt(sign: exponent.sign, limbs: exponent.numerator) + } + + if BInt(limbs: exponent.numerator) != 1 { + return (base ** BInt(sign: exponent.sign, limbs: exponent.numerator)) ** BDouble(sign: false, numerator: BDouble(1).numerator, denominator: exponent.denominator) + } + + // we have 1/something + + var previous = BDouble(1) + var ans = previous + let exp = BInt(sign: exponent.sign, limbs: exponent.denominator) + let prec = BDouble(0.1) ** (abs(base.precision) + 1) + + while(true) { + previous = ans + + let rlhs = BDouble(BInt(1), over:exp) + let rrhs = ((exp-1)*ans + (base / pow(ans, exp-1))) + ans = rlhs * rrhs + + if abs(ans-previous) < prec { + break + } + + count = count + 1 + } + + return ans + } // // @@ -2825,6 +2913,7 @@ public struct BDouble: return res } public static func /(lhs: BDouble, rhs: Double) -> BDouble { return lhs / BDouble(rhs) } + public static func /(lhs: BDouble, rhs: BInt) -> BDouble { return lhs / BDouble(rhs) } public static func /(lhs: Double, rhs: BDouble) -> BDouble { return BDouble(lhs) / rhs } // @@ -2998,11 +3087,27 @@ public func ceil(_ base: BDouble) -> BInt /** * Returns a BDouble number raised to a given power. + * - warning: This may take a while */ public func pow(_ base : BDouble, _ exp : Int) -> BDouble { return base**exp } +/** + * Returns a BDouble number raised to a given power. + * - warning: This may take a while + */ +public func pow(_ base : BDouble, _ exp : BInt) -> BDouble { + return base**exp +} + +/** + * - warning: This may take a while. This is only precise up until precision. When comparing results after `pow` or `** ` use` nearlyEqual` + */ +public func pow(_ base : BDouble, _ exp : BDouble) -> BDouble { + return base**exp +} + /** * Returns the BDouble that is the smallest */ diff --git a/Swift-BigNumber.xcodeproj/project.pbxproj b/Swift-BigNumber.xcodeproj/project.pbxproj index 8676712..e8f1541 100644 --- a/Swift-BigNumber.xcodeproj/project.pbxproj +++ b/Swift-BigNumber.xcodeproj/project.pbxproj @@ -611,6 +611,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -634,6 +635,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -761,7 +763,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "$(SRCROOT)/Testing/Info.plist"; @@ -780,7 +782,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = ""; GCC_OPTIMIZATION_LEVEL = fast; @@ -864,7 +866,7 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = ""; @@ -886,7 +888,7 @@ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CODE_SIGN_IDENTITY = "Mac Developer"; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = ""; diff --git a/Tests/BDoubleTests.swift b/Tests/BDoubleTests.swift index eebc17e..d64eccb 100644 --- a/Tests/BDoubleTests.swift +++ b/Tests/BDoubleTests.swift @@ -79,6 +79,15 @@ class BDoubleTests : XCTestCase { } func testPow() { + XCTAssertEqual((BDouble("27")!**3), BDouble("19683")!) + XCTAssertEqual(pow(BDouble("27")!,BInt("3")!), BDouble("19683")!) + + XCTAssertEqual((BDouble("27")!**BInt("3")!), BDouble("19683")!) + XCTAssertEqual(pow(BDouble("27")!,BInt("3")!), BDouble("19683")!) + + XCTAssertTrue(BDouble.nearlyEqual(BDouble("-27")!**BDouble("1", over: "3")!, BDouble("-3")!)) + + XCTAssertTrue(BDouble.nearlyEqual(BDouble("4")!.nthroot(2), BDouble(2.0))) // Test that a number to the zero power is 1 for i in 0..<100 { XCTAssertEqual(pow(BDouble(Double(i)), 0), 1.0) @@ -453,5 +462,4 @@ class BDoubleTests : XCTestCase { } } } - }