Skip to content

Commit c29251b

Browse files
authored
Merge pull request #58 from fremling/master
Overloading of arithithmetic operators
2 parents 4017f9e + 9eb48be commit c29251b

File tree

6 files changed

+296
-5
lines changed

6 files changed

+296
-5
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
Manifest.toml
22
deps/deps.jl
33
deps/*.log
4+
*~

README.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,80 @@ julia> weval(sinx; x=2.0)
5858
0.9092974268256817
5959
```
6060

61+
## The algebraic operators
62+
63+
MathLink also overloads the `+`, `-`, `*`, `/` operations
64+
65+
```julia
66+
julia> using MathLink
67+
68+
julia> W"a"+W"b"
69+
W"Plus"(W"a",W"b")
70+
71+
julia> W"a"+W"a"
72+
W"Plus"(W"a",W"a")
73+
74+
julia> W"a"-W"a"
75+
W"Plus"(W"a",W"Minus"(W"a"))
76+
```
77+
78+
One can toggle automatic use of `weval` on-and-off using `set_GreedyEval(x::Bool)`
79+
80+
```julia
81+
julia>set_GreedyEval(true)
82+
julia> W"a"+W"b"
83+
W"Plus"(W"a",W"b")
84+
85+
julia> W"a"+W"a"
86+
W"Times"(2,W"a")
87+
88+
julia> W"a"-W"a"
89+
0
90+
```
91+
92+
93+
## Fractions and Complex numbers
94+
95+
The package also contains extentions to handle fractions
96+
97+
```julia
98+
julia> weval(1//2)
99+
W"Rational"(1, 2)
100+
101+
julia> (4//5)*W"a"
102+
W"Times"(W"Rational"(4, 5), W"a")
103+
104+
julia> W"a"/(4//5)
105+
W"Times"(W"Rational"(5, 4), W"a")
106+
```
107+
108+
and complex numbers
109+
110+
```julia
111+
julia> im*W"a"
112+
W"Times"(W"Complex"(0, 1), W"a")
113+
114+
julia> im*(im*W"c")
115+
W"Times"(-1, W"c")
116+
```
117+
118+
119+
## Matrix Multiplication
120+
Since the arithematic operators are overloaded, operations such as matrix multiplication are also possible by default
121+
122+
```julia
123+
julia> P12 = [ 0 1 ; 1 0 ]
124+
2×2 Matrix{Int64}:
125+
0 1
126+
1 0
127+
128+
julia> set_GreedyEval(true)
129+
true
130+
131+
julia> P12 * [W"a" W"b" ; W`a+b` 2] == [ W"b" 2-W"b" ; W"a" W"b"]
132+
true
133+
```
134+
61135
## Notes
62136

63137
- Mathematica, Wolfram, MathLink are all trademarks of Wolfram Research.

src/MathLink.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ include("wstp.jl")
1313
include("extras.jl")
1414
include("eval.jl")
1515
include("display.jl")
16+
include("operators.jl")
1617

1718
end

src/operators.jl

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
2+
import Base.+
3+
import Base.*
4+
import Base.-
5+
import Base./
6+
import Base.//
7+
import Base.^
8+
import Base.zero
9+
#### + ####
10+
11+
12+
####If the flag for greedy evaluation does not exist
13+
## create it and set it to false.
14+
if !@isdefined(MLGreedyEval)
15+
MLGreedyEval=false
16+
end
17+
18+
function MLeval(x::WTypes)
19+
#println("MLGreedyEval=$MLGreedyEval")
20+
if MLGreedyEval
21+
return weval(x)
22+
else
23+
return x
24+
end
25+
end
26+
27+
export set_GreedyEval
28+
29+
function set_GreedyEval(x::Bool)
30+
global MLGreedyEval
31+
MLGreedyEval=x
32+
end
33+
34+
35+
###A special case of weval on rationals that was not handled
36+
zero(x::WTypes)=0
37+
38+
+(a::WTypes)=MLeval(a)
39+
+(a::WTypes,b::WTypes)=MLeval(W"Plus"(a,b))
40+
+(a::WTypes,b::Number)=MLeval(W"Plus"(a,b))
41+
+(a::Number,b::WTypes)=MLeval(W"Plus"(a,b))
42+
+(a::WTypes,b::Complex)=a+WComplex(b)
43+
+(a::Complex,b::WTypes)=WComplex(a)+b
44+
#### - ####
45+
-(a::WTypes)=MLeval(W"Minus"(a))
46+
-(a::WTypes,b::WTypes)=MLeval(W"Plus"(a,W"Minus"(b)))
47+
-(a::WTypes,b::Number)=MLeval(W"Plus"(a,W"Minus"(b)))
48+
-(a::Number,b::WTypes)=MLeval(W"Plus"(a,W"Minus"(b)))
49+
-(a::WTypes,b::Complex)=a-WComplex(b)
50+
-(a::Complex,b::WTypes)=WComplex(a)-b
51+
52+
53+
#### * ####
54+
*(a::WTypes,b::WTypes)=MLeval(W"Times"(a,b))
55+
*(a::WTypes,b::Number)=MLeval(W"Times"(a,b))
56+
*(a::Number,b::WTypes)=MLeval(W"Times"(a,b))
57+
*(a::WTypes,b::Rational)=a*WRational(b)
58+
*(a::Rational,b::WTypes)=WRational(a)*b
59+
*(a::WTypes,b::Complex)=a*WComplex(b)
60+
*(a::Complex,b::WTypes)=WComplex(a)*b
61+
62+
63+
#### // ####
64+
//(a::WTypes,b::WTypes)=MLeval(W"Times"(a, W"Power"(b, -1)))
65+
//(a::WTypes,b::Number)=MLeval(W"Times"(a, W"Power"(b, -1)))
66+
//(a::Number,b::WTypes)=MLeval(W"Times"(a, W"Power"(b, -1)))
67+
//(a::WTypes,b::Rational)=a//WRational(b)
68+
//(a::Rational,b::WTypes,)=WRational(a)//b
69+
//(a::WTypes,b::Complex)=a//WComplex(b)
70+
//(a::Complex,b::WTypes,)=WComplex(a)//b
71+
72+
73+
#### / ####
74+
/(a::WTypes,b::WTypes)=a//b
75+
/(a::WTypes,b::Number)=a//b
76+
/(a::Number,b::WTypes)=a//b
77+
78+
79+
#### ^ ####
80+
^(a::WTypes,b::WTypes)=MLeval(W"Power"(a,b))
81+
^(a::WTypes,b::Number)=MLeval(W"Power"(a,b))
82+
^(a::Number,b::WTypes)=MLeval(W"Power"(a,b))
83+
84+
WRational(x::Rational) = W"Times"(x.num, W"Power"(x.den, -1))
85+
WComplex(x::Complex) = W"Complex"(x.re,x.im)
86+
function WComplex(x::Complex{Bool})
87+
if x.re
88+
re = 1
89+
else
90+
re = 0
91+
end
92+
if x.im
93+
im = 1
94+
else
95+
im = 0
96+
end
97+
return W"Complex"(re,im)
98+
end
99+
100+
###Added a function to put that handles rationals
101+
import MathLink.put
102+
MathLink.put(x::MathLink.Link,r::Rational)=MathLink.put(x,WRational(r))
103+
MathLink.put(x::MathLink.Link,z::Complex)=MathLink.put(x,WComplex(z))
104+

src/types.jl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
abstract type WTypes end
2+
3+
14
"""
25
WSymbol(name::Union{String, Symbol})
36
W"..."
@@ -28,9 +31,9 @@ julia> weval(W"Simplify"(ex, Assumptions=assume))
2831
W"Times"(-1, W"x")
2932
```
3033
"""
31-
struct WSymbol
34+
struct WSymbol <: WTypes
3235
name::String
33-
end
36+
end
3437
WSymbol(sym::Symbol) = WSymbol(String(sym))
3538
Base.print(io::IO, s::WSymbol) = print(io, s.name)
3639
Base.show(io::IO, s::WSymbol) = print(io, 'W', '"', s.name, '"')
@@ -45,7 +48,7 @@ end
4548
4649
A Wolfram arbitrary-precision real number.
4750
"""
48-
struct WReal
51+
struct WReal <: WTypes
4952
value::String
5053
end
5154
Base.show(io::IO, x::WReal) = print(io, x.value)
@@ -56,7 +59,7 @@ Base.:(==)(a::WReal, b::WReal) = a.value == b.value
5659
5760
A Wolfram arbitrary-precision integer.
5861
"""
59-
struct WInteger
62+
struct WInteger <: WTypes
6063
value::String
6164
end
6265
Base.show(io::IO, x::WInteger) = print(io, x.value)
@@ -78,7 +81,7 @@ julia> weval(W`Function[x,x+1]`(2))
7881
3
7982
```
8083
"""
81-
struct WExpr
84+
struct WExpr <: WTypes
8285
head
8386
args
8487
end

test/runtests.jl

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,111 @@ end
7474

7575
@test W`Cos[$(log(2))]` == W"Cos"(log(2))
7676
end
77+
78+
79+
80+
@testset "README" begin
81+
82+
###The operations mentioned for MathLink the README
83+
sin1 = W"Sin"(1.0)
84+
@test sin1 == W"Sin"(1.0)
85+
86+
sinx = W"Sin"(W"x")
87+
@test sinx == W"Sin"(W"x")
88+
@test W`Sin[1]` == W"Sin"(1)
89+
90+
@test weval(sin1) == 0.8414709848078965
91+
92+
@test weval(sinx) == W"Sin"(W"x")
93+
94+
@test weval(W"Integrate"(sinx, (W"x", 0, 1))) == W"Plus"(1, W"Times"(-1, W"Cos"(1)))
95+
end
96+
97+
98+
@testset "GreedyEval" begin
99+
###Testing turning on and turning of the greedy evaluation
100+
###The default is "false"
101+
@test W"a"+W"b" == W"Plus"(W"a",W"b")
102+
@test W"a"+W"a" == W"Plus"(W"a",W"a")
103+
@test W"a"-W"a" == W"Plus"(W"a",W"Minus"(W"a"))
104+
set_GreedyEval(true)
105+
@test W"a"+W"b" == W"Plus"(W"a",W"b")
106+
@test W"a"+W"a" == W"Times"(2,W"a")
107+
@test W"a"-W"a" == 0
108+
set_GreedyEval(false)
109+
@test W"b"+W"b" == W"Plus"(W"b",W"b")
110+
set_GreedyEval(true)
111+
end
112+
113+
@testset "Rationals" begin
114+
#### Test Rationals parts
115+
@test (4//5)*W"a" == weval(W`4 a/5`)
116+
@test W"a"*(4//5) == weval(W`4 a/5`)
117+
@test (4//5)/W"a" == weval(W`4/(a 5)`)
118+
@test W"a"/(4//5) == weval(W`5 a/4`)
119+
@test weval(1//2) == weval(W`1/2`)
120+
@test weval([1//2,W`a`]) == W"List"(weval(W`1/2`),W`a`)
121+
end
122+
123+
@testset "Complex Numbers" begin
124+
#### Test imaginary parts
125+
@test im*W"a" == weval(W`I * a`)
126+
@test (2*im)*W"a" == weval(W`2 I a`)
127+
@test im/W"a" == weval(W`I / a`)
128+
@test W"a"/(2* im) == weval(W`- I a/2`)
129+
@test im*(im*W"c") == weval(W`-c`)
130+
131+
132+
#####Testing that complex nubmers can be put in weval
133+
@test weval(im+2) == weval(W`I+2`)
134+
@test weval(im*2) == weval(W`I*2`)
135+
@test weval(im) == weval(W`I`)
136+
137+
@test (3*im)*(2*im)*W"a" == weval(W`-6 a`)
138+
@test (3*im) + (2*im)*W"a" == weval(W`3 I + 2 I a`)
139+
@test (3*im) - (2*im)*W"a" == weval(W`3 I - 2 I a`)
140+
end
141+
142+
143+
@testset "Unary operators" begin
144+
@test +W"b" == W"b"
145+
@test +W`a+b` == W`a+b`
146+
@test -W"b" == W`-b`
147+
@test -W`a-b` == W`-a+b`
148+
end
149+
150+
151+
152+
153+
@testset "Matrix Multiplication" begin
154+
155+
P12 = [ 0 1 ; 1 0 ]
156+
@test P12 * [W"a" W"b" ; W`a+b` 2] == [ W`a+b` 2 ; W"a" W"b"]
157+
@test [W"a" W"b" ; W`a+b` 2] * P12 == [ W"b" W"a" ; 2 W`a+b`]
158+
159+
#### test larger matrix
160+
@test P12 * [W"a" W"b" ; W`a+b` W`v+2`] == [ W`a+b` W`2+v` ; W"a" W"b"]
161+
@test [W"a" W"b" ; W`a+b` W`v+2`] * P12 == [ W"b" W"a" ; W`2+v` W`a+b`]
162+
163+
#### test larger matrix
164+
P13 = fill(0,(3,3))
165+
P13[1,3]=1
166+
P13[3,1]=1
167+
P13[2,2]=1
168+
Mat = fill(W`a+d`,3,3)
169+
Mat[:,:] = [W`a+d` W`a+d` W`f*g`; W`a+b` W`v+2` W`f*g` ; W`d+b` W`a+b` W`a+b`]
170+
P13 * Mat * P13
171+
#HM2 = P13*Mat*P13
172+
173+
###A real live eample
174+
P14 = fill(0,(4,4))
175+
P14[1,4]=1
176+
P14[4,1]=1
177+
P14[2,2]=1
178+
P14[3,3]=1
179+
Mat = MathLink.WExpr[W"Plus"(W"J1245", W"J1346", W"J2356") W"Plus"(W"Times"(W"Complex"(0, 1), W"J1356"), W"Times"(W"Complex"(0, -1), W"J2346")) W"Plus"(W"Times"(W"Complex"(0, -1), W"J1256"), W"Times"(W"Complex"(0, 1), W"J2345")) W"Plus"(W"J1246", W"Times"(-1, W"J1345")); W"Plus"(W"Times"(W"Complex"(0, -1), W"J1356"), W"Times"(W"Complex"(0, 1), W"J2346")) W"Plus"(W"J1245", W"Times"(-1, W"J1346"), W"Times"(-1, W"J2356")) W"Plus"(W"J1246", W"J1345") W"Plus"(W"Times"(W"Complex"(0, -1), W"J1256"), W"Times"(W"Complex"(0, -1), W"J2345")); W"Plus"(W"Times"(W"Complex"(0, 1), W"J1256"), W"Times"(W"Complex"(0, -1), W"J2345")) W"Plus"(W"J1246", W"J1345") W"Plus"(W"Times"(-1, W"J1245"), W"J1346", W"Times"(-1, W"J2356")) W"Plus"(W"Times"(W"Complex"(0, -1), W"J1356"), W"Times"(W"Complex"(0, -1), W"J2346")); W"Plus"(W"J1246", W"Times"(-1, W"J1345")) W"Plus"(W"Times"(W"Complex"(0, 1), W"J1256"), W"Times"(W"Complex"(0, 1), W"J2345")) W"Plus"(W"Times"(W"Complex"(0, 1), W"J1356"), W"Times"(W"Complex"(0, 1), W"J2346")) W"Plus"(W"Times"(-1, W"J1245"), W"Times"(-1, W"J1346"), W"J2356")]
180+
####WE just want to see that the numbers can be computed
181+
Mat * P14
182+
P14 * Mat
183+
P14 * Mat* P14
184+
end

0 commit comments

Comments
 (0)