This is the code:
|
for f in (:sin, :cos, :tan, :asin, :atan, :acos, |
|
:sinh, :cosh, :tanh, :asinh, :acosh, :atanh, |
|
:exp, :exp2, :exp10, :expm1, :log, :log2, :log10, :log1p, |
|
:exponent, :sqrt, :cbrt, :sinpi, :cospi, :sincospi, :tanpi) |
|
@eval function ($f)(x::Real) |
|
xf = float(x) |
|
x === xf && throw(MethodError($f, (x,))) |
|
return ($f)(xf) |
|
end |
|
@eval $(f)(::Missing) = missing |
|
end |
This line is meant to guard against stack overflow:
x === xf && throw(MethodError($f, (x,)))
... however I think that's only correct for isbits(x). Assuming x is mutable, float(x) might perhaps return xf such that (x == xf) && (x !== xf). I'd change the line to:
(xf isa typeof(x)) && throw(MethodError($f, (x,)))
A reproducer is:
julia> mutable struct T <: Real end
julia> Base.float(::T) = T()
julia> sinpi(T())
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
ERROR: StackOverflowError:
Stacktrace:
[1] sinpi(x::T)
@ Base.Math ./math.jl:1543
[2] sinpi(x::T) (repeats 79983 times)
@ Base.Math ./math.jl:1546
This is somewhat realistic given that some of the thick Number-like types in the ecosystem, such as intervals of real numbers, or Dual from ForwardDiff, subtype Real even though such an object is not mathematically a real number.
This is the code:
julia/base/math.jl
Lines 1539 to 1549 in 04922e7
This line is meant to guard against stack overflow:
... however I think that's only correct for
isbits(x). Assumingxis mutable,float(x)might perhaps returnxfsuch that(x == xf) && (x !== xf). I'd change the line to:A reproducer is:
This is somewhat realistic given that some of the thick
Number-like types in the ecosystem, such as intervals of real numbers, orDualfromForwardDiff, subtypeRealeven though such an object is not mathematically a real number.