-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
Copy pathconstants.jl
89 lines (73 loc) · 3.22 KB
/
constants.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
## general machinery for mathematical constants
immutable MathConst{sym} <: Real end
show{sym}(io::IO, x::MathConst{sym}) = print(io, "$sym = $(string(float(x))[1:15])...")
promote_rule{s,T<:Real}(::Type{MathConst{s}}, ::Type{T}) = Float64
promote_rule{s}(::Type{MathConst{s}}, ::Type{Float64}) = Float64
promote_rule{s}(::Type{MathConst{s}}, ::Type{Float32}) = Float32
promote_rule{s}(::Type{MathConst{s}}, ::Type{BigInt}) = BigFloat
promote_rule{s}(::Type{MathConst{s}}, ::Type{BigFloat}) = BigFloat
promote_rule{s}(::Type{MathConst{s}}, ::Type{ImaginaryUnit}) = Complex{Float64}
promote_rule{s}(::Type{ImaginaryUnit}, ::Type{MathConst{s}}) = Complex{Float64}
promote_rule{s,T<:Integer}(::Type{MathConst{s}}, ::Type{Rational{T}}) =
promote_type(MathConst{s},T)
promote_rule{s,T<:Real}(::Type{MathConst{s}}, ::Type{Complex{T}}) =
Complex{promote_type(MathConst{s},T)}
convert(::Type{FloatingPoint}, x::MathConst) = float64(x)
convert(::Type{Float16}, x::MathConst) = float16(float32(x))
convert{T<:Real}(::Type{Complex{T}}, x::MathConst) = convert(Complex{T}, float64(x))
convert{T<:Integer}(::Type{Rational{T}}, x::MathConst) = convert(Rational{T}, float64(x))
-(x::MathConst) = -float64(x)
for op in {:+, :-, :*, :/, :^}
@eval $op(x::MathConst, y::MathConst) = $op(float64(x),float64(y))
end
*(x::MathConst, i::ImaginaryUnit) = float64(x)*i
*(i::ImaginaryUnit, x::MathConst) = i*float64(x)
macro math_const(sym, val, def)
esym = esc(sym)
qsym = esc(Expr(:quote, sym))
bigconvert = isa(def,Symbol) ? quote
function Base.convert(::Type{BigFloat}, ::MathConst{$qsym})
c = BigFloat()
ccall(($(string("mpfr_const_", def)), :libmpfr),
Cint, (Ptr{BigFloat}, Int32),
&c, MPFR.ROUNDING_MODE[end])
return c
end
end : quote
Base.convert(::Type{BigFloat}, ::MathConst{$qsym}) = $(esc(def))
end
quote
const $esym = MathConst{$qsym}()
$bigconvert
Base.convert(::Type{Float64}, ::MathConst{$qsym}) = $val
Base.convert(::Type{Float32}, ::MathConst{$qsym}) = $(float32(val))
@assert isa(big($esym), BigFloat)
@assert float64($esym) == float64(big($esym))
@assert float32($esym) == float32(big($esym))
end
end
big(x::MathConst) = convert(BigFloat,x)
## specific mathematical constants
@math_const π 3.14159265358979323846 pi
@math_const e 2.71828182845904523536 exp(big(1))
@math_const γ 0.57721566490153286061 euler
@math_const catalan 0.91596559417721901505 catalan
@math_const φ 1.61803398874989484820 (1+sqrt(big(5)))/2
# aliases
const pi = π
const eu = e
const eulergamma = γ
const golden = φ
# special behaviors
# use exp for e^x or e.^x, as in
# ^(::MathConst{:e}, x::Number) = exp(x)
# .^(::MathConst{:e}, x) = exp(x)
# but need to loop over types to prevent ambiguity with generic rules for ^(::Number, x) etc.
for T in (MathConst, Rational, Integer, Number)
^(::MathConst{:e}, x::T) = exp(x)
end
for T in (Ranges, BitArray, SparseMatrixCSC, StridedArray, AbstractArray)
.^(::MathConst{:e}, x::T) = exp(x)
end
^(::MathConst{:e}, x::AbstractMatrix) = expm(x)
log(::MathConst{:e}) = 1 # use 1 to correctly promote expressions like log(x)/log(e)