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