-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathcomplex.clj
141 lines (128 loc) · 4 KB
/
complex.clj
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
136
137
138
139
140
141
(ns piplin.types.complex
(:require [piplin.types.core-impl :as impl])
(:use [piplin.types
[binops :only [defbinopimpl defcoercions defunopimpl]]
bits sints])
(:use [piplin [types :exclude [cast]] protocols])
(:use [slingshot.slingshot]))
(defpiplintype Complex [real imag])
(defn complex
"Makes a new complex number type
with the real part having type `real`
and the imaginary part having type `imag`.
`real` and `imag` must support addition,
subtraction, and multiplication."
[real imag]
(merge (Complex. real imag)
{:kind :complex}))
(defn real-part
"Returns the real part of a complex number."
[complex]
(if (pipinst? complex)
(first (value complex))
(mkast (:real (typeof complex))
:real-part
[complex]
real-part)))
(defn imag-part
"Returns the real part of a complex number."
[complex]
(if (pipinst? complex)
(second (value complex))
(mkast (:imag (typeof complex))
:imag-part
[complex]
imag-part)))
(defmethod constrain
:complex
[complex init-val]
(let [{:keys [real imag]} complex
[real-val imag-val] init-val]
[(instance real (constrain real (value real-val)))
(instance imag (constrain imag (value imag-val)))]))
(defmethod check
:complex
[inst]
(let [{:keys [real imag]} (typeof inst)
[real-val imag-val] (value inst)]
[(check real-val)
(check imag-val)]))
(defmethod promote
:complex
[this obj]
(let [{:keys [real imag]} this]
(cond
(= (typeof obj) this) obj
(and (vector? obj)
(= 2 (count obj)))
(let [[r i] obj]
(instance this [(promote real r)
(promote imag i)]))
(= (kindof obj) (:kind this))
(throw+ (error (str "Cannot convert " obj " to " this)))
:else (throw+ (error "Don't know how to promote to" this "from"
(typeof obj))))))
(defbinopimpl impl/+ :complex []
[x y]
(let [[r1 i1] (value x)
[r2 i2] (value y)]
[(impl/+ r1 r2)
(impl/+ i1 i2)]))
(defbinopimpl impl/- :complex []
[x y]
(let [[r1 i1] (value x)
[r2 i2] (value y)]
[(impl/- r1 r2)
(impl/- i1 i2)]))
(defbinopimpl impl/* :complex []
[x y]
(let [[r1 i1] (value x)
[r2 i2] (value y)]
[(impl/- (impl/* r1 r2) (impl/* i1 i2))
(impl/+ (impl/* i1 r2) (impl/* r1 i2))]))
(defmethod bit-width-of
:complex
[type]
(+ (bit-width-of (:real type))
(bit-width-of (:imag type))))
(defmethod get-bits
:complex
[expr]
(let [[r i] (value expr)]
(value (bit-cat (serialize r) (serialize i)))))
(defmethod from-bits
:complex
[type bits]
(let [bits (instance
(piplin.types.bits/bits (count bits))
bits)
{:keys [real imag]} type
imag-len (bit-width-of imag)
imag-bits (bit-slice bits 0 imag-len)
real-bits (bit-slice
bits
imag-len
(bit-width-of (typeof bits)))]
[(from-bits real real-bits) (from-bits imag imag-bits)]))
#_(let [disp #(let [[a b] (value %)
a (value a)
b (value b)]
(str (/ a (Math/pow 2 8)) \space
(/ b (Math/pow 2 8)) \i))
sfxpts-type (piplin.types.sfxpts/sfxpts 8 8)
c1 (piplin.types/cast (complex sfxpts-type sfxpts-type)
[2.0 2.0])
c2 (piplin.types/cast (complex sfxpts-type sfxpts-type)
[2.8 1.5])]
(println "c1 =" (disp c1))
(println "c2 =" (disp c2))
(println "c1 + c1 =" (disp (impl/+ c1 c1)))
(println "c1 + c2 =" (disp (impl/+ c1 c2)))
(println "c2 + c1 =" (disp (impl/+ c1 c2)))
(println "c1 * c1 =" (disp (impl/* c1 c1)))
(println "c1 * c2 =" (disp (impl/* c1 c2)))
(println "c2 * c1 =" (disp (impl/* c1 c2)))
(println "c1 * c2 * c2 =" (disp (impl/* c1 c2 c2)))
(println "c1 * c2 * c2 + c1=" (disp (impl/+ c1 (impl/* c1 c2 c2))))
(deserialize (complex sfxpts-type sfxpts-type) (serialize c1))
)