Newer
Older
bremer-ios-app / Pods / RealmSwift / RealmSwift / Decimal128.swift
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2020 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

import Foundation
import Realm

/**
 A 128-bit IEEE 754-2008 decimal floating point number.

 This type is similar to Swift's built-in Decimal type, but allocates bits differently, resulting in a different representable range. (NS)Decimal stores a significand of up to 38 digits long and an exponent from -128 to 127, while this type stores up to 34 digits of significand and an exponent from -6143 to 6144.
 */
@objc(RealmSwiftDecimal128)
public final class Decimal128: RLMDecimal128, Decodable, @unchecked Sendable {
    /// Creates a new zero-initialized Decimal128.
    public override required init() {
        super.init()
    }

    /// Converts the given value to a Decimal128.
    ///
    /// The following types can be converted to Decimal128:
    /// - Int (of any size)
    /// - Float
    /// - Double
    /// - String
    /// - NSNumber
    /// - Decimal
    ///
    /// Passing a value with a type not in this list is a fatal error. Passing a string which cannot be parsed as a valid Decimal128 is a fatal error.
    ///
    /// - parameter value: The value to convert to a Decimal128.
    public override required init(value: Any) {
        super.init(value: value)
    }

    /// Converts the given number to a Decimal128.
    ///
    /// This initializer cannot fail and is never lossy.
    ///
    /// - parameter number: The number to convert to a Decimal128.
    public override required init(number: NSNumber) {
        super.init(number: number)
    }

    /// Parse the given string as a Decimal128.
    ///
    /// This initializer never throws and is marked as `throws` only because removing it is a breaking
    /// change. Strings which cannot be parsed as a Decimal128 return a value where `isNaN` is `true`.
    ///
    /// - parameter string: The string to parse.
    public override required init(string: String) throws {
        try super.init(string: string)
    }

    /// Creates a new Decimal128 by decoding from the given decoder.
    ///
    /// This initializer throws an error if the decoder is invalid or does not decode to a value which can be converted to Decimal128.
    ///
    /// - Parameter decoder: The decoder to read data from.
    public required init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let strValue = try? container.decode(String.self) {
            try super.init(string: strValue)
        } else if let intValue = try? container.decode(Int64.self) {
            super.init(number: intValue as NSNumber)
        } else if let doubleValue = try? container.decode(Double.self) {
            super.init(number: doubleValue as NSNumber)
        } else {
            throw DecodingError.dataCorruptedError(in: container, debugDescription: "Cannot convert value to Decimal128")
        }
    }

    /// The mininum value for Decimal128
    public static var min: Decimal128 {
        unsafeDowncast(__minimumDecimalNumber, to: Self.self)
    }

    /// The maximum value for Decimal128
    public static var max: Decimal128 {
        unsafeDowncast(__maximumDecimalNumber, to: Self.self)
    }
}

extension Decimal128: Encodable {
    /// Encodes this Decimal128 to the given encoder.
    ///
    /// This function throws an error if the given encoder is unable to encode a string.
    ///
    /// - Parameter encoder: The encoder to write data to.
    public func encode(to encoder: Encoder) throws {
        try self.stringValue.encode(to: encoder)
    }
}

extension Decimal128: ExpressibleByIntegerLiteral {
    /// Creates a new Decimal128 from the given integer literal.
    public convenience init(integerLiteral value: Int64) {
        self.init(number: value as NSNumber)
    }
}

extension Decimal128: ExpressibleByFloatLiteral {
    /// Creates a new Decimal128 from the given float literal.
    public convenience init(floatLiteral value: Double) {
        self.init(number: value as NSNumber)
    }
}

extension Decimal128: ExpressibleByStringLiteral {
    /// Creates a new Decimal128 from the given string literal.
    ///
    /// Aborts if the string cannot be parsed as a Decimal128.
    public convenience init(stringLiteral value: String) {
        try! self.init(string: value)
    }
}

extension Decimal128: Comparable {
    /// Returns a Boolean value indicating whether two decimal128 values are equal.
    ///
    /// - Parameters:
    ///   - lhs: A Decimal128 value to compare.
    ///   - rhs: Another Decimal128 value to compare.
    public static func == (lhs: Decimal128, rhs: Decimal128) -> Bool {
        lhs.isEqual(rhs)
    }

    /// Returns a Boolean value indicating whether the decimal128 value of the first
    /// argument is less than that of the second argument.
    ///
    /// - Parameters:
    ///   - lhs: A Decimal128 value to compare.
    ///   - rhs: Another Decimal128 value to compare.
    public static func < (lhs: Decimal128, rhs: Decimal128) -> Bool {
        lhs.isLessThan(rhs)
    }

    /// Returns a Boolean value indicating whether the decimal128 value of the first
    /// argument is less than or equal to that of the second argument.
    ///
    /// - Parameters:
    ///   - lhs: A Decimal128 value to compare.
    ///   - rhs: Another Decimal128 value to compare.
    public static func <= (lhs: Decimal128, rhs: Decimal128) -> Bool {
        lhs.isLessThanOrEqual(to: rhs)
    }

