-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
promotion.jl
76 lines (63 loc) · 2.45 KB
/
promotion.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
## promotion mechanism ##
promote_type{T}(::Type{T}) = T
promote_type(::Type{None}, ::Type{None}) = None
promote_type{T}(::Type{T}, ::Type{T}) = T
promote_type{T}(::Type{T}, ::Type{None}) = T
promote_type{T}(::Type{None}, ::Type{T}) = T
promote_type(S::Type, T::Type...) = promote_type(S, promote_type(T...))
function promote_type{T,S}(::Type{T}, ::Type{S})
if applicable(promote_rule, T, S)
return promote_rule(T,S)
elseif applicable(promote_rule, S, T)
return promote_rule(S,T)
else
error("no promotion exists for ",T," and ",S)
end
end
promote() = ()
promote(x) = (x,)
function promote{T,S}(x::T, y::S)
(convert(promote_type(T,S),x), convert(promote_type(T,S),y))
end
function promote{T,S,U}(x::T, y::S, z::U)
R = promote_type(promote_type(T,S), U)
convert((R...), (x, y, z))
end
function promote{T,S}(x::T, y::S, zs...)
R = promote_type(T,S)
for z in zs
R = promote_type(R,typeof(z))
end
convert((R...), tuple(x,y,zs...))
end
# TODO: promote{T}(x::T, ys::T...) here to catch all circularities?
## promotions in arithmetic, etc. ##
+(x::Number, y::Number) = +(promote(x,y)...)
*(x::Number, y::Number) = *(promote(x,y)...)
-(x::Number, y::Number) = -(promote(x,y)...)
/(x::Number, y::Number) = /(promote(x,y)...)
^(x::Number, y::Number) = ^(promote(x,y)...)
(&)(x::Integer, y::Integer) = (&)(promote(x,y)...)
(|)(x::Integer, y::Integer) = (|)(promote(x,y)...)
($)(x::Integer, y::Integer) = ($)(promote(x,y)...)
==(x::Number, y::Number) = (==)(promote(x,y)...)
< (x::Real, y::Real) = (< )(promote(x,y)...)
<=(x::Real, y::Real) = (<=)(promote(x,y)...)
div(x::Real, y::Real) = div(promote(x,y)...)
fld(x::Real, y::Real) = fld(promote(x,y)...)
rem(x::Real, y::Real) = rem(promote(x,y)...)
mod(x::Real, y::Real) = mod(promote(x,y)...)
mod1(x::Real, y::Real) = mod1(promote(x,y)...)
cmp(x::Real, y::Real) = cmp(promote(x,y)...)
## catch-alls to prevent infinite recursion when definitions are missing ##
no_op_err(name, T) = error(name," not defined for ",T)
+{T<:Number}(x::T, y::T) = no_op_err("+", T)
*{T<:Number}(x::T, y::T) = no_op_err("*", T)
-{T<:Number}(x::T, y::T) = no_op_err("-", T)
/{T<:Number}(x::T, y::T) = no_op_err("/", T)
^{T<:Number}(x::T, y::T) = no_op_err("^", T)
(&){T<:Integer}(x::T, y::T) = no_op_err("&", T)
(|){T<:Integer}(x::T, y::T) = no_op_err("|", T)
($){T<:Integer}(x::T, y::T) = no_op_err("\$", T)
=={T<:Number}(x::T, y::T) = no_op_err("==", T)
<{T<:Real}(x::T, y::T) = no_op_err("<", T)