profile
viewpoint
Stephen Canon stephentyrone Lebanon, NH

stephentyrone/swift-numerics 1

Numerical APIs for Swift

stephentyrone/pcg-c 0

PCG — C Implementation

stephentyrone/swift 0

The Swift Programming Language

stephentyrone/swift-algorithms 0

Swift Algorithms is an open-source package of sequence and collection algorithms, along with their related types.

stephentyrone/swift-atomics 0

This package implements an atomics library for Swift, providing atomic operations for a variety of Swift types, including integers and pointer values. The goal is to enable intrepid developers to start building synchronization constructs directly in Swift.

stephentyrone/swift-evolution 0

This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.

stephentyrone/swift-lldb 0

This is the version of LLDB that supports the Swift programming language & REPL.

issue commentapple/swift-numerics

Real part of complex expMinusOne is bad when e^{-x} ~ cos y

It's no less accurate than the alternatives we have (as explained), not significantly slower, and yields considerable simplicity in the implementation. What's not to like?

riastradh

comment created time in 8 days

issue commentapple/swift-numerics

Real part of complex expMinusOne is bad when e^{-x} ~ cos y

Forgot to address z very nearly 0 😀

In this case, expMinusOne(x) cos(y) + cosMinusOne(y) becomes x*1 + y^2/2 = x, so there's no loss of accuracy in just using the expression we have.

riastradh

comment created time in 8 days

issue commentapple/swift-numerics

Real part of complex expMinusOne is bad when e^{-x} ~ cos y

Right, exp(x) * cos(y) - 1 is about as good on that region, but not better. The expMinusOne alternative is always strictly worse. So there's no reason to use either of those on any region of the plane. You're always at least as well off using what we have now, and often better off.

In an additive expression with cancellation, the error comes only from the rounding of the terms that are cancelling. If you look at what we use currently:

expMinusOne(x) cos(y) + cosMinusOne(y)

Assuming a good-quality host math library, expMinusOne, cos, and cosMinusOne are all computed with small relative error (ideally sub-ulp, a couple of ulp at worst). So we are evaluating an expression of the form a(1+δ₁) + b(1+δ₂) where a and b are the exact real values of (e^x-1)cos(y) and cos(y)-1, respectively and the deltas are bounded by a small multiple of epsilon. Because we're interested in the region close to the critical curve, the addition is computed exactly, so the result is precisely Re(exp(z)-1) + δ₁a + δ₂b, and so the absolute error is bounded by (|a|+|b|)kε for some small k.

Note that this analysis holds for all of the expressions you consider, except the "dual" factorization; the way we minimize the error bound is to minimize |a| and |b|. Among the alternatives considered, the one in use minimizes them for all input values, not just in some region. There's a small note to make for exp(x)cos(y) - 1, because 1 is exact and therefore does not contribute to the error, but that buys you at most a bit or two in practice in this case, hardly worth the added complexity when you still have essentially no good bits in the result (it would be likely to be worth using in an arbitrary-precision implementation, however).

riastradh

comment created time in 8 days

issue commentapple/swift-numerics

Real part of complex expMinusOne is bad when e^{-x} ~ cos y

Second, the problem curve approaches cos(y) = 0 as x increases, so cosMinusOne(y) is actively harmful in that region for large x.

Well, no, because the alternative factorization (exp(x) cosMinuxOne(y) + expMinusOne(x)) has terms that get arbitrarily large, while the terms in the factorization we're using stay bounded near 1. So it's not what we want, but it's far better than the only alternative we have available currently.

riastradh

comment created time in 8 days

pull request commentapple/swift-numerics

Refactor README.md and include Approximate Equality as part of the RealModule.

Hi @markuswntr, can you update this to point against main instead of master? Thanks.

markuswntr

comment created time in 9 days

push eventstephentyrone/swift-numerics

Stephen Canon

commit sha 957187037f3df905502e3c392976ac561a9a4939

WIP on log(onePlus:) The error is still slightly larger than it should be close to the critical circle when x ~ -0.5, so there's a rounding that isn't anticipated to be accounted for somewhere. However, the normwise accuracy is excellent, and the test refactoring is good. Drops ArgumentParser dependency, which we don't really need--it was more for fun--and is probably good to avoid possible numerics->algorithms->argument parser circular dependencies in the future.

view details

push time in 9 days

delete branch stephentyrone/swift-algorithms

delete branch : use-the-package-luke

delete time in 9 days

pull request commentapple/swift-algorithms

Use Swift Numerics for elementary functions

I think it makes sense because: (a) We want people to use SN for the elementary functions--it's the "blessed" package for those APIs. If Numerics needed Cycle or whatever, I would expect to pull in Algorithms for it. (b) In this particular case, I expect that Algorithms will want other pieces of Numerics in the future (especially stuff around RNGs), so I believe that you'll end up with this dependency sooner or later anyway.

stephentyrone

comment created time in 10 days

push eventapple/swift

tbkka

commit sha 5d30503894e1fc460fe98ba604ad21381a87637a

