#line 1 "numpy/core/src/umath/scalarmath.c.src"

/*
 *****************************************************************************
 **       This file was autogenerated from a template  DO NOT EDIT!!!!      **
 **       Changes should be made to the original source (.src) file         **
 *****************************************************************************
 */

#line 1
/* -*- c -*- */

/* The purpose of this module is to add faster math for array scalars
   that does not go through the ufunc machinery

   but still supports error-modes.
*/
#define PY_SSIZE_T_CLEAN
#include <Python.h>

#define _UMATHMODULE
#define _MULTIARRAYMODULE
#define NPY_NO_DEPRECATED_API NPY_API_VERSION

#include "npy_config.h"
#include "numpy/arrayobject.h"
#include "numpy/ufuncobject.h"
#include "numpy/arrayscalars.h"

#include "npy_import.h"
#include "npy_pycompat.h"

#include "numpy/halffloat.h"
#include "templ_common.h"

#include "binop_override.h"
#include "npy_longdouble.h"

#include "arraytypes.h"
#include "array_coercion.h"
#include "common.h"
#include "can_cast_table.h"
#include "umathmodule.h"

#include "convert_datatype.h"


/* TODO: Used for some functions, should possibly move these to npy_math.h */
#include "loops.h"

/* Basic operations:
 *
 *  BINARY:
 *
 * add, subtract, multiply, divide, remainder, divmod, power,
 * floor_divide, true_divide
 *
 * lshift, rshift, and, or, xor (integers only)
 *
 * UNARY:
 *
 * negative, positive, absolute, nonzero, invert, int, long, float, oct, hex
 *
 */

