Skip to content

Commit 110fc8a

Browse files
committed
Implement divmod and pow and check and fix interfaces for int, float, complex
1 parent c1b8923 commit 110fc8a

File tree

7 files changed

+339
-79
lines changed

7 files changed

+339
-79
lines changed

py/arithmetic.go

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111

1212
// Add two python objects together returning an Object
1313
//
14-
// Will raise TypeError if can't be added
14+
// Will raise TypeError if can't be add can't be run on these objects
1515
func Add(a, b Object) Object {
1616
// Try using a to add
1717
A, ok := a.(I__add__)
@@ -51,7 +51,7 @@ func IAdd(a, b Object) Object {
5151

5252
// Sub two python objects together returning an Object
5353
//
54-
// Will raise TypeError if can't be subed
54+
// Will raise TypeError if can't be sub can't be run on these objects
5555
func Sub(a, b Object) Object {
5656
// Try using a to sub
5757
A, ok := a.(I__sub__)
@@ -91,7 +91,7 @@ func ISub(a, b Object) Object {
9191

9292
// Mul two python objects together returning an Object
9393
//
94-
// Will raise TypeError if can't be muled
94+
// Will raise TypeError if can't be mul can't be run on these objects
9595
func Mul(a, b Object) Object {
9696
// Try using a to mul
9797
A, ok := a.(I__mul__)
@@ -131,7 +131,7 @@ func IMul(a, b Object) Object {
131131

132132
// TrueDiv two python objects together returning an Object
133133
//
134-
// Will raise TypeError if can't be truedived
134+
// Will raise TypeError if can't be truediv can't be run on these objects
135135
func TrueDiv(a, b Object) Object {
136136
// Try using a to truediv
137137
A, ok := a.(I__truediv__)
@@ -171,7 +171,7 @@ func ITrueDiv(a, b Object) Object {
171171

172172
// FloorDiv two python objects together returning an Object
173173
//
174-
// Will raise TypeError if can't be floordived
174+
// Will raise TypeError if can't be floordiv can't be run on these objects
175175
func FloorDiv(a, b Object) Object {
176176
// Try using a to floordiv
177177
A, ok := a.(I__floordiv__)
@@ -211,7 +211,7 @@ func IFloorDiv(a, b Object) Object {
211211

212212
// Mod two python objects together returning an Object
213213
//
214-
// Will raise TypeError if can't be moded
214+
// Will raise TypeError if can't be mod can't be run on these objects
215215
func Mod(a, b Object) Object {
216216
// Try using a to mod
217217
A, ok := a.(I__mod__)
@@ -249,9 +249,37 @@ func IMod(a, b Object) Object {
249249
return Mod(a, b)
250250
}
251251

252+
// DivMod two python objects together returning an Object
253+
//
254+
// Will raise TypeError if can't be divmod can't be run on these objects
255+
func DivMod(a, b Object) (Object, Object) {
256+
// Try using a to divmod
257+
A, ok := a.(I__divmod__)
258+
if ok {
259+
res, res2 := A.M__divmod__(b)
260+
if res != NotImplemented {
261+
return res, res2
262+
}
263+
}
264+
265+
// Now using b to rdivmod if different in type to a
266+
if a.Type() != b.Type() {
267+
B, ok := b.(I__rdivmod__)
268+
if ok {
269+
res, res2 := B.M__rdivmod__(a)
270+
if res != NotImplemented {
271+
return res, res2
272+
}
273+
}
274+
}
275+
276+
// FIXME should be TypeError
277+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for divmod: '%s' and '%s'", a.Type().Name, b.Type().Name))
278+
}
279+
252280
// Lshift two python objects together returning an Object
253281
//
254-
// Will raise TypeError if can't be lshifted
282+
// Will raise TypeError if can't be lshift can't be run on these objects
255283
func Lshift(a, b Object) Object {
256284
// Try using a to lshift
257285
A, ok := a.(I__lshift__)
@@ -291,7 +319,7 @@ func ILshift(a, b Object) Object {
291319

292320
// Rshift two python objects together returning an Object
293321
//
294-
// Will raise TypeError if can't be rshifted
322+
// Will raise TypeError if can't be rshift can't be run on these objects
295323
func Rshift(a, b Object) Object {
296324
// Try using a to rshift
297325
A, ok := a.(I__rshift__)
@@ -331,7 +359,7 @@ func IRshift(a, b Object) Object {
331359

332360
// And two python objects together returning an Object
333361
//
334-
// Will raise TypeError if can't be anded
362+
// Will raise TypeError if can't be and can't be run on these objects
335363
func And(a, b Object) Object {
336364
// Try using a to and
337365
A, ok := a.(I__and__)
@@ -371,7 +399,7 @@ func IAnd(a, b Object) Object {
371399

372400
// Xor two python objects together returning an Object
373401
//
374-
// Will raise TypeError if can't be xored
402+
// Will raise TypeError if can't be xor can't be run on these objects
375403
func Xor(a, b Object) Object {
376404
// Try using a to xor
377405
A, ok := a.(I__xor__)
@@ -411,7 +439,7 @@ func IXor(a, b Object) Object {
411439

412440
// Or two python objects together returning an Object
413441
//
414-
// Will raise TypeError if can't be ored
442+
// Will raise TypeError if can't be or can't be run on these objects
415443
func Or(a, b Object) Object {
416444
// Try using a to or
417445
A, ok := a.(I__or__)
@@ -448,3 +476,45 @@ func IOr(a, b Object) Object {
448476
}
449477
return Or(a, b)
450478
}
479+
480+
// Pow three python objects together returning an Object
481+
//
482+
// If c != None then it won't attempt to call __rpow__
483+
//
484+
// Will raise TypeError if can't be pow can't be run on these objects
485+
func Pow(a, b, c Object) Object {
486+
// Try using a to pow
487+
A, ok := a.(I__pow__)
488+
if ok {
489+
res := A.M__pow__(b, c)
490+
if res != NotImplemented {
491+
return res
492+
}
493+
}
494+
495+
// Now using b to rpow if different in type to a
496+
if c == None && a.Type() != b.Type() {
497+
B, ok := b.(I__rpow__)
498+
if ok {
499+
res := B.M__rpow__(a)
500+
if res != NotImplemented {
501+
return res
502+
}
503+
}
504+
}
505+
506+
// FIXME should be TypeError
507+
panic(fmt.Sprintf("TypeError: unsupported operand type(s) for ** or pow(): '%s' and '%s'", a.Type().Name, b.Type().Name))
508+
}
509+
510+
// Inplace pow
511+
func IPow(a, b, c Object) Object {
512+
A, ok := a.(I__ipow__)
513+
if ok {
514+
res := A.M__ipow__(b, c)
515+
if res != NotImplemented {
516+
return res
517+
}
518+
}
519+
return Pow(a, b, c)
520+
}

py/complex.go

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package py
44

55
import (
66
"math"
7+
"math/cmplx"
78
)
89

910
var ComplexType = NewType("complex64")
@@ -65,7 +66,7 @@ func (a Complex) M__rsub__(other Object) Object {
6566
return NotImplemented
6667
}
6768

68-
func (a Complex) M__isub(other Object) Object {
69+
func (a Complex) M__isub__(other Object) Object {
6970
return a.M__sub__(other)
7071
}
7172

@@ -98,7 +99,7 @@ func (a Complex) M__rtruediv__(other Object) Object {
9899
return NotImplemented
99100
}
100101

101-
func (a Complex) M__itruediv(other Object) Object {
102+
func (a Complex) M__itruediv__(other Object) Object {
102103
return Complex(a).M__truediv__(other)
103104
}
104105

@@ -128,31 +129,71 @@ func (a Complex) M__rfloordiv__(other Object) Object {
128129
return NotImplemented
129130
}
130131

131-
func (a Complex) M__ifloordiv(other Object) Object {
132+
func (a Complex) M__ifloordiv__(other Object) Object {
132133
return a.M__floordiv__(other)
133134
}
134135

135136
// Does Mod of two floating point numbers
136-
func complexMod(a, b Complex) Complex {
137+
func complexDivMod(a, b Complex) (Complex, Complex) {
137138
q := complexFloor(a / b)
138139
r := a - Complex(q)*b
139-
return Complex(r)
140+
return q, Complex(r)
140141
}
141142

142143
func (a Complex) M__mod__(other Object) Object {
143144
if b, ok := convertToComplex(other); ok {
144-
return complexMod(a, b)
145+
_, r := complexDivMod(a, b)
146+
return r
145147
}
146148
return NotImplemented
147149
}
148150

149151
func (a Complex) M__rmod__(other Object) Object {
150152
if b, ok := convertToComplex(other); ok {
151-
return complexMod(b, a)
153+
_, r := complexDivMod(b, a)
154+
return r
152155
}
153156
return NotImplemented
154157
}
155158

156-
func (a Complex) M__imod(other Object) Object {
159+
func (a Complex) M__imod__(other Object) Object {
157160
return a.M__mod__(other)
158161
}
162+
163+
func (a Complex) M__divmod__(other Object) (Object, Object) {
164+
if b, ok := convertToComplex(other); ok {
165+
return complexDivMod(a, b)
166+
}
167+
return NotImplemented, None
168+
}
169+
170+
func (a Complex) M__rdivmod__(other Object) (Object, Object) {
171+
if b, ok := convertToComplex(other); ok {
172+
return complexDivMod(b, a)
173+
}
174+
return NotImplemented, None
175+
}
176+
177+
func (a Complex) M__pow__(other, modulus Object) Object {
178+
if modulus != None {
179+
return NotImplemented
180+
}
181+
if b, ok := convertToComplex(other); ok {
182+
return Complex(cmplx.Pow(complex128(a), complex128(b)))
183+
}
184+
return NotImplemented
185+
}
186+
187+
func (a Complex) M__rpow__(other Object) Object {
188+
if b, ok := convertToComplex(other); ok {
189+
return Complex(cmplx.Pow(complex128(b), complex128(a)))
190+
}
191+
return NotImplemented
192+
}
193+
194+
func (a Complex) M__ipow__(other, modulus Object) Object {
195+
return a.M__pow__(other, modulus)
196+
}
197+
198+
// Check interface is satisfied
199+
var _ floatArithmetic = Complex(complex(0, 0))

py/float.go

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func (a Float) M__rsub__(other Object) Object {
6565
return NotImplemented
6666
}
6767

68-
func (a Float) M__isub(other Object) Object {
68+
func (a Float) M__isub__(other Object) Object {
6969
return a.M__sub__(other)
7070
}
7171

@@ -98,7 +98,7 @@ func (a Float) M__rtruediv__(other Object) Object {
9898
return NotImplemented
9999
}
100100

101-
func (a Float) M__itruediv(other Object) Object {
101+
func (a Float) M__itruediv__(other Object) Object {
102102
return Float(a).M__truediv__(other)
103103
}
104104

@@ -116,31 +116,71 @@ func (a Float) M__rfloordiv__(other Object) Object {
116116
return NotImplemented
117117
}
118118

119-
func (a Float) M__ifloordiv(other Object) Object {
119+
func (a Float) M__ifloordiv__(other Object) Object {
120120
return a.M__floordiv__(other)
121121
}
122122

123-
// Does Mod of two floating point numbers
124-
func floatMod(a, b Float) Float {
123+
// Does DivMod of two floating point numbers
124+
func floatDivMod(a, b Float) (Float, Float) {
125125
q := Float(math.Floor(float64(a / b)))
126126
r := a - q*b
127-
return Float(r)
127+
return q, Float(r)
128128
}
129129

130130
func (a Float) M__mod__(other Object) Object {
131131
if b, ok := convertToFloat(other); ok {
132-
return floatMod(a, b)
132+
_, r := floatDivMod(a, b)
133+
return r
133134
}
134135
return NotImplemented
135136
}
136137

137138
func (a Float) M__rmod__(other Object) Object {
138139
if b, ok := convertToFloat(other); ok {
139-
return floatMod(b, a)
140+
_, r := floatDivMod(b, a)
141+
return r
140142
}
141143
return NotImplemented
142144
}
143145

144-
func (a Float) M__imod(other Object) Object {
146+
func (a Float) M__imod__(other Object) Object {
145147
return a.M__mod__(other)
146148
}
149+
150+
func (a Float) M__divmod__(other Object) (Object, Object) {
151+
if b, ok := convertToFloat(other); ok {
152+
return floatDivMod(a, b)
153+
}
154+
return NotImplemented, None
155+
}
156+
157+
func (a Float) M__rdivmod__(other Object) (Object, Object) {
158+
if b, ok := convertToFloat(other); ok {
159+
return floatDivMod(b, a)
160+
}
161+
return NotImplemented, None
162+
}
163+
164+
func (a Float) M__pow__(other, modulus Object) Object {
165+
if modulus != None {
166+
return NotImplemented
167+
}
168+
if b, ok := convertToFloat(other); ok {
169+
return Float(math.Pow(float64(a), float64(b)))
170+
}
171+
return NotImplemented
172+
}
173+
174+
func (a Float) M__rpow__(other Object) Object {
175+
if b, ok := convertToFloat(other); ok {
176+
return Float(math.Pow(float64(b), float64(a)))
177+
}
178+
return NotImplemented
179+
}
180+
181+
func (a Float) M__ipow__(other, modulus Object) Object {
182+
return a.M__pow__(other, modulus)
183+
}
184+
185+
// Check interface is satisfied
186+
var _ floatArithmetic = Float(0)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy