strike
(V T)
1
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
jrose
(Jordan Rose)
2
This got added in Swift 4.2! See SR-2046. Things should Just Work now.
4 Likes
strike
(V T)
4
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
xwu
(Xiaodi Wu)
5
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).
strike
(V T)
6
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!
xwu
(Xiaodi Wu)
7
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.
strike
(V T)
8
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
}
:-|
strike
(V T)
9
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
Karl
(👑🦆)
10
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
}
}
strike
(V T)
11
Ah!
That was it! Missing 'f'...
Thanks!!
strike
jrose
(Jordan Rose)
12
@scanon, is the overload thing expected?
scanon
(Steve Canon)
13
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