diff -r b56ce3410ca6 Modules/cmathmodule.c --- a/Modules/cmathmodule.c Fri Jan 31 12:06:48 2014 -0600 +++ b/Modules/cmathmodule.c Fri Jan 31 15:12:51 2014 -0500 @@ -8,6 +8,39 @@ float.h. We assume that FLT_RADIX is either 2 or 16. */ #include +/*[clinic input] +module cmath +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=308d6839f4a46333]*/ + +/*[python input] +class Py_complex_protected_converter(Py_complex_converter): + def modify(self): + return 'errno = 0; PyFPE_START_PROTECT("complex function", goto exit);' + + +class Py_complex_protected_return_converter(CReturnConverter): + type = "Py_complex" + + def render(self, function, data): + self.declare(data) + data.return_conversion.append(""" +PyFPE_END_PROTECT(_return_value); +if (errno == EDOM) {{ + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; +}} +else if (errno == ERANGE) {{ + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; +}} +else {{ + return_value = PyComplex_FromCComplex(_return_value); +}} +""".strip()) +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=231019039a6fbb9a]*/ + #if (FLT_RADIX != 2 && FLT_RADIX != 16) #error "Modules/cmathmodule.c expects FLT_RADIX to be 2 or 16" #endif @@ -48,12 +81,12 @@ #define CM_SCALE_DOWN (-(CM_SCALE_UP+1)/2) /* forward declarations */ -static Py_complex c_asinh(Py_complex); -static Py_complex c_atanh(Py_complex); -static Py_complex c_cosh(Py_complex); -static Py_complex c_sinh(Py_complex); -static Py_complex c_sqrt(Py_complex); -static Py_complex c_tanh(Py_complex); +static Py_complex cmath_asinh_impl(PyModuleDef *, Py_complex); +static Py_complex cmath_atanh_impl(PyModuleDef *, Py_complex); +static Py_complex cmath_cosh_impl(PyModuleDef *, Py_complex); +static Py_complex cmath_sinh_impl(PyModuleDef *, Py_complex); +static Py_complex cmath_sqrt_impl(PyModuleDef *, Py_complex); +static Py_complex cmath_tanh_impl(PyModuleDef *, Py_complex); static PyObject * math_error(void); /* Code to deal with special values (infinities, NaNs, etc.). */ @@ -123,8 +156,59 @@ static Py_complex acos_special_values[7][7]; +/*[clinic input] +cmath.acos -> Py_complex_protected + + z: Py_complex_protected + / + +Return the arc cosine of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_acos__doc__, +"sig=($module, z)\n" +"Return the arc cosine of z."); + +#define CMATH_ACOS_METHODDEF \ + {"acos", (PyCFunction)cmath_acos, METH_VARARGS, cmath_acos__doc__}, + static Py_complex -c_acos(Py_complex z) +cmath_acos_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_acos(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:acos", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_acos_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_acos_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=813426ac7508ac24 input=bd6cbd78ae851927]*/ { Py_complex s1, s2, r; @@ -145,10 +229,10 @@ } else { s1.real = 1.-z.real; s1.imag = -z.imag; - s1 = c_sqrt(s1); + s1 = cmath_sqrt_impl(module, s1); s2.real = 1.+z.real; s2.imag = z.imag; - s2 = c_sqrt(s2); + s2 = cmath_sqrt_impl(module, s2); r.real = 2.*atan2(s1.real, s2.real); r.imag = m_asinh(s2.real*s1.imag - s2.imag*s1.real); } @@ -156,16 +240,59 @@ return r; } -PyDoc_STRVAR(c_acos_doc, -"acos(x)\n" -"\n" -"Return the arc cosine of x."); - static Py_complex acosh_special_values[7][7]; +/*[clinic input] +cmath.acosh = cmath.acos + +Return the hyperbolic arccosine of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_acosh__doc__, +"sig=($module, z)\n" +"Return the hyperbolic arccosine of z."); + +#define CMATH_ACOSH_METHODDEF \ + {"acosh", (PyCFunction)cmath_acosh, METH_VARARGS, cmath_acosh__doc__}, + static Py_complex -c_acosh(Py_complex z) +cmath_acosh_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_acosh(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:acosh", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_acosh_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_acosh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=64d4cc8636de03cc input=bc016412080bb3e9]*/ { Py_complex s1, s2, r; @@ -178,10 +305,10 @@ } else { s1.real = z.real - 1.; s1.imag = z.imag; - s1 = c_sqrt(s1); + s1 = cmath_sqrt_impl(module, s1); s2.real = z.real + 1.; s2.imag = z.imag; - s2 = c_sqrt(s2); + s2 = cmath_sqrt_impl(module, s2); r.real = m_asinh(s1.real*s2.real + s1.imag*s2.imag); r.imag = 2.*atan2(s1.imag, s2.real); } @@ -189,35 +316,120 @@ return r; } -PyDoc_STRVAR(c_acosh_doc, -"acosh(x)\n" -"\n" -"Return the hyperbolic arccosine of x."); +/*[clinic input] +cmath.asin = cmath.acos +Return the arc sine of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_asin__doc__, +"sig=($module, z)\n" +"Return the arc sine of z."); + +#define CMATH_ASIN_METHODDEF \ + {"asin", (PyCFunction)cmath_asin, METH_VARARGS, cmath_asin__doc__}, static Py_complex -c_asin(Py_complex z) +cmath_asin_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_asin(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:asin", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_asin_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_asin_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=7ef99cbd980cab8b input=be0bf0cfdd5239c5]*/ { /* asin(z) = -i asinh(iz) */ Py_complex s, r; s.real = -z.imag; s.imag = z.real; - s = c_asinh(s); + s = cmath_asinh_impl(module, s); r.real = s.imag; r.imag = -s.real; return r; } -PyDoc_STRVAR(c_asin_doc, -"asin(x)\n" -"\n" -"Return the arc sine of x."); - static Py_complex asinh_special_values[7][7]; +/*[clinic input] +cmath.asinh = cmath.acos + +Return the hyperbolic arc sine of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_asinh__doc__, +"sig=($module, z)\n" +"Return the hyperbolic arc sine of z."); + +#define CMATH_ASINH_METHODDEF \ + {"asinh", (PyCFunction)cmath_asinh, METH_VARARGS, cmath_asinh__doc__}, + static Py_complex -c_asinh(Py_complex z) +cmath_asinh_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_asinh(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:asinh", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_asinh_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_asinh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=e77b7cff67372482 input=5a21fa0242928c9b]*/ { Py_complex s1, s2, r; @@ -235,10 +447,10 @@ } else { s1.real = 1.+z.imag; s1.imag = -z.real; - s1 = c_sqrt(s1); + s1 = cmath_sqrt_impl(module, s1); s2.real = 1.-z.imag; s2.imag = z.real; - s2 = c_sqrt(s2); + s2 = cmath_sqrt_impl(module, s2); r.real = m_asinh(s1.real*s2.imag-s2.real*s1.imag); r.imag = atan2(z.imag, s1.real*s2.real-s1.imag*s2.imag); } @@ -246,20 +458,63 @@ return r; } -PyDoc_STRVAR(c_asinh_doc, -"asinh(x)\n" -"\n" -"Return the hyperbolic arc sine of x."); +/*[clinic input] +cmath.atan = cmath.acos + +Return the arc tangent of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_atan__doc__, +"sig=($module, z)\n" +"Return the arc tangent of z."); + +#define CMATH_ATAN_METHODDEF \ + {"atan", (PyCFunction)cmath_atan, METH_VARARGS, cmath_atan__doc__}, static Py_complex -c_atan(Py_complex z) +cmath_atan_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_atan(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:atan", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_atan_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_atan_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=20c9916282c3996f input=3b21ff7d5eac632a]*/ { /* atan(z) = -i atanh(iz) */ Py_complex s, r; s.real = -z.imag; s.imag = z.real; - s = c_atanh(s); + s = cmath_atanh_impl(module, s); r.real = s.imag; r.imag = -s.real; return r; @@ -295,16 +550,59 @@ return atan2(z.imag, z.real); } -PyDoc_STRVAR(c_atan_doc, -"atan(x)\n" -"\n" -"Return the arc tangent of x."); - static Py_complex atanh_special_values[7][7]; +/*[clinic input] +cmath.atanh = cmath.acos + +Return the hyperbolic arc tangent of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_atanh__doc__, +"sig=($module, z)\n" +"Return the hyperbolic arc tangent of z."); + +#define CMATH_ATANH_METHODDEF \ + {"atanh", (PyCFunction)cmath_atanh, METH_VARARGS, cmath_atanh__doc__}, + static Py_complex -c_atanh(Py_complex z) +cmath_atanh_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_atanh(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:atanh", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_atanh_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_atanh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=74319728f56ef03d input=df19cdc9f9d431c9]*/ { Py_complex r; double ay, h; @@ -313,7 +611,7 @@ /* Reduce to case where z.real >= 0., using atanh(z) = -atanh(-z). */ if (z.real < 0.) { - return c_neg(c_atanh(c_neg(z))); + return c_neg(cmath_atanh_impl(module, c_neg(z))); } ay = fabs(z.imag); @@ -350,34 +648,120 @@ return r; } -PyDoc_STRVAR(c_atanh_doc, -"atanh(x)\n" -"\n" -"Return the hyperbolic arc tangent of x."); +/*[clinic input] +cmath.cos = cmath.acos + +Return the cosine of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_cos__doc__, +"sig=($module, z)\n" +"Return the cosine of z."); + +#define CMATH_COS_METHODDEF \ + {"cos", (PyCFunction)cmath_cos, METH_VARARGS, cmath_cos__doc__}, static Py_complex -c_cos(Py_complex z) +cmath_cos_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_cos(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:cos", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_cos_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_cos_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=93142b79d492d7c0 input=6022e39b77127ac7]*/ { /* cos(z) = cosh(iz) */ Py_complex r; r.real = -z.imag; r.imag = z.real; - r = c_cosh(r); + r = cmath_cosh_impl(module, r); return r; } -PyDoc_STRVAR(c_cos_doc, -"cos(x)\n" -"\n" -"Return the cosine of x."); - /* cosh(infinity + i*y) needs to be dealt with specially */ static Py_complex cosh_special_values[7][7]; +/*[clinic input] +cmath.cosh = cmath.acos + +Return the hyperbolic cosine of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_cosh__doc__, +"sig=($module, z)\n" +"Return the hyperbolic cosine of z."); + +#define CMATH_COSH_METHODDEF \ + {"cosh", (PyCFunction)cmath_cosh, METH_VARARGS, cmath_cosh__doc__}, + static Py_complex -c_cosh(Py_complex z) +cmath_cosh_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_cosh(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:cosh", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_cosh_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_cosh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=b4e16d35197f62eb input=d6b66339e9cc332b]*/ { Py_complex r; double x_minus_one; @@ -426,18 +810,61 @@ return r; } -PyDoc_STRVAR(c_cosh_doc, -"cosh(x)\n" -"\n" -"Return the hyperbolic cosine of x."); - /* exp(infinity + i*y) and exp(-infinity + i*y) need special treatment for finite y */ static Py_complex exp_special_values[7][7]; +/*[clinic input] +cmath.exp = cmath.acos + +Return the exponential value e**z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_exp__doc__, +"sig=($module, z)\n" +"Return the exponential value e**z."); + +#define CMATH_EXP_METHODDEF \ + {"exp", (PyCFunction)cmath_exp, METH_VARARGS, cmath_exp__doc__}, + static Py_complex -c_exp(Py_complex z) +cmath_exp_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_exp(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:exp", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_exp_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_exp_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=ee371c7168672d3b input=8b9e6cf8a92174c3]*/ { Py_complex r; double l; @@ -486,12 +913,6 @@ return r; } -PyDoc_STRVAR(c_exp_doc, -"exp(x)\n" -"\n" -"Return the exponential value e**x."); - - static Py_complex log_special_values[7][7]; static Py_complex @@ -564,8 +985,56 @@ } +/*[clinic input] +cmath.log10 = cmath.acos + +Return the base-10 logarithm of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_log10__doc__, +"sig=($module, z)\n" +"Return the base-10 logarithm of z."); + +#define CMATH_LOG10_METHODDEF \ + {"log10", (PyCFunction)cmath_log10, METH_VARARGS, cmath_log10__doc__}, + static Py_complex -c_log10(Py_complex z) +cmath_log10_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_log10(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:log10", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_log10_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_log10_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=aaef54eda7281f4a input=cff5644f73c1519c]*/ { Py_complex r; int errno_save; @@ -578,36 +1047,122 @@ return r; } -PyDoc_STRVAR(c_log10_doc, -"log10(x)\n" -"\n" -"Return the base-10 logarithm of x."); +/*[clinic input] +cmath.sin = cmath.acos + +Return the sine of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_sin__doc__, +"sig=($module, z)\n" +"Return the sine of z."); + +#define CMATH_SIN_METHODDEF \ + {"sin", (PyCFunction)cmath_sin, METH_VARARGS, cmath_sin__doc__}, static Py_complex -c_sin(Py_complex z) +cmath_sin_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_sin(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:sin", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_sin_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_sin_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=964807bf6ca40dcb input=2d3519842a8b4b85]*/ { /* sin(z) = -i sin(iz) */ Py_complex s, r; s.real = -z.imag; s.imag = z.real; - s = c_sinh(s); + s = cmath_sinh_impl(module, s); r.real = s.imag; r.imag = -s.real; return r; } -PyDoc_STRVAR(c_sin_doc, -"sin(x)\n" -"\n" -"Return the sine of x."); - /* sinh(infinity + i*y) needs to be dealt with specially */ static Py_complex sinh_special_values[7][7]; +/*[clinic input] +cmath.sinh = cmath.acos + +Return the hyperbolic sine of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_sinh__doc__, +"sig=($module, z)\n" +"Return the hyperbolic sine of z."); + +#define CMATH_SINH_METHODDEF \ + {"sinh", (PyCFunction)cmath_sinh, METH_VARARGS, cmath_sinh__doc__}, + static Py_complex -c_sinh(Py_complex z) +cmath_sinh_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_sinh(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:sinh", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_sinh_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_sinh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=40e5eeeb6ccc079c input=d2d3fc8c1ddfd2dd]*/ { Py_complex r; double x_minus_one; @@ -655,16 +1210,59 @@ return r; } -PyDoc_STRVAR(c_sinh_doc, -"sinh(x)\n" -"\n" -"Return the hyperbolic sine of x."); - static Py_complex sqrt_special_values[7][7]; +/*[clinic input] +cmath.sqrt = cmath.acos + +Return the square root of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_sqrt__doc__, +"sig=($module, z)\n" +"Return the square root of z."); + +#define CMATH_SQRT_METHODDEF \ + {"sqrt", (PyCFunction)cmath_sqrt, METH_VARARGS, cmath_sqrt__doc__}, + static Py_complex -c_sqrt(Py_complex z) +cmath_sqrt_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_sqrt(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:sqrt", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_sqrt_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_sqrt_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=bdfada8afa0c0b66 input=7088b166fc9a58c7]*/ { /* Method: use symmetries to reduce to the case when x = z.real and y @@ -730,36 +1328,122 @@ return r; } -PyDoc_STRVAR(c_sqrt_doc, -"sqrt(x)\n" -"\n" -"Return the square root of x."); +/*[clinic input] +cmath.tan = cmath.acos + +Return the tangent of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_tan__doc__, +"sig=($module, z)\n" +"Return the tangent of z."); + +#define CMATH_TAN_METHODDEF \ + {"tan", (PyCFunction)cmath_tan, METH_VARARGS, cmath_tan__doc__}, static Py_complex -c_tan(Py_complex z) +cmath_tan_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_tan(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:tan", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_tan_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_tan_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=0f8d230fbae771e3 input=fc167e528767888e]*/ { /* tan(z) = -i tanh(iz) */ Py_complex s, r; s.real = -z.imag; s.imag = z.real; - s = c_tanh(s); + s = cmath_tanh_impl(module, s); r.real = s.imag; r.imag = -s.real; return r; } -PyDoc_STRVAR(c_tan_doc, -"tan(x)\n" -"\n" -"Return the tangent of x."); - /* tanh(infinity + i*y) needs to be dealt with specially */ static Py_complex tanh_special_values[7][7]; +/*[clinic input] +cmath.tanh = cmath.acos + +Return the hyperbolic tangent of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_tanh__doc__, +"sig=($module, z)\n" +"Return the hyperbolic tangent of z."); + +#define CMATH_TANH_METHODDEF \ + {"tanh", (PyCFunction)cmath_tanh, METH_VARARGS, cmath_tanh__doc__}, + static Py_complex -c_tanh(Py_complex z) +cmath_tanh_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_tanh(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + Py_complex z; + Py_complex _return_value; + + if (!PyArg_ParseTuple(args, + "D:tanh", + &z)) + goto exit; + /* modifications for z */ + errno = 0; PyFPE_START_PROTECT("complex function", goto exit); + _return_value = cmath_tanh_impl(module, z); + PyFPE_END_PROTECT(_return_value); + if (errno == EDOM) { + PyErr_SetString(PyExc_ValueError, "math domain error"); + goto exit; + } + else if (errno == ERANGE) { + PyErr_SetString(PyExc_OverflowError, "math range error"); + goto exit; + } + else { + return_value = PyComplex_FromCComplex(_return_value); + } + +exit: + return return_value; +} + +static Py_complex +cmath_tanh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=48e54f7da24f72eb input=22f67f9dc6d29685]*/ { /* Formula: @@ -822,25 +1506,62 @@ return r; } -PyDoc_STRVAR(c_tanh_doc, -"tanh(x)\n" + +/*[clinic input] +cmath.log + + x: Py_complex + y_obj: object = NULL + / + +The logarithm of z to the given base. + +If the base not specified, returns the natural logarithm (base e) of z. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_log__doc__, +"sig=($module, x, y_obj=None)\n" +"The logarithm of z to the given base.\n" "\n" -"Return the hyperbolic tangent of x."); +"If the base not specified, returns the natural logarithm (base e) of z."); +#define CMATH_LOG_METHODDEF \ + {"log", (PyCFunction)cmath_log, METH_VARARGS, cmath_log__doc__}, static PyObject * -cmath_log(PyObject *self, PyObject *args) +cmath_log_impl(PyModuleDef *module, Py_complex x, PyObject *y_obj); + +static PyObject * +cmath_log(PyModuleDef *module, PyObject *args) { + PyObject *return_value = NULL; Py_complex x; + PyObject *y_obj = NULL; + + if (!PyArg_ParseTuple(args, + "D|O:log", + &x, &y_obj)) + goto exit; + return_value = cmath_log_impl(module, x, y_obj); + +exit: + return return_value; +} + +static PyObject * +cmath_log_impl(PyModuleDef *module, Py_complex x, PyObject *y_obj) +/*[clinic end generated code: output=fd50458f51f64649 input=ee0e823a7c6e68ea]*/ +{ Py_complex y; - if (!PyArg_ParseTuple(args, "D|D", &x, &y)) - return NULL; - errno = 0; PyFPE_START_PROTECT("complex function", return 0) x = c_log(x); - if (PyTuple_GET_SIZE(args) == 2) { + if (y_obj != NULL) { + y = PyComplex_AsCComplex(y_obj); + if (PyErr_Occurred()) { + return NULL; + } y = c_log(y); x = c_quot(x, y); } @@ -850,10 +1571,6 @@ return PyComplex_FromCComplex(x); } -PyDoc_STRVAR(cmath_log_doc, -"log(x[, base]) -> the logarithm of x to the given base.\n\ -If the base not specified, returns the natural logarithm (base e) of x."); - /* And now the glue to make them available from Python: */ @@ -869,57 +1586,48 @@ return NULL; } + +/*[clinic input] +cmath.phase + + z: Py_complex + / + +Return argument, also known as the phase angle, of a complex. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_phase__doc__, +"sig=($module, z)\n" +"Return argument, also known as the phase angle, of a complex."); + +#define CMATH_PHASE_METHODDEF \ + {"phase", (PyCFunction)cmath_phase, METH_VARARGS, cmath_phase__doc__}, + static PyObject * -math_1(PyObject *args, Py_complex (*func)(Py_complex)) +cmath_phase_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_phase(PyModuleDef *module, PyObject *args) { - Py_complex x,r ; - if (!PyArg_ParseTuple(args, "D", &x)) - return NULL; - errno = 0; - PyFPE_START_PROTECT("complex function", return 0); - r = (*func)(x); - PyFPE_END_PROTECT(r); - if (errno == EDOM) { - PyErr_SetString(PyExc_ValueError, "math domain error"); - return NULL; - } - else if (errno == ERANGE) { - PyErr_SetString(PyExc_OverflowError, "math range error"); - return NULL; - } - else { - return PyComplex_FromCComplex(r); - } + PyObject *return_value = NULL; + Py_complex z; + + if (!PyArg_ParseTuple(args, + "D:phase", + &z)) + goto exit; + return_value = cmath_phase_impl(module, z); + +exit: + return return_value; } -#define FUNC1(stubname, func) \ - static PyObject * stubname(PyObject *self, PyObject *args) { \ - return math_1(args, func); \ - } +static PyObject * +cmath_phase_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=01d87a239d1176df input=5cf75228ba94b69d]*/ +{ + double phi; -FUNC1(cmath_acos, c_acos) -FUNC1(cmath_acosh, c_acosh) -FUNC1(cmath_asin, c_asin) -FUNC1(cmath_asinh, c_asinh) -FUNC1(cmath_atan, c_atan) -FUNC1(cmath_atanh, c_atanh) -FUNC1(cmath_cos, c_cos) -FUNC1(cmath_cosh, c_cosh) -FUNC1(cmath_exp, c_exp) -FUNC1(cmath_log10, c_log10) -FUNC1(cmath_sin, c_sin) -FUNC1(cmath_sinh, c_sinh) -FUNC1(cmath_sqrt, c_sqrt) -FUNC1(cmath_tan, c_tan) -FUNC1(cmath_tanh, c_tanh) - -static PyObject * -cmath_phase(PyObject *self, PyObject *args) -{ - Py_complex z; - double phi; - if (!PyArg_ParseTuple(args, "D:phase", &z)) - return NULL; errno = 0; PyFPE_START_PROTECT("arg function", return 0) phi = c_atan2(z); @@ -930,17 +1638,51 @@ return PyFloat_FromDouble(phi); } -PyDoc_STRVAR(cmath_phase_doc, -"phase(z) -> float\n\n\ -Return argument, also known as the phase angle, of a complex."); +/*[clinic input] +cmath.polar + + z: Py_complex + / + +Convert a complex from rectangular coordinates to polar coordinates. + +r is the distance from 0 and phi the phase angle. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_polar__doc__, +"sig=($module, z)\n" +"Convert a complex from rectangular coordinates to polar coordinates.\n" +"\n" +"r is the distance from 0 and phi the phase angle."); + +#define CMATH_POLAR_METHODDEF \ + {"polar", (PyCFunction)cmath_polar, METH_VARARGS, cmath_polar__doc__}, static PyObject * -cmath_polar(PyObject *self, PyObject *args) +cmath_polar_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_polar(PyModuleDef *module, PyObject *args) { + PyObject *return_value = NULL; Py_complex z; + + if (!PyArg_ParseTuple(args, + "D:polar", + &z)) + goto exit; + return_value = cmath_polar_impl(module, z); + +exit: + return return_value; +} + +static PyObject * +cmath_polar_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=b77118cb5c93eb41 input=26c353574fd1a861]*/ +{ double r, phi; - if (!PyArg_ParseTuple(args, "D:polar", &z)) - return NULL; + PyFPE_START_PROTECT("polar function", return 0) phi = c_atan2(z); /* should not cause any exception */ r = c_abs(z); /* sets errno to ERANGE on overflow; otherwise 0 */ @@ -951,11 +1693,6 @@ return Py_BuildValue("dd", r, phi); } -PyDoc_STRVAR(cmath_polar_doc, -"polar(z) -> r: float, phi: float\n\n\ -Convert a complex from rectangular coordinates to polar coordinates. r is\n\ -the distance from 0 and phi the phase angle."); - /* rect() isn't covered by the C99 standard, but it's not too hard to figure out 'spirit of C99' rules for special value handing: @@ -969,13 +1706,48 @@ static Py_complex rect_special_values[7][7]; +/*[clinic input] +cmath.rect + + r: double + phi: double + / + +Convert from polar coordinates to rectangular coordinates. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_rect__doc__, +"sig=($module, r, phi)\n" +"Convert from polar coordinates to rectangular coordinates."); + +#define CMATH_RECT_METHODDEF \ + {"rect", (PyCFunction)cmath_rect, METH_VARARGS, cmath_rect__doc__}, + static PyObject * -cmath_rect(PyObject *self, PyObject *args) +cmath_rect_impl(PyModuleDef *module, double r, double phi); + +static PyObject * +cmath_rect(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + double r; + double phi; + + if (!PyArg_ParseTuple(args, + "dd:rect", + &r, &phi)) + goto exit; + return_value = cmath_rect_impl(module, r, phi); + +exit: + return return_value; +} + +static PyObject * +cmath_rect_impl(PyModuleDef *module, double r, double phi) +/*[clinic end generated code: output=1ac78c6fe2157971 input=24c5646d147efd69]*/ { Py_complex z; - double r, phi; - if (!PyArg_ParseTuple(args, "dd:rect", &r, &phi)) - return NULL; errno = 0; PyFPE_START_PROTECT("rect function", return 0) @@ -1026,79 +1798,153 @@ return PyComplex_FromCComplex(z); } -PyDoc_STRVAR(cmath_rect_doc, -"rect(r, phi) -> z: complex\n\n\ -Convert from polar coordinates to rectangular coordinates."); +/*[clinic input] +cmath.isfinite = cmath.polar + +Return True if both the real and imaginary parts of z are finite, else False. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_isfinite__doc__, +"sig=($module, z)\n" +"Return True if both the real and imaginary parts of z are finite, else False."); + +#define CMATH_ISFINITE_METHODDEF \ + {"isfinite", (PyCFunction)cmath_isfinite, METH_VARARGS, cmath_isfinite__doc__}, static PyObject * -cmath_isfinite(PyObject *self, PyObject *args) +cmath_isfinite_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_isfinite(PyModuleDef *module, PyObject *args) { + PyObject *return_value = NULL; Py_complex z; - if (!PyArg_ParseTuple(args, "D:isfinite", &z)) - return NULL; + + if (!PyArg_ParseTuple(args, + "D:isfinite", + &z)) + goto exit; + return_value = cmath_isfinite_impl(module, z); + +exit: + return return_value; +} + +static PyObject * +cmath_isfinite_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=af0bb950610b6a71 input=848e7ee701895815]*/ +{ return PyBool_FromLong(Py_IS_FINITE(z.real) && Py_IS_FINITE(z.imag)); } -PyDoc_STRVAR(cmath_isfinite_doc, -"isfinite(z) -> bool\n\ -Return True if both the real and imaginary parts of z are finite, else False."); +/*[clinic input] +cmath.isnan = cmath.polar + +Checks if the real or imaginary part of z not a number (NaN). +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_isnan__doc__, +"sig=($module, z)\n" +"Checks if the real or imaginary part of z not a number (NaN)."); + +#define CMATH_ISNAN_METHODDEF \ + {"isnan", (PyCFunction)cmath_isnan, METH_VARARGS, cmath_isnan__doc__}, static PyObject * -cmath_isnan(PyObject *self, PyObject *args) +cmath_isnan_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_isnan(PyModuleDef *module, PyObject *args) { + PyObject *return_value = NULL; Py_complex z; - if (!PyArg_ParseTuple(args, "D:isnan", &z)) - return NULL; + + if (!PyArg_ParseTuple(args, + "D:isnan", + &z)) + goto exit; + return_value = cmath_isnan_impl(module, z); + +exit: + return return_value; +} + +static PyObject * +cmath_isnan_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=b09a1f22933472a6 input=71799f5d284c9baf]*/ +{ return PyBool_FromLong(Py_IS_NAN(z.real) || Py_IS_NAN(z.imag)); } -PyDoc_STRVAR(cmath_isnan_doc, -"isnan(z) -> bool\n\ -Checks if the real or imaginary part of z not a number (NaN)"); +/*[clinic input] +cmath.isinf = cmath.polar + +Checks if the real or imaginary part of z is infinite. +[clinic start generated code]*/ + +PyDoc_STRVAR(cmath_isinf__doc__, +"sig=($module, z)\n" +"Checks if the real or imaginary part of z is infinite."); + +#define CMATH_ISINF_METHODDEF \ + {"isinf", (PyCFunction)cmath_isinf, METH_VARARGS, cmath_isinf__doc__}, static PyObject * -cmath_isinf(PyObject *self, PyObject *args) +cmath_isinf_impl(PyModuleDef *module, Py_complex z); + +static PyObject * +cmath_isinf(PyModuleDef *module, PyObject *args) { + PyObject *return_value = NULL; Py_complex z; - if (!PyArg_ParseTuple(args, "D:isinf", &z)) - return NULL; + + if (!PyArg_ParseTuple(args, + "D:isinf", + &z)) + goto exit; + return_value = cmath_isinf_impl(module, z); + +exit: + return return_value; +} + +static PyObject * +cmath_isinf_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=f69f4aa49f8fbf3b input=363df155c7181329]*/ +{ return PyBool_FromLong(Py_IS_INFINITY(z.real) || Py_IS_INFINITY(z.imag)); } -PyDoc_STRVAR(cmath_isinf_doc, -"isinf(z) -> bool\n\ -Checks if the real or imaginary part of z is infinite."); - PyDoc_STRVAR(module_doc, "This module is always available. It provides access to mathematical\n" "functions for complex numbers."); static PyMethodDef cmath_methods[] = { - {"acos", cmath_acos, METH_VARARGS, c_acos_doc}, - {"acosh", cmath_acosh, METH_VARARGS, c_acosh_doc}, - {"asin", cmath_asin, METH_VARARGS, c_asin_doc}, - {"asinh", cmath_asinh, METH_VARARGS, c_asinh_doc}, - {"atan", cmath_atan, METH_VARARGS, c_atan_doc}, - {"atanh", cmath_atanh, METH_VARARGS, c_atanh_doc}, - {"cos", cmath_cos, METH_VARARGS, c_cos_doc}, - {"cosh", cmath_cosh, METH_VARARGS, c_cosh_doc}, - {"exp", cmath_exp, METH_VARARGS, c_exp_doc}, - {"isfinite", cmath_isfinite, METH_VARARGS, cmath_isfinite_doc}, - {"isinf", cmath_isinf, METH_VARARGS, cmath_isinf_doc}, - {"isnan", cmath_isnan, METH_VARARGS, cmath_isnan_doc}, - {"log", cmath_log, METH_VARARGS, cmath_log_doc}, - {"log10", cmath_log10, METH_VARARGS, c_log10_doc}, - {"phase", cmath_phase, METH_VARARGS, cmath_phase_doc}, - {"polar", cmath_polar, METH_VARARGS, cmath_polar_doc}, - {"rect", cmath_rect, METH_VARARGS, cmath_rect_doc}, - {"sin", cmath_sin, METH_VARARGS, c_sin_doc}, - {"sinh", cmath_sinh, METH_VARARGS, c_sinh_doc}, - {"sqrt", cmath_sqrt, METH_VARARGS, c_sqrt_doc}, - {"tan", cmath_tan, METH_VARARGS, c_tan_doc}, - {"tanh", cmath_tanh, METH_VARARGS, c_tanh_doc}, - {NULL, NULL} /* sentinel */ + CMATH_ACOS_METHODDEF + CMATH_ACOSH_METHODDEF + CMATH_ASIN_METHODDEF + CMATH_ASINH_METHODDEF + CMATH_ATAN_METHODDEF + CMATH_ATANH_METHODDEF + CMATH_COS_METHODDEF + CMATH_COSH_METHODDEF + CMATH_EXP_METHODDEF + CMATH_ISFINITE_METHODDEF + CMATH_ISINF_METHODDEF + CMATH_ISNAN_METHODDEF + CMATH_LOG_METHODDEF + CMATH_LOG10_METHODDEF + CMATH_PHASE_METHODDEF + CMATH_POLAR_METHODDEF + CMATH_RECT_METHODDEF + CMATH_SIN_METHODDEF + CMATH_SINH_METHODDEF + CMATH_SQRT_METHODDEF + CMATH_TAN_METHODDEF + CMATH_TANH_METHODDEF + {NULL, NULL} /* sentinel */ };