#line 60
static inline int
byte_ctype_add(npy_byte a, npy_byte b, npy_byte *out) {
    *out = a + b;
    if ((*out^a) >= 0 || (*out^b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
byte_ctype_subtract(npy_byte a, npy_byte b, npy_byte *out) {
    *out = a - b;
    if ((*out^a) >= 0 || (*out^~b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

#line 60
static inline int
short_ctype_add(npy_short a, npy_short b, npy_short *out) {
    *out = a + b;
    if ((*out^a) >= 0 || (*out^b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
short_ctype_subtract(npy_short a, npy_short b, npy_short *out) {
    *out = a - b;
    if ((*out^a) >= 0 || (*out^~b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

#line 60
static inline int
int_ctype_add(npy_int a, npy_int b, npy_int *out) {
    *out = a + b;
    if ((*out^a) >= 0 || (*out^b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
int_ctype_subtract(npy_int a, npy_int b, npy_int *out) {
    *out = a - b;
    if ((*out^a) >= 0 || (*out^~b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

#line 60
static inline int
long_ctype_add(npy_long a, npy_long b, npy_long *out) {
    *out = a + b;
    if ((*out^a) >= 0 || (*out^b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
long_ctype_subtract(npy_long a, npy_long b, npy_long *out) {
    *out = a - b;
    if ((*out^a) >= 0 || (*out^~b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

#line 60
static inline int
longlong_ctype_add(npy_longlong a, npy_longlong b, npy_longlong *out) {
    *out = a + b;
    if ((*out^a) >= 0 || (*out^b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
longlong_ctype_subtract(npy_longlong a, npy_longlong b, npy_longlong *out) {
    *out = a - b;
    if ((*out^a) >= 0 || (*out^~b) >= 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}


#line 83
static inline int
ubyte_ctype_add(npy_ubyte a, npy_ubyte b, npy_ubyte *out) {
    *out = a + b;
    if (*out >= a && *out >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
ubyte_ctype_subtract(npy_ubyte a, npy_ubyte b, npy_ubyte *out) {
    *out = a - b;
    if (a >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

#line 83
static inline int
ushort_ctype_add(npy_ushort a, npy_ushort b, npy_ushort *out) {
    *out = a + b;
    if (*out >= a && *out >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
ushort_ctype_subtract(npy_ushort a, npy_ushort b, npy_ushort *out) {
    *out = a - b;
    if (a >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

#line 83
static inline int
uint_ctype_add(npy_uint a, npy_uint b, npy_uint *out) {
    *out = a + b;
    if (*out >= a && *out >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
uint_ctype_subtract(npy_uint a, npy_uint b, npy_uint *out) {
    *out = a - b;
    if (a >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

#line 83
static inline int
ulong_ctype_add(npy_ulong a, npy_ulong b, npy_ulong *out) {
    *out = a + b;
    if (*out >= a && *out >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
ulong_ctype_subtract(npy_ulong a, npy_ulong b, npy_ulong *out) {
    *out = a - b;
    if (a >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

#line 83
static inline int
ulonglong_ctype_add(npy_ulonglong a, npy_ulonglong b, npy_ulonglong *out) {
    *out = a + b;
    if (*out >= a && *out >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}

static inline int
ulonglong_ctype_subtract(npy_ulonglong a, npy_ulonglong b, npy_ulonglong *out) {
    *out = a - b;
    if (a >= b) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
}


#ifndef NPY_SIZEOF_BYTE
#define NPY_SIZEOF_BYTE 1
#endif

#line 120
#if NPY_SIZEOF_INT > NPY_SIZEOF_BYTE
static inline int
byte_ctype_multiply(npy_byte a, npy_byte b, npy_byte *out) {
    npy_int temp;
    temp = ((npy_int) a) * ((npy_int) b);
    *out = (npy_byte) temp;
#if 1
    if (temp > NPY_MAX_BYTE || temp < NPY_MIN_BYTE) {
#else
    if (temp > NPY_MAX_BYTE) {
#endif
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 120
#if NPY_SIZEOF_INT > NPY_SIZEOF_BYTE
static inline int
ubyte_ctype_multiply(npy_ubyte a, npy_ubyte b, npy_ubyte *out) {
    npy_uint temp;
    temp = ((npy_uint) a) * ((npy_uint) b);
    *out = (npy_ubyte) temp;
#if 0
    if (temp > NPY_MAX_UBYTE || temp < NPY_MIN_UBYTE) {
#else
    if (temp > NPY_MAX_UBYTE) {
#endif
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 120
#if NPY_SIZEOF_INT > NPY_SIZEOF_SHORT
static inline int
short_ctype_multiply(npy_short a, npy_short b, npy_short *out) {
    npy_int temp;
    temp = ((npy_int) a) * ((npy_int) b);
    *out = (npy_short) temp;
#if 1
    if (temp > NPY_MAX_SHORT || temp < NPY_MIN_SHORT) {
#else
    if (temp > NPY_MAX_SHORT) {
#endif
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 120
#if NPY_SIZEOF_INT > NPY_SIZEOF_SHORT
static inline int
ushort_ctype_multiply(npy_ushort a, npy_ushort b, npy_ushort *out) {
    npy_uint temp;
    temp = ((npy_uint) a) * ((npy_uint) b);
    *out = (npy_ushort) temp;
#if 0
    if (temp > NPY_MAX_USHORT || temp < NPY_MIN_USHORT) {
#else
    if (temp > NPY_MAX_USHORT) {
#endif
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 120
#if NPY_SIZEOF_LONGLONG > NPY_SIZEOF_INT
static inline int
int_ctype_multiply(npy_int a, npy_int b, npy_int *out) {
    npy_longlong temp;
    temp = ((npy_longlong) a) * ((npy_longlong) b);
    *out = (npy_int) temp;
#if 1
    if (temp > NPY_MAX_INT || temp < NPY_MIN_INT) {
#else
    if (temp > NPY_MAX_INT) {
#endif
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 120
#if NPY_SIZEOF_LONGLONG > NPY_SIZEOF_INT
static inline int
uint_ctype_multiply(npy_uint a, npy_uint b, npy_uint *out) {
    npy_ulonglong temp;
    temp = ((npy_ulonglong) a) * ((npy_ulonglong) b);
    *out = (npy_uint) temp;
#if 0
    if (temp > NPY_MAX_UINT || temp < NPY_MIN_UINT) {
#else
    if (temp > NPY_MAX_UINT) {
#endif
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 120
#if NPY_SIZEOF_LONGLONG > NPY_SIZEOF_LONG
static inline int
long_ctype_multiply(npy_long a, npy_long b, npy_long *out) {
    npy_longlong temp;
    temp = ((npy_longlong) a) * ((npy_longlong) b);
    *out = (npy_long) temp;
#if 1
    if (temp > NPY_MAX_LONG || temp < NPY_MIN_LONG) {
#else
    if (temp > NPY_MAX_LONG) {
#endif
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 120
#if NPY_SIZEOF_LONGLONG > NPY_SIZEOF_LONG
static inline int
ulong_ctype_multiply(npy_ulong a, npy_ulong b, npy_ulong *out) {
    npy_ulonglong temp;
    temp = ((npy_ulonglong) a) * ((npy_ulonglong) b);
    *out = (npy_ulong) temp;
#if 0
    if (temp > NPY_MAX_ULONG || temp < NPY_MIN_ULONG) {
#else
    if (temp > NPY_MAX_ULONG) {
#endif
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif


#line 146
#if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_INT
static inline int
int_ctype_multiply(npy_int a, npy_int b, npy_int *out) {
    if (npy_mul_with_overflow_int(out, a, b)) {
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 146
#if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_INT
static inline int
uint_ctype_multiply(npy_uint a, npy_uint b, npy_uint *out) {
    if (npy_mul_with_overflow_uint(out, a, b)) {
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 146
#if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_LONG
static inline int
long_ctype_multiply(npy_long a, npy_long b, npy_long *out) {
    if (npy_mul_with_overflow_long(out, a, b)) {
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 146
#if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_LONG
static inline int
ulong_ctype_multiply(npy_ulong a, npy_ulong b, npy_ulong *out) {
    if (npy_mul_with_overflow_ulong(out, a, b)) {
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 146
#if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_LONGLONG
static inline int
longlong_ctype_multiply(npy_longlong a, npy_longlong b, npy_longlong *out) {
    if (npy_mul_with_overflow_longlong(out, a, b)) {
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif

#line 146
#if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_LONGLONG
static inline int
ulonglong_ctype_multiply(npy_ulonglong a, npy_ulonglong b, npy_ulonglong *out) {
    if (npy_mul_with_overflow_ulonglong(out, a, b)) {
        return NPY_FPE_OVERFLOW;
    }
    return 0;
}
#endif


#line 167

#if 1
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_BYTE && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
byte_ctype_divide(npy_byte a, npy_byte b, npy_byte *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 1
    else if (b == -1 && a == NPY_MIN_BYTE) {
        *out = NPY_MIN_BYTE;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 1
        npy_byte tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define byte_ctype_floor_divide byte_ctype_divide

static inline int
byte_ctype_remainder(npy_byte a, npy_byte b, npy_byte *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 1
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK

#line 167

#if 0
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_UBYTE && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
ubyte_ctype_divide(npy_ubyte a, npy_ubyte b, npy_ubyte *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 0
    else if (b == -1 && a == NPY_MIN_UBYTE) {
        *out = NPY_MIN_UBYTE;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 0
        npy_ubyte tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define ubyte_ctype_floor_divide ubyte_ctype_divide

static inline int
ubyte_ctype_remainder(npy_ubyte a, npy_ubyte b, npy_ubyte *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 0
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK

#line 167

#if 1
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_SHORT && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
short_ctype_divide(npy_short a, npy_short b, npy_short *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 1
    else if (b == -1 && a == NPY_MIN_SHORT) {
        *out = NPY_MIN_SHORT;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 1
        npy_short tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define short_ctype_floor_divide short_ctype_divide

static inline int
short_ctype_remainder(npy_short a, npy_short b, npy_short *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 1
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK

#line 167

#if 0
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_USHORT && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
ushort_ctype_divide(npy_ushort a, npy_ushort b, npy_ushort *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 0
    else if (b == -1 && a == NPY_MIN_USHORT) {
        *out = NPY_MIN_USHORT;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 0
        npy_ushort tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define ushort_ctype_floor_divide ushort_ctype_divide

static inline int
ushort_ctype_remainder(npy_ushort a, npy_ushort b, npy_ushort *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 0
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK

#line 167

#if 1
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_INT && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
int_ctype_divide(npy_int a, npy_int b, npy_int *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 1
    else if (b == -1 && a == NPY_MIN_INT) {
        *out = NPY_MIN_INT;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 1
        npy_int tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define int_ctype_floor_divide int_ctype_divide

static inline int
int_ctype_remainder(npy_int a, npy_int b, npy_int *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 1
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK

#line 167

#if 0
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_UINT && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
uint_ctype_divide(npy_uint a, npy_uint b, npy_uint *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 0
    else if (b == -1 && a == NPY_MIN_UINT) {
        *out = NPY_MIN_UINT;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 0
        npy_uint tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define uint_ctype_floor_divide uint_ctype_divide

static inline int
uint_ctype_remainder(npy_uint a, npy_uint b, npy_uint *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 0
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK

#line 167

#if 1
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_LONG && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
long_ctype_divide(npy_long a, npy_long b, npy_long *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 1
    else if (b == -1 && a == NPY_MIN_LONG) {
        *out = NPY_MIN_LONG;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 1
        npy_long tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define long_ctype_floor_divide long_ctype_divide

static inline int
long_ctype_remainder(npy_long a, npy_long b, npy_long *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 1
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK

#line 167

#if 0
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_ULONG && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
ulong_ctype_divide(npy_ulong a, npy_ulong b, npy_ulong *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 0
    else if (b == -1 && a == NPY_MIN_ULONG) {
        *out = NPY_MIN_ULONG;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 0
        npy_ulong tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define ulong_ctype_floor_divide ulong_ctype_divide

static inline int
ulong_ctype_remainder(npy_ulong a, npy_ulong b, npy_ulong *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 0
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK

#line 167

#if 1
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_LONGLONG && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
longlong_ctype_divide(npy_longlong a, npy_longlong b, npy_longlong *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 1
    else if (b == -1 && a == NPY_MIN_LONGLONG) {
        *out = NPY_MIN_LONGLONG;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 1
        npy_longlong tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define longlong_ctype_floor_divide longlong_ctype_divide

static inline int
longlong_ctype_remainder(npy_longlong a, npy_longlong b, npy_longlong *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 1
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK

#line 167

#if 0
    #define DIVIDEBYZERO_CHECK (b == 0 || (a == NPY_MIN_ULONGLONG && b == -1))
#else
    #define DIVIDEBYZERO_CHECK (b == 0)
#endif

static inline int
ulonglong_ctype_divide(npy_ulonglong a, npy_ulonglong b, npy_ulonglong *out) {
    if (b == 0) {
        *out = 0;
        return NPY_FPE_DIVIDEBYZERO;
    }
#if 0
    else if (b == -1 && a == NPY_MIN_ULONGLONG) {
        *out = NPY_MIN_ULONGLONG;
        return NPY_FPE_OVERFLOW;
    }
#endif
    else {
#if 0
        npy_ulonglong tmp;
        tmp = a / b;
        if (((a > 0) != (b > 0)) && (a % b != 0)) {
            tmp--;
        }
        *out = tmp;
#else
        *out = a / b;
#endif
        return 0;
    }
}

#define ulonglong_ctype_floor_divide ulonglong_ctype_divide

static inline int
ulonglong_ctype_remainder(npy_ulonglong a, npy_ulonglong b, npy_ulonglong *out) {
    if (DIVIDEBYZERO_CHECK) {
        *out = 0;
        if (b == 0) {
            return NPY_FPE_DIVIDEBYZERO;
        }
        return 0;
    }
#if 0
    else if ((a > 0) == (b > 0)) {
        *out = a % b;
    }
    else {
        /* handled like Python does */
        *out = a % b;
        if (*out) *out += b;
    }
#else
    *out = a % b;
#endif
    return 0;
}
#undef DIVIDEBYZERO_CHECK


#line 234

static inline int
byte_ctype_true_divide(npy_byte a, npy_byte b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}


#line 234

static inline int
ubyte_ctype_true_divide(npy_ubyte a, npy_ubyte b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}


#line 234

static inline int
short_ctype_true_divide(npy_short a, npy_short b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}


#line 234

static inline int
ushort_ctype_true_divide(npy_ushort a, npy_ushort b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}


#line 234

static inline int
int_ctype_true_divide(npy_int a, npy_int b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}


#line 234

static inline int
uint_ctype_true_divide(npy_uint a, npy_uint b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}


#line 234

static inline int
long_ctype_true_divide(npy_long a, npy_long b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}


#line 234

static inline int
ulong_ctype_true_divide(npy_ulong a, npy_ulong b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}


#line 234

static inline int
longlong_ctype_true_divide(npy_longlong a, npy_longlong b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}


#line 234

static inline int
ulonglong_ctype_true_divide(npy_ulonglong a, npy_ulonglong b, npy_double *out)
{
    *out = (npy_double)a / (npy_double)b;
    return 0;
}



/* b will always be positive in this call */
#line 254
static inline int
byte_ctype_power(npy_byte a, npy_byte b, npy_byte *out) {
    npy_byte tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}

#line 254
static inline int
ubyte_ctype_power(npy_ubyte a, npy_ubyte b, npy_ubyte *out) {
    npy_ubyte tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}

#line 254
static inline int
short_ctype_power(npy_short a, npy_short b, npy_short *out) {
    npy_short tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}

#line 254
static inline int
ushort_ctype_power(npy_ushort a, npy_ushort b, npy_ushort *out) {
    npy_ushort tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}

#line 254
static inline int
int_ctype_power(npy_int a, npy_int b, npy_int *out) {
    npy_int tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}

#line 254
static inline int
uint_ctype_power(npy_uint a, npy_uint b, npy_uint *out) {
    npy_uint tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}

#line 254
static inline int
long_ctype_power(npy_long a, npy_long b, npy_long *out) {
    npy_long tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}

#line 254
static inline int
ulong_ctype_power(npy_ulong a, npy_ulong b, npy_ulong *out) {
    npy_ulong tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}

#line 254
static inline int
longlong_ctype_power(npy_longlong a, npy_longlong b, npy_longlong *out) {
    npy_longlong tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}

#line 254
static inline int
ulonglong_ctype_power(npy_ulonglong a, npy_ulonglong b, npy_ulonglong *out) {
    npy_ulonglong tmp;

    if (b == 0) {
        *out = 1;
        return 0;
    }
    if (a == 1) {
        *out = 1;
        return 0;
    }

    tmp = b & 1 ? a : 1;
    b >>= 1;
    while (b > 0) {
        a *= a;
        if (b & 1) {
            tmp *= a;
        }
        b >>= 1;
    }
    *out = tmp;
    return 0;
}



#line 289

#line 294

static inline int
byte_ctype_and(npy_byte arg1, npy_byte arg2, npy_byte *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
byte_ctype_xor(npy_byte arg1, npy_byte arg2, npy_byte *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
byte_ctype_or(npy_byte arg1, npy_byte arg2, npy_byte *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
byte_ctype_lshift(npy_byte arg1, npy_byte arg2, npy_byte *out)
{
    *out = npy_lshifthh(arg1, arg2);
    return 0;
}

static inline int
byte_ctype_rshift(npy_byte arg1, npy_byte arg2, npy_byte *out)
{
    *out = npy_rshifthh(arg1, arg2);
    return 0;
}


#line 289

#line 294

static inline int
ubyte_ctype_and(npy_ubyte arg1, npy_ubyte arg2, npy_ubyte *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
ubyte_ctype_xor(npy_ubyte arg1, npy_ubyte arg2, npy_ubyte *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
ubyte_ctype_or(npy_ubyte arg1, npy_ubyte arg2, npy_ubyte *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
ubyte_ctype_lshift(npy_ubyte arg1, npy_ubyte arg2, npy_ubyte *out)
{
    *out = npy_lshiftuhh(arg1, arg2);
    return 0;
}

static inline int
ubyte_ctype_rshift(npy_ubyte arg1, npy_ubyte arg2, npy_ubyte *out)
{
    *out = npy_rshiftuhh(arg1, arg2);
    return 0;
}


#line 289

#line 294

static inline int
short_ctype_and(npy_short arg1, npy_short arg2, npy_short *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
short_ctype_xor(npy_short arg1, npy_short arg2, npy_short *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
short_ctype_or(npy_short arg1, npy_short arg2, npy_short *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
short_ctype_lshift(npy_short arg1, npy_short arg2, npy_short *out)
{
    *out = npy_lshifth(arg1, arg2);
    return 0;
}

static inline int
short_ctype_rshift(npy_short arg1, npy_short arg2, npy_short *out)
{
    *out = npy_rshifth(arg1, arg2);
    return 0;
}


#line 289

#line 294

static inline int
ushort_ctype_and(npy_ushort arg1, npy_ushort arg2, npy_ushort *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
ushort_ctype_xor(npy_ushort arg1, npy_ushort arg2, npy_ushort *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
ushort_ctype_or(npy_ushort arg1, npy_ushort arg2, npy_ushort *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
ushort_ctype_lshift(npy_ushort arg1, npy_ushort arg2, npy_ushort *out)
{
    *out = npy_lshiftuh(arg1, arg2);
    return 0;
}

static inline int
ushort_ctype_rshift(npy_ushort arg1, npy_ushort arg2, npy_ushort *out)
{
    *out = npy_rshiftuh(arg1, arg2);
    return 0;
}


#line 289

#line 294

static inline int
int_ctype_and(npy_int arg1, npy_int arg2, npy_int *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
int_ctype_xor(npy_int arg1, npy_int arg2, npy_int *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
int_ctype_or(npy_int arg1, npy_int arg2, npy_int *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
int_ctype_lshift(npy_int arg1, npy_int arg2, npy_int *out)
{
    *out = npy_lshift(arg1, arg2);
    return 0;
}

static inline int
int_ctype_rshift(npy_int arg1, npy_int arg2, npy_int *out)
{
    *out = npy_rshift(arg1, arg2);
    return 0;
}


#line 289

#line 294

static inline int
uint_ctype_and(npy_uint arg1, npy_uint arg2, npy_uint *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
uint_ctype_xor(npy_uint arg1, npy_uint arg2, npy_uint *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
uint_ctype_or(npy_uint arg1, npy_uint arg2, npy_uint *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
uint_ctype_lshift(npy_uint arg1, npy_uint arg2, npy_uint *out)
{
    *out = npy_lshiftu(arg1, arg2);
    return 0;
}

static inline int
uint_ctype_rshift(npy_uint arg1, npy_uint arg2, npy_uint *out)
{
    *out = npy_rshiftu(arg1, arg2);
    return 0;
}


#line 289

#line 294

static inline int
long_ctype_and(npy_long arg1, npy_long arg2, npy_long *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
long_ctype_xor(npy_long arg1, npy_long arg2, npy_long *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
long_ctype_or(npy_long arg1, npy_long arg2, npy_long *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
long_ctype_lshift(npy_long arg1, npy_long arg2, npy_long *out)
{
    *out = npy_lshiftl(arg1, arg2);
    return 0;
}

static inline int
long_ctype_rshift(npy_long arg1, npy_long arg2, npy_long *out)
{
    *out = npy_rshiftl(arg1, arg2);
    return 0;
}


#line 289

#line 294

static inline int
ulong_ctype_and(npy_ulong arg1, npy_ulong arg2, npy_ulong *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
ulong_ctype_xor(npy_ulong arg1, npy_ulong arg2, npy_ulong *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
ulong_ctype_or(npy_ulong arg1, npy_ulong arg2, npy_ulong *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
ulong_ctype_lshift(npy_ulong arg1, npy_ulong arg2, npy_ulong *out)
{
    *out = npy_lshiftul(arg1, arg2);
    return 0;
}

static inline int
ulong_ctype_rshift(npy_ulong arg1, npy_ulong arg2, npy_ulong *out)
{
    *out = npy_rshiftul(arg1, arg2);
    return 0;
}


#line 289

#line 294

static inline int
longlong_ctype_and(npy_longlong arg1, npy_longlong arg2, npy_longlong *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
longlong_ctype_xor(npy_longlong arg1, npy_longlong arg2, npy_longlong *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
longlong_ctype_or(npy_longlong arg1, npy_longlong arg2, npy_longlong *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
longlong_ctype_lshift(npy_longlong arg1, npy_longlong arg2, npy_longlong *out)
{
    *out = npy_lshiftll(arg1, arg2);
    return 0;
}

static inline int
longlong_ctype_rshift(npy_longlong arg1, npy_longlong arg2, npy_longlong *out)
{
    *out = npy_rshiftll(arg1, arg2);
    return 0;
}


#line 289

#line 294

static inline int
ulonglong_ctype_and(npy_ulonglong arg1, npy_ulonglong arg2, npy_ulonglong *out)
{
    *out = arg1 & arg2;
    return 0;
}


#line 294

static inline int
ulonglong_ctype_xor(npy_ulonglong arg1, npy_ulonglong arg2, npy_ulonglong *out)
{
    *out = arg1 ^ arg2;
    return 0;
}


#line 294

static inline int
ulonglong_ctype_or(npy_ulonglong arg1, npy_ulonglong arg2, npy_ulonglong *out)
{
    *out = arg1 | arg2;
    return 0;
}



static inline int
ulonglong_ctype_lshift(npy_ulonglong arg1, npy_ulonglong arg2, npy_ulonglong *out)
{
    *out = npy_lshiftull(arg1, arg2);
    return 0;
}

static inline int
ulonglong_ctype_rshift(npy_ulonglong arg1, npy_ulonglong arg2, npy_ulonglong *out)
{
    *out = npy_rshiftull(arg1, arg2);
    return 0;
}



#line 325

#line 330

static inline int
float_ctype_add(npy_float a, npy_float b, npy_float *out)
{
    *out = a + b;
    return 0;
}


#line 330

static inline int
float_ctype_subtract(npy_float a, npy_float b, npy_float *out)
{
    *out = a - b;
    return 0;
}


#line 330

static inline int
float_ctype_multiply(npy_float a, npy_float b, npy_float *out)
{
    *out = a * b;
    return 0;
}


#line 330

static inline int
float_ctype_divide(npy_float a, npy_float b, npy_float *out)
{
    *out = a / b;
    return 0;
}



#define float_ctype_true_divide float_ctype_divide


static inline int
float_ctype_floor_divide(npy_float a, npy_float b, npy_float *out) {
    *out = npy_floor_dividef(a, b);
    return 0;
}


static inline int
float_ctype_remainder(npy_float a, npy_float b, npy_float *out) {
    *out = npy_remainderf(a, b);
    return 0;
}


static inline int
float_ctype_divmod(npy_float a, npy_float b, npy_float *out1, npy_float *out2) {
    *out1 = npy_divmodf(a, b, out2);
    return 0;
}



#line 325

#line 330

static inline int
double_ctype_add(npy_double a, npy_double b, npy_double *out)
{
    *out = a + b;
    return 0;
}


#line 330

static inline int
double_ctype_subtract(npy_double a, npy_double b, npy_double *out)
{
    *out = a - b;
    return 0;
}


#line 330

static inline int
double_ctype_multiply(npy_double a, npy_double b, npy_double *out)
{
    *out = a * b;
    return 0;
}


#line 330

static inline int
double_ctype_divide(npy_double a, npy_double b, npy_double *out)
{
    *out = a / b;
    return 0;
}



#define double_ctype_true_divide double_ctype_divide


static inline int
double_ctype_floor_divide(npy_double a, npy_double b, npy_double *out) {
    *out = npy_floor_divide(a, b);
    return 0;
}


static inline int
double_ctype_remainder(npy_double a, npy_double b, npy_double *out) {
    *out = npy_remainder(a, b);
    return 0;
}


static inline int
double_ctype_divmod(npy_double a, npy_double b, npy_double *out1, npy_double *out2) {
    *out1 = npy_divmod(a, b, out2);
    return 0;
}



#line 325

#line 330

static inline int
longdouble_ctype_add(npy_longdouble a, npy_longdouble b, npy_longdouble *out)
{
    *out = a + b;
    return 0;
}


#line 330

static inline int
longdouble_ctype_subtract(npy_longdouble a, npy_longdouble b, npy_longdouble *out)
{
    *out = a - b;
    return 0;
}


#line 330

static inline int
longdouble_ctype_multiply(npy_longdouble a, npy_longdouble b, npy_longdouble *out)
{
    *out = a * b;
    return 0;
}


#line 330

static inline int
longdouble_ctype_divide(npy_longdouble a, npy_longdouble b, npy_longdouble *out)
{
    *out = a / b;
    return 0;
}



#define longdouble_ctype_true_divide longdouble_ctype_divide


static inline int
longdouble_ctype_floor_divide(npy_longdouble a, npy_longdouble b, npy_longdouble *out) {
    *out = npy_floor_dividel(a, b);
    return 0;
}


static inline int
longdouble_ctype_remainder(npy_longdouble a, npy_longdouble b, npy_longdouble *out) {
    *out = npy_remainderl(a, b);
    return 0;
}


static inline int
longdouble_ctype_divmod(npy_longdouble a, npy_longdouble b, npy_longdouble *out1, npy_longdouble *out2) {
    *out1 = npy_divmodl(a, b, out2);
    return 0;
}




#line 370

static inline int
half_ctype_add(npy_half a, npy_half b, npy_half *out)
{
    float res = npy_half_to_float(a) + npy_half_to_float(b);
    *out = npy_float_to_half(res);
    return 0;
}


#line 370

static inline int
half_ctype_subtract(npy_half a, npy_half b, npy_half *out)
{
    float res = npy_half_to_float(a) - npy_half_to_float(b);
    *out = npy_float_to_half(res);
    return 0;
}


#line 370

static inline int
half_ctype_multiply(npy_half a, npy_half b, npy_half *out)
{
    float res = npy_half_to_float(a) * npy_half_to_float(b);
    *out = npy_float_to_half(res);
    return 0;
}


#line 370

static inline int
half_ctype_divide(npy_half a, npy_half b, npy_half *out)
{
    float res = npy_half_to_float(a) / npy_half_to_float(b);
    *out = npy_float_to_half(res);
    return 0;
}


#define half_ctype_true_divide half_ctype_divide


static inline int
half_ctype_floor_divide(npy_half a, npy_half b, npy_half *out)
{
    npy_half mod;

    if (!b) {
        float res = npy_half_to_float(a) / npy_half_to_float(b);
        *out = npy_float_to_half(res);
    }
    else {
        *out = npy_half_divmod(a, b, &mod);
    }
    return 0;
}


static inline int
half_ctype_remainder(npy_half a, npy_half b, npy_half *out)
{
    npy_half_divmod(a, b, out);
    return 0;
}


static inline int
half_ctype_divmod(npy_half a, npy_half b, npy_half *out1, npy_half *out2)
{
    *out1 = npy_half_divmod(a, b, out2);
    return 0;
}

#line 422
static inline int
cfloat_ctype_add(npy_cfloat a, npy_cfloat b, npy_cfloat *out)
{
    out->real = a.real + b.real;
    out->imag = a.imag + b.imag;
    return 0;
}

static inline int
cfloat_ctype_subtract(npy_cfloat a, npy_cfloat b, npy_cfloat *out)
{
    out->real = a.real - b.real;
    out->imag = a.imag - b.imag;
    return 0;
}


/*
 * TODO: Mark as  to work around FPEs not being issues on clang 12.
 *       This should be removed when possible.
 */
static inline int
cfloat_ctype_multiply( npy_cfloat a, npy_cfloat b, npy_cfloat *out)
{
    out->real = a.real * b.real - a.imag * b.imag;
    out->imag = a.real * b.imag + a.imag * b.real;
    return 0;
}

/* Use the ufunc loop directly to avoid duplicating the complicated logic */
static inline int
cfloat_ctype_divide(npy_cfloat a, npy_cfloat b, npy_cfloat *out)
{
    char *args[3] = {(char *)&a, (char *)&b, (char *)out};
    npy_intp steps[3] = {0, 0, 0};
    npy_intp size = 1;
    CFLOAT_divide(args, &size, steps, NULL);
    return 0;
}

#define cfloat_ctype_true_divide cfloat_ctype_divide


#line 422
static inline int
cdouble_ctype_add(npy_cdouble a, npy_cdouble b, npy_cdouble *out)
{
    out->real = a.real + b.real;
    out->imag = a.imag + b.imag;
    return 0;
}

static inline int
cdouble_ctype_subtract(npy_cdouble a, npy_cdouble b, npy_cdouble *out)
{
    out->real = a.real - b.real;
    out->imag = a.imag - b.imag;
    return 0;
}


/*
 * TODO: Mark as  to work around FPEs not being issues on clang 12.
 *       This should be removed when possible.
 */
static inline int
cdouble_ctype_multiply( npy_cdouble a, npy_cdouble b, npy_cdouble *out)
{
    out->real = a.real * b.real - a.imag * b.imag;
    out->imag = a.real * b.imag + a.imag * b.real;
    return 0;
}

/* Use the ufunc loop directly to avoid duplicating the complicated logic */
static inline int
cdouble_ctype_divide(npy_cdouble a, npy_cdouble b, npy_cdouble *out)
{
    char *args[3] = {(char *)&a, (char *)&b, (char *)out};
    npy_intp steps[3] = {0, 0, 0};
    npy_intp size = 1;
    CDOUBLE_divide(args, &size, steps, NULL);
    return 0;
}

#define cdouble_ctype_true_divide cdouble_ctype_divide


#line 422
static inline int
clongdouble_ctype_add(npy_clongdouble a, npy_clongdouble b, npy_clongdouble *out)
{
    out->real = a.real + b.real;
    out->imag = a.imag + b.imag;
    return 0;
}

static inline int
clongdouble_ctype_subtract(npy_clongdouble a, npy_clongdouble b, npy_clongdouble *out)
{
    out->real = a.real - b.real;
    out->imag = a.imag - b.imag;
    return 0;
}


/*
 * TODO: Mark as  to work around FPEs not being issues on clang 12.
 *       This should be removed when possible.
 */
static inline int
clongdouble_ctype_multiply( npy_clongdouble a, npy_clongdouble b, npy_clongdouble *out)
{
    out->real = a.real * b.real - a.imag * b.imag;
    out->imag = a.real * b.imag + a.imag * b.real;
    return 0;
}

/* Use the ufunc loop directly to avoid duplicating the complicated logic */
static inline int
clongdouble_ctype_divide(npy_clongdouble a, npy_clongdouble b, npy_clongdouble *out)
{
    char *args[3] = {(char *)&a, (char *)&b, (char *)out};
    npy_intp steps[3] = {0, 0, 0};
    npy_intp size = 1;
    CLONGDOUBLE_divide(args, &size, steps, NULL);
    return 0;
}

#define clongdouble_ctype_true_divide clongdouble_ctype_divide





#line 472

static inline int
byte_ctype_divmod(npy_byte a, npy_byte b, npy_byte *out, npy_byte *out2)
{
    int res = byte_ctype_floor_divide(a, b, out);
    res |= byte_ctype_remainder(a, b, out2);
    return res;
}


#line 472

static inline int
ubyte_ctype_divmod(npy_ubyte a, npy_ubyte b, npy_ubyte *out, npy_ubyte *out2)
{
    int res = ubyte_ctype_floor_divide(a, b, out);
    res |= ubyte_ctype_remainder(a, b, out2);
    return res;
}


#line 472

static inline int
short_ctype_divmod(npy_short a, npy_short b, npy_short *out, npy_short *out2)
{
    int res = short_ctype_floor_divide(a, b, out);
    res |= short_ctype_remainder(a, b, out2);
    return res;
}


#line 472

static inline int
ushort_ctype_divmod(npy_ushort a, npy_ushort b, npy_ushort *out, npy_ushort *out2)
{
    int res = ushort_ctype_floor_divide(a, b, out);
    res |= ushort_ctype_remainder(a, b, out2);
    return res;
}


#line 472

static inline int
int_ctype_divmod(npy_int a, npy_int b, npy_int *out, npy_int *out2)
{
    int res = int_ctype_floor_divide(a, b, out);
    res |= int_ctype_remainder(a, b, out2);
    return res;
}


#line 472

static inline int
uint_ctype_divmod(npy_uint a, npy_uint b, npy_uint *out, npy_uint *out2)
{
    int res = uint_ctype_floor_divide(a, b, out);
    res |= uint_ctype_remainder(a, b, out2);
    return res;
}


#line 472

static inline int
long_ctype_divmod(npy_long a, npy_long b, npy_long *out, npy_long *out2)
{
    int res = long_ctype_floor_divide(a, b, out);
    res |= long_ctype_remainder(a, b, out2);
    return res;
}


#line 472

static inline int
ulong_ctype_divmod(npy_ulong a, npy_ulong b, npy_ulong *out, npy_ulong *out2)
{
    int res = ulong_ctype_floor_divide(a, b, out);
    res |= ulong_ctype_remainder(a, b, out2);
    return res;
}


#line 472

static inline int
longlong_ctype_divmod(npy_longlong a, npy_longlong b, npy_longlong *out, npy_longlong *out2)
{
    int res = longlong_ctype_floor_divide(a, b, out);
    res |= longlong_ctype_remainder(a, b, out2);
    return res;
}


#line 472

static inline int
ulonglong_ctype_divmod(npy_ulonglong a, npy_ulonglong b, npy_ulonglong *out, npy_ulonglong *out2)
{
    int res = ulonglong_ctype_floor_divide(a, b, out);
    res |= ulonglong_ctype_remainder(a, b, out2);
    return res;
}




#line 489

static inline int
float_ctype_power(npy_float a, npy_float b, npy_float *out)
{
    *out = npy_powf(a, b);
    return 0;
}


#line 489

static inline int
double_ctype_power(npy_double a, npy_double b, npy_double *out)
{
    *out = npy_pow(a, b);
    return 0;
}


#line 489

static inline int
longdouble_ctype_power(npy_longdouble a, npy_longdouble b, npy_longdouble *out)
{
    *out = npy_powl(a, b);
    return 0;
}


static inline int
half_ctype_power(npy_half a, npy_half b, npy_half *out)
{
    const npy_float af = npy_half_to_float(a);
    const npy_float bf = npy_half_to_float(b);
    const npy_float outf = npy_powf(af,bf);
    *out = npy_float_to_half(outf);
    return 0;
}

#line 521
static inline int
byte_ctype_negative(npy_byte a, npy_byte *out)
{
#if 0
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_BYTE){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
ubyte_ctype_negative(npy_ubyte a, npy_ubyte *out)
{
#if 1
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_UBYTE){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
short_ctype_negative(npy_short a, npy_short *out)
{
#if 0
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_SHORT){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
ushort_ctype_negative(npy_ushort a, npy_ushort *out)
{
#if 1
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_USHORT){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
int_ctype_negative(npy_int a, npy_int *out)
{
#if 0
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_INT){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
uint_ctype_negative(npy_uint a, npy_uint *out)
{
#if 1
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_UINT){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
long_ctype_negative(npy_long a, npy_long *out)
{
#if 0
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_LONG){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
ulong_ctype_negative(npy_ulong a, npy_ulong *out)
{
#if 1
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_ULONG){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
longlong_ctype_negative(npy_longlong a, npy_longlong *out)
{
#if 0
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_LONGLONG){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
ulonglong_ctype_negative(npy_ulonglong a, npy_ulonglong *out)
{
#if 1
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 1
    if (a == NPY_MIN_ULONGLONG){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
float_ctype_negative(npy_float a, npy_float *out)
{
#if 0
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 0
    if (a == NPY_MIN_FLOAT){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
double_ctype_negative(npy_double a, npy_double *out)
{
#if 0
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 0
    if (a == NPY_MIN_DOUBLE){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}

#line 521
static inline int
longdouble_ctype_negative(npy_longdouble a, npy_longdouble *out)
{
#if 0
    *out = -a;
    if (a == 0) {
        return 0;
    }
    return NPY_FPE_OVERFLOW;
#elif 0
    if (a == NPY_MIN_LONGDOUBLE){
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = -a;
    return 0;
#else  /* floats */
    *out = -a;
    return 0;
#endif
}


static inline int
half_ctype_negative(npy_half a, npy_half *out)
{
    *out = a^0x8000u;
    return 0;
}


#line 556
static inline int
cfloat_ctype_negative(npy_cfloat a, npy_cfloat *out)
{
    out->real = -a.real;
    out->imag = -a.imag;
    return 0;
}

#line 556
static inline int
cdouble_ctype_negative(npy_cdouble a, npy_cdouble *out)
{
    out->real = -a.real;
    out->imag = -a.imag;
    return 0;
}

#line 556
static inline int
clongdouble_ctype_negative(npy_clongdouble a, npy_clongdouble *out)
{
    out->real = -a.real;
    out->imag = -a.imag;
    return 0;
}


#line 573
static inline int
byte_ctype_positive(npy_byte a, npy_byte *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
ubyte_ctype_positive(npy_ubyte a, npy_ubyte *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
short_ctype_positive(npy_short a, npy_short *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
ushort_ctype_positive(npy_ushort a, npy_ushort *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
int_ctype_positive(npy_int a, npy_int *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
uint_ctype_positive(npy_uint a, npy_uint *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
long_ctype_positive(npy_long a, npy_long *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
ulong_ctype_positive(npy_ulong a, npy_ulong *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
longlong_ctype_positive(npy_longlong a, npy_longlong *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
ulonglong_ctype_positive(npy_ulonglong a, npy_ulonglong *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
half_ctype_positive(npy_half a, npy_half *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
float_ctype_positive(npy_float a, npy_float *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
double_ctype_positive(npy_double a, npy_double *out)
{
    *out = a;
    return 0;
}

#line 573
static inline int
longdouble_ctype_positive(npy_longdouble a, npy_longdouble *out)
{
    *out = a;
    return 0;
}


#line 586
static inline int
cfloat_ctype_positive(npy_cfloat a, npy_cfloat *out)
{
    out->real = a.real;
    out->imag = a.imag;
    return 0;
}

static inline int
cfloat_ctype_power(npy_cfloat a, npy_cfloat b, npy_cfloat *out)
{
    *out = npy_cpowf(a, b);
    return 0;
}

#line 586
static inline int
cdouble_ctype_positive(npy_cdouble a, npy_cdouble *out)
{
    out->real = a.real;
    out->imag = a.imag;
    return 0;
}

static inline int
cdouble_ctype_power(npy_cdouble a, npy_cdouble b, npy_cdouble *out)
{
    *out = npy_cpow(a, b);
    return 0;
}

#line 586
static inline int
clongdouble_ctype_positive(npy_clongdouble a, npy_clongdouble *out)
{
    out->real = a.real;
    out->imag = a.imag;
    return 0;
}

static inline int
clongdouble_ctype_power(npy_clongdouble a, npy_clongdouble b, npy_clongdouble *out)
{
    *out = npy_cpowl(a, b);
    return 0;
}



#line 606

#define ubyte_ctype_absolute ubyte_ctype_positive


#line 606

#define ushort_ctype_absolute ushort_ctype_positive


#line 606

#define uint_ctype_absolute uint_ctype_positive


#line 606

#define ulong_ctype_absolute ulong_ctype_positive


#line 606

#define ulonglong_ctype_absolute ulonglong_ctype_positive




#line 617
static inline int
byte_ctype_absolute(npy_byte a, npy_byte *out)
{
    if (a == NPY_MIN_BYTE) {
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = (a < 0 ? -a : a);
    return 0;
}

#line 617
static inline int
short_ctype_absolute(npy_short a, npy_short *out)
{
    if (a == NPY_MIN_SHORT) {
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = (a < 0 ? -a : a);
    return 0;
}

#line 617
static inline int
int_ctype_absolute(npy_int a, npy_int *out)
{
    if (a == NPY_MIN_INT) {
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = (a < 0 ? -a : a);
    return 0;
}

#line 617
static inline int
long_ctype_absolute(npy_long a, npy_long *out)
{
    if (a == NPY_MIN_LONG) {
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = (a < 0 ? -a : a);
    return 0;
}

#line 617
static inline int
longlong_ctype_absolute(npy_longlong a, npy_longlong *out)
{
    if (a == NPY_MIN_LONGLONG) {
        *out = a;
        return NPY_FPE_OVERFLOW;
    }
    *out = (a < 0 ? -a : a);
    return 0;
}


#line 634
static inline int
float_ctype_absolute(npy_float a, npy_float *out)
{
    *out = npy_fabsf(a);
    return 0;
}

#line 634
static inline int
double_ctype_absolute(npy_double a, npy_double *out)
{
    *out = npy_fabs(a);
    return 0;
}

#line 634
static inline int
longdouble_ctype_absolute(npy_longdouble a, npy_longdouble *out)
{
    *out = npy_fabsl(a);
    return 0;
}


static inline int
half_ctype_absolute(npy_half a, npy_half *out)
{
    *out = a&0x7fffu;
    return 0;
}

#line 655
static inline int
cfloat_ctype_absolute(npy_cfloat a, npy_float *out)
{
    *out = npy_cabsf(a);
    return 0;
}

#line 655
static inline int
cdouble_ctype_absolute(npy_cdouble a, npy_double *out)
{
    *out = npy_cabs(a);
    return 0;
}

#line 655
static inline int
clongdouble_ctype_absolute(npy_clongdouble a, npy_longdouble *out)
{
    *out = npy_cabsl(a);
    return 0;
}


#line 667

static inline int
byte_ctype_invert(npy_byte a, npy_byte *out)
{
    *out = ~a;
    return 0;
}


#line 667

static inline int
ubyte_ctype_invert(npy_ubyte a, npy_ubyte *out)
{
    *out = ~a;
    return 0;
}


#line 667

static inline int
short_ctype_invert(npy_short a, npy_short *out)
{
    *out = ~a;
    return 0;
}


#line 667

static inline int
ushort_ctype_invert(npy_ushort a, npy_ushort *out)
{
    *out = ~a;
    return 0;
}


#line 667

static inline int
int_ctype_invert(npy_int a, npy_int *out)
{
    *out = ~a;
    return 0;
}


#line 667

static inline int
uint_ctype_invert(npy_uint a, npy_uint *out)
{
    *out = ~a;
    return 0;
}


#line 667

static inline int
long_ctype_invert(npy_long a, npy_long *out)
{
    *out = ~a;
    return 0;
}


#line 667

static inline int
ulong_ctype_invert(npy_ulong a, npy_ulong *out)
{
    *out = ~a;
    return 0;
}


#line 667

static inline int
longlong_ctype_invert(npy_longlong a, npy_longlong *out)
{
    *out = ~a;
    return 0;
}


#line 667

static inline int
ulonglong_ctype_invert(npy_ulonglong a, npy_ulonglong *out)
{
    *out = ~a;
    return 0;
}



/*** END OF BASIC CODE **/


/*
 * How binary operators work
 * -------------------------
 *
 * All binary (numeric) operators use the larger of the two types, with the
 * exception of unsigned int and signed int mixed cases which must promote
 * to a larger type.
 *
 * The strategy employed for all binary operation is that we coerce the other
 * scalar if it is safe to do.  E.g. `float64 + float32` the `float64` can
 * convert `float32` and do the operation as `float64 + float64`.
 * OTOH, for `float32 + float64` it is safe, and we should defer to `float64`.
 *
 * So we have multiple possible paths:
 * - The other scalar is a subclass.  In principle *both* inputs could be
 *   different subclasses.  In this case it would make sense to defer, but
 *   Python's `int` does not try this as well, so we do not here:
 *
 *      class A(int): pass
 *      class B(int):
 *          def __add__(self, other): return "b"
 *          __radd__ = __add__
 *
 *      A(1) + B(1)  # return 2
 *      B(1) + A(1)  # return "b"
 *
 * - The other scalar can be converted:  All is good, we do the operation
 * - The other scalar cannot be converted, there are two possibilities:
 *   - The reverse should work, so we return NotImplemented to defer.
 *     (If self is a subclass, this will end up in the "unknown" path.)
 *   - Neither works (e.g. `uint8 + int8`):  We currently use the array path.
 * - The other object is a unknown.  It could be either a scalar, an array,
 *   or an array-like (including a list!).  Because NumPy scalars pretend to be
 *   arrays we fall into the array fallback path here _normally_ (through
 *   the generic scalar path).
 *   First we check if we should defer, though.
 *
 * The last possibility is awkward and leads to very confusing situations.
 * The problem is that usually we should defer (return NotImplemented)
 * in that path.
 * If the other object is a NumPy array (or array-like) it will know what to
 * do.  If NumPy knows that it is a scalar (not generic `object`), then it
 * would make sense to try and use the "array path" (i.e. deal with it
 * using the ufunc machinery).
 *
 * But this overlooks two things that currently work:
 *
 * 1. `np.float64(3) * [1, 2, 3]`  happily returns an array result.
 * 2. `np.int32(3) * decimal.Decimal(3)` works!  (see below)
 *
 * The first must work, because scalars pretend to be arrays.  Which means
 * they inherit the greedy "convert the other object to an array" logic.
 * This may be a questionable choice, but is fine.
 * (As of now, it is not negotiable, since NumPy often converts 0-D arrays
 * to scalars.)
 *
 * The second one is more confusing.  This works also by using the ufunc
 * machinery (array path), but it works because:
 *
 *     np.add(np.int32(3), decimal.Decimal(3))
 *
 * Will convert the `int32` to an int32 array, and the decimal to an object
 * array.  It then *casts* the `int32` array to an object array.
 * The casting step CONVERTS the integer to a Python integer.  The ufunc object
 * loop will then call back into Python scalar logic.
 *
 * The above would be recursive, if it was not for the conversion of the int32
 * to a Python integer!
 * This leads us to the EXCEEDINGLY IMPORTANT special case:
 *
 * WARNING: longdouble and clongdouble do NOT convert to a Python scalar
 *          when cast to object.  Thus they MUST NEVER take the array-path.
 *          However, they STILL should defer at least for
 *          `np.longdouble(3) + array`.
 *
 *
 * As a general note, in the above we defer exactly when we know that deferring
 * will work.  `longdouble` uses the "simple" logic of generally deferring
 * though, because it would otherwise easily run into an infinite recursion.
 *
 *
 * The future?!
 * ------------
 *
 * This is very tricky and it would be nice to formalize away that "recursive"
 * path we currently use.  I (seberg) have currently no great idea on this,
 * this is more brainstorming!
 *
 * If both are scalars (known to NumPy), they have a DType and we may be able
 * to do the ufunc promotion to make sure there is no risk of recursion.
 *
 * In principle always deferring would probably be clean.  But we likely cannot
 * do that?  There is also an issue that it is nice that we allow adding a
 * DType for an existing Python scalar (which will not know about NumPy
 * scalars).
 * The DType/ufunc machinery teaches NumPy how arrays will work with that
 * Python scalar, but the DType may need to help us decide whether we should
 * defer (return NotImplemented) or try using the ufunc machinery (or a
 * simplified ufunc-like machinery limited to scalars).
 */


/*
 * Enum used to describe the space of possibilities when converting the second
 * argument to a binary operation.
 * Any of these flags may be combined with the return flag of
 * `may_need_deferring` indicating that the other is any type of object which
 * may e.g. define an `__array_priority__`.
 */
typedef enum {
    /* An error occurred (should not really happen/be possible) */
    CONVERSION_ERROR = -1,
    /* A known NumPy scalar, but of higher precision: we defer */
    DEFER_TO_OTHER_KNOWN_SCALAR,
    /*
     * Conversion was successful (known scalar of less precision).  Note that
     * the other value may still be a subclass of such a scalar so even here
     * we may have to check for deferring.
     * More specialized subclass handling, which defers based on whether the
     * subclass has an implementation, plausible but complicated.
     * We do not do it, as even CPython does not do it for the builtin `int`.
     */
    CONVERSION_SUCCESS,
    /*
     * We use the normal conversion (setitem) function when coercing from
     * Python scalars.
     */
    CONVERT_PYSCALAR,
    /*
     * Other object is an unknown scalar or array-like, we (typically) use
     * the generic path, which normally ends up in the ufunc machinery.
     */
    OTHER_IS_UNKNOWN_OBJECT,
    /*
     * Promotion necessary
     */
    PROMOTION_REQUIRED,
} conversion_result;

#line 837

#define IS_BYTE 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_BYTE)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_BYTE, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_BYTE)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_BYTE, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_BYTE, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_byte(PyObject *value, npy_byte *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyByteArrType_Type) {
        *result = PyArrayScalar_VAL(value, Byte);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, Byte)) {
        *result = PyArrayScalar_VAL(value, Byte);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_BYTE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_BYTE) && !PyTypeNum_ISCOMPLEX(NPY_BYTE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_BYTE)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_BYTE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_BYTE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_BYTE)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_BYTE, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_BYTE


#line 837

#define IS_UBYTE 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_UBYTE)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_UBYTE, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_UBYTE)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_UBYTE, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_UBYTE, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_ubyte(PyObject *value, npy_ubyte *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyUByteArrType_Type) {
        *result = PyArrayScalar_VAL(value, UByte);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, UByte)) {
        *result = PyArrayScalar_VAL(value, UByte);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_UBYTE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_UBYTE) && !PyTypeNum_ISCOMPLEX(NPY_UBYTE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_UBYTE)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_UBYTE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_UBYTE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_UBYTE)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_UBYTE, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_UBYTE


#line 837

#define IS_SHORT 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_SHORT)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_SHORT, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_SHORT)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_SHORT, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_SHORT, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_short(PyObject *value, npy_short *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyShortArrType_Type) {
        *result = PyArrayScalar_VAL(value, Short);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, Short)) {
        *result = PyArrayScalar_VAL(value, Short);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_SHORT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_SHORT) && !PyTypeNum_ISCOMPLEX(NPY_SHORT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_SHORT)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_SHORT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_SHORT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_SHORT)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_SHORT, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_SHORT


#line 837

#define IS_USHORT 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_USHORT)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_USHORT, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_USHORT)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_USHORT, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_USHORT, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_ushort(PyObject *value, npy_ushort *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyUShortArrType_Type) {
        *result = PyArrayScalar_VAL(value, UShort);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, UShort)) {
        *result = PyArrayScalar_VAL(value, UShort);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_USHORT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_USHORT) && !PyTypeNum_ISCOMPLEX(NPY_USHORT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_USHORT)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_USHORT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_USHORT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_USHORT)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_USHORT, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_USHORT


#line 837

#define IS_INT 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_INT)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_INT, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_INT)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_INT, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_INT, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_int(PyObject *value, npy_int *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyIntArrType_Type) {
        *result = PyArrayScalar_VAL(value, Int);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, Int)) {
        *result = PyArrayScalar_VAL(value, Int);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_INT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_INT) && !PyTypeNum_ISCOMPLEX(NPY_INT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_INT)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_INT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_INT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_INT)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_INT, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_INT


#line 837

#define IS_UINT 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_UINT)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_UINT, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_UINT)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_UINT, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_UINT, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_uint(PyObject *value, npy_uint *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyUIntArrType_Type) {
        *result = PyArrayScalar_VAL(value, UInt);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, UInt)) {
        *result = PyArrayScalar_VAL(value, UInt);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_UINT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_UINT) && !PyTypeNum_ISCOMPLEX(NPY_UINT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_UINT)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_UINT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_UINT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_UINT)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_UINT, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_UINT


#line 837

#define IS_LONG 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_LONG)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_LONG, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_LONG)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_LONG, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_LONG, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_long(PyObject *value, npy_long *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyLongArrType_Type) {
        *result = PyArrayScalar_VAL(value, Long);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, Long)) {
        *result = PyArrayScalar_VAL(value, Long);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_LONG)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_LONG) && !PyTypeNum_ISCOMPLEX(NPY_LONG)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_LONG)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_LONG)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_LONG)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_LONG)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_LONG, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_LONG


#line 837

#define IS_ULONG 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_ULONG)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_ULONG, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_ULONG)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_ULONG, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_ULONG, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_ulong(PyObject *value, npy_ulong *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyULongArrType_Type) {
        *result = PyArrayScalar_VAL(value, ULong);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, ULong)) {
        *result = PyArrayScalar_VAL(value, ULong);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_ULONG)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_ULONG) && !PyTypeNum_ISCOMPLEX(NPY_ULONG)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_ULONG)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_ULONG)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_ULONG)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_ULONG)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_ULONG, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_ULONG


#line 837

#define IS_LONGLONG 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_LONGLONG)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_LONGLONG, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_LONGLONG)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_LONGLONG, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_LONGLONG, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_longlong(PyObject *value, npy_longlong *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyLongLongArrType_Type) {
        *result = PyArrayScalar_VAL(value, LongLong);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, LongLong)) {
        *result = PyArrayScalar_VAL(value, LongLong);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_LONGLONG)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_LONGLONG) && !PyTypeNum_ISCOMPLEX(NPY_LONGLONG)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_LONGLONG)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_LONGLONG)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_LONGLONG)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_LONGLONG)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_LONGLONG, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_LONGLONG


#line 837

#define IS_ULONGLONG 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_ULONGLONG)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_ULONGLONG, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_ULONGLONG)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_ULONGLONG, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_ULONGLONG, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_ulonglong(PyObject *value, npy_ulonglong *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyULongLongArrType_Type) {
        *result = PyArrayScalar_VAL(value, ULongLong);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, ULongLong)) {
        *result = PyArrayScalar_VAL(value, ULongLong);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_ULONGLONG)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_ULONGLONG) && !PyTypeNum_ISCOMPLEX(NPY_ULONGLONG)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_ULONGLONG)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_ULONGLONG)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_ULONGLONG)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_ULONGLONG)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_ULONGLONG, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_ULONGLONG


#line 837

#define IS_HALF 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_HALF)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_HALF, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_HALF)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_HALF, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_HALF, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_half(PyObject *value, npy_half *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyHalfArrType_Type) {
        *result = PyArrayScalar_VAL(value, Half);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, Half)) {
        *result = PyArrayScalar_VAL(value, Half);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_HALF)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_HALF) && !PyTypeNum_ISCOMPLEX(NPY_HALF)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_HALF)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_HALF)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_HALF)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_HALF)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_HALF, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_HALF


#line 837

#define IS_FLOAT 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_FLOAT)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_FLOAT, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_FLOAT)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_FLOAT, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_FLOAT, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_float(PyObject *value, npy_float *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyFloatArrType_Type) {
        *result = PyArrayScalar_VAL(value, Float);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, Float)) {
        *result = PyArrayScalar_VAL(value, Float);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_FLOAT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_FLOAT) && !PyTypeNum_ISCOMPLEX(NPY_FLOAT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_FLOAT)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_FLOAT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_FLOAT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_FLOAT)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_FLOAT, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_FLOAT


#line 837

#define IS_DOUBLE 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_DOUBLE)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_DOUBLE, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_DOUBLE)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_DOUBLE, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_DOUBLE, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_double(PyObject *value, npy_double *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyDoubleArrType_Type) {
        *result = PyArrayScalar_VAL(value, Double);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, Double)) {
        *result = PyArrayScalar_VAL(value, Double);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_DOUBLE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_DOUBLE) && !PyTypeNum_ISCOMPLEX(NPY_DOUBLE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_DOUBLE)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_DOUBLE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_DOUBLE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_DOUBLE)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_DOUBLE, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_DOUBLE


#line 837

#define IS_LONGDOUBLE 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_LONGDOUBLE)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_LONGDOUBLE, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_LONGDOUBLE)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_LONGDOUBLE, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_LONGDOUBLE, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_longdouble(PyObject *value, npy_longdouble *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyLongDoubleArrType_Type) {
        *result = PyArrayScalar_VAL(value, LongDouble);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, LongDouble)) {
        *result = PyArrayScalar_VAL(value, LongDouble);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_LONGDOUBLE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_LONGDOUBLE) && !PyTypeNum_ISCOMPLEX(NPY_LONGDOUBLE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_LONGDOUBLE)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_LONGDOUBLE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_LONGDOUBLE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_LONGDOUBLE)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_LONGDOUBLE, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_LONGDOUBLE


#line 837

#define IS_CFLOAT 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_CFLOAT)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_CFLOAT, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_CFLOAT)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_CFLOAT, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_CFLOAT, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_cfloat(PyObject *value, npy_cfloat *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyCFloatArrType_Type) {
        *result = PyArrayScalar_VAL(value, CFloat);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, CFloat)) {
        *result = PyArrayScalar_VAL(value, CFloat);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_CFLOAT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_CFLOAT) && !PyTypeNum_ISCOMPLEX(NPY_CFLOAT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_CFLOAT)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_CFLOAT)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_CFLOAT)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_CFLOAT)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_CFLOAT, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_CFLOAT


#line 837

#define IS_CDOUBLE 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_CDOUBLE)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_CDOUBLE, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_CDOUBLE)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_CDOUBLE, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_CDOUBLE, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_cdouble(PyObject *value, npy_cdouble *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyCDoubleArrType_Type) {
        *result = PyArrayScalar_VAL(value, CDouble);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, CDouble)) {
        *result = PyArrayScalar_VAL(value, CDouble);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_CDOUBLE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_CDOUBLE) && !PyTypeNum_ISCOMPLEX(NPY_CDOUBLE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_CDOUBLE)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_CDOUBLE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_CDOUBLE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_CDOUBLE)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_CDOUBLE, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_CDOUBLE


#line 837

#define IS_CLONGDOUBLE 1

#define IS_SAFE(FROM, TO) _npy_can_cast_safely_table[FROM][TO]

/*
 * TODO: This whole thing is awkward, and we should create a helper header to
 *       define inline functions that convert single elements for all numeric
 *       types.  That could then also be used to define all cast loops.
 *       (Even if that may get more complex for SIMD at some point.)
 *       For now, half casts could be optimized because of that.
 */

#if defined(IS_HALF)
    #define CONVERT_TO_RESULT(value)  \
        *result = npy_float_to_half((float)(value))
#elif defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
    #define CONVERT_TO_RESULT(value)  \
        result->real = value;  \
        result->imag = 0
#else
    #define CONVERT_TO_RESULT(value) *result = value
#endif


#define GET_VALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_CLONGDOUBLE)) {  \
            CONVERT_TO_RESULT(PyArrayScalar_VAL(value, Other));  \
            ret = CONVERSION_SUCCESS;  \
        }  \
        else if (IS_SAFE(NPY_CLONGDOUBLE, NPY_##OTHER)) {  \
            /*
             * If self can cast safely to other, this is clear:
             * we should definitely defer.
             */  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            /* Otherwise, we must promote */  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

/*
 * Complex to complex (and rejecting complex to real) is a bit different:
 */

#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)

#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_##OTHER, NPY_CLONGDOUBLE)) {  \
            assert(Py_TYPE(value) == &Py##Other##ArrType_Type);  \
            result->real = PyArrayScalar_VAL(value, Other).real;  \
            result->imag = PyArrayScalar_VAL(value, Other).imag;  \
            ret = 1;  \
        }  \
        else if (IS_SAFE(NPY_CLONGDOUBLE, NPY_##OTHER)) {  \
             ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#else

/* Getting a complex value to real is never safe: */
#define GET_CVALUE_OR_DEFER(OTHER, Other, value)  \
    case NPY_##OTHER:  \
        if (IS_SAFE(NPY_CLONGDOUBLE, NPY_##OTHER)) {  \
            ret = DEFER_TO_OTHER_KNOWN_SCALAR;  \
        }  \
        else {  \
            ret = PROMOTION_REQUIRED;  \
        }  \
        break;

#endif


/**
 * Convert the value to the own type and and store the result.
 *
 * @param value The value to convert (if compatible)
 * @param result The result value (output)
 * @param may_need_deferring Set to `NPY_TRUE` when the caller must check
 *        `BINOP_GIVE_UP_IF_NEEDED` (or similar) due to possible implementation
 *        of `__array_priority__` (or similar).
 *        This is set for unknown objects and all subclasses even when they
 *        can be handled.
 * @result The result value indicating what we did with `value` or what type
 *         of object it is (see `conversion_result`).
 */
static inline conversion_result
convert_to_clongdouble(PyObject *value, npy_clongdouble *result, npy_bool *may_need_deferring)
{
    PyArray_Descr *descr;
    *may_need_deferring = NPY_FALSE;

    if (Py_TYPE(value) == &PyCLongDoubleArrType_Type) {
        *result = PyArrayScalar_VAL(value, CLongDouble);
        return CONVERSION_SUCCESS;
    }
    /* Optimize the identical scalar specifically. */
    if (PyArray_IsScalar(value, CLongDouble)) {
        *result = PyArrayScalar_VAL(value, CLongDouble);
        /*
         * In principle special, assyemetric, handling could be possible for
         * explicit subclasses.
         * In practice, we just check the normal deferring logic.
         */
        *may_need_deferring = NPY_TRUE;
        return CONVERSION_SUCCESS;
    }

    /*
     * Then we check for the basic Python types float, int, and complex.
     * (this is a bit tedious to do right for complex).
     */
    if (PyBool_Check(value)) {
        CONVERT_TO_RESULT(value == Py_True);
        return CONVERSION_SUCCESS;
    }

    if (PyFloat_Check(value)) {
        if (!PyFloat_CheckExact(value)) {
            /* A NumPy double is a float subclass, but special. */
            if (PyArray_IsScalar(value, Double)) {
                descr = PyArray_DescrFromType(NPY_DOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_DOUBLE, NPY_CLONGDOUBLE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISFLOAT(NPY_CLONGDOUBLE) && !PyTypeNum_ISCOMPLEX(NPY_CLONGDOUBLE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        CONVERT_TO_RESULT(PyFloat_AS_DOUBLE(value));
        return CONVERSION_SUCCESS;
    }

    if (PyLong_Check(value)) {
        if (!PyLong_CheckExact(value)) {
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_LONG, NPY_CLONGDOUBLE)) {
            /*
             * long -> (c)longdouble is safe, so `OTHER_IS_UNKNOWN_OBJECT` will
             * be returned below for huge integers.
             */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
        int overflow;
        long val = PyLong_AsLongAndOverflow(value, &overflow);
        if (overflow) {
            /* handle as if "unsafe" */
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                return OTHER_IS_UNKNOWN_OBJECT;
            }
            return CONVERT_PYSCALAR;
        }
        if (error_converting(val)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        CONVERT_TO_RESULT(val);
        return CONVERSION_SUCCESS;
    }

    if (PyComplex_Check(value)) {
        if (!PyComplex_CheckExact(value)) {
            /* A NumPy complex double is a float subclass, but special. */
            if (PyArray_IsScalar(value, CDouble)) {
                descr = PyArray_DescrFromType(NPY_CDOUBLE);
                goto numpy_scalar;
            }
            *may_need_deferring = NPY_TRUE;
        }
        if (!IS_SAFE(NPY_CDOUBLE, NPY_CLONGDOUBLE)) {
            if (npy_promotion_state != NPY_USE_WEAK_PROMOTION) {
                /* Legacy promotion and weak-and-warn not handled here */
                return PROMOTION_REQUIRED;
            }
            /* Weak promotion is used when self is float or complex: */
            if (!PyTypeNum_ISCOMPLEX(NPY_CLONGDOUBLE)) {
                return PROMOTION_REQUIRED;
            }
            return CONVERT_PYSCALAR;
        }
#if defined(IS_CFLOAT) || defined(IS_CDOUBLE) || defined(IS_CLONGDOUBLE)
        Py_complex val = PyComplex_AsCComplex(value);
        if (error_converting(val.real)) {
            return CONVERSION_ERROR;  /* should not be possible */
        }
        result->real = val.real;
        result->imag = val.imag;
        return CONVERSION_SUCCESS;
#else
        /* unreachable, always unsafe cast above; return to avoid warning */
        assert(0);
        return OTHER_IS_UNKNOWN_OBJECT;
#endif  /* defined(IS_CFLOAT) || ... */
    }

    /*
     * (seberg) It would be nice to use `PyArray_DiscoverDTypeFromScalarType`
     * from array coercion here.  OTOH, the array coercion code also falls
     * back to this code.  The issue is around how subclasses should work...
     *
     * It would be nice to try to fully align the paths again (they effectively
     * are equivalent).  Proper support for subclasses is in general tricky,
     * and it would make more sense to just _refuse_ to support them.
     * However, it is unclear that this is a viable option...
     */
    if (!PyArray_IsScalar(value, Generic)) {
        /*
         * The input is an unknown python object.  This should probably defer
         * but only does so for float128.
         * For all other cases, we defer to the array logic.  If the object
         * is indeed not an array-like, this will end up converting the NumPy
         * scalar to a Python scalar and then try again.
         * The logic is that the ufunc casts the input to object, which does
         * the conversion.
         * If the object is an array, deferring will always kick in.
         */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

    descr = PyArray_DescrFromScalar(value);
    if (descr == NULL) {
        if (PyErr_Occurred()) {
            return CONVERSION_ERROR;
        }
        /* Should not happen, but may be possible with bad user subclasses */
        *may_need_deferring = NPY_TRUE;
        return OTHER_IS_UNKNOWN_OBJECT;
    }

  numpy_scalar:
    if (descr->typeobj != Py_TYPE(value)) {
        /*
         * This is a subclass of a builtin type, we may continue normally,
         * but should check whether we need to defer.
         */
        *may_need_deferring = NPY_TRUE;
    }

    /*
     * Otherwise, we have a clear NumPy scalar, find if it is a compatible
     * builtin scalar.
     * Each `GET_VALUE_OR_DEFER` represents a case clause for its type number,
     * extracting the value if it is safe and otherwise deferring.
     * (Safety is known at compile time, so the switch statement should be
     * simplified by the compiler accordingly.)
     * If we have a scalar that is not listed or not safe, we defer to it.
     *
     * We should probably defer more aggressively, but that is too big a change,
     * since it would disable `np.float64(1.) * [1, 2, 3, 4]`.
     */
    int ret;  /* set by the GET_VALUE_OR_DEFER macro */
    switch (descr->type_num) {
        GET_VALUE_OR_DEFER(BOOL, Bool, value);
        /* UInts */
        GET_VALUE_OR_DEFER(UBYTE, UByte, value);
        GET_VALUE_OR_DEFER(USHORT, UShort, value);
        GET_VALUE_OR_DEFER(UINT, UInt, value);
        GET_VALUE_OR_DEFER(ULONG, ULong, value);
        GET_VALUE_OR_DEFER(ULONGLONG, ULongLong, value);
        /* Ints */
        GET_VALUE_OR_DEFER(BYTE, Byte, value);
        GET_VALUE_OR_DEFER(SHORT, Short, value);
        GET_VALUE_OR_DEFER(INT, Int, value);
        GET_VALUE_OR_DEFER(LONG, Long, value);
        GET_VALUE_OR_DEFER(LONGLONG, LongLong, value);
        /* Floats */
        case NPY_HALF:
            if (IS_SAFE(NPY_HALF, NPY_CLONGDOUBLE)) {
                CONVERT_TO_RESULT(npy_half_to_float(PyArrayScalar_VAL(value, Half)));
                ret = CONVERSION_SUCCESS;
            }
            else if (IS_SAFE(NPY_CLONGDOUBLE, NPY_HALF)) {
                ret = DEFER_TO_OTHER_KNOWN_SCALAR;
            }
            else {
                ret = PROMOTION_REQUIRED;
            }
            break;
        GET_VALUE_OR_DEFER(FLOAT, Float, value);
        GET_VALUE_OR_DEFER(DOUBLE, Double, value);
        GET_VALUE_OR_DEFER(LONGDOUBLE, LongDouble, value);
        /* Complex: We should still defer, but the code won't work... */
        GET_CVALUE_OR_DEFER(CFLOAT, CFloat, value);
        GET_CVALUE_OR_DEFER(CDOUBLE, CDouble, value);
        GET_CVALUE_OR_DEFER(CLONGDOUBLE, CLongDouble, value);
        default:
            /*
             * If there is no match, this is an unknown scalar object.  It
             * would make sense to defer generously here, but it should also
             * always be safe to use the array path.
             * The issue is, that the other scalar may or may not be designed
             * to deal with NumPy scalars.  Without knowing that, we cannot
             * defer (which would be much faster potentially).
             * TODO: We could add a DType flag to allow opting in to deferring!
             */
            *may_need_deferring = NPY_TRUE;
            ret = OTHER_IS_UNKNOWN_OBJECT;
    }
    Py_DECREF(descr);
    return ret;
}

#undef IS_SAFE
#undef CONVERT_TO_RESULT
#undef GET_VALUE_OR_DEFER
#undef GET_CVALUE_OR_DEFER
#undef IS_CLONGDOUBLE




#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
byte_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, byte_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
ubyte_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, ubyte_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
short_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, short_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
ushort_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, ushort_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
int_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, int_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
uint_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, uint_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
long_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, long_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
ulong_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, ulong_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
longlong_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, longlong_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
ulonglong_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, ulonglong_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_add(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
byte_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, byte_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
ubyte_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, ubyte_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
short_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, short_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
ushort_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, ushort_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
int_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, int_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
uint_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, uint_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
long_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, long_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
ulong_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, ulong_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
longlong_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, longlong_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
ulonglong_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, ulonglong_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_subtract(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
byte_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, byte_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
ubyte_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, ubyte_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
short_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, short_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
ushort_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, ushort_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
int_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, int_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
uint_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, uint_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
long_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, long_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
ulong_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, ulong_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
longlong_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, longlong_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
ulonglong_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, ulonglong_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_multiply(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
byte_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, byte_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
ubyte_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, ubyte_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
short_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, short_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
ushort_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, ushort_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
int_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, int_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
uint_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, uint_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
long_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, long_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
ulong_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, ulong_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
longlong_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, longlong_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
ulonglong_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, ulonglong_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_remainder(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
byte_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, byte_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 1
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = byte_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
ubyte_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, ubyte_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 1
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = ubyte_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
short_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, short_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 1
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = short_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
ushort_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, ushort_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 1
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = ushort_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
int_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, int_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 1
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = int_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
uint_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, uint_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 1
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = uint_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
long_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, long_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 1
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = long_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
ulong_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, ulong_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 1
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = ulong_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
longlong_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, longlong_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 1
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = longlong_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
ulonglong_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, ulonglong_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 1
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = ulonglong_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_divmod(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
byte_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, byte_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
ubyte_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, ubyte_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
short_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, short_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
ushort_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, ushort_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
int_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, int_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
uint_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, uint_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
long_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, long_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
ulong_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, ulong_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
longlong_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, longlong_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
ulonglong_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, ulonglong_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
byte_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, byte_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
ubyte_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, ubyte_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
short_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, short_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
ushort_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, ushort_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
int_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, int_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
uint_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, uint_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
long_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, long_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
ulong_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, ulong_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
longlong_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, longlong_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_lshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "lshift"
#endif

static PyObject *
ulonglong_lshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_lshift, ulonglong_lshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_lshift(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_lshift(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_lshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_lshift
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
byte_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, byte_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
ubyte_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, ubyte_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
short_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, short_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
ushort_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, ushort_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
int_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, int_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
uint_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, uint_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
long_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, long_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
ulong_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, ulong_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
longlong_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, longlong_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_rshift
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "rshift"
#endif

static PyObject *
ulonglong_rshift(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_rshift, ulonglong_rshift);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_rshift(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_rshift(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_rshift(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_rshift
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
byte_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, byte_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
ubyte_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, ubyte_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
short_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, short_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
ushort_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, ushort_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
int_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, int_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
uint_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, uint_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
long_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, long_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
ulong_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, ulong_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
longlong_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, longlong_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_and
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "and"
#endif

static PyObject *
ulonglong_and(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_and, ulonglong_and);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_and(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_and(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_and(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_and
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
byte_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, byte_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
ubyte_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, ubyte_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
short_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, short_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
ushort_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, ushort_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
int_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, int_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
uint_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, uint_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
long_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, long_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
ulong_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, ulong_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
longlong_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, longlong_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_or
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "or"
#endif

static PyObject *
ulonglong_or(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_or, ulonglong_or);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_or(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_or(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_or(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_or
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
byte_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, byte_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_byte out;
#if 0
    npy_byte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Byte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Byte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
ubyte_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, ubyte_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ubyte out;
#if 0
    npy_ubyte out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UByte);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UByte, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
short_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, short_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_short out;
#if 0
    npy_short out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Short);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Short, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
ushort_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, ushort_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ushort out;
#if 0
    npy_ushort out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UShort);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UShort, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
int_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, int_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_int out;
#if 0
    npy_int out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Int);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Int, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
uint_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, uint_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_uint out;
#if 0
    npy_uint out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(UInt);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, UInt, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
long_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, long_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_long out;
#if 0
    npy_long out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Long);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Long, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
ulong_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, ulong_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulong out;
#if 0
    npy_ulong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
longlong_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, longlong_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longlong out;
#if 0
    npy_longlong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_xor
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "xor"
#endif

static PyObject *
ulonglong_xor(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_xor, ulonglong_xor);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_xor(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_ulonglong out;
#if 0
    npy_ulonglong out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_xor(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_xor(arg1, arg2, &out);
#endif

#if 0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(ULongLong);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, ULongLong, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_xor
#undef IS_ulonglong


#line 1217
#define IS_byte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
byte_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_byte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, byte_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = byte_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = byte_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_byte


#line 1217
#define IS_ubyte
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
ubyte_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ubyte(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, ubyte_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ubyte_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = ubyte_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_ubyte


#line 1217
#define IS_short
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
short_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_short arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_short(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, short_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = short_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = short_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_short


#line 1217
#define IS_ushort
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
ushort_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ushort(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, ushort_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ushort_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = ushort_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_ushort


#line 1217
#define IS_int
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
int_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_int arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_int(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, int_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = int_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = int_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_int


#line 1217
#define IS_uint
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
uint_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_uint(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, uint_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = uint_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = uint_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_uint


#line 1217
#define IS_long
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
long_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_long arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_long(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, long_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = long_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = long_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_long


#line 1217
#define IS_ulong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
ulong_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, ulong_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulong_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = ulong_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_ulong


#line 1217
#define IS_longlong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
longlong_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longlong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, longlong_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longlong_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = longlong_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_longlong


#line 1217
#define IS_ulonglong
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
ulonglong_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_ulonglong(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, ulonglong_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = ulonglong_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = ulonglong_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_ulonglong


#line 1217
#define IS_half
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
half_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_half arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyHalfArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyHalfArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Half);
        assert(is_forward || PyArray_IsScalar(b, Half));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_half(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, half_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (HALF_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Half);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Half);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_half out;
#if 0
    npy_half out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = half_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = half_ctype_add(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Half);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Half, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_half


#line 1217
#define IS_float
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
float_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_float arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Float);
        assert(is_forward || PyArray_IsScalar(b, Float));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_float(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, float_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (FLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Float);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Float);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_float out;
#if 0
    npy_float out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = float_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = float_ctype_add(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Float);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Float, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_float


#line 1217
#define IS_double
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
double_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_double arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Double);
        assert(is_forward || PyArray_IsScalar(b, Double));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_double(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, double_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (DOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Double);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Double);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = double_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = double_ctype_add(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_double


#line 1217
#define IS_longdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
longdouble_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongDouble);
        assert(is_forward || PyArray_IsScalar(b, LongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, longdouble_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (LONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longdouble out;
#if 0
    npy_longdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longdouble_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = longdouble_ctype_add(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_longdouble


#line 1217
#define IS_cfloat
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
cfloat_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_cfloat arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CFloat);
        assert(is_forward || PyArray_IsScalar(b, CFloat));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_cfloat(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, cfloat_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (CFLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CFloat);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CFloat);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_cfloat out;
#if 0
    npy_cfloat out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = cfloat_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = cfloat_ctype_add(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CFloat);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CFloat, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CFloat);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CFloat, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CFloat);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CFloat, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_cfloat


#line 1217
#define IS_cdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
cdouble_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_cdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CDouble);
        assert(is_forward || PyArray_IsScalar(b, CDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_cdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, cdouble_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (CDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_cdouble out;
#if 0
    npy_cdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = cdouble_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = cdouble_ctype_add(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_cdouble


#line 1217
#define IS_clongdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_add
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "add"
#endif

static PyObject *
clongdouble_add(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_clongdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CLongDouble);
        assert(is_forward || PyArray_IsScalar(b, CLongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_clongdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_add, clongdouble_add);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_add(a,b);
        case CONVERT_PYSCALAR:
            if (CLONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CLongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CLongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_clongdouble out;
#if 0
    npy_clongdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = clongdouble_ctype_add(arg1, arg2, &out, &out2);
#else
    int retstatus = clongdouble_ctype_add(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CLongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CLongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CLongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CLongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CLongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CLongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_add
#undef IS_clongdouble


#line 1217
#define IS_half
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
half_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_half arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyHalfArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyHalfArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Half);
        assert(is_forward || PyArray_IsScalar(b, Half));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_half(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, half_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (HALF_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Half);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Half);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_half out;
#if 0
    npy_half out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = half_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = half_ctype_subtract(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Half);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Half, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_half


#line 1217
#define IS_float
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
float_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_float arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Float);
        assert(is_forward || PyArray_IsScalar(b, Float));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_float(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, float_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (FLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Float);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Float);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_float out;
#if 0
    npy_float out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = float_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = float_ctype_subtract(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Float);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Float, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_float


#line 1217
#define IS_double
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
double_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_double arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Double);
        assert(is_forward || PyArray_IsScalar(b, Double));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_double(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, double_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (DOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Double);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Double);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = double_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = double_ctype_subtract(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_double


#line 1217
#define IS_longdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
longdouble_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongDouble);
        assert(is_forward || PyArray_IsScalar(b, LongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, longdouble_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (LONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longdouble out;
#if 0
    npy_longdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longdouble_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = longdouble_ctype_subtract(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_longdouble


#line 1217
#define IS_cfloat
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
cfloat_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_cfloat arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CFloat);
        assert(is_forward || PyArray_IsScalar(b, CFloat));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_cfloat(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, cfloat_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (CFLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CFloat);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CFloat);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_cfloat out;
#if 0
    npy_cfloat out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = cfloat_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = cfloat_ctype_subtract(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CFloat);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CFloat, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CFloat);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CFloat, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CFloat);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CFloat, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_cfloat


#line 1217
#define IS_cdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
cdouble_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_cdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CDouble);
        assert(is_forward || PyArray_IsScalar(b, CDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_cdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, cdouble_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (CDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_cdouble out;
#if 0
    npy_cdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = cdouble_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = cdouble_ctype_subtract(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_cdouble


#line 1217
#define IS_clongdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_subtract
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "subtract"
#endif

static PyObject *
clongdouble_subtract(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_clongdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CLongDouble);
        assert(is_forward || PyArray_IsScalar(b, CLongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_clongdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_subtract, clongdouble_subtract);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_subtract(a,b);
        case CONVERT_PYSCALAR:
            if (CLONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CLongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CLongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_clongdouble out;
#if 0
    npy_clongdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = clongdouble_ctype_subtract(arg1, arg2, &out, &out2);
#else
    int retstatus = clongdouble_ctype_subtract(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CLongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CLongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CLongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CLongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CLongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CLongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_subtract
#undef IS_clongdouble


#line 1217
#define IS_half
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
half_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_half arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyHalfArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyHalfArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Half);
        assert(is_forward || PyArray_IsScalar(b, Half));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_half(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, half_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (HALF_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Half);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Half);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_half out;
#if 0
    npy_half out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = half_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = half_ctype_multiply(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Half);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Half, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_half


#line 1217
#define IS_float
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
float_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_float arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Float);
        assert(is_forward || PyArray_IsScalar(b, Float));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_float(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, float_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (FLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Float);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Float);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_float out;
#if 0
    npy_float out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = float_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = float_ctype_multiply(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Float);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Float, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_float


#line 1217
#define IS_double
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
double_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_double arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Double);
        assert(is_forward || PyArray_IsScalar(b, Double));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_double(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, double_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (DOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Double);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Double);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = double_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = double_ctype_multiply(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_double


#line 1217
#define IS_longdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
longdouble_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongDouble);
        assert(is_forward || PyArray_IsScalar(b, LongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, longdouble_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (LONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longdouble out;
#if 0
    npy_longdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longdouble_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = longdouble_ctype_multiply(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_longdouble


#line 1217
#define IS_cfloat
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
cfloat_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_cfloat arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CFloat);
        assert(is_forward || PyArray_IsScalar(b, CFloat));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_cfloat(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, cfloat_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (CFLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CFloat);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CFloat);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_cfloat out;
#if 0
    npy_cfloat out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = cfloat_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = cfloat_ctype_multiply(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CFloat);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CFloat, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CFloat);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CFloat, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CFloat);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CFloat, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_cfloat


#line 1217
#define IS_cdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
cdouble_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_cdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CDouble);
        assert(is_forward || PyArray_IsScalar(b, CDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_cdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, cdouble_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (CDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_cdouble out;
#if 0
    npy_cdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = cdouble_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = cdouble_ctype_multiply(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_cdouble


#line 1217
#define IS_clongdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_multiply
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "multiply"
#endif

static PyObject *
clongdouble_multiply(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_clongdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CLongDouble);
        assert(is_forward || PyArray_IsScalar(b, CLongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_clongdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_multiply, clongdouble_multiply);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_multiply(a,b);
        case CONVERT_PYSCALAR:
            if (CLONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CLongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CLongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_clongdouble out;
#if 0
    npy_clongdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = clongdouble_ctype_multiply(arg1, arg2, &out, &out2);
#else
    int retstatus = clongdouble_ctype_multiply(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CLongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CLongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CLongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CLongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CLongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CLongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_multiply
#undef IS_clongdouble


#line 1217
#define IS_half
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
half_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_half arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyHalfArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyHalfArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Half);
        assert(is_forward || PyArray_IsScalar(b, Half));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_half(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, half_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (HALF_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Half);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Half);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_half out;
#if 0
    npy_half out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = half_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = half_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Half);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Half, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_half


#line 1217
#define IS_float
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
float_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_float arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Float);
        assert(is_forward || PyArray_IsScalar(b, Float));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_float(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, float_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (FLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Float);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Float);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_float out;
#if 0
    npy_float out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = float_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = float_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Float);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Float, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_float


#line 1217
#define IS_double
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
double_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_double arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Double);
        assert(is_forward || PyArray_IsScalar(b, Double));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_double(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, double_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (DOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Double);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Double);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = double_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = double_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_double


#line 1217
#define IS_longdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
longdouble_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongDouble);
        assert(is_forward || PyArray_IsScalar(b, LongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, longdouble_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (LONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longdouble out;
#if 0
    npy_longdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longdouble_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = longdouble_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_longdouble


#line 1217
#define IS_cfloat
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
cfloat_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_cfloat arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CFloat);
        assert(is_forward || PyArray_IsScalar(b, CFloat));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_cfloat(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, cfloat_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (CFLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CFloat);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CFloat);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_cfloat out;
#if 0
    npy_cfloat out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = cfloat_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = cfloat_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CFloat);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CFloat, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CFloat);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CFloat, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CFloat);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CFloat, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_cfloat


#line 1217
#define IS_cdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
cdouble_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_cdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CDouble);
        assert(is_forward || PyArray_IsScalar(b, CDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_cdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, cdouble_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (CDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_cdouble out;
#if 0
    npy_cdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = cdouble_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = cdouble_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_cdouble


#line 1217
#define IS_clongdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_true_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "true_divide"
#endif

static PyObject *
clongdouble_true_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_clongdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyCLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CLongDouble);
        assert(is_forward || PyArray_IsScalar(b, CLongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_clongdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_true_divide, clongdouble_true_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_true_divide(a,b);
        case CONVERT_PYSCALAR:
            if (CLONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CLongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CLongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_clongdouble out;
#if 0
    npy_clongdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = clongdouble_ctype_true_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = clongdouble_ctype_true_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(CLongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CLongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(CLongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, CLongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(CLongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CLongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_true_divide
#undef IS_clongdouble


#line 1217
#define IS_half
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
half_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_half arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyHalfArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyHalfArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Half);
        assert(is_forward || PyArray_IsScalar(b, Half));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_half(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, half_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (HALF_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Half);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Half);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_half out;
#if 0
    npy_half out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = half_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = half_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Half);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Half, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_half


#line 1217
#define IS_float
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
float_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_float arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Float);
        assert(is_forward || PyArray_IsScalar(b, Float));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_float(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, float_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (FLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Float);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Float);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_float out;
#if 0
    npy_float out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = float_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = float_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Float);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Float, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_float


#line 1217
#define IS_double
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
double_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_double arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Double);
        assert(is_forward || PyArray_IsScalar(b, Double));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_double(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, double_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (DOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Double);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Double);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = double_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = double_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_double


#line 1217
#define IS_longdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_floor_divide
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "floor_divide"
#endif

static PyObject *
longdouble_floor_divide(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongDouble);
        assert(is_forward || PyArray_IsScalar(b, LongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_floor_divide, longdouble_floor_divide);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_floor_divide(a,b);
        case CONVERT_PYSCALAR:
            if (LONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longdouble out;
#if 0
    npy_longdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longdouble_ctype_floor_divide(arg1, arg2, &out, &out2);
#else
    int retstatus = longdouble_ctype_floor_divide(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_floor_divide
#undef IS_longdouble


#line 1217
#define IS_half
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
half_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_half arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyHalfArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyHalfArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Half);
        assert(is_forward || PyArray_IsScalar(b, Half));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_half(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, half_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (HALF_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Half);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Half);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_half out;
#if 1
    npy_half out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = half_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = half_ctype_divmod(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Half);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Half, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_half


#line 1217
#define IS_float
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
float_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_float arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Float);
        assert(is_forward || PyArray_IsScalar(b, Float));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_float(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, float_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (FLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Float);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Float);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_float out;
#if 1
    npy_float out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = float_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = float_ctype_divmod(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Float);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Float, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_float


#line 1217
#define IS_double
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
double_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_double arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Double);
        assert(is_forward || PyArray_IsScalar(b, Double));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_double(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, double_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (DOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Double);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Double);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 1
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = double_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = double_ctype_divmod(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_double


#line 1217
#define IS_longdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_divmod
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "divmod"
#endif

static PyObject *
longdouble_divmod(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongDouble);
        assert(is_forward || PyArray_IsScalar(b, LongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_divmod, longdouble_divmod);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_divmod(a,b);
        case CONVERT_PYSCALAR:
            if (LONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longdouble out;
#if 1
    npy_longdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 1
    int retstatus = longdouble_ctype_divmod(arg1, arg2, &out, &out2);
#else
    int retstatus = longdouble_ctype_divmod(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 1
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_divmod
#undef IS_longdouble


#line 1217
#define IS_half
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
half_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_half arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyHalfArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyHalfArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Half);
        assert(is_forward || PyArray_IsScalar(b, Half));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_half(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, half_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (HALF_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Half);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Half);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_half out;
#if 0
    npy_half out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = half_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = half_ctype_remainder(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Half);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Half, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Half);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Half, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_half


#line 1217
#define IS_float
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
float_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_float arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Float);
        assert(is_forward || PyArray_IsScalar(b, Float));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_float(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, float_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (FLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Float);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Float);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_float out;
#if 0
    npy_float out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = float_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = float_ctype_remainder(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Float);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Float, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Float);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Float, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_float


#line 1217
#define IS_double
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
double_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_double arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Double);
        assert(is_forward || PyArray_IsScalar(b, Double));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_double(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, double_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (DOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Double);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Double);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_double out;
#if 0
    npy_double out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = double_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = double_ctype_remainder(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(Double);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, Double, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_double


#line 1217
#define IS_longdouble
/* drop the "true_" from "true_divide" for floating point warnings: */
#define IS_remainder
#ifdef IS_true_divide
    #define OP_NAME "divide"
#else
    #define OP_NAME "remainder"
#endif

static PyObject *
longdouble_remainder(PyObject *a, PyObject *b)
{
    PyObject *ret;
    npy_longdouble arg1, arg2, other_val;

    /*
     * Check if this operation may be considered forward.  Note `is_forward`
     * does not imply that we can defer to a subclass `b`.  It just means that
     * the first operand fits to the method.
     */
    int is_forward;
    if (Py_TYPE(a) == &PyLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongDouble);
        assert(is_forward || PyArray_IsScalar(b, LongDouble));
    }

    /*
     * Extract the other value (if it is compatible).  Otherwise, decide
     * how to deal with it.  This is somewhat complicated.
     *
     * Note: This pattern is used multiple times below.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    conversion_result res = convert_to_longdouble(
            other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_remainder, longdouble_remainder);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            /*
             * defer to other;  This is normally a forward operation.  However,
             * it could be backward if an operation is undefined forward.
             * An example is the complex remainder `complex % bool` will defer
             * even though it would normally handle the operation.
             */
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
            /*
             * Either an array-like, unknown scalar (any Python object, but
             * also integers that are too large to convert to `long`), or
             * even a subclass of a NumPy scalar (currently).
             *
             * Generally, we try dropping through to the array path here,
             * but this can lead to infinite recursions for (c)longdouble.
             */
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            /*
             * Python scalar that is larger than the current one, or two
             * NumPy scalars that promote to a third (uint16 + int16 -> int32).
             *
             * TODO: We could special case the promotion case here for much
             *       better speed and to deal with integer overflow warnings
             *       correctly.  (e.g. `uint8 * int8` cannot warn).
             */
            return PyGenericArrType_Type.tp_as_number->nb_remainder(a,b);
        case CONVERT_PYSCALAR:
            if (LONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if 1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif
    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongDouble);
    }

    /*
     * Prepare the actual calculation.
     */
    npy_longdouble out;
#if 0
    npy_longdouble out2;
    PyObject *obj;
#endif

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     * Note that `retstatus` is the "floating point error" value for integer
     * functions.  Float functions should always return 0, and then use
     * the following `npy_get_floatstatus_barrier`.
     */
#if 0
    int retstatus = longdouble_ctype_remainder(arg1, arg2, &out, &out2);
#else
    int retstatus = longdouble_ctype_remainder(arg1, arg2, &out);
#endif

#if 1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar " OP_NAME, retstatus) < 0) {
            return NULL;
        }
    }


#if 0
    ret = PyTuple_New(2);
    if (ret == NULL) {
        return NULL;
    }
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out);
    PyTuple_SET_ITEM(ret, 0, obj);
    obj = PyArrayScalar_New(LongDouble);
    if (obj == NULL) {
        Py_DECREF(ret);
        return NULL;
    }
    PyArrayScalar_ASSIGN(obj, LongDouble, out2);
    PyTuple_SET_ITEM(ret, 1, obj);
#else
    ret = PyArrayScalar_New(LongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongDouble, out);
#endif
    return ret;
}


#undef OP_NAME
#undef IS_remainder
#undef IS_longdouble



#define _IS_ZERO(x) (x == 0)

#line 1421
#define IS_byte

static PyObject *
byte_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_byte arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Byte);
        assert(is_forward || PyArray_IsScalar(b, Byte));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_byte(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, byte_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Byte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Byte);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_byte out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = byte_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(Byte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Byte, out);

    return ret;
}


#undef IS_byte

#line 1421
#define IS_ubyte

static PyObject *
ubyte_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_ubyte arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyUByteArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUByteArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UByte);
        assert(is_forward || PyArray_IsScalar(b, UByte));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_ubyte(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, ubyte_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UByte);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UByte);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_ubyte out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !1
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = ubyte_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(UByte);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UByte, out);

    return ret;
}


#undef IS_ubyte

#line 1421
#define IS_short

static PyObject *
short_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_short arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Short);
        assert(is_forward || PyArray_IsScalar(b, Short));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_short(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, short_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Short);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Short);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_short out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = short_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(Short);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Short, out);

    return ret;
}


#undef IS_short

#line 1421
#define IS_ushort

static PyObject *
ushort_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_ushort arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyUShortArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUShortArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UShort);
        assert(is_forward || PyArray_IsScalar(b, UShort));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_ushort(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, ushort_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UShort);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UShort);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_ushort out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !1
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = ushort_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(UShort);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UShort, out);

    return ret;
}


#undef IS_ushort

#line 1421
#define IS_int

static PyObject *
int_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_int arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Int);
        assert(is_forward || PyArray_IsScalar(b, Int));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_int(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, int_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Int);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Int);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_int out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = int_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(Int);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Int, out);

    return ret;
}


#undef IS_int

#line 1421
#define IS_uint

static PyObject *
uint_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_uint arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyUIntArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyUIntArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, UInt);
        assert(is_forward || PyArray_IsScalar(b, UInt));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_uint(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, uint_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, UInt);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, UInt);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_uint out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !1
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = uint_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(UInt);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, UInt, out);

    return ret;
}


#undef IS_uint

#line 1421
#define IS_long

static PyObject *
long_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_long arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Long);
        assert(is_forward || PyArray_IsScalar(b, Long));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_long(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, long_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Long);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Long);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_long out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = long_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(Long);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Long, out);

    return ret;
}


#undef IS_long

#line 1421
#define IS_ulong

static PyObject *
ulong_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_ulong arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyULongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULong);
        assert(is_forward || PyArray_IsScalar(b, ULong));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_ulong(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, ulong_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULong);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_ulong out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !1
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = ulong_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(ULong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULong, out);

    return ret;
}


#undef IS_ulong

#line 1421
#define IS_longlong

static PyObject *
longlong_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_longlong arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyLongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongLong);
        assert(is_forward || PyArray_IsScalar(b, LongLong));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_longlong(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, longlong_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongLong);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_longlong out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = longlong_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(LongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongLong, out);

    return ret;
}


#undef IS_longlong

#line 1421
#define IS_ulonglong

static PyObject *
ulonglong_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_ulonglong arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyULongLongArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyULongLongArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, ULongLong);
        assert(is_forward || PyArray_IsScalar(b, ULongLong));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_ulonglong(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, ulonglong_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !1
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, ULongLong);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, ULongLong);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_ulonglong out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 1 && !1
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = ulonglong_ctype_power(arg1, arg2, &out);

#if !1
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(ULongLong);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, ULongLong, out);

    return ret;
}


#undef IS_ulonglong

#line 1421
#define IS_half

static PyObject *
half_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_half arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyHalfArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyHalfArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Half);
        assert(is_forward || PyArray_IsScalar(b, Half));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_half(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, half_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (HALF_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Half);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Half);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_half out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 0 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = half_ctype_power(arg1, arg2, &out);

#if !0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(Half);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Half, out);

    return ret;
}


#undef IS_half

#line 1421
#define IS_float

static PyObject *
float_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_float arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Float);
        assert(is_forward || PyArray_IsScalar(b, Float));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_float(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, float_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (FLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Float);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Float);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_float out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 0 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = float_ctype_power(arg1, arg2, &out);

#if !0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(Float);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Float, out);

    return ret;
}


#undef IS_float

#line 1421
#define IS_double

static PyObject *
double_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_double arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, Double);
        assert(is_forward || PyArray_IsScalar(b, Double));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_double(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, double_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (DOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, Double);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, Double);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_double out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 0 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = double_ctype_power(arg1, arg2, &out);

#if !0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(Double);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, Double, out);

    return ret;
}


#undef IS_double

#line 1421
#define IS_longdouble

static PyObject *
longdouble_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_longdouble arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, LongDouble);
        assert(is_forward || PyArray_IsScalar(b, LongDouble));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_longdouble(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, longdouble_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (LONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, LongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, LongDouble);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_longdouble out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 0 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = longdouble_ctype_power(arg1, arg2, &out);

#if !0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(LongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, LongDouble, out);

    return ret;
}


#undef IS_longdouble

#line 1421
#define IS_cfloat

static PyObject *
cfloat_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_cfloat arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyCFloatArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCFloatArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CFloat);
        assert(is_forward || PyArray_IsScalar(b, CFloat));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_cfloat(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, cfloat_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (CFLOAT_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CFloat);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CFloat);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_cfloat out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 0 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = cfloat_ctype_power(arg1, arg2, &out);

#if !0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(CFloat);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CFloat, out);

    return ret;
}


#undef IS_cfloat

#line 1421
#define IS_cdouble

static PyObject *
cdouble_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_cdouble arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyCDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CDouble);
        assert(is_forward || PyArray_IsScalar(b, CDouble));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_cdouble(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, cdouble_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (CDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CDouble);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_cdouble out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 0 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = cdouble_ctype_power(arg1, arg2, &out);

#if !0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(CDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CDouble, out);

    return ret;
}


#undef IS_cdouble

#line 1421
#define IS_clongdouble

static PyObject *
clongdouble_power(PyObject *a, PyObject *b, PyObject *modulo)
{
    if (modulo != Py_None) {
        /* modular exponentiation is not implemented (gh-8804) */
        Py_INCREF(Py_NotImplemented);
        return Py_NotImplemented;
    }

    PyObject *ret;
    npy_clongdouble arg1, arg2, other_val;

    int is_forward;
    if (Py_TYPE(a) == &PyCLongDoubleArrType_Type) {
        is_forward = 1;
    }
    else if (Py_TYPE(b) == &PyCLongDoubleArrType_Type) {
        is_forward = 0;
    }
    else {
        /* subclasses are involved */
        is_forward = PyArray_IsScalar(a, CLongDouble);
        assert(is_forward || PyArray_IsScalar(b, CLongDouble));
    }
    /*
     * Extract the other value (if it is compatible). See the generic
     * (non power) version above for detailed notes.
     */
    PyObject *other = is_forward ? b : a;

    npy_bool may_need_deferring;
    int res = convert_to_clongdouble(other, &other_val, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        BINOP_GIVE_UP_IF_NEEDED(a, b, nb_power, clongdouble_power);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_as_number->nb_power(a, b, modulo);
        case CONVERT_PYSCALAR:
            if (CLONGDOUBLE_setitem(other, (char *)&other_val, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

#if !0
    npy_clear_floatstatus_barrier((char*)&arg1);
#endif

    if (is_forward) {
        arg1 = PyArrayScalar_VAL(a, CLongDouble);
        arg2 = other_val;
    }
    else {
        arg1 = other_val;
        arg2 = PyArrayScalar_VAL(b, CLongDouble);
    }

    /*
     * Prepare the actual calculation:
     */
    npy_clongdouble out;

    /*
     * here we do the actual calculation with arg1 and arg2
     * as a function call.
     */
#if 0 && !0
    if (arg2 < 0) {
        PyErr_SetString(PyExc_ValueError,
                "Integers to negative integer powers are not allowed.");
        return NULL;
    }
#endif
    int retstatus = clongdouble_ctype_power(arg1, arg2, &out);

#if !0
    /* Check status flag.  If it is set, then look up what to do */
    retstatus |= npy_get_floatstatus_barrier((char*)&out);
#endif
    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar power", retstatus) < 0) {
            return NULL;
        }
    }

    ret = PyArrayScalar_New(CLongDouble);
    if (ret == NULL) {
        return NULL;
    }
    PyArrayScalar_ASSIGN(ret, CLongDouble, out);

    return ret;
}


#undef IS_clongdouble

#undef _IS_ZERO


#line 1544

/*
 * Complex numbers do not support remainder so we manually make sure that the
 * operation is not defined.  This is/was especially important for longdoubles
 * due to their tendency to recurse for some operations, see gh-18548.
 * (We need to define the slots to avoid inheriting it.)
 */
static PyObject *
cfloat_floor_divide(PyObject *NPY_UNUSED(a), PyObject *NPY_UNUSED(b))
{
    Py_RETURN_NOTIMPLEMENTED;
}


#line 1544

/*
 * Complex numbers do not support remainder so we manually make sure that the
 * operation is not defined.  This is/was especially important for longdoubles
 * due to their tendency to recurse for some operations, see gh-18548.
 * (We need to define the slots to avoid inheriting it.)
 */
static PyObject *
cdouble_floor_divide(PyObject *NPY_UNUSED(a), PyObject *NPY_UNUSED(b))
{
    Py_RETURN_NOTIMPLEMENTED;
}


#line 1544

/*
 * Complex numbers do not support remainder so we manually make sure that the
 * operation is not defined.  This is/was especially important for longdoubles
 * due to their tendency to recurse for some operations, see gh-18548.
 * (We need to define the slots to avoid inheriting it.)
 */
static PyObject *
clongdouble_floor_divide(PyObject *NPY_UNUSED(a), PyObject *NPY_UNUSED(b))
{
    Py_RETURN_NOTIMPLEMENTED;
}


#line 1544

/*
 * Complex numbers do not support remainder so we manually make sure that the
 * operation is not defined.  This is/was especially important for longdoubles
 * due to their tendency to recurse for some operations, see gh-18548.
 * (We need to define the slots to avoid inheriting it.)
 */
static PyObject *
cfloat_divmod(PyObject *NPY_UNUSED(a), PyObject *NPY_UNUSED(b))
{
    Py_RETURN_NOTIMPLEMENTED;
}


#line 1544

/*
 * Complex numbers do not support remainder so we manually make sure that the
 * operation is not defined.  This is/was especially important for longdoubles
 * due to their tendency to recurse for some operations, see gh-18548.
 * (We need to define the slots to avoid inheriting it.)
 */
static PyObject *
cdouble_divmod(PyObject *NPY_UNUSED(a), PyObject *NPY_UNUSED(b))
{
    Py_RETURN_NOTIMPLEMENTED;
}


#line 1544

/*
 * Complex numbers do not support remainder so we manually make sure that the
 * operation is not defined.  This is/was especially important for longdoubles
 * due to their tendency to recurse for some operations, see gh-18548.
 * (We need to define the slots to avoid inheriting it.)
 */
static PyObject *
clongdouble_divmod(PyObject *NPY_UNUSED(a), PyObject *NPY_UNUSED(b))
{
    Py_RETURN_NOTIMPLEMENTED;
}


#line 1544

/*
 * Complex numbers do not support remainder so we manually make sure that the
 * operation is not defined.  This is/was especially important for longdoubles
 * due to their tendency to recurse for some operations, see gh-18548.
 * (We need to define the slots to avoid inheriting it.)
 */
static PyObject *
cfloat_remainder(PyObject *NPY_UNUSED(a), PyObject *NPY_UNUSED(b))
{
    Py_RETURN_NOTIMPLEMENTED;
}


#line 1544

/*
 * Complex numbers do not support remainder so we manually make sure that the
 * operation is not defined.  This is/was especially important for longdoubles
 * due to their tendency to recurse for some operations, see gh-18548.
 * (We need to define the slots to avoid inheriting it.)
 */
static PyObject *
cdouble_remainder(PyObject *NPY_UNUSED(a), PyObject *NPY_UNUSED(b))
{
    Py_RETURN_NOTIMPLEMENTED;
}


#line 1544

/*
 * Complex numbers do not support remainder so we manually make sure that the
 * operation is not defined.  This is/was especially important for longdoubles
 * due to their tendency to recurse for some operations, see gh-18548.
 * (We need to define the slots to avoid inheriting it.)
 */
static PyObject *
clongdouble_remainder(PyObject *NPY_UNUSED(a), PyObject *NPY_UNUSED(b))
{
    Py_RETURN_NOTIMPLEMENTED;
}



#line 1564

#line 1570

#define half_lshift NULL


#line 1570

#define half_rshift NULL


#line 1570

#define half_and NULL


#line 1570

#define half_or NULL


#line 1570

#define half_xor NULL




#line 1564

#line 1570

#define float_lshift NULL


#line 1570

#define float_rshift NULL


#line 1570

#define float_and NULL


#line 1570

#define float_or NULL


#line 1570

#define float_xor NULL




#line 1564

#line 1570

#define double_lshift NULL


#line 1570

#define double_rshift NULL


#line 1570

#define double_and NULL


#line 1570

#define double_or NULL


#line 1570

#define double_xor NULL




#line 1564

#line 1570

#define longdouble_lshift NULL


#line 1570

#define longdouble_rshift NULL


#line 1570

#define longdouble_and NULL


#line 1570

#define longdouble_or NULL


#line 1570

#define longdouble_xor NULL




#line 1564

#line 1570

#define cfloat_lshift NULL


#line 1570

#define cfloat_rshift NULL


#line 1570

#define cfloat_and NULL


#line 1570

#define cfloat_or NULL


#line 1570

#define cfloat_xor NULL




#line 1564

#line 1570

#define cdouble_lshift NULL


#line 1570

#define cdouble_rshift NULL


#line 1570

#define cdouble_and NULL


#line 1570

#define cdouble_or NULL


#line 1570

#define cdouble_xor NULL




#line 1564

#line 1570

#define clongdouble_lshift NULL


#line 1570

#define clongdouble_rshift NULL


#line 1570

#define clongdouble_and NULL


#line 1570

#define clongdouble_or NULL


#line 1570

#define clongdouble_xor NULL





#line 1628
static PyObject *
byte_negative(PyObject *a)
{
    npy_byte val;
    npy_byte out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Byte);
    int retstatus = byte_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Byte);
    PyArrayScalar_ASSIGN(ret, Byte, out);

    return ret;
}

#line 1628
static PyObject *
ubyte_negative(PyObject *a)
{
    npy_ubyte val;
    npy_ubyte out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UByte);
    int retstatus = ubyte_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UByte);
    PyArrayScalar_ASSIGN(ret, UByte, out);

    return ret;
}

#line 1628
static PyObject *
short_negative(PyObject *a)
{
    npy_short val;
    npy_short out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Short);
    int retstatus = short_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Short);
    PyArrayScalar_ASSIGN(ret, Short, out);

    return ret;
}

#line 1628
static PyObject *
ushort_negative(PyObject *a)
{
    npy_ushort val;
    npy_ushort out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UShort);
    int retstatus = ushort_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UShort);
    PyArrayScalar_ASSIGN(ret, UShort, out);

    return ret;
}

#line 1628
static PyObject *
int_negative(PyObject *a)
{
    npy_int val;
    npy_int out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Int);
    int retstatus = int_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Int);
    PyArrayScalar_ASSIGN(ret, Int, out);

    return ret;
}

#line 1628
static PyObject *
uint_negative(PyObject *a)
{
    npy_uint val;
    npy_uint out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UInt);
    int retstatus = uint_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UInt);
    PyArrayScalar_ASSIGN(ret, UInt, out);

    return ret;
}

#line 1628
static PyObject *
long_negative(PyObject *a)
{
    npy_long val;
    npy_long out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Long);
    int retstatus = long_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Long);
    PyArrayScalar_ASSIGN(ret, Long, out);

    return ret;
}

#line 1628
static PyObject *
ulong_negative(PyObject *a)
{
    npy_ulong val;
    npy_ulong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, ULong);
    int retstatus = ulong_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(ULong);
    PyArrayScalar_ASSIGN(ret, ULong, out);

    return ret;
}

#line 1628
static PyObject *
longlong_negative(PyObject *a)
{
    npy_longlong val;
    npy_longlong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, LongLong);
    int retstatus = longlong_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(LongLong);
    PyArrayScalar_ASSIGN(ret, LongLong, out);

    return ret;
}

#line 1628
static PyObject *
ulonglong_negative(PyObject *a)
{
    npy_ulonglong val;
    npy_ulonglong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, ULongLong);
    int retstatus = ulonglong_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(ULongLong);
    PyArrayScalar_ASSIGN(ret, ULongLong, out);

    return ret;
}

#line 1628
static PyObject *
half_negative(PyObject *a)
{
    npy_half val;
    npy_half out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Half);
    int retstatus = half_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Half);
    PyArrayScalar_ASSIGN(ret, Half, out);

    return ret;
}

#line 1628
static PyObject *
float_negative(PyObject *a)
{
    npy_float val;
    npy_float out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Float);
    int retstatus = float_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Float);
    PyArrayScalar_ASSIGN(ret, Float, out);

    return ret;
}

#line 1628
static PyObject *
double_negative(PyObject *a)
{
    npy_double val;
    npy_double out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Double);
    int retstatus = double_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Double);
    PyArrayScalar_ASSIGN(ret, Double, out);

    return ret;
}

#line 1628
static PyObject *
longdouble_negative(PyObject *a)
{
    npy_longdouble val;
    npy_longdouble out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, LongDouble);
    int retstatus = longdouble_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(LongDouble);
    PyArrayScalar_ASSIGN(ret, LongDouble, out);

    return ret;
}

#line 1628
static PyObject *
cfloat_negative(PyObject *a)
{
    npy_cfloat val;
    npy_cfloat out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, CFloat);
    int retstatus = cfloat_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(CFloat);
    PyArrayScalar_ASSIGN(ret, CFloat, out);

    return ret;
}

#line 1628
static PyObject *
cdouble_negative(PyObject *a)
{
    npy_cdouble val;
    npy_cdouble out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, CDouble);
    int retstatus = cdouble_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(CDouble);
    PyArrayScalar_ASSIGN(ret, CDouble, out);

    return ret;
}

#line 1628
static PyObject *
clongdouble_negative(PyObject *a)
{
    npy_clongdouble val;
    npy_clongdouble out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, CLongDouble);
    int retstatus = clongdouble_ctype_negative(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar negative", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(CLongDouble);
    PyArrayScalar_ASSIGN(ret, CLongDouble, out);

    return ret;
}

#line 1628
static PyObject *
byte_positive(PyObject *a)
{
    npy_byte val;
    npy_byte out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Byte);
    int retstatus = byte_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Byte);
    PyArrayScalar_ASSIGN(ret, Byte, out);

    return ret;
}

#line 1628
static PyObject *
ubyte_positive(PyObject *a)
{
    npy_ubyte val;
    npy_ubyte out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UByte);
    int retstatus = ubyte_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UByte);
    PyArrayScalar_ASSIGN(ret, UByte, out);

    return ret;
}

#line 1628
static PyObject *
short_positive(PyObject *a)
{
    npy_short val;
    npy_short out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Short);
    int retstatus = short_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Short);
    PyArrayScalar_ASSIGN(ret, Short, out);

    return ret;
}

#line 1628
static PyObject *
ushort_positive(PyObject *a)
{
    npy_ushort val;
    npy_ushort out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UShort);
    int retstatus = ushort_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UShort);
    PyArrayScalar_ASSIGN(ret, UShort, out);

    return ret;
}

#line 1628
static PyObject *
int_positive(PyObject *a)
{
    npy_int val;
    npy_int out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Int);
    int retstatus = int_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Int);
    PyArrayScalar_ASSIGN(ret, Int, out);

    return ret;
}

#line 1628
static PyObject *
uint_positive(PyObject *a)
{
    npy_uint val;
    npy_uint out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UInt);
    int retstatus = uint_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UInt);
    PyArrayScalar_ASSIGN(ret, UInt, out);

    return ret;
}

#line 1628
static PyObject *
long_positive(PyObject *a)
{
    npy_long val;
    npy_long out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Long);
    int retstatus = long_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Long);
    PyArrayScalar_ASSIGN(ret, Long, out);

    return ret;
}

#line 1628
static PyObject *
ulong_positive(PyObject *a)
{
    npy_ulong val;
    npy_ulong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, ULong);
    int retstatus = ulong_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(ULong);
    PyArrayScalar_ASSIGN(ret, ULong, out);

    return ret;
}

#line 1628
static PyObject *
longlong_positive(PyObject *a)
{
    npy_longlong val;
    npy_longlong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, LongLong);
    int retstatus = longlong_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(LongLong);
    PyArrayScalar_ASSIGN(ret, LongLong, out);

    return ret;
}

#line 1628
static PyObject *
ulonglong_positive(PyObject *a)
{
    npy_ulonglong val;
    npy_ulonglong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, ULongLong);
    int retstatus = ulonglong_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(ULongLong);
    PyArrayScalar_ASSIGN(ret, ULongLong, out);

    return ret;
}

#line 1628
static PyObject *
half_positive(PyObject *a)
{
    npy_half val;
    npy_half out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Half);
    int retstatus = half_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Half);
    PyArrayScalar_ASSIGN(ret, Half, out);

    return ret;
}

#line 1628
static PyObject *
float_positive(PyObject *a)
{
    npy_float val;
    npy_float out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Float);
    int retstatus = float_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Float);
    PyArrayScalar_ASSIGN(ret, Float, out);

    return ret;
}

#line 1628
static PyObject *
double_positive(PyObject *a)
{
    npy_double val;
    npy_double out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Double);
    int retstatus = double_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Double);
    PyArrayScalar_ASSIGN(ret, Double, out);

    return ret;
}

#line 1628
static PyObject *
longdouble_positive(PyObject *a)
{
    npy_longdouble val;
    npy_longdouble out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, LongDouble);
    int retstatus = longdouble_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(LongDouble);
    PyArrayScalar_ASSIGN(ret, LongDouble, out);

    return ret;
}

#line 1628
static PyObject *
cfloat_positive(PyObject *a)
{
    npy_cfloat val;
    npy_cfloat out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, CFloat);
    int retstatus = cfloat_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(CFloat);
    PyArrayScalar_ASSIGN(ret, CFloat, out);

    return ret;
}

#line 1628
static PyObject *
cdouble_positive(PyObject *a)
{
    npy_cdouble val;
    npy_cdouble out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, CDouble);
    int retstatus = cdouble_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(CDouble);
    PyArrayScalar_ASSIGN(ret, CDouble, out);

    return ret;
}

#line 1628
static PyObject *
clongdouble_positive(PyObject *a)
{
    npy_clongdouble val;
    npy_clongdouble out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, CLongDouble);
    int retstatus = clongdouble_ctype_positive(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar positive", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(CLongDouble);
    PyArrayScalar_ASSIGN(ret, CLongDouble, out);

    return ret;
}

#line 1628
static PyObject *
byte_absolute(PyObject *a)
{
    npy_byte val;
    npy_byte out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Byte);
    int retstatus = byte_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Byte);
    PyArrayScalar_ASSIGN(ret, Byte, out);

    return ret;
}

#line 1628
static PyObject *
ubyte_absolute(PyObject *a)
{
    npy_ubyte val;
    npy_ubyte out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UByte);
    int retstatus = ubyte_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UByte);
    PyArrayScalar_ASSIGN(ret, UByte, out);

    return ret;
}

#line 1628
static PyObject *
short_absolute(PyObject *a)
{
    npy_short val;
    npy_short out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Short);
    int retstatus = short_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Short);
    PyArrayScalar_ASSIGN(ret, Short, out);

    return ret;
}

#line 1628
static PyObject *
ushort_absolute(PyObject *a)
{
    npy_ushort val;
    npy_ushort out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UShort);
    int retstatus = ushort_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UShort);
    PyArrayScalar_ASSIGN(ret, UShort, out);

    return ret;
}

#line 1628
static PyObject *
int_absolute(PyObject *a)
{
    npy_int val;
    npy_int out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Int);
    int retstatus = int_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Int);
    PyArrayScalar_ASSIGN(ret, Int, out);

    return ret;
}

#line 1628
static PyObject *
uint_absolute(PyObject *a)
{
    npy_uint val;
    npy_uint out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UInt);
    int retstatus = uint_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UInt);
    PyArrayScalar_ASSIGN(ret, UInt, out);

    return ret;
}

#line 1628
static PyObject *
long_absolute(PyObject *a)
{
    npy_long val;
    npy_long out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Long);
    int retstatus = long_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Long);
    PyArrayScalar_ASSIGN(ret, Long, out);

    return ret;
}

#line 1628
static PyObject *
ulong_absolute(PyObject *a)
{
    npy_ulong val;
    npy_ulong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, ULong);
    int retstatus = ulong_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(ULong);
    PyArrayScalar_ASSIGN(ret, ULong, out);

    return ret;
}

#line 1628
static PyObject *
longlong_absolute(PyObject *a)
{
    npy_longlong val;
    npy_longlong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, LongLong);
    int retstatus = longlong_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(LongLong);
    PyArrayScalar_ASSIGN(ret, LongLong, out);

    return ret;
}

#line 1628
static PyObject *
ulonglong_absolute(PyObject *a)
{
    npy_ulonglong val;
    npy_ulonglong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, ULongLong);
    int retstatus = ulonglong_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(ULongLong);
    PyArrayScalar_ASSIGN(ret, ULongLong, out);

    return ret;
}

#line 1628
static PyObject *
half_absolute(PyObject *a)
{
    npy_half val;
    npy_half out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Half);
    int retstatus = half_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Half);
    PyArrayScalar_ASSIGN(ret, Half, out);

    return ret;
}

#line 1628
static PyObject *
float_absolute(PyObject *a)
{
    npy_float val;
    npy_float out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Float);
    int retstatus = float_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Float);
    PyArrayScalar_ASSIGN(ret, Float, out);

    return ret;
}

#line 1628
static PyObject *
double_absolute(PyObject *a)
{
    npy_double val;
    npy_double out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Double);
    int retstatus = double_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Double);
    PyArrayScalar_ASSIGN(ret, Double, out);

    return ret;
}

#line 1628
static PyObject *
longdouble_absolute(PyObject *a)
{
    npy_longdouble val;
    npy_longdouble out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, LongDouble);
    int retstatus = longdouble_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(LongDouble);
    PyArrayScalar_ASSIGN(ret, LongDouble, out);

    return ret;
}

#line 1628
static PyObject *
cfloat_absolute(PyObject *a)
{
    npy_cfloat val;
    npy_float out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, CFloat);
    int retstatus = cfloat_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Float);
    PyArrayScalar_ASSIGN(ret, Float, out);

    return ret;
}

#line 1628
static PyObject *
cdouble_absolute(PyObject *a)
{
    npy_cdouble val;
    npy_double out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, CDouble);
    int retstatus = cdouble_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Double);
    PyArrayScalar_ASSIGN(ret, Double, out);

    return ret;
}

#line 1628
static PyObject *
clongdouble_absolute(PyObject *a)
{
    npy_clongdouble val;
    npy_longdouble out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, CLongDouble);
    int retstatus = clongdouble_ctype_absolute(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar absolute", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(LongDouble);
    PyArrayScalar_ASSIGN(ret, LongDouble, out);

    return ret;
}

#line 1628
static PyObject *
byte_invert(PyObject *a)
{
    npy_byte val;
    npy_byte out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Byte);
    int retstatus = byte_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Byte);
    PyArrayScalar_ASSIGN(ret, Byte, out);

    return ret;
}

