diff options
Diffstat (limited to 'Modules/cmathmodule.c')
| -rw-r--r-- | Modules/cmathmodule.c | 558 | 
1 files changed, 335 insertions, 223 deletions
| diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c index b341c343e1..7f6c2c9df4 100644 --- a/Modules/cmathmodule.c +++ b/Modules/cmathmodule.c @@ -8,6 +8,40 @@     float.h.  We assume that FLT_RADIX is either 2 or 16. */  #include <float.h> +#include "clinic/cmathmodule.c.h" +/*[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 +82,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 +157,18 @@ special_type(double d)  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]*/ +  static Py_complex -c_acos(Py_complex z) +cmath_acos_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=7c1dd21ff818db6b input=bd6cbd78ae851927]*/  {      Py_complex s1, s2, r; @@ -145,10 +189,10 @@ c_acos(Py_complex z)      } 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 +200,18 @@ c_acos(Py_complex z)      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 inverse hyperbolic cosine of z. +[clinic start generated code]*/ +  static Py_complex -c_acosh(Py_complex z) +cmath_acosh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=c23c776429def981 input=3f61bee7d703e53c]*/  {      Py_complex s1, s2, r; @@ -178,10 +224,10 @@ c_acosh(Py_complex z)      } 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 +235,38 @@ c_acosh(Py_complex z)      return r;  } -PyDoc_STRVAR(c_acosh_doc, -"acosh(x)\n" -"\n" -"Return the inverse hyperbolic cosine of x."); +/*[clinic input] +cmath.asin = cmath.acos +Return the arc sine of z. +[clinic start generated code]*/  static Py_complex -c_asin(Py_complex z) +cmath_asin_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=42d2346d46690826 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 inverse hyperbolic sine of z. +[clinic start generated code]*/ +  static Py_complex -c_asinh(Py_complex z) +cmath_asinh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=0c6664823c7b1b35 input=5c09448fcfc89a79]*/  {      Py_complex s1, s2, r; @@ -235,10 +284,10 @@ c_asinh(Py_complex z)      } 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 +295,22 @@ c_asinh(Py_complex z)      return r;  } -PyDoc_STRVAR(c_asinh_doc, -"asinh(x)\n" -"\n" -"Return the inverse hyperbolic sine of x."); +/*[clinic input] +cmath.atan = cmath.acos + +Return the arc tangent of z. +[clinic start generated code]*/  static Py_complex -c_atan(Py_complex z) +cmath_atan_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=b7d44f02c6a5c3b5 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 +346,18 @@ c_atan2(Py_complex z)      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 inverse hyperbolic tangent of z. +[clinic start generated code]*/ +  static Py_complex -c_atanh(Py_complex z) +cmath_atanh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=279e0b9fefc8da7c input=2b3fdb82fb34487b]*/  {      Py_complex r;      double ay, h; @@ -313,7 +366,7 @@ c_atanh(Py_complex z)      /* 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 _Py_c_neg(cmath_atanh_impl(module, _Py_c_neg(z)));      }      ay = fabs(z.imag); @@ -350,34 +403,38 @@ c_atanh(Py_complex z)      return r;  } -PyDoc_STRVAR(c_atanh_doc, -"atanh(x)\n" -"\n" -"Return the inverse hyperbolic tangent of x."); +/*[clinic input] +cmath.cos = cmath.acos + +Return the cosine of z. +[clinic start generated code]*/  static Py_complex -c_cos(Py_complex z) +cmath_cos_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=9d1cdc1b5e761667 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]*/ +  static Py_complex -c_cosh(Py_complex z) +cmath_cosh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=f3b5d3282b3024d3 input=d6b66339e9cc332b]*/  {      Py_complex r;      double x_minus_one; @@ -426,18 +483,20 @@ c_cosh(Py_complex z)      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]*/ +  static Py_complex -c_exp(Py_complex z) +cmath_exp_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=6f8825eb2bcad9ba input=8b9e6cf8a92174c3]*/  {      Py_complex r;      double l; @@ -486,12 +545,6 @@ c_exp(Py_complex z)      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 +617,15 @@ c_log(Py_complex z)  } +/*[clinic input] +cmath.log10 = cmath.acos + +Return the base-10 logarithm of z. +[clinic start generated code]*/ +  static Py_complex -c_log10(Py_complex z) +cmath_log10_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=c7c426ca0e782341 input=cff5644f73c1519c]*/  {      Py_complex r;      int errno_save; @@ -578,36 +638,40 @@ c_log10(Py_complex z)      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]*/  static Py_complex -c_sin(Py_complex z) +cmath_sin_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=e7f5e2b253825ac7 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]*/ +  static Py_complex -c_sinh(Py_complex z) +cmath_sinh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=d71fff8298043a95 input=d2d3fc8c1ddfd2dd]*/  {      Py_complex r;      double x_minus_one; @@ -655,16 +719,18 @@ c_sinh(Py_complex z)      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]*/ +  static Py_complex -c_sqrt(Py_complex z) +cmath_sqrt_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=b6bda283d0c5a7b4 input=7088b166fc9a58c7]*/  {      /*         Method: use symmetries to reduce to the case when x = z.real and y @@ -730,36 +796,40 @@ c_sqrt(Py_complex z)      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]*/  static Py_complex -c_tan(Py_complex z) +cmath_tan_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=df374bacf36d99b4 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]*/ +  static Py_complex -c_tanh(Py_complex z) +cmath_tanh_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=f578773d27a18e96 input=22f67f9dc6d29685]*/  {      /* Formula: @@ -822,27 +892,35 @@ c_tanh(Py_complex z)      return r;  } -PyDoc_STRVAR(c_tanh_doc, -"tanh(x)\n" -"\n" -"Return the hyperbolic tangent of x."); +/*[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]*/  static PyObject * -cmath_log(PyObject *self, PyObject *args) +cmath_log_impl(PyModuleDef *module, Py_complex x, PyObject *y_obj) +/*[clinic end generated code: output=35e2a1e5229b5a46 input=ee0e823a7c6e68ea]*/  { -    Py_complex x;      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); +        x = _Py_c_quot(x, y);      }      PyFPE_END_PROTECT(x)      if (errno != 0) @@ -850,10 +928,6 @@ cmath_log(PyObject *self, PyObject *args)      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 +943,22 @@ math_error(void)      return NULL;  } -static PyObject * -math_1(PyObject *args, Py_complex (*func)(Py_complex)) -{ -    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); -    } -} -#define FUNC1(stubname, func) \ -    static PyObject * stubname(PyObject *self, PyObject *args) { \ -        return math_1(args, func); \ -    } +/*[clinic input] +cmath.phase + +    z: Py_complex +    / -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) +Return argument, also known as the phase angle, of a complex. +[clinic start generated code]*/  static PyObject * -cmath_phase(PyObject *self, PyObject *args) +cmath_phase_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=e09eaf373cb624c3 input=5cf75228ba94b69d]*/  { -    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,21 +969,27 @@ cmath_phase(PyObject *self, PyObject *args)          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]*/  static PyObject * -cmath_polar(PyObject *self, PyObject *args) +cmath_polar_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=07d41b16c877875a input=26c353574fd1a861]*/  { -    Py_complex z;      double r, phi; -    if (!PyArg_ParseTuple(args, "D:polar", &z)) -        return NULL; +      errno = 0;      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 */ +    r = _Py_c_abs(z); /* sets errno to ERANGE on overflow */      PyFPE_END_PROTECT(r)      if (errno != 0)          return math_error(); @@ -952,11 +997,6 @@ cmath_polar(PyObject *self, PyObject *args)          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: @@ -970,13 +1010,21 @@ the distance from 0 and phi the phase angle.");  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]*/ +  static PyObject * -cmath_rect(PyObject *self, PyObject *args) +cmath_rect_impl(PyModuleDef *module, double r, double phi) +/*[clinic end generated code: output=d97a8749bd63e9d5 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) @@ -1027,79 +1075,143 @@ cmath_rect(PyObject *self, PyObject *args)          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]*/  static PyObject * -cmath_isfinite(PyObject *self, PyObject *args) +cmath_isfinite_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=8f6682fa93de45d6 input=848e7ee701895815]*/  { -    Py_complex z; -    if (!PyArg_ParseTuple(args, "D:isfinite", &z)) -        return NULL;      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]*/  static PyObject * -cmath_isnan(PyObject *self, PyObject *args) +cmath_isnan_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=b85fe8c2047718ee input=71799f5d284c9baf]*/  { -    Py_complex z; -    if (!PyArg_ParseTuple(args, "D:isnan", &z)) -        return NULL;      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]*/  static PyObject * -cmath_isinf(PyObject *self, PyObject *args) +cmath_isinf_impl(PyModuleDef *module, Py_complex z) +/*[clinic end generated code: output=8ca9c6109e468bf4 input=363df155c7181329]*/  { -    Py_complex z; -    if (!PyArg_ParseTuple(args, "D:isinf", &z)) -        return NULL;      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."); +/*[clinic input] +cmath.isclose -> bool + +    a: Py_complex +    b: Py_complex +    * +    rel_tol: double = 1e-09 +        maximum difference for being considered "close", relative to the +        magnitude of the input values +    abs_tol: double = 0.0 +        maximum difference for being considered "close", regardless of the +        magnitude of the input values + +Determine whether two complex numbers are close in value. +Return True if a is close in value to b, and False otherwise. + +For the values to be considered close, the difference between them must be +smaller than at least one of the tolerances. + +-inf, inf and NaN behave similarly to the IEEE 754 Standard. That is, NaN is +not close to anything, even itself. inf and -inf are only close to themselves. +[clinic start generated code]*/ + +static int +cmath_isclose_impl(PyModuleDef *module, Py_complex a, Py_complex b, +                   double rel_tol, double abs_tol) +/*[clinic end generated code: output=da0c535fb54e2310 input=df9636d7de1d4ac3]*/ +{ +    double diff; + +    /* sanity check on the inputs */ +    if (rel_tol < 0.0 || abs_tol < 0.0 ) { +        PyErr_SetString(PyExc_ValueError, +                        "tolerances must be non-negative"); +        return -1; +    } + +    if ( (a.real == b.real) && (a.imag == b.imag) ) { +        /* short circuit exact equality -- needed to catch two infinities of +           the same sign. And perhaps speeds things up a bit sometimes. +        */ +        return 1; +    } + +    /* This catches the case of two infinities of opposite sign, or +       one infinity and one finite number. Two infinities of opposite +       sign would otherwise have an infinite relative tolerance. +       Two infinities of the same sign are caught by the equality check +       above. +    */ + +    if (Py_IS_INFINITY(a.real) || Py_IS_INFINITY(a.imag) || +        Py_IS_INFINITY(b.real) || Py_IS_INFINITY(b.imag)) { +        return 0; +    } + +    /* now do the regular computation +       this is essentially the "weak" test from the Boost library +    */ + +    diff = _Py_c_abs(_Py_c_diff(a, b)); + +    return (((diff <= rel_tol * _Py_c_abs(b)) || +             (diff <= rel_tol * _Py_c_abs(a))) || +            (diff <= abs_tol)); +}  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_ISCLOSE_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 */  }; | 
