Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Definition of math_sin function in the CPython source code?

I am studing the codebase of CPython.

I would like to know where can I find the definition of the math_sin function that appears in the mathmethods table in mathmodule.c:

{"sin",             math_sin,       METH_O,         math_sin_doc}

Doing grep "math_sin" -wr in the main cpython folder only returns:

Modules/mathmodule.c:    {"sin",             math_sin,       METH_O,         math_sin_doc},

Where can I find the definition of this function?

like image 470
PintoDoido Avatar asked Jan 02 '23 01:01

PintoDoido


1 Answers

math_sin is defined via the FUNC1 macro:

FUNC1(sin, sin, 0,
      "sin($module, x, /)\n--\n\n"
      "Return the sine of x (measured in radians).")

where FUNC1 is defined as:

#define FUNC1(funcname, func, can_overflow, docstring)                  \
    static PyObject * math_##funcname(PyObject *self, PyObject *args) { \
        return math_1(args, func, can_overflow);                            \
    }\
    PyDoc_STRVAR(math_##funcname##_doc, docstring);

so the preprocessor expands this to:

    static PyObject * math_sin(PyObject *self, PyObject *args) {
        return math_1(args, sin, 0);
    }
    PyDoc_STRVAR(math_sin_doc, "sin($module, x, /)\n--\n\n"
      "Return the sine of x (measured in radians).");

(but then all on one line, and with the PyDoc_STRVAR macro also having been expanded)

So math_sin(module, args) basically is a call to math_1(args, sin, 0), and math_1(args, sin, 0) calls math_1_to_whatever(args, sin, PyFloat_FromDouble, 0) which takes care of validating that a Python float was passed in, converting that to a C double, calling sin(arg_as_double), raising exceptions as needed or wrapping the double return value from sin() with the PyFloat_FromDouble function passed in by math_1() before returning that result to the caller.

sin() here is the double sin(double x) function defined in POSIX math.h.

You can, in principle, preprocess the whole Python source tree and dump the output into a new directory; the following does presume you successfully built the python binary already, as it is used to extract the necessary include flags for gcc:

find . -type d -exec mkdir -p /tmp/processed/{} \;
(export FLAGS=$(./python.exe -m sysconfig | grep PY_CORE_CFLAGS | cut -d\" -f2) && \
 find . -type f \( -name '*.c' -o -name '*.h' \) -exec gcc -E $FLAGS {} -o /tmp/processed/{} \;)

and then math_sin will show up in /tmp/preprocessed/Modules/mathmodule.c.

Or you can tell the compiler to save preprocessor output to .i files with the -save-temps flag:

make clean && make CC="gcc -save-temps"

and you'll find make_sin in Modules/mathmodule.i.

like image 200
Martijn Pieters Avatar answered Jan 08 '23 01:01

Martijn Pieters