diff --git a/Package.swift b/Package.swift index c400cac..b3bb142 100644 --- a/Package.swift +++ b/Package.swift @@ -5,10 +5,10 @@ import PackageDescription let package = Package( name: "BigDecimal", - platforms: [ - .macOS("13.3"), .iOS("16.4"), .macCatalyst(.v16), .tvOS("16.4"), - .watchOS("9.4") - ], +// platforms: [ +// .macOS("13.3"), .iOS("16.4"), .macCatalyst(.v16), .tvOS("16.4"), +// .watchOS("9.4") +// ], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. .library( diff --git a/Sources/BigDecimal/BigDecimal.swift b/Sources/BigDecimal/BigDecimal.swift index 644045c..0cd17a6 100644 --- a/Sources/BigDecimal/BigDecimal.swift +++ b/Sources/BigDecimal/BigDecimal.swift @@ -249,9 +249,12 @@ extension BigDecimal : Strideable { } extension BigDecimal : ExpressibleByIntegerLiteral { - public init(integerLiteral value: StaticBigInt) { - let bint = BInt(integerLiteral: value) - self = Self(bint) +// public init(integerLiteral value: StaticBigInt) { +// let bint = BInt(integerLiteral: value) +// self = Self(bint) +// } + public init(integerLiteral value: Int) { + self.init(value) } } @@ -739,7 +742,7 @@ extension BigDecimal { public func asDecimal() -> Decimal { let maxExp = 127 let minExp = -128 - let maxDec = Self(BInt(0xffffffff_ffffffff_ffffffff_ffffffff), maxExp) + let maxDec = Self(BInt("ffffffffffffffffffffffffffffffff", radix:16)!, maxExp) if self.isNaN || self.abs > maxDec { return Decimal.nan diff --git a/Sources/BigDecimal/Decimal128.swift b/Sources/BigDecimal/Decimal128.swift index 90bee48..286790f 100644 --- a/Sources/BigDecimal/Decimal128.swift +++ b/Sources/BigDecimal/Decimal128.swift @@ -28,8 +28,7 @@ import BigInt /// the operation, and convert back to Decimal128 format. public struct Decimal128 : DecimalType, Codable, Hashable { // Decimal64 characteristics - static let largestNumber = - UInt128(9_999_999_999_999_999_999_999_999_999_999_999) + static let largestNumber = UInt128("9999999999999999999999999999999999")! static let exponentBias = 6176 static let maxExponent = 6111 static let exponentBits = 14 diff --git a/Sources/BigDecimal/DecimalFloatingPoint.swift b/Sources/BigDecimal/DecimalFloatingPoint.swift index c446387..b58ee62 100644 --- a/Sources/BigDecimal/DecimalFloatingPoint.swift +++ b/Sources/BigDecimal/DecimalFloatingPoint.swift @@ -348,6 +348,7 @@ extension DecimalType { while exp < 0 { exp += 1; sig /= 10 } + if sig > Self.largestNumber { sig = 0 } self.init(sign: sign, exponentBitPattern: exp, significandBitPattern: sig) } diff --git a/Sources/BigDecimal/DecimalMath.swift b/Sources/BigDecimal/DecimalMath.swift index 3a76dfc..9421818 100644 --- a/Sources/BigDecimal/DecimalMath.swift +++ b/Sources/BigDecimal/DecimalMath.swift @@ -45,12 +45,14 @@ public extension BigDecimal { } /** - * Returns whether the specified `BigDecimal` value can be represented as int. + * Returns whether the specified ``BigDecimal`` value can be represented as + * an `Int`. * - * If this returns true you can call {@link BigDecimal#intValueExact()} without fear of an {@link ArithmeticException}.

+ * If this returns `true` you can call ``asInt()` + * without fear of an `ArithmeticException`. * - * @param value the `BigDecimal` to check - * @return true if the value can be represented as int value + * - Parameter value the ``BigDecimal`` to check + * - Returns: `true` if the value can be represented as `Int` value */ static func isIntValue(_ value:Self) -> Bool { if value > BigDecimal(Int.max) { @@ -63,26 +65,29 @@ public extension BigDecimal { } /** - * Returns whether the specified `BigDecimal` value can be represented as double. + * Returns whether the specified ``BigDecimal`` value can be represented + * as `Double`. * - * If this returns true you can call {@link BigDecimal#doubleValue()} - * without fear of getting {@link Double#POSITIVE_INFINITY} or {@link Double#NEGATIVE_INFINITY} as result.

+ * If this returns `true` you can call ``asDouble()`` + * without fear of getting ``infinity`` or -``infinity`` as result. * - * Example: BigDecimalMath.isDoubleValue(new BigDecimal("1E309")) returns false, - * because new BigDecimal("1E309").doubleValue() returns Infinity.

+ * Example: `BigDecimal.isDoubleValue(BigDecimal("1E309"))` returns `false`, + * because `BigDecimal("1E309").asDouble()` returns ``infinity``. * - * Note: This method does not check for possible loss of precision.

+ * Note: This method does **not** check for possible loss of precision. * - * For example BigDecimalMath.isDoubleValue(new BigDecimal("1.23400000000000000000000000000000001")) will return true, - * because new BigDecimal("1.23400000000000000000000000000000001").doubleValue() returns a valid double value, - * although it loses precision and returns 1.234.

+ * For example `BigDecimalMath.isDoubleValue(BigDecimal("1.23400000000000000000000000000000001"))` will return `true`, + * because `BigDecimal("1.23400000000000000000000000000000001").asDouble()` returns a valid double value, + * although it loses precision and returns `1.234`. * - * BigDecimalMath.isDoubleValue(new BigDecimal("1E-325")) will return true - * although this value is smaller than {@link Double#MIN_VALUE} (and therefore outside the range of values that can be represented as double) - * because new BigDecimal("1E-325").doubleValue() returns 0 which is a legal value with loss of precision.

+ * `BigDecimalMath.isDoubleValue(BigDecimal("1E-325"))` will return `true` + * although this value is smaller than -`Double.greatestFiniteMagnitude` + * (and therefore outside the range of values that can be represented as `Double`) + * because `BigDecimal("1E-325").asDouble()` returns `0` which is a legal + * value with loss of precision. * - * @param value the `BigDecimal` to check - * @return true if the value can be represented as double value + * - Parameter value: ``BigDecimal`` number to check + * - Returns: `true` if the `value` can be represented as `Double` value */ static func isDoubleValue(_ value:Self) -> Bool { if value > doubleMax { @@ -95,38 +100,41 @@ public extension BigDecimal { } /** - * Returns the integral part of the specified `BigDecimal` (left of the decimal point). + * Returns the integral part of the specified ``BigDecimal`` (left of + * the decimal point). See ``fractionalPart(_:)``. * - * @param value the `BigDecimal` - * @return the integral part - * @see #fractionalPart(BigDecimal) + * - Parameter value: the ``BigDecimal`` + * - Returns: the integral part */ static func integralPart(_ value:Self) -> Self { - return value.withExponent(0, .down) // setScale(0, Rou ROUND_DOWN); + return value.withExponent(0, .down) } /** - * Returns the fractional part of the specified `BigDecimal` (right of the decimal point). + * Returns the fractional part of the specified `BigDecimal` (right of + * the decimal point). See ``integralPart(_:)``. * - * @param value the `BigDecimal` - * @return the fractional part - * @see #integralPart(BigDecimal) + * - Parameter value: the ``BigDecimal`` + * - Returns: the fractional part */ static func fractionalPart(_ value:Self) -> Self { - return value - integralPart(value) // subtract(integralPart(value), Rounding(.HALF_EVEN, 0)) + return value - integralPart(value) } /** * Calculates the square root of ``BigDecimal`` `x`. * - * See Wikipedia: Square root. http://en.wikipedia.org/wiki/Square_root. + * See Wikipedia: [Square root][lsqrt] + * + * [lsqrt]: https://en.wikipedia.org/wiki/Square_root + * * - Parameters: * - x: The ``BigDecimal`` value to calculate the square root * - mc: The ``Rounding`` used for the result * - Returns: The calculated square root of `x` with the precision specified * in the `mc` - * */ - static func sqrt(_ x: BigDecimal, _ mc: Rounding) -> BigDecimal { + */ + static func sqrt(_ x: Self, _ mc: Rounding) -> Self { guard x.signum >= 0 else { return BigDecimal.nan } if x.isZero { return zero } @@ -170,13 +178,18 @@ public extension BigDecimal { /** * Calculates the n'th root of ``BigDecimal`` `x`. * - * See Wikipedia: Nth root -> https://en.wikipedia.org/wiki/Nth_root + * See Wikipedia: [Nth root][nsqrt]. + * + * [nsqrt]: https://en.wikipedia.org/wiki/Nth_root + * * - Parameters: - * - x: the `BigDecimal` value to calculate the n'th root - * - n: the `BigDecimal` defining the root - * - mc: the {@link MathContext} used for the result - * - Returns: The calculated n'th root of x with the precision specified in the mathContext - **/ + * - x: the `BigDecimal` value to calculate the n'th root + * - n: the `BigDecimal` defining the root + * - mc: the `Rounding` context used for the result + * - Returns: The calculated n'th root of x with the precision + * specified in the mathContext + * + */ static func root(_ x:Self, _ n:Self, _ mc:Rounding) -> Self { precondition(n.signum > 0, "Illegal root(x, n) for n <= 0: n = \(n)") precondition(x.signum >= 0, "Illegal root(x, n) for x < 0: x = \(x)") @@ -227,14 +240,14 @@ public extension BigDecimal { } /** - * Calculates `BigDecimal` x to the power of `BigDecimal` y (xy). - * - * @param x the `BigDecimal` value to take to the power - * @param y the `BigDecimal` value to serve as exponent - * @param mathContext the {@link MathContext} used for the result - * @return the calculated x to the power of y with the precision specified in the mathContext - * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision - * @see #pow(BigDecimal, long, MathContext) + * Calculates ``BigDecimal`` x to the power of ``BigDecimal`` y (x^y). + * + * - Parameters: + * - x: The `BigDecimal` value to take to the power + * - y: The `BigDecimal` value to serve as exponent + * - mc: The ``Rounding`` context used for the result + * - Returns: The calculated x to the power of y with the precision + * specified in the `mc` ``Rounding`` context. */ static func pow(_ x:Self, _ y:Self, _ mc:Rounding) -> Self { // checkMathContext(mathContext); @@ -260,15 +273,18 @@ public extension BigDecimal { } /** - * Calculates `BigDecimal` x to the power of the integer value y (xy). + * Calculates ``BigDecimal`` x to the power of the integer value y (xʸ). + * + * See ``pow(_:_:_:)``. * - * The value y MUST be an integer value.

+ * The value y **MUST** be an integer value. * - * @param x the `BigDecimal` value to take to the power - * @param integerY the `BigDecimal` integer value to serve as exponent - * @param mathContext the {@link MathContext} used for the result - * @return the calculated x to the power of y with the precision specified in the mathContext - * @see #pow(BigDecimal, long, MathContext) + * - Parameters: + * - x: The ``BigDecimal`` value to take to the power + * - integerY: The ``BigDecimal`` **integer** value to serve as exponent + * - mc: the ``Rounding`` context used for the result + * - Returns: The calculated x to the power of y with the precision + * specified in the `mc`. */ private static func powInteger(_ x:Self, _ integerY:Self, _ mc:Rounding) -> Self { var integerY = integerY @@ -308,16 +324,16 @@ public extension BigDecimal { } /** - * Returns the number pi. + * Returns the number pi (π). + * + * See [Wikipedia: Pi][piref]. * - * See Wikipedia: Pi

+ * [piref]: https://en.wikipedia.org/wiki/Pi * - * @param mathContext the {@link MathContext} used for the result - * @return the number pi with the precision specified in the mathContext - * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision - **/ + * - Parameter mc: The ``Rounding`` context used for the result. + * - Returns: The number π with the precision specified in the `mc`. + */ static func pi(_ mc: Rounding) -> Self { - //checkMathContext(mathContext); let result: Self? if let pi = piCache, mc.precision <= pi.precision { @@ -375,14 +391,17 @@ public extension BigDecimal { } /** - * Calculates the natural exponent of `BigDecimal` x (ex). + * Calculates the natural exponent of ``BigDecimal`` x (eˣ). * - * See: Wikipedia: Exponent

+ * See: [Wikipedia: Exponential Function][exp]. * - * @param x the `BigDecimal` to calculate the exponent for - * @param mathContext the {@link MathContext} used for the result - * @return the calculated exponent `BigDecimal` with the precision specified in the mathContext - * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision + * [exp]: https://en.wikipedia.org/wiki/Exponential_function + * + * - Parameters: + * - x: The ``BigDecimal`` to calculate the exponent for + * - mc: The ``Rounding`` ontextt used for the result + * - Returns: The calculated exponent ``BigDecimal`` with the precision + * specified in the `mc`. */ static func exp(_ x:Self, _ mc: Rounding) -> Self { // checkMathContext(mathContext); @@ -427,17 +446,19 @@ public extension BigDecimal { } /** - * Calculates the natural logarithm of `BigDecimal` `x`. + * Calculates the natural logarithm of ``BigDecimal`` `x`. + * + * See: [Wikipedia: Natural logarithm][REF]. * - * See: [Wikipedia: Natural logarithm][REF] * [REF]: http://en.wikipedia.org/wiki/Natural_logarithm * - * @param x the `BigDecimal` to calculate the natural logarithm for - * @param mathContext the {@link MathContext} used for the result - * @return the calculated natural logarithm `BigDecimal` with the precision specified in the mathContext + * - Parameters: + * - x: The ``BigDecimal`` to calculate the natural logarithm for + * - mc: The ``Rounding`` context used for the result + * - Returns: The calculated natural logarithm ``BigDecimal`` with the + * precision specified in the `mc`. */ static func log(_ x:Self, _ mc:Rounding) -> Self { - // checkMathContext(mathContext); precondition(x.signum <= 0, "Illegal log(x) for x <= 0: x = \(x)") if x == one { return zero @@ -451,16 +472,15 @@ public extension BigDecimal { } /** - * Calculates the logarithm of `BigDecimal` x to the base 2. + * Calculates the logarithm of ``BigDecimal`` x to the base 2. * - * @param x the `BigDecimal` to calculate the logarithm base 2 for - * @param mathContext the {@link MathContext} used for the result - * @return the calculated natural logarithm `BigDecimal` to the base 2 with the precision specified in the mathContext - * @throws ArithmeticException if x <= 0 - * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision + * - Parameters: + * - x: The ``BigDecimal`` to calculate the logarithm base 2 for. + * - mc: The ``Rounding`` context used for the result. + * - Returns: The calculated natural logarithm ``BigDecimal`` to the + * base 2 with the precision specified in the `mc`. */ static func log2(_ x:Self, _ mc:Rounding) -> Self { - //checkMathContext(mathContext); let mc2 = Rounding(mc.mode, mc.precision + 4) let result = log(x, mc2).divide(logTwo(mc2), mc2) @@ -468,16 +488,15 @@ public extension BigDecimal { } /** - * Calculates the logarithm of `BigDecimal` x to the base 10. + * Calculates the logarithm of ``BigDecimal`` x to the base 10. * - * @param x the `BigDecimal` to calculate the logarithm base 10 for - * @param mathContext the {@link MathContext} used for the result - * @return the calculated natural logarithm `BigDecimal` to the base 10 with the precision specified in the mathContext - * @throws ArithmeticException if x <= 0 - * @throws UnsupportedOperationException if the {@link MathContext} has unlimited precision + * - Parameters: + * - x: The ``BigDecimal`` to calculate the logarithm base 10 for. + * - mc: The ``Rounding`` context used for the result. + * - Returns: The calculated natural logarithm ``BigDecimal`` to the + * base 10 with the precision specified in the `mc`. */ static func log10(_ x:Self, _ mc:Rounding) -> Self { - //heckMathContext(mathContext); let mc2 = Rounding(mc.mode, mc.precision + 2) let result = log(x, mc2).divide(logTen(mc2), mc2) diff --git a/Tests/BigDecimalTests/Decimal32Tests.swift b/Tests/BigDecimalTests/Decimal32Tests.swift index 4e8e3d7..88b2a0a 100644 --- a/Tests/BigDecimalTests/Decimal32Tests.swift +++ b/Tests/BigDecimalTests/Decimal32Tests.swift @@ -5078,8 +5078,7 @@ final class Decimal32Tests: XCTestCase { func checkValues(_ test: TestCase, _ x: UInt128, _ s: Status, _ msg: String) { - let pass1 = test.reshi == x >> 64 && test.reslo == x & - UInt128(0xFFFFFFFF_FFFFFFFF) + let pass1 = test.reshi == x >> 64 && test.reslo == x & UInt128.max let pass2 = true // test.status == s XCTAssert(pass1, "Expected: " + msg) XCTAssert(pass2, "[\(test.status)] != [\(s)]") @@ -5130,8 +5129,8 @@ final class Decimal32Tests: XCTestCase { if testID == 70 { print(getNumber(test.istr)) } - let t1 = getNumber(test.istr) - let t1f = Float(t1, round: test.roundMode) + let t1 = getNumber(test.istr) + let t1f = Float(t1, round: test.roundMode) let d1 = Float(bitPattern: UInt32(test.res)) let error = "\(d1) != \(t1f)" checkValues(test, UInt64(t1f.bitPattern), state, error)