There was an error while loading. Please reload this page.
1 parent 1710193 commit 76821baCopy full SHA for 76821ba
5 files changed
Doc/library/math.rst
@@ -394,7 +394,8 @@ Trigonometric functions
394
.. function:: dist(p, q)
395
396
Return the Euclidean distance between two points *p* and *q*, each
397
- given as a tuple of coordinates. The two tuples must be the same size.
+ given as a sequence (or iterable) of coordinates. The two points
398
+ must have the same dimension.
399
400
Roughly equivalent to::
401
Lib/test/test_math.py
@@ -826,6 +826,10 @@ def testDist(self):
826
sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))
827
)
828
829
+ # Test non-tuple inputs
830
+ self.assertEqual(dist([1.0, 2.0, 3.0], [4.0, 2.0, -1.0]), 5.0)
831
+ self.assertEqual(dist(iter([1.0, 2.0, 3.0]), iter([4.0, 2.0, -1.0])), 5.0)
832
+
833
# Test allowable types (those with __float__)
834
self.assertEqual(dist((14.0, 1.0), (2.0, -4.0)), 13.0)
835
self.assertEqual(dist((14, 1), (2, -4)), 13)
@@ -866,8 +870,6 @@ class T(tuple):
866
870
dist((1, 2, 3), (4, 5, 6), (7, 8, 9))
867
871
with self.assertRaises(TypeError): # Scalars not allowed
868
872
dist(1, 2)
869
- with self.assertRaises(TypeError): # Lists not allowed
- dist([1, 2, 3], [4, 5, 6])
873
with self.assertRaises(TypeError): # Reject values without __float__
874
dist((1.1, 'string', 2.2), (1, 2, 3))
875
with self.assertRaises(ValueError): # Check dimension agree
Misc/NEWS.d/next/Library/2019-07-26-22-30-01.bpo-37691.1Li3rx.rst
@@ -0,0 +1,2 @@
1
+Let math.dist() accept coordinates as sequences (or iterables) rather than
2
+just tuples.
Modules/clinic/mathmodule.c.h
Modules/mathmodule.c
@@ -2418,31 +2418,49 @@ vector_norm(Py_ssize_t n, double *vec, double max, int found_nan)
2418
/*[clinic input]
2419
math.dist
2420
2421
- p: object(subclass_of='&PyTuple_Type')
2422
- q: object(subclass_of='&PyTuple_Type')
+ p: object
+ q: object
2423
/
2424
2425
Return the Euclidean distance between two points p and q.
2426
2427
-The points should be specified as tuples of coordinates.
2428
-Both tuples must be the same size.
+The points should be specified as sequences (or iterables) of
+coordinates. Both inputs must have the same dimension.
2429
2430
Roughly equivalent to:
2431
2432
[clinic start generated code]*/
2433
2434
static PyObject *
2435
math_dist_impl(PyObject *module, PyObject *p, PyObject *q)
2436
-/*[clinic end generated code: output=56bd9538d06bbcfe input=937122eaa5f19272]*/
+/*[clinic end generated code: output=56bd9538d06bbcfe input=74e85e1b6092e68e]*/
2437
{
2438
PyObject *item;
2439
double max = 0.0;
2440
double x, px, qx, result;
2441
Py_ssize_t i, m, n;
2442
- int found_nan = 0;
+ int found_nan = 0, p_allocated = 0, q_allocated = 0;
2443
double diffs_on_stack[NUM_STACK_ELEMS];
2444
double *diffs = diffs_on_stack;
2445
2446
+ if (!PyTuple_Check(p)) {
2447
+ p = PySequence_Tuple(p);
2448
+ if (p == NULL) {
2449
+ return NULL;
2450
+ }
2451
+ p_allocated = 1;
2452
2453
+ if (!PyTuple_Check(q)) {
2454
+ q = PySequence_Tuple(q);
2455
+ if (q == NULL) {
2456
+ if (p_allocated) {
2457
+ Py_DECREF(p);
2458
2459
2460
2461
+ q_allocated = 1;
2462
2463
2464
m = PyTuple_GET_SIZE(p);
2465
n = PyTuple_GET_SIZE(q);
2466
if (m != n) {
@@ -2473,12 +2491,24 @@ math_dist_impl(PyObject *module, PyObject *p, PyObject *q)
2473
2491
if (diffs != diffs_on_stack) {
2474
2492
PyObject_Free(diffs);
2475
2493
}
2494
2495
2496
2497
+ if (q_allocated) {
2498
+ Py_DECREF(q);
2499
2476
2500
return PyFloat_FromDouble(result);
2477
2501
2478
2502
error_exit:
2479
2503
2480
2504
2481
2505
2506
2507
2508
2509
2510
2511
2482
2512
return NULL;
2483
2513
2484
2514
0 commit comments