blob: 72f33f472f1d5e3df45931242ccf27c1e5a4c045 [file] [log] [blame]
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
import Foundation
import XCTest
#else
import SwiftFoundation
import SwiftXCTest
#endif
class TestNSDecimal: XCTestCase {
static var allTests : [(String, (TestNSDecimal) -> () throws -> Void)] {
return [
("test_BasicConstruction", test_BasicConstruction),
("test_Constants", test_Constants),
("test_Description", test_Description),
("test_ExplicitConstruction", test_ExplicitConstruction),
("test_Maths", test_Maths),
("test_Misc", test_Misc),
("test_Normalise", test_Normalise),
("test_Round", test_Round),
("test_NSDecimal", test_NSDecimal),
]
}
func test_BasicConstruction() {
let zero = Decimal()
XCTAssertEqual(20, MemoryLayout<Decimal>.size)
XCTAssertEqual(0, zero._exponent)
XCTAssertEqual(0, zero._length)
XCTAssertEqual(0, zero._isNegative)
XCTAssertEqual(0, zero._isCompact)
XCTAssertEqual(0, zero._reserved)
let (m0,m1,m2,m3,m4,m5,m6,m7) = zero._mantissa
XCTAssertEqual(0, m0)
XCTAssertEqual(0, m1)
XCTAssertEqual(0, m2)
XCTAssertEqual(0, m3)
XCTAssertEqual(0, m4)
XCTAssertEqual(0, m5)
XCTAssertEqual(0, m6)
XCTAssertEqual(0, m7)
XCTAssertEqual(8, NSDecimalMaxSize)
XCTAssertEqual(32767, NSDecimalNoScale)
XCTAssertFalse(zero.isNormal)
XCTAssertTrue(zero.isFinite)
XCTAssertTrue(zero.isZero)
XCTAssertFalse(zero.isSubnormal)
XCTAssertFalse(zero.isInfinite)
XCTAssertFalse(zero.isNaN)
XCTAssertFalse(zero.isSignaling)
}
func test_Constants() {
XCTAssertEqual(8,NSDecimalMaxSize)
XCTAssertEqual(32767,NSDecimalNoScale)
let smallest = Decimal(_exponent: 127, _length: 8, _isNegative: 1, _isCompact: 1, _reserved: 0, _mantissa: (UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max))
XCTAssertEqual(smallest, Decimal.leastFiniteMagnitude)
let biggest = Decimal(_exponent: 127, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max, UInt16.max))
XCTAssertEqual(biggest, Decimal.greatestFiniteMagnitude)
let leastNormal = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1,0,0,0,0,0,0,0))
XCTAssertEqual(leastNormal, Decimal.leastNormalMagnitude)
let leastNonzero = Decimal(_exponent: -127, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1,0,0,0,0,0,0,0))
XCTAssertEqual(leastNonzero, Decimal.leastNonzeroMagnitude)
let pi = Decimal(_exponent: -38, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x6623, 0x7d57, 0x16e7, 0xad0d, 0xaf52, 0x4641, 0xdfa7, 0xec58))
XCTAssertEqual(pi,Decimal.pi)
XCTAssertEqual(10,Decimal.radix)
XCTAssertTrue(Decimal().isCanonical)
XCTAssertFalse(Decimal().isSignalingNaN)
XCTAssertFalse(Decimal.nan.isSignalingNaN)
XCTAssertTrue(Decimal.nan.isNaN)
XCTAssertEqual(.quietNaN,Decimal.nan.floatingPointClass)
XCTAssertEqual(.positiveZero,Decimal().floatingPointClass)
XCTAssertEqual(.negativeNormal,smallest.floatingPointClass)
XCTAssertEqual(.positiveNormal,biggest.floatingPointClass)
XCTAssertFalse(Double.nan.isFinite)
XCTAssertFalse(Double.nan.isInfinite)
}
func test_Description() {
XCTAssertEqual("0",Decimal().description)
XCTAssertEqual("0",Decimal(0).description)
XCTAssertEqual("10",Decimal(_exponent: 1, _length: 1, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (1,0,0,0,0,0,0,0)).description)
XCTAssertEqual("10",Decimal(10).description)
XCTAssertEqual("123.458",Decimal(_exponent: -3, _length: 2, _isNegative: 0, _isCompact:1, _reserved: 0, _mantissa: (57922,1,0,0,0,0,0,0)).description)
XCTAssertEqual("123.458",Decimal(123.458).description)
XCTAssertEqual("123",Decimal(UInt8(123)).description)
XCTAssertEqual("45",Decimal(Int8(45)).description)
XCTAssertEqual("3.14159265358979323846264338327950288419",Decimal.pi.description)
XCTAssertEqual("-30000000000",Decimal(sign: .minus, exponent: 10, significand: Decimal(3)).description)
XCTAssertEqual("300000",Decimal(sign: .plus, exponent: 5, significand: Decimal(3)).description)
XCTAssertEqual("5",Decimal(signOf: Decimal(3), magnitudeOf: Decimal(5)).description)
XCTAssertEqual("-5",Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(5)).description)
XCTAssertEqual("5",Decimal(signOf: Decimal(3), magnitudeOf: Decimal(-5)).description)
XCTAssertEqual("-5",Decimal(signOf: Decimal(-3), magnitudeOf: Decimal(-5)).description)
}
func test_ExplicitConstruction() {
var explicit = Decimal(
_exponent: 0x17f,
_length: 0xff,
_isNegative: 3,
_isCompact: 4,
_reserved: UInt32(1<<18 + 1<<17 + 1),
_mantissa: (6,7,8,9,10,11,12,13)
)
XCTAssertEqual(0x7f, explicit._exponent)
XCTAssertEqual(0x7f, explicit.exponent)
XCTAssertEqual(0x0f, explicit._length)
XCTAssertEqual(1, explicit._isNegative)
XCTAssertEqual(FloatingPointSign.minus, explicit.sign)
XCTAssertTrue(explicit.isSignMinus)
XCTAssertEqual(0, explicit._isCompact)
XCTAssertEqual(UInt32(1<<17 + 1), explicit._reserved)
let (m0,m1,m2,m3,m4,m5,m6,m7) = explicit._mantissa
XCTAssertEqual(6, m0)
XCTAssertEqual(7, m1)
XCTAssertEqual(8, m2)
XCTAssertEqual(9, m3)
XCTAssertEqual(10, m4)
XCTAssertEqual(11, m5)
XCTAssertEqual(12, m6)
XCTAssertEqual(13, m7)
explicit._isCompact = 5
explicit._isNegative = 6
XCTAssertEqual(0, explicit._isNegative)
XCTAssertEqual(1, explicit._isCompact)
XCTAssertEqual(FloatingPointSign.plus, explicit.sign)
XCTAssertFalse(explicit.isSignMinus)
XCTAssertTrue(explicit.isNormal)
let significand = explicit.significand
XCTAssertEqual(0, significand._exponent)
XCTAssertEqual(0, significand.exponent)
XCTAssertEqual(0x0f, significand._length)
XCTAssertEqual(0, significand._isNegative)
XCTAssertEqual(1, significand._isCompact)
XCTAssertEqual(0, significand._reserved)
let (sm0,sm1,sm2,sm3,sm4,sm5,sm6,sm7) = significand._mantissa
XCTAssertEqual(6, sm0)
XCTAssertEqual(7, sm1)
XCTAssertEqual(8, sm2)
XCTAssertEqual(9, sm3)
XCTAssertEqual(10, sm4)
XCTAssertEqual(11, sm5)
XCTAssertEqual(12, sm6)
XCTAssertEqual(13, sm7)
let ulp = explicit.ulp
XCTAssertEqual(0x7f, ulp.exponent)
XCTAssertEqual(8, ulp._length)
XCTAssertEqual(0, ulp._isNegative)
XCTAssertEqual(1, ulp._isCompact)
XCTAssertEqual(0, ulp._reserved)
XCTAssertEqual(1, ulp._mantissa.0)
XCTAssertEqual(0, ulp._mantissa.1)
XCTAssertEqual(0, ulp._mantissa.2)
XCTAssertEqual(0, ulp._mantissa.3)
XCTAssertEqual(0, ulp._mantissa.4)
XCTAssertEqual(0, ulp._mantissa.5)
XCTAssertEqual(0, ulp._mantissa.6)
XCTAssertEqual(0, ulp._mantissa.7)
}
func test_Maths() {
for i in -2...10 {
for j in 0...5 {
XCTAssertEqual(Decimal(i*j), Decimal(i) * Decimal(j), "\(Decimal(i*j)) == \(i) * \(j)")
XCTAssertEqual(Decimal(i+j), Decimal(i) + Decimal(j), "\(Decimal(i+j)) == \(i)+\(j)")
XCTAssertEqual(Decimal(i-j), Decimal(i) - Decimal(j), "\(Decimal(i-j)) == \(i)-\(j)")
if j != 0 {
let approximation = Decimal(Double(i)/Double(j))
let answer = Decimal(i) / Decimal(j)
let answerDescription = answer.description
let approximationDescription = approximation.description
var failed: Bool = false
var count = 0
let SIG_FIG = 14
for (a, b) in zip(answerDescription.characters, approximationDescription.characters) {
if a != b {
failed = true
break
}
if count == 0 && (a == "-" || a == "0" || a == ".") {
continue // don't count these as significant figures
}
if count >= SIG_FIG {
break
}
count += 1
}
XCTAssertFalse(failed, "\(Decimal(i/j)) == \(i)/\(j)")
}
}
}
XCTAssertEqual(Decimal(186243*15673), Decimal(186243) * Decimal(15673))
}
func test_Misc() {
XCTAssertEqual(.minus,Decimal(-5.2).sign)
XCTAssertEqual(.plus,Decimal(5.2).sign)
var d = Decimal(5.2)
XCTAssertEqual(.plus,d.sign)
d.negate()
XCTAssertEqual(.minus,d.sign)
d.negate()
XCTAssertEqual(.plus,d.sign)
XCTAssertTrue(Decimal(3.5).isEqual(to: Decimal(3.5)))
XCTAssertTrue(Decimal.nan.isEqual(to: Decimal.nan))
XCTAssertTrue(Decimal(1.28).isLess(than: Decimal(2.24)))
XCTAssertFalse(Decimal(2.28).isLess(than: Decimal(2.24)))
XCTAssertTrue(Decimal(1.28).isTotallyOrdered(belowOrEqualTo: Decimal(2.24)))
XCTAssertFalse(Decimal(2.28).isTotallyOrdered(belowOrEqualTo: Decimal(2.24)))
XCTAssertTrue(Decimal(1.2).isTotallyOrdered(belowOrEqualTo: Decimal(1.2)))
XCTAssertTrue(Decimal.nan.isEqual(to: Decimal.nan))
XCTAssertTrue(Decimal.nan.isLess(than: Decimal(0)))
XCTAssertFalse(Decimal.nan.isLess(than: Decimal.nan))
XCTAssertTrue(Decimal.nan.isLessThanOrEqualTo(Decimal(0)))
XCTAssertTrue(Decimal.nan.isLessThanOrEqualTo(Decimal.nan))
XCTAssertFalse(Decimal.nan.isTotallyOrdered(belowOrEqualTo: Decimal.nan))
XCTAssertFalse(Decimal.nan.isTotallyOrdered(belowOrEqualTo: Decimal(2.3)))
XCTAssertTrue(Decimal(2) < Decimal(3))
XCTAssertTrue(Decimal(3) > Decimal(2))
XCTAssertEqual(3275573729074,Decimal(1234).hashValue)
XCTAssertEqual(Decimal(-9), Decimal(1) - Decimal(10))
XCTAssertEqual(Decimal(3),Decimal(2).nextUp)
XCTAssertEqual(Decimal(2),Decimal(3).nextDown)
XCTAssertEqual(Decimal(-476),Decimal(1024).distance(to: Decimal(1500)))
XCTAssertEqual(Decimal(68040),Decimal(386).advanced(by: Decimal(67654)))
XCTAssertEqual(Decimal(1.234),abs(Decimal(1.234)))
XCTAssertEqual(Decimal(1.234),abs(Decimal(-1.234)))
var a = Decimal(1234)
XCTAssertEqual(.noError,NSDecimalMultiplyByPowerOf10(&a,&a,1,.plain))
XCTAssertEqual(Decimal(12340),a)
a = Decimal(1234)
XCTAssertEqual(.noError,NSDecimalMultiplyByPowerOf10(&a,&a,2,.plain))
XCTAssertEqual(Decimal(123400),a)
XCTAssertEqual(.overflow,NSDecimalMultiplyByPowerOf10(&a,&a,128,.plain))
XCTAssertTrue(a.isNaN)
a = Decimal(1234)
XCTAssertEqual(.noError,NSDecimalMultiplyByPowerOf10(&a,&a,-2,.plain))
XCTAssertEqual(Decimal(12.34),a)
XCTAssertEqual(.underflow,NSDecimalMultiplyByPowerOf10(&a,&a,-128,.plain))
XCTAssertTrue(a.isNaN)
a = Decimal(1234)
XCTAssertEqual(.noError,NSDecimalPower(&a,&a,0,.plain))
XCTAssertEqual(Decimal(1),a)
a = Decimal(8)
XCTAssertEqual(.noError,NSDecimalPower(&a,&a,2,.plain))
XCTAssertEqual(Decimal(64),a)
a = Decimal(-2)
XCTAssertEqual(.noError,NSDecimalPower(&a,&a,3,.plain))
XCTAssertEqual(Decimal(-8),a)
for i in -2...10 {
for j in 0...5 {
var actual = Decimal(i)
XCTAssertEqual(.noError,NSDecimalPower(&actual,&actual,j,.plain))
let expected = Decimal(pow(Double(i),Double(j)))
XCTAssertEqual(expected, actual, "\(actual) == \(i)^\(j)")
}
}
}
func test_Round() {
let testCases = [
// expected, start, scale, round
( 0, 0.5, 0, Decimal.RoundingMode.down ),
( 1, 0.5, 0, Decimal.RoundingMode.up ),
( 2, 2.5, 0, Decimal.RoundingMode.bankers ),
( 4, 3.5, 0, Decimal.RoundingMode.bankers ),
( 5, 5.2, 0, Decimal.RoundingMode.plain ),
( 4.5, 4.5, 1, Decimal.RoundingMode.down ),
( 5.5, 5.5, 1, Decimal.RoundingMode.up ),
( 6.5, 6.5, 1, Decimal.RoundingMode.plain ),
( 7.5, 7.5, 1, Decimal.RoundingMode.bankers ),
( -1, -0.5, 0, Decimal.RoundingMode.down ),
( -2, -2.5, 0, Decimal.RoundingMode.up ),
( -3, -2.5, 0, Decimal.RoundingMode.bankers ),
( -4, -3.5, 0, Decimal.RoundingMode.bankers ),
( -5, -5.2, 0, Decimal.RoundingMode.plain ),
( -4.5, -4.5, 1, Decimal.RoundingMode.down ),
( -5.5, -5.5, 1, Decimal.RoundingMode.up ),
( -6.5, -6.5, 1, Decimal.RoundingMode.plain ),
( -7.5, -7.5, 1, Decimal.RoundingMode.bankers ),
]
for testCase in testCases {
let (expected, start, scale, mode) = testCase
var num = Decimal(start)
NSDecimalRound(&num,&num,scale,mode)
XCTAssertEqual(Decimal(expected), num)
}
}
func test_Normalise() {
var one = Decimal(1)
var ten = Decimal(-10)
XCTAssertEqual(.noError,NSDecimalNormalize(&one,&ten,.plain))
XCTAssertEqual(Decimal(1),one)
XCTAssertEqual(Decimal(-10),ten)
XCTAssertEqual(1,one._length)
XCTAssertEqual(1,ten._length)
one = Decimal(1)
ten = Decimal(10)
XCTAssertEqual(.noError,NSDecimalNormalize(&one,&ten,.plain))
XCTAssertEqual(Decimal(1),one)
XCTAssertEqual(Decimal(10),ten)
XCTAssertEqual(1,one._length)
XCTAssertEqual(1,ten._length)
}
func test_NSDecimal() {
var nan = Decimal.nan
XCTAssertTrue(NSDecimalIsNotANumber(&nan))
var zero = Decimal()
XCTAssertFalse(NSDecimalIsNotANumber(&zero))
var three = Decimal(3)
var guess = Decimal()
NSDecimalCopy(&guess,&three)
XCTAssertEqual(three,guess)
var f = Decimal(_exponent: 0, _length: 2, _isNegative: 0, _isCompact: 0, _reserved: 0, _mantissa: (0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
let before = f.description
XCTAssertEqual(0,f._isCompact)
NSDecimalCompact(&f)
XCTAssertEqual(1,f._isCompact)
let after = f.description
XCTAssertEqual(before,after)
}
}