Float80 math function

Hi there!

Is there a way to use mathematical functions like lgamma (), tgamma () or pow () with Float80 numbers and get Float80 numbers as a result?

Thanks in advance!

strike

This got added in Swift 4.2! See SR-2046. Things should Just Work now.

4 Likes

Wow. That's great!

Thanks!

Hi again!

It seems that there are to different versions of lgamma() with different return types:

lgamma(_ x: Double/Float/Float80) -> (Double/Float/Float80, Int)

and

lgamma(_x: Double/Float/Float80) -> Double/Float/Float80

How can I determine, which version will be used?
I suppose the Int will be used to store the sign of the Gamma function.

I want to have a generic lgamma-version as follows:

internal func lgamma<T: FloatingPoint>(_ x: T) -> T {
    if x.self is Double {
        return lgamma(x as! Double) as! T    /* <- Ambiguous use of 'lgamma' */
    }
    if x.self is Float {
        return lgamma(x as! Float) as! T /
    }
    #if arch(x86_64)
    if x.self is Float80 {
        return lgammal(x as! Float80) as! T
    }
    #endif
    return T.nan
}

Best regards!

strike

You are getting an ambiguity error not for the reason you think, but because you have created the ambiguity yourself by defining a function with exactly the same name and return type. You can disambiguate by spelling the library function Darwin.lgamma (or Glibc.lgamma on Linux).

Hi!

No. Same error:

internal func lgamma1<T: FloatingPoint>(_ x: T) -> T {
    if x.self is Double {
        return Darwin.lgamma(x as! Double) as! T. /* Ambiguous use of 'lgamma' */
    }
    if x.self is Float {
        return lgamma(x as! Float) as! T. /* <- no error */
    }
    #if arch(x86_64)
    if x.self is Float80 {
        return lgammal(x as! Float80) as! T
    }
    #endif
    return T.nan
}

Regards!

Ah, right. You would use the as operator to disambiguate return types. This operator looks like as! but they are actually quite different: as is a type coercion operator and as! is a dynamic casting operator. In other words:

return Darwin.lgamma(x as! Double) as Double as! T

By the way, you want to write if x is Double; there is no reason, ever, to use .self on a value.

Hi!

Ok. That works. Partially:

internal func lgamma1<T: FloatingPoint>(_ x: T) -> T {
if x is Double {
return Darwin.lgamma(x as! Double) as Double as! T
}
if x is Float {
return Darwin.lgamma(x as! Float) as Float as! T /* Cannot convert value of type '(Float, Int)' to type 'Float' in coercion */
}
if arch(x86_64)
if x is Float80 {
return Darwin.lgammal(x as! Float80) as Float80 as! T
}
#endif
return T.nan
}

:-|

I'm wondering how the compiler decides, which version will be called
lgamma(:) -> (Double, Int) or lgamma(:) -> Double

Sorry. That's confusing...

Using Swift 4.1 this error never showed up...

Regards!

strike

You want to use lgammaf for the float version. This works for me (also using switch... I find it's better style for this kind of thing):

internal func lgamma1<T: FloatingPoint>(_ x: T) -> T {
  switch x {
  case let d as Double:
    return lgamma(d) as Double as! T
  case let f as Float:
    return lgammaf(f) as! T
  #if arch(x86_64)
  case let lf as Float80:
    return lgammal(lf) as! T
  #endif
  default:
    return T.nan
  }
}

Ah!

That was it! Missing 'f'...

Thanks!!

strike

@scanon, is the overload thing expected?

No, that's very much not intended, and also I don't recall any specific change that would have caused this.

@strike, can you file a bug report at bugs.swift.org? A two-sentence description of the problem and a link to this thread is fine.

1 Like

Done

2 Likes

Thanks very much!