debuggings
[software/python-on-guile.git] / modules / language / python / number.scm
1 (define-module (language python number)
2 #:use-module (oop pf-objects)
3 #:use-module (oop goops)
4 #:use-module (language python hash)
5 #:use-module (language python list)
6 #:use-module (language python try)
7 #:use-module (language python exceptions)
8 #:use-module (language python persist)
9 #:export (py-int py-float py-complex
10 py-/ py-logand py-logior py-logxor py-abs py-trunc
11 py-lshift py-rshift py-mod py-floordiv py-round py-iadd
12 py-lognot py-matmul
13 <py-int> <py-float> <py-complex>
14 py-divmod pyfloat-listing pyint-listing pycomplex-listing
15 py-as-integer-ratio py-conjugate py-fromhex py-hex py-imag
16 py-is-integer py-real hex py-bin py-index
17 py-ifloordiv py-ilshift py-imod py-imul py-imatmul
18 py-ilogior py-ilogand py-ipow py-isub py-i/
19 py-irshift py-ilogxor))
20
21 (define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))
22
23 (define-syntax-rule (mki py-iadd __iadd__)
24 (define (py-iadd x y)
25 ((ref x '__iadd__) y)))
26
27 (mki py-iadd __iadd__)
28
29 (mki py-matmul __matmul__)
30 (mki py-ifloordiv __ifloordiv__)
31 (mki py-ilshift __ilshift__)
32 (mki py-imod __imod__)
33 (mki py-imul __imul__)
34 (mki py-imatmul __imatmul__)
35 (mki py-ilogior __ior__)
36 (mki py-ilogand __iand__)
37 (mki py-ipow __ipow__)
38 (mki py-isub __isub__)
39 (mki py-irshift __irshift__)
40 (mki py-ilogxor __ixor__)
41 (mki py-i/ __itruediv__)
42
43
44 (define-class <py-int> () x)
45 (define-class <py-float> () x)
46 (define-class <py-complex> () x)
47
48 (name-object <py-int>)
49 (name-object <py-float>)
50 (name-object <py-complex>)
51
52 (define-syntax-rule (mk <py-int>)
53 (cpit <py-int> (o (lambda (o x) (slot-set! o 'x x)) (list (slot-ref o 'x)))))
54
55 (mk <py-int>)
56 (mk <py-float>)
57 (mk <py-complex>)
58
59 (define-syntax-rule (b0 op)
60 (begin
61 (define-method (op (o1 <py-int>) o2)
62 (op (slot-ref o1 'x) o2))
63 (define-method (op (o1 <py-float>) o2)
64 (op (slot-ref o1 'x) o2))
65 (define-method (op (o1 <py-complex>) o2)
66 (op (slot-ref o1 'x) o2))
67 (define-method (op o2 (o1 <py-int>))
68 (op o2 (slot-ref o1 'x)))
69 (define-method (op o2 (o1 <py-complex>))
70 (op o2 (slot-ref o1 'x)))
71 (define-method (op o2 (o1 <py-float>))
72 (op o2 (slot-ref o1 'x)))))
73
74 (define-syntax-rule (mk-biop1 mk-biop0 op r1)
75 (begin
76 (mk-biop0 op)
77 (define-method (op (o <p>) v)
78 (aif it (ref o 'r1)
79 (it v)
80 (next-method)))))
81
82 (define-syntax-rule (mk-biop2 mk-biop0 rop op r1 r2)
83 (begin
84 (define-syntax-rule (rop x y) (op y x))
85 (mk-biop1 mk-biop0 op r1)
86 (define-method (op v (o <p>))
87 (aif it (ref o 'r2)
88 (it v)
89 (next-method)))))
90
91 (define-syntax-rule (i0 op)
92 (begin
93 (define-method (op (o1 <py-int>) o2)
94 (op (slot-ref o1 'x) o2))
95 (define-method (op o2 (o1 <py-int>))
96 (op o2 (slot-ref o1 'x)))))
97
98
99 (mk-biop2 b0 r+ + __add__ __radd__)
100 (mk-biop2 b0 r- - __sub__ __rsub__)
101 (mk-biop2 b0 r* * __mul__ __rmul__)
102
103 (mk-biop1 b0 < __le__)
104 (mk-biop1 b0 > __ge__)
105 (mk-biop1 b0 <= __lt__)
106 (mk-biop1 b0 >= __gt__)
107 (mk-biop2 b0 rexpt expt __pow__ __rpow__)
108 (b0 py-equal?)
109
110
111 (define-method (py-lshift (o1 <integer>) (o2 <integer>))
112 (ash o1 o2))
113 (define-method (py-rshift (o1 <integer>) (o2 <integer>))
114 (ash o1 (- o2)))
115
116 (mk-biop2 i0 py-rlshift py-lshift __lshift__ __rlshift__)
117 (mk-biop2 i0 py-rrshift py-rshift __rshift__ __rrshift__)
118
119 (define-method (py-logand (o1 <integer>) (o2 <integer>))
120 (logand o1 o2))
121 (define-method (py-logior (o1 <integer>) (o2 <integer>))
122 (logior o1 o2))
123 (define-method (py-logxor (o1 <integer>) (o2 <integer>))
124 (logxor o1 o2))
125 (define-method (py-lognot (o1 <integer>))
126 (lognot o1))
127
128 (define-method (py-logand o1 (o2 <py-int>))
129 (py-logand o1 (slot-ref o2 'x)))
130
131 (define-method (py-logand (o1 <py-int>) o2)
132 (py-logand (slot-ref o1 'x) o2))
133
134 (define-method (py-logior o1 (o2 <py-int>))
135 (py-logior o1 (slot-ref o2 'x)))
136
137 (define-method (py-logior (o1 <py-int>) o2)
138 (py-logior (slot-ref o1 'x) o2))
139
140 (define-method (py-logxor o1 (o2 <py-int>))
141 (py-logxor o1 (slot-ref o2 'x)))
142
143 (define-method (py-logxor (o1 <py-int>) o2)
144 (py-logxor (slot-ref o1 'x) o2))
145
146 (define-method (py-lognot (o1 <py-int>))
147 (lognot (slot-ref o1 'x)))
148
149 (define-method (py-logand (o1 <p>) o2)
150 (aif it (ref o1 '__and__)
151 (it o2)
152 (next-method)))
153
154 (define-method (py-logand o1 (o2 <p>))
155 (aif it (ref o1 '__rand__)
156 (it o2)
157 (next-method)))
158
159 (define-method (py-logior (o1 <p>) o2)
160 (aif it (ref o1 '__or__)
161 (it o2)
162 (next-method)))
163
164 (define-method (py-logior o1 (o2 <p>))
165 (aif it (ref o1 '__ror__)
166 (it o2)
167 (next-method)))
168
169 (define-method (py-logxor (o1 <p>) o2)
170 (aif it (ref o1 '__xor__)
171 (it o2)
172 (next-method)))
173
174 (define-method (py-logxor o1 (o2 <p>))
175 (aif it (ref o1 '__rxor__)
176 (it o2)
177 (next-method)))
178
179 (define-method (py-lognot (o1 <p>))
180 (aif it (ref o1 '__not__)
181 (it)
182 (next-method)))
183
184
185 (define-method (py-/ (o1 <number>) (o2 <integer>))
186 (/ o1 (exact->inexact o2)))
187 (define-method (py-/ (o1 <number>) (o2 <number>))
188 (/ o1 o2))
189
190 (define-method (py-divmod (o1 <integer>) (o2 <integer>))
191 (values
192 (floor-quotient o1 o2)
193 (modulo o1 o2)))
194
195 (define-method (py-divmod (o1 <number>) (o2 <number>))
196 (values
197 (floor-quotient o1 o2)
198 (floor-remainder o1 o2)))
199
200 (define-method (py-floordiv (o1 <number>) (o2 <number>))
201 (floor-quotient o1 o2))
202
203 (mk-biop2 b0 py-rfloordiv py-floordiv __floordiv__ __rfloordiv__)
204 (mk-biop2 b0 py-rdivmod py-divmod __divmod__ __rdivmod__)
205 (mk-biop2 b0 py-r/ py-/ __truediv__ __rtruediv__)
206
207 (mk-biop2 i0 py-rlogand py-logand __and__ __rand__)
208 (mk-biop2 i0 py-rlogior py-logior __or__ __ror__)
209 (mk-biop2 i0 py-rlogxor py-logxor __xor__ __rxor__)
210
211 (define-method (py-mod (o1 <integer>) (o2 <integer>))
212 (modulo o1 o2))
213 (define-method (py-mod (o1 <real>) (o2 <real>))
214 (floor-remainder o1 o2))
215
216 (mk-biop2 i0 py-rmod py-mod __mod__ __rmod__)
217
218
219 (define-method (py-floor (o1 <integer>)) o1)
220 (define-method (py-floor (o1 <number> )) )
221 (define-method (py-trunc (o1 <integer>)) (exact->inexact o1))
222 (define-method (py-trunc (o1 <number> ))
223 (floor o1))
224
225 (define-syntax-rule (u0 f)
226 (begin
227 (define-method (f (o <py-int> )) (f (slot-ref o 'x)))
228 (define-method (f (o <py-float>)) (f (slot-ref o 'x)))
229 (define-method (f (o <py-complex>)) (f (slot-ref o 'x)))))
230
231 (define-syntax-rule (i0 f)
232 (begin
233 (define-method (f (o <py-int> )) (f (slot-ref o 'x)))))
234
235 (define-syntax-rule (mk-unop u0 f r)
236 (begin
237 (u0 f)
238 (define-method (f (o <p>))
239 ((ref o 'r)))))
240
241 (u0 py-hash )
242 (mk-unop u0 - __neg__ )
243 (mk-unop u0 py-trunc __trunc__ )
244 (mk-unop i0 py-lognot __invert__)
245
246 (define-method (py-bit-length (i <integer>))
247 (logcount i))
248
249 (define-method (py-conjugate (i <complex>))
250 (make-rectangular (real-part i) (- (imag-part i))))
251 (define-method (py-conjugate (i <number>)) i)
252
253 (define-method (py-imag (i <complex>)) (imag-part i))
254 (define-method (py-imag (i <number>)) i)
255
256 (define-method (py-real (i <complex>)) (real-part i))
257 (define-method (py-real (i <number>)) i)
258
259 (define-method (py-denominator (o <integer>)) 0)
260 (define-method (py-denominator (o <real>))
261 (denominator (inexact->exact o)))
262
263 (define-method (py-numerator (o <integer>)) o)
264 (define-method (py-numerator (o <real> ))
265 (numerator (inexact->exact o)))
266
267 (define-method (py-as-integer-ratio (o <integer>))
268 (list o 0))
269 (define-method (py-as-integer-ratio (o <real>))
270 (let ((r (inexact->exact o)))
271 (list (numerator r) (denominator r))))
272
273 (define-method (py-fromhex (o <real>))
274 (error "1.2.fromhex('0x1.ap4') is not implemented"))
275
276 (define (py-hex x)
277 (+ "0x" (number->string (py-index x) 16)))
278
279 (define-method (py-is-integer (o <real>))
280 (= 1 (denominator (inexact->exact o))))
281 (define-method (py-is-integer (o <integer>)) #t)
282
283 (define-method (hex (o <integer>))
284 (+ "0x" (number->string o 16)))
285
286 (define-method (py-abs (o <complex>))
287 (magnitude o))
288 (define-method (py-abs (o <number>))
289 (abs o))
290 (define-method (py-index (o <integer>)) o)
291 (mk-unop u0 py-abs __abs__)
292 (mk-unop u0 py-conjugate conjugate)
293 (mk-unop u0 py-imag imag)
294 (mk-unop u0 py-real real)
295 (mk-unop u0 py-denominator denominator)
296 (mk-unop u0 py-numerator numerator)
297 (mk-unop u0 py-as-integer-ratio as_integer_ratio)
298 (mk-unop u0 py-fromhex fromhex)
299 (mk-unop i0 hex __hex__)
300 (mk-unop u0 py-is-integer is_integer)
301 (mk-unop u0 py-index __index__)
302
303 (define-method (write (o <py-float>) . l)
304 (apply write (slot-ref o 'x) l))
305 (define-method (write (o <py-int>) . l)
306 (apply write (slot-ref o 'x) l))
307
308 (define-python-class int (<py> <py-int>)
309 (define __new__
310 (letrec ((__new__
311 (case-lambda
312 ((self)
313 0)
314
315 ((self n)
316 (let lp ((n n))
317 (cond
318 ((and (number? n) (integer? n))
319 n)
320 ((boolean? n)
321 (if n 1 0))
322 ((number? n)
323 (lp (py-floor n)))
324 ((string? n)
325 (lp (string->number n)))
326 (else
327 (catch #t
328 (lambda ()
329 (aif it (slot-ref n '__int__)
330 it
331 (raise (ValueError (py-mod "could not make int from %r"
332 (list n))))))
333 (lambda z (raise (ValueError (py-mod "could not make int from %r"
334 (list n))))))))))
335
336 ((self n k)
337 (__new__ self (string->number n k))))))
338 __new__)))
339
340 (name-object int)
341
342 (define (proj? x)
343 (if (number? x)
344 x
345 (and
346 (or (is-a? x <py-complex>)
347 (is-a? x <py-int>)
348 (is-a? x <py-float>))
349 (slot-ref x 'x))))
350
351 (define (projc? x)
352 (if (number? x)
353 (if (not (complex? x))
354 x
355 #f)
356 (and
357 (or (is-a? x <py-complex>)
358 (is-a? x <py-int>)
359 (is-a? x <py-float>))
360 (let ((ret (slot-ref x 'x)))
361 (if (not (complex? ret))
362 ret
363 #f)))))
364
365 (define-python-class float (<py> <py-float>)
366 (define __init__
367 (case-lambda
368 ((self n)
369 (let lp ((n n))
370 (cond
371 ((projc? n) =>
372 (lambda (n)
373 (slot-set! self 'x n)))
374 ((string? n)
375 (lp (string->number n)))
376 (else
377 (aif it (slot-ref n '__float__)
378 (slot-set! self 'x it)
379 (raise ValueError "could not make float from " n)))))))))
380
381 (name-object float)
382
383 (define-python-class py-complex (<py> <py-complex>)
384 (define __init__
385 (case-lambda
386 ((self n)
387 (cond
388 ((proj? n) =>
389 (lambda (n)
390 (slot-set! self 'x n)))
391 (else
392 (raise ValueError "could not make complex from " n))))
393 ((self n m)
394 (cond
395 ((projc? n) =>
396 (lambda (n)
397 (cond
398 ((projc? m)
399 (lambda (m)
400 (slot-set! self 'x (make-rectangular n m))))
401 (else
402 (raise ValueError "could not make complex from " n m)))))
403 (else
404 (raise ValueError "could not make complex from " n m)))))))
405
406 (name-object py-complex)
407
408 (define-method (py-class (o <integer> )) int)
409 (define-method (py-class (o <real> )) float)
410 (u0 py-class)
411
412 (define py-int int)
413 (define py-float float)
414
415 (define-method (mk-int (o <number>)) (slot-ref (py-int o) 'x))
416 (define-method (mk-float (o <number>)) (slot-ref (py-float o) 'x))
417
418 (mk-unop u0 mk-int __int__)
419 (mk-unop u0 mk-float __float__)
420
421 (define (pyint-listing)
422 (let ((l
423 (to-pylist
424 (map symbol->string
425 '(__abs__ __add__ __and__ __class__ __cmp__ __coerce__
426 __delattr__ __div__ __divmod__ __doc__ __float__
427 __floordiv__ __format__ __getattribute__
428 __getnewargs__ __hash__ __hex__ __index__ __init__
429 __int__ __invert__ __long__ __lshift__ __mod__
430 __mul__ __neg__ __new__ __nonzero__ __oct__ __or__
431 __pos__ __pow__ __radd__ __rand__ __rdiv__
432 __rdivmod__ __reduce__ __reduce_ex__ __repr__
433 __rfloordiv__ __rlshift__ __rmod__ __rmul__ __ror__
434 __rpow__ __rrshift__ __rshift__ __rsub__ __rtruediv__
435 __rxor__ __setattr__ __sizeof__ __str__ __sub__
436 __subclasshook__ __truediv__ __trunc__ __xor__
437 bit_length conjugate denominator imag numerator
438 real)))))
439 (pylist-sort! l)
440 l))
441
442 (define (pyfloat-listing)
443 (let ((l
444 (to-pylist
445 (map symbol->string
446 '(__abs__ __add__ __class__ __coerce__ __delattr__ __div__
447 __divmod__ __doc__ __eq__ __float__ __floordiv__
448 __format__ __ge__ __getattribute__ __getformat__
449 __getnewargs__ __gt__ __hash__ __init__ __int__
450 __le__ __long__ __lt__ __mod__ __mul__ __ne__
451 __neg__ __new__ __nonzero__ __pos__ __pow__
452 __radd__ __rdiv__ __rdivmod__ __reduce__
453 __reduce_ex__ __repr__ __rfloordiv__ __rmod__
454 __rmul__ __rpow__ __rsub__ __rtruediv__
455 __setattr__ __setformat__ __sizeof__ __str__
456 __sub__ __subclasshook__ __truediv__ __trunc__
457 as_integer_ratio conjugate fromhex hex imag
458 is_integer real)))))
459 (pylist-sort! l)
460 l))
461
462 (define (pycomplex-listing)
463 (let ((l
464 (to-pylist
465 (map symbol->string
466 '(__abs__ __add__ __class__ __coerce__ __delattr__ __div__
467 __divmod__ __doc__ __eq__ __float__ __floordiv__
468 __format__ __ge__ __getattribute__ __getnewargs__
469 __gt__ __hash__ __init__ __int__ __le__ __long__
470 __lt__ __mod__ __mul__ __ne__ __neg__ __new__
471 __nonzero__ __pos__ __pow__ __radd__ __rdiv__
472 __rdivmod__ __reduce__ __reduce_ex__ __repr__
473 __rfloordiv__ __rmod__ __rmul__ __rpow__ __rsub__
474 __rtruediv__ __setattr__ __sizeof__ __str__
475 __sub__ __subclasshook__ __truediv__
476 conjugate imag real)))))
477 (pylist-sort! l)
478 l))
479
480 (define* (py-round x #:optional (digits 0))
481 (let* ((f (expt 10.0 digits)))
482 (if (equal? digits 0)
483 (round x)
484 (/ (round (* x f)) f))))
485
486 (define-method (py-bin (o <integer>))
487 (number->string o 2))
488 (define-method (py-bin (o <py-int>))
489 (number->string (slot-ref o 'x) 2))
490 (define (py-bin o)
491 (+ "0b" (number->string (py-index o) 2)))
492
493