text: //     Copyright 2020, Kay Hayen, mailto:kay.hayen@gmail.com
  //
  //     Part of "Nuitka", an optimizing Python compiler that is compatible and
  //     integrates with CPython, but also works on its own.
  //
  //     Licensed under the Apache License, Version 2.0 (the "License");
  //     you may not use this file except in compliance with the License.
  //     You may obtain a copy of the License at
  //
  //        http://www.apache.org/licenses/LICENSE-2.0
  //
  //     Unless required by applicable law or agreed to in writing, software
  //     distributed under the License is distributed on an "AS IS" BASIS,
  //     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  //     See the License for the specific language governing permissions and
  //     limitations under the License.
  //
  /* WARNING, this code is GENERATED. Modify the template HelperOperationBinary.c.j2 instead! */
  // This file is included from another C file, help IDEs to still parse it on
  // its own.
  #ifdef __IDE_ONLY__
  #include "nuitka/prelude.h"
  #endif
  
  /* C helpers for type specialized "@" (MATMULT) operations */
  
  /* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */
  PyObject *BINARY_OPERATION_MATMULT_LONG_OBJECT(PyObject *operand1, PyObject *operand2) {
      CHECK_OBJECT(operand1);
      assert(PyLong_CheckExact(operand1));
  #if PYTHON_VERSION < 300
      assert(NEW_STYLE_NUMBER(operand1));
  #endif
      CHECK_OBJECT(operand2);
  
      PyTypeObject *type1 = &PyLong_Type;
      binaryfunc slot1 = NULL;
  
      PyTypeObject *type2 = Py_TYPE(operand2);
      binaryfunc slot2 = NULL;
  
      if (!(type1 == type2)) {
          assert(type1 != type2);
          /* Different types, need to consider second value slot. */
  
          slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_matrix_multiply
                                                                                : NULL;
  
          if (slot1 == slot2) {
              slot2 = NULL;
          }
      } else {
          assert(type1 == type2);
      }
  
      if (slot1 != NULL) {
          if (slot2 != NULL) {
              if (PyType_IsSubtype(type2, type1)) {
                  PyObject *x = slot2(operand1, operand2);
  
                  if (x != Py_NotImplemented) {
                      if (unlikely(x == NULL)) {
                          return NULL;
                      }
  
                      return x;
                  }
  
                  Py_DECREF(x);
                  slot2 = NULL;
              }
          }
  
          PyObject *x = slot1(operand1, operand2);
  
          if (x != Py_NotImplemented) {
              if (unlikely(x == NULL)) {
                  return NULL;
              }
  
              return x;
          }
  
          Py_DECREF(x);
      }
  
      if (slot2 != NULL) {
          PyObject *x = slot2(operand1, operand2);
  
          if (x != Py_NotImplemented) {
              if (unlikely(x == NULL)) {
                  return NULL;
              }
  
              return x;
          }
  
          Py_DECREF(x);
      }
  
  #if PYTHON_VERSION < 300 && (1 || 1)
      if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
          coercion c = PyLong_Type.tp_as_number->nb_coerce;
  
          if (c != NULL) {
              PyObject *coerced1 = operand1;
              PyObject *coerced2 = operand2;
  
              int err = c(&coerced1, &coerced2);
  
              if (unlikely(err < 0)) {
                  return NULL;
              }
  
              if (err == 0) {
                  PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
  
                  if (likely(mv == NULL)) {
                      binaryfunc slot = mv->nb_matrix_multiply;
  
                      if (likely(slot != NULL)) {
                          PyObject *x = slot(coerced1, coerced2);
  
                          Py_DECREF(coerced1);
                          Py_DECREF(coerced2);
  
                          if (unlikely(x == NULL)) {
                              return NULL;
                          }
  
                          return x;
                      }
                  }
  
                  // nb_coerce took a reference.
                  Py_DECREF(coerced1);
                  Py_DECREF(coerced2);
              }
          }
  
          c = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
  
          if (c != NULL) {
              PyObject *coerced1 = operand1;
              PyObject *coerced2 = operand2;
  
              int err = c(&coerced2, &coerced1);
  
              if (unlikely(err < 0)) {
                  return NULL;
              }
  
              if (err == 0) {
                  PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
  
                  if (likely(mv == NULL)) {
                      binaryfunc slot = mv->nb_matrix_multiply;
  
                      if (likely(slot != NULL)) {
                          PyObject *x = slot(coerced1, coerced2);
  
                          Py_DECREF(coerced1);
                          Py_DECREF(coerced2);
  
                          if (unlikely(x == NULL)) {
                              return NULL;
                          }
  
                          return x;
                      }
                  }
  
                  // nb_coerce took a reference.
                  Py_DECREF(coerced1);
                  Py_DECREF(coerced2);
              }
          }
      }
  #endif
  
  #if PYTHON_VERSION < 300
      PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'long' and '%s'", type2->tp_name);
  #else
      PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: 'int' and '%s'", type2->tp_name);
  #endif
      return NULL;
  }
  
  /* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */
  PyObject *BINARY_OPERATION_MATMULT_OBJECT_LONG(PyObject *operand1, PyObject *operand2) {
      CHECK_OBJECT(operand1);
      CHECK_OBJECT(operand2);
      assert(PyLong_CheckExact(operand2));
  #if PYTHON_VERSION < 300
      assert(NEW_STYLE_NUMBER(operand2));
  #endif
  
      PyTypeObject *type1 = Py_TYPE(operand1);
      binaryfunc slot1 =
          (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_matrix_multiply : NULL;
  
      PyTypeObject *type2 = &PyLong_Type;
      binaryfunc slot2 = NULL;
  
      if (!(type1 == type2)) {
          assert(type1 != type2);
          /* Different types, need to consider second value slot. */
  
          slot2 = NULL;
  
          if (slot1 == slot2) {
              slot2 = NULL;
          }
      } else {
          assert(type1 == type2);
      }
  
      if (slot1 != NULL) {
          if (slot2 != NULL) {
              if (0) {
                  PyObject *x = slot2(operand1, operand2);
  
                  if (x != Py_NotImplemented) {
                      if (unlikely(x == NULL)) {
                          return NULL;
                      }
  
                      return x;
                  }
  
                  Py_DECREF(x);
                  slot2 = NULL;
              }
          }
  
          PyObject *x = slot1(operand1, operand2);
  
          if (x != Py_NotImplemented) {
              if (unlikely(x == NULL)) {
                  return NULL;
              }
  
              return x;
          }
  
          Py_DECREF(x);
      }
  
      if (slot2 != NULL) {
          PyObject *x = slot2(operand1, operand2);
  
          if (x != Py_NotImplemented) {
              if (unlikely(x == NULL)) {
                  return NULL;
              }
  
              return x;
          }
  
          Py_DECREF(x);
      }
  
  #if PYTHON_VERSION < 300 && (1 || 1)
      if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
          coercion c =
              (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
  
          if (c != NULL) {
              PyObject *coerced1 = operand1;
              PyObject *coerced2 = operand2;
  
              int err = c(&coerced1, &coerced2);
  
              if (unlikely(err < 0)) {
                  return NULL;
              }
  
              if (err == 0) {
                  PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
  
                  if (likely(mv == NULL)) {
                      binaryfunc slot = mv->nb_matrix_multiply;
  
                      if (likely(slot != NULL)) {
                          PyObject *x = slot(coerced1, coerced2);
  
                          Py_DECREF(coerced1);
                          Py_DECREF(coerced2);
  
                          if (unlikely(x == NULL)) {
                              return NULL;
                          }
  
                          return x;
                      }
                  }
  
                  // nb_coerce took a reference.
                  Py_DECREF(coerced1);
                  Py_DECREF(coerced2);
              }
          }
  
          c = PyLong_Type.tp_as_number->nb_coerce;
  
          if (c != NULL) {
              PyObject *coerced1 = operand1;
              PyObject *coerced2 = operand2;
  
              int err = c(&coerced2, &coerced1);
  
              if (unlikely(err < 0)) {
                  return NULL;
              }
  
              if (err == 0) {
                  PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
  
                  if (likely(mv == NULL)) {
                      binaryfunc slot = mv->nb_matrix_multiply;
  
                      if (likely(slot != NULL)) {
                          PyObject *x = slot(coerced1, coerced2);
  
                          Py_DECREF(coerced1);
                          Py_DECREF(coerced2);
  
                          if (unlikely(x == NULL)) {
                              return NULL;
                          }
  
                          return x;
                      }
                  }
  
                  // nb_coerce took a reference.
                  Py_DECREF(coerced1);
                  Py_DECREF(coerced2);
              }
          }
      }
  #endif
  
  #if PYTHON_VERSION < 300
      PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and 'long'", type1->tp_name);
  #else
      PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and 'int'", type1->tp_name);
  #endif
      return NULL;
  }
  
  /* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */
  PyObject *BINARY_OPERATION_MATMULT_OBJECT_OBJECT(PyObject *operand1, PyObject *operand2) {
      CHECK_OBJECT(operand1);
      CHECK_OBJECT(operand2);
  
  #if PYTHON_VERSION < 300
      if (PyInt_CheckExact(operand1) && PyInt_CheckExact(operand2)) {
          return BINARY_OPERATION_MATMULT_INT_INT(operand1, operand2);
      }
  #endif
  
      PyTypeObject *type1 = Py_TYPE(operand1);
      binaryfunc slot1 =
          (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_matrix_multiply : NULL;
  
      PyTypeObject *type2 = Py_TYPE(operand2);
      binaryfunc slot2 = NULL;
  
      if (!(type1 == type2)) {
          assert(type1 != type2);
          /* Different types, need to consider second value slot. */
  
          slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_matrix_multiply
                                                                                : NULL;
  
          if (slot1 == slot2) {
              slot2 = NULL;
          }
      } else {
          assert(type1 == type2);
      }
  
      if (slot1 != NULL) {
          if (slot2 != NULL) {
              if (PyType_IsSubtype(type2, type1)) {
                  PyObject *x = slot2(operand1, operand2);
  
                  if (x != Py_NotImplemented) {
                      if (unlikely(x == NULL)) {
                          return NULL;
                      }
  
                      return x;
                  }
  
                  Py_DECREF(x);
                  slot2 = NULL;
              }
          }
  
          PyObject *x = slot1(operand1, operand2);
  
          if (x != Py_NotImplemented) {
              if (unlikely(x == NULL)) {
                  return NULL;
              }
  
              return x;
          }
  
          Py_DECREF(x);
      }
  
      if (slot2 != NULL) {
          PyObject *x = slot2(operand1, operand2);
  
          if (x != Py_NotImplemented) {
              if (unlikely(x == NULL)) {
                  return NULL;
              }
  
              return x;
          }
  
          Py_DECREF(x);
      }
  
  #if PYTHON_VERSION < 300 && (1 || 1)
      if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) {
          coercion c =
              (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
  
          if (c != NULL) {
              PyObject *coerced1 = operand1;
              PyObject *coerced2 = operand2;
  
              int err = c(&coerced1, &coerced2);
  
              if (unlikely(err < 0)) {
                  return NULL;
              }
  
              if (err == 0) {
                  PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
  
                  if (likely(mv == NULL)) {
                      binaryfunc slot = mv->nb_matrix_multiply;
  
                      if (likely(slot != NULL)) {
                          PyObject *x = slot(coerced1, coerced2);
  
                          Py_DECREF(coerced1);
                          Py_DECREF(coerced2);
  
                          if (unlikely(x == NULL)) {
                              return NULL;
                          }
  
                          return x;
                      }
                  }
  
                  // nb_coerce took a reference.
                  Py_DECREF(coerced1);
                  Py_DECREF(coerced2);
              }
          }
  
          c = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
  
          if (c != NULL) {
              PyObject *coerced1 = operand1;
              PyObject *coerced2 = operand2;
  
              int err = c(&coerced2, &coerced1);
  
              if (unlikely(err < 0)) {
                  return NULL;
              }
  
              if (err == 0) {
                  PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
  
                  if (likely(mv == NULL)) {
                      binaryfunc slot = mv->nb_matrix_multiply;
  
                      if (likely(slot != NULL)) {
                          PyObject *x = slot(coerced1, coerced2);
  
                          Py_DECREF(coerced1);
                          Py_DECREF(coerced2);
  
                          if (unlikely(x == NULL)) {
                              return NULL;
                          }
  
                          return x;
                      }
                  }
  
                  // nb_coerce took a reference.
                  Py_DECREF(coerced1);
                  Py_DECREF(coerced2);
              }
          }
      }
  #endif
  
      PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for @: '%s' and '%s'", type1->tp_name, type2->tp_name);
      return NULL;
  }
  