Add tie-breaking exponentiation operators and tests
This commit is contained in:
parent
16d65fca54
commit
23f5c7a496
12
README.md
12
README.md
|
@ -59,6 +59,18 @@ add the package as a dependency. See Swift documentation for details.
|
|||
```swift
|
||||
import NumericAnnex
|
||||
|
||||
print(2 ** 3)
|
||||
// Prints "8".
|
||||
|
||||
print(4.0 ** 5.0)
|
||||
// Prints "1024.0".
|
||||
|
||||
print(Int.cbrt(8))
|
||||
// Prints "2".
|
||||
|
||||
print(Double.cbrt(27.0))
|
||||
// Prints "3.0".
|
||||
|
||||
var x: Ratio = 1 / 4
|
||||
// Ratio is a type alias for Rational<Int>.
|
||||
|
||||
|
|
|
@ -10,10 +10,10 @@ extension BinaryInteger {
|
|||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: Self, rhs: Self) -> Self {
|
||||
// We need to factor out the implementation of `**` so that the tie-breaking
|
||||
// operators implemented in extensions to concrete integer types can call it.
|
||||
@_versioned
|
||||
internal static func _pow(_ lhs: Self, _ rhs: Self) -> Self {
|
||||
var x = lhs, n = rhs
|
||||
if Self.isSigned && n < 0 {
|
||||
x = 1 / x
|
||||
|
@ -34,6 +34,13 @@ extension BinaryInteger {
|
|||
return x * y
|
||||
}
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: Self, rhs: Self) -> Self {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
|
@ -230,3 +237,233 @@ where Self : FixedWidthInteger,
|
|||
return (Self(t.high), t.low)
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// TIE-BREAKING OPERATORS
|
||||
//
|
||||
// The following extensions are required so that an expression such as `2 ** 3`
|
||||
// is unambiguous as long as `IntegerLiteralType` is one of the standard library
|
||||
// types below.
|
||||
// =============================================================================
|
||||
|
||||
extension Int {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: Int, rhs: Int) -> Int {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout Int, rhs: Int) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension Int8 {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: Int8, rhs: Int8) -> Int8 {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout Int8, rhs: Int8) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension Int16 {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: Int16, rhs: Int16) -> Int16 {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout Int16, rhs: Int16) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension Int32 {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: Int32, rhs: Int32) -> Int32 {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout Int32, rhs: Int32) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension Int64 {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: Int64, rhs: Int64) -> Int64 {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout Int64, rhs: Int64) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: UInt, rhs: UInt) -> UInt {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout UInt, rhs: UInt) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt8 {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: UInt8, rhs: UInt8) -> UInt8 {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout UInt8, rhs: UInt8) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt16 {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: UInt16, rhs: UInt16) -> UInt16 {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout UInt16, rhs: UInt16) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt32 {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: UInt32, rhs: UInt32) -> UInt32 {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout UInt32, rhs: UInt32) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt64 {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: UInt64, rhs: UInt64) -> UInt64 {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout UInt64, rhs: UInt64) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
|
||||
#if false
|
||||
extension DoubleWidth {
|
||||
// ---------------------------------------------------------------------------
|
||||
// MARK: Exponentiation
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Returns the result of raising `lhs` to the power of `rhs`, rounded to a
|
||||
/// representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func ** (lhs: DoubleWidth, rhs: DoubleWidth) -> DoubleWidth {
|
||||
return _pow(lhs, rhs)
|
||||
}
|
||||
|
||||
/// Raises `lhs` to the power of `rhs` and stores the result in `lhs`, rounded
|
||||
/// to a representable value.
|
||||
@_transparent // @_inlineable
|
||||
public static func **= (lhs: inout DoubleWidth, rhs: DoubleWidth) {
|
||||
lhs = lhs ** rhs
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -2,6 +2,7 @@ import XCTest
|
|||
@testable import NumericAnnexTests
|
||||
|
||||
XCTMain([
|
||||
testCase(DocumentationExampleTests.allTests),
|
||||
testCase(ExponentiationTests.allTests),
|
||||
testCase(RootExtractionTests.allTests),
|
||||
testCase(FactoringTests.allTests),
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import XCTest
|
||||
/* @testable */ import NumericAnnex
|
||||
|
||||
class DocumentationExampleTests : XCTestCase {
|
||||
// It reflects poorly on the project to provide examples that don't compile or
|
||||
// give the wrong result, so test them here:
|
||||
|
||||
func testReadmeExample() {
|
||||
print(2 ** 3)
|
||||
// Prints "8".
|
||||
XCTAssertEqual("\(2 ** 3)", "8")
|
||||
|
||||
print(4.0 ** 5.0)
|
||||
// Prints "1024.0".
|
||||
XCTAssertEqual("\(4.0 ** 5.0)", "1024.0")
|
||||
|
||||
print(Int.cbrt(8))
|
||||
// Prints "2".
|
||||
XCTAssertEqual("\(Int.cbrt(8))", "2")
|
||||
|
||||
print(Double.cbrt(27.0))
|
||||
// Prints "3.0".
|
||||
XCTAssertEqual("\(Double.cbrt(27.0))", "3.0")
|
||||
|
||||
var x: Ratio = 1 / 4
|
||||
// Ratio is a type alias for Rational<Int>.
|
||||
|
||||
print(x.reciprocal())
|
||||
// Prints "4".
|
||||
XCTAssertEqual("\(x.reciprocal())", "4")
|
||||
|
||||
x *= 8
|
||||
print(x + x)
|
||||
// Prints "4".
|
||||
XCTAssertEqual("\(x + x)", "4")
|
||||
|
||||
x = Ratio(Float.phi) // Golden ratio.
|
||||
print(x)
|
||||
// Prints "13573053/8388608".
|
||||
XCTAssertEqual("\(x)", "13573053/8388608")
|
||||
|
||||
var z: Complex64 = 42 * .i
|
||||
// Complex64 is a type alias for Complex<Float>.
|
||||
|
||||
print(Complex.sqrt(z))
|
||||
// Prints "4.58258 + 4.58258i".
|
||||
XCTAssertEqual("\(Complex.sqrt(z))", "4.58258 + 4.58258i")
|
||||
|
||||
z = .pi + .i * .log(2 - .sqrt(3))
|
||||
print(Complex.cos(z).real)
|
||||
// Prints "-2.0".
|
||||
XCTAssertEqual("\(Complex.cos(z).real)", "-2.0")
|
||||
}
|
||||
|
||||
static var allTests = [
|
||||
("testReadmeExample", testReadmeExample),
|
||||
]
|
||||
}
|
|
@ -27,8 +27,47 @@ class ExponentiationTests : XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
func testConcreteIntegerTypePow() {
|
||||
XCTAssertEqual((2 as Int) ** 3, 8 as Int)
|
||||
XCTAssertEqual((2 as Int8) ** 3, 8 as Int8)
|
||||
XCTAssertEqual((2 as Int16) ** 3, 8 as Int16)
|
||||
XCTAssertEqual((2 as Int32) ** 3, 8 as Int32)
|
||||
XCTAssertEqual((2 as Int64) ** 3, 8 as Int64)
|
||||
|
||||
do { var x = 2 as Int; x **= 3; XCTAssertEqual(x, 8 as Int) }
|
||||
do { var x = 2 as Int8; x **= 3; XCTAssertEqual(x, 8 as Int8) }
|
||||
do { var x = 2 as Int16; x **= 3; XCTAssertEqual(x, 8 as Int16) }
|
||||
do { var x = 2 as Int32; x **= 3; XCTAssertEqual(x, 8 as Int32) }
|
||||
do { var x = 2 as Int64; x **= 3; XCTAssertEqual(x, 8 as Int64) }
|
||||
|
||||
XCTAssertEqual((2 as UInt) ** 3, 8 as UInt)
|
||||
XCTAssertEqual((2 as UInt8) ** 3, 8 as UInt8)
|
||||
XCTAssertEqual((2 as UInt16) ** 3, 8 as UInt16)
|
||||
XCTAssertEqual((2 as UInt32) ** 3, 8 as UInt32)
|
||||
XCTAssertEqual((2 as UInt64) ** 3, 8 as UInt64)
|
||||
|
||||
do { var x = 2 as UInt; x **= 3; XCTAssertEqual(x, 8 as UInt) }
|
||||
do { var x = 2 as UInt8; x **= 3; XCTAssertEqual(x, 8 as UInt8) }
|
||||
do { var x = 2 as UInt16; x **= 3; XCTAssertEqual(x, 8 as UInt16) }
|
||||
do { var x = 2 as UInt32; x **= 3; XCTAssertEqual(x, 8 as UInt32) }
|
||||
do { var x = 2 as UInt64; x **= 3; XCTAssertEqual(x, 8 as UInt64) }
|
||||
}
|
||||
|
||||
func testGenericIntegerTypePow() {
|
||||
func _testPow<
|
||||
T : BinaryInteger
|
||||
>(_: T.Type = T.self, lhs: T, rhs: T, expected: T) {
|
||||
XCTAssertEqual(lhs ** rhs, expected)
|
||||
do { var x = lhs; x **= rhs; XCTAssertEqual(x, expected) }
|
||||
}
|
||||
_testPow(lhs: 2 as Int, rhs: 3, expected: 8)
|
||||
_testPow(lhs: 2 as UInt, rhs: 3, expected: 8)
|
||||
}
|
||||
|
||||
static var allTests = [
|
||||
("testIntPow", testIntPow),
|
||||
("testUIntPow", testUIntPow),
|
||||
("testConcreteIntegerTypePow", testConcreteIntegerTypePow),
|
||||
("testGenericIntegerTypePow", testGenericIntegerTypePow),
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue