There was an error while loading. Please reload this page.
1 parent 3221a63 commit 6b5f1b4Copy full SHA for 6b5f1b4
5 files changed
Doc/library/math.rst
@@ -400,7 +400,8 @@ Trigonometric functions
400
.. function:: dist(p, q)
401
402
Return the Euclidean distance between two points *p* and *q*, each
403
- 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
404
+ must have the same dimension.
405
406
Roughly equivalent to::
407
Lib/test/test_math.py
@@ -833,6 +833,10 @@ def testDist(self):
833
sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))
834
)
835
836
+ # Test non-tuple inputs
837
+ self.assertEqual(dist([1.0, 2.0, 3.0], [4.0, 2.0, -1.0]), 5.0)
838
+ self.assertEqual(dist(iter([1.0, 2.0, 3.0]), iter([4.0, 2.0, -1.0])), 5.0)
839
+
840
# Test allowable types (those with __float__)
841
self.assertEqual(dist((14.0, 1.0), (2.0, -4.0)), 13.0)
842
self.assertEqual(dist((14, 1), (2, -4)), 13)
@@ -873,8 +877,6 @@ class T(tuple):
873
877
dist((1, 2, 3), (4, 5, 6), (7, 8, 9))
874
878
with self.assertRaises(TypeError): # Scalars not allowed
875
879
dist(1, 2)
876
- with self.assertRaises(TypeError): # Lists not allowed
- dist([1, 2, 3], [4, 5, 6])
880
with self.assertRaises(TypeError): # Reject values without __float__
881
dist((1.1, 'string', 2.2), (1, 2, 3))
882
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
@@ -2427,31 +2427,49 @@ vector_norm(Py_ssize_t n, double *vec, double max, int found_nan)
2427
/*[clinic input]
2428
math.dist
2429
2430
- p: object(subclass_of='&PyTuple_Type')
2431
- q: object(subclass_of='&PyTuple_Type')
+ p: object
+ q: object
2432
/
2433
2434
Return the Euclidean distance between two points p and q.
2435
2436
-The points should be specified as tuples of coordinates.
2437
-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.
2438
2439
Roughly equivalent to:
2440
2441
[clinic start generated code]*/
2442
2443
static PyObject *
2444
math_dist_impl(PyObject *module, PyObject *p, PyObject *q)
2445
-/*[clinic end generated code: output=56bd9538d06bbcfe input=937122eaa5f19272]*/
+/*[clinic end generated code: output=56bd9538d06bbcfe input=74e85e1b6092e68e]*/
2446
{
2447
PyObject *item;
2448
double max = 0.0;
2449
double x, px, qx, result;
2450
Py_ssize_t i, m, n;
2451
- int found_nan = 0;
+ int found_nan = 0, p_allocated = 0, q_allocated = 0;
2452
double diffs_on_stack[NUM_STACK_ELEMS];
2453
double *diffs = diffs_on_stack;
2454
2455
+ if (!PyTuple_Check(p)) {
2456
+ p = PySequence_Tuple(p);
2457
+ if (p == NULL) {
2458
+ return NULL;
2459
+ }
2460
+ p_allocated = 1;
2461
2462
+ if (!PyTuple_Check(q)) {
2463
+ q = PySequence_Tuple(q);
2464
+ if (q == NULL) {
2465
+ if (p_allocated) {
2466
+ Py_DECREF(p);
2467
2468
2469
2470
+ q_allocated = 1;
2471
2472
2473
m = PyTuple_GET_SIZE(p);
2474
n = PyTuple_GET_SIZE(q);
2475
if (m != n) {
@@ -2482,12 +2500,24 @@ math_dist_impl(PyObject *module, PyObject *p, PyObject *q)
2482
2500
if (diffs != diffs_on_stack) {
2483
2501
PyObject_Free(diffs);
2484
2502
}
2503
2504
2505
2506
+ if (q_allocated) {
2507
+ Py_DECREF(q);
2508
2485
2509
return PyFloat_FromDouble(result);
2486
2510
2487
2511
error_exit:
2488
2512
2489
2513
2490
2514
2515
2516
2517
2518
2519
2520
2491
2521
return NULL;
2492
2522
2493
2523
0 commit comments