Add tie-breaking exponentiation operators and tests

This commit is contained in:
Xiaodi Wu 2017-08-27 18:04:21 -05:00
parent 16d65fca54
commit 23f5c7a496
5 changed files with 351 additions and 4 deletions

View File

@ -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>.

View File

@ -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

View File

@ -2,6 +2,7 @@ import XCTest
@testable import NumericAnnexTests
XCTMain([
testCase(DocumentationExampleTests.allTests),
testCase(ExponentiationTests.allTests),
testCase(RootExtractionTests.allTests),
testCase(FactoringTests.allTests),

View File

@ -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),
]
}

View File

@ -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),
]
}