Repository: numpy/numpy
File: numpy/_core/src/umath/ufunc_object.c (C)

Code before:
 * a suitable inner loop for it, assuming the output has the same data type as the
 * input (this function is not called if output or any other argument was given).
 * If a loop was found, call it and store the result.
 *
 * Returns -2 if a short-cut is not possible, 0 on success and -1 on error.
 */
static int
try_trivial_scalar_call(
    PyUFuncObject *ufunc, PyObject *const obj, PyObject **result)
{
    assert(ufunc->nin == 1 && ufunc->nout == 1 && !ufunc->core_enabled);
    char in[sizeof(npy_clongdouble)], out[sizeof(npy_clongdouble)];  // storage
    char *data[] = {in, out};
    int ret = -2;
    PyArray_Descr *dt;
    if (obj == Py_False || obj == Py_True) {
        *(npy_bool *)in = (obj == Py_True);
        dt = PyArray_DescrFromType(NPY_BOOL);
    }
    else if (PyFloat_CheckExact(obj)) {
        *(double *)in = PyFloat_AS_DOUBLE(obj);
        dt = PyArray_DescrFromType(NPY_FLOAT64);
    }
    else if (PyLong_CheckExact(obj)) {
        if (PyLong_AsInt64(obj, (int64_t *)in) < 0) {
            PyErr_Clear();
            return -2;
        }
        dt = PyArray_DescrFromType(NPY_INT64);
    }
    else if (PyComplex_CheckExact(obj)) {
        Py_complex oop = PyComplex_AsCComplex(obj);
        if (error_converting(oop.real)) {  // should never happen
            PyErr_Clear();
            return -2;
        }
        *(double *)in = oop.real;
        *(double *)(in+sizeof(double)) = oop.imag;
        dt = PyArray_DescrFromType(NPY_COMPLEX128);
    }
    else if (is_anyscalar_exact(obj)) {
        dt = PyArray_DescrFromScalar(obj);
        if (!PyDataType_ISNUMBER(dt)) {
            goto fail;
        }
        data[0] = scalar_value(obj, dt);
    }
    else {
        return -2;
    }
    // Try getting info from the (private) cache.  Fall back if not found,

Review comment (bug):
@seberg - just as an example: here I clear the error and bail, so that the main routine can have a go. This can lead to different errors. E.g.,
```
np.log(2**100)
# TypeError: loop of ufunc does not support argument 0 of type int which has no callable sin method
```
while if we let this stay in place one would get,
```
OverflowError: Python int too large to convert to C long
```
And, really, I'm doing the wrong thing here: if somewhere down the line we decide that such long integers should just be converted to double.

Anyway, my logic with the `PyErr_Clear()` was to ensure we don't change behaviour.

Code after:
 * a suitable inner loop for it, which takes and returns the data type of the
 * input (this function is not called if output or any other argument was given).
 * If a loop was found, call it and store the result.
 *
 * Returns -2 if a short-cut is not possible, 0 on success and -1 on error.
 */
static int
try_trivial_scalar_call(
    PyUFuncObject *ufunc, PyObject *const obj, PyObject **result)
{
    assert(ufunc->nin == 1 && ufunc->nout == 1 && !ufunc->core_enabled);
    npy_clongdouble cin, cout;  // aligned storage, using longest type.
    char *in = (char *)&cin, *out = (char *)&cout;
    char *data[] = {in, out};
    int ret = -2;
    PyArray_Descr *dt;
    /*
     * For supported input, get input pointer and descriptor. Otherwise, bail.
     */
    if (obj == Py_False || obj == Py_True) {
        *(npy_bool *)in = (obj == Py_True);
        dt = PyArray_DescrFromType(NPY_BOOL);
    }
    else if (PyFloat_CheckExact(obj)) {
        *(double *)in = PyFloat_AS_DOUBLE(obj);
        dt = PyArray_DescrFromType(NPY_FLOAT64);
    }
    else if (PyLong_CheckExact(obj)) {
        int overflow;
        npy_intp val = PyLong_AsLongAndOverflow(obj, &overflow);
        if (overflow) {
            return -2;  // bail, main code perhaps deals with this.
        }
        if (error_converting(val)) {
            return -1;  // should never happen; pass on it if does.
        }
        *(npy_intp *)in = val;
        dt = PyArray_DescrFromType(NPY_INTP);
    }
    else if (PyComplex_CheckExact(obj)) {
        Py_complex oop = PyComplex_AsCComplex(obj);
        if (error_converting(oop.real)) {
            return -1;  // should never happen; pass on it if does.
        }
        *(double *)in = oop.real;
        *(double *)(in+sizeof(double)) = oop.imag;
        dt = PyArray_DescrFromType(NPY_COMPLEX128);
    }
    else if (is_anyscalar_exact(obj)) {
        dt = PyArray_DescrFromScalar(obj);
        if (!PyDataType_ISNUMBER(dt)) {