@@ -126,6 +126,41 @@ mp_float_t mp_obj_float_get(mp_obj_t self_in) {
126126 return self -> value ;
127127}
128128
129+ STATIC void mp_obj_float_divmod (mp_float_t * x , mp_float_t * y ) {
130+ // logic here follows that of CPython
131+ // https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations
132+ // x == (x//y)*y + (x%y)
133+ // divmod(x, y) == (x//y, x%y)
134+ mp_float_t mod = MICROPY_FLOAT_C_FUN (fmod )(* x , * y );
135+ mp_float_t div = (* x - mod ) / * y ;
136+
137+ // Python specs require that mod has same sign as second operand
138+ if (mod == 0.0 ) {
139+ mod = MICROPY_FLOAT_C_FUN (copysign )(0.0 , * y );
140+ } else {
141+ if ((mod < 0.0 ) != (* y < 0.0 )) {
142+ mod += * y ;
143+ div -= 1.0 ;
144+ }
145+ }
146+
147+ mp_float_t floordiv ;
148+ if (div == 0.0 ) {
149+ // if division is zero, take the correct sign of zero
150+ floordiv = MICROPY_FLOAT_C_FUN (copysign )(0.0 , * x / * y );
151+ } else {
152+ // Python specs require that x == (x//y)*y + (x%y)
153+ floordiv = MICROPY_FLOAT_C_FUN (floor )(div );
154+ if (div - floordiv > 0.5 ) {
155+ floordiv += 1.0 ;
156+ }
157+ }
158+
159+ // return results
160+ * x = floordiv ;
161+ * y = mod ;
162+ }
163+
129164mp_obj_t mp_obj_float_binary_op (mp_uint_t op , mp_float_t lhs_val , mp_obj_t rhs_in ) {
130165 mp_float_t rhs_val = mp_obj_get_float (rhs_in ); // can be any type, this function will convert to float (if possible)
131166 switch (op ) {
@@ -170,6 +205,17 @@ mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_i
170205 break ;
171206 case MP_BINARY_OP_POWER :
172207 case MP_BINARY_OP_INPLACE_POWER : lhs_val = MICROPY_FLOAT_C_FUN (pow )(lhs_val , rhs_val ); break ;
208+ case MP_BINARY_OP_DIVMOD : {
209+ if (rhs_val == 0 ) {
210+ goto zero_division_error ;
211+ }
212+ mp_obj_float_divmod (& lhs_val , & rhs_val );
213+ mp_obj_t tuple [2 ] = {
214+ mp_obj_new_float (lhs_val ),
215+ mp_obj_new_float (rhs_val ),
216+ };
217+ return mp_obj_new_tuple (2 , tuple );
218+ }
173219 case MP_BINARY_OP_LESS : return MP_BOOL (lhs_val < rhs_val );
174220 case MP_BINARY_OP_MORE : return MP_BOOL (lhs_val > rhs_val );
175221 case MP_BINARY_OP_EQUAL : return MP_BOOL (lhs_val == rhs_val );
@@ -182,39 +228,4 @@ mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_i
182228 return mp_obj_new_float (lhs_val );
183229}
184230
185- void mp_obj_float_divmod (mp_float_t * x , mp_float_t * y ) {
186- // logic here follows that of CPython
187- // https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations
188- // x == (x//y)*y + (x%y)
189- // divmod(x, y) == (x//y, x%y)
190- mp_float_t mod = MICROPY_FLOAT_C_FUN (fmod )(* x , * y );
191- mp_float_t div = (* x - mod ) / * y ;
192-
193- // Python specs require that mod has same sign as second operand
194- if (mod == 0.0 ) {
195- mod = MICROPY_FLOAT_C_FUN (copysign )(0.0 , * y );
196- } else {
197- if ((mod < 0.0 ) != (* y < 0.0 )) {
198- mod += * y ;
199- div -= 1.0 ;
200- }
201- }
202-
203- mp_float_t floordiv ;
204- if (div == 0.0 ) {
205- // if division is zero, take the correct sign of zero
206- floordiv = MICROPY_FLOAT_C_FUN (copysign )(0.0 , * x / * y );
207- } else {
208- // Python specs require that x == (x//y)*y + (x%y)
209- floordiv = MICROPY_FLOAT_C_FUN (floor )(div );
210- if (div - floordiv > 0.5 ) {
211- floordiv += 1.0 ;
212- }
213- }
214-
215- // return results
216- * x = floordiv ;
217- * y = mod ;
218- }
219-
220231#endif // MICROPY_PY_BUILTINS_FLOAT
0 commit comments