#line 1628
static PyObject *
ubyte_invert(PyObject *a)
{
    npy_ubyte val;
    npy_ubyte out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UByte);
    int retstatus = ubyte_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UByte);
    PyArrayScalar_ASSIGN(ret, UByte, out);

    return ret;
}

#line 1628
static PyObject *
short_invert(PyObject *a)
{
    npy_short val;
    npy_short out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Short);
    int retstatus = short_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Short);
    PyArrayScalar_ASSIGN(ret, Short, out);

    return ret;
}

#line 1628
static PyObject *
ushort_invert(PyObject *a)
{
    npy_ushort val;
    npy_ushort out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UShort);
    int retstatus = ushort_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UShort);
    PyArrayScalar_ASSIGN(ret, UShort, out);

    return ret;
}

#line 1628
static PyObject *
int_invert(PyObject *a)
{
    npy_int val;
    npy_int out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Int);
    int retstatus = int_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Int);
    PyArrayScalar_ASSIGN(ret, Int, out);

    return ret;
}

#line 1628
static PyObject *
uint_invert(PyObject *a)
{
    npy_uint val;
    npy_uint out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, UInt);
    int retstatus = uint_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(UInt);
    PyArrayScalar_ASSIGN(ret, UInt, out);

    return ret;
}

#line 1628
static PyObject *
long_invert(PyObject *a)
{
    npy_long val;
    npy_long out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, Long);
    int retstatus = long_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(Long);
    PyArrayScalar_ASSIGN(ret, Long, out);

    return ret;
}

