• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*[clinic input]
2 preserve
3 [clinic start generated code]*/
4 
5 #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
6 #  include "pycore_gc.h"          // PyGC_Head
7 #  include "pycore_runtime.h"     // _Py_ID()
8 #endif
9 #include "pycore_modsupport.h"    // _PyArg_CheckPositional()
10 
11 PyDoc_STRVAR(math_ceil__doc__,
12 "ceil($module, x, /)\n"
13 "--\n"
14 "\n"
15 "Return the ceiling of x as an Integral.\n"
16 "\n"
17 "This is the smallest integer >= x.");
18 
19 #define MATH_CEIL_METHODDEF    \
20     {"ceil", (PyCFunction)math_ceil, METH_O, math_ceil__doc__},
21 
22 PyDoc_STRVAR(math_floor__doc__,
23 "floor($module, x, /)\n"
24 "--\n"
25 "\n"
26 "Return the floor of x as an Integral.\n"
27 "\n"
28 "This is the largest integer <= x.");
29 
30 #define MATH_FLOOR_METHODDEF    \
31     {"floor", (PyCFunction)math_floor, METH_O, math_floor__doc__},
32 
33 PyDoc_STRVAR(math_fsum__doc__,
34 "fsum($module, seq, /)\n"
35 "--\n"
36 "\n"
37 "Return an accurate floating-point sum of values in the iterable seq.\n"
38 "\n"
39 "Assumes IEEE-754 floating-point arithmetic.");
40 
41 #define MATH_FSUM_METHODDEF    \
42     {"fsum", (PyCFunction)math_fsum, METH_O, math_fsum__doc__},
43 
44 PyDoc_STRVAR(math_isqrt__doc__,
45 "isqrt($module, n, /)\n"
46 "--\n"
47 "\n"
48 "Return the integer part of the square root of the input.");
49 
50 #define MATH_ISQRT_METHODDEF    \
51     {"isqrt", (PyCFunction)math_isqrt, METH_O, math_isqrt__doc__},
52 
53 PyDoc_STRVAR(math_factorial__doc__,
54 "factorial($module, n, /)\n"
55 "--\n"
56 "\n"
57 "Find n!.\n"
58 "\n"
59 "Raise a ValueError if x is negative or non-integral.");
60 
61 #define MATH_FACTORIAL_METHODDEF    \
62     {"factorial", (PyCFunction)math_factorial, METH_O, math_factorial__doc__},
63 
64 PyDoc_STRVAR(math_trunc__doc__,
65 "trunc($module, x, /)\n"
66 "--\n"
67 "\n"
68 "Truncates the Real x to the nearest Integral toward 0.\n"
69 "\n"
70 "Uses the __trunc__ magic method.");
71 
72 #define MATH_TRUNC_METHODDEF    \
73     {"trunc", (PyCFunction)math_trunc, METH_O, math_trunc__doc__},
74 
75 PyDoc_STRVAR(math_frexp__doc__,
76 "frexp($module, x, /)\n"
77 "--\n"
78 "\n"
79 "Return the mantissa and exponent of x, as pair (m, e).\n"
80 "\n"
81 "m is a float and e is an int, such that x = m * 2.**e.\n"
82 "If x is 0, m and e are both 0.  Else 0.5 <= abs(m) < 1.0.");
83 
84 #define MATH_FREXP_METHODDEF    \
85     {"frexp", (PyCFunction)math_frexp, METH_O, math_frexp__doc__},
86 
87 static PyObject *
88 math_frexp_impl(PyObject *module, double x);
89 
90 static PyObject *
math_frexp(PyObject * module,PyObject * arg)91 math_frexp(PyObject *module, PyObject *arg)
92 {
93     PyObject *return_value = NULL;
94     double x;
95 
96     if (PyFloat_CheckExact(arg)) {
97         x = PyFloat_AS_DOUBLE(arg);
98     }
99     else
100     {
101         x = PyFloat_AsDouble(arg);
102         if (x == -1.0 && PyErr_Occurred()) {
103             goto exit;
104         }
105     }
106     return_value = math_frexp_impl(module, x);
107 
108 exit:
109     return return_value;
110 }
111 
112 PyDoc_STRVAR(math_ldexp__doc__,
113 "ldexp($module, x, i, /)\n"
114 "--\n"
115 "\n"
116 "Return x * (2**i).\n"
117 "\n"
118 "This is essentially the inverse of frexp().");
119 
120 #define MATH_LDEXP_METHODDEF    \
121     {"ldexp", _PyCFunction_CAST(math_ldexp), METH_FASTCALL, math_ldexp__doc__},
122 
123 static PyObject *
124 math_ldexp_impl(PyObject *module, double x, PyObject *i);
125 
126 static PyObject *
math_ldexp(PyObject * module,PyObject * const * args,Py_ssize_t nargs)127 math_ldexp(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
128 {
129     PyObject *return_value = NULL;
130     double x;
131     PyObject *i;
132 
133     if (!_PyArg_CheckPositional("ldexp", nargs, 2, 2)) {
134         goto exit;
135     }
136     if (PyFloat_CheckExact(args[0])) {
137         x = PyFloat_AS_DOUBLE(args[0]);
138     }
139     else
140     {
141         x = PyFloat_AsDouble(args[0]);
142         if (x == -1.0 && PyErr_Occurred()) {
143             goto exit;
144         }
145     }
146     i = args[1];
147     return_value = math_ldexp_impl(module, x, i);
148 
149 exit:
150     return return_value;
151 }
152 
153 PyDoc_STRVAR(math_modf__doc__,
154 "modf($module, x, /)\n"
155 "--\n"
156 "\n"
157 "Return the fractional and integer parts of x.\n"
158 "\n"
159 "Both results carry the sign of x and are floats.");
160 
161 #define MATH_MODF_METHODDEF    \
162     {"modf", (PyCFunction)math_modf, METH_O, math_modf__doc__},
163 
164 static PyObject *
165 math_modf_impl(PyObject *module, double x);
166 
167 static PyObject *
math_modf(PyObject * module,PyObject * arg)168 math_modf(PyObject *module, PyObject *arg)
169 {
170     PyObject *return_value = NULL;
171     double x;
172 
173     if (PyFloat_CheckExact(arg)) {
174         x = PyFloat_AS_DOUBLE(arg);
175     }
176     else
177     {
178         x = PyFloat_AsDouble(arg);
179         if (x == -1.0 && PyErr_Occurred()) {
180             goto exit;
181         }
182     }
183     return_value = math_modf_impl(module, x);
184 
185 exit:
186     return return_value;
187 }
188 
189 PyDoc_STRVAR(math_log2__doc__,
190 "log2($module, x, /)\n"
191 "--\n"
192 "\n"
193 "Return the base 2 logarithm of x.");
194 
195 #define MATH_LOG2_METHODDEF    \
196     {"log2", (PyCFunction)math_log2, METH_O, math_log2__doc__},
197 
198 PyDoc_STRVAR(math_log10__doc__,
199 "log10($module, x, /)\n"
200 "--\n"
201 "\n"
202 "Return the base 10 logarithm of x.");
203 
204 #define MATH_LOG10_METHODDEF    \
205     {"log10", (PyCFunction)math_log10, METH_O, math_log10__doc__},
206 
207 PyDoc_STRVAR(math_fma__doc__,
208 "fma($module, x, y, z, /)\n"
209 "--\n"
210 "\n"
211 "Fused multiply-add operation.\n"
212 "\n"
213 "Compute (x * y) + z with a single round.");
214 
215 #define MATH_FMA_METHODDEF    \
216     {"fma", _PyCFunction_CAST(math_fma), METH_FASTCALL, math_fma__doc__},
217 
218 static PyObject *
219 math_fma_impl(PyObject *module, double x, double y, double z);
220 
221 static PyObject *
math_fma(PyObject * module,PyObject * const * args,Py_ssize_t nargs)222 math_fma(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
223 {
224     PyObject *return_value = NULL;
225     double x;
226     double y;
227     double z;
228 
229     if (!_PyArg_CheckPositional("fma", nargs, 3, 3)) {
230         goto exit;
231     }
232     if (PyFloat_CheckExact(args[0])) {
233         x = PyFloat_AS_DOUBLE(args[0]);
234     }
235     else
236     {
237         x = PyFloat_AsDouble(args[0]);
238         if (x == -1.0 && PyErr_Occurred()) {
239             goto exit;
240         }
241     }
242     if (PyFloat_CheckExact(args[1])) {
243         y = PyFloat_AS_DOUBLE(args[1]);
244     }
245     else
246     {
247         y = PyFloat_AsDouble(args[1]);
248         if (y == -1.0 && PyErr_Occurred()) {
249             goto exit;
250         }
251     }
252     if (PyFloat_CheckExact(args[2])) {
253         z = PyFloat_AS_DOUBLE(args[2]);
254     }
255     else
256     {
257         z = PyFloat_AsDouble(args[2]);
258         if (z == -1.0 && PyErr_Occurred()) {
259             goto exit;
260         }
261     }
262     return_value = math_fma_impl(module, x, y, z);
263 
264 exit:
265     return return_value;
266 }
267 
268 PyDoc_STRVAR(math_fmod__doc__,
269 "fmod($module, x, y, /)\n"
270 "--\n"
271 "\n"
272 "Return fmod(x, y), according to platform C.\n"
273 "\n"
274 "x % y may differ.");
275 
276 #define MATH_FMOD_METHODDEF    \
277     {"fmod", _PyCFunction_CAST(math_fmod), METH_FASTCALL, math_fmod__doc__},
278 
279 static PyObject *
280 math_fmod_impl(PyObject *module, double x, double y);
281 
282 static PyObject *
math_fmod(PyObject * module,PyObject * const * args,Py_ssize_t nargs)283 math_fmod(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
284 {
285     PyObject *return_value = NULL;
286     double x;
287     double y;
288 
289     if (!_PyArg_CheckPositional("fmod", nargs, 2, 2)) {
290         goto exit;
291     }
292     if (PyFloat_CheckExact(args[0])) {
293         x = PyFloat_AS_DOUBLE(args[0]);
294     }
295     else
296     {
297         x = PyFloat_AsDouble(args[0]);
298         if (x == -1.0 && PyErr_Occurred()) {
299             goto exit;
300         }
301     }
302     if (PyFloat_CheckExact(args[1])) {
303         y = PyFloat_AS_DOUBLE(args[1]);
304     }
305     else
306     {
307         y = PyFloat_AsDouble(args[1]);
308         if (y == -1.0 && PyErr_Occurred()) {
309             goto exit;
310         }
311     }
312     return_value = math_fmod_impl(module, x, y);
313 
314 exit:
315     return return_value;
316 }
317 
318 PyDoc_STRVAR(math_dist__doc__,
319 "dist($module, p, q, /)\n"
320 "--\n"
321 "\n"
322 "Return the Euclidean distance between two points p and q.\n"
323 "\n"
324 "The points should be specified as sequences (or iterables) of\n"
325 "coordinates.  Both inputs must have the same dimension.\n"
326 "\n"
327 "Roughly equivalent to:\n"
328 "    sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))");
329 
330 #define MATH_DIST_METHODDEF    \
331     {"dist", _PyCFunction_CAST(math_dist), METH_FASTCALL, math_dist__doc__},
332 
333 static PyObject *
334 math_dist_impl(PyObject *module, PyObject *p, PyObject *q);
335 
336 static PyObject *
math_dist(PyObject * module,PyObject * const * args,Py_ssize_t nargs)337 math_dist(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
338 {
339     PyObject *return_value = NULL;
340     PyObject *p;
341     PyObject *q;
342 
343     if (!_PyArg_CheckPositional("dist", nargs, 2, 2)) {
344         goto exit;
345     }
346     p = args[0];
347     q = args[1];
348     return_value = math_dist_impl(module, p, q);
349 
350 exit:
351     return return_value;
352 }
353 
354 PyDoc_STRVAR(math_sumprod__doc__,
355 "sumprod($module, p, q, /)\n"
356 "--\n"
357 "\n"
358 "Return the sum of products of values from two iterables p and q.\n"
359 "\n"
360 "Roughly equivalent to:\n"
361 "\n"
362 "    sum(itertools.starmap(operator.mul, zip(p, q, strict=True)))\n"
363 "\n"
364 "For float and mixed int/float inputs, the intermediate products\n"
365 "and sums are computed with extended precision.");
366 
367 #define MATH_SUMPROD_METHODDEF    \
368     {"sumprod", _PyCFunction_CAST(math_sumprod), METH_FASTCALL, math_sumprod__doc__},
369 
370 static PyObject *
371 math_sumprod_impl(PyObject *module, PyObject *p, PyObject *q);
372 
373 static PyObject *
math_sumprod(PyObject * module,PyObject * const * args,Py_ssize_t nargs)374 math_sumprod(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
375 {
376     PyObject *return_value = NULL;
377     PyObject *p;
378     PyObject *q;
379 
380     if (!_PyArg_CheckPositional("sumprod", nargs, 2, 2)) {
381         goto exit;
382     }
383     p = args[0];
384     q = args[1];
385     return_value = math_sumprod_impl(module, p, q);
386 
387 exit:
388     return return_value;
389 }
390 
391 PyDoc_STRVAR(math_pow__doc__,
392 "pow($module, x, y, /)\n"
393 "--\n"
394 "\n"
395 "Return x**y (x to the power of y).");
396 
397 #define MATH_POW_METHODDEF    \
398     {"pow", _PyCFunction_CAST(math_pow), METH_FASTCALL, math_pow__doc__},
399 
400 static PyObject *
401 math_pow_impl(PyObject *module, double x, double y);
402 
403 static PyObject *
math_pow(PyObject * module,PyObject * const * args,Py_ssize_t nargs)404 math_pow(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
405 {
406     PyObject *return_value = NULL;
407     double x;
408     double y;
409 
410     if (!_PyArg_CheckPositional("pow", nargs, 2, 2)) {
411         goto exit;
412     }
413     if (PyFloat_CheckExact(args[0])) {
414         x = PyFloat_AS_DOUBLE(args[0]);
415     }
416     else
417     {
418         x = PyFloat_AsDouble(args[0]);
419         if (x == -1.0 && PyErr_Occurred()) {
420             goto exit;
421         }
422     }
423     if (PyFloat_CheckExact(args[1])) {
424         y = PyFloat_AS_DOUBLE(args[1]);
425     }
426     else
427     {
428         y = PyFloat_AsDouble(args[1]);
429         if (y == -1.0 && PyErr_Occurred()) {
430             goto exit;
431         }
432     }
433     return_value = math_pow_impl(module, x, y);
434 
435 exit:
436     return return_value;
437 }
438 
439 PyDoc_STRVAR(math_degrees__doc__,
440 "degrees($module, x, /)\n"
441 "--\n"
442 "\n"
443 "Convert angle x from radians to degrees.");
444 
445 #define MATH_DEGREES_METHODDEF    \
446     {"degrees", (PyCFunction)math_degrees, METH_O, math_degrees__doc__},
447 
448 static PyObject *
449 math_degrees_impl(PyObject *module, double x);
450 
451 static PyObject *
math_degrees(PyObject * module,PyObject * arg)452 math_degrees(PyObject *module, PyObject *arg)
453 {
454     PyObject *return_value = NULL;
455     double x;
456 
457     if (PyFloat_CheckExact(arg)) {
458         x = PyFloat_AS_DOUBLE(arg);
459     }
460     else
461     {
462         x = PyFloat_AsDouble(arg);
463         if (x == -1.0 && PyErr_Occurred()) {
464             goto exit;
465         }
466     }
467     return_value = math_degrees_impl(module, x);
468 
469 exit:
470     return return_value;
471 }
472 
473 PyDoc_STRVAR(math_radians__doc__,
474 "radians($module, x, /)\n"
475 "--\n"
476 "\n"
477 "Convert angle x from degrees to radians.");
478 
479 #define MATH_RADIANS_METHODDEF    \
480     {"radians", (PyCFunction)math_radians, METH_O, math_radians__doc__},
481 
482 static PyObject *
483 math_radians_impl(PyObject *module, double x);
484 
485 static PyObject *
math_radians(PyObject * module,PyObject * arg)486 math_radians(PyObject *module, PyObject *arg)
487 {
488     PyObject *return_value = NULL;
489     double x;
490 
491     if (PyFloat_CheckExact(arg)) {
492         x = PyFloat_AS_DOUBLE(arg);
493     }
494     else
495     {
496         x = PyFloat_AsDouble(arg);
497         if (x == -1.0 && PyErr_Occurred()) {
498             goto exit;
499         }
500     }
501     return_value = math_radians_impl(module, x);
502 
503 exit:
504     return return_value;
505 }
506 
507 PyDoc_STRVAR(math_isfinite__doc__,
508 "isfinite($module, x, /)\n"
509 "--\n"
510 "\n"
511 "Return True if x is neither an infinity nor a NaN, and False otherwise.");
512 
513 #define MATH_ISFINITE_METHODDEF    \
514     {"isfinite", (PyCFunction)math_isfinite, METH_O, math_isfinite__doc__},
515 
516 static PyObject *
517 math_isfinite_impl(PyObject *module, double x);
518 
519 static PyObject *
math_isfinite(PyObject * module,PyObject * arg)520 math_isfinite(PyObject *module, PyObject *arg)
521 {
522     PyObject *return_value = NULL;
523     double x;
524 
525     if (PyFloat_CheckExact(arg)) {
526         x = PyFloat_AS_DOUBLE(arg);
527     }
528     else
529     {
530         x = PyFloat_AsDouble(arg);
531         if (x == -1.0 && PyErr_Occurred()) {
532             goto exit;
533         }
534     }
535     return_value = math_isfinite_impl(module, x);
536 
537 exit:
538     return return_value;
539 }
540 
541 PyDoc_STRVAR(math_isnan__doc__,
542 "isnan($module, x, /)\n"
543 "--\n"
544 "\n"
545 "Return True if x is a NaN (not a number), and False otherwise.");
546 
547 #define MATH_ISNAN_METHODDEF    \
548     {"isnan", (PyCFunction)math_isnan, METH_O, math_isnan__doc__},
549 
550 static PyObject *
551 math_isnan_impl(PyObject *module, double x);
552 
553 static PyObject *
math_isnan(PyObject * module,PyObject * arg)554 math_isnan(PyObject *module, PyObject *arg)
555 {
556     PyObject *return_value = NULL;
557     double x;
558 
559     if (PyFloat_CheckExact(arg)) {
560         x = PyFloat_AS_DOUBLE(arg);
561     }
562     else
563     {
564         x = PyFloat_AsDouble(arg);
565         if (x == -1.0 && PyErr_Occurred()) {
566             goto exit;
567         }
568     }
569     return_value = math_isnan_impl(module, x);
570 
571 exit:
572     return return_value;
573 }
574 
575 PyDoc_STRVAR(math_isinf__doc__,
576 "isinf($module, x, /)\n"
577 "--\n"
578 "\n"
579 "Return True if x is a positive or negative infinity, and False otherwise.");
580 
581 #define MATH_ISINF_METHODDEF    \
582     {"isinf", (PyCFunction)math_isinf, METH_O, math_isinf__doc__},
583 
584 static PyObject *
585 math_isinf_impl(PyObject *module, double x);
586 
587 static PyObject *
math_isinf(PyObject * module,PyObject * arg)588 math_isinf(PyObject *module, PyObject *arg)
589 {
590     PyObject *return_value = NULL;
591     double x;
592 
593     if (PyFloat_CheckExact(arg)) {
594         x = PyFloat_AS_DOUBLE(arg);
595     }
596     else
597     {
598         x = PyFloat_AsDouble(arg);
599         if (x == -1.0 && PyErr_Occurred()) {
600             goto exit;
601         }
602     }
603     return_value = math_isinf_impl(module, x);
604 
605 exit:
606     return return_value;
607 }
608 
609 PyDoc_STRVAR(math_isclose__doc__,
610 "isclose($module, /, a, b, *, rel_tol=1e-09, abs_tol=0.0)\n"
611 "--\n"
612 "\n"
613 "Determine whether two floating-point numbers are close in value.\n"
614 "\n"
615 "  rel_tol\n"
616 "    maximum difference for being considered \"close\", relative to the\n"
617 "    magnitude of the input values\n"
618 "  abs_tol\n"
619 "    maximum difference for being considered \"close\", regardless of the\n"
620 "    magnitude of the input values\n"
621 "\n"
622 "Return True if a is close in value to b, and False otherwise.\n"
623 "\n"
624 "For the values to be considered close, the difference between them\n"
625 "must be smaller than at least one of the tolerances.\n"
626 "\n"
627 "-inf, inf and NaN behave similarly to the IEEE 754 Standard.  That\n"
628 "is, NaN is not close to anything, even itself.  inf and -inf are\n"
629 "only close to themselves.");
630 
631 #define MATH_ISCLOSE_METHODDEF    \
632     {"isclose", _PyCFunction_CAST(math_isclose), METH_FASTCALL|METH_KEYWORDS, math_isclose__doc__},
633 
634 static int
635 math_isclose_impl(PyObject *module, double a, double b, double rel_tol,
636                   double abs_tol);
637 
638 static PyObject *
math_isclose(PyObject * module,PyObject * const * args,Py_ssize_t nargs,PyObject * kwnames)639 math_isclose(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
640 {
641     PyObject *return_value = NULL;
642     #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
643 
644     #define NUM_KEYWORDS 4
645     static struct {
646         PyGC_Head _this_is_not_used;
647         PyObject_VAR_HEAD
648         PyObject *ob_item[NUM_KEYWORDS];
649     } _kwtuple = {
650         .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
651         .ob_item = { _Py_LATIN1_CHR('a'), _Py_LATIN1_CHR('b'), &_Py_ID(rel_tol), &_Py_ID(abs_tol), },
652     };
653     #undef NUM_KEYWORDS
654     #define KWTUPLE (&_kwtuple.ob_base.ob_base)
655 
656     #else  // !Py_BUILD_CORE
657     #  define KWTUPLE NULL
658     #endif  // !Py_BUILD_CORE
659 
660     static const char * const _keywords[] = {"a", "b", "rel_tol", "abs_tol", NULL};
661     static _PyArg_Parser _parser = {
662         .keywords = _keywords,
663         .fname = "isclose",
664         .kwtuple = KWTUPLE,
665     };
666     #undef KWTUPLE
667     PyObject *argsbuf[4];
668     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
669     double a;
670     double b;
671     double rel_tol = 1e-09;
672     double abs_tol = 0.0;
673     int _return_value;
674 
675     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
676     if (!args) {
677         goto exit;
678     }
679     if (PyFloat_CheckExact(args[0])) {
680         a = PyFloat_AS_DOUBLE(args[0]);
681     }
682     else
683     {
684         a = PyFloat_AsDouble(args[0]);
685         if (a == -1.0 && PyErr_Occurred()) {
686             goto exit;
687         }
688     }
689     if (PyFloat_CheckExact(args[1])) {
690         b = PyFloat_AS_DOUBLE(args[1]);
691     }
692     else
693     {
694         b = PyFloat_AsDouble(args[1]);
695         if (b == -1.0 && PyErr_Occurred()) {
696             goto exit;
697         }
698     }
699     if (!noptargs) {
700         goto skip_optional_kwonly;
701     }
702     if (args[2]) {
703         if (PyFloat_CheckExact(args[2])) {
704             rel_tol = PyFloat_AS_DOUBLE(args[2]);
705         }
706         else
707         {
708             rel_tol = PyFloat_AsDouble(args[2]);
709             if (rel_tol == -1.0 && PyErr_Occurred()) {
710                 goto exit;
711             }
712         }
713         if (!--noptargs) {
714             goto skip_optional_kwonly;
715         }
716     }
717     if (PyFloat_CheckExact(args[3])) {
718         abs_tol = PyFloat_AS_DOUBLE(args[3]);
719     }
720     else
721     {
722         abs_tol = PyFloat_AsDouble(args[3]);
723         if (abs_tol == -1.0 && PyErr_Occurred()) {
724             goto exit;
725         }
726     }
727 skip_optional_kwonly:
728     _return_value = math_isclose_impl(module, a, b, rel_tol, abs_tol);
729     if ((_return_value == -1) && PyErr_Occurred()) {
730         goto exit;
731     }
732     return_value = PyBool_FromLong((long)_return_value);
733 
734 exit:
735     return return_value;
736 }
737 
738 PyDoc_STRVAR(math_prod__doc__,
739 "prod($module, iterable, /, *, start=1)\n"
740 "--\n"
741 "\n"
742 "Calculate the product of all the elements in the input iterable.\n"
743 "\n"
744 "The default start value for the product is 1.\n"
745 "\n"
746 "When the iterable is empty, return the start value.  This function is\n"
747 "intended specifically for use with numeric values and may reject\n"
748 "non-numeric types.");
749 
750 #define MATH_PROD_METHODDEF    \
751     {"prod", _PyCFunction_CAST(math_prod), METH_FASTCALL|METH_KEYWORDS, math_prod__doc__},
752 
753 static PyObject *
754 math_prod_impl(PyObject *module, PyObject *iterable, PyObject *start);
755 
756 static PyObject *
math_prod(PyObject * module,PyObject * const * args,Py_ssize_t nargs,PyObject * kwnames)757 math_prod(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
758 {
759     PyObject *return_value = NULL;
760     #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
761 
762     #define NUM_KEYWORDS 1
763     static struct {
764         PyGC_Head _this_is_not_used;
765         PyObject_VAR_HEAD
766         PyObject *ob_item[NUM_KEYWORDS];
767     } _kwtuple = {
768         .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
769         .ob_item = { &_Py_ID(start), },
770     };
771     #undef NUM_KEYWORDS
772     #define KWTUPLE (&_kwtuple.ob_base.ob_base)
773 
774     #else  // !Py_BUILD_CORE
775     #  define KWTUPLE NULL
776     #endif  // !Py_BUILD_CORE
777 
778     static const char * const _keywords[] = {"", "start", NULL};
779     static _PyArg_Parser _parser = {
780         .keywords = _keywords,
781         .fname = "prod",
782         .kwtuple = KWTUPLE,
783     };
784     #undef KWTUPLE
785     PyObject *argsbuf[2];
786     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
787     PyObject *iterable;
788     PyObject *start = NULL;
789 
790     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
791     if (!args) {
792         goto exit;
793     }
794     iterable = args[0];
795     if (!noptargs) {
796         goto skip_optional_kwonly;
797     }
798     start = args[1];
799 skip_optional_kwonly:
800     return_value = math_prod_impl(module, iterable, start);
801 
802 exit:
803     return return_value;
804 }
805 
806 PyDoc_STRVAR(math_perm__doc__,
807 "perm($module, n, k=None, /)\n"
808 "--\n"
809 "\n"
810 "Number of ways to choose k items from n items without repetition and with order.\n"
811 "\n"
812 "Evaluates to n! / (n - k)! when k <= n and evaluates\n"
813 "to zero when k > n.\n"
814 "\n"
815 "If k is not specified or is None, then k defaults to n\n"
816 "and the function returns n!.\n"
817 "\n"
818 "Raises TypeError if either of the arguments are not integers.\n"
819 "Raises ValueError if either of the arguments are negative.");
820 
821 #define MATH_PERM_METHODDEF    \
822     {"perm", _PyCFunction_CAST(math_perm), METH_FASTCALL, math_perm__doc__},
823 
824 static PyObject *
825 math_perm_impl(PyObject *module, PyObject *n, PyObject *k);
826 
827 static PyObject *
math_perm(PyObject * module,PyObject * const * args,Py_ssize_t nargs)828 math_perm(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
829 {
830     PyObject *return_value = NULL;
831     PyObject *n;
832     PyObject *k = Py_None;
833 
834     if (!_PyArg_CheckPositional("perm", nargs, 1, 2)) {
835         goto exit;
836     }
837     n = args[0];
838     if (nargs < 2) {
839         goto skip_optional;
840     }
841     k = args[1];
842 skip_optional:
843     return_value = math_perm_impl(module, n, k);
844 
845 exit:
846     return return_value;
847 }
848 
849 PyDoc_STRVAR(math_comb__doc__,
850 "comb($module, n, k, /)\n"
851 "--\n"
852 "\n"
853 "Number of ways to choose k items from n items without repetition and without order.\n"
854 "\n"
855 "Evaluates to n! / (k! * (n - k)!) when k <= n and evaluates\n"
856 "to zero when k > n.\n"
857 "\n"
858 "Also called the binomial coefficient because it is equivalent\n"
859 "to the coefficient of k-th term in polynomial expansion of the\n"
860 "expression (1 + x)**n.\n"
861 "\n"
862 "Raises TypeError if either of the arguments are not integers.\n"
863 "Raises ValueError if either of the arguments are negative.");
864 
865 #define MATH_COMB_METHODDEF    \
866     {"comb", _PyCFunction_CAST(math_comb), METH_FASTCALL, math_comb__doc__},
867 
868 static PyObject *
869 math_comb_impl(PyObject *module, PyObject *n, PyObject *k);
870 
871 static PyObject *
math_comb(PyObject * module,PyObject * const * args,Py_ssize_t nargs)872 math_comb(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
873 {
874     PyObject *return_value = NULL;
875     PyObject *n;
876     PyObject *k;
877 
878     if (!_PyArg_CheckPositional("comb", nargs, 2, 2)) {
879         goto exit;
880     }
881     n = args[0];
882     k = args[1];
883     return_value = math_comb_impl(module, n, k);
884 
885 exit:
886     return return_value;
887 }
888 
889 PyDoc_STRVAR(math_nextafter__doc__,
890 "nextafter($module, x, y, /, *, steps=None)\n"
891 "--\n"
892 "\n"
893 "Return the floating-point value the given number of steps after x towards y.\n"
894 "\n"
895 "If steps is not specified or is None, it defaults to 1.\n"
896 "\n"
897 "Raises a TypeError, if x or y is not a double, or if steps is not an integer.\n"
898 "Raises ValueError if steps is negative.");
899 
900 #define MATH_NEXTAFTER_METHODDEF    \
901     {"nextafter", _PyCFunction_CAST(math_nextafter), METH_FASTCALL|METH_KEYWORDS, math_nextafter__doc__},
902 
903 static PyObject *
904 math_nextafter_impl(PyObject *module, double x, double y, PyObject *steps);
905 
906 static PyObject *
math_nextafter(PyObject * module,PyObject * const * args,Py_ssize_t nargs,PyObject * kwnames)907 math_nextafter(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
908 {
909     PyObject *return_value = NULL;
910     #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
911 
912     #define NUM_KEYWORDS 1
913     static struct {
914         PyGC_Head _this_is_not_used;
915         PyObject_VAR_HEAD
916         PyObject *ob_item[NUM_KEYWORDS];
917     } _kwtuple = {
918         .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
919         .ob_item = { &_Py_ID(steps), },
920     };
921     #undef NUM_KEYWORDS
922     #define KWTUPLE (&_kwtuple.ob_base.ob_base)
923 
924     #else  // !Py_BUILD_CORE
925     #  define KWTUPLE NULL
926     #endif  // !Py_BUILD_CORE
927 
928     static const char * const _keywords[] = {"", "", "steps", NULL};
929     static _PyArg_Parser _parser = {
930         .keywords = _keywords,
931         .fname = "nextafter",
932         .kwtuple = KWTUPLE,
933     };
934     #undef KWTUPLE
935     PyObject *argsbuf[3];
936     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
937     double x;
938     double y;
939     PyObject *steps = Py_None;
940 
941     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
942     if (!args) {
943         goto exit;
944     }
945     if (PyFloat_CheckExact(args[0])) {
946         x = PyFloat_AS_DOUBLE(args[0]);
947     }
948     else
949     {
950         x = PyFloat_AsDouble(args[0]);
951         if (x == -1.0 && PyErr_Occurred()) {
952             goto exit;
953         }
954     }
955     if (PyFloat_CheckExact(args[1])) {
956         y = PyFloat_AS_DOUBLE(args[1]);
957     }
958     else
959     {
960         y = PyFloat_AsDouble(args[1]);
961         if (y == -1.0 && PyErr_Occurred()) {
962             goto exit;
963         }
964     }
965     if (!noptargs) {
966         goto skip_optional_kwonly;
967     }
968     steps = args[2];
969 skip_optional_kwonly:
970     return_value = math_nextafter_impl(module, x, y, steps);
971 
972 exit:
973     return return_value;
974 }
975 
976 PyDoc_STRVAR(math_ulp__doc__,
977 "ulp($module, x, /)\n"
978 "--\n"
979 "\n"
980 "Return the value of the least significant bit of the float x.");
981 
982 #define MATH_ULP_METHODDEF    \
983     {"ulp", (PyCFunction)math_ulp, METH_O, math_ulp__doc__},
984 
985 static double
986 math_ulp_impl(PyObject *module, double x);
987 
988 static PyObject *
math_ulp(PyObject * module,PyObject * arg)989 math_ulp(PyObject *module, PyObject *arg)
990 {
991     PyObject *return_value = NULL;
992     double x;
993     double _return_value;
994 
995     if (PyFloat_CheckExact(arg)) {
996         x = PyFloat_AS_DOUBLE(arg);
997     }
998     else
999     {
1000         x = PyFloat_AsDouble(arg);
1001         if (x == -1.0 && PyErr_Occurred()) {
1002             goto exit;
1003         }
1004     }
1005     _return_value = math_ulp_impl(module, x);
1006     if ((_return_value == -1.0) && PyErr_Occurred()) {
1007         goto exit;
1008     }
1009     return_value = PyFloat_FromDouble(_return_value);
1010 
1011 exit:
1012     return return_value;
1013 }
1014 /*[clinic end generated code: output=755da3b1dbd9e45f input=a9049054013a1b77]*/
1015