Nuitka
The Python compiler
Loading...
Searching...
No Matches
HelpersOperationBinaryDivmod.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3/* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */
4
5/* This file is included from another C file, help IDEs to still parse it on its own. */
6#ifdef __IDE_ONLY__
7#include "nuitka/prelude.h"
8#endif
9
10#include "HelpersOperationBinaryDivmodUtils.c"
11/* C helpers for type specialized "divmod" (DIVMOD) operations */
12
13#if PYTHON_VERSION < 0x300
14/* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */
15static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) {
16 CHECK_OBJECT(operand1);
17 assert(PyInt_CheckExact(operand1));
18 CHECK_OBJECT(operand2);
19 assert(PyInt_CheckExact(operand2));
20
21 PyObject *result;
22
23 // Not every code path will make use of all possible results.
24#if defined(_MSC_VER)
25#pragma warning(push)
26#pragma warning(disable : 4101)
27#endif
28 NUITKA_MAY_BE_UNUSED bool cbool_result;
29 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
30 NUITKA_MAY_BE_UNUSED long clong_result;
31 NUITKA_MAY_BE_UNUSED double cfloat_result;
32#if defined(_MSC_VER)
33#pragma warning(pop)
34#endif
35
36 CHECK_OBJECT(operand1);
37 assert(PyInt_CheckExact(operand1));
38 CHECK_OBJECT(operand2);
39 assert(PyInt_CheckExact(operand2));
40
41 const long a = PyInt_AS_LONG(operand1);
42 const long b = PyInt_AS_LONG(operand2);
43
44 if (unlikely(b == 0)) {
45 PyThreadState *tstate = PyThreadState_GET();
46
47 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "integer division or modulo by zero");
48 goto exit_result_exception;
49 }
50
51 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
52 long a_div_b = a / b;
53 long a_mod_b = (long)(a - (unsigned long)a_div_b * b);
54
55 if (a_mod_b && (b ^ a_mod_b) < 0) {
56 a_mod_b += b;
57 a_div_b -= 1;
58 }
59
60 PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b);
61 obj_result = r;
62 goto exit_result_object;
63 }
64
65 {
66 PyObject *operand1_object = operand1;
67 PyObject *operand2_object = operand2;
68
69 PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object);
70 assert(r != Py_NotImplemented);
71
72 obj_result = r;
73 goto exit_result_object;
74 }
75
76exit_result_object:
77 if (unlikely(obj_result == NULL)) {
78 goto exit_result_exception;
79 }
80 result = obj_result;
81 goto exit_result_ok;
82
83exit_result_ok:
84 return result;
85
86exit_result_exception:
87 return NULL;
88}
89
90PyObject *BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(PyObject *operand1, PyObject *operand2) {
91 return _BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(operand1, operand2);
92}
93#endif
94
95#if PYTHON_VERSION < 0x300
96/* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */
97static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(PyObject *operand1,
98 PyObject *operand2) {
99 PyTypeObject *type1 = Py_TYPE(operand1);
100
101#if defined(_MSC_VER)
102#pragma warning(push)
103#pragma warning(disable : 4101)
104#endif
105 NUITKA_MAY_BE_UNUSED bool cbool_result;
106 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
107#if defined(_MSC_VER)
108#pragma warning(pop)
109#endif
110
111 binaryfunc slot1 =
112 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divmod : NULL;
113 binaryfunc slot2 = NULL;
114
115 if (!(type1 == &PyInt_Type)) {
116 // Different types, need to consider second value slot.
117
118 slot2 = PyInt_Type.tp_as_number->nb_divmod;
119
120 if (slot1 == slot2) {
121 slot2 = NULL;
122 }
123 }
124
125 if (slot1 != NULL) {
126 PyObject *x = slot1(operand1, operand2);
127
128 if (x != Py_NotImplemented) {
129 obj_result = x;
130 goto exit_binary_result_object;
131 }
132
133 Py_DECREF_IMMORTAL(x);
134 }
135
136 if (slot2 != NULL) {
137 PyObject *x = slot2(operand1, operand2);
138
139 if (x != Py_NotImplemented) {
140 obj_result = x;
141 goto exit_binary_result_object;
142 }
143
144 Py_DECREF_IMMORTAL(x);
145 }
146
147#if PYTHON_VERSION < 0x300
148 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
149 coercion c1 =
150 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
151
152 if (c1 != NULL) {
153 PyObject *coerced1 = operand1;
154 PyObject *coerced2 = operand2;
155
156 int err = c1(&coerced1, &coerced2);
157
158 if (unlikely(err < 0)) {
159 goto exit_binary_exception;
160 }
161
162 if (err == 0) {
163 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
164
165 if (likely(mv == NULL)) {
166 binaryfunc slot = mv->nb_divmod;
167
168 if (likely(slot != NULL)) {
169 PyObject *x = slot(coerced1, coerced2);
170
171 Py_DECREF(coerced1);
172 Py_DECREF(coerced2);
173
174 obj_result = x;
175 goto exit_binary_result_object;
176 }
177 }
178
179 // nb_coerce took a reference.
180 Py_DECREF(coerced1);
181 Py_DECREF(coerced2);
182 }
183 }
184 coercion c2 = PyInt_Type.tp_as_number->nb_coerce;
185
186 if (c2 != NULL) {
187 PyObject *coerced1 = operand1;
188 PyObject *coerced2 = operand2;
189
190 int err = c2(&coerced2, &coerced1);
191
192 if (unlikely(err < 0)) {
193 goto exit_binary_exception;
194 }
195
196 if (err == 0) {
197 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
198
199 if (likely(mv == NULL)) {
200 binaryfunc slot = mv->nb_divmod;
201
202 if (likely(slot != NULL)) {
203 PyObject *x = slot(coerced1, coerced2);
204
205 Py_DECREF(coerced1);
206 Py_DECREF(coerced2);
207
208 obj_result = x;
209 goto exit_binary_result_object;
210 }
211 }
212
213 // nb_coerce took a reference.
214 Py_DECREF(coerced1);
215 Py_DECREF(coerced2);
216 }
217 }
218 }
219#endif
220
221 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and 'int'", type1->tp_name);
222 goto exit_binary_exception;
223
224exit_binary_result_object:
225 return obj_result;
226
227exit_binary_exception:
228 return NULL;
229}
230static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) {
231 CHECK_OBJECT(operand1);
232 CHECK_OBJECT(operand2);
233 assert(PyInt_CheckExact(operand2));
234
235 PyTypeObject *type1 = Py_TYPE(operand1);
236
237 if (type1 == &PyInt_Type) {
238 PyObject *result;
239
240 // return _BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(operand1, operand2);
241
242 // Not every code path will make use of all possible results.
243#if defined(_MSC_VER)
244#pragma warning(push)
245#pragma warning(disable : 4101)
246#endif
247 NUITKA_MAY_BE_UNUSED bool cbool_result;
248 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
249 NUITKA_MAY_BE_UNUSED long clong_result;
250 NUITKA_MAY_BE_UNUSED double cfloat_result;
251#if defined(_MSC_VER)
252#pragma warning(pop)
253#endif
254
255 CHECK_OBJECT(operand1);
256 assert(PyInt_CheckExact(operand1));
257 CHECK_OBJECT(operand2);
258 assert(PyInt_CheckExact(operand2));
259
260 const long a = PyInt_AS_LONG(operand1);
261 const long b = PyInt_AS_LONG(operand2);
262
263 if (unlikely(b == 0)) {
264 PyThreadState *tstate = PyThreadState_GET();
265
266 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "integer division or modulo by zero");
267 goto exit_result_exception;
268 }
269
270 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
271 long a_div_b = a / b;
272 long a_mod_b = (long)(a - (unsigned long)a_div_b * b);
273
274 if (a_mod_b && (b ^ a_mod_b) < 0) {
275 a_mod_b += b;
276 a_div_b -= 1;
277 }
278
279 PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b);
280 obj_result = r;
281 goto exit_result_object;
282 }
283
284 {
285 PyObject *operand1_object = operand1;
286 PyObject *operand2_object = operand2;
287
288 PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object);
289 assert(r != Py_NotImplemented);
290
291 obj_result = r;
292 goto exit_result_object;
293 }
294
295 exit_result_object:
296 if (unlikely(obj_result == NULL)) {
297 goto exit_result_exception;
298 }
299 result = obj_result;
300 goto exit_result_ok;
301
302 exit_result_ok:
303 return result;
304
305 exit_result_exception:
306 return NULL;
307 }
308
309 return __BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(operand1, operand2);
310}
311
312PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(PyObject *operand1, PyObject *operand2) {
313 return _BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_INT(operand1, operand2);
314}
315#endif
316
317#if PYTHON_VERSION < 0x300
318/* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */
319static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(PyObject *operand1,
320 PyObject *operand2) {
321 PyTypeObject *type2 = Py_TYPE(operand2);
322
323#if defined(_MSC_VER)
324#pragma warning(push)
325#pragma warning(disable : 4101)
326#endif
327 NUITKA_MAY_BE_UNUSED bool cbool_result;
328 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
329#if defined(_MSC_VER)
330#pragma warning(pop)
331#endif
332
333 binaryfunc slot1 = PyInt_Type.tp_as_number->nb_divmod;
334 binaryfunc slot2 = NULL;
335
336 if (!(&PyInt_Type == type2)) {
337 // Different types, need to consider second value slot.
338
339 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divmod : NULL;
340
341 if (slot1 == slot2) {
342 slot2 = NULL;
343 }
344 }
345
346 if (slot1 != NULL) {
347 if (slot2 != NULL) {
348 if (Nuitka_Type_IsSubtype(type2, &PyInt_Type)) {
349 PyObject *x = slot2(operand1, operand2);
350
351 if (x != Py_NotImplemented) {
352 obj_result = x;
353 goto exit_binary_result_object;
354 }
355
356 Py_DECREF_IMMORTAL(x);
357 slot2 = NULL;
358 }
359 }
360
361 PyObject *x = slot1(operand1, operand2);
362
363 if (x != Py_NotImplemented) {
364 obj_result = x;
365 goto exit_binary_result_object;
366 }
367
368 Py_DECREF_IMMORTAL(x);
369 }
370
371 if (slot2 != NULL) {
372 PyObject *x = slot2(operand1, operand2);
373
374 if (x != Py_NotImplemented) {
375 obj_result = x;
376 goto exit_binary_result_object;
377 }
378
379 Py_DECREF_IMMORTAL(x);
380 }
381
382#if PYTHON_VERSION < 0x300
383 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
384 coercion c1 = PyInt_Type.tp_as_number->nb_coerce;
385
386 if (c1 != NULL) {
387 PyObject *coerced1 = operand1;
388 PyObject *coerced2 = operand2;
389
390 int err = c1(&coerced1, &coerced2);
391
392 if (unlikely(err < 0)) {
393 goto exit_binary_exception;
394 }
395
396 if (err == 0) {
397 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
398
399 if (likely(mv == NULL)) {
400 binaryfunc slot = mv->nb_divmod;
401
402 if (likely(slot != NULL)) {
403 PyObject *x = slot(coerced1, coerced2);
404
405 Py_DECREF(coerced1);
406 Py_DECREF(coerced2);
407
408 obj_result = x;
409 goto exit_binary_result_object;
410 }
411 }
412
413 // nb_coerce took a reference.
414 Py_DECREF(coerced1);
415 Py_DECREF(coerced2);
416 }
417 }
418 coercion c2 =
419 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
420
421 if (c2 != NULL) {
422 PyObject *coerced1 = operand1;
423 PyObject *coerced2 = operand2;
424
425 int err = c2(&coerced2, &coerced1);
426
427 if (unlikely(err < 0)) {
428 goto exit_binary_exception;
429 }
430
431 if (err == 0) {
432 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
433
434 if (likely(mv == NULL)) {
435 binaryfunc slot = mv->nb_divmod;
436
437 if (likely(slot != NULL)) {
438 PyObject *x = slot(coerced1, coerced2);
439
440 Py_DECREF(coerced1);
441 Py_DECREF(coerced2);
442
443 obj_result = x;
444 goto exit_binary_result_object;
445 }
446 }
447
448 // nb_coerce took a reference.
449 Py_DECREF(coerced1);
450 Py_DECREF(coerced2);
451 }
452 }
453 }
454#endif
455
456 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'int' and '%s'", type2->tp_name);
457 goto exit_binary_exception;
458
459exit_binary_result_object:
460 return obj_result;
461
462exit_binary_exception:
463 return NULL;
464}
465static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) {
466 CHECK_OBJECT(operand1);
467 assert(PyInt_CheckExact(operand1));
468 CHECK_OBJECT(operand2);
469
470 PyTypeObject *type2 = Py_TYPE(operand2);
471
472 if (&PyInt_Type == type2) {
473 PyObject *result;
474
475 // return _BINARY_OPERATION_DIVMOD_OBJECT_INT_INT(operand1, operand2);
476
477 // Not every code path will make use of all possible results.
478#if defined(_MSC_VER)
479#pragma warning(push)
480#pragma warning(disable : 4101)
481#endif
482 NUITKA_MAY_BE_UNUSED bool cbool_result;
483 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
484 NUITKA_MAY_BE_UNUSED long clong_result;
485 NUITKA_MAY_BE_UNUSED double cfloat_result;
486#if defined(_MSC_VER)
487#pragma warning(pop)
488#endif
489
490 CHECK_OBJECT(operand1);
491 assert(PyInt_CheckExact(operand1));
492 CHECK_OBJECT(operand2);
493 assert(PyInt_CheckExact(operand2));
494
495 const long a = PyInt_AS_LONG(operand1);
496 const long b = PyInt_AS_LONG(operand2);
497
498 if (unlikely(b == 0)) {
499 PyThreadState *tstate = PyThreadState_GET();
500
501 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "integer division or modulo by zero");
502 goto exit_result_exception;
503 }
504
505 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
506 long a_div_b = a / b;
507 long a_mod_b = (long)(a - (unsigned long)a_div_b * b);
508
509 if (a_mod_b && (b ^ a_mod_b) < 0) {
510 a_mod_b += b;
511 a_div_b -= 1;
512 }
513
514 PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b);
515 obj_result = r;
516 goto exit_result_object;
517 }
518
519 {
520 PyObject *operand1_object = operand1;
521 PyObject *operand2_object = operand2;
522
523 PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object);
524 assert(r != Py_NotImplemented);
525
526 obj_result = r;
527 goto exit_result_object;
528 }
529
530 exit_result_object:
531 if (unlikely(obj_result == NULL)) {
532 goto exit_result_exception;
533 }
534 result = obj_result;
535 goto exit_result_ok;
536
537 exit_result_ok:
538 return result;
539
540 exit_result_exception:
541 return NULL;
542 }
543
544 return __BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(operand1, operand2);
545}
546
547PyObject *BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(PyObject *operand1, PyObject *operand2) {
548 return _BINARY_OPERATION_DIVMOD_OBJECT_INT_OBJECT(operand1, operand2);
549}
550#endif
551
552/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */
553static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) {
554 CHECK_OBJECT(operand1);
555 assert(PyLong_CheckExact(operand1));
556 CHECK_OBJECT(operand2);
557 assert(PyLong_CheckExact(operand2));
558
559 PyObject *result;
560
561 // Not every code path will make use of all possible results.
562#if defined(_MSC_VER)
563#pragma warning(push)
564#pragma warning(disable : 4101)
565#endif
566 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
567 NUITKA_MAY_BE_UNUSED long clong_result;
568#if defined(_MSC_VER)
569#pragma warning(pop)
570#endif
571
572 PyObject *x = PyLong_Type.tp_as_number->nb_divmod(operand1, operand2);
573 assert(x != Py_NotImplemented);
574
575 obj_result = x;
576 goto exit_result_object;
577
578exit_result_object:
579 if (unlikely(obj_result == NULL)) {
580 goto exit_result_exception;
581 }
582 result = obj_result;
583 goto exit_result_ok;
584
585exit_result_ok:
586 return result;
587
588exit_result_exception:
589 return NULL;
590}
591
592PyObject *BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(PyObject *operand1, PyObject *operand2) {
593 return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(operand1, operand2);
594}
595
596/* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */
597static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(PyObject *operand1,
598 PyObject *operand2) {
599 PyTypeObject *type1 = Py_TYPE(operand1);
600
601#if defined(_MSC_VER)
602#pragma warning(push)
603#pragma warning(disable : 4101)
604#endif
605 NUITKA_MAY_BE_UNUSED bool cbool_result;
606 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
607#if defined(_MSC_VER)
608#pragma warning(pop)
609#endif
610
611 binaryfunc slot1 =
612 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divmod : NULL;
613 binaryfunc slot2 = NULL;
614
615 if (!(type1 == &PyLong_Type)) {
616 // Different types, need to consider second value slot.
617
618 slot2 = PyLong_Type.tp_as_number->nb_divmod;
619
620 if (slot1 == slot2) {
621 slot2 = NULL;
622 }
623 }
624
625 if (slot1 != NULL) {
626 PyObject *x = slot1(operand1, operand2);
627
628 if (x != Py_NotImplemented) {
629 obj_result = x;
630 goto exit_binary_result_object;
631 }
632
633 Py_DECREF_IMMORTAL(x);
634 }
635
636 if (slot2 != NULL) {
637 PyObject *x = slot2(operand1, operand2);
638
639 if (x != Py_NotImplemented) {
640 obj_result = x;
641 goto exit_binary_result_object;
642 }
643
644 Py_DECREF_IMMORTAL(x);
645 }
646
647#if PYTHON_VERSION < 0x300
648 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
649 coercion c1 =
650 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
651
652 if (c1 != NULL) {
653 PyObject *coerced1 = operand1;
654 PyObject *coerced2 = operand2;
655
656 int err = c1(&coerced1, &coerced2);
657
658 if (unlikely(err < 0)) {
659 goto exit_binary_exception;
660 }
661
662 if (err == 0) {
663 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
664
665 if (likely(mv == NULL)) {
666 binaryfunc slot = mv->nb_divmod;
667
668 if (likely(slot != NULL)) {
669 PyObject *x = slot(coerced1, coerced2);
670
671 Py_DECREF(coerced1);
672 Py_DECREF(coerced2);
673
674 obj_result = x;
675 goto exit_binary_result_object;
676 }
677 }
678
679 // nb_coerce took a reference.
680 Py_DECREF(coerced1);
681 Py_DECREF(coerced2);
682 }
683 }
684 coercion c2 = PyLong_Type.tp_as_number->nb_coerce;
685
686 if (c2 != NULL) {
687 PyObject *coerced1 = operand1;
688 PyObject *coerced2 = operand2;
689
690 int err = c2(&coerced2, &coerced1);
691
692 if (unlikely(err < 0)) {
693 goto exit_binary_exception;
694 }
695
696 if (err == 0) {
697 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
698
699 if (likely(mv == NULL)) {
700 binaryfunc slot = mv->nb_divmod;
701
702 if (likely(slot != NULL)) {
703 PyObject *x = slot(coerced1, coerced2);
704
705 Py_DECREF(coerced1);
706 Py_DECREF(coerced2);
707
708 obj_result = x;
709 goto exit_binary_result_object;
710 }
711 }
712
713 // nb_coerce took a reference.
714 Py_DECREF(coerced1);
715 Py_DECREF(coerced2);
716 }
717 }
718 }
719#endif
720
721#if PYTHON_VERSION < 0x300
722 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and 'long'", type1->tp_name);
723#else
724 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and 'int'", type1->tp_name);
725#endif
726 goto exit_binary_exception;
727
728exit_binary_result_object:
729 return obj_result;
730
731exit_binary_exception:
732 return NULL;
733}
734static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) {
735 CHECK_OBJECT(operand1);
736 CHECK_OBJECT(operand2);
737 assert(PyLong_CheckExact(operand2));
738
739 PyTypeObject *type1 = Py_TYPE(operand1);
740
741 if (type1 == &PyLong_Type) {
742 PyObject *result;
743
744 // return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(operand1, operand2);
745
746 // Not every code path will make use of all possible results.
747#if defined(_MSC_VER)
748#pragma warning(push)
749#pragma warning(disable : 4101)
750#endif
751 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
752 NUITKA_MAY_BE_UNUSED long clong_result;
753#if defined(_MSC_VER)
754#pragma warning(pop)
755#endif
756
757 PyObject *x = PyLong_Type.tp_as_number->nb_divmod(operand1, operand2);
758 assert(x != Py_NotImplemented);
759
760 obj_result = x;
761 goto exit_result_object;
762
763 exit_result_object:
764 if (unlikely(obj_result == NULL)) {
765 goto exit_result_exception;
766 }
767 result = obj_result;
768 goto exit_result_ok;
769
770 exit_result_ok:
771 return result;
772
773 exit_result_exception:
774 return NULL;
775 }
776
777 return __BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(operand1, operand2);
778}
779
780PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) {
781 return _BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_LONG(operand1, operand2);
782}
783
784/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */
785static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(PyObject *operand1,
786 PyObject *operand2) {
787 PyTypeObject *type2 = Py_TYPE(operand2);
788
789#if defined(_MSC_VER)
790#pragma warning(push)
791#pragma warning(disable : 4101)
792#endif
793 NUITKA_MAY_BE_UNUSED bool cbool_result;
794 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
795#if defined(_MSC_VER)
796#pragma warning(pop)
797#endif
798
799 binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divmod;
800 binaryfunc slot2 = NULL;
801
802 if (!(&PyLong_Type == type2)) {
803 // Different types, need to consider second value slot.
804
805 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divmod : NULL;
806
807 if (slot1 == slot2) {
808 slot2 = NULL;
809 }
810 }
811
812 if (slot1 != NULL) {
813 if (slot2 != NULL) {
814 if (Nuitka_Type_IsSubtype(type2, &PyLong_Type)) {
815 PyObject *x = slot2(operand1, operand2);
816
817 if (x != Py_NotImplemented) {
818 obj_result = x;
819 goto exit_binary_result_object;
820 }
821
822 Py_DECREF_IMMORTAL(x);
823 slot2 = NULL;
824 }
825 }
826
827 PyObject *x = slot1(operand1, operand2);
828
829 if (x != Py_NotImplemented) {
830 obj_result = x;
831 goto exit_binary_result_object;
832 }
833
834 Py_DECREF_IMMORTAL(x);
835 }
836
837 if (slot2 != NULL) {
838 PyObject *x = slot2(operand1, operand2);
839
840 if (x != Py_NotImplemented) {
841 obj_result = x;
842 goto exit_binary_result_object;
843 }
844
845 Py_DECREF_IMMORTAL(x);
846 }
847
848#if PYTHON_VERSION < 0x300
849 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
850 coercion c1 = PyLong_Type.tp_as_number->nb_coerce;
851
852 if (c1 != NULL) {
853 PyObject *coerced1 = operand1;
854 PyObject *coerced2 = operand2;
855
856 int err = c1(&coerced1, &coerced2);
857
858 if (unlikely(err < 0)) {
859 goto exit_binary_exception;
860 }
861
862 if (err == 0) {
863 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
864
865 if (likely(mv == NULL)) {
866 binaryfunc slot = mv->nb_divmod;
867
868 if (likely(slot != NULL)) {
869 PyObject *x = slot(coerced1, coerced2);
870
871 Py_DECREF(coerced1);
872 Py_DECREF(coerced2);
873
874 obj_result = x;
875 goto exit_binary_result_object;
876 }
877 }
878
879 // nb_coerce took a reference.
880 Py_DECREF(coerced1);
881 Py_DECREF(coerced2);
882 }
883 }
884 coercion c2 =
885 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
886
887 if (c2 != NULL) {
888 PyObject *coerced1 = operand1;
889 PyObject *coerced2 = operand2;
890
891 int err = c2(&coerced2, &coerced1);
892
893 if (unlikely(err < 0)) {
894 goto exit_binary_exception;
895 }
896
897 if (err == 0) {
898 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
899
900 if (likely(mv == NULL)) {
901 binaryfunc slot = mv->nb_divmod;
902
903 if (likely(slot != NULL)) {
904 PyObject *x = slot(coerced1, coerced2);
905
906 Py_DECREF(coerced1);
907 Py_DECREF(coerced2);
908
909 obj_result = x;
910 goto exit_binary_result_object;
911 }
912 }
913
914 // nb_coerce took a reference.
915 Py_DECREF(coerced1);
916 Py_DECREF(coerced2);
917 }
918 }
919 }
920#endif
921
922#if PYTHON_VERSION < 0x300
923 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'long' and '%s'", type2->tp_name);
924#else
925 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'int' and '%s'", type2->tp_name);
926#endif
927 goto exit_binary_exception;
928
929exit_binary_result_object:
930 return obj_result;
931
932exit_binary_exception:
933 return NULL;
934}
935static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) {
936 CHECK_OBJECT(operand1);
937 assert(PyLong_CheckExact(operand1));
938 CHECK_OBJECT(operand2);
939
940 PyTypeObject *type2 = Py_TYPE(operand2);
941
942 if (&PyLong_Type == type2) {
943 PyObject *result;
944
945 // return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_LONG(operand1, operand2);
946
947 // Not every code path will make use of all possible results.
948#if defined(_MSC_VER)
949#pragma warning(push)
950#pragma warning(disable : 4101)
951#endif
952 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
953 NUITKA_MAY_BE_UNUSED long clong_result;
954#if defined(_MSC_VER)
955#pragma warning(pop)
956#endif
957
958 PyObject *x = PyLong_Type.tp_as_number->nb_divmod(operand1, operand2);
959 assert(x != Py_NotImplemented);
960
961 obj_result = x;
962 goto exit_result_object;
963
964 exit_result_object:
965 if (unlikely(obj_result == NULL)) {
966 goto exit_result_exception;
967 }
968 result = obj_result;
969 goto exit_result_ok;
970
971 exit_result_ok:
972 return result;
973
974 exit_result_exception:
975 return NULL;
976 }
977
978 return __BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(operand1, operand2);
979}
980
981PyObject *BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) {
982 return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_OBJECT(operand1, operand2);
983}
984
985/* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */
986static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) {
987 CHECK_OBJECT(operand1);
988 assert(PyFloat_CheckExact(operand1));
989 CHECK_OBJECT(operand2);
990 assert(PyFloat_CheckExact(operand2));
991
992 PyObject *result;
993
994#if defined(_MSC_VER)
995#pragma warning(push)
996#pragma warning(disable : 4101)
997#endif
998 // Not every code path will make use of all possible results.
999 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1000 NUITKA_MAY_BE_UNUSED long clong_result;
1001 NUITKA_MAY_BE_UNUSED double cfloat_result;
1002#if defined(_MSC_VER)
1003#pragma warning(pop)
1004#endif
1005
1006 CHECK_OBJECT(operand1);
1007 assert(PyFloat_CheckExact(operand1));
1008 CHECK_OBJECT(operand2);
1009 assert(PyFloat_CheckExact(operand2));
1010
1011 const double a = PyFloat_AS_DOUBLE(operand1);
1012 const double b = PyFloat_AS_DOUBLE(operand2);
1013
1014 if (unlikely(b == 0.0)) {
1015 PyThreadState *tstate = PyThreadState_GET();
1016
1017 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "float modulo");
1018 goto exit_result_exception;
1019 }
1020
1021 {
1022 double mod = fmod(a, b);
1023 double div = (a - mod) / b;
1024
1025 if (mod) {
1026 if ((b < 0) != (mod < 0)) {
1027 mod += b;
1028 div -= 1.0;
1029 }
1030 } else {
1031 mod = copysign(0.0, b);
1032 }
1033
1034 double floordiv;
1035 if (div) {
1036 floordiv = floor(div);
1037 if (div - floordiv > 0.5) {
1038 floordiv += 1.0;
1039 }
1040 } else {
1041 floordiv = copysign(0.0, a / b);
1042 }
1043
1044 PyObject *r = Py_BuildValue("(dd)", floordiv, mod);
1045
1046 obj_result = r;
1047 goto exit_result_object;
1048 }
1049
1050exit_result_object:
1051 if (unlikely(obj_result == NULL)) {
1052 goto exit_result_exception;
1053 }
1054 result = obj_result;
1055 goto exit_result_ok;
1056
1057exit_result_ok:
1058 return result;
1059
1060exit_result_exception:
1061 return NULL;
1062}
1063
1064PyObject *BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(PyObject *operand1, PyObject *operand2) {
1065 return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(operand1, operand2);
1066}
1067
1068/* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */
1069static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(PyObject *operand1,
1070 PyObject *operand2) {
1071 PyTypeObject *type1 = Py_TYPE(operand1);
1072
1073#if defined(_MSC_VER)
1074#pragma warning(push)
1075#pragma warning(disable : 4101)
1076#endif
1077 NUITKA_MAY_BE_UNUSED bool cbool_result;
1078 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1079#if defined(_MSC_VER)
1080#pragma warning(pop)
1081#endif
1082
1083 binaryfunc slot1 =
1084 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divmod : NULL;
1085 binaryfunc slot2 = NULL;
1086
1087 if (!(type1 == &PyFloat_Type)) {
1088 // Different types, need to consider second value slot.
1089
1090 slot2 = PyFloat_Type.tp_as_number->nb_divmod;
1091
1092 if (slot1 == slot2) {
1093 slot2 = NULL;
1094 }
1095 }
1096
1097 if (slot1 != NULL) {
1098 PyObject *x = slot1(operand1, operand2);
1099
1100 if (x != Py_NotImplemented) {
1101 obj_result = x;
1102 goto exit_binary_result_object;
1103 }
1104
1105 Py_DECREF_IMMORTAL(x);
1106 }
1107
1108 if (slot2 != NULL) {
1109 PyObject *x = slot2(operand1, operand2);
1110
1111 if (x != Py_NotImplemented) {
1112 obj_result = x;
1113 goto exit_binary_result_object;
1114 }
1115
1116 Py_DECREF_IMMORTAL(x);
1117 }
1118
1119#if PYTHON_VERSION < 0x300
1120 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
1121 coercion c1 =
1122 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
1123
1124 if (c1 != NULL) {
1125 PyObject *coerced1 = operand1;
1126 PyObject *coerced2 = operand2;
1127
1128 int err = c1(&coerced1, &coerced2);
1129
1130 if (unlikely(err < 0)) {
1131 goto exit_binary_exception;
1132 }
1133
1134 if (err == 0) {
1135 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1136
1137 if (likely(mv == NULL)) {
1138 binaryfunc slot = mv->nb_divmod;
1139
1140 if (likely(slot != NULL)) {
1141 PyObject *x = slot(coerced1, coerced2);
1142
1143 Py_DECREF(coerced1);
1144 Py_DECREF(coerced2);
1145
1146 obj_result = x;
1147 goto exit_binary_result_object;
1148 }
1149 }
1150
1151 // nb_coerce took a reference.
1152 Py_DECREF(coerced1);
1153 Py_DECREF(coerced2);
1154 }
1155 }
1156 coercion c2 = PyFloat_Type.tp_as_number->nb_coerce;
1157
1158 if (c2 != NULL) {
1159 PyObject *coerced1 = operand1;
1160 PyObject *coerced2 = operand2;
1161
1162 int err = c2(&coerced2, &coerced1);
1163
1164 if (unlikely(err < 0)) {
1165 goto exit_binary_exception;
1166 }
1167
1168 if (err == 0) {
1169 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1170
1171 if (likely(mv == NULL)) {
1172 binaryfunc slot = mv->nb_divmod;
1173
1174 if (likely(slot != NULL)) {
1175 PyObject *x = slot(coerced1, coerced2);
1176
1177 Py_DECREF(coerced1);
1178 Py_DECREF(coerced2);
1179
1180 obj_result = x;
1181 goto exit_binary_result_object;
1182 }
1183 }
1184
1185 // nb_coerce took a reference.
1186 Py_DECREF(coerced1);
1187 Py_DECREF(coerced2);
1188 }
1189 }
1190 }
1191#endif
1192
1193 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and 'float'", type1->tp_name);
1194 goto exit_binary_exception;
1195
1196exit_binary_result_object:
1197 return obj_result;
1198
1199exit_binary_exception:
1200 return NULL;
1201}
1202static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) {
1203 CHECK_OBJECT(operand1);
1204 CHECK_OBJECT(operand2);
1205 assert(PyFloat_CheckExact(operand2));
1206
1207 PyTypeObject *type1 = Py_TYPE(operand1);
1208
1209 if (type1 == &PyFloat_Type) {
1210 PyObject *result;
1211
1212 // return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(operand1, operand2);
1213
1214#if defined(_MSC_VER)
1215#pragma warning(push)
1216#pragma warning(disable : 4101)
1217#endif
1218 // Not every code path will make use of all possible results.
1219 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1220 NUITKA_MAY_BE_UNUSED long clong_result;
1221 NUITKA_MAY_BE_UNUSED double cfloat_result;
1222#if defined(_MSC_VER)
1223#pragma warning(pop)
1224#endif
1225
1226 CHECK_OBJECT(operand1);
1227 assert(PyFloat_CheckExact(operand1));
1228 CHECK_OBJECT(operand2);
1229 assert(PyFloat_CheckExact(operand2));
1230
1231 const double a = PyFloat_AS_DOUBLE(operand1);
1232 const double b = PyFloat_AS_DOUBLE(operand2);
1233
1234 if (unlikely(b == 0.0)) {
1235 PyThreadState *tstate = PyThreadState_GET();
1236
1237 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "float modulo");
1238 goto exit_result_exception;
1239 }
1240
1241 {
1242 double mod = fmod(a, b);
1243 double div = (a - mod) / b;
1244
1245 if (mod) {
1246 if ((b < 0) != (mod < 0)) {
1247 mod += b;
1248 div -= 1.0;
1249 }
1250 } else {
1251 mod = copysign(0.0, b);
1252 }
1253
1254 double floordiv;
1255 if (div) {
1256 floordiv = floor(div);
1257 if (div - floordiv > 0.5) {
1258 floordiv += 1.0;
1259 }
1260 } else {
1261 floordiv = copysign(0.0, a / b);
1262 }
1263
1264 PyObject *r = Py_BuildValue("(dd)", floordiv, mod);
1265
1266 obj_result = r;
1267 goto exit_result_object;
1268 }
1269
1270 exit_result_object:
1271 if (unlikely(obj_result == NULL)) {
1272 goto exit_result_exception;
1273 }
1274 result = obj_result;
1275 goto exit_result_ok;
1276
1277 exit_result_ok:
1278 return result;
1279
1280 exit_result_exception:
1281 return NULL;
1282 }
1283
1284 return __BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(operand1, operand2);
1285}
1286
1287PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(PyObject *operand1, PyObject *operand2) {
1288 return _BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_FLOAT(operand1, operand2);
1289}
1290
1291/* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */
1292static HEDLEY_NEVER_INLINE PyObject *__BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(PyObject *operand1,
1293 PyObject *operand2) {
1294 PyTypeObject *type2 = Py_TYPE(operand2);
1295
1296#if defined(_MSC_VER)
1297#pragma warning(push)
1298#pragma warning(disable : 4101)
1299#endif
1300 NUITKA_MAY_BE_UNUSED bool cbool_result;
1301 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1302#if defined(_MSC_VER)
1303#pragma warning(pop)
1304#endif
1305
1306 binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divmod;
1307 binaryfunc slot2 = NULL;
1308
1309 if (!(&PyFloat_Type == type2)) {
1310 // Different types, need to consider second value slot.
1311
1312 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divmod : NULL;
1313
1314 if (slot1 == slot2) {
1315 slot2 = NULL;
1316 }
1317 }
1318
1319 if (slot1 != NULL) {
1320 if (slot2 != NULL) {
1321 if (Nuitka_Type_IsSubtype(type2, &PyFloat_Type)) {
1322 PyObject *x = slot2(operand1, operand2);
1323
1324 if (x != Py_NotImplemented) {
1325 obj_result = x;
1326 goto exit_binary_result_object;
1327 }
1328
1329 Py_DECREF_IMMORTAL(x);
1330 slot2 = NULL;
1331 }
1332 }
1333
1334 PyObject *x = slot1(operand1, operand2);
1335
1336 if (x != Py_NotImplemented) {
1337 obj_result = x;
1338 goto exit_binary_result_object;
1339 }
1340
1341 Py_DECREF_IMMORTAL(x);
1342 }
1343
1344 if (slot2 != NULL) {
1345 PyObject *x = slot2(operand1, operand2);
1346
1347 if (x != Py_NotImplemented) {
1348 obj_result = x;
1349 goto exit_binary_result_object;
1350 }
1351
1352 Py_DECREF_IMMORTAL(x);
1353 }
1354
1355#if PYTHON_VERSION < 0x300
1356 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
1357 coercion c1 = PyFloat_Type.tp_as_number->nb_coerce;
1358
1359 if (c1 != NULL) {
1360 PyObject *coerced1 = operand1;
1361 PyObject *coerced2 = operand2;
1362
1363 int err = c1(&coerced1, &coerced2);
1364
1365 if (unlikely(err < 0)) {
1366 goto exit_binary_exception;
1367 }
1368
1369 if (err == 0) {
1370 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1371
1372 if (likely(mv == NULL)) {
1373 binaryfunc slot = mv->nb_divmod;
1374
1375 if (likely(slot != NULL)) {
1376 PyObject *x = slot(coerced1, coerced2);
1377
1378 Py_DECREF(coerced1);
1379 Py_DECREF(coerced2);
1380
1381 obj_result = x;
1382 goto exit_binary_result_object;
1383 }
1384 }
1385
1386 // nb_coerce took a reference.
1387 Py_DECREF(coerced1);
1388 Py_DECREF(coerced2);
1389 }
1390 }
1391 coercion c2 =
1392 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
1393
1394 if (c2 != NULL) {
1395 PyObject *coerced1 = operand1;
1396 PyObject *coerced2 = operand2;
1397
1398 int err = c2(&coerced2, &coerced1);
1399
1400 if (unlikely(err < 0)) {
1401 goto exit_binary_exception;
1402 }
1403
1404 if (err == 0) {
1405 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1406
1407 if (likely(mv == NULL)) {
1408 binaryfunc slot = mv->nb_divmod;
1409
1410 if (likely(slot != NULL)) {
1411 PyObject *x = slot(coerced1, coerced2);
1412
1413 Py_DECREF(coerced1);
1414 Py_DECREF(coerced2);
1415
1416 obj_result = x;
1417 goto exit_binary_result_object;
1418 }
1419 }
1420
1421 // nb_coerce took a reference.
1422 Py_DECREF(coerced1);
1423 Py_DECREF(coerced2);
1424 }
1425 }
1426 }
1427#endif
1428
1429 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'float' and '%s'", type2->tp_name);
1430 goto exit_binary_exception;
1431
1432exit_binary_result_object:
1433 return obj_result;
1434
1435exit_binary_exception:
1436 return NULL;
1437}
1438static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) {
1439 CHECK_OBJECT(operand1);
1440 assert(PyFloat_CheckExact(operand1));
1441 CHECK_OBJECT(operand2);
1442
1443 PyTypeObject *type2 = Py_TYPE(operand2);
1444
1445 if (&PyFloat_Type == type2) {
1446 PyObject *result;
1447
1448 // return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_FLOAT(operand1, operand2);
1449
1450#if defined(_MSC_VER)
1451#pragma warning(push)
1452#pragma warning(disable : 4101)
1453#endif
1454 // Not every code path will make use of all possible results.
1455 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1456 NUITKA_MAY_BE_UNUSED long clong_result;
1457 NUITKA_MAY_BE_UNUSED double cfloat_result;
1458#if defined(_MSC_VER)
1459#pragma warning(pop)
1460#endif
1461
1462 CHECK_OBJECT(operand1);
1463 assert(PyFloat_CheckExact(operand1));
1464 CHECK_OBJECT(operand2);
1465 assert(PyFloat_CheckExact(operand2));
1466
1467 const double a = PyFloat_AS_DOUBLE(operand1);
1468 const double b = PyFloat_AS_DOUBLE(operand2);
1469
1470 if (unlikely(b == 0.0)) {
1471 PyThreadState *tstate = PyThreadState_GET();
1472
1473 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "float modulo");
1474 goto exit_result_exception;
1475 }
1476
1477 {
1478 double mod = fmod(a, b);
1479 double div = (a - mod) / b;
1480
1481 if (mod) {
1482 if ((b < 0) != (mod < 0)) {
1483 mod += b;
1484 div -= 1.0;
1485 }
1486 } else {
1487 mod = copysign(0.0, b);
1488 }
1489
1490 double floordiv;
1491 if (div) {
1492 floordiv = floor(div);
1493 if (div - floordiv > 0.5) {
1494 floordiv += 1.0;
1495 }
1496 } else {
1497 floordiv = copysign(0.0, a / b);
1498 }
1499
1500 PyObject *r = Py_BuildValue("(dd)", floordiv, mod);
1501
1502 obj_result = r;
1503 goto exit_result_object;
1504 }
1505
1506 exit_result_object:
1507 if (unlikely(obj_result == NULL)) {
1508 goto exit_result_exception;
1509 }
1510 result = obj_result;
1511 goto exit_result_ok;
1512
1513 exit_result_ok:
1514 return result;
1515
1516 exit_result_exception:
1517 return NULL;
1518 }
1519
1520 return __BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(operand1, operand2);
1521}
1522
1523PyObject *BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(PyObject *operand1, PyObject *operand2) {
1524 return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_OBJECT(operand1, operand2);
1525}
1526
1527/* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */
1528static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) {
1529 CHECK_OBJECT(operand1);
1530 assert(PyFloat_CheckExact(operand1));
1531 CHECK_OBJECT(operand2);
1532 assert(PyLong_CheckExact(operand2));
1533
1534#if defined(_MSC_VER)
1535#pragma warning(push)
1536#pragma warning(disable : 4101)
1537#endif
1538 NUITKA_MAY_BE_UNUSED bool cbool_result;
1539 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1540#if defined(_MSC_VER)
1541#pragma warning(pop)
1542#endif
1543
1544 binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divmod;
1545 // Slot2 ignored on purpose, type1 takes precedence.
1546
1547 if (slot1 != NULL) {
1548 PyObject *x = slot1(operand1, operand2);
1549
1550 if (x != Py_NotImplemented) {
1551 obj_result = x;
1552 goto exit_binary_result_object;
1553 }
1554
1555 Py_DECREF_IMMORTAL(x);
1556 }
1557
1558 // Statically recognized that coercion is not possible with these types
1559
1560#if PYTHON_VERSION < 0x300
1561 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'float' and 'long'");
1562#else
1563 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'float' and 'int'");
1564#endif
1565 goto exit_binary_exception;
1566
1567exit_binary_result_object:
1568 return obj_result;
1569
1570exit_binary_exception:
1571 return NULL;
1572}
1573
1574PyObject *BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_LONG(PyObject *operand1, PyObject *operand2) {
1575 return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_LONG(operand1, operand2);
1576}
1577
1578/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */
1579static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) {
1580 CHECK_OBJECT(operand1);
1581 assert(PyLong_CheckExact(operand1));
1582 CHECK_OBJECT(operand2);
1583 assert(PyFloat_CheckExact(operand2));
1584
1585#if defined(_MSC_VER)
1586#pragma warning(push)
1587#pragma warning(disable : 4101)
1588#endif
1589 NUITKA_MAY_BE_UNUSED bool cbool_result;
1590 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1591#if defined(_MSC_VER)
1592#pragma warning(pop)
1593#endif
1594
1595 // Slot1 ignored on purpose, type2 takes precedence.
1596 binaryfunc slot2 = NULL;
1597
1598 if (!(0)) {
1599 // Different types, need to consider second value slot.
1600
1601 slot2 = PyFloat_Type.tp_as_number->nb_divmod;
1602 }
1603
1604 if (slot2 != NULL) {
1605 PyObject *x = slot2(operand1, operand2);
1606
1607 if (x != Py_NotImplemented) {
1608 obj_result = x;
1609 goto exit_binary_result_object;
1610 }
1611
1612 Py_DECREF_IMMORTAL(x);
1613 }
1614
1615 // Statically recognized that coercion is not possible with these types
1616
1617#if PYTHON_VERSION < 0x300
1618 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'long' and 'float'");
1619#else
1620 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'int' and 'float'");
1621#endif
1622 goto exit_binary_exception;
1623
1624exit_binary_result_object:
1625 return obj_result;
1626
1627exit_binary_exception:
1628 return NULL;
1629}
1630
1631PyObject *BINARY_OPERATION_DIVMOD_OBJECT_LONG_FLOAT(PyObject *operand1, PyObject *operand2) {
1632 return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_FLOAT(operand1, operand2);
1633}
1634
1635#if PYTHON_VERSION < 0x300
1636/* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */
1637static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) {
1638 CHECK_OBJECT(operand1);
1639 assert(PyFloat_CheckExact(operand1));
1640 CHECK_OBJECT(operand2);
1641 assert(PyInt_CheckExact(operand2));
1642
1643#if defined(_MSC_VER)
1644#pragma warning(push)
1645#pragma warning(disable : 4101)
1646#endif
1647 NUITKA_MAY_BE_UNUSED bool cbool_result;
1648 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1649#if defined(_MSC_VER)
1650#pragma warning(pop)
1651#endif
1652
1653 binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_divmod;
1654 // Slot2 ignored on purpose, type1 takes precedence.
1655
1656 if (slot1 != NULL) {
1657 PyObject *x = slot1(operand1, operand2);
1658
1659 if (x != Py_NotImplemented) {
1660 obj_result = x;
1661 goto exit_binary_result_object;
1662 }
1663
1664 Py_DECREF_IMMORTAL(x);
1665 }
1666
1667 // Statically recognized that coercion is not possible with these types
1668
1669 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'float' and 'int'");
1670 goto exit_binary_exception;
1671
1672exit_binary_result_object:
1673 return obj_result;
1674
1675exit_binary_exception:
1676 return NULL;
1677}
1678
1679PyObject *BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_INT(PyObject *operand1, PyObject *operand2) {
1680 return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_INT(operand1, operand2);
1681}
1682#endif
1683
1684#if PYTHON_VERSION < 0x300
1685/* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */
1686static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) {
1687 CHECK_OBJECT(operand1);
1688 assert(PyInt_CheckExact(operand1));
1689 CHECK_OBJECT(operand2);
1690 assert(PyFloat_CheckExact(operand2));
1691
1692#if defined(_MSC_VER)
1693#pragma warning(push)
1694#pragma warning(disable : 4101)
1695#endif
1696 NUITKA_MAY_BE_UNUSED bool cbool_result;
1697 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1698#if defined(_MSC_VER)
1699#pragma warning(pop)
1700#endif
1701
1702 // Slot1 ignored on purpose, type2 takes precedence.
1703 binaryfunc slot2 = NULL;
1704
1705 if (!(0)) {
1706 // Different types, need to consider second value slot.
1707
1708 slot2 = PyFloat_Type.tp_as_number->nb_divmod;
1709 }
1710
1711 if (slot2 != NULL) {
1712 PyObject *x = slot2(operand1, operand2);
1713
1714 if (x != Py_NotImplemented) {
1715 obj_result = x;
1716 goto exit_binary_result_object;
1717 }
1718
1719 Py_DECREF_IMMORTAL(x);
1720 }
1721
1722 // Statically recognized that coercion is not possible with these types
1723
1724 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'int' and 'float'");
1725 goto exit_binary_exception;
1726
1727exit_binary_result_object:
1728 return obj_result;
1729
1730exit_binary_exception:
1731 return NULL;
1732}
1733
1734PyObject *BINARY_OPERATION_DIVMOD_OBJECT_INT_FLOAT(PyObject *operand1, PyObject *operand2) {
1735 return _BINARY_OPERATION_DIVMOD_OBJECT_INT_FLOAT(operand1, operand2);
1736}
1737#endif
1738
1739#if PYTHON_VERSION < 0x300
1740/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */
1741static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) {
1742 CHECK_OBJECT(operand1);
1743 assert(PyLong_CheckExact(operand1));
1744 CHECK_OBJECT(operand2);
1745 assert(PyInt_CheckExact(operand2));
1746
1747#if defined(_MSC_VER)
1748#pragma warning(push)
1749#pragma warning(disable : 4101)
1750#endif
1751 NUITKA_MAY_BE_UNUSED bool cbool_result;
1752 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1753#if defined(_MSC_VER)
1754#pragma warning(pop)
1755#endif
1756
1757 binaryfunc slot1 = PyLong_Type.tp_as_number->nb_divmod;
1758 // Slot2 ignored on purpose, type1 takes precedence.
1759
1760 if (slot1 != NULL) {
1761 PyObject *x = slot1(operand1, operand2);
1762
1763 if (x != Py_NotImplemented) {
1764 obj_result = x;
1765 goto exit_binary_result_object;
1766 }
1767
1768 Py_DECREF_IMMORTAL(x);
1769 }
1770
1771 // Statically recognized that coercion is not possible with these types
1772
1773 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'long' and 'int'");
1774 goto exit_binary_exception;
1775
1776exit_binary_result_object:
1777 return obj_result;
1778
1779exit_binary_exception:
1780 return NULL;
1781}
1782
1783PyObject *BINARY_OPERATION_DIVMOD_OBJECT_LONG_INT(PyObject *operand1, PyObject *operand2) {
1784 return _BINARY_OPERATION_DIVMOD_OBJECT_LONG_INT(operand1, operand2);
1785}
1786#endif
1787
1788#if PYTHON_VERSION < 0x300
1789/* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */
1790static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) {
1791 CHECK_OBJECT(operand1);
1792 assert(PyInt_CheckExact(operand1));
1793 CHECK_OBJECT(operand2);
1794 assert(PyLong_CheckExact(operand2));
1795
1796#if defined(_MSC_VER)
1797#pragma warning(push)
1798#pragma warning(disable : 4101)
1799#endif
1800 NUITKA_MAY_BE_UNUSED bool cbool_result;
1801 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1802#if defined(_MSC_VER)
1803#pragma warning(pop)
1804#endif
1805
1806 // Slot1 ignored on purpose, type2 takes precedence.
1807 binaryfunc slot2 = NULL;
1808
1809 if (!(0)) {
1810 // Different types, need to consider second value slot.
1811
1812 slot2 = PyLong_Type.tp_as_number->nb_divmod;
1813 }
1814
1815 if (slot2 != NULL) {
1816 PyObject *x = slot2(operand1, operand2);
1817
1818 if (x != Py_NotImplemented) {
1819 obj_result = x;
1820 goto exit_binary_result_object;
1821 }
1822
1823 Py_DECREF_IMMORTAL(x);
1824 }
1825
1826 // Statically recognized that coercion is not possible with these types
1827
1828 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): 'int' and 'long'");
1829 goto exit_binary_exception;
1830
1831exit_binary_result_object:
1832 return obj_result;
1833
1834exit_binary_exception:
1835 return NULL;
1836}
1837
1838PyObject *BINARY_OPERATION_DIVMOD_OBJECT_INT_LONG(PyObject *operand1, PyObject *operand2) {
1839 return _BINARY_OPERATION_DIVMOD_OBJECT_INT_LONG(operand1, operand2);
1840}
1841#endif
1842
1843#if PYTHON_VERSION < 0x300
1844/* Code referring to "INT" corresponds to Python2 'int' and "CLONG" to C platform long value. */
1845static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_INT_CLONG(PyObject *operand1, long operand2) {
1846 CHECK_OBJECT(operand1);
1847 assert(PyInt_CheckExact(operand1));
1848
1849 PyObject *result;
1850
1851 // Not every code path will make use of all possible results.
1852#if defined(_MSC_VER)
1853#pragma warning(push)
1854#pragma warning(disable : 4101)
1855#endif
1856 NUITKA_MAY_BE_UNUSED bool cbool_result;
1857 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1858 NUITKA_MAY_BE_UNUSED long clong_result;
1859 NUITKA_MAY_BE_UNUSED double cfloat_result;
1860#if defined(_MSC_VER)
1861#pragma warning(pop)
1862#endif
1863
1864 CHECK_OBJECT(operand1);
1865 assert(PyInt_CheckExact(operand1));
1866
1867 const long a = PyInt_AS_LONG(operand1);
1868 const long b = operand2;
1869
1870 if (unlikely(b == 0)) {
1871 PyThreadState *tstate = PyThreadState_GET();
1872
1873 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "integer division or modulo by zero");
1874 goto exit_result_exception;
1875 }
1876
1877 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
1878 long a_div_b = a / b;
1879 long a_mod_b = (long)(a - (unsigned long)a_div_b * b);
1880
1881 if (a_mod_b && (b ^ a_mod_b) < 0) {
1882 a_mod_b += b;
1883 a_div_b -= 1;
1884 }
1885
1886 PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b);
1887 obj_result = r;
1888 goto exit_result_object;
1889 }
1890
1891 {
1892 PyObject *operand1_object = operand1;
1893 PyObject *operand2_object = Nuitka_PyLong_FromLong(operand2);
1894
1895 PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object);
1896 assert(r != Py_NotImplemented);
1897
1898 Py_DECREF(operand2_object);
1899
1900 obj_result = r;
1901 goto exit_result_object;
1902 }
1903
1904exit_result_object:
1905 if (unlikely(obj_result == NULL)) {
1906 goto exit_result_exception;
1907 }
1908 result = obj_result;
1909 goto exit_result_ok;
1910
1911exit_result_ok:
1912 return result;
1913
1914exit_result_exception:
1915 return NULL;
1916}
1917
1918PyObject *BINARY_OPERATION_DIVMOD_OBJECT_INT_CLONG(PyObject *operand1, long operand2) {
1919 return _BINARY_OPERATION_DIVMOD_OBJECT_INT_CLONG(operand1, operand2);
1920}
1921#endif
1922
1923#if PYTHON_VERSION < 0x300
1924/* Code referring to "CLONG" corresponds to C platform long value and "INT" to Python2 'int'. */
1925static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_CLONG_INT(long operand1, PyObject *operand2) {
1926
1927 CHECK_OBJECT(operand2);
1928 assert(PyInt_CheckExact(operand2));
1929
1930 PyObject *result;
1931
1932 // Not every code path will make use of all possible results.
1933#if defined(_MSC_VER)
1934#pragma warning(push)
1935#pragma warning(disable : 4101)
1936#endif
1937 NUITKA_MAY_BE_UNUSED bool cbool_result;
1938 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1939 NUITKA_MAY_BE_UNUSED long clong_result;
1940 NUITKA_MAY_BE_UNUSED double cfloat_result;
1941#if defined(_MSC_VER)
1942#pragma warning(pop)
1943#endif
1944
1945 CHECK_OBJECT(operand2);
1946 assert(PyInt_CheckExact(operand2));
1947
1948 const long a = operand1;
1949 const long b = PyInt_AS_LONG(operand2);
1950
1951 if (unlikely(b == 0)) {
1952 PyThreadState *tstate = PyThreadState_GET();
1953
1954 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "integer division or modulo by zero");
1955 goto exit_result_exception;
1956 }
1957
1958 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
1959 long a_div_b = a / b;
1960 long a_mod_b = (long)(a - (unsigned long)a_div_b * b);
1961
1962 if (a_mod_b && (b ^ a_mod_b) < 0) {
1963 a_mod_b += b;
1964 a_div_b -= 1;
1965 }
1966
1967 PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b);
1968 obj_result = r;
1969 goto exit_result_object;
1970 }
1971
1972 {
1973 PyObject *operand1_object = Nuitka_PyLong_FromLong(operand1);
1974 PyObject *operand2_object = operand2;
1975
1976 PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object);
1977 assert(r != Py_NotImplemented);
1978
1979 Py_DECREF(operand1_object);
1980
1981 obj_result = r;
1982 goto exit_result_object;
1983 }
1984
1985exit_result_object:
1986 if (unlikely(obj_result == NULL)) {
1987 goto exit_result_exception;
1988 }
1989 result = obj_result;
1990 goto exit_result_ok;
1991
1992exit_result_ok:
1993 return result;
1994
1995exit_result_exception:
1996 return NULL;
1997}
1998
1999PyObject *BINARY_OPERATION_DIVMOD_OBJECT_CLONG_INT(long operand1, PyObject *operand2) {
2000 return _BINARY_OPERATION_DIVMOD_OBJECT_CLONG_INT(operand1, operand2);
2001}
2002#endif
2003
2004/* Code referring to "FLOAT" corresponds to Python 'float' and "CFLOAT" to C platform float value. */
2005static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_CFLOAT(PyObject *operand1, double operand2) {
2006 CHECK_OBJECT(operand1);
2007 assert(PyFloat_CheckExact(operand1));
2008
2009 PyObject *result;
2010
2011#if defined(_MSC_VER)
2012#pragma warning(push)
2013#pragma warning(disable : 4101)
2014#endif
2015 // Not every code path will make use of all possible results.
2016 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2017 NUITKA_MAY_BE_UNUSED long clong_result;
2018 NUITKA_MAY_BE_UNUSED double cfloat_result;
2019#if defined(_MSC_VER)
2020#pragma warning(pop)
2021#endif
2022
2023 CHECK_OBJECT(operand1);
2024 assert(PyFloat_CheckExact(operand1));
2025
2026 const double a = PyFloat_AS_DOUBLE(operand1);
2027 const double b = operand2;
2028
2029 if (unlikely(b == 0.0)) {
2030 PyThreadState *tstate = PyThreadState_GET();
2031
2032 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "float modulo");
2033 goto exit_result_exception;
2034 }
2035
2036 {
2037 double mod = fmod(a, b);
2038 double div = (a - mod) / b;
2039
2040 if (mod) {
2041 if ((b < 0) != (mod < 0)) {
2042 mod += b;
2043 div -= 1.0;
2044 }
2045 } else {
2046 mod = copysign(0.0, b);
2047 }
2048
2049 double floordiv;
2050 if (div) {
2051 floordiv = floor(div);
2052 if (div - floordiv > 0.5) {
2053 floordiv += 1.0;
2054 }
2055 } else {
2056 floordiv = copysign(0.0, a / b);
2057 }
2058
2059 PyObject *r = Py_BuildValue("(dd)", floordiv, mod);
2060
2061 obj_result = r;
2062 goto exit_result_object;
2063 }
2064
2065exit_result_object:
2066 if (unlikely(obj_result == NULL)) {
2067 goto exit_result_exception;
2068 }
2069 result = obj_result;
2070 goto exit_result_ok;
2071
2072exit_result_ok:
2073 return result;
2074
2075exit_result_exception:
2076 return NULL;
2077}
2078
2079PyObject *BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_CFLOAT(PyObject *operand1, double operand2) {
2080 return _BINARY_OPERATION_DIVMOD_OBJECT_FLOAT_CFLOAT(operand1, operand2);
2081}
2082
2083/* Code referring to "CFLOAT" corresponds to C platform float value and "FLOAT" to Python 'float'. */
2084static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_CFLOAT_FLOAT(double operand1, PyObject *operand2) {
2085
2086 CHECK_OBJECT(operand2);
2087 assert(PyFloat_CheckExact(operand2));
2088
2089 PyObject *result;
2090
2091#if defined(_MSC_VER)
2092#pragma warning(push)
2093#pragma warning(disable : 4101)
2094#endif
2095 // Not every code path will make use of all possible results.
2096 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2097 NUITKA_MAY_BE_UNUSED long clong_result;
2098 NUITKA_MAY_BE_UNUSED double cfloat_result;
2099#if defined(_MSC_VER)
2100#pragma warning(pop)
2101#endif
2102
2103 CHECK_OBJECT(operand2);
2104 assert(PyFloat_CheckExact(operand2));
2105
2106 const double a = operand1;
2107 const double b = PyFloat_AS_DOUBLE(operand2);
2108
2109 if (unlikely(b == 0.0)) {
2110 PyThreadState *tstate = PyThreadState_GET();
2111
2112 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "float modulo");
2113 goto exit_result_exception;
2114 }
2115
2116 {
2117 double mod = fmod(a, b);
2118 double div = (a - mod) / b;
2119
2120 if (mod) {
2121 if ((b < 0) != (mod < 0)) {
2122 mod += b;
2123 div -= 1.0;
2124 }
2125 } else {
2126 mod = copysign(0.0, b);
2127 }
2128
2129 double floordiv;
2130 if (div) {
2131 floordiv = floor(div);
2132 if (div - floordiv > 0.5) {
2133 floordiv += 1.0;
2134 }
2135 } else {
2136 floordiv = copysign(0.0, a / b);
2137 }
2138
2139 PyObject *r = Py_BuildValue("(dd)", floordiv, mod);
2140
2141 obj_result = r;
2142 goto exit_result_object;
2143 }
2144
2145exit_result_object:
2146 if (unlikely(obj_result == NULL)) {
2147 goto exit_result_exception;
2148 }
2149 result = obj_result;
2150 goto exit_result_ok;
2151
2152exit_result_ok:
2153 return result;
2154
2155exit_result_exception:
2156 return NULL;
2157}
2158
2159PyObject *BINARY_OPERATION_DIVMOD_OBJECT_CFLOAT_FLOAT(double operand1, PyObject *operand2) {
2160 return _BINARY_OPERATION_DIVMOD_OBJECT_CFLOAT_FLOAT(operand1, operand2);
2161}
2162
2163/* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */
2164static PyObject *_BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) {
2165 CHECK_OBJECT(operand1);
2166 CHECK_OBJECT(operand2);
2167
2168#if PYTHON_VERSION < 0x300
2169 if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) {
2170 PyObject *result;
2171
2172 // Not every code path will make use of all possible results.
2173#if defined(_MSC_VER)
2174#pragma warning(push)
2175#pragma warning(disable : 4101)
2176#endif
2177 NUITKA_MAY_BE_UNUSED bool cbool_result;
2178 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2179 NUITKA_MAY_BE_UNUSED long clong_result;
2180 NUITKA_MAY_BE_UNUSED double cfloat_result;
2181#if defined(_MSC_VER)
2182#pragma warning(pop)
2183#endif
2184
2185 CHECK_OBJECT(operand1);
2186 assert(PyInt_CheckExact(operand1));
2187 CHECK_OBJECT(operand2);
2188 assert(PyInt_CheckExact(operand2));
2189
2190 const long a = PyInt_AS_LONG(operand1);
2191 const long b = PyInt_AS_LONG(operand2);
2192
2193 if (unlikely(b == 0)) {
2194 PyThreadState *tstate = PyThreadState_GET();
2195
2196 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "integer division or modulo by zero");
2197 goto exit_result_exception;
2198 }
2199
2200 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
2201 long a_div_b = a / b;
2202 long a_mod_b = (long)(a - (unsigned long)a_div_b * b);
2203
2204 if (a_mod_b && (b ^ a_mod_b) < 0) {
2205 a_mod_b += b;
2206 a_div_b -= 1;
2207 }
2208
2209 PyObject *r = Py_BuildValue("(ll)", a_div_b, a_mod_b);
2210 obj_result = r;
2211 goto exit_result_object;
2212 }
2213
2214 {
2215 PyObject *operand1_object = operand1;
2216 PyObject *operand2_object = operand2;
2217
2218 PyObject *r = PyLong_Type.tp_as_number->nb_divmod(operand1_object, operand2_object);
2219 assert(r != Py_NotImplemented);
2220
2221 obj_result = r;
2222 goto exit_result_object;
2223 }
2224
2225 exit_result_object:
2226 if (unlikely(obj_result == NULL)) {
2227 goto exit_result_exception;
2228 }
2229 result = obj_result;
2230 goto exit_result_ok;
2231
2232 exit_result_ok:
2233 return result;
2234
2235 exit_result_exception:
2236 return NULL;
2237 }
2238#endif
2239
2240 PyTypeObject *type1 = Py_TYPE(operand1);
2241 PyTypeObject *type2 = Py_TYPE(operand2);
2242
2243#if defined(_MSC_VER)
2244#pragma warning(push)
2245#pragma warning(disable : 4101)
2246#endif
2247 NUITKA_MAY_BE_UNUSED bool cbool_result;
2248 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2249#if defined(_MSC_VER)
2250#pragma warning(pop)
2251#endif
2252
2253 binaryfunc slot1 =
2254 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_divmod : NULL;
2255 binaryfunc slot2 = NULL;
2256
2257 if (!(type1 == type2)) {
2258 // Different types, need to consider second value slot.
2259
2260 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_divmod : NULL;
2261
2262 if (slot1 == slot2) {
2263 slot2 = NULL;
2264 }
2265 }
2266
2267 if (slot1 != NULL) {
2268 if (slot2 != NULL) {
2269 if (Nuitka_Type_IsSubtype(type2, type1)) {
2270 PyObject *x = slot2(operand1, operand2);
2271
2272 if (x != Py_NotImplemented) {
2273 obj_result = x;
2274 goto exit_binary_result_object;
2275 }
2276
2277 Py_DECREF_IMMORTAL(x);
2278 slot2 = NULL;
2279 }
2280 }
2281
2282 PyObject *x = slot1(operand1, operand2);
2283
2284 if (x != Py_NotImplemented) {
2285 obj_result = x;
2286 goto exit_binary_result_object;
2287 }
2288
2289 Py_DECREF_IMMORTAL(x);
2290 }
2291
2292 if (slot2 != NULL) {
2293 PyObject *x = slot2(operand1, operand2);
2294
2295 if (x != Py_NotImplemented) {
2296 obj_result = x;
2297 goto exit_binary_result_object;
2298 }
2299
2300 Py_DECREF_IMMORTAL(x);
2301 }
2302
2303#if PYTHON_VERSION < 0x300
2304 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) {
2305 coercion c1 =
2306 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
2307
2308 if (c1 != NULL) {
2309 PyObject *coerced1 = operand1;
2310 PyObject *coerced2 = operand2;
2311
2312 int err = c1(&coerced1, &coerced2);
2313
2314 if (unlikely(err < 0)) {
2315 goto exit_binary_exception;
2316 }
2317
2318 if (err == 0) {
2319 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
2320
2321 if (likely(mv == NULL)) {
2322 binaryfunc slot = mv->nb_divmod;
2323
2324 if (likely(slot != NULL)) {
2325 PyObject *x = slot(coerced1, coerced2);
2326
2327 Py_DECREF(coerced1);
2328 Py_DECREF(coerced2);
2329
2330 obj_result = x;
2331 goto exit_binary_result_object;
2332 }
2333 }
2334
2335 // nb_coerce took a reference.
2336 Py_DECREF(coerced1);
2337 Py_DECREF(coerced2);
2338 }
2339 }
2340 coercion c2 =
2341 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
2342
2343 if (c2 != NULL) {
2344 PyObject *coerced1 = operand1;
2345 PyObject *coerced2 = operand2;
2346
2347 int err = c2(&coerced2, &coerced1);
2348
2349 if (unlikely(err < 0)) {
2350 goto exit_binary_exception;
2351 }
2352
2353 if (err == 0) {
2354 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
2355
2356 if (likely(mv == NULL)) {
2357 binaryfunc slot = mv->nb_divmod;
2358
2359 if (likely(slot != NULL)) {
2360 PyObject *x = slot(coerced1, coerced2);
2361
2362 Py_DECREF(coerced1);
2363 Py_DECREF(coerced2);
2364
2365 obj_result = x;
2366 goto exit_binary_result_object;
2367 }
2368 }
2369
2370 // nb_coerce took a reference.
2371 Py_DECREF(coerced1);
2372 Py_DECREF(coerced2);
2373 }
2374 }
2375 }
2376#endif
2377
2378 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", type1->tp_name,
2379 type2->tp_name);
2380 goto exit_binary_exception;
2381
2382exit_binary_result_object:
2383 return obj_result;
2384
2385exit_binary_exception:
2386 return NULL;
2387}
2388
2389PyObject *BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) {
2390 return _BINARY_OPERATION_DIVMOD_OBJECT_OBJECT_OBJECT(operand1, operand2);
2391}
2392
2393// Part of "Nuitka", an optimizing Python compiler that is compatible and
2394// integrates with CPython, but also works on its own.
2395//
2396// Licensed under the Apache License, Version 2.0 (the "License");
2397// you may not use this file except in compliance with the License.
2398// You may obtain a copy of the License at
2399//
2400// http://www.apache.org/licenses/LICENSE-2.0
2401//
2402// Unless required by applicable law or agreed to in writing, software
2403// distributed under the License is distributed on an "AS IS" BASIS,
2404// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2405// See the License for the specific language governing permissions and
2406// limitations under the License.