#line 1628
static PyObject *
ulong_invert(PyObject *a)
{
    npy_ulong val;
    npy_ulong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, ULong);
    int retstatus = ulong_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(ULong);
    PyArrayScalar_ASSIGN(ret, ULong, out);

    return ret;
}

#line 1628
static PyObject *
longlong_invert(PyObject *a)
{
    npy_longlong val;
    npy_longlong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, LongLong);
    int retstatus = longlong_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(LongLong);
    PyArrayScalar_ASSIGN(ret, LongLong, out);

    return ret;
}

#line 1628
static PyObject *
ulonglong_invert(PyObject *a)
{
    npy_ulonglong val;
    npy_ulonglong out;
    PyObject *ret;


    val = PyArrayScalar_VAL(a, ULongLong);
    int retstatus = ulonglong_ctype_invert(val, &out);

    if (retstatus) {
        if (PyUFunc_GiveFloatingpointErrors("scalar invert", retstatus) < 0) {
            return NULL;
        }
    }

    /*
     * TODO: Complex absolute should check floating point flags.
     */

    ret = PyArrayScalar_New(ULongLong);
    PyArrayScalar_ASSIGN(ret, ULongLong, out);

    return ret;
}


#line 1660

#define half_invert NULL


#line 1660

#define float_invert NULL


