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