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