# 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?

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
2 Likes

Thanks very much!