blob: 8af713e62a1ca5e2fa99ac2e7b5ce3ea7449b8f4 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@_exported import Foundation // Clang module
import _SwiftCoreFoundationOverlayShims
extension Decimal {
public typealias RoundingMode = NSDecimalNumber.RoundingMode
public typealias CalculationError = NSDecimalNumber.CalculationError
public static let leastFiniteMagnitude = Decimal(_exponent: 127, _length: 8, _isNegative: 1, _isCompact: 1, _reserved: 0, _mantissa: (0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff))
public static let greatestFiniteMagnitude = Decimal(_exponent: 127, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff))
public static let leastNormalMagnitude = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
public static let leastNonzeroMagnitude = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
public static let pi = Decimal(_exponent: -38, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x6623, 0x7d57, 0x16e7, 0xad0d, 0xaf52, 0x4641, 0xdfa7, 0xec58))
public var exponent: Int {
get {
return Int(_exponent)
}
}
public var significand: Decimal {
get {
return Decimal(_exponent: 0, _length: _length, _isNegative: _isNegative, _isCompact: _isCompact, _reserved: 0, _mantissa: _mantissa)
}
}
public init(sign: FloatingPointSign, exponent: Int, significand: Decimal) {
self.init(_exponent: Int32(exponent) + significand._exponent, _length: significand._length, _isNegative: sign == .plus ? 0 : 1, _isCompact: significand._isCompact, _reserved: 0, _mantissa: significand._mantissa)
}
public init(signOf: Decimal, magnitudeOf magnitude: Decimal) {
self.init(_exponent: magnitude._exponent, _length: magnitude._length, _isNegative: signOf._isNegative, _isCompact: magnitude._isCompact, _reserved: 0, _mantissa: magnitude._mantissa)
}
public var sign: FloatingPointSign {
return _isNegative == 0 ? FloatingPointSign.plus : FloatingPointSign.minus
}
public static var radix: Int { return 10 }
public var ulp: Decimal {
if !self.isFinite { return Decimal.nan }
return Decimal(_exponent: _exponent, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
}
@available(*, unavailable, message: "Decimal does not yet fully adopt FloatingPoint.")
public mutating func formTruncatingRemainder(dividingBy other: Decimal) { fatalError("Decimal does not yet fully adopt FloatingPoint") }
public mutating func negate() {
_isNegative = _isNegative == 0 ? 1 : 0
}
public func isEqual(to other: Decimal) -> Bool {
var lhs = self
var rhs = other
return NSDecimalCompare(&lhs, &rhs) == .orderedSame
}
public func isLess(than other: Decimal) -> Bool {
var lhs = self
var rhs = other
return NSDecimalCompare(&lhs, &rhs) == .orderedAscending
}
public func isLessThanOrEqualTo(_ other: Decimal) -> Bool {
var lhs = self
var rhs = other
let order = NSDecimalCompare(&lhs, &rhs)
return order == .orderedAscending || order == .orderedSame
}
public func isTotallyOrdered(belowOrEqualTo other: Decimal) -> Bool {
// Notes: Decimal does not have -0 or infinities to worry about
if self.isNaN {
return false
} else if self < other {
return true
} else if other < self {
return false
}
// fall through to == behavior
return true
}
public var isCanonical: Bool {
return true
}
public var nextUp: Decimal {
return self + Decimal(_exponent: _exponent, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
}
public var nextDown: Decimal {
return self - Decimal(_exponent: _exponent, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
}
public static func +(lhs: Decimal, rhs: Decimal) -> Decimal {
var res = Decimal()
var leftOp = lhs
var rightOp = rhs
NSDecimalAdd(&res, &leftOp, &rightOp, .plain)
return res
}
public static func -(lhs: Decimal, rhs: Decimal) -> Decimal {
var res = Decimal()
var leftOp = lhs
var rightOp = rhs
NSDecimalSubtract(&res, &leftOp, &rightOp, .plain)
return res
}
public static func /(lhs: Decimal, rhs: Decimal) -> Decimal {
var res = Decimal()
var leftOp = lhs
var rightOp = rhs
NSDecimalDivide(&res, &leftOp, &rightOp, .plain)
return res
}
public static func *(lhs: Decimal, rhs: Decimal) -> Decimal {
var res = Decimal()
var leftOp = lhs
var rightOp = rhs
NSDecimalMultiply(&res, &leftOp, &rightOp, .plain)
return res
}
}
public func pow(_ x: Decimal, _ y: Int) -> Decimal {
var res = Decimal()
var num = x
NSDecimalPower(&res, &num, y, .plain)
return res
}
extension Decimal : Hashable, Comparable {
internal var doubleValue : Double {
var d = 0.0
if _length == 0 && _isNegative == 0 {
return Double.nan
}
d = d * 65536 + Double(_mantissa.7)
d = d * 65536 + Double(_mantissa.6)
d = d * 65536 + Double(_mantissa.5)
d = d * 65536 + Double(_mantissa.4)
d = d * 65536 + Double(_mantissa.3)
d = d * 65536 + Double(_mantissa.2)
d = d * 65536 + Double(_mantissa.1)
d = d * 65536 + Double(_mantissa.0)
if _exponent < 0 {
for _ in _exponent..<0 {
d /= 10.0
}
} else {
for _ in 0..<_exponent {
d *= 10.0
}
}
return _isNegative != 0 ? -d : d
}
public var hashValue: Int {
return Int(bitPattern: __CFHashDouble(doubleValue))
}
public static func ==(lhs: Decimal, rhs: Decimal) -> Bool {
var lhsVal = lhs
var rhsVal = rhs
return NSDecimalCompare(&lhsVal, &rhsVal) == .orderedSame
}
public static func <(lhs: Decimal, rhs: Decimal) -> Bool {
var lhsVal = lhs
var rhsVal = rhs
return NSDecimalCompare(&lhsVal, &rhsVal) == .orderedAscending
}
}
extension Decimal : ExpressibleByFloatLiteral {
public init(floatLiteral value: Double) {
self.init(value)
}
}
extension Decimal : ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) {
self.init(value)
}
}
extension Decimal : SignedNumeric {
public var magnitude: Decimal {
return Decimal(
_exponent: self._exponent, _length: self._length,
_isNegative: 0, _isCompact: self._isCompact,
_reserved: 0, _mantissa: self._mantissa)
}
// FIXME(integers): implement properly
public init?<T : BinaryInteger>(exactly source: T) {
fatalError()
}
public static func +=(_ lhs: inout Decimal, _ rhs: Decimal) {
var rhs = rhs
_ = withUnsafeMutablePointer(to: &lhs) {
NSDecimalAdd($0, $0, &rhs, .plain)
}
}
public static func -=(_ lhs: inout Decimal, _ rhs: Decimal) {
var rhs = rhs
_ = withUnsafeMutablePointer(to: &lhs) {
NSDecimalSubtract($0, $0, &rhs, .plain)
}
}
public static func *=(_ lhs: inout Decimal, _ rhs: Decimal) {
var rhs = rhs
_ = withUnsafeMutablePointer(to: &lhs) {
NSDecimalMultiply($0, $0, &rhs, .plain)
}
}
public static func /=(_ lhs: inout Decimal, _ rhs: Decimal) {
var rhs = rhs
_ = withUnsafeMutablePointer(to: &lhs) {
NSDecimalDivide($0, $0, &rhs, .plain)
}
}
}
extension Decimal {
@available(swift, obsoleted: 4, message: "Please use arithmetic operators instead")
@_transparent
public mutating func add(_ other: Decimal) {
self += other
}
@available(swift, obsoleted: 4, message: "Please use arithmetic operators instead")
@_transparent
public mutating func subtract(_ other: Decimal) {
self -= other
}
@available(swift, obsoleted: 4, message: "Please use arithmetic operators instead")
@_transparent
public mutating func multiply(by other: Decimal) {
self *= other
}
@available(swift, obsoleted: 4, message: "Please use arithmetic operators instead")
@_transparent
public mutating func divide(by other: Decimal) {
self /= other
}
}
extension Decimal : Strideable {
public func distance(to other: Decimal) -> Decimal {
return self - other
}
public func advanced(by n: Decimal) -> Decimal {
return self + n
}
}
extension Decimal {
public init(_ value: UInt8) {
self.init(UInt64(value))
}
public init(_ value: Int8) {
self.init(Int64(value))
}
public init(_ value: UInt16) {
self.init(UInt64(value))
}
public init(_ value: Int16) {
self.init(Int64(value))
}
public init(_ value: UInt32) {
self.init(UInt64(value))
}
public init(_ value: Int32) {
self.init(Int64(value))
}
public init(_ value: Double) {
if value.isNaN {
self = Decimal.nan
} else if value == 0.0 {
self = Decimal(_exponent: 0, _length: 0, _isNegative: 0, _isCompact: 0, _reserved: 0, _mantissa: (0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
} else {
self.init() // zero-initialize everything
let negative = value < 0
var val = negative ? -1 * value : value
var exponent = 0
while val < Double(UInt64.max - 1) {
val *= 10.0
exponent -= 1
}
while Double(UInt64.max - 1) < val {
val /= 10.0
exponent += 1
}
var mantissa = UInt64(val)
var i = UInt32(0)
// this is a bit ugly but it is the closest approximation of the C initializer that can be expressed here.
while mantissa != 0 && i < 8 /* NSDecimalMaxSize */ {
switch i {
case 0:
_mantissa.0 = UInt16(mantissa & 0xffff)
case 1:
_mantissa.1 = UInt16(mantissa & 0xffff)
case 2:
_mantissa.2 = UInt16(mantissa & 0xffff)
case 3:
_mantissa.3 = UInt16(mantissa & 0xffff)
case 4:
_mantissa.4 = UInt16(mantissa & 0xffff)
case 5:
_mantissa.5 = UInt16(mantissa & 0xffff)
case 6:
_mantissa.6 = UInt16(mantissa & 0xffff)
case 7:
_mantissa.7 = UInt16(mantissa & 0xffff)
default:
fatalError("initialization overflow")
}
mantissa = mantissa >> 16
i += 1
}
_length = i
_isNegative = negative ? 1 : 0
_isCompact = 0
_exponent = Int32(exponent)
NSDecimalCompact(&self)
}
}
public init(_ value: UInt64) {
self.init(Double(value))
}
public init(_ value: Int64) {
self.init(Double(value))
}
public init(_ value: UInt) {
self.init(UInt64(value))
}
public init(_ value: Int) {
self.init(Int64(value))
}
@available(*, unavailable, message: "Decimal does not yet fully adopt FloatingPoint.")
public static var infinity: Decimal { fatalError("Decimal does not yet fully adopt FloatingPoint") }
@available(*, unavailable, message: "Decimal does not yet fully adopt FloatingPoint.")
public static var signalingNaN: Decimal { fatalError("Decimal does not yet fully adopt FloatingPoint") }
public var isSignalingNaN: Bool {
return false
}
public static var nan: Decimal {
return quietNaN
}
public static var quietNaN: Decimal {
return Decimal(_exponent: 0, _length: 0, _isNegative: 1, _isCompact: 0, _reserved: 0, _mantissa: (0, 0, 0, 0, 0, 0, 0, 0))
}
/// The IEEE 754 "class" of this type.
public var floatingPointClass: FloatingPointClassification {
if _length == 0 && _isNegative == 1 {
return .quietNaN
} else if _length == 0 {
return .positiveZero
}
// NSDecimal does not really represent normal and subnormal in the same manner as the IEEE standard, for now we can probably claim normal for any nonzero, nonnan values
if _isNegative == 1 {
return .negativeNormal
} else {
return .positiveNormal
}
}
/// `true` iff `self` is negative.
public var isSignMinus: Bool { return _isNegative != 0 }
/// `true` iff `self` is normal (not zero, subnormal, infinity, or
/// NaN).
public var isNormal: Bool { return !isZero && !isInfinite && !isNaN }
/// `true` iff `self` is zero, subnormal, or normal (not infinity
/// or NaN).
public var isFinite: Bool { return !isNaN }
/// `true` iff `self` is +0.0 or -0.0.
public var isZero: Bool { return _length == 0 && _isNegative == 0 }
/// `true` iff `self` is subnormal.
public var isSubnormal: Bool { return false }
/// `true` iff `self` is infinity.
public var isInfinite: Bool { return false }
/// `true` iff `self` is NaN.
public var isNaN: Bool { return _length == 0 && _isNegative == 1 }
/// `true` iff `self` is a signaling NaN.
public var isSignaling: Bool { return false }
}
extension Decimal : CustomStringConvertible {
public init?(string: String, locale: Locale? = nil) {
let scan = Scanner(string: string)
var theDecimal = Decimal()
scan.locale = locale
if !scan.scanDecimal(&theDecimal) {
return nil
}
self = theDecimal
}
public var description: String {
var val = self
return NSDecimalString(&val, nil)
}
}
extension Decimal : _ObjectiveCBridgeable {
@_semantics("convertToObjectiveC")
public func _bridgeToObjectiveC() -> NSDecimalNumber {
return NSDecimalNumber(decimal: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSDecimalNumber, result: inout Decimal?) {
if !_conditionallyBridgeFromObjectiveC(x, result: &result) {
fatalError("Unable to bridge \(_ObjectiveCType.self) to \(self)")
}
}
public static func _conditionallyBridgeFromObjectiveC(_ input: NSDecimalNumber, result: inout Decimal?) -> Bool {
result = input.decimalValue
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSDecimalNumber?) -> Decimal {
guard let src = source else { return Decimal(_exponent: 0, _length: 0, _isNegative: 0, _isCompact: 0, _reserved: 0, _mantissa: (0, 0, 0, 0, 0, 0, 0, 0)) }
return src.decimalValue
}
}
extension Decimal : Codable {
private enum CodingKeys : Int, CodingKey {
case exponent
case length
case isNegative
case isCompact
case mantissa
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let exponent = try container.decode(CInt.self, forKey: .exponent)
let length = try container.decode(CUnsignedInt.self, forKey: .length)
let isNegative = try container.decode(Bool.self, forKey: .isNegative)
let isCompact = try container.decode(Bool.self, forKey: .isCompact)
var mantissaContainer = try container.nestedUnkeyedContainer(forKey: .mantissa)
var mantissa: (CUnsignedShort, CUnsignedShort, CUnsignedShort, CUnsignedShort,
CUnsignedShort, CUnsignedShort, CUnsignedShort, CUnsignedShort) = (0,0,0,0,0,0,0,0)
mantissa.0 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.1 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.2 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.3 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.4 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.5 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.6 = try mantissaContainer.decode(CUnsignedShort.self)
mantissa.7 = try mantissaContainer.decode(CUnsignedShort.self)
self = Decimal(_exponent: exponent,
_length: length,
_isNegative: CUnsignedInt(isNegative ? 1 : 0),
_isCompact: CUnsignedInt(isCompact ? 1 : 0),
_reserved: 0,
_mantissa: mantissa)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(_exponent, forKey: .exponent)
try container.encode(_length, forKey: .length)
try container.encode(_isNegative == 0 ? false : true, forKey: .isNegative)
try container.encode(_isCompact == 0 ? false : true, forKey: .isCompact)
var mantissaContainer = container.nestedUnkeyedContainer(forKey: .mantissa)
try mantissaContainer.encode(_mantissa.0)
try mantissaContainer.encode(_mantissa.1)
try mantissaContainer.encode(_mantissa.2)
try mantissaContainer.encode(_mantissa.3)
try mantissaContainer.encode(_mantissa.4)
try mantissaContainer.encode(_mantissa.5)
try mantissaContainer.encode(_mantissa.6)
try mantissaContainer.encode(_mantissa.7)
}
}