diff options
| author | Paul Eggert | 2024-07-07 15:42:10 +0200 |
|---|---|---|
| committer | Paul Eggert | 2024-07-11 16:01:41 +0200 |
| commit | 0e221d3789a40d22bd4a9489985aebeb86f43e01 (patch) | |
| tree | ccd43f006ac64fbc99d1566a4c45d0943f9327a3 /src | |
| parent | 35365620e4c4c2560e13eba1f03332970129d7f8 (diff) | |
| download | emacs-0e221d3789a40d22bd4a9489985aebeb86f43e01.tar.gz emacs-0e221d3789a40d22bd4a9489985aebeb86f43e01.zip | |
Refactor timefns order
Move definitions around in timefns.c. This does not affect the
implementation; it merely makes future changes easier to follow.
* src/timefns.c (frac_to_double, mpz_time, lisp_to_timespec)
(enum cform, union c_time, decode_ticks_hz): Move earlier.
Diffstat (limited to 'src')
| -rw-r--r-- | src/timefns.c | 400 |
1 files changed, 200 insertions, 200 deletions
diff --git a/src/timefns.c b/src/timefns.c index 70961c1a560..a7a7d552506 100644 --- a/src/timefns.c +++ b/src/timefns.c | |||
| @@ -400,6 +400,112 @@ enum { flt_radix_power_size = DBL_MANT_DIG - DBL_MIN_EXP + 1 }; | |||
| 400 | equals FLT_RADIX**P. */ | 400 | equals FLT_RADIX**P. */ |
| 401 | static Lisp_Object flt_radix_power; | 401 | static Lisp_Object flt_radix_power; |
| 402 | 402 | ||
| 403 | /* Return NUMERATOR / DENOMINATOR, rounded to the nearest double. | ||
| 404 | Arguments must be Lisp integers, and DENOMINATOR must be positive. */ | ||
| 405 | static double | ||
| 406 | frac_to_double (Lisp_Object numerator, Lisp_Object denominator) | ||
| 407 | { | ||
| 408 | intmax_t intmax_numerator, intmax_denominator; | ||
| 409 | if (FASTER_TIMEFNS | ||
| 410 | && integer_to_intmax (numerator, &intmax_numerator) | ||
| 411 | && integer_to_intmax (denominator, &intmax_denominator) | ||
| 412 | && intmax_numerator % intmax_denominator == 0) | ||
| 413 | return intmax_numerator / intmax_denominator; | ||
| 414 | |||
| 415 | /* Compute number of base-FLT_RADIX digits in numerator and denominator. */ | ||
| 416 | mpz_t const *n = bignum_integer (&mpz[0], numerator); | ||
| 417 | mpz_t const *d = bignum_integer (&mpz[1], denominator); | ||
| 418 | ptrdiff_t ndig = mpz_sizeinbase (*n, FLT_RADIX); | ||
| 419 | ptrdiff_t ddig = mpz_sizeinbase (*d, FLT_RADIX); | ||
| 420 | |||
| 421 | /* Scale with SCALE when doing integer division. That is, compute | ||
| 422 | (N * FLT_RADIX**SCALE) / D [or, if SCALE is negative, N / (D * | ||
| 423 | FLT_RADIX**-SCALE)] as a bignum, convert the bignum to double, | ||
| 424 | then divide the double by FLT_RADIX**SCALE. First scale N | ||
| 425 | (or scale D, if SCALE is negative) ... */ | ||
| 426 | ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG; | ||
| 427 | if (scale < 0) | ||
| 428 | { | ||
| 429 | mpz_mul_2exp (mpz[1], *d, - (scale * LOG2_FLT_RADIX)); | ||
| 430 | d = &mpz[1]; | ||
| 431 | } | ||
| 432 | else | ||
| 433 | { | ||
| 434 | /* min so we don't scale tiny numbers as if they were normalized. */ | ||
| 435 | scale = min (scale, flt_radix_power_size - 1); | ||
| 436 | |||
| 437 | mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX); | ||
| 438 | n = &mpz[0]; | ||
| 439 | } | ||
| 440 | /* ... and then divide, with quotient Q and remainder R. */ | ||
| 441 | mpz_t *q = &mpz[2]; | ||
| 442 | mpz_t *r = &mpz[3]; | ||
| 443 | mpz_tdiv_qr (*q, *r, *n, *d); | ||
| 444 | |||
| 445 | /* The amount to add to the absolute value of Q so that truncating | ||
| 446 | it to double will round correctly. */ | ||
| 447 | int incr; | ||
| 448 | |||
| 449 | /* Round the quotient before converting it to double. | ||
| 450 | If the quotient is less than FLT_RADIX ** DBL_MANT_DIG, | ||
| 451 | round to the nearest integer; otherwise, it is less than | ||
| 452 | FLT_RADIX ** (DBL_MANT_DIG + 1) and round it to the nearest | ||
| 453 | multiple of FLT_RADIX. Break ties to even. */ | ||
| 454 | if (mpz_sizeinbase (*q, FLT_RADIX) <= DBL_MANT_DIG) | ||
| 455 | { | ||
| 456 | /* Converting to double will use the whole quotient so add 1 to | ||
| 457 | its absolute value as per round-to-even; i.e., if the doubled | ||
| 458 | remainder exceeds the denominator, or exactly equals the | ||
| 459 | denominator and adding 1 would make the quotient even. */ | ||
| 460 | mpz_mul_2exp (*r, *r, 1); | ||
| 461 | int cmp = mpz_cmpabs (*r, *d); | ||
| 462 | incr = cmp > 0 || (cmp == 0 && (FASTER_TIMEFNS && FLT_RADIX == 2 | ||
| 463 | ? mpz_odd_p (*q) | ||
| 464 | : mpz_tdiv_ui (*q, FLT_RADIX) & 1)); | ||
| 465 | } | ||
| 466 | else | ||
| 467 | { | ||
| 468 | /* Converting to double will discard the quotient's low-order digit, | ||
| 469 | so add FLT_RADIX to its absolute value as per round-to-even. */ | ||
| 470 | int lo_2digits = mpz_tdiv_ui (*q, FLT_RADIX * FLT_RADIX); | ||
| 471 | eassume (0 <= lo_2digits && lo_2digits < FLT_RADIX * FLT_RADIX); | ||
| 472 | int lo_digit = lo_2digits % FLT_RADIX; | ||
| 473 | incr = ((lo_digit > FLT_RADIX / 2 | ||
| 474 | || (lo_digit == FLT_RADIX / 2 && FLT_RADIX % 2 == 0 | ||
| 475 | && ((lo_2digits / FLT_RADIX) & 1 | ||
| 476 | || mpz_sgn (*r) != 0))) | ||
| 477 | ? FLT_RADIX : 0); | ||
| 478 | } | ||
| 479 | |||
| 480 | /* Increment the absolute value of the quotient by INCR. */ | ||
| 481 | if (!FASTER_TIMEFNS || incr != 0) | ||
| 482 | (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr); | ||
| 483 | |||
| 484 | /* Rescale the integer Q back to double. This step does not round. */ | ||
| 485 | return scalbn (mpz_get_d (*q), -scale); | ||
| 486 | } | ||
| 487 | |||
| 488 | /* Convert Z to time_t, returning true if it fits. */ | ||
| 489 | static bool | ||
| 490 | mpz_time (mpz_t const z, time_t *t) | ||
| 491 | { | ||
| 492 | if (TYPE_SIGNED (time_t)) | ||
| 493 | { | ||
| 494 | intmax_t i; | ||
| 495 | if (! (mpz_to_intmax (z, &i) && TIME_T_MIN <= i && i <= TIME_T_MAX)) | ||
| 496 | return false; | ||
| 497 | *t = i; | ||
| 498 | } | ||
| 499 | else | ||
| 500 | { | ||
| 501 | uintmax_t i; | ||
| 502 | if (! (mpz_to_uintmax (z, &i) && i <= TIME_T_MAX)) | ||
| 503 | return false; | ||
| 504 | *t = i; | ||
| 505 | } | ||
| 506 | return true; | ||
| 507 | } | ||
| 508 | |||
| 403 | /* Components of a Lisp timestamp (TICKS . HZ). Using this C struct can | 509 | /* Components of a Lisp timestamp (TICKS . HZ). Using this C struct can |
| 404 | avoid the consing overhead of creating (TICKS . HZ). */ | 510 | avoid the consing overhead of creating (TICKS . HZ). */ |
| 405 | struct lisp_time | 511 | struct lisp_time |
| @@ -411,6 +517,100 @@ struct lisp_time | |||
| 411 | Lisp_Object hz; | 517 | Lisp_Object hz; |
| 412 | }; | 518 | }; |
| 413 | 519 | ||
| 520 | /* Convert T to struct timespec, returning an invalid timespec | ||
| 521 | if T does not fit. */ | ||
| 522 | static struct timespec | ||
| 523 | lisp_to_timespec (struct lisp_time t) | ||
| 524 | { | ||
| 525 | struct timespec result = invalid_timespec (); | ||
| 526 | int ns; | ||
| 527 | mpz_t *q = &mpz[0]; | ||
| 528 | mpz_t const *qt = q; | ||
| 529 | |||
| 530 | /* Floor-divide (T.ticks * TIMESPEC_HZ) by T.hz, | ||
| 531 | yielding quotient Q (tv_sec) and remainder NS (tv_nsec). | ||
| 532 | Return an invalid timespec if Q does not fit in time_t. | ||
| 533 | For speed, prefer fixnum arithmetic if it works. */ | ||
| 534 | if (FASTER_TIMEFNS && BASE_EQ (t.hz, timespec_hz)) | ||
| 535 | { | ||
| 536 | if (FIXNUMP (t.ticks)) | ||
| 537 | { | ||
| 538 | EMACS_INT s = XFIXNUM (t.ticks) / TIMESPEC_HZ; | ||
| 539 | ns = XFIXNUM (t.ticks) % TIMESPEC_HZ; | ||
| 540 | if (ns < 0) | ||
| 541 | s--, ns += TIMESPEC_HZ; | ||
| 542 | if ((TYPE_SIGNED (time_t) ? TIME_T_MIN <= s : 0 <= s) | ||
| 543 | && s <= TIME_T_MAX) | ||
| 544 | { | ||
| 545 | result.tv_sec = s; | ||
| 546 | result.tv_nsec = ns; | ||
| 547 | } | ||
| 548 | return result; | ||
| 549 | } | ||
| 550 | else | ||
| 551 | ns = mpz_fdiv_q_ui (*q, *xbignum_val (t.ticks), TIMESPEC_HZ); | ||
| 552 | } | ||
| 553 | else if (FASTER_TIMEFNS && BASE_EQ (t.hz, make_fixnum (1))) | ||
| 554 | { | ||
| 555 | ns = 0; | ||
| 556 | if (FIXNUMP (t.ticks)) | ||
| 557 | { | ||
| 558 | EMACS_INT s = XFIXNUM (t.ticks); | ||
| 559 | if ((TYPE_SIGNED (time_t) ? TIME_T_MIN <= s : 0 <= s) | ||
| 560 | && s <= TIME_T_MAX) | ||
| 561 | { | ||
| 562 | result.tv_sec = s; | ||
| 563 | result.tv_nsec = ns; | ||
| 564 | } | ||
| 565 | return result; | ||
| 566 | } | ||
| 567 | else | ||
| 568 | qt = xbignum_val (t.ticks); | ||
| 569 | } | ||
| 570 | else | ||
| 571 | { | ||
| 572 | mpz_mul_ui (*q, *bignum_integer (q, t.ticks), TIMESPEC_HZ); | ||
| 573 | mpz_fdiv_q (*q, *q, *bignum_integer (&mpz[1], t.hz)); | ||
| 574 | ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ); | ||
| 575 | } | ||
| 576 | |||
| 577 | /* Check that Q fits in time_t, not merely in T.tv_sec. With some versions | ||
| 578 | of MinGW, tv_sec is a 64-bit type, whereas time_t is a 32-bit type. */ | ||
| 579 | time_t sec; | ||
| 580 | if (mpz_time (*qt, &sec)) | ||
| 581 | { | ||
| 582 | result.tv_sec = sec; | ||
| 583 | result.tv_nsec = ns; | ||
| 584 | } | ||
| 585 | return result; | ||
| 586 | } | ||
| 587 | |||
| 588 | /* C timestamp forms. This enum is passed to conversion functions to | ||
| 589 | specify the desired C timestamp form. */ | ||
| 590 | enum cform | ||
| 591 | { | ||
| 592 | CFORM_TICKS_HZ, /* struct lisp_time */ | ||
| 593 | CFORM_SECS_ONLY, /* struct lisp_time but HZ is 1 */ | ||
| 594 | CFORM_DOUBLE /* double */ | ||
| 595 | }; | ||
| 596 | |||
| 597 | /* A C timestamp in one of the forms specified by enum cform. */ | ||
| 598 | union c_time | ||
| 599 | { | ||
| 600 | struct lisp_time lt; | ||
| 601 | double d; | ||
| 602 | }; | ||
| 603 | |||
| 604 | /* From a valid timestamp (TICKS . HZ), generate the corresponding | ||
| 605 | time value in CFORM form. */ | ||
| 606 | static union c_time | ||
| 607 | decode_ticks_hz (Lisp_Object ticks, Lisp_Object hz, enum cform cform) | ||
| 608 | { | ||
| 609 | return (cform == CFORM_DOUBLE | ||
| 610 | ? (union c_time) { .d = frac_to_double (ticks, hz) } | ||
| 611 | : (union c_time) { .lt = { .ticks = ticks, .hz = hz } }); | ||
| 612 | } | ||
| 613 | |||
| 414 | /* Convert the finite number T into an Emacs time, truncating | 614 | /* Convert the finite number T into an Emacs time, truncating |
| 415 | toward minus infinity. Signal an error if unsuccessful. */ | 615 | toward minus infinity. Signal an error if unsuccessful. */ |
| 416 | static struct lisp_time | 616 | static struct lisp_time |
| @@ -613,117 +813,6 @@ timespec_to_lisp (struct timespec t) | |||
| 613 | return Fcons (timespec_ticks (t), timespec_hz); | 813 | return Fcons (timespec_ticks (t), timespec_hz); |
| 614 | } | 814 | } |
| 615 | 815 | ||
| 616 | /* Return NUMERATOR / DENOMINATOR, rounded to the nearest double. | ||
| 617 | Arguments must be Lisp integers, and DENOMINATOR must be positive. */ | ||
| 618 | static double | ||
| 619 | frac_to_double (Lisp_Object numerator, Lisp_Object denominator) | ||
| 620 | { | ||
| 621 | intmax_t intmax_numerator, intmax_denominator; | ||
| 622 | if (FASTER_TIMEFNS | ||
| 623 | && integer_to_intmax (numerator, &intmax_numerator) | ||
| 624 | && integer_to_intmax (denominator, &intmax_denominator) | ||
| 625 | && intmax_numerator % intmax_denominator == 0) | ||
| 626 | return intmax_numerator / intmax_denominator; | ||
| 627 | |||
| 628 | /* Compute number of base-FLT_RADIX digits in numerator and denominator. */ | ||
| 629 | mpz_t const *n = bignum_integer (&mpz[0], numerator); | ||
| 630 | mpz_t const *d = bignum_integer (&mpz[1], denominator); | ||
| 631 | ptrdiff_t ndig = mpz_sizeinbase (*n, FLT_RADIX); | ||
| 632 | ptrdiff_t ddig = mpz_sizeinbase (*d, FLT_RADIX); | ||
| 633 | |||
| 634 | /* Scale with SCALE when doing integer division. That is, compute | ||
| 635 | (N * FLT_RADIX**SCALE) / D [or, if SCALE is negative, N / (D * | ||
| 636 | FLT_RADIX**-SCALE)] as a bignum, convert the bignum to double, | ||
| 637 | then divide the double by FLT_RADIX**SCALE. First scale N | ||
| 638 | (or scale D, if SCALE is negative) ... */ | ||
| 639 | ptrdiff_t scale = ddig - ndig + DBL_MANT_DIG; | ||
| 640 | if (scale < 0) | ||
| 641 | { | ||
| 642 | mpz_mul_2exp (mpz[1], *d, - (scale * LOG2_FLT_RADIX)); | ||
| 643 | d = &mpz[1]; | ||
| 644 | } | ||
| 645 | else | ||
| 646 | { | ||
| 647 | /* min so we don't scale tiny numbers as if they were normalized. */ | ||
| 648 | scale = min (scale, flt_radix_power_size - 1); | ||
| 649 | |||
| 650 | mpz_mul_2exp (mpz[0], *n, scale * LOG2_FLT_RADIX); | ||
| 651 | n = &mpz[0]; | ||
| 652 | } | ||
| 653 | /* ... and then divide, with quotient Q and remainder R. */ | ||
| 654 | mpz_t *q = &mpz[2]; | ||
| 655 | mpz_t *r = &mpz[3]; | ||
| 656 | mpz_tdiv_qr (*q, *r, *n, *d); | ||
| 657 | |||
| 658 | /* The amount to add to the absolute value of Q so that truncating | ||
| 659 | it to double will round correctly. */ | ||
| 660 | int incr; | ||
| 661 | |||
| 662 | /* Round the quotient before converting it to double. | ||
| 663 | If the quotient is less than FLT_RADIX ** DBL_MANT_DIG, | ||
| 664 | round to the nearest integer; otherwise, it is less than | ||
| 665 | FLT_RADIX ** (DBL_MANT_DIG + 1) and round it to the nearest | ||
| 666 | multiple of FLT_RADIX. Break ties to even. */ | ||
| 667 | if (mpz_sizeinbase (*q, FLT_RADIX) <= DBL_MANT_DIG) | ||
| 668 | { | ||
| 669 | /* Converting to double will use the whole quotient so add 1 to | ||
| 670 | its absolute value as per round-to-even; i.e., if the doubled | ||
| 671 | remainder exceeds the denominator, or exactly equals the | ||
| 672 | denominator and adding 1 would make the quotient even. */ | ||
| 673 | mpz_mul_2exp (*r, *r, 1); | ||
| 674 | int cmp = mpz_cmpabs (*r, *d); | ||
| 675 | incr = cmp > 0 || (cmp == 0 && (FASTER_TIMEFNS && FLT_RADIX == 2 | ||
| 676 | ? mpz_odd_p (*q) | ||
| 677 | : mpz_tdiv_ui (*q, FLT_RADIX) & 1)); | ||
| 678 | } | ||
| 679 | else | ||
| 680 | { | ||
| 681 | /* Converting to double will discard the quotient's low-order digit, | ||
| 682 | so add FLT_RADIX to its absolute value as per round-to-even. */ | ||
| 683 | int lo_2digits = mpz_tdiv_ui (*q, FLT_RADIX * FLT_RADIX); | ||
| 684 | eassume (0 <= lo_2digits && lo_2digits < FLT_RADIX * FLT_RADIX); | ||
| 685 | int lo_digit = lo_2digits % FLT_RADIX; | ||
| 686 | incr = ((lo_digit > FLT_RADIX / 2 | ||
| 687 | || (lo_digit == FLT_RADIX / 2 && FLT_RADIX % 2 == 0 | ||
| 688 | && ((lo_2digits / FLT_RADIX) & 1 | ||
| 689 | || mpz_sgn (*r) != 0))) | ||
| 690 | ? FLT_RADIX : 0); | ||
| 691 | } | ||
| 692 | |||
| 693 | /* Increment the absolute value of the quotient by INCR. */ | ||
| 694 | if (!FASTER_TIMEFNS || incr != 0) | ||
| 695 | (mpz_sgn (*n) < 0 ? mpz_sub_ui : mpz_add_ui) (*q, *q, incr); | ||
| 696 | |||
| 697 | /* Rescale the integer Q back to double. This step does not round. */ | ||
| 698 | return scalbn (mpz_get_d (*q), -scale); | ||
| 699 | } | ||
| 700 | |||
| 701 | /* C timestamp forms. This enum is passed to conversion functions to | ||
| 702 | specify the desired C timestamp form. */ | ||
| 703 | enum cform | ||
| 704 | { | ||
| 705 | CFORM_TICKS_HZ, /* struct lisp_time */ | ||
| 706 | CFORM_SECS_ONLY, /* struct lisp_time but HZ is 1 */ | ||
| 707 | CFORM_DOUBLE /* double */ | ||
| 708 | }; | ||
| 709 | |||
| 710 | /* A C timestamp in one of the forms specified by enum cform. */ | ||
| 711 | union c_time | ||
| 712 | { | ||
| 713 | struct lisp_time lt; | ||
| 714 | double d; | ||
| 715 | }; | ||
| 716 | |||
| 717 | /* From a valid timestamp (TICKS . HZ), generate the corresponding | ||
| 718 | time value in CFORM form. */ | ||
| 719 | static union c_time | ||
| 720 | decode_ticks_hz (Lisp_Object ticks, Lisp_Object hz, enum cform cform) | ||
| 721 | { | ||
| 722 | return (cform == CFORM_DOUBLE | ||
| 723 | ? (union c_time) { .d = frac_to_double (ticks, hz) } | ||
| 724 | : (union c_time) { .lt = { .ticks = ticks, .hz = hz } }); | ||
| 725 | } | ||
| 726 | |||
| 727 | /* An (error number, C timestamp) pair. */ | 816 | /* An (error number, C timestamp) pair. */ |
| 728 | struct err_time | 817 | struct err_time |
| 729 | { | 818 | { |
| @@ -939,95 +1028,6 @@ float_time (Lisp_Object specified_time) | |||
| 939 | return decode_lisp_time (specified_time, CFORM_DOUBLE).time.d; | 1028 | return decode_lisp_time (specified_time, CFORM_DOUBLE).time.d; |
| 940 | } | 1029 | } |
| 941 | 1030 | ||
| 942 | /* Convert Z to time_t, returning true if it fits. */ | ||
| 943 | static bool | ||
| 944 | mpz_time (mpz_t const z, time_t *t) | ||
| 945 | { | ||
| 946 | if (TYPE_SIGNED (time_t)) | ||
| 947 | { | ||
| 948 | intmax_t i; | ||
| 949 | if (! (mpz_to_intmax (z, &i) && TIME_T_MIN <= i && i <= TIME_T_MAX)) | ||
| 950 | return false; | ||
| 951 | *t = i; | ||
| 952 | } | ||
| 953 | else | ||
| 954 | { | ||
| 955 | uintmax_t i; | ||
| 956 | if (! (mpz_to_uintmax (z, &i) && i <= TIME_T_MAX)) | ||
| 957 | return false; | ||
| 958 | *t = i; | ||
| 959 | } | ||
| 960 | return true; | ||
| 961 | } | ||
| 962 | |||
| 963 | /* Convert T to struct timespec, returning an invalid timespec | ||
| 964 | if T does not fit. */ | ||
| 965 | static struct timespec | ||
| 966 | lisp_to_timespec (struct lisp_time t) | ||
| 967 | { | ||
| 968 | struct timespec result = invalid_timespec (); | ||
| 969 | int ns; | ||
| 970 | mpz_t *q = &mpz[0]; | ||
| 971 | mpz_t const *qt = q; | ||
| 972 | |||
| 973 | /* Floor-divide (T.ticks * TIMESPEC_HZ) by T.hz, | ||
| 974 | yielding quotient Q (tv_sec) and remainder NS (tv_nsec). | ||
| 975 | Return an invalid timespec if Q does not fit in time_t. | ||
| 976 | For speed, prefer fixnum arithmetic if it works. */ | ||
| 977 | if (FASTER_TIMEFNS && BASE_EQ (t.hz, timespec_hz)) | ||
| 978 | { | ||
| 979 | if (FIXNUMP (t.ticks)) | ||
| 980 | { | ||
| 981 | EMACS_INT s = XFIXNUM (t.ticks) / TIMESPEC_HZ; | ||
| 982 | ns = XFIXNUM (t.ticks) % TIMESPEC_HZ; | ||
| 983 | if (ns < 0) | ||
| 984 | s--, ns += TIMESPEC_HZ; | ||
| 985 | if ((TYPE_SIGNED (time_t) ? TIME_T_MIN <= s : 0 <= s) | ||
| 986 | && s <= TIME_T_MAX) | ||
| 987 | { | ||
| 988 | result.tv_sec = s; | ||
| 989 | result.tv_nsec = ns; | ||
| 990 | } | ||
| 991 | return result; | ||
| 992 | } | ||
| 993 | else | ||
| 994 | ns = mpz_fdiv_q_ui (*q, *xbignum_val (t.ticks), TIMESPEC_HZ); | ||
| 995 | } | ||
| 996 | else if (FASTER_TIMEFNS && BASE_EQ (t.hz, make_fixnum (1))) | ||
| 997 | { | ||
| 998 | ns = 0; | ||
| 999 | if (FIXNUMP (t.ticks)) | ||
| 1000 | { | ||
| 1001 | EMACS_INT s = XFIXNUM (t.ticks); | ||
| 1002 | if ((TYPE_SIGNED (time_t) ? TIME_T_MIN <= s : 0 <= s) | ||
| 1003 | && s <= TIME_T_MAX) | ||
| 1004 | { | ||
| 1005 | result.tv_sec = s; | ||
| 1006 | result.tv_nsec = ns; | ||
| 1007 | } | ||
| 1008 | return result; | ||
| 1009 | } | ||
| 1010 | else | ||
| 1011 | qt = xbignum_val (t.ticks); | ||
| 1012 | } | ||
| 1013 | else | ||
| 1014 | { | ||
| 1015 | mpz_mul_ui (*q, *bignum_integer (q, t.ticks), TIMESPEC_HZ); | ||
| 1016 | mpz_fdiv_q (*q, *q, *bignum_integer (&mpz[1], t.hz)); | ||
| 1017 | ns = mpz_fdiv_q_ui (*q, *q, TIMESPEC_HZ); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | /* Check that Q fits in time_t, not merely in T.tv_sec. With some versions | ||
| 1021 | of MinGW, tv_sec is a 64-bit type, whereas time_t is a 32-bit type. */ | ||
| 1022 | time_t sec; | ||
| 1023 | if (mpz_time (*qt, &sec)) | ||
| 1024 | { | ||
| 1025 | result.tv_sec = sec; | ||
| 1026 | result.tv_nsec = ns; | ||
| 1027 | } | ||
| 1028 | return result; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | /* Convert (HIGH LOW USEC PSEC) to struct timespec. | 1031 | /* Convert (HIGH LOW USEC PSEC) to struct timespec. |
| 1032 | Return a valid timestamp if successful, an invalid one otherwise. */ | 1032 | Return a valid timestamp if successful, an invalid one otherwise. */ |
| 1033 | struct timespec | 1033 | struct timespec |