#line 1660

#define double_invert NULL


#line 1660

#define longdouble_invert NULL


#line 1660

#define cfloat_invert NULL


#line 1660

#define cdouble_invert NULL


#line 1660

#define clongdouble_invert NULL



#define _IS_NONZERO(x) (x != 0)
#line 1683
static int
byte_bool(PyObject *a)
{
    int ret;
    npy_byte val;

    val = PyArrayScalar_VAL(a, Byte);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
ubyte_bool(PyObject *a)
{
    int ret;
    npy_ubyte val;

    val = PyArrayScalar_VAL(a, UByte);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
short_bool(PyObject *a)
{
    int ret;
    npy_short val;

    val = PyArrayScalar_VAL(a, Short);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
ushort_bool(PyObject *a)
{
    int ret;
    npy_ushort val;

    val = PyArrayScalar_VAL(a, UShort);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
int_bool(PyObject *a)
{
    int ret;
    npy_int val;

    val = PyArrayScalar_VAL(a, Int);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
uint_bool(PyObject *a)
{
    int ret;
    npy_uint val;

    val = PyArrayScalar_VAL(a, UInt);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
long_bool(PyObject *a)
{
    int ret;
    npy_long val;

    val = PyArrayScalar_VAL(a, Long);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
ulong_bool(PyObject *a)
{
    int ret;
    npy_ulong val;

    val = PyArrayScalar_VAL(a, ULong);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
longlong_bool(PyObject *a)
{
    int ret;
    npy_longlong val;

    val = PyArrayScalar_VAL(a, LongLong);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
ulonglong_bool(PyObject *a)
{
    int ret;
    npy_ulonglong val;

    val = PyArrayScalar_VAL(a, ULongLong);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
half_bool(PyObject *a)
{
    int ret;
    npy_half val;

    val = PyArrayScalar_VAL(a, Half);

#if 1
    ret = !npy_half_iszero(val);
#else
    ret = (!npy_half_iszero(val.real) || !npy_half_iszero(val.imag));
#endif

    return ret;
}

#line 1683
static int
float_bool(PyObject *a)
{
    int ret;
    npy_float val;

    val = PyArrayScalar_VAL(a, Float);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
double_bool(PyObject *a)
{
    int ret;
    npy_double val;

    val = PyArrayScalar_VAL(a, Double);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
longdouble_bool(PyObject *a)
{
    int ret;
    npy_longdouble val;

    val = PyArrayScalar_VAL(a, LongDouble);

#if 1
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
cfloat_bool(PyObject *a)
{
    int ret;
    npy_cfloat val;

    val = PyArrayScalar_VAL(a, CFloat);

#if 0
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
cdouble_bool(PyObject *a)
{
    int ret;
    npy_cdouble val;

    val = PyArrayScalar_VAL(a, CDouble);

#if 0
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#line 1683
static int
clongdouble_bool(PyObject *a)
{
    int ret;
    npy_clongdouble val;

    val = PyArrayScalar_VAL(a, CLongDouble);

#if 0
    ret = _IS_NONZERO(val);
#else
    ret = (_IS_NONZERO(val.real) || _IS_NONZERO(val.imag));
#endif

    return ret;
}

#undef _IS_NONZERO


static int
emit_complexwarning(void)
{
    static PyObject *cls = NULL;
    npy_cache_import("numpy.exceptions", "ComplexWarning", &cls);
    if (cls == NULL) {
        return -1;
    }
    return PyErr_WarnEx(cls,
            "Casting complex values to real discards the imaginary part", 1);
}

#line 1737
static PyObject *
byte_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    signed long x = (PyArrayScalar_VAL(obj, Byte).real);
#else
    signed long x = (PyArrayScalar_VAL(obj, Byte));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
ubyte_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    unsigned long x = (PyArrayScalar_VAL(obj, UByte).real);
#else
    unsigned long x = (PyArrayScalar_VAL(obj, UByte));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromUnsignedLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
short_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    signed long x = (PyArrayScalar_VAL(obj, Short).real);
#else
    signed long x = (PyArrayScalar_VAL(obj, Short));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
ushort_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    unsigned long x = (PyArrayScalar_VAL(obj, UShort).real);
#else
    unsigned long x = (PyArrayScalar_VAL(obj, UShort));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromUnsignedLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
int_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    signed long x = (PyArrayScalar_VAL(obj, Int).real);
#else
    signed long x = (PyArrayScalar_VAL(obj, Int));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
uint_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    unsigned long x = (PyArrayScalar_VAL(obj, UInt).real);
#else
    unsigned long x = (PyArrayScalar_VAL(obj, UInt));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromUnsignedLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
long_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    signed long x = (PyArrayScalar_VAL(obj, Long).real);
#else
    signed long x = (PyArrayScalar_VAL(obj, Long));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
ulong_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    unsigned long x = (PyArrayScalar_VAL(obj, ULong).real);
#else
    unsigned long x = (PyArrayScalar_VAL(obj, ULong));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromUnsignedLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
longlong_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    signed PY_LONG_LONG x = (PyArrayScalar_VAL(obj, LongLong).real);
#else
    signed PY_LONG_LONG x = (PyArrayScalar_VAL(obj, LongLong));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromLongLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
ulonglong_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
    unsigned PY_LONG_LONG x = (PyArrayScalar_VAL(obj, ULongLong).real);
#else
    unsigned PY_LONG_LONG x = (PyArrayScalar_VAL(obj, ULongLong));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromUnsignedLongLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
half_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
     double x = npy_half_to_double(PyArrayScalar_VAL(obj, Half).real);
#else
     double x = npy_half_to_double(PyArrayScalar_VAL(obj, Half));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromDouble(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
float_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
     double x = (PyArrayScalar_VAL(obj, Float).real);
#else
     double x = (PyArrayScalar_VAL(obj, Float));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromDouble(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
double_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
     double x = (PyArrayScalar_VAL(obj, Double).real);
#else
     double x = (PyArrayScalar_VAL(obj, Double));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromDouble(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
longdouble_int(PyObject *obj)
{
    PyObject *long_result;

#if 0
     npy_longdouble x = (PyArrayScalar_VAL(obj, LongDouble).real);
#else
     npy_longdouble x = (PyArrayScalar_VAL(obj, LongDouble));
#endif

#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = npy_longdouble_to_PyLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
cfloat_int(PyObject *obj)
{
    PyObject *long_result;

#if 1
     double x = (PyArrayScalar_VAL(obj, CFloat).real);
#else
     double x = (PyArrayScalar_VAL(obj, CFloat));
#endif

#if 1
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromDouble(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
cdouble_int(PyObject *obj)
{
    PyObject *long_result;

#if 1
     double x = (PyArrayScalar_VAL(obj, CDouble).real);
#else
     double x = (PyArrayScalar_VAL(obj, CDouble));
#endif

#if 1
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = PyLong_FromDouble(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}

#line 1737
static PyObject *
clongdouble_int(PyObject *obj)
{
    PyObject *long_result;

#if 1
     npy_longdouble x = (PyArrayScalar_VAL(obj, CLongDouble).real);
#else
     npy_longdouble x = (PyArrayScalar_VAL(obj, CLongDouble));
#endif

#if 1
    if (emit_complexwarning() < 0) {
        return NULL;
    }
#endif

    long_result = npy_longdouble_to_PyLong(x);
    if (long_result == NULL){
        return NULL;
    }

    return long_result;
}


#line 1777
static PyObject *
byte_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Byte).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Byte)));
#endif
}

#line 1777
static PyObject *
ubyte_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, UByte).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, UByte)));
#endif
}

#line 1777
static PyObject *
short_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Short).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Short)));
#endif
}

#line 1777
static PyObject *
ushort_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, UShort).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, UShort)));
#endif
}

#line 1777
static PyObject *
int_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Int).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Int)));
#endif
}

