Changeset 388 for python/vendor/current/Modules/cmathmodule.c
- Timestamp:
- Mar 19, 2014, 11:11:30 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
python/vendor/current/Modules/cmathmodule.c
r2 r388 4 4 5 5 #include "Python.h" 6 #include "_math.h" 6 7 /* we need DBL_MAX, DBL_MIN, DBL_EPSILON, DBL_MANT_DIG and FLT_RADIX from 7 8 float.h. We assume that FLT_RADIX is either 2 or 16. */ … … 23 24 CM_LARGE_DOUBLE is used to avoid spurious overflow in the sqrt, log, 24 25 inverse trig and inverse hyperbolic trig functions. Its log is used in the 25 evaluation of exp, cos, cosh, sin, sinh, tan, and tanh to avoid un ecessary26 evaluation of exp, cos, cosh, sin, sinh, tan, and tanh to avoid unnecessary 26 27 overflow. 27 28 */ … … 32 33 #define CM_SQRT_DBL_MIN (sqrt(DBL_MIN)) 33 34 34 /* 35 /* 35 36 CM_SCALE_UP is an odd integer chosen such that multiplication by 36 37 2**CM_SCALE_UP is sufficient to turn a subnormal into a normal. … … 63 64 64 65 enum special_types { 65 ST_NINF,/* 0, negative infinity */66 ST_NEG,/* 1, negative finite number (nonzero) */67 ST_NZERO,/* 2, -0. */68 ST_PZERO,/* 3, +0. */69 ST_POS,/* 4, positive finite number (nonzero) */70 ST_PINF,/* 5, positive infinity */71 ST_NAN/* 6, Not a Number */66 ST_NINF, /* 0, negative infinity */ 67 ST_NEG, /* 1, negative finite number (nonzero) */ 68 ST_NZERO, /* 2, -0. */ 69 ST_PZERO, /* 3, +0. */ 70 ST_POS, /* 4, positive finite number (nonzero) */ 71 ST_PINF, /* 5, positive infinity */ 72 ST_NAN /* 6, Not a Number */ 72 73 }; 73 74 … … 75 76 special_type(double d) 76 77 { 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 } 98 99 #define SPECIAL_VALUE(z, table) 100 if (!Py_IS_FINITE((z).real) || !Py_IS_FINITE((z).imag)) {\101 102 return table[special_type((z).real)]\103 [special_type((z).imag)];\104 78 if (Py_IS_FINITE(d)) { 79 if (d != 0) { 80 if (copysign(1., d) == 1.) 81 return ST_POS; 82 else 83 return ST_NEG; 84 } 85 else { 86 if (copysign(1., d) == 1.) 87 return ST_PZERO; 88 else 89 return ST_NZERO; 90 } 91 } 92 if (Py_IS_NAN(d)) 93 return ST_NAN; 94 if (copysign(1., d) == 1.) 95 return ST_PINF; 96 else 97 return ST_NINF; 98 } 99 100 #define SPECIAL_VALUE(z, table) \ 101 if (!Py_IS_FINITE((z).real) || !Py_IS_FINITE((z).imag)) { \ 102 errno = 0; \ 103 return table[special_type((z).real)] \ 104 [special_type((z).imag)]; \ 105 } 105 106 106 107 #define P Py_MATH_PI … … 126 127 c_acos(Py_complex z) 127 128 { 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 r.imag =asinh(s2.real*s1.imag - s2.imag*s1.real);153 154 155 129 Py_complex s1, s2, r; 130 131 SPECIAL_VALUE(z, acos_special_values); 132 133 if (fabs(z.real) > CM_LARGE_DOUBLE || fabs(z.imag) > CM_LARGE_DOUBLE) { 134 /* avoid unnecessary overflow for large arguments */ 135 r.real = atan2(fabs(z.imag), z.real); 136 /* split into cases to make sure that the branch cut has the 137 correct continuity on systems with unsigned zeros */ 138 if (z.real < 0.) { 139 r.imag = -copysign(log(hypot(z.real/2., z.imag/2.)) + 140 M_LN2*2., z.imag); 141 } else { 142 r.imag = copysign(log(hypot(z.real/2., z.imag/2.)) + 143 M_LN2*2., -z.imag); 144 } 145 } else { 146 s1.real = 1.-z.real; 147 s1.imag = -z.imag; 148 s1 = c_sqrt(s1); 149 s2.real = 1.+z.real; 150 s2.imag = z.imag; 151 s2 = c_sqrt(s2); 152 r.real = 2.*atan2(s1.real, s2.real); 153 r.imag = m_asinh(s2.real*s1.imag - s2.imag*s1.real); 154 } 155 errno = 0; 156 return r; 156 157 } 157 158 … … 167 168 c_acosh(Py_complex z) 168 169 { 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 r.real =asinh(s1.real*s2.real + s1.imag*s2.imag);185 186 187 188 170 Py_complex s1, s2, r; 171 172 SPECIAL_VALUE(z, acosh_special_values); 173 174 if (fabs(z.real) > CM_LARGE_DOUBLE || fabs(z.imag) > CM_LARGE_DOUBLE) { 175 /* avoid unnecessary overflow for large arguments */ 176 r.real = log(hypot(z.real/2., z.imag/2.)) + M_LN2*2.; 177 r.imag = atan2(z.imag, z.real); 178 } else { 179 s1.real = z.real - 1.; 180 s1.imag = z.imag; 181 s1 = c_sqrt(s1); 182 s2.real = z.real + 1.; 183 s2.imag = z.imag; 184 s2 = c_sqrt(s2); 185 r.real = m_asinh(s1.real*s2.real + s1.imag*s2.imag); 186 r.imag = 2.*atan2(s1.imag, s2.real); 187 } 188 errno = 0; 189 return r; 189 190 } 190 191 … … 198 199 c_asin(Py_complex z) 199 200 { 200 201 202 203 204 205 206 207 201 /* asin(z) = -i asinh(iz) */ 202 Py_complex s, r; 203 s.real = -z.imag; 204 s.imag = z.real; 205 s = c_asinh(s); 206 r.real = s.imag; 207 r.imag = -s.real; 208 return r; 208 209 } 209 210 … … 219 220 c_asinh(Py_complex z) 220 221 { 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 r.real =asinh(s1.real*s2.imag-s2.real*s1.imag);242 243 244 245 222 Py_complex s1, s2, r; 223 224 SPECIAL_VALUE(z, asinh_special_values); 225 226 if (fabs(z.real) > CM_LARGE_DOUBLE || fabs(z.imag) > CM_LARGE_DOUBLE) { 227 if (z.imag >= 0.) { 228 r.real = copysign(log(hypot(z.real/2., z.imag/2.)) + 229 M_LN2*2., z.real); 230 } else { 231 r.real = -copysign(log(hypot(z.real/2., z.imag/2.)) + 232 M_LN2*2., -z.real); 233 } 234 r.imag = atan2(z.imag, fabs(z.real)); 235 } else { 236 s1.real = 1.+z.imag; 237 s1.imag = -z.real; 238 s1 = c_sqrt(s1); 239 s2.real = 1.-z.imag; 240 s2.imag = z.real; 241 s2 = c_sqrt(s2); 242 r.real = m_asinh(s1.real*s2.imag-s2.real*s1.imag); 243 r.imag = atan2(z.imag, s1.real*s2.real-s1.imag*s2.imag); 244 } 245 errno = 0; 246 return r; 246 247 } 247 248 … … 255 256 c_atan(Py_complex z) 256 257 { 257 258 259 260 261 262 263 264 258 /* atan(z) = -i atanh(iz) */ 259 Py_complex s, r; 260 s.real = -z.imag; 261 s.imag = z.real; 262 s = c_atanh(s); 263 r.real = s.imag; 264 r.imag = -s.real; 265 return r; 265 266 } 266 267 … … 270 271 c_atan2(Py_complex z) 271 272 { 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 273 if (Py_IS_NAN(z.real) || Py_IS_NAN(z.imag)) 274 return Py_NAN; 275 if (Py_IS_INFINITY(z.imag)) { 276 if (Py_IS_INFINITY(z.real)) { 277 if (copysign(1., z.real) == 1.) 278 /* atan2(+-inf, +inf) == +-pi/4 */ 279 return copysign(0.25*Py_MATH_PI, z.imag); 280 else 281 /* atan2(+-inf, -inf) == +-pi*3/4 */ 282 return copysign(0.75*Py_MATH_PI, z.imag); 283 } 284 /* atan2(+-inf, x) == +-pi/2 for finite x */ 285 return copysign(0.5*Py_MATH_PI, z.imag); 286 } 287 if (Py_IS_INFINITY(z.real) || z.imag == 0.) { 288 if (copysign(1., z.real) == 1.) 289 /* atan2(+-y, +inf) = atan2(+-0, +x) = +-0. */ 290 return copysign(0., z.imag); 291 else 292 /* atan2(+-y, -inf) = atan2(+-0., -x) = +-pi. */ 293 return copysign(Py_MATH_PI, z.imag); 294 } 295 return atan2(z.imag, z.real); 295 296 } 296 297 … … 306 307 c_atanh(Py_complex z) 307 308 { 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 r.real =log1p(4.*z.real/((1-z.real)*(1-z.real) + ay*ay))/4.;346 347 348 349 309 Py_complex r; 310 double ay, h; 311 312 SPECIAL_VALUE(z, atanh_special_values); 313 314 /* Reduce to case where z.real >= 0., using atanh(z) = -atanh(-z). */ 315 if (z.real < 0.) { 316 return c_neg(c_atanh(c_neg(z))); 317 } 318 319 ay = fabs(z.imag); 320 if (z.real > CM_SQRT_LARGE_DOUBLE || ay > CM_SQRT_LARGE_DOUBLE) { 321 /* 322 if abs(z) is large then we use the approximation 323 atanh(z) ~ 1/z +/- i*pi/2 (+/- depending on the sign 324 of z.imag) 325 */ 326 h = hypot(z.real/2., z.imag/2.); /* safe from overflow */ 327 r.real = z.real/4./h/h; 328 /* the two negations in the next line cancel each other out 329 except when working with unsigned zeros: they're there to 330 ensure that the branch cut has the correct continuity on 331 systems that don't support signed zeros */ 332 r.imag = -copysign(Py_MATH_PI/2., -z.imag); 333 errno = 0; 334 } else if (z.real == 1. && ay < CM_SQRT_DBL_MIN) { 335 /* C99 standard says: atanh(1+/-0.) should be inf +/- 0i */ 336 if (ay == 0.) { 337 r.real = INF; 338 r.imag = z.imag; 339 errno = EDOM; 340 } else { 341 r.real = -log(sqrt(ay)/sqrt(hypot(ay, 2.))); 342 r.imag = copysign(atan2(2., -ay)/2, z.imag); 343 errno = 0; 344 } 345 } else { 346 r.real = m_log1p(4.*z.real/((1-z.real)*(1-z.real) + ay*ay))/4.; 347 r.imag = -atan2(-2.*z.imag, (1-z.real)*(1+z.real) - ay*ay)/2.; 348 errno = 0; 349 } 350 return r; 350 351 } 351 352 … … 359 360 c_cos(Py_complex z) 360 361 { 361 362 363 364 365 366 362 /* cos(z) = cosh(iz) */ 363 Py_complex r; 364 r.real = -z.imag; 365 r.imag = z.real; 366 r = c_cosh(r); 367 return r; 367 368 } 368 369 … … 379 380 c_cosh(Py_complex z) 380 381 { 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 382 Py_complex r; 383 double x_minus_one; 384 385 /* special treatment for cosh(+/-inf + iy) if y is not a NaN */ 386 if (!Py_IS_FINITE(z.real) || !Py_IS_FINITE(z.imag)) { 387 if (Py_IS_INFINITY(z.real) && Py_IS_FINITE(z.imag) && 388 (z.imag != 0.)) { 389 if (z.real > 0) { 390 r.real = copysign(INF, cos(z.imag)); 391 r.imag = copysign(INF, sin(z.imag)); 392 } 393 else { 394 r.real = copysign(INF, cos(z.imag)); 395 r.imag = -copysign(INF, sin(z.imag)); 396 } 397 } 398 else { 399 r = cosh_special_values[special_type(z.real)] 400 [special_type(z.imag)]; 401 } 402 /* need to set errno = EDOM if y is +/- infinity and x is not 403 a NaN */ 404 if (Py_IS_INFINITY(z.imag) && !Py_IS_NAN(z.real)) 405 errno = EDOM; 406 else 407 errno = 0; 408 return r; 409 } 410 411 if (fabs(z.real) > CM_LOG_LARGE_DOUBLE) { 412 /* deal correctly with cases where cosh(z.real) overflows but 413 cosh(z) does not. */ 414 x_minus_one = z.real - copysign(1., z.real); 415 r.real = cos(z.imag) * cosh(x_minus_one) * Py_MATH_E; 416 r.imag = sin(z.imag) * sinh(x_minus_one) * Py_MATH_E; 417 } else { 418 r.real = cos(z.imag) * cosh(z.real); 419 r.imag = sin(z.imag) * sinh(z.real); 420 } 421 /* detect overflow, and set errno accordingly */ 422 if (Py_IS_INFINITY(r.real) || Py_IS_INFINITY(r.imag)) 423 errno = ERANGE; 424 else 425 errno = 0; 426 return r; 426 427 } 427 428 … … 439 440 c_exp(Py_complex z) 440 441 { 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 442 Py_complex r; 443 double l; 444 445 if (!Py_IS_FINITE(z.real) || !Py_IS_FINITE(z.imag)) { 446 if (Py_IS_INFINITY(z.real) && Py_IS_FINITE(z.imag) 447 && (z.imag != 0.)) { 448 if (z.real > 0) { 449 r.real = copysign(INF, cos(z.imag)); 450 r.imag = copysign(INF, sin(z.imag)); 451 } 452 else { 453 r.real = copysign(0., cos(z.imag)); 454 r.imag = copysign(0., sin(z.imag)); 455 } 456 } 457 else { 458 r = exp_special_values[special_type(z.real)] 459 [special_type(z.imag)]; 460 } 461 /* need to set errno = EDOM if y is +/- infinity and x is not 462 a NaN and not -infinity */ 463 if (Py_IS_INFINITY(z.imag) && 464 (Py_IS_FINITE(z.real) || 465 (Py_IS_INFINITY(z.real) && z.real > 0))) 466 errno = EDOM; 467 else 468 errno = 0; 469 return r; 470 } 471 472 if (z.real > CM_LOG_LARGE_DOUBLE) { 473 l = exp(z.real-1.); 474 r.real = l*cos(z.imag)*Py_MATH_E; 475 r.imag = l*sin(z.imag)*Py_MATH_E; 476 } else { 477 l = exp(z.real); 478 r.real = l*cos(z.imag); 479 r.imag = l*sin(z.imag); 480 } 481 /* detect overflow, and set errno accordingly */ 482 if (Py_IS_INFINITY(r.real) || Py_IS_INFINITY(r.imag)) 483 errno = ERANGE; 484 else 485 errno = 0; 486 return r; 486 487 } 487 488 … … 497 498 c_log(Py_complex z) 498 499 { 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 r.real =log1p((am-1)*(am+1)+an*an)/2.;556 557 558 559 560 561 562 500 /* 501 The usual formula for the real part is log(hypot(z.real, z.imag)). 502 There are four situations where this formula is potentially 503 problematic: 504 505 (1) the absolute value of z is subnormal. Then hypot is subnormal, 506 so has fewer than the usual number of bits of accuracy, hence may 507 have large relative error. This then gives a large absolute error 508 in the log. This can be solved by rescaling z by a suitable power 509 of 2. 510 511 (2) the absolute value of z is greater than DBL_MAX (e.g. when both 512 z.real and z.imag are within a factor of 1/sqrt(2) of DBL_MAX) 513 Again, rescaling solves this. 514 515 (3) the absolute value of z is close to 1. In this case it's 516 difficult to achieve good accuracy, at least in part because a 517 change of 1ulp in the real or imaginary part of z can result in a 518 change of billions of ulps in the correctly rounded answer. 519 520 (4) z = 0. The simplest thing to do here is to call the 521 floating-point log with an argument of 0, and let its behaviour 522 (returning -infinity, signaling a floating-point exception, setting 523 errno, or whatever) determine that of c_log. So the usual formula 524 is fine here. 525 526 */ 527 528 Py_complex r; 529 double ax, ay, am, an, h; 530 531 SPECIAL_VALUE(z, log_special_values); 532 533 ax = fabs(z.real); 534 ay = fabs(z.imag); 535 536 if (ax > CM_LARGE_DOUBLE || ay > CM_LARGE_DOUBLE) { 537 r.real = log(hypot(ax/2., ay/2.)) + M_LN2; 538 } else if (ax < DBL_MIN && ay < DBL_MIN) { 539 if (ax > 0. || ay > 0.) { 540 /* catch cases where hypot(ax, ay) is subnormal */ 541 r.real = log(hypot(ldexp(ax, DBL_MANT_DIG), 542 ldexp(ay, DBL_MANT_DIG))) - DBL_MANT_DIG*M_LN2; 543 } 544 else { 545 /* log(+/-0. +/- 0i) */ 546 r.real = -INF; 547 r.imag = atan2(z.imag, z.real); 548 errno = EDOM; 549 return r; 550 } 551 } else { 552 h = hypot(ax, ay); 553 if (0.71 <= h && h <= 1.73) { 554 am = ax > ay ? ax : ay; /* max(ax, ay) */ 555 an = ax > ay ? ay : ax; /* min(ax, ay) */ 556 r.real = m_log1p((am-1)*(am+1)+an*an)/2.; 557 } else { 558 r.real = log(h); 559 } 560 } 561 r.imag = atan2(z.imag, z.real); 562 errno = 0; 563 return r; 563 564 } 564 565 … … 567 568 c_log10(Py_complex z) 568 569 { 569 570 571 572 573 574 575 576 577 570 Py_complex r; 571 int errno_save; 572 573 r = c_log(z); 574 errno_save = errno; /* just in case the divisions affect errno */ 575 r.real = r.real / M_LN10; 576 r.imag = r.imag / M_LN10; 577 errno = errno_save; 578 return r; 578 579 } 579 580 … … 587 588 c_sin(Py_complex z) 588 589 { 589 590 591 592 593 594 595 596 590 /* sin(z) = -i sin(iz) */ 591 Py_complex s, r; 592 s.real = -z.imag; 593 s.imag = z.real; 594 s = c_sinh(s); 595 r.real = s.imag; 596 r.imag = -s.real; 597 return r; 597 598 } 598 599 … … 609 610 c_sinh(Py_complex z) 610 611 { 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 612 Py_complex r; 613 double x_minus_one; 614 615 /* special treatment for sinh(+/-inf + iy) if y is finite and 616 nonzero */ 617 if (!Py_IS_FINITE(z.real) || !Py_IS_FINITE(z.imag)) { 618 if (Py_IS_INFINITY(z.real) && Py_IS_FINITE(z.imag) 619 && (z.imag != 0.)) { 620 if (z.real > 0) { 621 r.real = copysign(INF, cos(z.imag)); 622 r.imag = copysign(INF, sin(z.imag)); 623 } 624 else { 625 r.real = -copysign(INF, cos(z.imag)); 626 r.imag = copysign(INF, sin(z.imag)); 627 } 628 } 629 else { 630 r = sinh_special_values[special_type(z.real)] 631 [special_type(z.imag)]; 632 } 633 /* need to set errno = EDOM if y is +/- infinity and x is not 634 a NaN */ 635 if (Py_IS_INFINITY(z.imag) && !Py_IS_NAN(z.real)) 636 errno = EDOM; 637 else 638 errno = 0; 639 return r; 640 } 641 642 if (fabs(z.real) > CM_LOG_LARGE_DOUBLE) { 643 x_minus_one = z.real - copysign(1., z.real); 644 r.real = cos(z.imag) * sinh(x_minus_one) * Py_MATH_E; 645 r.imag = sin(z.imag) * cosh(x_minus_one) * Py_MATH_E; 646 } else { 647 r.real = cos(z.imag) * sinh(z.real); 648 r.imag = sin(z.imag) * cosh(z.real); 649 } 650 /* detect overflow, and set errno accordingly */ 651 if (Py_IS_INFINITY(r.real) || Py_IS_INFINITY(r.imag)) 652 errno = ERANGE; 653 else 654 errno = 0; 655 return r; 655 656 } 656 657 … … 666 667 c_sqrt(Py_complex z) 667 668 { 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 669 /* 670 Method: use symmetries to reduce to the case when x = z.real and y 671 = z.imag are nonnegative. Then the real part of the result is 672 given by 673 674 s = sqrt((x + hypot(x, y))/2) 675 676 and the imaginary part is 677 678 d = (y/2)/s 679 680 If either x or y is very large then there's a risk of overflow in 681 computation of the expression x + hypot(x, y). We can avoid this 682 by rewriting the formula for s as: 683 684 s = 2*sqrt(x/8 + hypot(x/8, y/8)) 685 686 This costs us two extra multiplications/divisions, but avoids the 687 overhead of checking for x and y large. 688 689 If both x and y are subnormal then hypot(x, y) may also be 690 subnormal, so will lack full precision. We solve this by rescaling 691 x and y by a sufficiently large power of 2 to ensure that x and y 692 are normal. 693 */ 694 695 696 Py_complex r; 697 double s,d; 698 double ax, ay; 699 700 SPECIAL_VALUE(z, sqrt_special_values); 701 702 if (z.real == 0. && z.imag == 0.) { 703 r.real = 0.; 704 r.imag = z.imag; 705 return r; 706 } 707 708 ax = fabs(z.real); 709 ay = fabs(z.imag); 710 711 if (ax < DBL_MIN && ay < DBL_MIN && (ax > 0. || ay > 0.)) { 712 /* here we catch cases where hypot(ax, ay) is subnormal */ 713 ax = ldexp(ax, CM_SCALE_UP); 714 s = ldexp(sqrt(ax + hypot(ax, ldexp(ay, CM_SCALE_UP))), 715 CM_SCALE_DOWN); 716 } else { 717 ax /= 8.; 718 s = 2.*sqrt(ax + hypot(ax, ay/8.)); 719 } 720 d = ay/(2.*s); 721 722 if (z.real >= 0.) { 723 r.real = s; 724 r.imag = copysign(d, z.imag); 725 } else { 726 r.real = d; 727 r.imag = copysign(s, z.imag); 728 } 729 errno = 0; 730 return r; 730 731 } 731 732 … … 739 740 c_tan(Py_complex z) 740 741 { 741 742 743 744 745 746 747 748 742 /* tan(z) = -i tanh(iz) */ 743 Py_complex s, r; 744 s.real = -z.imag; 745 s.imag = z.real; 746 s = c_tanh(s); 747 r.real = s.imag; 748 r.imag = -s.real; 749 return r; 749 750 } 750 751 … … 761 762 c_tanh(Py_complex z) 762 763 { 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 764 /* Formula: 765 766 tanh(x+iy) = (tanh(x)(1+tan(y)^2) + i tan(y)(1-tanh(x))^2) / 767 (1+tan(y)^2 tanh(x)^2) 768 769 To avoid excessive roundoff error, 1-tanh(x)^2 is better computed 770 as 1/cosh(x)^2. When abs(x) is large, we approximate 1-tanh(x)^2 771 by 4 exp(-2*x) instead, to avoid possible overflow in the 772 computation of cosh(x). 773 774 */ 775 776 Py_complex r; 777 double tx, ty, cx, txty, denom; 778 779 /* special treatment for tanh(+/-inf + iy) if y is finite and 780 nonzero */ 781 if (!Py_IS_FINITE(z.real) || !Py_IS_FINITE(z.imag)) { 782 if (Py_IS_INFINITY(z.real) && Py_IS_FINITE(z.imag) 783 && (z.imag != 0.)) { 784 if (z.real > 0) { 785 r.real = 1.0; 786 r.imag = copysign(0., 787 2.*sin(z.imag)*cos(z.imag)); 788 } 789 else { 790 r.real = -1.0; 791 r.imag = copysign(0., 792 2.*sin(z.imag)*cos(z.imag)); 793 } 794 } 795 else { 796 r = tanh_special_values[special_type(z.real)] 797 [special_type(z.imag)]; 798 } 799 /* need to set errno = EDOM if z.imag is +/-infinity and 800 z.real is finite */ 801 if (Py_IS_INFINITY(z.imag) && Py_IS_FINITE(z.real)) 802 errno = EDOM; 803 else 804 errno = 0; 805 return r; 806 } 807 808 /* danger of overflow in 2.*z.imag !*/ 809 if (fabs(z.real) > CM_LOG_LARGE_DOUBLE) { 810 r.real = copysign(1., z.real); 811 r.imag = 4.*sin(z.imag)*cos(z.imag)*exp(-2.*fabs(z.real)); 812 } else { 813 tx = tanh(z.real); 814 ty = tan(z.imag); 815 cx = 1./cosh(z.real); 816 txty = tx*ty; 817 denom = 1. + txty*txty; 818 r.real = tx*(1.+ty*ty)/denom; 819 r.imag = ((ty/denom)*cx)*cx; 820 } 821 errno = 0; 822 return r; 822 823 } 823 824 … … 831 832 cmath_log(PyObject *self, PyObject *args) 832 833 { 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 834 Py_complex x; 835 Py_complex y; 836 837 if (!PyArg_ParseTuple(args, "D|D", &x, &y)) 838 return NULL; 839 840 errno = 0; 841 PyFPE_START_PROTECT("complex function", return 0) 842 x = c_log(x); 843 if (PyTuple_GET_SIZE(args) == 2) { 844 y = c_log(y); 845 x = c_quot(x, y); 846 } 847 PyFPE_END_PROTECT(x) 848 if (errno != 0) 849 return math_error(); 850 return PyComplex_FromCComplex(x); 850 851 } 851 852 … … 860 861 math_error(void) 861 862 { 862 863 864 865 866 867 868 863 if (errno == EDOM) 864 PyErr_SetString(PyExc_ValueError, "math domain error"); 865 else if (errno == ERANGE) 866 PyErr_SetString(PyExc_OverflowError, "math range error"); 867 else /* Unexpected math error */ 868 PyErr_SetFromErrno(PyExc_ValueError); 869 return NULL; 869 870 } 870 871 … … 872 873 math_1(PyObject *args, Py_complex (*func)(Py_complex)) 873 874 { 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 875 Py_complex x,r ; 876 if (!PyArg_ParseTuple(args, "D", &x)) 877 return NULL; 878 errno = 0; 879 PyFPE_START_PROTECT("complex function", return 0); 880 r = (*func)(x); 881 PyFPE_END_PROTECT(r); 882 if (errno == EDOM) { 883 PyErr_SetString(PyExc_ValueError, "math domain error"); 884 return NULL; 885 } 886 else if (errno == ERANGE) { 887 PyErr_SetString(PyExc_OverflowError, "math range error"); 888 return NULL; 889 } 890 else { 891 return PyComplex_FromCComplex(r); 892 } 892 893 } 893 894 894 895 #define FUNC1(stubname, func) \ 895 896 897 896 static PyObject * stubname(PyObject *self, PyObject *args) { \ 897 return math_1(args, func); \ 898 } 898 899 899 900 FUNC1(cmath_acos, c_acos) … … 916 917 cmath_phase(PyObject *self, PyObject *args) 917 918 { 918 919 920 921 922 923 924 925 926 927 928 929 919 Py_complex z; 920 double phi; 921 if (!PyArg_ParseTuple(args, "D:phase", &z)) 922 return NULL; 923 errno = 0; 924 PyFPE_START_PROTECT("arg function", return 0) 925 phi = c_atan2(z); 926 PyFPE_END_PROTECT(phi) 927 if (errno != 0) 928 return math_error(); 929 else 930 return PyFloat_FromDouble(phi); 930 931 } 931 932 … … 937 938 cmath_polar(PyObject *self, PyObject *args) 938 939 { 939 940 941 942 943 944 945 946 947 948 949 950 940 Py_complex z; 941 double r, phi; 942 if (!PyArg_ParseTuple(args, "D:polar", &z)) 943 return NULL; 944 PyFPE_START_PROTECT("polar function", return 0) 945 phi = c_atan2(z); /* should not cause any exception */ 946 r = c_abs(z); /* sets errno to ERANGE on overflow; otherwise 0 */ 947 PyFPE_END_PROTECT(r) 948 if (errno != 0) 949 return math_error(); 950 else 951 return Py_BuildValue("dd", r, phi); 951 952 } 952 953 … … 972 973 cmath_rect(PyObject *self, PyObject *args) 973 974 { 974 Py_complex z; 975 double r, phi; 976 if (!PyArg_ParseTuple(args, "dd:rect", &r, &phi)) 977 return NULL; 978 errno = 0; 979 PyFPE_START_PROTECT("rect function", return 0) 980 981 /* deal with special values */ 982 if (!Py_IS_FINITE(r) || !Py_IS_FINITE(phi)) { 983 /* if r is +/-infinity and phi is finite but nonzero then 984 result is (+-INF +-INF i), but we need to compute cos(phi) 985 and sin(phi) to figure out the signs. */ 986 if (Py_IS_INFINITY(r) && (Py_IS_FINITE(phi) 987 && (phi != 0.))) { 988 if (r > 0) { 989 z.real = copysign(INF, cos(phi)); 990 z.imag = copysign(INF, sin(phi)); 991 } 992 else { 993 z.real = -copysign(INF, cos(phi)); 994 z.imag = -copysign(INF, sin(phi)); 995 } 996 } 997 else { 998 z = rect_special_values[special_type(r)] 999 [special_type(phi)]; 1000 } 1001 /* need to set errno = EDOM if r is a nonzero number and phi 1002 is infinite */ 1003 if (r != 0. && !Py_IS_NAN(r) && Py_IS_INFINITY(phi)) 1004 errno = EDOM; 1005 else 1006 errno = 0; 1007 } 1008 else { 1009 z.real = r * cos(phi); 1010 z.imag = r * sin(phi); 1011 errno = 0; 1012 } 1013 1014 PyFPE_END_PROTECT(z) 1015 if (errno != 0) 1016 return math_error(); 1017 else 1018 return PyComplex_FromCComplex(z); 975 Py_complex z; 976 double r, phi; 977 if (!PyArg_ParseTuple(args, "dd:rect", &r, &phi)) 978 return NULL; 979 errno = 0; 980 PyFPE_START_PROTECT("rect function", return 0) 981 982 /* deal with special values */ 983 if (!Py_IS_FINITE(r) || !Py_IS_FINITE(phi)) { 984 /* if r is +/-infinity and phi is finite but nonzero then 985 result is (+-INF +-INF i), but we need to compute cos(phi) 986 and sin(phi) to figure out the signs. */ 987 if (Py_IS_INFINITY(r) && (Py_IS_FINITE(phi) 988 && (phi != 0.))) { 989 if (r > 0) { 990 z.real = copysign(INF, cos(phi)); 991 z.imag = copysign(INF, sin(phi)); 992 } 993 else { 994 z.real = -copysign(INF, cos(phi)); 995 z.imag = -copysign(INF, sin(phi)); 996 } 997 } 998 else { 999 z = rect_special_values[special_type(r)] 1000 [special_type(phi)]; 1001 } 1002 /* need to set errno = EDOM if r is a nonzero number and phi 1003 is infinite */ 1004 if (r != 0. && !Py_IS_NAN(r) && Py_IS_INFINITY(phi)) 1005 errno = EDOM; 1006 else 1007 errno = 0; 1008 } 1009 else if (phi == 0.0) { 1010 /* Workaround for buggy results with phi=-0.0 on OS X 10.8. See 1011 bugs.python.org/issue18513. */ 1012 z.real = r; 1013 z.imag = r * phi; 1014 errno = 0; 1015 } 1016 else { 1017 z.real = r * cos(phi); 1018 z.imag = r * sin(phi); 1019 errno = 0; 1020 } 1021 1022 PyFPE_END_PROTECT(z) 1023 if (errno != 0) 1024 return math_error(); 1025 else 1026 return PyComplex_FromCComplex(z); 1019 1027 } 1020 1028 … … 1026 1034 cmath_isnan(PyObject *self, PyObject *args) 1027 1035 { 1028 1029 1030 1031 1036 Py_complex z; 1037 if (!PyArg_ParseTuple(args, "D:isnan", &z)) 1038 return NULL; 1039 return PyBool_FromLong(Py_IS_NAN(z.real) || Py_IS_NAN(z.imag)); 1032 1040 } 1033 1041 … … 1039 1047 cmath_isinf(PyObject *self, PyObject *args) 1040 1048 { 1041 1042 1043 1044 1045 1049 Py_complex z; 1050 if (!PyArg_ParseTuple(args, "D:isnan", &z)) 1051 return NULL; 1052 return PyBool_FromLong(Py_IS_INFINITY(z.real) || 1053 Py_IS_INFINITY(z.imag)); 1046 1054 } 1047 1055 … … 1056 1064 1057 1065 static PyMethodDef cmath_methods[] = { 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 {NULL, NULL}/* sentinel */1066 {"acos", cmath_acos, METH_VARARGS, c_acos_doc}, 1067 {"acosh", cmath_acosh, METH_VARARGS, c_acosh_doc}, 1068 {"asin", cmath_asin, METH_VARARGS, c_asin_doc}, 1069 {"asinh", cmath_asinh, METH_VARARGS, c_asinh_doc}, 1070 {"atan", cmath_atan, METH_VARARGS, c_atan_doc}, 1071 {"atanh", cmath_atanh, METH_VARARGS, c_atanh_doc}, 1072 {"cos", cmath_cos, METH_VARARGS, c_cos_doc}, 1073 {"cosh", cmath_cosh, METH_VARARGS, c_cosh_doc}, 1074 {"exp", cmath_exp, METH_VARARGS, c_exp_doc}, 1075 {"isinf", cmath_isinf, METH_VARARGS, cmath_isinf_doc}, 1076 {"isnan", cmath_isnan, METH_VARARGS, cmath_isnan_doc}, 1077 {"log", cmath_log, METH_VARARGS, cmath_log_doc}, 1078 {"log10", cmath_log10, METH_VARARGS, c_log10_doc}, 1079 {"phase", cmath_phase, METH_VARARGS, cmath_phase_doc}, 1080 {"polar", cmath_polar, METH_VARARGS, cmath_polar_doc}, 1081 {"rect", cmath_rect, METH_VARARGS, cmath_rect_doc}, 1082 {"sin", cmath_sin, METH_VARARGS, c_sin_doc}, 1083 {"sinh", cmath_sinh, METH_VARARGS, c_sinh_doc}, 1084 {"sqrt", cmath_sqrt, METH_VARARGS, c_sqrt_doc}, 1085 {"tan", cmath_tan, METH_VARARGS, c_tan_doc}, 1086 {"tanh", cmath_tanh, METH_VARARGS, c_tanh_doc}, 1087 {NULL, NULL} /* sentinel */ 1080 1088 }; 1081 1089 … … 1083 1091 initcmath(void) 1084 1092 { 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1093 PyObject *m; 1094 1095 m = Py_InitModule3("cmath", cmath_methods, module_doc); 1096 if (m == NULL) 1097 return; 1098 1099 PyModule_AddObject(m, "pi", 1100 PyFloat_FromDouble(Py_MATH_PI)); 1101 PyModule_AddObject(m, "e", PyFloat_FromDouble(Py_MATH_E)); 1102 1103 /* initialize special value tables */ 1096 1104 1097 1105 #define INIT_SPECIAL_VALUES(NAME, BODY) { Py_complex* p = (Py_complex*)NAME; BODY } 1098 1106 #define C(REAL, IMAG) p->real = REAL; p->imag = IMAG; ++p; 1099 1107 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 } 1108 INIT_SPECIAL_VALUES(acos_special_values, { 1109 C(P34,INF) C(P,INF) C(P,INF) C(P,-INF) C(P,-INF) C(P34,-INF) C(N,INF) 1110 C(P12,INF) C(U,U) C(U,U) C(U,U) C(U,U) C(P12,-INF) C(N,N) 1111 C(P12,INF) C(U,U) C(P12,0.) C(P12,-0.) C(U,U) C(P12,-INF) C(P12,N) 1112 C(P12,INF) C(U,U) C(P12,0.) C(P12,-0.) C(U,U) C(P12,-INF) C(P12,N) 1113 C(P12,INF) C(U,U) C(U,U) C(U,U) C(U,U) C(P12,-INF) C(N,N) 1114 C(P14,INF) C(0.,INF) C(0.,INF) C(0.,-INF) C(0.,-INF) C(P14,-INF) C(N,INF) 1115 C(N,INF) C(N,N) C(N,N) C(N,N) C(N,N) C(N,-INF) C(N,N) 1116 }) 1117 1118 INIT_SPECIAL_VALUES(acosh_special_values, { 1119 C(INF,-P34) C(INF,-P) C(INF,-P) C(INF,P) C(INF,P) C(INF,P34) C(INF,N) 1120 C(INF,-P12) C(U,U) C(U,U) C(U,U) C(U,U) C(INF,P12) C(N,N) 1121 C(INF,-P12) C(U,U) C(0.,-P12) C(0.,P12) C(U,U) C(INF,P12) C(N,N) 1122 C(INF,-P12) C(U,U) C(0.,-P12) C(0.,P12) C(U,U) C(INF,P12) C(N,N) 1123 C(INF,-P12) C(U,U) C(U,U) C(U,U) C(U,U) C(INF,P12) C(N,N) 1124 C(INF,-P14) C(INF,-0.) C(INF,-0.) C(INF,0.) C(INF,0.) C(INF,P14) C(INF,N) 1125 C(INF,N) C(N,N) C(N,N) C(N,N) C(N,N) C(INF,N) C(N,N) 1126 }) 1127 1128 INIT_SPECIAL_VALUES(asinh_special_values, { 1129 C(-INF,-P14) C(-INF,-0.) C(-INF,-0.) C(-INF,0.) C(-INF,0.) C(-INF,P14) C(-INF,N) 1130 C(-INF,-P12) C(U,U) C(U,U) C(U,U) C(U,U) C(-INF,P12) C(N,N) 1131 C(-INF,-P12) C(U,U) C(-0.,-0.) C(-0.,0.) C(U,U) C(-INF,P12) C(N,N) 1132 C(INF,-P12) C(U,U) C(0.,-0.) C(0.,0.) C(U,U) C(INF,P12) C(N,N) 1133 C(INF,-P12) C(U,U) C(U,U) C(U,U) C(U,U) C(INF,P12) C(N,N) 1134 C(INF,-P14) C(INF,-0.) C(INF,-0.) C(INF,0.) C(INF,0.) C(INF,P14) C(INF,N) 1135 C(INF,N) C(N,N) C(N,-0.) C(N,0.) C(N,N) C(INF,N) C(N,N) 1136 }) 1137 1138 INIT_SPECIAL_VALUES(atanh_special_values, { 1139 C(-0.,-P12) C(-0.,-P12) C(-0.,-P12) C(-0.,P12) C(-0.,P12) C(-0.,P12) C(-0.,N) 1140 C(-0.,-P12) C(U,U) C(U,U) C(U,U) C(U,U) C(-0.,P12) C(N,N) 1141 C(-0.,-P12) C(U,U) C(-0.,-0.) C(-0.,0.) C(U,U) C(-0.,P12) C(-0.,N) 1142 C(0.,-P12) C(U,U) C(0.,-0.) C(0.,0.) C(U,U) C(0.,P12) C(0.,N) 1143 C(0.,-P12) C(U,U) C(U,U) C(U,U) C(U,U) C(0.,P12) C(N,N) 1144 C(0.,-P12) C(0.,-P12) C(0.,-P12) C(0.,P12) C(0.,P12) C(0.,P12) C(0.,N) 1145 C(0.,-P12) C(N,N) C(N,N) C(N,N) C(N,N) C(0.,P12) C(N,N) 1146 }) 1147 1148 INIT_SPECIAL_VALUES(cosh_special_values, { 1149 C(INF,N) C(U,U) C(INF,0.) C(INF,-0.) C(U,U) C(INF,N) C(INF,N) 1150 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1151 C(N,0.) C(U,U) C(1.,0.) C(1.,-0.) C(U,U) C(N,0.) C(N,0.) 1152 C(N,0.) C(U,U) C(1.,-0.) C(1.,0.) C(U,U) C(N,0.) C(N,0.) 1153 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1154 C(INF,N) C(U,U) C(INF,-0.) C(INF,0.) C(U,U) C(INF,N) C(INF,N) 1155 C(N,N) C(N,N) C(N,0.) C(N,0.) C(N,N) C(N,N) C(N,N) 1156 }) 1157 1158 INIT_SPECIAL_VALUES(exp_special_values, { 1159 C(0.,0.) C(U,U) C(0.,-0.) C(0.,0.) C(U,U) C(0.,0.) C(0.,0.) 1160 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1161 C(N,N) C(U,U) C(1.,-0.) C(1.,0.) C(U,U) C(N,N) C(N,N) 1162 C(N,N) C(U,U) C(1.,-0.) C(1.,0.) C(U,U) C(N,N) C(N,N) 1163 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1164 C(INF,N) C(U,U) C(INF,-0.) C(INF,0.) C(U,U) C(INF,N) C(INF,N) 1165 C(N,N) C(N,N) C(N,-0.) C(N,0.) C(N,N) C(N,N) C(N,N) 1166 }) 1167 1168 INIT_SPECIAL_VALUES(log_special_values, { 1169 C(INF,-P34) C(INF,-P) C(INF,-P) C(INF,P) C(INF,P) C(INF,P34) C(INF,N) 1170 C(INF,-P12) C(U,U) C(U,U) C(U,U) C(U,U) C(INF,P12) C(N,N) 1171 C(INF,-P12) C(U,U) C(-INF,-P) C(-INF,P) C(U,U) C(INF,P12) C(N,N) 1172 C(INF,-P12) C(U,U) C(-INF,-0.) C(-INF,0.) C(U,U) C(INF,P12) C(N,N) 1173 C(INF,-P12) C(U,U) C(U,U) C(U,U) C(U,U) C(INF,P12) C(N,N) 1174 C(INF,-P14) C(INF,-0.) C(INF,-0.) C(INF,0.) C(INF,0.) C(INF,P14) C(INF,N) 1175 C(INF,N) C(N,N) C(N,N) C(N,N) C(N,N) C(INF,N) C(N,N) 1176 }) 1177 1178 INIT_SPECIAL_VALUES(sinh_special_values, { 1179 C(INF,N) C(U,U) C(-INF,-0.) C(-INF,0.) C(U,U) C(INF,N) C(INF,N) 1180 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1181 C(0.,N) C(U,U) C(-0.,-0.) C(-0.,0.) C(U,U) C(0.,N) C(0.,N) 1182 C(0.,N) C(U,U) C(0.,-0.) C(0.,0.) C(U,U) C(0.,N) C(0.,N) 1183 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1184 C(INF,N) C(U,U) C(INF,-0.) C(INF,0.) C(U,U) C(INF,N) C(INF,N) 1185 C(N,N) C(N,N) C(N,-0.) C(N,0.) C(N,N) C(N,N) C(N,N) 1186 }) 1187 1188 INIT_SPECIAL_VALUES(sqrt_special_values, { 1189 C(INF,-INF) C(0.,-INF) C(0.,-INF) C(0.,INF) C(0.,INF) C(INF,INF) C(N,INF) 1190 C(INF,-INF) C(U,U) C(U,U) C(U,U) C(U,U) C(INF,INF) C(N,N) 1191 C(INF,-INF) C(U,U) C(0.,-0.) C(0.,0.) C(U,U) C(INF,INF) C(N,N) 1192 C(INF,-INF) C(U,U) C(0.,-0.) C(0.,0.) C(U,U) C(INF,INF) C(N,N) 1193 C(INF,-INF) C(U,U) C(U,U) C(U,U) C(U,U) C(INF,INF) C(N,N) 1194 C(INF,-INF) C(INF,-0.) C(INF,-0.) C(INF,0.) C(INF,0.) C(INF,INF) C(INF,N) 1195 C(INF,-INF) C(N,N) C(N,N) C(N,N) C(N,N) C(INF,INF) C(N,N) 1196 }) 1197 1198 INIT_SPECIAL_VALUES(tanh_special_values, { 1199 C(-1.,0.) C(U,U) C(-1.,-0.) C(-1.,0.) C(U,U) C(-1.,0.) C(-1.,0.) 1200 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1201 C(N,N) C(U,U) C(-0.,-0.) C(-0.,0.) C(U,U) C(N,N) C(N,N) 1202 C(N,N) C(U,U) C(0.,-0.) C(0.,0.) C(U,U) C(N,N) C(N,N) 1203 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1204 C(1.,0.) C(U,U) C(1.,-0.) C(1.,0.) C(U,U) C(1.,0.) C(1.,0.) 1205 C(N,N) C(N,N) C(N,-0.) C(N,0.) C(N,N) C(N,N) C(N,N) 1206 }) 1207 1208 INIT_SPECIAL_VALUES(rect_special_values, { 1209 C(INF,N) C(U,U) C(-INF,0.) C(-INF,-0.) C(U,U) C(INF,N) C(INF,N) 1210 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1211 C(0.,0.) C(U,U) C(-0.,0.) C(-0.,-0.) C(U,U) C(0.,0.) C(0.,0.) 1212 C(0.,0.) C(U,U) C(0.,-0.) C(0.,0.) C(U,U) C(0.,0.) C(0.,0.) 1213 C(N,N) C(U,U) C(U,U) C(U,U) C(U,U) C(N,N) C(N,N) 1214 C(INF,N) C(U,U) C(INF,-0.) C(INF,0.) C(U,U) C(INF,N) C(INF,N) 1215 C(N,N) C(N,N) C(N,0.) C(N,0.) C(N,N) C(N,N) C(N,N) 1216 }) 1217 }
Note:
See TracChangeset
for help on using the changeset viewer.