Compare commits

..

1 Commits

10 changed files with 83 additions and 62 deletions

View File

@ -6,14 +6,14 @@ matrix:
dist: trusty
before_install:
- wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import -
- wget https://swift.org/builds/swift-4.1-release/ubuntu1404/swift-4.1-RELEASE/swift-4.1-RELEASE-ubuntu14.04.tar.gz
- tar xzf swift-4.1-RELEASE-ubuntu14.04.tar.gz
- export PATH=${PWD}/swift-4.1-RELEASE-ubuntu14.04/usr/bin:"${PATH}"
- wget https://swift.org/builds/swift-4.0-release/ubuntu1404/swift-4.0-RELEASE/swift-4.0-RELEASE-ubuntu14.04.tar.gz
- tar xzf swift-4.0-RELEASE-ubuntu14.04.tar.gz
- export PATH=${PWD}/swift-4.0-RELEASE-ubuntu14.04/usr/bin:"${PATH}"
script:
- swift test -Xcc -D_GNU_SOURCE
- os: osx
language: objective-c
osx_image: xcode9.3beta
osx_image: xcode9
script:
- swift package generate-xcodeproj && xcodebuild clean test -project NumericAnnex.xcodeproj -scheme NumericAnnex-Package -enableCodeCoverage YES
after_success:

View File

@ -28,9 +28,8 @@ library.
## Requirements
NumericAnnex requires Swift 4.1 (`swift-4.1-branch`) or Swift 4.2 (`master`). On
Apple platforms, it also requires the Security framework for cryptographically
secure random bytes.
NumericAnnex requires Swift 4.0. On Apple platforms, it also requires the
Security framework for cryptographically secure random bytes.
## Installation

View File