#line 1777
static PyObject *
uint_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, UInt).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, UInt)));
#endif
}

#line 1777
static PyObject *
long_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Long).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Long)));
#endif
}

#line 1777
static PyObject *
ulong_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, ULong).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, ULong)));
#endif
}

#line 1777
static PyObject *
longlong_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, LongLong).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, LongLong)));
#endif
}

#line 1777
static PyObject *
ulonglong_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, ULongLong).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, ULongLong)));
#endif
}

#line 1777
static PyObject *
half_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble(npy_half_to_double(PyArrayScalar_VAL(obj, Half).real));
#else
    return PyFloat_FromDouble(npy_half_to_double(PyArrayScalar_VAL(obj, Half)));
#endif
}

#line 1777
static PyObject *
float_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Float).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Float)));
#endif
}

#line 1777
static PyObject *
double_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Double).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, Double)));
#endif
}

#line 1777
static PyObject *
longdouble_float(PyObject *obj)
{
#if 0
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, LongDouble).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, LongDouble)));
#endif
}

#line 1777
static PyObject *
cfloat_float(PyObject *obj)
{
#if 1
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, CFloat).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, CFloat)));
#endif
}

#line 1777
static PyObject *
cdouble_float(PyObject *obj)
{
#if 1
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, CDouble).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, CDouble)));
#endif
}

