├── .DS_Store ├── requirements.txt ├── pyCon materials ├── .DS_Store ├── new_york_hotels.csv ├── PyCon presentation.pdf └── PyCon un-sad Pandas.ipynb ├── README.md └── MinneAnalytics materials ├── new_york_hotels.csv └── Minneanalytics_talk_slides.pdf /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-heisler/pycon2017-optimizing-pandas/HEAD/.DS_Store -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Cython>=0.25.2 2 | jupyter>=1.0.0 3 | line-profiler>=2.0 4 | pandas>=0.20.1 5 | -------------------------------------------------------------------------------- /pyCon materials/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-heisler/pycon2017-optimizing-pandas/HEAD/pyCon materials/.DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PyCon 2017: Optimizing Pandas Code for Performance 2 | 3 | Materials for the PyCon talk by Sofia Heisler 4 | 5 | -------------------------------------------------------------------------------- /pyCon materials/new_york_hotels.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-heisler/pycon2017-optimizing-pandas/HEAD/pyCon materials/new_york_hotels.csv -------------------------------------------------------------------------------- /pyCon materials/PyCon presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-heisler/pycon2017-optimizing-pandas/HEAD/pyCon materials/PyCon presentation.pdf -------------------------------------------------------------------------------- /MinneAnalytics materials/new_york_hotels.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-heisler/pycon2017-optimizing-pandas/HEAD/MinneAnalytics materials/new_york_hotels.csv -------------------------------------------------------------------------------- /MinneAnalytics materials/Minneanalytics_talk_slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s-heisler/pycon2017-optimizing-pandas/HEAD/MinneAnalytics materials/Minneanalytics_talk_slides.pdf -------------------------------------------------------------------------------- /pyCon materials/PyCon un-sad Pandas.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 51, 6 | "metadata": { 7 | "collapsed": true, 8 | "deletable": true, 9 | "editable": true 10 | }, 11 | "outputs": [], 12 | "source": [ 13 | "import pandas as pd\n", 14 | "import numpy as np\n", 15 | "from math import *" 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "### Read in the data" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 52, 28 | "metadata": { 29 | "collapsed": false, 30 | "deletable": true, 31 | "editable": true 32 | }, 33 | "outputs": [], 34 | "source": [ 35 | "df = pd.read_csv('new_york_hotels.csv', encoding='cp1252')" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 53, 41 | "metadata": { 42 | "collapsed": false, 43 | "deletable": true, 44 | "editable": true, 45 | "scrolled": true 46 | }, 47 | "outputs": [ 48 | { 49 | "data": { 50 | "text/html": [ 51 | "
\n", 52 | "\n", 65 | "\n", 66 | " \n", 67 | " \n", 68 | " \n", 69 | " \n", 70 | " \n", 71 | " \n", 72 | " \n", 73 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | "
ean_hotel_idnameaddress1citystate_provincepostal_codelatitudelongitudestar_ratinghigh_ratelow_rate
0269955Hilton Garden Inn Albany/SUNY Area1389 Washington AveAlbanyNY1220642.68751-73.816433.0154.0272124.0216
1113431Courtyard by Marriott Albany Thruway1455 Washington AvenueAlbanyNY1220642.68971-73.820213.0179.0100134.0000
2108151Radisson Hotel Albany205 Wolf RdAlbanyNY1220542.72410-73.798223.0134.170084.1600
3254756Hilton Garden Inn Albany Medical Center62 New Scotland AveAlbanyNY1220842.65157-73.776383.0308.2807228.4597
4198232CrestHill Suites SUNY University Albany1415 Washington AvenueAlbanyNY1220642.68873-73.818543.0169.390089.3900
\n", 155 | "
" 156 | ], 157 | "text/plain": [ 158 | " ean_hotel_id name \\\n", 159 | "0 269955 Hilton Garden Inn Albany/SUNY Area \n", 160 | "1 113431 Courtyard by Marriott Albany Thruway \n", 161 | "2 108151 Radisson Hotel Albany \n", 162 | "3 254756 Hilton Garden Inn Albany Medical Center \n", 163 | "4 198232 CrestHill Suites SUNY University Albany \n", 164 | "\n", 165 | " address1 city state_province postal_code latitude \\\n", 166 | "0 1389 Washington Ave Albany NY 12206 42.68751 \n", 167 | "1 1455 Washington Avenue Albany NY 12206 42.68971 \n", 168 | "2 205 Wolf Rd Albany NY 12205 42.72410 \n", 169 | "3 62 New Scotland Ave Albany NY 12208 42.65157 \n", 170 | "4 1415 Washington Avenue Albany NY 12206 42.68873 \n", 171 | "\n", 172 | " longitude star_rating high_rate low_rate \n", 173 | "0 -73.81643 3.0 154.0272 124.0216 \n", 174 | "1 -73.82021 3.0 179.0100 134.0000 \n", 175 | "2 -73.79822 3.0 134.1700 84.1600 \n", 176 | "3 -73.77638 3.0 308.2807 228.4597 \n", 177 | "4 -73.81854 3.0 169.3900 89.3900 " 178 | ] 179 | }, 180 | "execution_count": 53, 181 | "metadata": {}, 182 | "output_type": "execute_result" 183 | } 184 | ], 185 | "source": [ 186 | "df.head()" 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": { 192 | "deletable": true, 193 | "editable": true 194 | }, 195 | "source": [ 196 | "## Benchmarking example" 197 | ] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "metadata": {}, 202 | "source": [ 203 | "#### Define the normalization function" 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "execution_count": 54, 209 | "metadata": { 210 | "collapsed": true, 211 | "deletable": true, 212 | "editable": true 213 | }, 214 | "outputs": [], 215 | "source": [ 216 | "def normalize(df, pd_series):\n", 217 | " pd_series = pd_series.astype(float)\n", 218 | "\n", 219 | " # Find upper and lower bound for outliers\n", 220 | " avg = np.mean(pd_series)\n", 221 | " sd = np.std(pd_series)\n", 222 | " lower_bound = avg - 2*sd\n", 223 | " upper_bound = avg + 2*sd\n", 224 | "\n", 225 | " # Collapse in the outliers\n", 226 | " df.loc[pd_series < lower_bound , \"cutoff_rate\" ] = lower_bound\n", 227 | " df.loc[pd_series > upper_bound , \"cutoff_rate\" ] = upper_bound\n", 228 | "\n", 229 | " # Finally, take the log\n", 230 | " normalized_price = np.log(df[\"cutoff_rate\"].astype(float))\n", 231 | " \n", 232 | " return normalized_price" 233 | ] 234 | }, 235 | { 236 | "cell_type": "markdown", 237 | "metadata": {}, 238 | "source": [ 239 | "#### Timing the normalization function" 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": 55, 245 | "metadata": { 246 | "collapsed": false, 247 | "deletable": true, 248 | "editable": true 249 | }, 250 | "outputs": [ 251 | { 252 | "name": "stdout", 253 | "output_type": "stream", 254 | "text": [ 255 | "2.84 ms ± 180 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" 256 | ] 257 | } 258 | ], 259 | "source": [ 260 | "%timeit df['high_rate_normalized'] = normalize(df, df['high_rate'])" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "#### Profiling the normalization function" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 56, 273 | "metadata": { 274 | "collapsed": false, 275 | "deletable": true, 276 | "editable": true 277 | }, 278 | "outputs": [ 279 | { 280 | "name": "stdout", 281 | "output_type": "stream", 282 | "text": [ 283 | "The line_profiler extension is already loaded. To reload it, use:\n", 284 | " %reload_ext line_profiler\n" 285 | ] 286 | } 287 | ], 288 | "source": [ 289 | " %load_ext line_profiler" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": 75, 295 | "metadata": { 296 | "collapsed": false, 297 | "deletable": true, 298 | "editable": true, 299 | "scrolled": true 300 | }, 301 | "outputs": [], 302 | "source": [ 303 | "%lprun -f normalize df['high_rate_normalized'] =\\\n", 304 | " normalize(df, df['high_rate'])" 305 | ] 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "metadata": { 310 | "deletable": true, 311 | "editable": true 312 | }, 313 | "source": [ 314 | "## Haversine definition" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 58, 320 | "metadata": { 321 | "collapsed": true, 322 | "deletable": true, 323 | "editable": true 324 | }, 325 | "outputs": [], 326 | "source": [ 327 | "def haversine(lat1, lon1, lat2, lon2):\n", 328 | " miles_constant = 3959\n", 329 | " lat1, lon1, lat2, lon2 = map(np.deg2rad, [lat1, lon1, lat2, lon2])\n", 330 | " dlat = lat2 - lat1 \n", 331 | " dlon = lon2 - lon1 \n", 332 | " a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2\n", 333 | " c = 2 * np.arcsin(np.sqrt(a)) \n", 334 | " mi = miles_constant * c\n", 335 | " return mi" 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "metadata": { 341 | "deletable": true, 342 | "editable": true 343 | }, 344 | "source": [ 345 | "## Iterrows Haversine" 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": 59, 351 | "metadata": { 352 | "collapsed": false, 353 | "deletable": true, 354 | "editable": true 355 | }, 356 | "outputs": [ 357 | { 358 | "name": "stdout", 359 | "output_type": "stream", 360 | "text": [ 361 | "197 ms ± 6.65 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" 362 | ] 363 | } 364 | ], 365 | "source": [ 366 | "%%timeit\n", 367 | "# Haversine applied on rows via iteration\n", 368 | "haversine_series = []\n", 369 | "for index, row in df.iterrows():\n", 370 | " haversine_series.append(haversine(40.671, -73.985,\\\n", 371 | " row['latitude'], row['longitude']))\n", 372 | "df['distance'] = haversine_series" 373 | ] 374 | }, 375 | { 376 | "cell_type": "markdown", 377 | "metadata": { 378 | "deletable": true, 379 | "editable": true 380 | }, 381 | "source": [ 382 | "## Apply Haversine on rows" 383 | ] 384 | }, 385 | { 386 | "cell_type": "markdown", 387 | "metadata": {}, 388 | "source": [ 389 | "### Timing \"apply\"" 390 | ] 391 | }, 392 | { 393 | "cell_type": "code", 394 | "execution_count": 71, 395 | "metadata": { 396 | "collapsed": false, 397 | "deletable": true, 398 | "editable": true, 399 | "scrolled": true 400 | }, 401 | "outputs": [ 402 | { 403 | "name": "stdout", 404 | "output_type": "stream", 405 | "text": [ 406 | "90.6 ms ± 7.55 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" 407 | ] 408 | } 409 | ], 410 | "source": [ 411 | "%timeit df['distance'] =\\\n", 412 | "df.apply(lambda row: haversine(40.671, -73.985,\\\n", 413 | " row['latitude'], row['longitude']), axis=1)" 414 | ] 415 | }, 416 | { 417 | "cell_type": "markdown", 418 | "metadata": {}, 419 | "source": [ 420 | "#### Profiling \"apply\"" 421 | ] 422 | }, 423 | { 424 | "cell_type": "code", 425 | "execution_count": 76, 426 | "metadata": { 427 | "collapsed": false, 428 | "deletable": true, 429 | "editable": true 430 | }, 431 | "outputs": [], 432 | "source": [ 433 | "# Haversine applied on rows\n", 434 | "%lprun -f haversine \\\n", 435 | "df.apply(lambda row: haversine(40.671, -73.985,\\\n", 436 | " row['latitude'], row['longitude']), axis=1)" 437 | ] 438 | }, 439 | { 440 | "cell_type": "markdown", 441 | "metadata": { 442 | "deletable": true, 443 | "editable": true 444 | }, 445 | "source": [ 446 | "## Vectorized implementation of Haversine applied on Pandas series" 447 | ] 448 | }, 449 | { 450 | "cell_type": "markdown", 451 | "metadata": {}, 452 | "source": [ 453 | "#### Timing vectorized implementation" 454 | ] 455 | }, 456 | { 457 | "cell_type": "code", 458 | "execution_count": 73, 459 | "metadata": { 460 | "collapsed": false, 461 | "deletable": true, 462 | "editable": true 463 | }, 464 | "outputs": [ 465 | { 466 | "name": "stdout", 467 | "output_type": "stream", 468 | "text": [ 469 | "2.21 ms ± 230 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" 470 | ] 471 | } 472 | ], 473 | "source": [ 474 | "# Vectorized implementation of Haversine applied on Pandas series\n", 475 | "%timeit df['distance'] = haversine(40.671, -73.985,\\\n", 476 | " df['latitude'], df['longitude'])" 477 | ] 478 | }, 479 | { 480 | "cell_type": "markdown", 481 | "metadata": {}, 482 | "source": [ 483 | "#### Profiling vectorized implementation" 484 | ] 485 | }, 486 | { 487 | "cell_type": "code", 488 | "execution_count": 77, 489 | "metadata": { 490 | "collapsed": true, 491 | "deletable": true, 492 | "editable": true 493 | }, 494 | "outputs": [], 495 | "source": [ 496 | "# Vectorized implementation profile\n", 497 | "%lprun -f haversine haversine(40.671, -73.985,\\\n", 498 | " df['latitude'], df['longitude'])" 499 | ] 500 | }, 501 | { 502 | "cell_type": "markdown", 503 | "metadata": { 504 | "deletable": true, 505 | "editable": true 506 | }, 507 | "source": [ 508 | "## Vectorized implementation of Haversine applied on NumPy arrays" 509 | ] 510 | }, 511 | { 512 | "cell_type": "markdown", 513 | "metadata": {}, 514 | "source": [ 515 | "#### Timing vectorized implementation" 516 | ] 517 | }, 518 | { 519 | "cell_type": "code", 520 | "execution_count": 55, 521 | "metadata": { 522 | "collapsed": false, 523 | "deletable": true, 524 | "editable": true 525 | }, 526 | "outputs": [ 527 | { 528 | "name": "stdout", 529 | "output_type": "stream", 530 | "text": [ 531 | "370 µs ± 18 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" 532 | ] 533 | } 534 | ], 535 | "source": [ 536 | "# Vectorized implementation of Haversine applied on NumPy arrays\n", 537 | "%timeit df['distance'] = haversine(40.671, -73.985,\\\n", 538 | " df['latitude'].values, df['longitude'].values)" 539 | ] 540 | }, 541 | { 542 | "cell_type": "code", 543 | "execution_count": 57, 544 | "metadata": { 545 | "collapsed": false, 546 | "deletable": true, 547 | "editable": true 548 | }, 549 | "outputs": [ 550 | { 551 | "name": "stdout", 552 | "output_type": "stream", 553 | "text": [ 554 | "7.66 µs ± 289 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" 555 | ] 556 | } 557 | ], 558 | "source": [ 559 | "%%timeit\n", 560 | "# Convert pandas arrays to NumPy ndarrays\n", 561 | "np_lat = df['latitude'].values\n", 562 | "np_lon = df['longitude'].values" 563 | ] 564 | }, 565 | { 566 | "cell_type": "markdown", 567 | "metadata": {}, 568 | "source": [ 569 | "#### Profiling vectorized implementation" 570 | ] 571 | }, 572 | { 573 | "cell_type": "code", 574 | "execution_count": 53, 575 | "metadata": { 576 | "collapsed": true, 577 | "deletable": true, 578 | "editable": true 579 | }, 580 | "outputs": [], 581 | "source": [ 582 | "%lprun -f haversine df['distance'] = haversine(40.671, -73.985,\\\n", 583 | " df['latitude'].values, df['longitude'].values)" 584 | ] 585 | }, 586 | { 587 | "cell_type": "markdown", 588 | "metadata": { 589 | "deletable": true, 590 | "editable": true 591 | }, 592 | "source": [ 593 | "## Cythonize that loop" 594 | ] 595 | }, 596 | { 597 | "cell_type": "markdown", 598 | "metadata": {}, 599 | "source": [ 600 | "#### Load the cython extension" 601 | ] 602 | }, 603 | { 604 | "cell_type": "code", 605 | "execution_count": 65, 606 | "metadata": { 607 | "collapsed": false, 608 | "deletable": true, 609 | "editable": true 610 | }, 611 | "outputs": [ 612 | { 613 | "name": "stdout", 614 | "output_type": "stream", 615 | "text": [ 616 | "The cython extension is already loaded. To reload it, use:\n", 617 | " %reload_ext cython\n" 618 | ] 619 | } 620 | ], 621 | "source": [ 622 | "%load_ext cython" 623 | ] 624 | }, 625 | { 626 | "cell_type": "markdown", 627 | "metadata": {}, 628 | "source": [ 629 | "#### Run unaltered Haversine through Cython" 630 | ] 631 | }, 632 | { 633 | "cell_type": "code", 634 | "execution_count": 68, 635 | "metadata": { 636 | "collapsed": false, 637 | "deletable": true, 638 | "editable": true 639 | }, 640 | "outputs": [ 641 | { 642 | "data": { 643 | "text/html": [ 644 | "\n", 645 | "\n", 646 | "\n", 647 | "\n", 648 | " \n", 649 | " Cython: _cython_magic_4d2d58d72a34088836da9f445cf39e4f.pyx\n", 650 | " \n", 1002 | " \n", 1009 | "\n", 1010 | "\n", 1011 | "

Generated by Cython 0.25.2

\n", 1012 | "

\n", 1013 | " Yellow lines hint at Python interaction.
\n", 1014 | " Click on a line that starts with a \"+\" to see the C code that Cython generated for it.\n", 1015 | "

\n", 1016 | "
 01: 
\n", 1017 | "
 02: # Haversine cythonized (no other edits)
\n", 1018 | "
+03: import numpy as np
\n", 1019 | "
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
1020 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
1021 |        "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 3, __pyx_L1_error)\n",
1022 |        "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1023 |        "
+04: cpdef haversine_cy(lat1, lon1, lat2, lon2):
\n", 1024 | "
static PyObject *__pyx_pw_46_cython_magic_4d2d58d72a34088836da9f445cf39e4f_1haversine_cy(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
1025 |        "static PyObject *__pyx_f_46_cython_magic_4d2d58d72a34088836da9f445cf39e4f_haversine_cy(PyObject *__pyx_v_lat1, PyObject *__pyx_v_lon1, PyObject *__pyx_v_lat2, PyObject *__pyx_v_lon2, CYTHON_UNUSED int __pyx_skip_dispatch) {\n",
1026 |        "  PyObject *__pyx_v_miles_constant = NULL;\n",
1027 |        "  PyObject *__pyx_v_dlat = NULL;\n",
1028 |        "  PyObject *__pyx_v_dlon = NULL;\n",
1029 |        "  PyObject *__pyx_v_a = NULL;\n",
1030 |        "  PyObject *__pyx_v_c = NULL;\n",
1031 |        "  PyObject *__pyx_v_mi = NULL;\n",
1032 |        "  PyObject *__pyx_r = NULL;\n",
1033 |        "  __Pyx_RefNannyDeclarations\n",
1034 |        "  __Pyx_RefNannySetupContext(\"haversine_cy\", 0);\n",
1035 |        "  __Pyx_INCREF(__pyx_v_lat1);\n",
1036 |        "  __Pyx_INCREF(__pyx_v_lon1);\n",
1037 |        "  __Pyx_INCREF(__pyx_v_lat2);\n",
1038 |        "  __Pyx_INCREF(__pyx_v_lon2);\n",
1039 |        "/* … */\n",
1040 |        "  /* function exit code */\n",
1041 |        "  __pyx_L1_error:;\n",
1042 |        "  __Pyx_XDECREF(__pyx_t_1);\n",
1043 |        "  __Pyx_XDECREF(__pyx_t_2);\n",
1044 |        "  __Pyx_XDECREF(__pyx_t_3);\n",
1045 |        "  __Pyx_XDECREF(__pyx_t_4);\n",
1046 |        "  __Pyx_XDECREF(__pyx_t_5);\n",
1047 |        "  __Pyx_XDECREF(__pyx_t_6);\n",
1048 |        "  __Pyx_XDECREF(__pyx_t_8);\n",
1049 |        "  __Pyx_AddTraceback(\"_cython_magic_4d2d58d72a34088836da9f445cf39e4f.haversine_cy\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
1050 |        "  __pyx_r = 0;\n",
1051 |        "  __pyx_L0:;\n",
1052 |        "  __Pyx_XDECREF(__pyx_v_miles_constant);\n",
1053 |        "  __Pyx_XDECREF(__pyx_v_dlat);\n",
1054 |        "  __Pyx_XDECREF(__pyx_v_dlon);\n",
1055 |        "  __Pyx_XDECREF(__pyx_v_a);\n",
1056 |        "  __Pyx_XDECREF(__pyx_v_c);\n",
1057 |        "  __Pyx_XDECREF(__pyx_v_mi);\n",
1058 |        "  __Pyx_XDECREF(__pyx_v_lat1);\n",
1059 |        "  __Pyx_XDECREF(__pyx_v_lon1);\n",
1060 |        "  __Pyx_XDECREF(__pyx_v_lat2);\n",
1061 |        "  __Pyx_XDECREF(__pyx_v_lon2);\n",
1062 |        "  __Pyx_XGIVEREF(__pyx_r);\n",
1063 |        "  __Pyx_RefNannyFinishContext();\n",
1064 |        "  return __pyx_r;\n",
1065 |        "}\n",
1066 |        "\n",
1067 |        "/* Python wrapper */\n",
1068 |        "static PyObject *__pyx_pw_46_cython_magic_4d2d58d72a34088836da9f445cf39e4f_1haversine_cy(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
1069 |        "static PyObject *__pyx_pw_46_cython_magic_4d2d58d72a34088836da9f445cf39e4f_1haversine_cy(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
1070 |        "  PyObject *__pyx_v_lat1 = 0;\n",
1071 |        "  PyObject *__pyx_v_lon1 = 0;\n",
1072 |        "  PyObject *__pyx_v_lat2 = 0;\n",
1073 |        "  PyObject *__pyx_v_lon2 = 0;\n",
1074 |        "  PyObject *__pyx_r = 0;\n",
1075 |        "  __Pyx_RefNannyDeclarations\n",
1076 |        "  __Pyx_RefNannySetupContext(\"haversine_cy (wrapper)\", 0);\n",
1077 |        "  {\n",
1078 |        "    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_lat1,&__pyx_n_s_lon1,&__pyx_n_s_lat2,&__pyx_n_s_lon2,0};\n",
1079 |        "    PyObject* values[4] = {0,0,0,0};\n",
1080 |        "    if (unlikely(__pyx_kwds)) {\n",
1081 |        "      Py_ssize_t kw_args;\n",
1082 |        "      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);\n",
1083 |        "      switch (pos_args) {\n",
1084 |        "        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n",
1085 |        "        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
1086 |        "        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
1087 |        "        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
1088 |        "        case  0: break;\n",
1089 |        "        default: goto __pyx_L5_argtuple_error;\n",
1090 |        "      }\n",
1091 |        "      kw_args = PyDict_Size(__pyx_kwds);\n",
1092 |        "      switch (pos_args) {\n",
1093 |        "        case  0:\n",
1094 |        "        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lat1)) != 0)) kw_args--;\n",
1095 |        "        else goto __pyx_L5_argtuple_error;\n",
1096 |        "        case  1:\n",
1097 |        "        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lon1)) != 0)) kw_args--;\n",
1098 |        "        else {\n",
1099 |        "          __Pyx_RaiseArgtupleInvalid(\"haversine_cy\", 1, 4, 4, 1); __PYX_ERR(0, 4, __pyx_L3_error)\n",
1100 |        "        }\n",
1101 |        "        case  2:\n",
1102 |        "        if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lat2)) != 0)) kw_args--;\n",
1103 |        "        else {\n",
1104 |        "          __Pyx_RaiseArgtupleInvalid(\"haversine_cy\", 1, 4, 4, 2); __PYX_ERR(0, 4, __pyx_L3_error)\n",
1105 |        "        }\n",
1106 |        "        case  3:\n",
1107 |        "        if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lon2)) != 0)) kw_args--;\n",
1108 |        "        else {\n",
1109 |        "          __Pyx_RaiseArgtupleInvalid(\"haversine_cy\", 1, 4, 4, 3); __PYX_ERR(0, 4, __pyx_L3_error)\n",
1110 |        "        }\n",
1111 |        "      }\n",
1112 |        "      if (unlikely(kw_args > 0)) {\n",
1113 |        "        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"haversine_cy\") < 0)) __PYX_ERR(0, 4, __pyx_L3_error)\n",
1114 |        "      }\n",
1115 |        "    } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {\n",
1116 |        "      goto __pyx_L5_argtuple_error;\n",
1117 |        "    } else {\n",
1118 |        "      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
1119 |        "      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
1120 |        "      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
1121 |        "      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n",
1122 |        "    }\n",
1123 |        "    __pyx_v_lat1 = values[0];\n",
1124 |        "    __pyx_v_lon1 = values[1];\n",
1125 |        "    __pyx_v_lat2 = values[2];\n",
1126 |        "    __pyx_v_lon2 = values[3];\n",
1127 |        "  }\n",
1128 |        "  goto __pyx_L4_argument_unpacking_done;\n",
1129 |        "  __pyx_L5_argtuple_error:;\n",
1130 |        "  __Pyx_RaiseArgtupleInvalid(\"haversine_cy\", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 4, __pyx_L3_error)\n",
1131 |        "  __pyx_L3_error:;\n",
1132 |        "  __Pyx_AddTraceback(\"_cython_magic_4d2d58d72a34088836da9f445cf39e4f.haversine_cy\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
1133 |        "  __Pyx_RefNannyFinishContext();\n",
1134 |        "  return NULL;\n",
1135 |        "  __pyx_L4_argument_unpacking_done:;\n",
1136 |        "  __pyx_r = __pyx_pf_46_cython_magic_4d2d58d72a34088836da9f445cf39e4f_haversine_cy(__pyx_self, __pyx_v_lat1, __pyx_v_lon1, __pyx_v_lat2, __pyx_v_lon2);\n",
1137 |        "\n",
1138 |        "  /* function exit code */\n",
1139 |        "  __Pyx_RefNannyFinishContext();\n",
1140 |        "  return __pyx_r;\n",
1141 |        "}\n",
1142 |        "\n",
1143 |        "static PyObject *__pyx_pf_46_cython_magic_4d2d58d72a34088836da9f445cf39e4f_haversine_cy(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_lat1, PyObject *__pyx_v_lon1, PyObject *__pyx_v_lat2, PyObject *__pyx_v_lon2) {\n",
1144 |        "  PyObject *__pyx_r = NULL;\n",
1145 |        "  __Pyx_RefNannyDeclarations\n",
1146 |        "  __Pyx_RefNannySetupContext(\"haversine_cy\", 0);\n",
1147 |        "  __Pyx_XDECREF(__pyx_r);\n",
1148 |        "  __pyx_t_1 = __pyx_f_46_cython_magic_4d2d58d72a34088836da9f445cf39e4f_haversine_cy(__pyx_v_lat1, __pyx_v_lon1, __pyx_v_lat2, __pyx_v_lon2, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
1149 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
1150 |        "  __pyx_r = __pyx_t_1;\n",
1151 |        "  __pyx_t_1 = 0;\n",
1152 |        "  goto __pyx_L0;\n",
1153 |        "\n",
1154 |        "  /* function exit code */\n",
1155 |        "  __pyx_L1_error:;\n",
1156 |        "  __Pyx_XDECREF(__pyx_t_1);\n",
1157 |        "  __Pyx_AddTraceback(\"_cython_magic_4d2d58d72a34088836da9f445cf39e4f.haversine_cy\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
1158 |        "  __pyx_r = NULL;\n",
1159 |        "  __pyx_L0:;\n",
1160 |        "  __Pyx_XGIVEREF(__pyx_r);\n",
1161 |        "  __Pyx_RefNannyFinishContext();\n",
1162 |        "  return __pyx_r;\n",
1163 |        "}\n",
1164 |        "
+05:     miles_constant = 3959
\n", 1165 | "
  __Pyx_INCREF(__pyx_int_3959);\n",
1166 |        "  __pyx_v_miles_constant = __pyx_int_3959;\n",
1167 |        "
+06:     lat1, lon1, lat2, lon2 = map(np.deg2rad, [lat1, lon1, lat2, lon2])
\n", 1168 | "
  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
1169 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
1170 |        "  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_deg2rad); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
1171 |        "  __Pyx_GOTREF(__pyx_t_2);\n",
1172 |        "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1173 |        "  __pyx_t_1 = PyList_New(4); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
1174 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
1175 |        "  __Pyx_INCREF(__pyx_v_lat1);\n",
1176 |        "  __Pyx_GIVEREF(__pyx_v_lat1);\n",
1177 |        "  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_lat1);\n",
1178 |        "  __Pyx_INCREF(__pyx_v_lon1);\n",
1179 |        "  __Pyx_GIVEREF(__pyx_v_lon1);\n",
1180 |        "  PyList_SET_ITEM(__pyx_t_1, 1, __pyx_v_lon1);\n",
1181 |        "  __Pyx_INCREF(__pyx_v_lat2);\n",
1182 |        "  __Pyx_GIVEREF(__pyx_v_lat2);\n",
1183 |        "  PyList_SET_ITEM(__pyx_t_1, 2, __pyx_v_lat2);\n",
1184 |        "  __Pyx_INCREF(__pyx_v_lon2);\n",
1185 |        "  __Pyx_GIVEREF(__pyx_v_lon2);\n",
1186 |        "  PyList_SET_ITEM(__pyx_t_1, 3, __pyx_v_lon2);\n",
1187 |        "  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
1188 |        "  __Pyx_GOTREF(__pyx_t_3);\n",
1189 |        "  __Pyx_GIVEREF(__pyx_t_2);\n",
1190 |        "  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2);\n",
1191 |        "  __Pyx_GIVEREF(__pyx_t_1);\n",
1192 |        "  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);\n",
1193 |        "  __pyx_t_2 = 0;\n",
1194 |        "  __pyx_t_1 = 0;\n",
1195 |        "  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_map, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
1196 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
1197 |        "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1198 |        "  if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {\n",
1199 |        "    PyObject* sequence = __pyx_t_1;\n",
1200 |        "    #if !CYTHON_COMPILING_IN_PYPY\n",
1201 |        "    Py_ssize_t size = Py_SIZE(sequence);\n",
1202 |        "    #else\n",
1203 |        "    Py_ssize_t size = PySequence_Size(sequence);\n",
1204 |        "    #endif\n",
1205 |        "    if (unlikely(size != 4)) {\n",
1206 |        "      if (size > 4) __Pyx_RaiseTooManyValuesError(4);\n",
1207 |        "      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);\n",
1208 |        "      __PYX_ERR(0, 6, __pyx_L1_error)\n",
1209 |        "    }\n",
1210 |        "    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n",
1211 |        "    if (likely(PyTuple_CheckExact(sequence))) {\n",
1212 |        "      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); \n",
1213 |        "      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1); \n",
1214 |        "      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2); \n",
1215 |        "      __pyx_t_5 = PyTuple_GET_ITEM(sequence, 3); \n",
1216 |        "    } else {\n",
1217 |        "      __pyx_t_3 = PyList_GET_ITEM(sequence, 0); \n",
1218 |        "      __pyx_t_2 = PyList_GET_ITEM(sequence, 1); \n",
1219 |        "      __pyx_t_4 = PyList_GET_ITEM(sequence, 2); \n",
1220 |        "      __pyx_t_5 = PyList_GET_ITEM(sequence, 3); \n",
1221 |        "    }\n",
1222 |        "    __Pyx_INCREF(__pyx_t_3);\n",
1223 |        "    __Pyx_INCREF(__pyx_t_2);\n",
1224 |        "    __Pyx_INCREF(__pyx_t_4);\n",
1225 |        "    __Pyx_INCREF(__pyx_t_5);\n",
1226 |        "    #else\n",
1227 |        "    {\n",
1228 |        "      Py_ssize_t i;\n",
1229 |        "      PyObject** temps[4] = {&__pyx_t_3,&__pyx_t_2,&__pyx_t_4,&__pyx_t_5};\n",
1230 |        "      for (i=0; i < 4; i++) {\n",
1231 |        "        PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
1232 |        "        __Pyx_GOTREF(item);\n",
1233 |        "        *(temps[i]) = item;\n",
1234 |        "      }\n",
1235 |        "    }\n",
1236 |        "    #endif\n",
1237 |        "    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1238 |        "  } else {\n",
1239 |        "    Py_ssize_t index = -1;\n",
1240 |        "    PyObject** temps[4] = {&__pyx_t_3,&__pyx_t_2,&__pyx_t_4,&__pyx_t_5};\n",
1241 |        "    __pyx_t_6 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
1242 |        "    __Pyx_GOTREF(__pyx_t_6);\n",
1243 |        "    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1244 |        "    __pyx_t_7 = Py_TYPE(__pyx_t_6)->tp_iternext;\n",
1245 |        "    for (index=0; index < 4; index++) {\n",
1246 |        "      PyObject* item = __pyx_t_7(__pyx_t_6); if (unlikely(!item)) goto __pyx_L3_unpacking_failed;\n",
1247 |        "      __Pyx_GOTREF(item);\n",
1248 |        "      *(temps[index]) = item;\n",
1249 |        "    }\n",
1250 |        "    if (__Pyx_IternextUnpackEndCheck(__pyx_t_7(__pyx_t_6), 4) < 0) __PYX_ERR(0, 6, __pyx_L1_error)\n",
1251 |        "    __pyx_t_7 = NULL;\n",
1252 |        "    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
1253 |        "    goto __pyx_L4_unpacking_done;\n",
1254 |        "    __pyx_L3_unpacking_failed:;\n",
1255 |        "    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
1256 |        "    __pyx_t_7 = NULL;\n",
1257 |        "    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);\n",
1258 |        "    __PYX_ERR(0, 6, __pyx_L1_error)\n",
1259 |        "    __pyx_L4_unpacking_done:;\n",
1260 |        "  }\n",
1261 |        "  __Pyx_DECREF_SET(__pyx_v_lat1, __pyx_t_3);\n",
1262 |        "  __pyx_t_3 = 0;\n",
1263 |        "  __Pyx_DECREF_SET(__pyx_v_lon1, __pyx_t_2);\n",
1264 |        "  __pyx_t_2 = 0;\n",
1265 |        "  __Pyx_DECREF_SET(__pyx_v_lat2, __pyx_t_4);\n",
1266 |        "  __pyx_t_4 = 0;\n",
1267 |        "  __Pyx_DECREF_SET(__pyx_v_lon2, __pyx_t_5);\n",
1268 |        "  __pyx_t_5 = 0;\n",
1269 |        "
+07:     dlat = lat2 - lat1
\n", 1270 | "
  __pyx_t_1 = PyNumber_Subtract(__pyx_v_lat2, __pyx_v_lat1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
1271 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
1272 |        "  __pyx_v_dlat = __pyx_t_1;\n",
1273 |        "  __pyx_t_1 = 0;\n",
1274 |        "
+08:     dlon = lon2 - lon1
\n", 1275 | "
  __pyx_t_1 = PyNumber_Subtract(__pyx_v_lon2, __pyx_v_lon1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
1276 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
1277 |        "  __pyx_v_dlon = __pyx_t_1;\n",
1278 |        "  __pyx_t_1 = 0;\n",
1279 |        "
+09:     a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2
\n", 1280 | "
  __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1281 |        "  __Pyx_GOTREF(__pyx_t_5);\n",
1282 |        "  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_sin); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1283 |        "  __Pyx_GOTREF(__pyx_t_4);\n",
1284 |        "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1285 |        "  __pyx_t_5 = __Pyx_PyInt_TrueDivideObjC(__pyx_v_dlat, __pyx_int_2, 2, 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1286 |        "  __Pyx_GOTREF(__pyx_t_5);\n",
1287 |        "  __pyx_t_2 = NULL;\n",
1288 |        "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {\n",
1289 |        "    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_4);\n",
1290 |        "    if (likely(__pyx_t_2)) {\n",
1291 |        "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);\n",
1292 |        "      __Pyx_INCREF(__pyx_t_2);\n",
1293 |        "      __Pyx_INCREF(function);\n",
1294 |        "      __Pyx_DECREF_SET(__pyx_t_4, function);\n",
1295 |        "    }\n",
1296 |        "  }\n",
1297 |        "  if (!__pyx_t_2) {\n",
1298 |        "    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1299 |        "    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1300 |        "    __Pyx_GOTREF(__pyx_t_1);\n",
1301 |        "  } else {\n",
1302 |        "    #if CYTHON_FAST_PYCALL\n",
1303 |        "    if (PyFunction_Check(__pyx_t_4)) {\n",
1304 |        "      PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_t_5};\n",
1305 |        "      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1306 |        "      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
1307 |        "      __Pyx_GOTREF(__pyx_t_1);\n",
1308 |        "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1309 |        "    } else\n",
1310 |        "    #endif\n",
1311 |        "    #if CYTHON_FAST_PYCCALL\n",
1312 |        "    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {\n",
1313 |        "      PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_t_5};\n",
1314 |        "      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1315 |        "      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
1316 |        "      __Pyx_GOTREF(__pyx_t_1);\n",
1317 |        "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1318 |        "    } else\n",
1319 |        "    #endif\n",
1320 |        "    {\n",
1321 |        "      __pyx_t_3 = PyTuple_New(1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1322 |        "      __Pyx_GOTREF(__pyx_t_3);\n",
1323 |        "      __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_2); __pyx_t_2 = NULL;\n",
1324 |        "      __Pyx_GIVEREF(__pyx_t_5);\n",
1325 |        "      PyTuple_SET_ITEM(__pyx_t_3, 0+1, __pyx_t_5);\n",
1326 |        "      __pyx_t_5 = 0;\n",
1327 |        "      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1328 |        "      __Pyx_GOTREF(__pyx_t_1);\n",
1329 |        "      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1330 |        "    }\n",
1331 |        "  }\n",
1332 |        "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
1333 |        "  __pyx_t_4 = PyNumber_Power(__pyx_t_1, __pyx_int_2, Py_None); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1334 |        "  __Pyx_GOTREF(__pyx_t_4);\n",
1335 |        "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1336 |        "  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1337 |        "  __Pyx_GOTREF(__pyx_t_3);\n",
1338 |        "  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_cos); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1339 |        "  __Pyx_GOTREF(__pyx_t_5);\n",
1340 |        "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1341 |        "  __pyx_t_3 = NULL;\n",
1342 |        "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {\n",
1343 |        "    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_5);\n",
1344 |        "    if (likely(__pyx_t_3)) {\n",
1345 |        "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);\n",
1346 |        "      __Pyx_INCREF(__pyx_t_3);\n",
1347 |        "      __Pyx_INCREF(function);\n",
1348 |        "      __Pyx_DECREF_SET(__pyx_t_5, function);\n",
1349 |        "    }\n",
1350 |        "  }\n",
1351 |        "  if (!__pyx_t_3) {\n",
1352 |        "    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_lat1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1353 |        "    __Pyx_GOTREF(__pyx_t_1);\n",
1354 |        "  } else {\n",
1355 |        "    #if CYTHON_FAST_PYCALL\n",
1356 |        "    if (PyFunction_Check(__pyx_t_5)) {\n",
1357 |        "      PyObject *__pyx_temp[2] = {__pyx_t_3, __pyx_v_lat1};\n",
1358 |        "      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1359 |        "      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1360 |        "      __Pyx_GOTREF(__pyx_t_1);\n",
1361 |        "    } else\n",
1362 |        "    #endif\n",
1363 |        "    #if CYTHON_FAST_PYCCALL\n",
1364 |        "    if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {\n",
1365 |        "      PyObject *__pyx_temp[2] = {__pyx_t_3, __pyx_v_lat1};\n",
1366 |        "      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1367 |        "      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1368 |        "      __Pyx_GOTREF(__pyx_t_1);\n",
1369 |        "    } else\n",
1370 |        "    #endif\n",
1371 |        "    {\n",
1372 |        "      __pyx_t_2 = PyTuple_New(1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1373 |        "      __Pyx_GOTREF(__pyx_t_2);\n",
1374 |        "      __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3); __pyx_t_3 = NULL;\n",
1375 |        "      __Pyx_INCREF(__pyx_v_lat1);\n",
1376 |        "      __Pyx_GIVEREF(__pyx_v_lat1);\n",
1377 |        "      PyTuple_SET_ITEM(__pyx_t_2, 0+1, __pyx_v_lat1);\n",
1378 |        "      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1379 |        "      __Pyx_GOTREF(__pyx_t_1);\n",
1380 |        "      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
1381 |        "    }\n",
1382 |        "  }\n",
1383 |        "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1384 |        "  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1385 |        "  __Pyx_GOTREF(__pyx_t_2);\n",
1386 |        "  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_cos); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1387 |        "  __Pyx_GOTREF(__pyx_t_3);\n",
1388 |        "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
1389 |        "  __pyx_t_2 = NULL;\n",
1390 |        "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {\n",
1391 |        "    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);\n",
1392 |        "    if (likely(__pyx_t_2)) {\n",
1393 |        "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);\n",
1394 |        "      __Pyx_INCREF(__pyx_t_2);\n",
1395 |        "      __Pyx_INCREF(function);\n",
1396 |        "      __Pyx_DECREF_SET(__pyx_t_3, function);\n",
1397 |        "    }\n",
1398 |        "  }\n",
1399 |        "  if (!__pyx_t_2) {\n",
1400 |        "    __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_lat2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1401 |        "    __Pyx_GOTREF(__pyx_t_5);\n",
1402 |        "  } else {\n",
1403 |        "    #if CYTHON_FAST_PYCALL\n",
1404 |        "    if (PyFunction_Check(__pyx_t_3)) {\n",
1405 |        "      PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_v_lat2};\n",
1406 |        "      __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1407 |        "      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
1408 |        "      __Pyx_GOTREF(__pyx_t_5);\n",
1409 |        "    } else\n",
1410 |        "    #endif\n",
1411 |        "    #if CYTHON_FAST_PYCCALL\n",
1412 |        "    if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {\n",
1413 |        "      PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_v_lat2};\n",
1414 |        "      __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1415 |        "      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
1416 |        "      __Pyx_GOTREF(__pyx_t_5);\n",
1417 |        "    } else\n",
1418 |        "    #endif\n",
1419 |        "    {\n",
1420 |        "      __pyx_t_6 = PyTuple_New(1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1421 |        "      __Pyx_GOTREF(__pyx_t_6);\n",
1422 |        "      __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_2); __pyx_t_2 = NULL;\n",
1423 |        "      __Pyx_INCREF(__pyx_v_lat2);\n",
1424 |        "      __Pyx_GIVEREF(__pyx_v_lat2);\n",
1425 |        "      PyTuple_SET_ITEM(__pyx_t_6, 0+1, __pyx_v_lat2);\n",
1426 |        "      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_6, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1427 |        "      __Pyx_GOTREF(__pyx_t_5);\n",
1428 |        "      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
1429 |        "    }\n",
1430 |        "  }\n",
1431 |        "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1432 |        "  __pyx_t_3 = PyNumber_Multiply(__pyx_t_1, __pyx_t_5); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1433 |        "  __Pyx_GOTREF(__pyx_t_3);\n",
1434 |        "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1435 |        "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1436 |        "  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1437 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
1438 |        "  __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_sin); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1439 |        "  __Pyx_GOTREF(__pyx_t_6);\n",
1440 |        "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1441 |        "  __pyx_t_1 = __Pyx_PyInt_TrueDivideObjC(__pyx_v_dlon, __pyx_int_2, 2, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1442 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
1443 |        "  __pyx_t_2 = NULL;\n",
1444 |        "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) {\n",
1445 |        "    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_6);\n",
1446 |        "    if (likely(__pyx_t_2)) {\n",
1447 |        "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);\n",
1448 |        "      __Pyx_INCREF(__pyx_t_2);\n",
1449 |        "      __Pyx_INCREF(function);\n",
1450 |        "      __Pyx_DECREF_SET(__pyx_t_6, function);\n",
1451 |        "    }\n",
1452 |        "  }\n",
1453 |        "  if (!__pyx_t_2) {\n",
1454 |        "    __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1455 |        "    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1456 |        "    __Pyx_GOTREF(__pyx_t_5);\n",
1457 |        "  } else {\n",
1458 |        "    #if CYTHON_FAST_PYCALL\n",
1459 |        "    if (PyFunction_Check(__pyx_t_6)) {\n",
1460 |        "      PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_t_1};\n",
1461 |        "      __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1462 |        "      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
1463 |        "      __Pyx_GOTREF(__pyx_t_5);\n",
1464 |        "      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1465 |        "    } else\n",
1466 |        "    #endif\n",
1467 |        "    #if CYTHON_FAST_PYCCALL\n",
1468 |        "    if (__Pyx_PyFastCFunction_Check(__pyx_t_6)) {\n",
1469 |        "      PyObject *__pyx_temp[2] = {__pyx_t_2, __pyx_t_1};\n",
1470 |        "      __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_6, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1471 |        "      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
1472 |        "      __Pyx_GOTREF(__pyx_t_5);\n",
1473 |        "      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1474 |        "    } else\n",
1475 |        "    #endif\n",
1476 |        "    {\n",
1477 |        "      __pyx_t_8 = PyTuple_New(1+1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1478 |        "      __Pyx_GOTREF(__pyx_t_8);\n",
1479 |        "      __Pyx_GIVEREF(__pyx_t_2); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_2); __pyx_t_2 = NULL;\n",
1480 |        "      __Pyx_GIVEREF(__pyx_t_1);\n",
1481 |        "      PyTuple_SET_ITEM(__pyx_t_8, 0+1, __pyx_t_1);\n",
1482 |        "      __pyx_t_1 = 0;\n",
1483 |        "      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_6, __pyx_t_8, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1484 |        "      __Pyx_GOTREF(__pyx_t_5);\n",
1485 |        "      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;\n",
1486 |        "    }\n",
1487 |        "  }\n",
1488 |        "  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
1489 |        "  __pyx_t_6 = PyNumber_Power(__pyx_t_5, __pyx_int_2, Py_None); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1490 |        "  __Pyx_GOTREF(__pyx_t_6);\n",
1491 |        "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1492 |        "  __pyx_t_5 = PyNumber_Multiply(__pyx_t_3, __pyx_t_6); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1493 |        "  __Pyx_GOTREF(__pyx_t_5);\n",
1494 |        "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1495 |        "  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
1496 |        "  __pyx_t_6 = PyNumber_Add(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
1497 |        "  __Pyx_GOTREF(__pyx_t_6);\n",
1498 |        "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
1499 |        "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1500 |        "  __pyx_v_a = __pyx_t_6;\n",
1501 |        "  __pyx_t_6 = 0;\n",
1502 |        "
+10:     c = 2 * np.arcsin(np.sqrt(a))
\n", 1503 | "
  __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1504 |        "  __Pyx_GOTREF(__pyx_t_5);\n",
1505 |        "  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_arcsin); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1506 |        "  __Pyx_GOTREF(__pyx_t_4);\n",
1507 |        "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1508 |        "  __pyx_t_3 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1509 |        "  __Pyx_GOTREF(__pyx_t_3);\n",
1510 |        "  __pyx_t_8 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_sqrt); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1511 |        "  __Pyx_GOTREF(__pyx_t_8);\n",
1512 |        "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1513 |        "  __pyx_t_3 = NULL;\n",
1514 |        "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_8))) {\n",
1515 |        "    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_8);\n",
1516 |        "    if (likely(__pyx_t_3)) {\n",
1517 |        "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_8);\n",
1518 |        "      __Pyx_INCREF(__pyx_t_3);\n",
1519 |        "      __Pyx_INCREF(function);\n",
1520 |        "      __Pyx_DECREF_SET(__pyx_t_8, function);\n",
1521 |        "    }\n",
1522 |        "  }\n",
1523 |        "  if (!__pyx_t_3) {\n",
1524 |        "    __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_8, __pyx_v_a); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1525 |        "    __Pyx_GOTREF(__pyx_t_5);\n",
1526 |        "  } else {\n",
1527 |        "    #if CYTHON_FAST_PYCALL\n",
1528 |        "    if (PyFunction_Check(__pyx_t_8)) {\n",
1529 |        "      PyObject *__pyx_temp[2] = {__pyx_t_3, __pyx_v_a};\n",
1530 |        "      __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_8, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1531 |        "      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1532 |        "      __Pyx_GOTREF(__pyx_t_5);\n",
1533 |        "    } else\n",
1534 |        "    #endif\n",
1535 |        "    #if CYTHON_FAST_PYCCALL\n",
1536 |        "    if (__Pyx_PyFastCFunction_Check(__pyx_t_8)) {\n",
1537 |        "      PyObject *__pyx_temp[2] = {__pyx_t_3, __pyx_v_a};\n",
1538 |        "      __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_8, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1539 |        "      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
1540 |        "      __Pyx_GOTREF(__pyx_t_5);\n",
1541 |        "    } else\n",
1542 |        "    #endif\n",
1543 |        "    {\n",
1544 |        "      __pyx_t_1 = PyTuple_New(1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1545 |        "      __Pyx_GOTREF(__pyx_t_1);\n",
1546 |        "      __Pyx_GIVEREF(__pyx_t_3); PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3); __pyx_t_3 = NULL;\n",
1547 |        "      __Pyx_INCREF(__pyx_v_a);\n",
1548 |        "      __Pyx_GIVEREF(__pyx_v_a);\n",
1549 |        "      PyTuple_SET_ITEM(__pyx_t_1, 0+1, __pyx_v_a);\n",
1550 |        "      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_8, __pyx_t_1, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1551 |        "      __Pyx_GOTREF(__pyx_t_5);\n",
1552 |        "      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1553 |        "    }\n",
1554 |        "  }\n",
1555 |        "  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;\n",
1556 |        "  __pyx_t_8 = NULL;\n",
1557 |        "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {\n",
1558 |        "    __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_4);\n",
1559 |        "    if (likely(__pyx_t_8)) {\n",
1560 |        "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);\n",
1561 |        "      __Pyx_INCREF(__pyx_t_8);\n",
1562 |        "      __Pyx_INCREF(function);\n",
1563 |        "      __Pyx_DECREF_SET(__pyx_t_4, function);\n",
1564 |        "    }\n",
1565 |        "  }\n",
1566 |        "  if (!__pyx_t_8) {\n",
1567 |        "    __pyx_t_6 = __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1568 |        "    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1569 |        "    __Pyx_GOTREF(__pyx_t_6);\n",
1570 |        "  } else {\n",
1571 |        "    #if CYTHON_FAST_PYCALL\n",
1572 |        "    if (PyFunction_Check(__pyx_t_4)) {\n",
1573 |        "      PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_t_5};\n",
1574 |        "      __pyx_t_6 = __Pyx_PyFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1575 |        "      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;\n",
1576 |        "      __Pyx_GOTREF(__pyx_t_6);\n",
1577 |        "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1578 |        "    } else\n",
1579 |        "    #endif\n",
1580 |        "    #if CYTHON_FAST_PYCCALL\n",
1581 |        "    if (__Pyx_PyFastCFunction_Check(__pyx_t_4)) {\n",
1582 |        "      PyObject *__pyx_temp[2] = {__pyx_t_8, __pyx_t_5};\n",
1583 |        "      __pyx_t_6 = __Pyx_PyCFunction_FastCall(__pyx_t_4, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1584 |        "      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;\n",
1585 |        "      __Pyx_GOTREF(__pyx_t_6);\n",
1586 |        "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
1587 |        "    } else\n",
1588 |        "    #endif\n",
1589 |        "    {\n",
1590 |        "      __pyx_t_1 = PyTuple_New(1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1591 |        "      __Pyx_GOTREF(__pyx_t_1);\n",
1592 |        "      __Pyx_GIVEREF(__pyx_t_8); PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_8); __pyx_t_8 = NULL;\n",
1593 |        "      __Pyx_GIVEREF(__pyx_t_5);\n",
1594 |        "      PyTuple_SET_ITEM(__pyx_t_1, 0+1, __pyx_t_5);\n",
1595 |        "      __pyx_t_5 = 0;\n",
1596 |        "      __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_1, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1597 |        "      __Pyx_GOTREF(__pyx_t_6);\n",
1598 |        "      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
1599 |        "    }\n",
1600 |        "  }\n",
1601 |        "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
1602 |        "  __pyx_t_4 = PyNumber_Multiply(__pyx_int_2, __pyx_t_6); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 10, __pyx_L1_error)\n",
1603 |        "  __Pyx_GOTREF(__pyx_t_4);\n",
1604 |        "  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
1605 |        "  __pyx_v_c = __pyx_t_4;\n",
1606 |        "  __pyx_t_4 = 0;\n",
1607 |        "
+11:     mi = miles_constant * c
\n", 1608 | "
  __pyx_t_4 = PyNumber_Multiply(__pyx_v_miles_constant, __pyx_v_c); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 11, __pyx_L1_error)\n",
1609 |        "  __Pyx_GOTREF(__pyx_t_4);\n",
1610 |        "  __pyx_v_mi = __pyx_t_4;\n",
1611 |        "  __pyx_t_4 = 0;\n",
1612 |        "
+12:     return mi
\n", 1613 | "
  __Pyx_XDECREF(__pyx_r);\n",
1614 |        "  __Pyx_INCREF(__pyx_v_mi);\n",
1615 |        "  __pyx_r = __pyx_v_mi;\n",
1616 |        "  goto __pyx_L0;\n",
1617 |        "
" 1618 | ], 1619 | "text/plain": [ 1620 | "" 1621 | ] 1622 | }, 1623 | "execution_count": 68, 1624 | "metadata": {}, 1625 | "output_type": "execute_result" 1626 | } 1627 | ], 1628 | "source": [ 1629 | "%%cython -a\n", 1630 | "\n", 1631 | "# Haversine cythonized (no other edits)\n", 1632 | "import numpy as np\n", 1633 | "cpdef haversine_cy(lat1, lon1, lat2, lon2):\n", 1634 | " miles_constant = 3959\n", 1635 | " lat1, lon1, lat2, lon2 = map(np.deg2rad, [lat1, lon1, lat2, lon2])\n", 1636 | " dlat = lat2 - lat1 \n", 1637 | " dlon = lon2 - lon1 \n", 1638 | " a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2\n", 1639 | " c = 2 * np.arcsin(np.sqrt(a)) \n", 1640 | " mi = miles_constant * c\n", 1641 | " return mi" 1642 | ] 1643 | }, 1644 | { 1645 | "cell_type": "markdown", 1646 | "metadata": {}, 1647 | "source": [ 1648 | "#### Time it" 1649 | ] 1650 | }, 1651 | { 1652 | "cell_type": "code", 1653 | "execution_count": 67, 1654 | "metadata": { 1655 | "collapsed": false, 1656 | "deletable": true, 1657 | "editable": true 1658 | }, 1659 | "outputs": [ 1660 | { 1661 | "name": "stdout", 1662 | "output_type": "stream", 1663 | "text": [ 1664 | "98.3 ms ± 6.42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" 1665 | ] 1666 | } 1667 | ], 1668 | "source": [ 1669 | "%timeit df['distance'] =\\\n", 1670 | " df.apply(lambda row: haversine_cy(40.671, -73.985,\\\n", 1671 | " row['latitude'], row['longitude']), axis=1)" 1672 | ] 1673 | }, 1674 | { 1675 | "cell_type": "markdown", 1676 | "metadata": {}, 1677 | "source": [ 1678 | "#### Redefine Haversine with data types and C libraries" 1679 | ] 1680 | }, 1681 | { 1682 | "cell_type": "code", 1683 | "execution_count": 70, 1684 | "metadata": { 1685 | "collapsed": false, 1686 | "deletable": true, 1687 | "editable": true 1688 | }, 1689 | "outputs": [ 1690 | { 1691 | "data": { 1692 | "text/html": [ 1693 | "\n", 1694 | "\n", 1695 | "\n", 1696 | "\n", 1697 | " \n", 1698 | " Cython: _cython_magic_52b523ae42eb5022300cbde7a2455256.pyx\n", 1699 | " \n", 2051 | " \n", 2058 | "\n", 2059 | "\n", 2060 | "

Generated by Cython 0.25.2

\n", 2061 | "

\n", 2062 | " Yellow lines hint at Python interaction.
\n", 2063 | " Click on a line that starts with a \"+\" to see the C code that Cython generated for it.\n", 2064 | "

\n", 2065 | "
+01: # Haversine cythonized
\n", 2066 | "
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
2067 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
2068 |        "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
2069 |        "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
2070 |        "
 02: from libc.math cimport sin, cos, acos, asin, sqrt
\n", 2071 | "
 03: 
\n", 2072 | "
+04: cdef deg2rad_cy(float deg):
\n", 2073 | "
static PyObject *__pyx_f_46_cython_magic_52b523ae42eb5022300cbde7a2455256_deg2rad_cy(float __pyx_v_deg) {\n",
2074 |        "  float __pyx_v_rad;\n",
2075 |        "  PyObject *__pyx_r = NULL;\n",
2076 |        "  __Pyx_RefNannyDeclarations\n",
2077 |        "  __Pyx_RefNannySetupContext(\"deg2rad_cy\", 0);\n",
2078 |        "/* … */\n",
2079 |        "  /* function exit code */\n",
2080 |        "  __pyx_L1_error:;\n",
2081 |        "  __Pyx_XDECREF(__pyx_t_1);\n",
2082 |        "  __Pyx_AddTraceback(\"_cython_magic_52b523ae42eb5022300cbde7a2455256.deg2rad_cy\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
2083 |        "  __pyx_r = 0;\n",
2084 |        "  __pyx_L0:;\n",
2085 |        "  __Pyx_XGIVEREF(__pyx_r);\n",
2086 |        "  __Pyx_RefNannyFinishContext();\n",
2087 |        "  return __pyx_r;\n",
2088 |        "}\n",
2089 |        "
 05:     cdef float rad
\n", 2090 | "
+06:     rad = 0.01745329252*deg
\n", 2091 | "
  __pyx_v_rad = (0.01745329252 * __pyx_v_deg);\n",
2092 |        "
+07:     return rad
\n", 2093 | "
  __Pyx_XDECREF(__pyx_r);\n",
2094 |        "  __pyx_t_1 = PyFloat_FromDouble(__pyx_v_rad); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
2095 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
2096 |        "  __pyx_r = __pyx_t_1;\n",
2097 |        "  __pyx_t_1 = 0;\n",
2098 |        "  goto __pyx_L0;\n",
2099 |        "
 08: 
\n", 2100 | "
+09: cpdef haversine_cy_dtyped(float lat1, float lon1, float lat2, float lon2):
\n", 2101 | "
static PyObject *__pyx_pw_46_cython_magic_52b523ae42eb5022300cbde7a2455256_1haversine_cy_dtyped(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
2102 |        "static PyObject *__pyx_f_46_cython_magic_52b523ae42eb5022300cbde7a2455256_haversine_cy_dtyped(float __pyx_v_lat1, float __pyx_v_lon1, float __pyx_v_lat2, float __pyx_v_lon2, CYTHON_UNUSED int __pyx_skip_dispatch) {\n",
2103 |        "  float __pyx_v_dlon;\n",
2104 |        "  float __pyx_v_dlat;\n",
2105 |        "  float __pyx_v_a;\n",
2106 |        "  float __pyx_v_c;\n",
2107 |        "  float __pyx_v_mi;\n",
2108 |        "  PyObject *__pyx_r = NULL;\n",
2109 |        "  __Pyx_RefNannyDeclarations\n",
2110 |        "  __Pyx_RefNannySetupContext(\"haversine_cy_dtyped\", 0);\n",
2111 |        "/* … */\n",
2112 |        "  /* function exit code */\n",
2113 |        "  __pyx_L1_error:;\n",
2114 |        "  __Pyx_XDECREF(__pyx_t_1);\n",
2115 |        "  __Pyx_XDECREF(__pyx_t_2);\n",
2116 |        "  __Pyx_XDECREF(__pyx_t_3);\n",
2117 |        "  __Pyx_XDECREF(__pyx_t_4);\n",
2118 |        "  __Pyx_XDECREF(__pyx_t_5);\n",
2119 |        "  __Pyx_XDECREF(__pyx_t_6);\n",
2120 |        "  __Pyx_AddTraceback(\"_cython_magic_52b523ae42eb5022300cbde7a2455256.haversine_cy_dtyped\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
2121 |        "  __pyx_r = 0;\n",
2122 |        "  __pyx_L0:;\n",
2123 |        "  __Pyx_XGIVEREF(__pyx_r);\n",
2124 |        "  __Pyx_RefNannyFinishContext();\n",
2125 |        "  return __pyx_r;\n",
2126 |        "}\n",
2127 |        "\n",
2128 |        "/* Python wrapper */\n",
2129 |        "static PyObject *__pyx_pw_46_cython_magic_52b523ae42eb5022300cbde7a2455256_1haversine_cy_dtyped(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
2130 |        "static PyObject *__pyx_pw_46_cython_magic_52b523ae42eb5022300cbde7a2455256_1haversine_cy_dtyped(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
2131 |        "  float __pyx_v_lat1;\n",
2132 |        "  float __pyx_v_lon1;\n",
2133 |        "  float __pyx_v_lat2;\n",
2134 |        "  float __pyx_v_lon2;\n",
2135 |        "  PyObject *__pyx_r = 0;\n",
2136 |        "  __Pyx_RefNannyDeclarations\n",
2137 |        "  __Pyx_RefNannySetupContext(\"haversine_cy_dtyped (wrapper)\", 0);\n",
2138 |        "  {\n",
2139 |        "    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_lat1,&__pyx_n_s_lon1,&__pyx_n_s_lat2,&__pyx_n_s_lon2,0};\n",
2140 |        "    PyObject* values[4] = {0,0,0,0};\n",
2141 |        "    if (unlikely(__pyx_kwds)) {\n",
2142 |        "      Py_ssize_t kw_args;\n",
2143 |        "      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);\n",
2144 |        "      switch (pos_args) {\n",
2145 |        "        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n",
2146 |        "        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
2147 |        "        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
2148 |        "        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
2149 |        "        case  0: break;\n",
2150 |        "        default: goto __pyx_L5_argtuple_error;\n",
2151 |        "      }\n",
2152 |        "      kw_args = PyDict_Size(__pyx_kwds);\n",
2153 |        "      switch (pos_args) {\n",
2154 |        "        case  0:\n",
2155 |        "        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lat1)) != 0)) kw_args--;\n",
2156 |        "        else goto __pyx_L5_argtuple_error;\n",
2157 |        "        case  1:\n",
2158 |        "        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lon1)) != 0)) kw_args--;\n",
2159 |        "        else {\n",
2160 |        "          __Pyx_RaiseArgtupleInvalid(\"haversine_cy_dtyped\", 1, 4, 4, 1); __PYX_ERR(0, 9, __pyx_L3_error)\n",
2161 |        "        }\n",
2162 |        "        case  2:\n",
2163 |        "        if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lat2)) != 0)) kw_args--;\n",
2164 |        "        else {\n",
2165 |        "          __Pyx_RaiseArgtupleInvalid(\"haversine_cy_dtyped\", 1, 4, 4, 2); __PYX_ERR(0, 9, __pyx_L3_error)\n",
2166 |        "        }\n",
2167 |        "        case  3:\n",
2168 |        "        if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_lon2)) != 0)) kw_args--;\n",
2169 |        "        else {\n",
2170 |        "          __Pyx_RaiseArgtupleInvalid(\"haversine_cy_dtyped\", 1, 4, 4, 3); __PYX_ERR(0, 9, __pyx_L3_error)\n",
2171 |        "        }\n",
2172 |        "      }\n",
2173 |        "      if (unlikely(kw_args > 0)) {\n",
2174 |        "        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"haversine_cy_dtyped\") < 0)) __PYX_ERR(0, 9, __pyx_L3_error)\n",
2175 |        "      }\n",
2176 |        "    } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {\n",
2177 |        "      goto __pyx_L5_argtuple_error;\n",
2178 |        "    } else {\n",
2179 |        "      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
2180 |        "      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
2181 |        "      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
2182 |        "      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n",
2183 |        "    }\n",
2184 |        "    __pyx_v_lat1 = __pyx_PyFloat_AsFloat(values[0]); if (unlikely((__pyx_v_lat1 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 9, __pyx_L3_error)\n",
2185 |        "    __pyx_v_lon1 = __pyx_PyFloat_AsFloat(values[1]); if (unlikely((__pyx_v_lon1 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 9, __pyx_L3_error)\n",
2186 |        "    __pyx_v_lat2 = __pyx_PyFloat_AsFloat(values[2]); if (unlikely((__pyx_v_lat2 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 9, __pyx_L3_error)\n",
2187 |        "    __pyx_v_lon2 = __pyx_PyFloat_AsFloat(values[3]); if (unlikely((__pyx_v_lon2 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 9, __pyx_L3_error)\n",
2188 |        "  }\n",
2189 |        "  goto __pyx_L4_argument_unpacking_done;\n",
2190 |        "  __pyx_L5_argtuple_error:;\n",
2191 |        "  __Pyx_RaiseArgtupleInvalid(\"haversine_cy_dtyped\", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 9, __pyx_L3_error)\n",
2192 |        "  __pyx_L3_error:;\n",
2193 |        "  __Pyx_AddTraceback(\"_cython_magic_52b523ae42eb5022300cbde7a2455256.haversine_cy_dtyped\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
2194 |        "  __Pyx_RefNannyFinishContext();\n",
2195 |        "  return NULL;\n",
2196 |        "  __pyx_L4_argument_unpacking_done:;\n",
2197 |        "  __pyx_r = __pyx_pf_46_cython_magic_52b523ae42eb5022300cbde7a2455256_haversine_cy_dtyped(__pyx_self, __pyx_v_lat1, __pyx_v_lon1, __pyx_v_lat2, __pyx_v_lon2);\n",
2198 |        "\n",
2199 |        "  /* function exit code */\n",
2200 |        "  __Pyx_RefNannyFinishContext();\n",
2201 |        "  return __pyx_r;\n",
2202 |        "}\n",
2203 |        "\n",
2204 |        "static PyObject *__pyx_pf_46_cython_magic_52b523ae42eb5022300cbde7a2455256_haversine_cy_dtyped(CYTHON_UNUSED PyObject *__pyx_self, float __pyx_v_lat1, float __pyx_v_lon1, float __pyx_v_lat2, float __pyx_v_lon2) {\n",
2205 |        "  PyObject *__pyx_r = NULL;\n",
2206 |        "  __Pyx_RefNannyDeclarations\n",
2207 |        "  __Pyx_RefNannySetupContext(\"haversine_cy_dtyped\", 0);\n",
2208 |        "  __Pyx_XDECREF(__pyx_r);\n",
2209 |        "  __pyx_t_1 = __pyx_f_46_cython_magic_52b523ae42eb5022300cbde7a2455256_haversine_cy_dtyped(__pyx_v_lat1, __pyx_v_lon1, __pyx_v_lat2, __pyx_v_lon2, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
2210 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
2211 |        "  __pyx_r = __pyx_t_1;\n",
2212 |        "  __pyx_t_1 = 0;\n",
2213 |        "  goto __pyx_L0;\n",
2214 |        "\n",
2215 |        "  /* function exit code */\n",
2216 |        "  __pyx_L1_error:;\n",
2217 |        "  __Pyx_XDECREF(__pyx_t_1);\n",
2218 |        "  __Pyx_AddTraceback(\"_cython_magic_52b523ae42eb5022300cbde7a2455256.haversine_cy_dtyped\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
2219 |        "  __pyx_r = NULL;\n",
2220 |        "  __pyx_L0:;\n",
2221 |        "  __Pyx_XGIVEREF(__pyx_r);\n",
2222 |        "  __Pyx_RefNannyFinishContext();\n",
2223 |        "  return __pyx_r;\n",
2224 |        "}\n",
2225 |        "
 10:     cdef:
\n", 2226 | "
 11:         float dlon
\n", 2227 | "
 12:         float dlat
\n", 2228 | "
 13:         float a
\n", 2229 | "
 14:         float c
\n", 2230 | "
 15:         float mi
\n", 2231 | "
 16: 
\n", 2232 | "
+17:     lat1, lon1, lat2, lon2 = map(deg2rad_cy, [lat1, lon1, lat2, lon2])
\n", 2233 | "
  __pyx_t_1 = __Pyx_CFunc_object____float___to_py(__pyx_f_46_cython_magic_52b523ae42eb5022300cbde7a2455256_deg2rad_cy); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2234 |        "  __Pyx_GOTREF(__pyx_t_1);\n",
2235 |        "  __pyx_t_2 = PyFloat_FromDouble(__pyx_v_lat1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2236 |        "  __Pyx_GOTREF(__pyx_t_2);\n",
2237 |        "  __pyx_t_3 = PyFloat_FromDouble(__pyx_v_lon1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2238 |        "  __Pyx_GOTREF(__pyx_t_3);\n",
2239 |        "  __pyx_t_4 = PyFloat_FromDouble(__pyx_v_lat2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2240 |        "  __Pyx_GOTREF(__pyx_t_4);\n",
2241 |        "  __pyx_t_5 = PyFloat_FromDouble(__pyx_v_lon2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2242 |        "  __Pyx_GOTREF(__pyx_t_5);\n",
2243 |        "  __pyx_t_6 = PyList_New(4); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2244 |        "  __Pyx_GOTREF(__pyx_t_6);\n",
2245 |        "  __Pyx_GIVEREF(__pyx_t_2);\n",
2246 |        "  PyList_SET_ITEM(__pyx_t_6, 0, __pyx_t_2);\n",
2247 |        "  __Pyx_GIVEREF(__pyx_t_3);\n",
2248 |        "  PyList_SET_ITEM(__pyx_t_6, 1, __pyx_t_3);\n",
2249 |        "  __Pyx_GIVEREF(__pyx_t_4);\n",
2250 |        "  PyList_SET_ITEM(__pyx_t_6, 2, __pyx_t_4);\n",
2251 |        "  __Pyx_GIVEREF(__pyx_t_5);\n",
2252 |        "  PyList_SET_ITEM(__pyx_t_6, 3, __pyx_t_5);\n",
2253 |        "  __pyx_t_2 = 0;\n",
2254 |        "  __pyx_t_3 = 0;\n",
2255 |        "  __pyx_t_4 = 0;\n",
2256 |        "  __pyx_t_5 = 0;\n",
2257 |        "  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2258 |        "  __Pyx_GOTREF(__pyx_t_5);\n",
2259 |        "  __Pyx_GIVEREF(__pyx_t_1);\n",
2260 |        "  PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_1);\n",
2261 |        "  __Pyx_GIVEREF(__pyx_t_6);\n",
2262 |        "  PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_6);\n",
2263 |        "  __pyx_t_1 = 0;\n",
2264 |        "  __pyx_t_6 = 0;\n",
2265 |        "  __pyx_t_6 = __Pyx_PyObject_Call(__pyx_builtin_map, __pyx_t_5, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2266 |        "  __Pyx_GOTREF(__pyx_t_6);\n",
2267 |        "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
2268 |        "  if ((likely(PyTuple_CheckExact(__pyx_t_6))) || (PyList_CheckExact(__pyx_t_6))) {\n",
2269 |        "    PyObject* sequence = __pyx_t_6;\n",
2270 |        "    #if !CYTHON_COMPILING_IN_PYPY\n",
2271 |        "    Py_ssize_t size = Py_SIZE(sequence);\n",
2272 |        "    #else\n",
2273 |        "    Py_ssize_t size = PySequence_Size(sequence);\n",
2274 |        "    #endif\n",
2275 |        "    if (unlikely(size != 4)) {\n",
2276 |        "      if (size > 4) __Pyx_RaiseTooManyValuesError(4);\n",
2277 |        "      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);\n",
2278 |        "      __PYX_ERR(0, 17, __pyx_L1_error)\n",
2279 |        "    }\n",
2280 |        "    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS\n",
2281 |        "    if (likely(PyTuple_CheckExact(sequence))) {\n",
2282 |        "      __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); \n",
2283 |        "      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 1); \n",
2284 |        "      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2); \n",
2285 |        "      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 3); \n",
2286 |        "    } else {\n",
2287 |        "      __pyx_t_5 = PyList_GET_ITEM(sequence, 0); \n",
2288 |        "      __pyx_t_1 = PyList_GET_ITEM(sequence, 1); \n",
2289 |        "      __pyx_t_4 = PyList_GET_ITEM(sequence, 2); \n",
2290 |        "      __pyx_t_3 = PyList_GET_ITEM(sequence, 3); \n",
2291 |        "    }\n",
2292 |        "    __Pyx_INCREF(__pyx_t_5);\n",
2293 |        "    __Pyx_INCREF(__pyx_t_1);\n",
2294 |        "    __Pyx_INCREF(__pyx_t_4);\n",
2295 |        "    __Pyx_INCREF(__pyx_t_3);\n",
2296 |        "    #else\n",
2297 |        "    {\n",
2298 |        "      Py_ssize_t i;\n",
2299 |        "      PyObject** temps[4] = {&__pyx_t_5,&__pyx_t_1,&__pyx_t_4,&__pyx_t_3};\n",
2300 |        "      for (i=0; i < 4; i++) {\n",
2301 |        "        PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2302 |        "        __Pyx_GOTREF(item);\n",
2303 |        "        *(temps[i]) = item;\n",
2304 |        "      }\n",
2305 |        "    }\n",
2306 |        "    #endif\n",
2307 |        "    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
2308 |        "  } else {\n",
2309 |        "    Py_ssize_t index = -1;\n",
2310 |        "    PyObject** temps[4] = {&__pyx_t_5,&__pyx_t_1,&__pyx_t_4,&__pyx_t_3};\n",
2311 |        "    __pyx_t_2 = PyObject_GetIter(__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2312 |        "    __Pyx_GOTREF(__pyx_t_2);\n",
2313 |        "    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;\n",
2314 |        "    __pyx_t_7 = Py_TYPE(__pyx_t_2)->tp_iternext;\n",
2315 |        "    for (index=0; index < 4; index++) {\n",
2316 |        "      PyObject* item = __pyx_t_7(__pyx_t_2); if (unlikely(!item)) goto __pyx_L3_unpacking_failed;\n",
2317 |        "      __Pyx_GOTREF(item);\n",
2318 |        "      *(temps[index]) = item;\n",
2319 |        "    }\n",
2320 |        "    if (__Pyx_IternextUnpackEndCheck(__pyx_t_7(__pyx_t_2), 4) < 0) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2321 |        "    __pyx_t_7 = NULL;\n",
2322 |        "    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
2323 |        "    goto __pyx_L4_unpacking_done;\n",
2324 |        "    __pyx_L3_unpacking_failed:;\n",
2325 |        "    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
2326 |        "    __pyx_t_7 = NULL;\n",
2327 |        "    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);\n",
2328 |        "    __PYX_ERR(0, 17, __pyx_L1_error)\n",
2329 |        "    __pyx_L4_unpacking_done:;\n",
2330 |        "  }\n",
2331 |        "  __pyx_t_8 = __pyx_PyFloat_AsFloat(__pyx_t_5); if (unlikely((__pyx_t_8 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2332 |        "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
2333 |        "  __pyx_t_9 = __pyx_PyFloat_AsFloat(__pyx_t_1); if (unlikely((__pyx_t_9 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2334 |        "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
2335 |        "  __pyx_t_10 = __pyx_PyFloat_AsFloat(__pyx_t_4); if (unlikely((__pyx_t_10 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2336 |        "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
2337 |        "  __pyx_t_11 = __pyx_PyFloat_AsFloat(__pyx_t_3); if (unlikely((__pyx_t_11 == (float)-1) && PyErr_Occurred())) __PYX_ERR(0, 17, __pyx_L1_error)\n",
2338 |        "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
2339 |        "  __pyx_v_lat1 = __pyx_t_8;\n",
2340 |        "  __pyx_v_lon1 = __pyx_t_9;\n",
2341 |        "  __pyx_v_lat2 = __pyx_t_10;\n",
2342 |        "  __pyx_v_lon2 = __pyx_t_11;\n",
2343 |        "
+18:     dlat = lat2 - lat1
\n", 2344 | "
  __pyx_v_dlat = (__pyx_v_lat2 - __pyx_v_lat1);\n",
2345 |        "
+19:     dlon = lon2 - lon1
\n", 2346 | "
  __pyx_v_dlon = (__pyx_v_lon2 - __pyx_v_lon1);\n",
2347 |        "
+20:     a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
\n", 2348 | "
  __pyx_v_a = (pow(sin((__pyx_v_dlat / 2.0)), 2.0) + ((cos(__pyx_v_lat1) * cos(__pyx_v_lat2)) * pow(sin((__pyx_v_dlon / 2.0)), 2.0)));\n",
2349 |        "
+21:     c = 2 * asin(sqrt(a))
\n", 2350 | "
  __pyx_v_c = (2.0 * asin(sqrt(__pyx_v_a)));\n",
2351 |        "
+22:     mi = 3959 * c
\n", 2352 | "
  __pyx_v_mi = (3959.0 * __pyx_v_c);\n",
2353 |        "
+23:     return mi
\n", 2354 | "
  __Pyx_XDECREF(__pyx_r);\n",
2355 |        "  __pyx_t_6 = PyFloat_FromDouble(__pyx_v_mi); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 23, __pyx_L1_error)\n",
2356 |        "  __Pyx_GOTREF(__pyx_t_6);\n",
2357 |        "  __pyx_r = __pyx_t_6;\n",
2358 |        "  __pyx_t_6 = 0;\n",
2359 |        "  goto __pyx_L0;\n",
2360 |        "
" 2361 | ], 2362 | "text/plain": [ 2363 | "" 2364 | ] 2365 | }, 2366 | "execution_count": 70, 2367 | "metadata": {}, 2368 | "output_type": "execute_result" 2369 | } 2370 | ], 2371 | "source": [ 2372 | "%%cython -a\n", 2373 | "# Haversine cythonized\n", 2374 | "from libc.math cimport sin, cos, acos, asin, sqrt\n", 2375 | "\n", 2376 | "cdef deg2rad_cy(float deg):\n", 2377 | " cdef float rad\n", 2378 | " rad = 0.01745329252*deg\n", 2379 | " return rad\n", 2380 | " \n", 2381 | "cpdef haversine_cy_dtyped(float lat1, float lon1, float lat2, float lon2):\n", 2382 | " cdef: \n", 2383 | " float dlon\n", 2384 | " float dlat\n", 2385 | " float a\n", 2386 | " float c\n", 2387 | " float mi\n", 2388 | " \n", 2389 | " lat1, lon1, lat2, lon2 = map(deg2rad_cy, [lat1, lon1, lat2, lon2])\n", 2390 | " dlat = lat2 - lat1 \n", 2391 | " dlon = lon2 - lon1 \n", 2392 | " a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2\n", 2393 | " c = 2 * asin(sqrt(a)) \n", 2394 | " mi = 3959 * c\n", 2395 | " return mi\n" 2396 | ] 2397 | }, 2398 | { 2399 | "cell_type": "markdown", 2400 | "metadata": {}, 2401 | "source": [ 2402 | "#### Time it" 2403 | ] 2404 | }, 2405 | { 2406 | "cell_type": "code", 2407 | "execution_count": 69, 2408 | "metadata": { 2409 | "collapsed": false, 2410 | "deletable": true, 2411 | "editable": true 2412 | }, 2413 | "outputs": [ 2414 | { 2415 | "name": "stdout", 2416 | "output_type": "stream", 2417 | "text": [ 2418 | "51.1 ms ± 2.74 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" 2419 | ] 2420 | } 2421 | ], 2422 | "source": [ 2423 | "%timeit df['distance'] =\\\n", 2424 | "df.apply(lambda row: haversine_cy_dtyped(40.671, -73.985,\\\n", 2425 | " row['latitude'], row['longitude']), axis=1)" 2426 | ] 2427 | } 2428 | ], 2429 | "metadata": { 2430 | "kernelspec": { 2431 | "display_name": "Python 3", 2432 | "language": "python", 2433 | "name": "python3" 2434 | }, 2435 | "language_info": { 2436 | "codemirror_mode": { 2437 | "name": "ipython", 2438 | "version": 3 2439 | }, 2440 | "file_extension": ".py", 2441 | "mimetype": "text/x-python", 2442 | "name": "python", 2443 | "nbconvert_exporter": "python", 2444 | "pygments_lexer": "ipython3", 2445 | "version": "3.5.1" 2446 | } 2447 | }, 2448 | "nbformat": 4, 2449 | "nbformat_minor": 2 2450 | } 2451 | --------------------------------------------------------------------------------