@ -18,14 +18,8 @@ extension _Hash {
///
/// [ref]: http://goanna.cs.rmit.edu.au/~jz/fulltext/jasist-tch.pdf
internal static func _combine(seed: Int = 0, _ values: AnyHashable...) -> Int {
// Use a magic number based on the golden ratio
// (0x1.9e3779b97f4a7c15f39cc0605cedc8341082276bf3a27251f86c6a11d0c18e95p0).
#if arch(i386) || arch(arm)
let magic = 0x9e3779b9 as UInt
#else
let magic = 0x9e3779b97f4a7c15 as UInt
#endif
var x = UInt(bitPattern: seed)
let magic = 0x9e3779b9 as UInt // Based on the golden ratio.
for v in values {
x ^= UInt(bitPattern: v.hashValue) &+ magic &+ (x &<< 6) &+ (x &>> 2)
}

View File

@ -201,7 +201,9 @@ extension BinaryInteger where Magnitude : UnsignedInteger {
// is necessary to disambiguate calls to `Magnitude.lcmReportingOverflow(_:_:)`
// and `Magnitude.lcmFullWidth(_:_:)`.
extension BinaryInteger
where Self : FixedWidthInteger, Magnitude : UnsignedInteger {
where Self : FixedWidthInteger,
Magnitude : FixedWidthInteger & UnsignedInteger,
Magnitude.Magnitude == Magnitude {
// ---------------------------------------------------------------------------
// MARK: Factoring (Fixed-Width)
// ---------------------------------------------------------------------------

View File

@ -51,7 +51,9 @@ import Security
/// numeric value is `uniform()`; that method is overloaded to permit custom
/// minimum and maximum values for the uniform distribution.
public protocol PRNG : class, IteratorProtocol, Sequence
where Element : FixedWidthInteger & UnsignedInteger {
where Element : FixedWidthInteger & UnsignedInteger,
SubSequence : Sequence,
Element == SubSequence.Element {
/// A type that can represent the internal state of the pseudo-random number
/// generator.
associatedtype State
@ -245,7 +247,7 @@ extension PRNG {
/// through `b` (inclusive) from the discrete uniform distribution.
public func uniform<T : FixedWidthInteger & SignedInteger>(
_: T.Type = T.self, a: T, b: T
) -> T where T.Magnitude : UnsignedInteger {
) -> T where T.Magnitude : FixedWidthInteger & UnsignedInteger {
precondition(
b >= a,
"Discrete uniform distribution parameter b should not be less than a"
@ -273,7 +275,7 @@ extension PRNG {
@_transparent // @_inlineable
public func uniform<T : FixedWidthInteger & SignedInteger>(
_: T.Type = T.self
) -> T where T.Magnitude : UnsignedInteger {
) -> T where T.Magnitude : FixedWidthInteger & UnsignedInteger {
return uniform(a: T.min, b: T.max)
}
@ -284,7 +286,7 @@ extension PRNG {
public func uniform<T : FixedWidthInteger & SignedInteger>(
_: T.Type = T.self, a: T, b: T, count: Int
) -> UnfoldSequence<T, Int>
where T.Magnitude : UnsignedInteger {
where T.Magnitude : FixedWidthInteger & UnsignedInteger {
precondition(count >= 0, "Element count should be non-negative")
return sequence(state: 0) { (state: inout Int) -> T? in
state += 1
@ -299,7 +301,7 @@ extension PRNG {
public func uniform<T : FixedWidthInteger & SignedInteger>(
_: T.Type = T.self, count: Int
) -> UnfoldSequence<T, Int>
where T.Magnitude : UnsignedInteger {
where T.Magnitude : FixedWidthInteger & UnsignedInteger {
return uniform(a: T.min, b: T.max, count: count)
}
}

View File

@ -70,7 +70,8 @@
@_fixed_layout
public struct Rational<T : SignedInteger> : Codable
where T : Codable & _ExpressibleByBuiltinIntegerLiteral,
T.Magnitude : UnsignedInteger {
T.Magnitude : UnsignedInteger,
T.Magnitude.Magnitude == T.Magnitude {
// ---------------------------------------------------------------------------
// MARK: Stored Properties
// ---------------------------------------------------------------------------
@ -162,7 +163,7 @@ where T : Codable & _ExpressibleByBuiltinIntegerLiteral,
}
}
extension Rational where T : FixedWidthInteger {
extension Rational where T : FixedWidthInteger, T.Magnitude : FixedWidthInteger {
// ---------------------------------------------------------------------------
// MARK: Initializers (Constrained)
// ---------------------------------------------------------------------------
@ -610,6 +611,26 @@ extension Rational : Strideable {
public func advanced(by amount: Rational) -> Rational {
return self + amount
}
@_transparent // @_inlineable
public func _steps(to other: Rational, by amount: Rational) -> Int {
let distance = self.distance(to: other)
precondition(amount != 0 && distance != 0)
guard (amount < 0) == (distance < 0) else { return 0 }
guard
let result = Int(exactly: ((distance - 1) / amount).mixed.whole),
result < Int.max
else {
fatalError("Steps from \(self) to \(other) exceed Int.max - 1")
}
return result
}
@_transparent // @_inlineable
public func _advanced(by amount: Rational, count: Int) -> Rational {
return advanced(by: Rational(count) * amount)
}
}
extension Rational : Numeric {

View File

@ -210,12 +210,12 @@ extension Float : Real {
@_transparent
public func naturalExponential() -> Float {
return _exp(self)
return expf(self)
}
@_transparent
public func binaryExponential() -> Float {
return _exp2(self)
return exp2f(self)
}
@_transparent
@ -234,17 +234,17 @@ extension Float : Real {
@_transparent
public func naturalLogarithm() -> Float {
return _log(self)
return logf(self)
}
@_transparent
public func binaryLogarithm() -> Float {
return _log2(self)
return log2f(self)
}
@_transparent
public func commonLogarithm() -> Float {
return _log10(self)
return log10f(self)
}
@_transparent
@ -259,12 +259,12 @@ extension Float : Real {
@_transparent
public func sine() -> Float {
return _sin(self)
return sinf(self)
}
@_transparent
public func cosine() -> Float {
return _cos(self)
return cosf(self)
}
@_transparent
@ -379,12 +379,20 @@ extension Double : Real {
@_transparent
public func naturalExponential() -> Double {
return _exp(self)
#if os(Linux)
return Glibc.exp(self)
#else
return Darwin.exp(self)
#endif
}
@_transparent
public func binaryExponential() -> Double {
return _exp2(self)
#if os(Linux)
return Glibc.exp2(self)
#else
return Darwin.exp2(self)
#endif
}
@_transparent
@ -407,17 +415,29 @@ extension Double : Real {
@_transparent
public func naturalLogarithm() -> Double {
return _log(self)
#if os(Linux)
return Glibc.log(self)
#else
return Darwin.log(self)
#endif
}
@_transparent
public func binaryLogarithm() -> Double {
return _log2(self)
#if os(Linux)
return Glibc.log2(self)
#else
return Darwin.log2(self)
#endif
}
@_transparent
public func commonLogarithm() -> Double {
return _log10(self)
#if os(Linux)
return Glibc.log10(self)
#else
return Darwin.log10(self)
#endif
}
@_transparent
@ -440,12 +460,20 @@ extension Double : Real {
@_transparent
public func sine() -> Double {
return _sin(self)
#if os(Linux)
return Glibc.sin(self)
#else
return Darwin.sin(self)
#endif
}
@_transparent
public func cosine() -> Double {
return _cos(self)
#if os(Linux)
return Glibc.cos(self)
#else
return Darwin.cos(self)
#endif
}
@_transparent

View File

@ -41,7 +41,6 @@ class FactoringTests : XCTestCase {
XCTAssertEqual(UInt.lcm(42, 0), 0)
XCTAssertEqual(UInt.lcm(0, 0), 0)
#if !swift(>=4.1)
XCTAssertEqual(Int8.lcmFullWidth(0, 42).high, 0)
XCTAssertEqual(Int8.lcmFullWidth(0, 42).low, 0)
XCTAssertEqual(Int8.lcmReportingOverflow(0, 42).partialValue, 0)
@ -56,7 +55,6 @@ class FactoringTests : XCTestCase {
XCTAssertEqual(Int8.lcmFullWidth(0, 0).low, 0)
XCTAssertEqual(Int8.lcmReportingOverflow(0, 0).partialValue, 0)
XCTAssertFalse(Int8.lcmReportingOverflow(0, 0).overflow)
#endif
XCTAssertEqual(UInt8.lcmFullWidth(0, 42).high, 0)
XCTAssertEqual(UInt8.lcmFullWidth(0, 42).low, 0)

View File

@ -97,19 +97,15 @@ class RationalTests : XCTestCase {
XCTAssertEqual(pi.description, "inf")
XCTAssertTrue(pi.isCanonical)
#if !swift(>=4.1)
XCTAssertTrue(Ratio(numerator: 2, denominator: 0).isInfinite)
XCTAssertFalse(Ratio(numerator: 2, denominator: 0).isCanonical)
#endif
let ni = -Ratio.infinity
XCTAssertEqual(ni.description, "-inf")
XCTAssertTrue(ni.isCanonical)
#if !swift(>=4.1)
XCTAssertTrue(Ratio(numerator: -2, denominator: 0).isInfinite)
XCTAssertFalse(Ratio(numerator: -2, denominator: 0).isCanonical)
#endif
let zero = 0 as Ratio
XCTAssertEqual(zero.description, "0")
@ -123,18 +119,14 @@ class RationalTests : XCTestCase {
XCTAssertEqual(pi + pi, .infinity)
XCTAssertEqual(ni + ni, -.infinity)
#if !swift(>=4.1)
XCTAssertEqual(pi + 0, .infinity)
XCTAssertEqual(ni + 0, -.infinity)
#endif
XCTAssertEqual(pi + 42, .infinity)
XCTAssertEqual(pi - 42, .infinity)
XCTAssertEqual(ni + 42, -.infinity)
XCTAssertEqual(ni - 42, -.infinity)
#if !swift(>=4.1)
XCTAssertEqual(0 + pi, .infinity)
XCTAssertEqual(0 + ni, -.infinity)
#endif
XCTAssertEqual(42 + pi, .infinity)
XCTAssertEqual(42 - pi, -.infinity)
XCTAssertEqual(42 + ni, -.infinity)
@ -145,7 +137,6 @@ class RationalTests : XCTestCase {
XCTAssertTrue((pi - pi).isNaN)
XCTAssertTrue((-pi + pi).isNaN)
#if !swift(>=4.1)
XCTAssertTrue((0 / 0 as Ratio).isNaN)
XCTAssert((0 / 0 as Ratio) != .nan) // NaN compares unequal to everything.
XCTAssertTrue((42 / 0 as Ratio).isInfinite)
@ -154,19 +145,16 @@ class RationalTests : XCTestCase {
XCTAssert(-42 / 0 as Ratio == -.infinity)
XCTAssertEqual((42 / 0 as Ratio).description, "inf")
XCTAssertEqual((-42 / 0 as Ratio).description, "-inf")
#endif
XCTAssertEqual(pi * pi, .infinity)
XCTAssertEqual(pi * ni, -.infinity)
XCTAssertEqual(ni * pi, -.infinity)
XCTAssertEqual(ni * ni, .infinity)
#if !swift(>=4.1)
XCTAssertTrue((pi * 0).isNaN)
XCTAssertTrue((ni * 0).isNaN)
XCTAssertTrue((0 * pi).isNaN)
XCTAssertTrue((0 * ni).isNaN)
#endif
XCTAssertTrue((pn * pi).isNaN)
XCTAssertTrue((pi * pn).isNaN)
XCTAssertTrue((pn * ni).isNaN)

View File

@ -23,7 +23,7 @@ extension MockReal : Hashable {
}
}
extension MockReal : Strideable {
extension MockReal : Strideable, _Strideable {
func distance(to other: MockReal) -> MockReal {
return MockReal(_value.distance(to: other._value))
}
@ -33,10 +33,6 @@ extension MockReal : Strideable {
}
}
#if !swift(>=4.1)
extension MockReal : _Strideable { }
#endif
extension MockReal : Numeric {
var magnitude: MockReal {
return MockReal(_value.magnitude)
@ -73,13 +69,6 @@ extension MockReal : Numeric {
}
extension MockReal : FloatingPoint {
init<T : BinaryInteger>(_ value: T) {
#if false
self = MockReal(Double(value))
#endif
fatalError()
}
init(_ value: Int) {
self = MockReal(Double(value))
}