#line 1777
static PyObject *
clongdouble_float(PyObject *obj)
{
#if 1
    if (emit_complexwarning() < 0) {
        return NULL;
    }
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, CLongDouble).real));
#else
    return PyFloat_FromDouble((PyArrayScalar_VAL(obj, CLongDouble)));
#endif
}


#if __GNUC__ < 10
    /* At least GCC 9.2 issues spurious warnings for arg2 below. */
    #pragma GCC diagnostic push  /* matching pop after function and repeat */
    #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif

#line 1803
#define def_cmp_le(arg1, arg2) (arg1 <= arg2)
#define cmplx_cmp_le(arg1, arg2) ((arg1.real == arg2.real) ?        \
                                      arg1.imag <= arg2.imag :        \
                                      arg1.real <= arg2.real)
#define def_half_cmp_le(arg1, arg2) npy_half_le(arg1, arg2)

#line 1803
#define def_cmp_ge(arg1, arg2) (arg1 >= arg2)
#define cmplx_cmp_ge(arg1, arg2) ((arg1.real == arg2.real) ?        \
                                      arg1.imag >= arg2.imag :        \
                                      arg1.real >= arg2.real)
#define def_half_cmp_ge(arg1, arg2) npy_half_ge(arg1, arg2)

#line 1803
#define def_cmp_lt(arg1, arg2) (arg1 < arg2)
#define cmplx_cmp_lt(arg1, arg2) ((arg1.real == arg2.real) ?        \
                                      arg1.imag < arg2.imag :        \
                                      arg1.real < arg2.real)
#define def_half_cmp_lt(arg1, arg2) npy_half_lt(arg1, arg2)

#line 1803
#define def_cmp_gt(arg1, arg2) (arg1 > arg2)
#define cmplx_cmp_gt(arg1, arg2) ((arg1.real == arg2.real) ?        \
                                      arg1.imag > arg2.imag :        \
                                      arg1.real > arg2.real)
#define def_half_cmp_gt(arg1, arg2) npy_half_gt(arg1, arg2)

#line 1803
#define def_cmp_eq(arg1, arg2) (arg1 == arg2)
#define cmplx_cmp_eq(arg1, arg2) ((arg1.real == arg2.real) ?        \
                                      arg1.imag == arg2.imag :        \
                                      arg1.real == arg2.real)
#define def_half_cmp_eq(arg1, arg2) npy_half_eq(arg1, arg2)

#line 1803
#define def_cmp_ne(arg1, arg2) (arg1 != arg2)
#define cmplx_cmp_ne(arg1, arg2) ((arg1.real == arg2.real) ?        \
                                      arg1.imag != arg2.imag :        \
                                      arg1.real != arg2.real)
#define def_half_cmp_ne(arg1, arg2) npy_half_ne(arg1, arg2)


#line 1825
#define IS_byte

