diff options
| author | Andy Moreton | 2018-08-04 10:28:13 -0600 |
|---|---|---|
| committer | Tom Tromey | 2018-08-04 10:28:13 -0600 |
| commit | bc8ff54efee05f4a2769be32046866ed1e152b41 (patch) | |
| tree | c6dac43f3b9abfc6bde54a9d245c04e5dbb360d5 /src/data.c | |
| parent | 76715f8921dca740880cd22c644a6328cd810846 (diff) | |
| download | emacs-bc8ff54efee05f4a2769be32046866ed1e152b41.tar.gz emacs-bc8ff54efee05f4a2769be32046866ed1e152b41.zip | |
Make bignums work better when EMACS_INT is larger than long
* lisp/international/ccl.el (ccl-fixnum): New function.
(ccl-embed-data, ccl-embed-current-address, ccl-dump): Use it.
* src/alloc.c (make_number): Handle case where EMACS_INT is
larger than long.
* src/data.c (bignumcompare): Handle case where EMACS_INT is
larger than long.
(arith_driver): Likewise. Coerce markers.
(float_arith_driver): Coerce markers.
(Flogcount): Use mpz_sgn.
(ash_lsh_impl): Fix bugs.
(Fsub1): Fix underflow check.
* src/lisp.h (NUMBERP): Don't check BIGNUMP.
(CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER): Fix indentation.
* test/lisp/international/ccl-tests.el: New file.
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 96 |
1 files changed, 79 insertions, 17 deletions
diff --git a/src/data.c b/src/data.c index 0deebdca1ae..3d55d9d17d5 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2409,7 +2409,18 @@ bignumcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2409 | if (FLOATP (num2)) | 2409 | if (FLOATP (num2)) |
| 2410 | cmp = mpz_cmp_d (XBIGNUM (num1)->value, XFLOAT_DATA (num2)); | 2410 | cmp = mpz_cmp_d (XBIGNUM (num1)->value, XFLOAT_DATA (num2)); |
| 2411 | else if (FIXNUMP (num2)) | 2411 | else if (FIXNUMP (num2)) |
| 2412 | cmp = mpz_cmp_si (XBIGNUM (num1)->value, XINT (num2)); | 2412 | { |
| 2413 | if (sizeof (EMACS_INT) > sizeof (long) && XINT (num2) > LONG_MAX) | ||
| 2414 | { | ||
| 2415 | mpz_t tem; | ||
| 2416 | mpz_init (tem); | ||
| 2417 | mpz_set_intmax (tem, XINT (num2)); | ||
| 2418 | cmp = mpz_cmp (XBIGNUM (num1)->value, tem); | ||
| 2419 | mpz_clear (tem); | ||
| 2420 | } | ||
| 2421 | else | ||
| 2422 | cmp = mpz_cmp_si (XBIGNUM (num1)->value, XINT (num2)); | ||
| 2423 | } | ||
| 2413 | else | 2424 | else |
| 2414 | { | 2425 | { |
| 2415 | eassume (BIGNUMP (num2)); | 2426 | eassume (BIGNUMP (num2)); |
| @@ -2422,10 +2433,19 @@ bignumcompare (Lisp_Object num1, Lisp_Object num2, | |||
| 2422 | if (FLOATP (num1)) | 2433 | if (FLOATP (num1)) |
| 2423 | cmp = - mpz_cmp_d (XBIGNUM (num2)->value, XFLOAT_DATA (num1)); | 2434 | cmp = - mpz_cmp_d (XBIGNUM (num2)->value, XFLOAT_DATA (num1)); |
| 2424 | else | 2435 | else |
| 2425 | { | 2436 | { |
| 2426 | eassume (FIXNUMP (num1)); | 2437 | eassume (FIXNUMP (num1)); |
| 2427 | cmp = - mpz_cmp_si (XBIGNUM (num2)->value, XINT (num1)); | 2438 | if (sizeof (EMACS_INT) > sizeof (long) && XINT (num1) > LONG_MAX) |
| 2428 | } | 2439 | { |
| 2440 | mpz_t tem; | ||
| 2441 | mpz_init (tem); | ||
| 2442 | mpz_set_intmax (tem, XINT (num1)); | ||
| 2443 | cmp = - mpz_cmp (XBIGNUM (num2)->value, tem); | ||
| 2444 | mpz_clear (tem); | ||
| 2445 | } | ||
| 2446 | else | ||
| 2447 | cmp = - mpz_cmp_si (XBIGNUM (num2)->value, XINT (num1)); | ||
| 2448 | } | ||
| 2429 | } | 2449 | } |
| 2430 | 2450 | ||
| 2431 | switch (comparison) | 2451 | switch (comparison) |
| @@ -2860,7 +2880,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 2860 | { | 2880 | { |
| 2861 | /* Using args[argnum] as argument to CHECK_NUMBER... */ | 2881 | /* Using args[argnum] as argument to CHECK_NUMBER... */ |
| 2862 | val = args[argnum]; | 2882 | val = args[argnum]; |
| 2863 | CHECK_NUMBER (val); | 2883 | CHECK_NUMBER_COERCE_MARKER (val); |
| 2864 | 2884 | ||
| 2865 | if (FLOATP (val)) | 2885 | if (FLOATP (val)) |
| 2866 | return unbind_to (count, | 2886 | return unbind_to (count, |
| @@ -2871,7 +2891,15 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 2871 | case Aadd: | 2891 | case Aadd: |
| 2872 | if (BIGNUMP (val)) | 2892 | if (BIGNUMP (val)) |
| 2873 | mpz_add (accum, accum, XBIGNUM (val)->value); | 2893 | mpz_add (accum, accum, XBIGNUM (val)->value); |
| 2874 | else if (XINT (val) < 0) | 2894 | else if (sizeof (EMACS_INT) > sizeof (long)) |
| 2895 | { | ||
| 2896 | mpz_t tem; | ||
| 2897 | mpz_init (tem); | ||
| 2898 | mpz_set_intmax (tem, XINT (val)); | ||
| 2899 | mpz_add (accum, accum, tem); | ||
| 2900 | mpz_clear (tem); | ||
| 2901 | } | ||
| 2902 | else if (XINT (val) < 0) | ||
| 2875 | mpz_sub_ui (accum, accum, - XINT (val)); | 2903 | mpz_sub_ui (accum, accum, - XINT (val)); |
| 2876 | else | 2904 | else |
| 2877 | mpz_add_ui (accum, accum, XINT (val)); | 2905 | mpz_add_ui (accum, accum, XINT (val)); |
| @@ -2888,6 +2916,14 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 2888 | } | 2916 | } |
| 2889 | else if (BIGNUMP (val)) | 2917 | else if (BIGNUMP (val)) |
| 2890 | mpz_sub (accum, accum, XBIGNUM (val)->value); | 2918 | mpz_sub (accum, accum, XBIGNUM (val)->value); |
| 2919 | else if (sizeof (EMACS_INT) > sizeof (long)) | ||
| 2920 | { | ||
| 2921 | mpz_t tem; | ||
| 2922 | mpz_init (tem); | ||
| 2923 | mpz_set_intmax (tem, XINT (val)); | ||
| 2924 | mpz_sub (accum, accum, tem); | ||
| 2925 | mpz_clear (tem); | ||
| 2926 | } | ||
| 2891 | else if (XINT (val) < 0) | 2927 | else if (XINT (val) < 0) |
| 2892 | mpz_add_ui (accum, accum, - XINT (val)); | 2928 | mpz_add_ui (accum, accum, - XINT (val)); |
| 2893 | else | 2929 | else |
| @@ -2896,6 +2932,14 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 2896 | case Amult: | 2932 | case Amult: |
| 2897 | if (BIGNUMP (val)) | 2933 | if (BIGNUMP (val)) |
| 2898 | mpz_mul (accum, accum, XBIGNUM (val)->value); | 2934 | mpz_mul (accum, accum, XBIGNUM (val)->value); |
| 2935 | else if (sizeof (EMACS_INT) > sizeof (long)) | ||
| 2936 | { | ||
| 2937 | mpz_t tem; | ||
| 2938 | mpz_init (tem); | ||
| 2939 | mpz_set_intmax (tem, XINT (val)); | ||
| 2940 | mpz_mul (accum, accum, tem); | ||
| 2941 | mpz_clear (tem); | ||
| 2942 | } | ||
| 2899 | else | 2943 | else |
| 2900 | mpz_mul_si (accum, accum, XINT (val)); | 2944 | mpz_mul_si (accum, accum, XINT (val)); |
| 2901 | break; | 2945 | break; |
| @@ -2915,6 +2959,14 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 2915 | xsignal0 (Qarith_error); | 2959 | xsignal0 (Qarith_error); |
| 2916 | if (BIGNUMP (val)) | 2960 | if (BIGNUMP (val)) |
| 2917 | mpz_tdiv_q (accum, accum, XBIGNUM (val)->value); | 2961 | mpz_tdiv_q (accum, accum, XBIGNUM (val)->value); |
| 2962 | else if (sizeof (EMACS_INT) > sizeof (long)) | ||
| 2963 | { | ||
| 2964 | mpz_t tem; | ||
| 2965 | mpz_init (tem); | ||
| 2966 | mpz_set_intmax (tem, XINT (val)); | ||
| 2967 | mpz_tdiv_q (accum, accum, tem); | ||
| 2968 | mpz_clear (tem); | ||
| 2969 | } | ||
| 2918 | else | 2970 | else |
| 2919 | { | 2971 | { |
| 2920 | EMACS_INT value = XINT (val); | 2972 | EMACS_INT value = XINT (val); |
| @@ -2982,8 +3034,9 @@ float_arith_driver (double accum, ptrdiff_t argnum, enum arithop code, | |||
| 2982 | 3034 | ||
| 2983 | for (; argnum < nargs; argnum++) | 3035 | for (; argnum < nargs; argnum++) |
| 2984 | { | 3036 | { |
| 2985 | val = args[argnum]; /* using args[argnum] as argument to CHECK_FIXNUM_... */ | 3037 | /* using args[argnum] as argument to CHECK_NUMBER_... */ |
| 2986 | CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER (val); | 3038 | val = args[argnum]; |
| 3039 | CHECK_NUMBER_COERCE_MARKER (val); | ||
| 2987 | 3040 | ||
| 2988 | if (FLOATP (val)) | 3041 | if (FLOATP (val)) |
| 2989 | { | 3042 | { |
| @@ -3277,7 +3330,7 @@ representation. */) | |||
| 3277 | 3330 | ||
| 3278 | if (BIGNUMP (value)) | 3331 | if (BIGNUMP (value)) |
| 3279 | { | 3332 | { |
| 3280 | if (mpz_cmp_si (XBIGNUM (value)->value, 0) >= 0) | 3333 | if (mpz_sgn (XBIGNUM (value)->value) >= 0) |
| 3281 | return make_fixnum (mpz_popcount (XBIGNUM (value)->value)); | 3334 | return make_fixnum (mpz_popcount (XBIGNUM (value)->value)); |
| 3282 | mpz_t tem; | 3335 | mpz_t tem; |
| 3283 | mpz_init (tem); | 3336 | mpz_init (tem); |
| @@ -3314,8 +3367,10 @@ ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh) | |||
| 3314 | mpz_init (result); | 3367 | mpz_init (result); |
| 3315 | if (XINT (count) >= 0) | 3368 | if (XINT (count) >= 0) |
| 3316 | mpz_mul_2exp (result, XBIGNUM (value)->value, XINT (count)); | 3369 | mpz_mul_2exp (result, XBIGNUM (value)->value, XINT (count)); |
| 3317 | else | 3370 | else if (lsh) |
| 3318 | mpz_tdiv_q_2exp (result, XBIGNUM (value)->value, - XINT (count)); | 3371 | mpz_tdiv_q_2exp (result, XBIGNUM (value)->value, - XINT (count)); |
| 3372 | else | ||
| 3373 | mpz_fdiv_q_2exp (result, XBIGNUM (value)->value, - XINT (count)); | ||
| 3319 | val = make_number (result); | 3374 | val = make_number (result); |
| 3320 | mpz_clear (result); | 3375 | mpz_clear (result); |
| 3321 | } | 3376 | } |
| @@ -3325,14 +3380,21 @@ ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh) | |||
| 3325 | mpz_t result; | 3380 | mpz_t result; |
| 3326 | eassume (FIXNUMP (value)); | 3381 | eassume (FIXNUMP (value)); |
| 3327 | mpz_init (result); | 3382 | mpz_init (result); |
| 3328 | if (lsh) | 3383 | |
| 3329 | mpz_set_uintmax (result, XUINT (value)); | 3384 | mpz_set_intmax (result, XINT (value)); |
| 3330 | else | 3385 | |
| 3331 | mpz_set_intmax (result, XINT (value)); | ||
| 3332 | if (XINT (count) >= 0) | 3386 | if (XINT (count) >= 0) |
| 3333 | mpz_mul_2exp (result, result, XINT (count)); | 3387 | mpz_mul_2exp (result, result, XINT (count)); |
| 3334 | else | 3388 | else if (lsh) |
| 3335 | mpz_tdiv_q_2exp (result, result, - XINT (count)); | 3389 | { |
| 3390 | if (mpz_sgn (result) > 0) | ||
| 3391 | mpz_fdiv_q_2exp (result, result, - XINT (count)); | ||
| 3392 | else | ||
| 3393 | mpz_fdiv_q_2exp (result, result, - XINT (count)); | ||
| 3394 | } | ||
| 3395 | else /* ash */ | ||
| 3396 | mpz_fdiv_q_2exp (result, result, - XINT (count)); | ||
| 3397 | |||
| 3336 | val = make_number (result); | 3398 | val = make_number (result); |
| 3337 | mpz_clear (result); | 3399 | mpz_clear (result); |
| 3338 | } | 3400 | } |
| @@ -3414,7 +3476,7 @@ Markers are converted to integers. */) | |||
| 3414 | else | 3476 | else |
| 3415 | { | 3477 | { |
| 3416 | eassume (FIXNUMP (number)); | 3478 | eassume (FIXNUMP (number)); |
| 3417 | if (XINT (number) > MOST_POSITIVE_FIXNUM) | 3479 | if (XINT (number) > MOST_NEGATIVE_FIXNUM) |
| 3418 | XSETINT (number, XINT (number) - 1); | 3480 | XSETINT (number, XINT (number) - 1); |
| 3419 | else | 3481 | else |
| 3420 | { | 3482 | { |