-
Notifications
You must be signed in to change notification settings - Fork 59
Expand file tree
/
Copy pathgeneric.jl
More file actions
135 lines (100 loc) · 3.91 KB
/
generic.jl
File metadata and controls
135 lines (100 loc) · 3.91 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
## functions for generic programming within SymPy
## if a generic method should apply to a sympy variable, it would
## be defined here.
## Iterator for Sym
import Base.iterate
iterate(x::Sym) = (x.__pyobject__, 0)
iterate(x::Sym, state) = nothing
Base.isless(a::Sym, b::Sym) = (a != sympy.nan && b != sympy.nan) && sympy.Lt(a,b) == True
Base.isless(a::Sym, b::Number) = isless(promote(a,b)...)
Base.isless(a::Number, b::Sym) = isless(promote(a,b)...)
Base.isequal(a::Sym, b::Sym) = Eq(a,b) == True
Base.isequal(a::Sym, b::Number) = Eq(promote(a,b)...) == True
Base.isequal(a::Number, b::Sym) = Eq(promote(a,b)...) == True
# Floating point bits
Base.eps(::Type{Sym}) = zero(Sym)
Base.eps(::Sym) = zero(Sym)
Base.signbit(x::Sym) = x < 0
Base.copysign(x::Sym, y::Number) = abs(x) * sign(y)
Base.flipsign(x::Sym, y) = signbit(y) ? -x : x
Base.typemax(::Type{Sym}) = oo
Base.typemin(::Type{Sym}) = -oo
Base.fld(x::SymbolicObject, y) = floor(x/y)
Base.cld(x::SymbolicObject, y) = ceil(x/y)
Base.mod(x::SymbolicObject, args...)= Mod(x, args...)
#Base.mod1
#Base.mod2pi
#Base.fldmod
# so we can compare numbers with ≈
Base.rtoldefault(::Type{<:SymbolicObject}) = eps()
# SymPy round only has a digits argument and errors on symbols
# here we relax it a git
function Base.round(x::Sym, r::RoundingMode=RoundNearest; digits=nothing, kwargs...)
x.is_number != true && return x
digits === nothing && return _round(x, r)
return x.round(digits)
end
_round(x::Sym, r::RoundingMode{:Nearest}) = x.round()
_round(x::Sym, r::RoundingMode) = begin
Sym(round(N(x), r))
end
function Base.round(::Type{T}, x::Sym, r::RoundingMode=RoundNearest) where {T <: Integer}
r != RoundToZero && (x = round(x, r))
convert(T, trunc(x))
end
#trunc(x) returns the nearest integral value of the same type as x whose absolute value is less than or equal to the absolute value of x.
function Base.trunc(x::Sym)
x.is_real == true || return x
y = x.evalf().floor()
x.is_positive && return y
return 1 + y
end
# check on type of number
# these are boolean: true/false; not tru/false/nothing,as in SymPy
Base.isfinite(x::Sym) = !is_(:infinite, x)
Base.isinf(x::Sym) = is_(:infinite, x)
Base.isnan(x::Sym) = x == sympy.nan
Base.isinteger(x::Sym) = is_(:integer, x)
Base.iseven(x::Sym) = is_(:even, x)
Base.isreal(x::Sym) = is_(:real, x)
Base.isodd(x::Sym) = is_(:odd, x)
## zero and one (zeros?)
Base.zero(x::Sym) = Sym(0)
Base.zero(::Type{Sym}) = Sym(0)
Base.one(x::Sym) = Sym(1)
Base.one(::Type{Sym}) = Sym(1)
## float, complex, real, imag, angle
Base.float(x::Sym) = _float(N(x))
_float(x::Sym) = throw(ArgumentError("variable must have no free symbols"))
_float(x) = float(x)
Base.Float64(x::Sym) = _Float64(N(x))
_Float64(x::Sym) = throw(ArgumentError("variable must have no free symbols"))
_Float64(x) = Float64(x)
Base.Integer(x::Sym) = is_integer(x) ? N(x) : throw(DomainError("x can not be converted to an integer"))
Base.complex(::Type{Sym}) = Sym
Base.complex(r::Sym) = real(r) + imag(r) * im
function Base.complex(r::Sym, i)
isreal(r) || throw(ArgumentError("r and i must not be complex"))
isreal(i) || throw(ArgumentError("r and i must not be complex"))
N(r) + N(i) * im
end
Base.complex(xs::AbstractArray{Sym}) = complex.(xs) # why is this in base?
Base.conj(x::SymbolicObject) = x.conjugate()
function Base.transpose(f::Sym)::Sym
if pycall_hasproperty(PyObject(f), :transpose)
f.transpose()
else
f
end
end
Base.real(::Type{Sym}) = Sym
Base.real(x::Sym) = sympy.re(x)
Base.imag(x::Sym) = sympy.im(x)
Base.angle(z::SymPy.SymbolicObject) = atan(sympy.im(z), sympy.re(z))
# sympy.div for poly division
Base.divrem(x::Sym, y) = sympy.div(x, y)
# needed for #390; but odd
Base.div(x::Sym, y::Union{Sym,Number}) = convert(Sym, sympy.floor(x/convert(Sym,y)))
Base.rem(x::Sym, y::Union{Sym,Number}) = x-Sym(y)*Sym(sympy.floor.(x/y))
Base.denominator(x::SymbolicObject) = denom(x)
Base.numerator(x::SymbolicObject) = numer(x)