static PyObject*
byte_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_byte arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_byte(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (BYTE_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, Byte);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_byte

#line 1825
#define IS_ubyte

static PyObject*
ubyte_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_ubyte arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_ubyte(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (UBYTE_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, UByte);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_ubyte

#line 1825
#define IS_short

static PyObject*
short_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_short arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_short(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (SHORT_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, Short);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_short

#line 1825
#define IS_ushort

static PyObject*
ushort_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_ushort arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_ushort(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (USHORT_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, UShort);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_ushort

#line 1825
#define IS_int

static PyObject*
int_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_int arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_int(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (INT_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, Int);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_int

#line 1825
#define IS_uint

static PyObject*
uint_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_uint arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_uint(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (UINT_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, UInt);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_uint

#line 1825
#define IS_long

static PyObject*
long_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_long arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_long(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (LONG_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, Long);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_long

#line 1825
#define IS_ulong

static PyObject*
ulong_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_ulong arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_ulong(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (ULONG_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, ULong);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_ulong

#line 1825
#define IS_longlong

static PyObject*
longlong_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_longlong arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_longlong(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (LONGLONG_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, LongLong);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_longlong

#line 1825
#define IS_ulonglong

static PyObject*
ulonglong_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_ulonglong arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_ulonglong(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (ULONGLONG_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, ULongLong);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_ulonglong

#line 1825
#define IS_half

static PyObject*
half_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_half arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_half(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (HALF_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, Half);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_half_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_half_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_half_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_half_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_half_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_half_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_half

#line 1825
#define IS_float

static PyObject*
float_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_float arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_float(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (FLOAT_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, Float);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_float

#line 1825
#define IS_double

static PyObject*
double_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_double arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_double(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (DOUBLE_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, Double);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_double

#line 1825
#define IS_longdouble

static PyObject*
longdouble_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_longdouble arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_longdouble(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (LONGDOUBLE_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, LongDouble);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = def_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = def_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = def_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = def_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = def_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = def_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_longdouble

#line 1825
#define IS_cfloat

static PyObject*
cfloat_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_cfloat arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_cfloat(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (CFLOAT_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, CFloat);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = cmplx_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = cmplx_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = cmplx_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = cmplx_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = cmplx_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = cmplx_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_cfloat

#line 1825
#define IS_cdouble

static PyObject*
cdouble_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_cdouble arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_cdouble(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (CDOUBLE_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, CDouble);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = cmplx_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = cmplx_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = cmplx_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = cmplx_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = cmplx_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = cmplx_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_cdouble

#line 1825
#define IS_clongdouble

static PyObject*
clongdouble_richcompare(PyObject *self, PyObject *other, int cmp_op)
{
    npy_clongdouble arg1, arg2;
    int out = 0;

    /*
     * Extract the other value (if it is compatible).
     */
    npy_bool may_need_deferring;
    int res = convert_to_clongdouble(other, &arg2, &may_need_deferring);
    if (res == CONVERSION_ERROR) {
        return NULL;  /* an error occurred (should never happen) */
    }
    if (may_need_deferring) {
        RICHCMP_GIVE_UP_IF_NEEDED(self, other);
    }
    switch (res) {
        case DEFER_TO_OTHER_KNOWN_SCALAR:
            Py_RETURN_NOTIMPLEMENTED;
        case CONVERSION_SUCCESS:
            break;  /* successfully extracted value we can proceed */
        case OTHER_IS_UNKNOWN_OBJECT:
#if defined(IS_longdouble) || defined(IS_clongdouble)
            Py_RETURN_NOTIMPLEMENTED;
#endif
        case PROMOTION_REQUIRED:
            return PyGenericArrType_Type.tp_richcompare(self, other, cmp_op);
        case CONVERT_PYSCALAR:
            if (CLONGDOUBLE_setitem(other, (char *)&arg2, NULL) < 0) {
                return NULL;
            }
            break;
        default:
            assert(0);  /* error was checked already, impossible to reach */
            return NULL;
    }

    arg1 = PyArrayScalar_VAL(self, CLongDouble);

    /* here we do the actual calculation with arg1 and arg2 */
    switch (cmp_op) {
    case Py_EQ:
        out = cmplx_cmp_eq(arg1, arg2);
        break;
    case Py_NE:
        out = cmplx_cmp_ne(arg1, arg2);
        break;
    case Py_LE:
        out = cmplx_cmp_le(arg1, arg2);
        break;
    case Py_GE:
        out = cmplx_cmp_ge(arg1, arg2);
        break;
    case Py_LT:
        out = cmplx_cmp_lt(arg1, arg2);
        break;
    case Py_GT:
        out = cmplx_cmp_gt(arg1, arg2);
        break;
    }

    if (out) {
        PyArrayScalar_RETURN_TRUE;
    }
    else {
        PyArrayScalar_RETURN_FALSE;
    }
}

#undef IS_clongdouble


#if __GNUC__ < 10
    #pragma GCC diagnostic pop
#endif


#line 1911
static PyNumberMethods byte_as_number = {
    .nb_add = (binaryfunc)byte_add,
    .nb_subtract = (binaryfunc)byte_subtract,
    .nb_multiply = (binaryfunc)byte_multiply,
    .nb_remainder = (binaryfunc)byte_remainder,
    .nb_divmod = (binaryfunc)byte_divmod,
    .nb_power = (ternaryfunc)byte_power,
    .nb_negative = (unaryfunc)byte_negative,
    .nb_positive = (unaryfunc)byte_positive,
    .nb_absolute = (unaryfunc)byte_absolute,
    .nb_bool = (inquiry)byte_bool,
    .nb_invert = (unaryfunc)byte_invert,
    .nb_lshift = (binaryfunc)byte_lshift,
    .nb_rshift = (binaryfunc)byte_rshift,
    .nb_and = (binaryfunc)byte_and,
    .nb_xor = (binaryfunc)byte_xor,
    .nb_or = (binaryfunc)byte_or,
    .nb_int = (unaryfunc)byte_int,
    .nb_float = (unaryfunc)byte_float,
    .nb_floor_divide = (binaryfunc)byte_floor_divide,
    .nb_true_divide = (binaryfunc)byte_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods ubyte_as_number = {
    .nb_add = (binaryfunc)ubyte_add,
    .nb_subtract = (binaryfunc)ubyte_subtract,
    .nb_multiply = (binaryfunc)ubyte_multiply,
    .nb_remainder = (binaryfunc)ubyte_remainder,
    .nb_divmod = (binaryfunc)ubyte_divmod,
    .nb_power = (ternaryfunc)ubyte_power,
    .nb_negative = (unaryfunc)ubyte_negative,
    .nb_positive = (unaryfunc)ubyte_positive,
    .nb_absolute = (unaryfunc)ubyte_absolute,
    .nb_bool = (inquiry)ubyte_bool,
    .nb_invert = (unaryfunc)ubyte_invert,
    .nb_lshift = (binaryfunc)ubyte_lshift,
    .nb_rshift = (binaryfunc)ubyte_rshift,
    .nb_and = (binaryfunc)ubyte_and,
    .nb_xor = (binaryfunc)ubyte_xor,
    .nb_or = (binaryfunc)ubyte_or,
    .nb_int = (unaryfunc)ubyte_int,
    .nb_float = (unaryfunc)ubyte_float,
    .nb_floor_divide = (binaryfunc)ubyte_floor_divide,
    .nb_true_divide = (binaryfunc)ubyte_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods short_as_number = {
    .nb_add = (binaryfunc)short_add,
    .nb_subtract = (binaryfunc)short_subtract,
    .nb_multiply = (binaryfunc)short_multiply,
    .nb_remainder = (binaryfunc)short_remainder,
    .nb_divmod = (binaryfunc)short_divmod,
    .nb_power = (ternaryfunc)short_power,
    .nb_negative = (unaryfunc)short_negative,
    .nb_positive = (unaryfunc)short_positive,
    .nb_absolute = (unaryfunc)short_absolute,
    .nb_bool = (inquiry)short_bool,
    .nb_invert = (unaryfunc)short_invert,
    .nb_lshift = (binaryfunc)short_lshift,
    .nb_rshift = (binaryfunc)short_rshift,
    .nb_and = (binaryfunc)short_and,
    .nb_xor = (binaryfunc)short_xor,
    .nb_or = (binaryfunc)short_or,
    .nb_int = (unaryfunc)short_int,
    .nb_float = (unaryfunc)short_float,
    .nb_floor_divide = (binaryfunc)short_floor_divide,
    .nb_true_divide = (binaryfunc)short_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods ushort_as_number = {
    .nb_add = (binaryfunc)ushort_add,
    .nb_subtract = (binaryfunc)ushort_subtract,
    .nb_multiply = (binaryfunc)ushort_multiply,
    .nb_remainder = (binaryfunc)ushort_remainder,
    .nb_divmod = (binaryfunc)ushort_divmod,
    .nb_power = (ternaryfunc)ushort_power,
    .nb_negative = (unaryfunc)ushort_negative,
    .nb_positive = (unaryfunc)ushort_positive,
    .nb_absolute = (unaryfunc)ushort_absolute,
    .nb_bool = (inquiry)ushort_bool,
    .nb_invert = (unaryfunc)ushort_invert,
    .nb_lshift = (binaryfunc)ushort_lshift,
    .nb_rshift = (binaryfunc)ushort_rshift,
    .nb_and = (binaryfunc)ushort_and,
    .nb_xor = (binaryfunc)ushort_xor,
    .nb_or = (binaryfunc)ushort_or,
    .nb_int = (unaryfunc)ushort_int,
    .nb_float = (unaryfunc)ushort_float,
    .nb_floor_divide = (binaryfunc)ushort_floor_divide,
    .nb_true_divide = (binaryfunc)ushort_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods int_as_number = {
    .nb_add = (binaryfunc)int_add,
    .nb_subtract = (binaryfunc)int_subtract,
    .nb_multiply = (binaryfunc)int_multiply,
    .nb_remainder = (binaryfunc)int_remainder,
    .nb_divmod = (binaryfunc)int_divmod,
    .nb_power = (ternaryfunc)int_power,
    .nb_negative = (unaryfunc)int_negative,
    .nb_positive = (unaryfunc)int_positive,
    .nb_absolute = (unaryfunc)int_absolute,
    .nb_bool = (inquiry)int_bool,
    .nb_invert = (unaryfunc)int_invert,
    .nb_lshift = (binaryfunc)int_lshift,
    .nb_rshift = (binaryfunc)int_rshift,
    .nb_and = (binaryfunc)int_and,
    .nb_xor = (binaryfunc)int_xor,
    .nb_or = (binaryfunc)int_or,
    .nb_int = (unaryfunc)int_int,
    .nb_float = (unaryfunc)int_float,
    .nb_floor_divide = (binaryfunc)int_floor_divide,
    .nb_true_divide = (binaryfunc)int_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods uint_as_number = {
    .nb_add = (binaryfunc)uint_add,
    .nb_subtract = (binaryfunc)uint_subtract,
    .nb_multiply = (binaryfunc)uint_multiply,
    .nb_remainder = (binaryfunc)uint_remainder,
    .nb_divmod = (binaryfunc)uint_divmod,
    .nb_power = (ternaryfunc)uint_power,
    .nb_negative = (unaryfunc)uint_negative,
    .nb_positive = (unaryfunc)uint_positive,
    .nb_absolute = (unaryfunc)uint_absolute,
    .nb_bool = (inquiry)uint_bool,
    .nb_invert = (unaryfunc)uint_invert,
    .nb_lshift = (binaryfunc)uint_lshift,
    .nb_rshift = (binaryfunc)uint_rshift,
    .nb_and = (binaryfunc)uint_and,
    .nb_xor = (binaryfunc)uint_xor,
    .nb_or = (binaryfunc)uint_or,
    .nb_int = (unaryfunc)uint_int,
    .nb_float = (unaryfunc)uint_float,
    .nb_floor_divide = (binaryfunc)uint_floor_divide,
    .nb_true_divide = (binaryfunc)uint_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods long_as_number = {
    .nb_add = (binaryfunc)long_add,
    .nb_subtract = (binaryfunc)long_subtract,
    .nb_multiply = (binaryfunc)long_multiply,
    .nb_remainder = (binaryfunc)long_remainder,
    .nb_divmod = (binaryfunc)long_divmod,
    .nb_power = (ternaryfunc)long_power,
    .nb_negative = (unaryfunc)long_negative,
    .nb_positive = (unaryfunc)long_positive,
    .nb_absolute = (unaryfunc)long_absolute,
    .nb_bool = (inquiry)long_bool,
    .nb_invert = (unaryfunc)long_invert,
    .nb_lshift = (binaryfunc)long_lshift,
    .nb_rshift = (binaryfunc)long_rshift,
    .nb_and = (binaryfunc)long_and,
    .nb_xor = (binaryfunc)long_xor,
    .nb_or = (binaryfunc)long_or,
    .nb_int = (unaryfunc)long_int,
    .nb_float = (unaryfunc)long_float,
    .nb_floor_divide = (binaryfunc)long_floor_divide,
    .nb_true_divide = (binaryfunc)long_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods ulong_as_number = {
    .nb_add = (binaryfunc)ulong_add,
    .nb_subtract = (binaryfunc)ulong_subtract,
    .nb_multiply = (binaryfunc)ulong_multiply,
    .nb_remainder = (binaryfunc)ulong_remainder,
    .nb_divmod = (binaryfunc)ulong_divmod,
    .nb_power = (ternaryfunc)ulong_power,
    .nb_negative = (unaryfunc)ulong_negative,
    .nb_positive = (unaryfunc)ulong_positive,
    .nb_absolute = (unaryfunc)ulong_absolute,
    .nb_bool = (inquiry)ulong_bool,
    .nb_invert = (unaryfunc)ulong_invert,
    .nb_lshift = (binaryfunc)ulong_lshift,
    .nb_rshift = (binaryfunc)ulong_rshift,
    .nb_and = (binaryfunc)ulong_and,
    .nb_xor = (binaryfunc)ulong_xor,
    .nb_or = (binaryfunc)ulong_or,
    .nb_int = (unaryfunc)ulong_int,
    .nb_float = (unaryfunc)ulong_float,
    .nb_floor_divide = (binaryfunc)ulong_floor_divide,
    .nb_true_divide = (binaryfunc)ulong_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods longlong_as_number = {
    .nb_add = (binaryfunc)longlong_add,
    .nb_subtract = (binaryfunc)longlong_subtract,
    .nb_multiply = (binaryfunc)longlong_multiply,
    .nb_remainder = (binaryfunc)longlong_remainder,
    .nb_divmod = (binaryfunc)longlong_divmod,
    .nb_power = (ternaryfunc)longlong_power,
    .nb_negative = (unaryfunc)longlong_negative,
    .nb_positive = (unaryfunc)longlong_positive,
    .nb_absolute = (unaryfunc)longlong_absolute,
    .nb_bool = (inquiry)longlong_bool,
    .nb_invert = (unaryfunc)longlong_invert,
    .nb_lshift = (binaryfunc)longlong_lshift,
    .nb_rshift = (binaryfunc)longlong_rshift,
    .nb_and = (binaryfunc)longlong_and,
    .nb_xor = (binaryfunc)longlong_xor,
    .nb_or = (binaryfunc)longlong_or,
    .nb_int = (unaryfunc)longlong_int,
    .nb_float = (unaryfunc)longlong_float,
    .nb_floor_divide = (binaryfunc)longlong_floor_divide,
    .nb_true_divide = (binaryfunc)longlong_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods ulonglong_as_number = {
    .nb_add = (binaryfunc)ulonglong_add,
    .nb_subtract = (binaryfunc)ulonglong_subtract,
    .nb_multiply = (binaryfunc)ulonglong_multiply,
    .nb_remainder = (binaryfunc)ulonglong_remainder,
    .nb_divmod = (binaryfunc)ulonglong_divmod,
    .nb_power = (ternaryfunc)ulonglong_power,
    .nb_negative = (unaryfunc)ulonglong_negative,
    .nb_positive = (unaryfunc)ulonglong_positive,
    .nb_absolute = (unaryfunc)ulonglong_absolute,
    .nb_bool = (inquiry)ulonglong_bool,
    .nb_invert = (unaryfunc)ulonglong_invert,
    .nb_lshift = (binaryfunc)ulonglong_lshift,
    .nb_rshift = (binaryfunc)ulonglong_rshift,
    .nb_and = (binaryfunc)ulonglong_and,
    .nb_xor = (binaryfunc)ulonglong_xor,
    .nb_or = (binaryfunc)ulonglong_or,
    .nb_int = (unaryfunc)ulonglong_int,
    .nb_float = (unaryfunc)ulonglong_float,
    .nb_floor_divide = (binaryfunc)ulonglong_floor_divide,
    .nb_true_divide = (binaryfunc)ulonglong_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods half_as_number = {
    .nb_add = (binaryfunc)half_add,
    .nb_subtract = (binaryfunc)half_subtract,
    .nb_multiply = (binaryfunc)half_multiply,
    .nb_remainder = (binaryfunc)half_remainder,
    .nb_divmod = (binaryfunc)half_divmod,
    .nb_power = (ternaryfunc)half_power,
    .nb_negative = (unaryfunc)half_negative,
    .nb_positive = (unaryfunc)half_positive,
    .nb_absolute = (unaryfunc)half_absolute,
    .nb_bool = (inquiry)half_bool,
    .nb_invert = (unaryfunc)half_invert,
    .nb_lshift = (binaryfunc)half_lshift,
    .nb_rshift = (binaryfunc)half_rshift,
    .nb_and = (binaryfunc)half_and,
    .nb_xor = (binaryfunc)half_xor,
    .nb_or = (binaryfunc)half_or,
    .nb_int = (unaryfunc)half_int,
    .nb_float = (unaryfunc)half_float,
    .nb_floor_divide = (binaryfunc)half_floor_divide,
    .nb_true_divide = (binaryfunc)half_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods float_as_number = {
    .nb_add = (binaryfunc)float_add,
    .nb_subtract = (binaryfunc)float_subtract,
    .nb_multiply = (binaryfunc)float_multiply,
    .nb_remainder = (binaryfunc)float_remainder,
    .nb_divmod = (binaryfunc)float_divmod,
    .nb_power = (ternaryfunc)float_power,
    .nb_negative = (unaryfunc)float_negative,
    .nb_positive = (unaryfunc)float_positive,
    .nb_absolute = (unaryfunc)float_absolute,
    .nb_bool = (inquiry)float_bool,
    .nb_invert = (unaryfunc)float_invert,
    .nb_lshift = (binaryfunc)float_lshift,
    .nb_rshift = (binaryfunc)float_rshift,
    .nb_and = (binaryfunc)float_and,
    .nb_xor = (binaryfunc)float_xor,
    .nb_or = (binaryfunc)float_or,
    .nb_int = (unaryfunc)float_int,
    .nb_float = (unaryfunc)float_float,
    .nb_floor_divide = (binaryfunc)float_floor_divide,
    .nb_true_divide = (binaryfunc)float_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods double_as_number = {
    .nb_add = (binaryfunc)double_add,
    .nb_subtract = (binaryfunc)double_subtract,
    .nb_multiply = (binaryfunc)double_multiply,
    .nb_remainder = (binaryfunc)double_remainder,
    .nb_divmod = (binaryfunc)double_divmod,
    .nb_power = (ternaryfunc)double_power,
    .nb_negative = (unaryfunc)double_negative,
    .nb_positive = (unaryfunc)double_positive,
    .nb_absolute = (unaryfunc)double_absolute,
    .nb_bool = (inquiry)double_bool,
    .nb_invert = (unaryfunc)double_invert,
    .nb_lshift = (binaryfunc)double_lshift,
    .nb_rshift = (binaryfunc)double_rshift,
    .nb_and = (binaryfunc)double_and,
    .nb_xor = (binaryfunc)double_xor,
    .nb_or = (binaryfunc)double_or,
    .nb_int = (unaryfunc)double_int,
    .nb_float = (unaryfunc)double_float,
    .nb_floor_divide = (binaryfunc)double_floor_divide,
    .nb_true_divide = (binaryfunc)double_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods longdouble_as_number = {
    .nb_add = (binaryfunc)longdouble_add,
    .nb_subtract = (binaryfunc)longdouble_subtract,
    .nb_multiply = (binaryfunc)longdouble_multiply,
    .nb_remainder = (binaryfunc)longdouble_remainder,
    .nb_divmod = (binaryfunc)longdouble_divmod,
    .nb_power = (ternaryfunc)longdouble_power,
    .nb_negative = (unaryfunc)longdouble_negative,
    .nb_positive = (unaryfunc)longdouble_positive,
    .nb_absolute = (unaryfunc)longdouble_absolute,
    .nb_bool = (inquiry)longdouble_bool,
    .nb_invert = (unaryfunc)longdouble_invert,
    .nb_lshift = (binaryfunc)longdouble_lshift,
    .nb_rshift = (binaryfunc)longdouble_rshift,
    .nb_and = (binaryfunc)longdouble_and,
    .nb_xor = (binaryfunc)longdouble_xor,
    .nb_or = (binaryfunc)longdouble_or,
    .nb_int = (unaryfunc)longdouble_int,
    .nb_float = (unaryfunc)longdouble_float,
    .nb_floor_divide = (binaryfunc)longdouble_floor_divide,
    .nb_true_divide = (binaryfunc)longdouble_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods cfloat_as_number = {
    .nb_add = (binaryfunc)cfloat_add,
    .nb_subtract = (binaryfunc)cfloat_subtract,
    .nb_multiply = (binaryfunc)cfloat_multiply,
    .nb_remainder = (binaryfunc)cfloat_remainder,
    .nb_divmod = (binaryfunc)cfloat_divmod,
    .nb_power = (ternaryfunc)cfloat_power,
    .nb_negative = (unaryfunc)cfloat_negative,
    .nb_positive = (unaryfunc)cfloat_positive,
    .nb_absolute = (unaryfunc)cfloat_absolute,
    .nb_bool = (inquiry)cfloat_bool,
    .nb_invert = (unaryfunc)cfloat_invert,
    .nb_lshift = (binaryfunc)cfloat_lshift,
    .nb_rshift = (binaryfunc)cfloat_rshift,
    .nb_and = (binaryfunc)cfloat_and,
    .nb_xor = (binaryfunc)cfloat_xor,
    .nb_or = (binaryfunc)cfloat_or,
    .nb_int = (unaryfunc)cfloat_int,
    .nb_float = (unaryfunc)cfloat_float,
    .nb_floor_divide = (binaryfunc)cfloat_floor_divide,
    .nb_true_divide = (binaryfunc)cfloat_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods cdouble_as_number = {
    .nb_add = (binaryfunc)cdouble_add,
    .nb_subtract = (binaryfunc)cdouble_subtract,
    .nb_multiply = (binaryfunc)cdouble_multiply,
    .nb_remainder = (binaryfunc)cdouble_remainder,
    .nb_divmod = (binaryfunc)cdouble_divmod,
    .nb_power = (ternaryfunc)cdouble_power,
    .nb_negative = (unaryfunc)cdouble_negative,
    .nb_positive = (unaryfunc)cdouble_positive,
    .nb_absolute = (unaryfunc)cdouble_absolute,
    .nb_bool = (inquiry)cdouble_bool,
    .nb_invert = (unaryfunc)cdouble_invert,
    .nb_lshift = (binaryfunc)cdouble_lshift,
    .nb_rshift = (binaryfunc)cdouble_rshift,
    .nb_and = (binaryfunc)cdouble_and,
    .nb_xor = (binaryfunc)cdouble_xor,
    .nb_or = (binaryfunc)cdouble_or,
    .nb_int = (unaryfunc)cdouble_int,
    .nb_float = (unaryfunc)cdouble_float,
    .nb_floor_divide = (binaryfunc)cdouble_floor_divide,
    .nb_true_divide = (binaryfunc)cdouble_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};

#line 1911
static PyNumberMethods clongdouble_as_number = {
    .nb_add = (binaryfunc)clongdouble_add,
    .nb_subtract = (binaryfunc)clongdouble_subtract,
    .nb_multiply = (binaryfunc)clongdouble_multiply,
    .nb_remainder = (binaryfunc)clongdouble_remainder,
    .nb_divmod = (binaryfunc)clongdouble_divmod,
    .nb_power = (ternaryfunc)clongdouble_power,
    .nb_negative = (unaryfunc)clongdouble_negative,
    .nb_positive = (unaryfunc)clongdouble_positive,
    .nb_absolute = (unaryfunc)clongdouble_absolute,
    .nb_bool = (inquiry)clongdouble_bool,
    .nb_invert = (unaryfunc)clongdouble_invert,
    .nb_lshift = (binaryfunc)clongdouble_lshift,
    .nb_rshift = (binaryfunc)clongdouble_rshift,
    .nb_and = (binaryfunc)clongdouble_and,
    .nb_xor = (binaryfunc)clongdouble_xor,
    .nb_or = (binaryfunc)clongdouble_or,
    .nb_int = (unaryfunc)clongdouble_int,
    .nb_float = (unaryfunc)clongdouble_float,
    .nb_floor_divide = (binaryfunc)clongdouble_floor_divide,
    .nb_true_divide = (binaryfunc)clongdouble_true_divide,
    /* TODO: This struct/initialization should not be split between files */
    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
};


NPY_NO_EXPORT void
add_scalarmath(void)
{
    #line 1950
    byte_as_number.nb_index = PyByteArrType_Type.tp_as_number->nb_index;
    PyByteArrType_Type.tp_as_number = &(byte_as_number);
    PyByteArrType_Type.tp_richcompare = byte_richcompare;
    
#line 1950
    ubyte_as_number.nb_index = PyUByteArrType_Type.tp_as_number->nb_index;
    PyUByteArrType_Type.tp_as_number = &(ubyte_as_number);
    PyUByteArrType_Type.tp_richcompare = ubyte_richcompare;
    
#line 1950
    short_as_number.nb_index = PyShortArrType_Type.tp_as_number->nb_index;
    PyShortArrType_Type.tp_as_number = &(short_as_number);
    PyShortArrType_Type.tp_richcompare = short_richcompare;
    
#line 1950
    ushort_as_number.nb_index = PyUShortArrType_Type.tp_as_number->nb_index;
    PyUShortArrType_Type.tp_as_number = &(ushort_as_number);
    PyUShortArrType_Type.tp_richcompare = ushort_richcompare;
    
#line 1950
    int_as_number.nb_index = PyIntArrType_Type.tp_as_number->nb_index;
    PyIntArrType_Type.tp_as_number = &(int_as_number);
    PyIntArrType_Type.tp_richcompare = int_richcompare;
    
#line 1950
    uint_as_number.nb_index = PyUIntArrType_Type.tp_as_number->nb_index;
    PyUIntArrType_Type.tp_as_number = &(uint_as_number);
    PyUIntArrType_Type.tp_richcompare = uint_richcompare;
    
#line 1950
    long_as_number.nb_index = PyLongArrType_Type.tp_as_number->nb_index;
    PyLongArrType_Type.tp_as_number = &(long_as_number);
    PyLongArrType_Type.tp_richcompare = long_richcompare;
    
#line 1950
    ulong_as_number.nb_index = PyULongArrType_Type.tp_as_number->nb_index;
    PyULongArrType_Type.tp_as_number = &(ulong_as_number);
    PyULongArrType_Type.tp_richcompare = ulong_richcompare;
    
#line 1950
    longlong_as_number.nb_index = PyLongLongArrType_Type.tp_as_number->nb_index;
    PyLongLongArrType_Type.tp_as_number = &(longlong_as_number);
    PyLongLongArrType_Type.tp_richcompare = longlong_richcompare;
    
#line 1950
    ulonglong_as_number.nb_index = PyULongLongArrType_Type.tp_as_number->nb_index;
    PyULongLongArrType_Type.tp_as_number = &(ulonglong_as_number);
    PyULongLongArrType_Type.tp_richcompare = ulonglong_richcompare;
    
#line 1950
    half_as_number.nb_index = PyHalfArrType_Type.tp_as_number->nb_index;
    PyHalfArrType_Type.tp_as_number = &(half_as_number);
    PyHalfArrType_Type.tp_richcompare = half_richcompare;
    
#line 1950
    float_as_number.nb_index = PyFloatArrType_Type.tp_as_number->nb_index;
    PyFloatArrType_Type.tp_as_number = &(float_as_number);
    PyFloatArrType_Type.tp_richcompare = float_richcompare;
    
#line 1950
    double_as_number.nb_index = PyDoubleArrType_Type.tp_as_number->nb_index;
    PyDoubleArrType_Type.tp_as_number = &(double_as_number);
    PyDoubleArrType_Type.tp_richcompare = double_richcompare;
    
#line 1950
    longdouble_as_number.nb_index = PyLongDoubleArrType_Type.tp_as_number->nb_index;
    PyLongDoubleArrType_Type.tp_as_number = &(longdouble_as_number);
    PyLongDoubleArrType_Type.tp_richcompare = longdouble_richcompare;
    
#line 1950
    cfloat_as_number.nb_index = PyCFloatArrType_Type.tp_as_number->nb_index;
    PyCFloatArrType_Type.tp_as_number = &(cfloat_as_number);
    PyCFloatArrType_Type.tp_richcompare = cfloat_richcompare;
    
#line 1950
    cdouble_as_number.nb_index = PyCDoubleArrType_Type.tp_as_number->nb_index;
    PyCDoubleArrType_Type.tp_as_number = &(cdouble_as_number);
    PyCDoubleArrType_Type.tp_richcompare = cdouble_richcompare;
    
#line 1950
    clongdouble_as_number.nb_index = PyCLongDoubleArrType_Type.tp_as_number->nb_index;
    PyCLongDoubleArrType_Type.tp_as_number = &(clongdouble_as_number);
    PyCLongDoubleArrType_Type.tp_richcompare = clongdouble_richcompare;
    
}


NPY_NO_EXPORT int initscalarmath(PyObject * m)
{
    add_scalarmath();

    return 0;
}

