Hi Jens —

BinaryFloatingPoint is very deliberately limited to the arithmetic operations 
required by IEEE 754. This is the minimal set of operations that a binary 
floating point type should provide, but it's already a really large 
implementation burden for someone who wants to implement their own conforming 
type.

I agree that there should eventually be either a refinement or orthogonal 
protocol[s] with the semantics “type implements [a subset of] the standard math 
functions”, but those shouldn’t get bolted onto 
BinaryFloatingPoint—implementing these functions for an arbitrary 
BinaryFloatingPoint type is highly non-trivial, and would make the 
implementation burden for a new floating point type unreasonably high. This is 
also out-of-scope for the current phase of Swift evolution.

In the short term for your immediate problem at hand, I’ve been doing something 
like:

import Darwin

public protocol Math: BinaryFloatingPoint {
  func _exp() -> Self
  func _log() -> Self
  func _sin() -> Self
  func _cos() -> Self
}

extension Double: Math {
  public func _exp() -> Double { return exp(self) }
  public func _log() -> Double { return log(self) }
  public func _sin() -> Double { return sin(self) }
  public func _cos() -> Double { return cos(self) }
}

extension Float: Math {
  public func _exp() -> Float { return exp(self) }
  public func _log() -> Float { return log(self) }
  public func _sin() -> Float { return sin(self) }
  public func _cos() -> Float { return cos(self) }
}

func exp<T: Math>(_ x: T) -> T { return x._exp() }
func log<T: Math>(_ x: T) -> T { return x._log() }
func sin<T: Math>(_ x: T) -> T { return x._sin() }
func cos<T: Math>(_ x: T) -> T { return x._cos() }

extension Math {
  func sigmoid() -> Self {
    return 1.0 / (1.0 + exp(-self))
  }
}

let x = 1.0
x.sigmoid()

Someone else might have a more clever solution.
– Steve

> On Jan 5, 2017, at 8:22 AM, Jens Persson via swift-users 
> <swift-users@swift.org> wrote:
> 
> The code below doesn't compile since there is no exponential function (exp) 
> that works on all FloatingPoint or BinaryFloatingPoint types, also no 
> protocol seems to define the power function or the constant e, although they 
> do define for example: basic arithmetic operators, squareRoot() and pi.
> 
> extension BinaryFloatingPoint {
>     func sigmoid() -> Self {
>         return 1.0 / (1.0 + exp(-self))
>     }
> }
> 
> I could, but don't want to write two free funcs sigmoid(Float) -> Float and 
> sigmoid(Double) -> Double, because I need to use x.sigmoid() in several 
> places where x is of a generic type (a BinaryFloatingPoint).
> 
> More generally: I would have the same problem if I needed eg sin or cos. Are 
> there any particular reason why, given a generic BinaryFloatingPoint, I 
> cannot use sin or cos, while I can use pi and squareRoot()? It does seem a 
> bit arbitrary.
> 
> Any ideas on how to implement a sigmoid() that works for all 
> BinaryFloatingPoint types?
> 
> /Jens
> _______________________________________________
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to