When parsing floating-point from String, underflow to 0, overflow to infinity (#34339) Previously, overflow and underflow both caused this to return `nil`, which causes several problems: * It does not distinguish between a large but valid input and a malformed input. `Float("3.402824e+38")` is perfectly well-formed but returns nil * It differs from how the compiler handles literals. As a result, `Float(3.402824e+38)` is very different from `Float("3.402824e+38")` * It's inconsistent with Foundation Scanner() * It's inconsistent with other programming languages This is exactly the same as #25313 Fixes rdar://problem/36990878

view details

push time in 10 days

PR merged apple/swift

When parsing floating-point from String, underflow to 0, overflow to ∞

Previously, overflow and underflow both caused this to return nil, which causes several problems:

  • It does not distinguish between a large but valid input and a malformed input. Float("3.402824e+38") is perfectly well-formed but returns nil
  • It differs from how the compiler handles literals. As a result, Float(3.402824e+38) is very different from Float("3.402824e+38")
  • It's inconsistent with Foundation Scanner()
  • It's inconsistent with other programming languages

Note: This is exactly the same as #25313 by @stephentyrone

Fixes rdar://problem/36990878

+9 -22

4 comments

3 changed files

tbkka

pr closed time in 10 days

pull request commentapple/swift

When parsing floating-point from String, underflow to 0, overflow to ∞

@swift-ci please test Linux

tbkka

comment created time in 11 days

PullRequestReviewEvent
PullRequestReviewEvent

push eventstephentyrone/swift-algorithms

Stephen Canon

commit sha 73c4a2156347366818ee6f7914bfdebc1239b079

Add the magic plist file to make xcode render the markdown guides. (#27)

view details

Stephen Canon

commit sha b85ada3c5416777ba2d5c264db6902a7f262443d

Use Swift Numerics for elementary functions instead of Darwin/Glibc/etc Also lets us use root instead of exp(log(x)/k), which is more accurate in some cases (but mainly is just nicer to read). The downside is that this introduces a dependency for Algorithms, where previously it had none. I think that Numerics is an OK thing to depend on (especially for these functions, which are available from 0.0.1), but it _is_ a _massive increase_ in the number of dependencies that the package has, and we should give that some thought.

view details

push time in 13 days

PR opened apple/swift-algorithms

Use Swift Numerics for elementary functions

This drops the canImport darwin/glibc/etc dance, which is ugly, and lets us use root instead of exp(log(x)/k), which is more accurate in some cases (but mainly is just nicer to read).

The downside is that this introduces a dependency for Algorithms, where previously it had none. I think that Numerics is an OK thing to depend on (especially for these functions, which are available from 0.0.1), but it is a massive increase in the number of dependencies that the package has, and we should give that some thought.

+17 -19

0 comment

3 changed files

pr created time in 13 days

create barnchstephentyrone/swift-algorithms

branch : use-the-package-luke

created branch time in 13 days

delete branch stephentyrone/swift-algorithms

delete branch : render-markdown-in-xcode

delete time in 13 days

create barnchstephentyrone/swift-algorithms

branch : render-markdown-in-xcode

created branch time in 13 days

delete branch stephentyrone/swift-algorithms

delete branch : render-markdown-in-xcode

delete time in 13 days

PR opened apple/swift-algorithms

Add the magic plist file to make xcode render the markdown guides.

The downside to doing this is that it makes the files more inconvenient to edit, since Xcode doesn't let you toggle out of the rendered view easily, but I think it makes sense on the premise that these are read much more often than edited. I have this flag set in Swift Numerics for this reason.

+5 -0

0 comment

1 changed file

pr created time in 13 days

create barnchstephentyrone/swift-algorithms

branch : render-markdown-in-xcode

created branch time in 13 days

fork stephentyrone/swift-algorithms

Swift Algorithms is an open-source package of sequence and collection algorithms, along with their related types.

fork in 13 days

push eventapple/swift-numerics

Saleem Abdulrasool

commit sha 0ee972ff9227b05207fa3f9b55aefe332c7fba1b

build: enable building `Numerics` on Darwin with CMake The `-enable-force-autolink` flag is not supported on Darwin. Fortunately, it is also unnecessary to work around the SR on Darwin. Simply exclude the flag when targeting Darwin.

view details

Stephen Canon

commit sha 874c7674243cae891ed2dd5c8750abe4249337e9

Merge pull request #159 from compnerd/autolink build: enable building `Numerics` on Darwin with CMake

view details

push time in 15 days

PR merged apple/swift-numerics

build: enable building `Numerics` on Darwin with CMake

The -enable-force-autolink flag is not supported on Darwin. Fortunately, it is also unnecessary to work around the SR on Darwin. Simply exclude the flag when targeting Darwin.

+1 -1

0 comment

1 changed file

compnerd

pr closed time in 15 days

PullRequestReviewEvent

pull request commentJuliaLang/julia

Switch Float16 to LLVM's half

@simonbyrne Swift doesn't document Float16 specifically, but as a matter of policy we never carry excess precision in floating-point. That leaves some optimizations on the table (and can give less accurate results), but helps with portability and predictability.

maleadt

comment created time in 21 days

startedapple/swift-atomics

started time in 21 days

fork stephentyrone/swift-atomics

This package implements an atomics library for Swift, providing atomic operations for a variety of Swift types, including integers and pointer values. The goal is to enable intrepid developers to start building synchronization constructs directly in Swift.

fork in 21 days

startedapple/swift-algorithms

started time in 21 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentapple/swift-atomics

[shims] Make retain_n/release_n shims header-only

 SWIFTATOMIC_DEFINE_TYPE(COMPLEX, DoubleWord, _sa_dword, uint64_t) #error "Unsupported intptr_t bit width" #endif // __INTPTR_WIDTH -extern void _sa_retain_n(void *object, uint32_t n);-extern void _sa_release_n(void *object, uint32_t n);+static inline void _sa_retain_n(void *object, uint32_t n) {

You might crib #define HEADER_SHIM static inline __attribute__((__always_inline__)) from Swift Numerics for this purpose.

lorentey

comment created time in 23 days

Pull request review commentapple/swift

[SE-0288] [stdlib] Adding isPower(of:) to BinaryInteger

 extension BinaryInteger {     return self.magnitude % other.magnitude == 0   } +  /// Returns `true` if this value is a power of the given base, and `false`+  /// otherwise.+  ///+  /// For two integers *a* and *b*, *a* is a power of *b* if *a* is equal to+  /// any repeated multiplication of *b*. For example, *16* is a power of *2*+  /// because _16 = 2 * 2 * 2 * 2_. *-27* is a power of *-3* because+  /// _-27 = -3 * -3 * -3_. *1* is a power of everything because any number to+  /// the zero power is one.

/// One is a power of everything because any number to the zero power is one.

This is not exactly right; one is a power of everything because the empty product is one because one is the multiplicative identity. "Any number to the zero power is one" also follows from the convention for the empty product. I'm not sure how far down this rabbit hole the comment actually needs to go, however =)

dingobye

comment created time in a month

PullRequestReviewEvent

Pull request review commentapple/swift

[SE-0288] [stdlib] Adding isPower(of:) to BinaryInteger

 extension BinaryInteger {     return self.magnitude % other.magnitude == 0   } +  /// Returns `true` if this value is a power of the given base, and `false`+  /// otherwise.+  ///+  /// For two integers *a* and *b*, *a* is a power of *b* if *a* is equal to+  /// any repeated multiplication of *b*. For example, *16* is a power of *2*+  /// because _16 = 2 * 2 * 2 * 2_. *-27* is a power of *-3* because+  /// _-27 = -3 * -3 * -3_. *1* is a power of everything because any number to+  /// the zero power is one.+  ///+  /// For the corner case where base is zero, `x.isPower(of: 0)` is `true` if+  /// `x` is either zero or one, and `false` otherwise.+  ///+  /// - Parameter base: The base value to test.+  @inlinable+  public func isPower(of base: Self) -> Bool {+    // Fast path when base is one of the common cases.+    if base == 2 { return self._isPowerOfTwo }+    if base == 10 { return self._isPowerOfTen }+    if base._isPowerOfTwo { return self._isPowerOf(powerOfTwo: base) }+    // Slow path for other bases.+    return self._slowIsPower(of: base)+  }++  /// Returns `true` iff `self` is a power of two.+  ///+  /// This serves as a fast path for `isPower(of:)` when the input base is two.+  @inlinable+  internal var _isPowerOfTwo: Bool {+    let words = self.words+    guard !words.isEmpty else { return false }++    // If the value is represented in a single word, perform the classic check.+    if words.count == 1 {+      return self > 0 && self & (self - 1) == 0+    }++    // Return false if it is negative.  Here we only need to check the most+    // significant word (i.e. the last element of `words`).+    if Self.isSigned && Int(bitPattern: words.last!) < 0 {+      return false+    }++    // Check if there is exactly one non-zero word and it is a power of two.+    var found = false+    for word in words {+      if word != 0 {+        if found || word & (word - 1) != 0 { return false }+        found = true+      }+    }+    return found+  }++  /// Returns `true` iff `self` is a power of the given `base`, which itself is+  /// a power of two.+  ///+  /// This serves as a fast path for `isPower(of:)` when the input base itself+  /// is a power of two.+  @inlinable+  internal func _isPowerOf(powerOfTwo base: Self) -> Bool {+    _precondition(base._isPowerOfTwo)+    guard self._isPowerOfTwo else { return false }+    return self.trailingZeroBitCount.isMultiple(of: base.trailingZeroBitCount)+  }++  /// Returns `true` iff `self` is a power of ten.+  ///+  /// This serves as a fast path for `isPower(of:)` when the input base is ten.+  @usableFromInline+  internal var _isPowerOfTen: Bool {+    let exponent = self.trailingZeroBitCount+    switch exponent {+    case 0:  return self == 1 as UInt8+    case 1:  return self == 10 as UInt8+    case 2:  return self == 100 as UInt8+    case 3:  return self == 1000 as UInt16+    case 4:  return self == 10000 as UInt16+    case 5:  return self == 100000 as UInt32+    case 6:  return self == 1000000 as UInt32+    case 7:  return self == 10000000 as UInt32+    case 8:  return self == 100000000 as UInt32+    case 9:  return self == 1000000000 as UInt32+    case 10: return self == 10000000000 as UInt64+    case 11: return self == 100000000000 as UInt64+    case 12: return self == 1000000000000 as UInt64+    case 13: return self == 10000000000000 as UInt64+    case 14: return self == 100000000000000 as UInt64+    case 15: return self == 1000000000000000 as UInt64+    case 16: return self == 10000000000000000 as UInt64+    case 17: return self == 100000000000000000 as UInt64+    case 18: return self == 1000000000000000000 as UInt64+    case 19: return self == 10000000000000000000 as UInt64+    default:+      // If this is 64-bit or less we can't have a higher power of 10+      if self.bitWidth <= 64 { return false }++      // Quickly check if parts of the bit pattern fits the power of 10.+      //+      // 10^0                                     1+      // 10^1                                  1_01_0+      // 10^2                               1_10_01_00+      // 10^3                             111_11_01_000+      // 10^4                          100111_00_01_0000+      // 10^5                        11000011_01_01_00000+      // 10^6                      1111010000_10_01_000000+      // 10^7                   1001100010010_11_01_0000000+      // 10^8                 101111101011110_00_01_00000000+      // 10^9               11101110011010110_01_01_000000000+      // 10^10           10010101000000101111_10_01_0000000000+      // ...+      // Column 1 is some "gibberish", which cannot be checked easily+      // Column 2 is always the last two bits of the exponent+      // Column 3 is always 01+      // Column 4 is the trailing zeros, in equal number to the exponent value+      //+      // We check if Column 2 matches the last two bits of the exponent and+      // Column 3 matches 0b01.+      guard (self >> exponent)._lowWord & 0b1111 ==+        ((exponent << 2) | 0b01) & 0b1111 else { return false }++      // Now time for the slow path.+      return self._slowIsPower(of: 10)+    }+  }++  /// Returns `true` iff `self` is a power of the given `base`.+  ///+  /// This serves as the slow path for `isPower(of:)`; it is based on a generic+  /// implementation that works for any input `base`.+  @usableFromInline+  internal func _slowIsPower(of base: Self) -> Bool {+    // If self is 1 (i.e. any base to the zero power), return true.+    if self == 1 { return true }++    // Here if base is 0, 1 or -1, return true iff self equals base.+    if base.magnitude <= 1 { return self == base }++    // At this point, we have base.magnitude >= 2. Repeatedly perform+    // multiplication by a factor of base, and check if it can equal self.

The comment here doesn't match the implementation. Please update.

dingobye

comment created time in a month

PullRequestReviewEvent

pull request commentapple/swift

[SE-0288] [stdlib] Adding isPower(of:) to BinaryInteger

@swift-ci Please test source compatibility

dingobye

comment created time in a month

pull request commentapple/swift

[SE-0288] [stdlib] Adding isPower(of:) to BinaryInteger

@swift-ci test

dingobye

comment created time in a month

push eventapple/swift-numerics

Stephen Canon

commit sha 0f8ef268d01fe0e77dcb8da46a5aa64590aa9abf

Remove muladdf16 for now.

view details

Stephen Canon

commit sha 3d7462a834b58b10b1af4b1a1e0eeb784835681b

Merge pull request #148 from stephentyrone/remove-f16-muladd Remove muladdf16 for now.

view details

Stephen Canon

commit sha e07b39453b883f554f1154eedeecd948c11d5888

Swap availability for #if check on Float16.

view details

Stephen Canon

commit sha 6b24333510e9044cf4716a07bed65eeed6bc6393

Merge pull request #157 from stephentyrone/float16-availability-redux Swap availability for #if check on Float16.

view details

Steve (Numerics) Canon

commit sha e20b32d40fbc8abad902b902261afb0244a44c55

Initial pass over implementing ElementaryFunctions for Complex.

view details

Stephen Canon

commit sha 6d9de5d4ce8c21749f9fb1cdedea39615738dfd7

Updates to resync with changes on master. - Renamed scaled/unscaled to multiplied/divided - Adopted new Real module name - Adopted expMinusOne, log(onePlus:) names

view details

Stephen Canon

commit sha 2179fa1f828b60f3699756d461aa16dc17f85148

Rename some tests to reflect what they actually do.

view details

Stephen Canon

commit sha 09beddce470c9ccc9ae57e17f582f1d8570f9ac8

WIP on complex elementary functions. Rebased on master, then cleaned up exp and expm1. New algorithm for expm1 that gives good componentwise accuracy as well as normwise. I _think_ that this is fundamentally new; I can't recall seeing it anywhere before, though it's simple enough that I expect someone has thought of it before. Also beefed up testing for exp and expm1. Left sketches of log/pow/sqrt/root in place, though I'm still working on filling out the testing for those.

view details

Stephen Canon

commit sha 5f408c012154b73112b9db837d29b84fd00ff453

Cleanup.

view details

Stephen Canon

commit sha 4798b682032a32a8c8dc2cd1993f1dd4776c4b5c

Refactor test support to remove XCTest dependency.

view details

Stephen Canon

commit sha efbe11a73418f6707b58086ef8e35044b8793c8a

Fix typo expMinusOne/exp in near-overflow check.

view details

Stephen Canon

commit sha 0b2dc469eda2c91c0091f56be7b1eaa4d5159b86

Moved sampling-based tests out of unit and into an exectuable target.

view details

Stephen Canon

commit sha 1cbb94ac717415450ee64ed0cd0b040d5e108460

First pass over hyperbolics and trig functions for Complex.

view details

Stephen Canon

commit sha ed8fc21f1e74633dd6a34a38110decdd6f0b9f02

Add TODO for algorithmic improvements on tanh.

view details

Stephen Canon

commit sha af19aec6ff4582378f178909aa364c32381bc894

WIP

view details

Stephen Canon

commit sha 209a794eb63c70e96d8c9deea96ffcfb0066a3e4

Initial implementation of log(onePlus:)

view details

Stephen Canon

commit sha 754cbd9e2e16799afcc3690a16eb125d97343ab5

Merge branch 'complex-elfns' of github.com:stephentyrone/swift-numerics into complex-elfns

view details

push time in a month

push eventstephentyrone/swift-numerics

Stephen Canon

commit sha 0f8ef268d01fe0e77dcb8da46a5aa64590aa9abf

Remove muladdf16 for now.

view details

Stephen Canon

commit sha 3d7462a834b58b10b1af4b1a1e0eeb784835681b

Merge pull request #148 from stephentyrone/remove-f16-muladd Remove muladdf16 for now.

view details

Stephen Canon

commit sha e07b39453b883f554f1154eedeecd948c11d5888

Swap availability for #if check on Float16.

view details

Stephen Canon

commit sha 6b24333510e9044cf4716a07bed65eeed6bc6393

Merge pull request #157 from stephentyrone/float16-availability-redux Swap availability for #if check on Float16.

view details

Steve (Numerics) Canon

commit sha e20b32d40fbc8abad902b902261afb0244a44c55

Initial pass over implementing ElementaryFunctions for Complex.

view details

Stephen Canon

commit sha 6d9de5d4ce8c21749f9fb1cdedea39615738dfd7

Updates to resync with changes on master. - Renamed scaled/unscaled to multiplied/divided - Adopted new Real module name - Adopted expMinusOne, log(onePlus:) names

view details

Stephen Canon

commit sha 2179fa1f828b60f3699756d461aa16dc17f85148

Rename some tests to reflect what they actually do.

view details

Stephen Canon

commit sha 09beddce470c9ccc9ae57e17f582f1d8570f9ac8

WIP on complex elementary functions. Rebased on master, then cleaned up exp and expm1. New algorithm for expm1 that gives good componentwise accuracy as well as normwise. I _think_ that this is fundamentally new; I can't recall seeing it anywhere before, though it's simple enough that I expect someone has thought of it before. Also beefed up testing for exp and expm1. Left sketches of log/pow/sqrt/root in place, though I'm still working on filling out the testing for those.

view details

Stephen Canon

commit sha 5f408c012154b73112b9db837d29b84fd00ff453

Cleanup.

view details

Stephen Canon

commit sha 4798b682032a32a8c8dc2cd1993f1dd4776c4b5c

Refactor test support to remove XCTest dependency.

view details

Stephen Canon

commit sha efbe11a73418f6707b58086ef8e35044b8793c8a

Fix typo expMinusOne/exp in near-overflow check.

view details

Stephen Canon

commit sha 0b2dc469eda2c91c0091f56be7b1eaa4d5159b86

Moved sampling-based tests out of unit and into an exectuable target.

view details

Stephen Canon

commit sha 1cbb94ac717415450ee64ed0cd0b040d5e108460

First pass over hyperbolics and trig functions for Complex.

view details

Stephen Canon

commit sha ed8fc21f1e74633dd6a34a38110decdd6f0b9f02

Add TODO for algorithmic improvements on tanh.

view details

Stephen Canon

commit sha af19aec6ff4582378f178909aa364c32381bc894

WIP

view details

Stephen Canon

commit sha 209a794eb63c70e96d8c9deea96ffcfb0066a3e4

Initial implementation of log(onePlus:)

view details

Stephen Canon

commit sha 754cbd9e2e16799afcc3690a16eb125d97343ab5

Merge branch 'complex-elfns' of github.com:stephentyrone/swift-numerics into complex-elfns

view details

push time in a month

pull request commentapple/swift

Floating point random benchmark

Seems reasonable to me!

NevinBR

comment created time in a month

pull request commentapple/swift

Floating point random benchmark

Okay, I’ve added benchmarks for those ranges.

Thank you!

I also notice that most of these functions are identical except for the range, the RNG, and the number of iterations. So I’m thinking of making a helper function to avoid the repetition. I’m not super familiar with benchmarking though—is there any reason I shouldn’t do that?

I think that's perfectly reasonable. Do make sure that it doesn't fall off a performance cliff, since we want to be benchmarking the RNG and transform, not the benchmark overhead, but I don't expect that it will.

NevinBR

comment created time in a month

delete branch stephentyrone/swift

delete branch : overflow-underflow-nonnil

delete time in a month

PR closed apple/swift

Reviewers
Change the overflow behavior of floating-point inits from String

All other floating-point inits round out-of-range inputs to the nearest representable value. The conversions from string currently do not match this behavior, and return nil instead. This change makes it so only invalid character sequences produce nil; with overflow producing infinity and underflow producing zero, matching the behavior of literals.

Fixes rdar://problem/36990878

+8 -20

15 comments

3 changed files

stephentyrone

pr closed time in a month

delete branch stephentyrone/swift-numerics

delete branch : master

delete time in a month

create barnchstephentyrone/swift-numerics

branch : main

created branch time in a month

create barnchapple/swift-numerics

branch : main

created branch time in a month

push eventstephentyrone/swift-numerics

Stephen Canon

commit sha 2d2c144808c13bd2e9a98476cc87de8e75306f03

Fixup tests borked by bad merge.

view details

push time in a month

push eventstephentyrone/swift-numerics

Stephen Canon

commit sha 6d396dfb4497e2d19c15ab671b6dd1dc47f7c0e5

First pass over hyperbolics and trig functions for Complex.

view details

Stephen Canon

commit sha beb85076a5ed5562c09474f273665af291e1b0fc

Add TODO for algorithmic improvements on tanh.

view details

Stephen Canon

commit sha a76404b263a8ddba34a9f3e91f7271c0d2c13777

WIP

view details

Stephen Canon

commit sha 0f02c6585465356cf5ba4d0937221dcc81fd7690

Initial implementation of log(onePlus:)

view details

Stephen Canon

commit sha 21282166fa3bc0102fb2454863c6ddeab988fed1

Merge pull request #152 from stephentyrone/complex-trig First pass over hyperbolics and trig functions for Complex.

view details

push time in a month

push eventstephentyrone/swift-numerics

Stephen Canon

commit sha 36bc51fc293f2a24ef5089b4276fbd964438d32a

Remove muladdf16 for now.

view details

Stephen Canon

commit sha 4deabc9cba7850d2aa0d186fc9deab51b13490f4

Swap availability for #if check on Float16.

view details

Stephen Canon

commit sha 51db622dcaf5578a10c21170125d5f8104eac3f2

Initial implementation of log(onePlus:)

view details

Stephen Canon

commit sha e6999a1d4185393072a06ce514da9e9b96777096

Fix typo.

view details

Stephen Canon

commit sha a048edfbf55e63535558390d660dc66ad9b5c095

Complex.log with good componentwise relative error Trying to better understand the problems with log1p led me to realize that they exist for log as well in the complex plane. So I reworked log using a novel approach, and now I'm going to circle around to log1p once more.

view details

Stephen Canon

commit sha 6fb9e4bfa3eb892f912c9e95d0975ddd56f0b122

WIP on complex elementary functions. Rebased on master, then cleaned up exp and expm1. New algorithm for expm1 that gives good componentwise accuracy as well as normwise. I _think_ that this is fundamentally new; I can't recall seeing it anywhere before, though it's simple enough that I expect someone has thought of it before. Also beefed up testing for exp and expm1. Left sketches of log/pow/sqrt/root in place, though I'm still working on filling out the testing for those.

view details

Stephen Canon

commit sha 21cc3d7bc949781745c08e9b337b17033e23ad19

Fix typo expMinusOne/exp in near-overflow check.

view details

Stephen Canon

commit sha 9671911ee640e2f25c7910481274166b28fd6d7a

Initial implementation of log(onePlus:)

view details

Stephen Canon

commit sha 4225c8b1d9fc771061cf67d08f0d8ac40822d806

Fix typo.

view details

Stephen Canon

commit sha 4494cea12b2e2343e32ed3dc055eb8a64a5dd136

Further WIP on log(onePlus:), more to be done.

view details

push time in a month

delete branch stephentyrone/swift-numerics

delete branch : complex-trig

delete time in a month

push eventapple/swift-numerics

Stephen Canon

commit sha 6d396dfb4497e2d19c15ab671b6dd1dc47f7c0e5

First pass over hyperbolics and trig functions for Complex.

view details

Stephen Canon

commit sha beb85076a5ed5562c09474f273665af291e1b0fc

Add TODO for algorithmic improvements on tanh.

view details

Stephen Canon

commit sha a76404b263a8ddba34a9f3e91f7271c0d2c13777

WIP

view details

Stephen Canon

commit sha 0f02c6585465356cf5ba4d0937221dcc81fd7690

Initial implementation of log(onePlus:)

view details

Stephen Canon

commit sha 21282166fa3bc0102fb2454863c6ddeab988fed1

Merge pull request #152 from stephentyrone/complex-trig First pass over hyperbolics and trig functions for Complex.

view details

push time in a month

PR merged apple/swift-numerics

First pass over hyperbolics and trig functions for Complex.

Also refactors exp and expMinusOne fairly incidentally.

+241 -75

0 comment

2 changed files

stephentyrone

pr closed time in a month

issue commentapple/swift-numerics

Real part of complex expMinusOne is bad when e^{-x} ~ cos y

Yup. This is a problem that no one has a good solution to yet. I have a few ideas, but haven't had time to sort through them.

As you suggest, the cosm1 factorization is strictly better than the expm1 factorization (it at least gets an absolute error bound for this case, which is why I'm using it).

riastradh

comment created time in a month

issue commentapple/swift-system

Question: why are @available directives commented out?

@Snowy1803 Note that System is included in those versions of the OSes (https://developer.apple.com/documentation/system).

BasThomas

comment created time in a month

Pull request review commentapple/swift-numerics

Add complex log(onePlus:), update log()

 extension Complex /*: ElementaryFunctions */ {     // If z is zero or infinite, the phase is undefined, so the result is     // the single exceptional value.     guard z.isFinite && !z.isZero else { return .infinity }-    // Otherwise, try computing lengthSquared; if the result is normal,-    // we can just take its log to get the real part of the result.-    let r2 = z.lengthSquared+    // Having eliminated non-finite values and zero, the imaginary part is+    // easy; it's just the phase, which is always computed with good+    // relative accuracy via atan2.     let θ = z.phase-    if r2.isNormal { return Complex(.log(r2)/2, θ) }-    // z is finite, but z.lengthSquared is not normal. Rescale and recompute.-    let w = z.divided(by: z.magnitude)-    return Complex(.log(z.magnitude) + .log(w.lengthSquared)/2, θ)-  }-  -  @inlinable-  public static func log(onePlus z: Complex) -> Complex {-    // Nevin proposed the idea for this implementation on the Swift forums:-    // https://forums.swift.org/t/elementaryfunctions-compliance-for-complex/37903/3+    // The real part of the result is trickier. In exact arithmetic, the+    // real part is just log |z|--many implementations of complex functions+    // simply use this expression as is. However, there are two problems+    // lurking here:+    //+    //   - length can overflow even when log(z) is finite.+    //+    //   - when length is close to 1, catastrophic cancellation is hidden+    //     in this expression. Consider, e.g. z = 1 + δi for small δ.+    //+    //     Because δ ≪ 1, |z| rounds to 1, and so log |z| produces zero.+    //     We can expand using Taylor series to see that the result should+    //     be:+    //+    //         log |z| = log √(1 + δ²)+    //                 = log(1 + δ²)/2+    //                 = δ²/2 + O(δ⁴)+    //+    //     So naively using log |z| results in a total loss of relative+    //     accuracy for this case. Note that this is _not_ constrained near+    //     a single point; it occurs everywhere close to the circle |z| = 1.+    //+    //     Note that this case still _does_ deliver a result with acceptable+    //     relative accuracy in the complex norm, because+    //+    //         Im(log z) ≈ δ ≫ δ²/2 ≈ Re(log z).     //-    // Here's a quick explainer on why it works: in exact arithmetic,+    // There are a number of ways to try to tackle this problem. I'll begin+    // with a simple one that solves the first issue, and _sometimes_ the+    // second, then analyze when it doesn't work for the second case.     //-    //      log(1+z) = (log |1+z|, atan2(y, 1+x))+    // To handle very large arguments without overflow, the standard+    // approach is to _rescale_ the problem. We can do this by finding+    // whichever of x and y has greater magnitude, and dividing through+    // by it. You can think of this as changing coordinates by reflections+    // so that we get a new value w = u + iv with |w| = |z| (and hence+    // Re(log w) = Re(log z), and 0 ≤ u, 0 ≤ v ≤ u.+    let u = max(z.x.magnitude, z.y.magnitude)+    let v = min(z.x.magnitude, z.y.magnitude)+    // Now expand out log |w|:     //-    // where x and y are the real and imaginary parts of z, respectively.+    //     log |w| = log(u² + v²)/2+    //             = log u + log(onePlus: (v/u)²)/2     //-    // The first thing to note is that the expression for the imaginary-    // part works fine as is. If cancellation occurs (because x ≈ -1),-    // then 1+x is exact, and so we have good componentwise relative-    // accuracy. Otherwise, x is bounded away from -1 and 1+x has good-    // relative accuracy, and therefore so does atan2(y, 1+x).+    // This looks promising! It handles overflow well, because log(u) is+    // finite for every finite u, and we have 0 ≤ v/u ≤ 1, so the second+    // term is bounded by 0 ≤ log(1 + (v/u)²)/2 ≤ (log 2)/2. It also+    // handles the example I gave above well: we have u = 1, v = δ, and     //-    // So the real part is the hard part (no surprise, just like expPlusOne).-    // Nevin's clever idea is simply to take advantage of the expansion:+    //     log(1) + log(onePlus: δ²)/2 = 0 + δ²/2     //-    //     Re(log 1+z) = (log 1+z + Conj(log 1+z))/2+    // as expected.     //-    // Log commutes with conjugation, so this becomes:+    // Unfortunately, it does not handle all points close to the unit+    // circle so well; it's easy to see why if we look at the two terms+    // that contribute to the result. Cancellation occurs when the result+    // is close to zero and the terms have opposing signs. By construction,+    // the second term is always positive, so the easiest observation is+    // that cancellation is only a problem for u < 1 (because otherwise+    // log u is also positive, and there can be no cancellation).+    //+    // We are not trying for sub-ulp accuracy, just a good relative error+    // bound, so for our purposes it suffices to have log u dominate the+    // result:+    if u >= 1 || u >= RealType._mulAdd(u,u,v*v) {+      let r = v / u+      return Complex(.log(u) + .log(onePlus: r*r)/2, θ)+    }+    // Here we're in the tricky case; cancellation is likely to occur.+    // Instead of the factorization used above, we will want to evaluate+    // log(onePlus: u² + v² - 1)/2. This all boils down to accurately+    // evaluating u² + v² - 1. To begin, calculate both squared terms+    // as exact head-tail products (u is guaranteed to be well scaled,+    // v may underflow, but if it does it doesn't matter, the u term is+    // all we need).+    let (a,b) = Augmented.twoProdFMA(u, u)+    let (c,d) = Augmented.twoProdFMA(v, v)+    // It would be nice if we could simply use a - 1, but unfortunately+    // we don't have a tight enough bound to guarantee that that expression+    // is exact; a may be as small as 1/4, so we could lose a single bit+    // to rounding if we did that.+    var (s,e) = Augmented.fastTwoSum(-1, a)+    // Now we are ready to assemble the result. If cancellation happens,+    // then |c| > |e| > |b|, |d|, so this assembly order is safe. It's+    // also possible that |c| and |d| are small, but if that happens then+    // there is no significant cancellation, and the exact assembly doesn't+    // matter.+    s = (s + c) + e + b + d+    return Complex(.log(onePlus: s)/2, θ)+  }+  +  @inlinable+  public static func log(onePlus z: Complex) -> Complex {+    // log(1+z) is basically only hard to compute close to the circle+    // |1+z| = 1; inside the circle the real part of the log is negative;+    // outside it positive. On the circle (which passes through 0, -1±i,+    // and -2), it is zero, so we need to be careful about cancellation.+    //+    // To begin, let's just see what domain z actually lies in.+    let r2 = (1 + z).lengthSquared+    // If |1+z| <= ½, we're well inside the circle (and close enough+    // to -1 that 1 + z is computed exactly. If |1+z| => 2, we're far+    // enough outside the circle that we can simply use log(1+z)--1+z+    // may round, but that rounding doesn't cause problematic error in+    // the final result.+    if 2*r2 <= 1 && !(r2 < 2) { return log(1 + z) }+    // Here we're in the annulus ½ < |1+z| < 2, so we need to be careful+    // about cancellation. Instead of computing the real part as+    // log(|1+z|), we use log(onePlus: 2x + |z|²)/2. This is a cute trick+    // that Nevin suggested on the swift forums, which works because:     //     //     Re(log 1+z) = (log 1+z + log 1+z̅)/2-    //                 = log((1+z)(1+z̅)/2+    //                 = log((1+z)(1+z̅))/2     //                 = log(1+z+z̅+zz̅)/2     //-    // This behaves well close to zero, because the z+z̅ term dominates-    // and is computed exactly. Away from zero, cancellation occurs near-    // the circle x(x+2) + y^2 = 1, but everywhere along this curve we-    // have |Im(log 1+z)| >= π/2, so the relative error in the complex-    // norm is well-controlled. We can take advantage of FMA to further-    // reduce the cancellation error and recover a good error bound.-    //-    // The other common implementation choice for log1p is Kahan's trick:+    // https://forums.swift.org/t/elementaryfunctions-compliance-for-complex/37903/3     //-    //     w := 1+z-    //     return z/(w-1) * log(w)+    // So now we just need to compute z+z̅+zz̅ == x(2+x) + y², carefully.+    // 2+x can round; we have -3 < x < 1, so we can compute a head-tail+    // sum easily. It's easiest to see why this is exact with a two-case+    // analysis:     //-    // But this actually doesn't do as well as Nevin's approach does,-    // and requires a complex division, which we want to avoid when we-    // can do so.-    var a = 2*z.x-    // We want to add the larger term first (contra usual guidance for-    // floating-point error optimization), because we're optimizing for-    // the catastrophic cancellation case; when that happens adding the-    // larger term via FMA is always exact. When cancellation doesn't-    // happen, the simple relative error bound carries through the-    // rest of the computation.-    let large = max(z.x.magnitude, z.y.magnitude)-    let small = min(z.x.magnitude, z.y.magnitude)-    a.addProduct(large, large)-    a.addProduct(small, small)-    // If r2 overflowed, then |z| ≫ 1, and so log(1+z) = log(z).-    guard a.isFinite else { return log(z) }-    // Unlike log(z), we do not need to worry about what happens if a-    // underflows.-    return Complex(-      RealType.log(onePlus: a)/2,-      RealType.atan2(y: z.y, x: 1+z.x)-    )+    //  	If x is in [-3, -1], everything is exact because of Sterbenz.+    //    If x is in (-1, +1], 2 + x will generally round, but 2 > |x|,+    //      so no sorting is needed to order the tail computation.+    return log(1+z)

(i.e. reviewing log(onePlus:) is wasted effort, I just hacked a merge together so it would build and I could do some testing on log( ).)

stephentyrone

comment created time in a month

PullRequestReviewEvent

Pull request review commentapple/swift-numerics

Add complex log(onePlus:), update log()

 extension Complex /*: ElementaryFunctions */ {     // If z is zero or infinite, the phase is undefined, so the result is     // the single exceptional value.     guard z.isFinite && !z.isZero else { return .infinity }-    // Otherwise, try computing lengthSquared; if the result is normal,-    // we can just take its log to get the real part of the result.-    let r2 = z.lengthSquared+    // Having eliminated non-finite values and zero, the imaginary part is+    // easy; it's just the phase, which is always computed with good+    // relative accuracy via atan2.     let θ = z.phase-    if r2.isNormal { return Complex(.log(r2)/2, θ) }-    // z is finite, but z.lengthSquared is not normal. Rescale and recompute.-    let w = z.divided(by: z.magnitude)-    return Complex(.log(z.magnitude) + .log(w.lengthSquared)/2, θ)-  }-  -  @inlinable-  public static func log(onePlus z: Complex) -> Complex {-    // Nevin proposed the idea for this implementation on the Swift forums:-    // https://forums.swift.org/t/elementaryfunctions-compliance-for-complex/37903/3+    // The real part of the result is trickier. In exact arithmetic, the+    // real part is just log |z|--many implementations of complex functions+    // simply use this expression as is. However, there are two problems+    // lurking here:+    //+    //   - length can overflow even when log(z) is finite.+    //+    //   - when length is close to 1, catastrophic cancellation is hidden+    //     in this expression. Consider, e.g. z = 1 + δi for small δ.+    //+    //     Because δ ≪ 1, |z| rounds to 1, and so log |z| produces zero.+    //     We can expand using Taylor series to see that the result should+    //     be:+    //+    //         log |z| = log √(1 + δ²)+    //                 = log(1 + δ²)/2+    //                 = δ²/2 + O(δ⁴)+    //+    //     So naively using log |z| results in a total loss of relative+    //     accuracy for this case. Note that this is _not_ constrained near+    //     a single point; it occurs everywhere close to the circle |z| = 1.+    //+    //     Note that this case still _does_ deliver a result with acceptable+    //     relative accuracy in the complex norm, because+    //+    //         Im(log z) ≈ δ ≫ δ²/2 ≈ Re(log z).     //-    // Here's a quick explainer on why it works: in exact arithmetic,+    // There are a number of ways to try to tackle this problem. I'll begin+    // with a simple one that solves the first issue, and _sometimes_ the+    // second, then analyze when it doesn't work for the second case.     //-    //      log(1+z) = (log |1+z|, atan2(y, 1+x))+    // To handle very large arguments without overflow, the standard+    // approach is to _rescale_ the problem. We can do this by finding+    // whichever of x and y has greater magnitude, and dividing through+    // by it. You can think of this as changing coordinates by reflections+    // so that we get a new value w = u + iv with |w| = |z| (and hence+    // Re(log w) = Re(log z), and 0 ≤ u, 0 ≤ v ≤ u.+    let u = max(z.x.magnitude, z.y.magnitude)+    let v = min(z.x.magnitude, z.y.magnitude)+    // Now expand out log |w|:     //-    // where x and y are the real and imaginary parts of z, respectively.+    //     log |w| = log(u² + v²)/2+    //             = log u + log(onePlus: (v/u)²)/2     //-    // The first thing to note is that the expression for the imaginary-    // part works fine as is. If cancellation occurs (because x ≈ -1),-    // then 1+x is exact, and so we have good componentwise relative-    // accuracy. Otherwise, x is bounded away from -1 and 1+x has good-    // relative accuracy, and therefore so does atan2(y, 1+x).+    // This looks promising! It handles overflow well, because log(u) is+    // finite for every finite u, and we have 0 ≤ v/u ≤ 1, so the second+    // term is bounded by 0 ≤ log(1 + (v/u)²)/2 ≤ (log 2)/2. It also+    // handles the example I gave above well: we have u = 1, v = δ, and     //-    // So the real part is the hard part (no surprise, just like expPlusOne).-    // Nevin's clever idea is simply to take advantage of the expansion:+    //     log(1) + log(onePlus: δ²)/2 = 0 + δ²/2     //-    //     Re(log 1+z) = (log 1+z + Conj(log 1+z))/2+    // as expected.     //-    // Log commutes with conjugation, so this becomes:+    // Unfortunately, it does not handle all points close to the unit+    // circle so well; it's easy to see why if we look at the two terms+    // that contribute to the result. Cancellation occurs when the result+    // is close to zero and the terms have opposing signs. By construction,+    // the second term is always positive, so the easiest observation is+    // that cancellation is only a problem for u < 1 (because otherwise+    // log u is also positive, and there can be no cancellation).+    //+    // We are not trying for sub-ulp accuracy, just a good relative error+    // bound, so for our purposes it suffices to have log u dominate the+    // result:+    if u >= 1 || u >= RealType._mulAdd(u,u,v*v) {+      let r = v / u+      return Complex(.log(u) + .log(onePlus: r*r)/2, θ)+    }+    // Here we're in the tricky case; cancellation is likely to occur.+    // Instead of the factorization used above, we will want to evaluate+    // log(onePlus: u² + v² - 1)/2. This all boils down to accurately+    // evaluating u² + v² - 1. To begin, calculate both squared terms+    // as exact head-tail products (u is guaranteed to be well scaled,+    // v may underflow, but if it does it doesn't matter, the u term is+    // all we need).+    let (a,b) = Augmented.twoProdFMA(u, u)+    let (c,d) = Augmented.twoProdFMA(v, v)+    // It would be nice if we could simply use a - 1, but unfortunately+    // we don't have a tight enough bound to guarantee that that expression+    // is exact; a may be as small as 1/4, so we could lose a single bit+    // to rounding if we did that.+    var (s,e) = Augmented.fastTwoSum(-1, a)+    // Now we are ready to assemble the result. If cancellation happens,+    // then |c| > |e| > |b|, |d|, so this assembly order is safe. It's+    // also possible that |c| and |d| are small, but if that happens then+    // there is no significant cancellation, and the exact assembly doesn't+    // matter.+    s = (s + c) + e + b + d+    return Complex(.log(onePlus: s)/2, θ)+  }+  +  @inlinable+  public static func log(onePlus z: Complex) -> Complex {+    // log(1+z) is basically only hard to compute close to the circle+    // |1+z| = 1; inside the circle the real part of the log is negative;+    // outside it positive. On the circle (which passes through 0, -1±i,+    // and -2), it is zero, so we need to be careful about cancellation.+    //+    // To begin, let's just see what domain z actually lies in.+    let r2 = (1 + z).lengthSquared+    // If |1+z| <= ½, we're well inside the circle (and close enough+    // to -1 that 1 + z is computed exactly. If |1+z| => 2, we're far+    // enough outside the circle that we can simply use log(1+z)--1+z+    // may round, but that rounding doesn't cause problematic error in+    // the final result.+    if 2*r2 <= 1 && !(r2 < 2) { return log(1 + z) }+    // Here we're in the annulus ½ < |1+z| < 2, so we need to be careful+    // about cancellation. Instead of computing the real part as+    // log(|1+z|), we use log(onePlus: 2x + |z|²)/2. This is a cute trick+    // that Nevin suggested on the swift forums, which works because:     //     //     Re(log 1+z) = (log 1+z + log 1+z̅)/2-    //                 = log((1+z)(1+z̅)/2+    //                 = log((1+z)(1+z̅))/2     //                 = log(1+z+z̅+zz̅)/2     //-    // This behaves well close to zero, because the z+z̅ term dominates-    // and is computed exactly. Away from zero, cancellation occurs near-    // the circle x(x+2) + y^2 = 1, but everywhere along this curve we-    // have |Im(log 1+z)| >= π/2, so the relative error in the complex-    // norm is well-controlled. We can take advantage of FMA to further-    // reduce the cancellation error and recover a good error bound.-    //-    // The other common implementation choice for log1p is Kahan's trick:+    // https://forums.swift.org/t/elementaryfunctions-compliance-for-complex/37903/3     //-    //     w := 1+z-    //     return z/(w-1) * log(w)+    // So now we just need to compute z+z̅+zz̅ == x(2+x) + y², carefully.+    // 2+x can round; we have -3 < x < 1, so we can compute a head-tail+    // sum easily. It's easiest to see why this is exact with a two-case+    // analysis:     //-    // But this actually doesn't do as well as Nevin's approach does,-    // and requires a complex division, which we want to avoid when we-    // can do so.-    var a = 2*z.x-    // We want to add the larger term first (contra usual guidance for-    // floating-point error optimization), because we're optimizing for-    // the catastrophic cancellation case; when that happens adding the-    // larger term via FMA is always exact. When cancellation doesn't-    // happen, the simple relative error bound carries through the-    // rest of the computation.-    let large = max(z.x.magnitude, z.y.magnitude)-    let small = min(z.x.magnitude, z.y.magnitude)-    a.addProduct(large, large)-    a.addProduct(small, small)-    // If r2 overflowed, then |z| ≫ 1, and so log(1+z) = log(z).-    guard a.isFinite else { return log(z) }-    // Unlike log(z), we do not need to worry about what happens if a-    // underflows.-    return Complex(-      RealType.log(onePlus: a)/2,-      RealType.atan2(y: z.y, x: 1+z.x)-    )+    //  	If x is in [-3, -1], everything is exact because of Sterbenz.+    //    If x is in (-1, +1], 2 + x will generally round, but 2 > |x|,+    //      so no sorting is needed to order the tail computation.+    return log(1+z)

Yeah, I'm revising it to handle some other cases, but got side-tracked into improving log( ) first.

stephentyrone

comment created time in a month

PullRequestReviewEvent

push eventstephentyrone/swift-numerics

Stephen Canon

commit sha 0f8ef268d01fe0e77dcb8da46a5aa64590aa9abf

Remove muladdf16 for now.

view details

Stephen Canon

commit sha 3d7462a834b58b10b1af4b1a1e0eeb784835681b

Merge pull request #148 from stephentyrone/remove-f16-muladd Remove muladdf16 for now.

view details

Stephen Canon

commit sha e07b39453b883f554f1154eedeecd948c11d5888

Swap availability for #if check on Float16.

view details

Stephen Canon

commit sha 6b24333510e9044cf4716a07bed65eeed6bc6393

Merge pull request #157 from stephentyrone/float16-availability-redux Swap availability for #if check on Float16.

view details

Steve (Numerics) Canon

commit sha 23b38ea0e431985ce64b4a9c8befe94cd74cd699

Initial pass over implementing ElementaryFunctions for Complex.

view details

Stephen Canon

commit sha 446ab158cf84cba001934e3d8c62aa8d5a9135dc

Updates to resync with changes on master. - Renamed scaled/unscaled to multiplied/divided - Adopted new Real module name - Adopted expMinusOne, log(onePlus:) names

view details

Stephen Canon

commit sha 095570738373c038b3ef4df09908a2ce470f91fc

Rename some tests to reflect what they actually do.

view details

Stephen Canon

commit sha 23ac35d928d01afc695b0e39d6e70f254404a1c5

WIP on complex elementary functions. Rebased on master, then cleaned up exp and expm1. New algorithm for expm1 that gives good componentwise accuracy as well as normwise. I _think_ that this is fundamentally new; I can't recall seeing it anywhere before, though it's simple enough that I expect someone has thought of it before. Also beefed up testing for exp and expm1. Left sketches of log/pow/sqrt/root in place, though I'm still working on filling out the testing for those.

view details

Stephen Canon

commit sha f624f4a37b7d83d554973a16c9a0091dbe16464b

Cleanup.

view details

Stephen Canon

commit sha 9f45eec186bbe04ba58891b7568fd86af3e59e9a

Refactor test support to remove XCTest dependency.

view details

Stephen Canon

commit sha 5727b7aa4601293322e142fd28d1e80db2727363

Fix typo expMinusOne/exp in near-overflow check.

view details

Stephen Canon

commit sha daf8db95c053bd040c8ec22c01b204213a86fc19

Moved sampling-based tests out of unit and into an exectuable target.

view details

Stephen Canon

commit sha b05c2cfe36a1169096e3fe0d56ea511105fa957c

Initial implementation of log(onePlus:)

view details

Stephen Canon

commit sha 82fb403d0c2bfa5257ce94535548d6d60ff54b78

Fix typo.

view details

Stephen Canon

commit sha c1081acba5d6744741217bdbb203736c9be5b846

Complex.log with good componentwise relative error Trying to better understand the problems with log1p led me to realize that they exist for log as well in the complex plane. So I reworked log using a novel approach, and now I'm going to circle around to log1p once more.

view details

Stephen Canon

commit sha e52a603384b0a70e62012c507a2c8267ca121141

Merge branch 'complex-log1p' of github.com:stephentyrone/swift-numerics into complex-log1p

view details

push time in a month

delete branch apple/swift-numerics

delete branch : swift-5.3

delete time in a month

issue closedapple/swift-numerics

Unable to Compile with Xcode 12 (12A7209)

I'm running Catalina 10.15.6 (19G2021), yet because of Float16 I'm unable to compile swift-numerics when targeting macOS.

Swift compiler is reporting the correct version Apple Swift version 5.3 (swiftlang-1200.0.29.2 clang-1200.0.30.1), yet I don't understand why it's trying to compile Float16 when it's explicitly marked as unavailable for macOS. Building for an iOS device or the iOS simulator works fine. I tried using swift-numerics with a sample Xcode project for a macOS app as well but it fails with the same issues.

Any idea what's up?

swift build

» xcrun swift build
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:18:11: error: cannot find type 'Float16' in scope
extension Float16: Real {
          ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:20:43: error: cannot find type 'Float16' in scope
  public static func cos(_ x: Float16) -> Float16 {
                                          ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:20:31: error: cannot find type 'Float16' in scope
  public static func cos(_ x: Float16) -> Float16 {
                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:25:43: error: cannot find type 'Float16' in scope
  public static func sin(_ x: Float16) -> Float16 {
                                          ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:25:31: error: cannot find type 'Float16' in scope
  public static func sin(_ x: Float16) -> Float16 {
                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:30:43: error: cannot find type 'Float16' in scope
  public static func tan(_ x: Float16) -> Float16 {
                                          ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:30:31: error: cannot find type 'Float16' in scope
  public static func tan(_ x: Float16) -> Float16 {
                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:35:44: error: cannot find type 'Float16' in scope
  public static func acos(_ x: Float16) -> Float16 {
                                           ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:35:32: error: cannot find type 'Float16' in scope
  public static func acos(_ x: Float16) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:40:44: error: cannot find type 'Float16' in scope
  public static func asin(_ x: Float16) -> Float16 {
                                           ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:40:32: error: cannot find type 'Float16' in scope
  public static func asin(_ x: Float16) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:45:44: error: cannot find type 'Float16' in scope
  public static func atan(_ x: Float16) -> Float16 {
                                           ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:45:32: error: cannot find type 'Float16' in scope
  public static func atan(_ x: Float16) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:50:44: error: cannot find type 'Float16' in scope
  public static func cosh(_ x: Float16) -> Float16 {
                                           ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:50:32: error: cannot find type 'Float16' in scope
  public static func cosh(_ x: Float16) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:55:44: error: cannot find type 'Float16' in scope
  public static func sinh(_ x: Float16) -> Float16 {
                                           ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:55:32: error: cannot find type 'Float16' in scope
  public static func sinh(_ x: Float16) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:60:44: error: cannot find type 'Float16' in scope
  public static func tanh(_ x: Float16) -> Float16 {
                                           ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:60:32: error: cannot find type 'Float16' in scope
  public static func tanh(_ x: Float16) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:65:45: error: cannot find type 'Float16' in scope
  public static func acosh(_ x: Float16) -> Float16 {
                                            ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:65:33: error: cannot find type 'Float16' in scope
  public static func acosh(_ x: Float16) -> Float16 {
                                ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:70:45: error: cannot find type 'Float16' in scope
  public static func asinh(_ x: Float16) -> Float16 {
                                            ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:70:33: error: cannot find type 'Float16' in scope
  public static func asinh(_ x: Float16) -> Float16 {
                                ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:75:45: error: cannot find type 'Float16' in scope
  public static func atanh(_ x: Float16) -> Float16 {
                                            ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:75:33: error: cannot find type 'Float16' in scope
  public static func atanh(_ x: Float16) -> Float16 {
                                ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:80:43: error: cannot find type 'Float16' in scope
  public static func exp(_ x: Float16) -> Float16 {
                                          ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:80:31: error: cannot find type 'Float16' in scope
  public static func exp(_ x: Float16) -> Float16 {
                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:85:51: error: cannot find type 'Float16' in scope
  public static func expMinusOne(_ x: Float16) -> Float16 {
                                                  ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:85:39: error: cannot find type 'Float16' in scope
  public static func expMinusOne(_ x: Float16) -> Float16 {
                                      ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:90:43: error: cannot find type 'Float16' in scope
  public static func log(_ x: Float16) -> Float16 {
                                          ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:90:31: error: cannot find type 'Float16' in scope
  public static func log(_ x: Float16) -> Float16 {
                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:95:49: error: cannot find type 'Float16' in scope
  public static func log(onePlus x: Float16) -> Float16 {
                                                ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:95:37: error: cannot find type 'Float16' in scope
  public static func log(onePlus x: Float16) -> Float16 {
                                    ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:100:43: error: cannot find type 'Float16' in scope
  public static func erf(_ x: Float16) -> Float16 {
                                          ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:100:31: error: cannot find type 'Float16' in scope
  public static func erf(_ x: Float16) -> Float16 {
                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:105:44: error: cannot find type 'Float16' in scope
  public static func erfc(_ x: Float16) -> Float16 {
                                           ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:105:32: error: cannot find type 'Float16' in scope
  public static func erfc(_ x: Float16) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:110:44: error: cannot find type 'Float16' in scope
  public static func exp2(_ x: Float16) -> Float16 {
                                           ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:110:32: error: cannot find type 'Float16' in scope
  public static func exp2(_ x: Float16) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:115:45: error: cannot find type 'Float16' in scope
  public static func exp10(_ x: Float16) -> Float16 {
                                            ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:115:33: error: cannot find type 'Float16' in scope
  public static func exp10(_ x: Float16) -> Float16 {
                                ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:120:59: error: cannot find type 'Float16' in scope
  public static func hypot(_ x: Float16, _ y: Float16) -> Float16 {
                                                          ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:120:33: error: cannot find type 'Float16' in scope
  public static func hypot(_ x: Float16, _ y: Float16) -> Float16 {
                                ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:120:47: error: cannot find type 'Float16' in scope
  public static func hypot(_ x: Float16, _ y: Float16) -> Float16 {
                                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:128:45: error: cannot find type 'Float16' in scope
  public static func gamma(_ x: Float16) -> Float16 {
                                            ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:128:33: error: cannot find type 'Float16' in scope
  public static func gamma(_ x: Float16) -> Float16 {
                                ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:133:44: error: cannot find type 'Float16' in scope
  public static func log2(_ x: Float16) -> Float16 {
                                           ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:133:32: error: cannot find type 'Float16' in scope
  public static func log2(_ x: Float16) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:138:45: error: cannot find type 'Float16' in scope
  public static func log10(_ x: Float16) -> Float16 {
                                            ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:138:33: error: cannot find type 'Float16' in scope
  public static func log10(_ x: Float16) -> Float16 {
                                ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:143:57: error: cannot find type 'Float16' in scope
  public static func pow(_ x: Float16, _ y: Float16) -> Float16 {
                                                        ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:143:31: error: cannot find type 'Float16' in scope
  public static func pow(_ x: Float16, _ y: Float16) -> Float16 {
                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:143:45: error: cannot find type 'Float16' in scope
  public static func pow(_ x: Float16, _ y: Float16) -> Float16 {
                                            ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:148:53: error: cannot find type 'Float16' in scope
  public static func pow(_ x: Float16, _ n: Int) -> Float16 {
                                                    ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:148:31: error: cannot find type 'Float16' in scope
  public static func pow(_ x: Float16, _ n: Int) -> Float16 {
                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:160:54: error: cannot find type 'Float16' in scope
  public static func root(_ x: Float16, _ n: Int) -> Float16 {
                                                     ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:160:32: error: cannot find type 'Float16' in scope
  public static func root(_ x: Float16, _ n: Int) -> Float16 {
                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:165:55: error: cannot find type 'Float16' in scope
  public static func atan2(y: Float16, x: Float16) -> Float16 {
                                                      ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:165:31: error: cannot find type 'Float16' in scope
  public static func atan2(y: Float16, x: Float16) -> Float16 {
                              ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:165:43: error: cannot find type 'Float16' in scope
  public static func atan2(y: Float16, x: Float16) -> Float16 {
                                          ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:171:48: error: cannot find type 'Float16' in scope
  public static func logGamma(_ x: Float16) -> Float16 {
                                               ^~~~~~~
/Users/Adam/Downloads/swift-numerics/Sources/RealModule/Float16+Real.swift:171:36: error: cannot find type 'Float16' in scope
  public static func logGamma(_ x: Float16) -> Float16 {
                                   ^~~~~~~
[1/1] Compiling RealModule Float16+Real.swift

Xcode

CompileSwift normal x86_64 /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/Float16+Real.swift (in target 'RealModule' from project 'swift-numerics')
    cd /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -c /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/AlgebraicField.swift /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/ApproximateEquality.swift /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/Double+Real.swift /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/ElementaryFunctions.swift /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/Float+Real.swift -primary-file /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/Float16+Real.swift /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/Float80+Real.swift /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/Real.swift /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/RealFunctions.swift -emit-module-path /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/Objects-normal/x86_64/Float16+Real\~partial.swiftmodule -emit-module-doc-path /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/Objects-normal/x86_64/Float16+Real\~partial.swiftdoc -emit-module-source-info-path /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/Objects-normal/x86_64/Float16+Real\~partial.swiftsourceinfo -serialize-diagnostics-path /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/Objects-normal/x86_64/Float16+Real.dia -emit-dependencies-path /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/Objects-normal/x86_64/Float16+Real.d -emit-reference-dependencies-path /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/Objects-normal/x86_64/Float16+Real.swiftdeps -target x86_64-apple-macos10.10 -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -I /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Products/Debug -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib -F /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Products/Debug -F /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -enable-testing -g -module-cache-path /Users/Adam/Library/Developer/Xcode/DerivedData/ModuleCache.noindex -swift-version 5 -enforce-exclusivity\=checked -Onone -D SWIFT_PACKAGE -D DEBUG -D Xcode -serialize-debugging-options -Xcc -working-directory -Xcc /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics -enable-anonymous-context-mangled-names -Xcc -I/Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/swift-overrides.hmap -Xcc -I/Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/_NumericsShims/include -Xcc -I/Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Products/Debug/include -Xcc -I/Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/DerivedSources-normal/x86_64 -Xcc -I/Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/DerivedSources/x86_64 -Xcc -I/Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/DerivedSources -Xcc -DSWIFT_PACKAGE -Xcc -DDEBUG\=1 -target-sdk-version 10.15.6 -module-name RealModule -o /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Build/Intermediates.noindex/swift-numerics.build/Debug/RealModule.build/Objects-normal/x86_64/Float16+Real.o -index-store-path /Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/Index/DataStore -index-system-modules

/Users/Adam/Library/Developer/Xcode/DerivedData/aaaaaaaaaaaaaa-aofjcusrwcvzregrwblywxeuucga/SourcePackages/checkouts/swift-numerics/Sources/RealModule/Float16+Real.swift:18:11: error: cannot find type 'Float16' in scope
extension Float16: Real {
          ^~~~~~~

closed time in a month

b3ll

issue commentapple/swift-numerics

Unable to Compile with Xcode 12 (12A7209)

@b3ll I just tagged 0.0.8, which should resolve this.

b3ll

comment created time in a month

created tagapple/swift-numerics

tag0.0.8

Numerical APIs for Swift

created time in a month

release apple/swift-numerics

0.0.8

released time in a month

push eventapple/swift-numerics

Stephen Canon

commit sha e07b39453b883f554f1154eedeecd948c11d5888

Swap availability for #if check on Float16.

view details

Stephen Canon

commit sha 6b24333510e9044cf4716a07bed65eeed6bc6393

Merge pull request #157 from stephentyrone/float16-availability-redux Swap availability for #if check on Float16.

view details

push time in a month

PR merged apple/swift-numerics

Swap availability for #if check on Float16.

Xcode 12 on Catalina has Swift 5.3 but the macOS 10.15 SDK, which breaks the conditionals around Float16. Since the type is unconditionally unavailable on macOS, we can simply #if-out any Float16 extensions instead.

+8 -13

1 comment

5 changed files

stephentyrone

pr closed time in a month

pull request commentapple/swift-numerics

Swap availability for #if check on Float16.

@lorentey yeah, step 2 here is definitely to figure out how to avoid this mess in the future =)

stephentyrone

comment created time in a month

PR opened apple/swift-numerics

Swap availability for #if check on Float16.

Xcode 12 on Catalina has Swift 5.3 but the macOS 10.15 SDK, which breaks the conditionals around Float16. Since the type is unconditionally unavailable on macOS, we can simply #if-out any Float16 extensions instead.

+8 -13

0 comment

5 changed files

pr created time in a month

create barnchstephentyrone/swift-numerics

branch : float16-availability-redux

created branch time in a month

issue commentapple/swift-numerics

Unable to Compile with Xcode 12 (12A7209)

Hi @b3ll, I was able to reproduce this. The basic issue is that 12A7209 contains a macOS 10.15 SDK (which correctly doesn't have Float16), rather than a macOS 10.16 SDK. By contrast it has an iOS 14 SDK, so there's no issue for iOS platforms. I'll have to think a little bit about what the best way to handle this in Swift-Numerics is, but I'll try to get a fix up later today. In the very-short term, you can pin to 0.0.6 as a workaround.

b3ll

comment created time in a month

pull request commentapple/swift-numerics

Add complex log(onePlus:)

Note that this doesn't yet handle Im(z) ≈ -1 right. That's relatively easy to fix up, but I have some other work to do today, so it'll have to wait.

stephentyrone

comment created time in a month

PullRequestReviewEvent

push eventstephentyrone/swift-numerics

Stephen Canon

commit sha a5a6a941c4ae9effbb68f75a8a3db026a4fdf752

Fix typo.

view details

push time in a month

pull request commentapple/swift-numerics

Add complex log(onePlus:)

@NevinBR what would you prefer to be credited as in the comments?

stephentyrone

comment created time in a month

PR opened apple/swift-numerics

Add complex log(onePlus:)

Adapts @NevinBR's cute factorization of the real part here:

https://forums.swift.org/t/elementaryfunctions-compliance-for-complex/37903/3

Adds a little bit of FMA magic to avoid catastrophic cancellation and recover a good componentwise error bound as well as an error bound in the complex norm.

+62 -1

0 comment

1 changed file

pr created time in a month

create barnchstephentyrone/swift-numerics

branch : complex-log1p

created branch time in a month

push eventstephentyrone/swift-numerics

Stephen Canon

commit sha 0f02c6585465356cf5ba4d0937221dcc81fd7690

Initial implementation of log(onePlus:)

view details

push time in a month

Pull request review commentapple/swift

[stdlib] Fix a Float16-to-integer conversion bug

 public struct ${Self}     // undefined if it overflows. %     if not (FloatBits == 16 and bits >= 32): # Float16 is always in-range for 32- and 64-bit ints.     guard source > ${str(lower)}.0 && source < ${str(upper)}.0 else {+%     else:

Alternatively, I think we could probably simply eliminate the gyb conditional and use source.isFinite && existing condition, right?

xwu

comment created time in a month

PullRequestReviewEvent

Pull request review commentapple/swift

[stdlib] Fix a Float16-to-integer conversion bug

 public struct ${Self}     // undefined if it overflows. %     if not (FloatBits == 16 and bits >= 32): # Float16 is always in-range for 32- and 64-bit ints.     guard source > ${str(lower)}.0 && source < ${str(upper)}.0 else {+%     else:

We also need to handle UInt16, I think (max value 65536, which rounds to infinity in Float16).

xwu

comment created time in a month

PullRequestReviewEvent

delete branch stephentyrone/swift

delete branch : random-simplification

delete time in a month

PR closed apple/swift

Reviewers
Minor simplification to `FixedWidthInteger._random(using: &generator)`.

We don't actually need a divide or two paths or any of the other complexity here; the optimizer knows how to do this for us.

+8 -12

4 comments

2 changed files

stephentyrone

pr closed time in a month

Pull request review commentapple/swift

[stdlib] Simplify 'BinaryFloatingPoint.init?<T: BinaryFloatingPoint>(exactly: T)'

 extension BinaryFloatingPoint {   /// - Parameter value: A floating-point value to be converted.   @inlinable   public init?<Source: BinaryFloatingPoint>(exactly value: Source) {-    let (value_, exact) = Self._convert(from: value)-    guard exact else { return nil }-    self = value_+    // We define exactness by equality after roundtripping; since NaN is never+    // equal to itself, it can never be converted exactly.+    if value.isNaN { return nil }+    

I think we can simplify the logic downstream by pulling out zero and infinity here (since both are always exact). WDYT?

xwu

comment created time in a month

PullRequestReviewEvent
PullRequestReviewEvent

PR closed apple/swift

Initial implementation of isAlmostEqual(to:) and isAlmostZero() swift-evolution-pending-discussion

Pending Swift-evolution review.

Pitch thread here: https://forums.swift.org/t/approximate-equality-for-floating-point/22420

+221 -0

2 comments

2 changed files

stephentyrone

pr closed time in a month

push eventapple/swift

Xiaodi Wu

commit sha 7898f0b7ad429652b2c35bccb2164df25f35e847

[stdlib] Silence signaling NaN in generic conversions (#33902)

view details

push time in a month

delete branch apple/swift

delete branch : silence-of-the-nans

delete time in a month

PR merged apple/swift

[stdlib] Silence signaling NaN in generic conversions

This PR is a follow-up to #33826, using a cheap operation (multiplying by one) to silence signaling NaN in generic conversions.

(Mostly I'm proud of the branch name.)

<!-- Before merging this pull request, you must run the Swift continuous integration tests. For information about triggering CI builds via @swift-ci, see: https://github.com/apple/swift/blob/master/docs/ContinuousIntegration.md#swift-ci

Thank you for your contribution to Swift! -->

+4 -2

1 comment

1 changed file

xwu

pr closed time in a month

PullRequestReviewEvent
PullRequestReviewEvent

pull request commentapple/swift

[stdlib] Add fast paths for generic floating-point-to-integer conversion

The new concrete implementations will have to be marked @_alwaysEmitIntoClient.

xwu

comment created time in a month

push eventstephentyrone/swift-numerics

Stephen Canon

commit sha a76404b263a8ddba34a9f3e91f7271c0d2c13777

WIP

view details

push time in a month

pull request commentapple/swift

[Diagnostics] Diagnose comparisons with '.nan' and suggest using '.isNan' instead

I'm fine with the diagnostics generated. Pavel or Holly may have feedback on the implementation details, so please let one of them review as well.

theblixguy

comment created time in 2 months

Pull request review commentapple/swift

[Diagnostics] Diagnose comparisons with '.nan' and suggest using '.isNan' instead

 static void diagnoseExplicitUseOfLazyVariableStorage(const Expr *E,   const_cast<Expr *>(E)->walk(Walker); } +static void diagnoseComparisonWithNaN(const Expr *E, const DeclContext *DC) {+  class ComparisonWithNaNFinder : public ASTWalker {+    const ASTContext &C;+    const DeclContext *DC;++  public:+    ComparisonWithNaNFinder(const DeclContext *dc)+        : C(dc->getASTContext()), DC(dc) {}++    void tryDiagnoseComparisonWithNaN(BinaryExpr *BE) {+      ValueDecl *comparisonDecl = nullptr;++      // The == and != methods take two arguments.+      if (BE->getArg()->getNumElements() != 2) {+        return;+      }++      // Dig out the function the arguments are being passed to.+      if (auto Fn = BE->getFn()) {+        if (auto DSCE = dyn_cast<DotSyntaxCallExpr>(Fn)) {+          comparisonDecl = DSCE->getCalledValue();+        } else {+          comparisonDecl = BE->getCalledValue();+        }+      }++      // Bail out if it isn't a function.+      if (!comparisonDecl || !isa<FuncDecl>(comparisonDecl)) {+        return;+      }++      // We're only interested in == and != functions.+      auto comparisonDeclName = comparisonDecl->getBaseIdentifier();+      if (!(comparisonDeclName.is("==") || comparisonDeclName.is("!=") ||+            comparisonDeclName.is("<=") || comparisonDeclName.is("<") ||+            comparisonDeclName.is(">") || comparisonDeclName.is(">="))) {+        return;+      }++      auto firstArg = BE->getArg()->getElement(0);+      auto secondArg = BE->getArg()->getElement(1);++      // Both arguments must conform to FloatingPoint protocol.+      auto conformsToFpProto = [&](Type type) {+        auto fpProto = C.getProtocol(KnownProtocolKind::FloatingPoint);+        return !TypeChecker::conformsToProtocol(type, fpProto,+                                                const_cast<DeclContext *>(DC))+                    .isInvalid();+      };++      if (!conformsToFpProto(firstArg->getType()) ||+          !conformsToFpProto(firstArg->getType())) {+        return;+      }++      // Dig out the declarations for the arguments.+      ValueDecl *firstVal = nullptr;+      ValueDecl *secondVal = nullptr;+      if (auto DRE = dyn_cast<DeclRefExpr>(firstArg)) {+        firstVal = DRE->getDecl();+      } else if (auto MRE = dyn_cast<MemberRefExpr>(firstArg)) {+        firstVal = MRE->getMember().getDecl();+      }++      if (auto DRE = dyn_cast<DeclRefExpr>(secondArg)) {+        secondVal = DRE->getDecl();+      } else if (auto MRE = dyn_cast<MemberRefExpr>(secondArg)) {+        secondVal = MRE->getMember().getDecl();+      }++      // One of them has to be '.nan', so if we don't have declarations+      // for both, then bail out.

Extremely minor nit: should be "if we don't have declarations for either, then bail out," I think.

theblixguy

comment created time in 2 months

PullRequestReviewEvent
more