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