    /// Returns a Boolean value indicating whether the decimal128 value of the first
    /// argument is greater than or equal to that of the second argument.
    ///
    /// - Parameters:
    ///   - lhs: A Decimal128 value to compare.
    ///   - rhs: Another Decimal128 value to compare.
    public static func >= (lhs: Decimal128, rhs: Decimal128) -> Bool {
        lhs.isGreaterThanOrEqual(to: rhs)
    }

    /// Returns a Boolean value indicating whether the decimal128 value of the first
    /// argument is greater than that of the second argument.
    ///
    /// - Parameters:
    ///   - lhs: A Decimal128 value to compare.
    ///   - rhs: Another Decimal128 value to compare.
    public static func > (lhs: Decimal128, rhs: Decimal128) -> Bool {
        lhs.isGreaterThan(rhs)
    }
}

extension Decimal128: Numeric {
    /// Creates a new instance from the given integer, if it can be represented
    /// exactly.
    ///
    /// If the value passed as `source` is not representable exactly, the result
    /// is `nil`. In the following example, the constant `x` is successfully
    /// created from a value of `100`, while the attempt to initialize the
    /// constant `y` from `1_000` fails because the `Int8` type can represent
    /// `127` at maximum:
    ///
    /// - Parameter source: A value to convert to this type of integer.
    public convenience init?<T>(exactly source: T) where T: BinaryInteger {
        self.init(value: source)
    }

    /// A type that can represent the absolute value of Decimal128
    public typealias Magnitude = Decimal128

    /// The magnitude of this Decimal128.
    public var magnitude: Magnitude {
        unsafeDowncast(self.__magnitude, to: Magnitude.self)
    }

    /// Adds two decimal128 values and produces their sum.
    ///
    /// - Parameters:
    ///   - lhs: The first Decimal128 value to add.
    ///   - rhs: The second Decimal128 value to add.
    public static func + (lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
        unsafeDowncast(lhs.decimalNumber(byAdding: rhs), to: Decimal128.self)
    }

    /// Subtracts one Decimal128 value from another and produces their difference.
    ///
    /// - Parameters:
    ///   - lhs: A Decimal128 value.
    ///   - rhs: The Decimal128 value to subtract from `lhs`.
    public static func - (lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
        unsafeDowncast(lhs.decimalNumber(bySubtracting: rhs), to: Decimal128.self)
    }

    /// Multiplies two Decimal128 values and produces their product.
    ///
    /// - Parameters:
    ///   - lhs: The first value to multiply.
    ///   - rhs: The second value to multiply.
    public static func * (lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
        unsafeDowncast(lhs.decimalNumberByMultiplying(by: rhs), to: Decimal128.self)
    }

    /// Multiplies two values and stores the result in the left-hand-side
    /// variable.
    ///
    /// - Parameters:
    ///   - lhs: The first value to multiply.
    ///   - rhs: The second value to multiply.
    public static func *= (lhs: inout Decimal128, rhs: Decimal128) {
        lhs = lhs * rhs
    }

    /// Returns the quotient of dividing the first Decimal128 value by the second.
    ///
    /// - Parameters:
    ///   - lhs: The Decimal128 value to divide.
    ///   - rhs: The Decimal128 value to divide `lhs` by. `rhs` must not be zero.
    public static func / (lhs: Decimal128, rhs: Decimal128) -> Decimal128 {
        unsafeDowncast(lhs.decimalNumberByDividing(by: rhs), to: Decimal128.self)
    }
}

extension Decimal128 {
    /// A type that represents the distance between two values.
    public typealias Stride = Decimal128

    /// Returns the distance from this Decimal128 to the given value, expressed as a
    /// stride.
    ///
    /// - Parameter other: The Decimal128 value to calculate the distance to.
    /// - Returns: The distance from this value to `other`.
    public func distance(to other: Decimal128) -> Decimal128 {
        unsafeDowncast(other.decimalNumber(bySubtracting: self), to: Decimal128.self)
    }

    /// Returns a Decimal128 that is offset the specified distance from this value.
    ///
    /// Use the `advanced(by:)` method in generic code to offset a value by a
    /// specified distance. If you're working directly with numeric values, use
    /// the addition operator (`+`) instead of this method.
    ///
    /// - Parameter n: The distance to advance this Decimal128.
    /// - Returns: A Decimal128 that is offset from this value by `n`.
    public func advanced(by n: Decimal128) -> Decimal128 {
        unsafeDowncast(decimalNumber(byAdding: n), to: Decimal128.self)
    }
}

extension Decimal128 {
    /// `true` if `self` is a signaling NaN, `false` otherwise.
    public var isSignaling: Bool {
        self.isNaN
    }

    /// `true` if `self` is a signaling NaN, `false` otherwise.
    public var isSignalingNaN: Bool {
        self.isSignaling
    }
}