aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
authorTom Tromey2018-07-07 23:42:10 -0600
committerTom Tromey2018-07-12 22:12:28 -0600
commit3dea8f8f53f81a1d15a55c9e3c87a7eade7ca273 (patch)
tree1f543cc1ccfe3552011f899d8f8e132ee9c7c276 /src/data.c
parentd0fac17abdf6883bbf82b1752988db38d05282e6 (diff)
downloademacs-3dea8f8f53f81a1d15a55c9e3c87a7eade7ca273.tar.gz
emacs-3dea8f8f53f81a1d15a55c9e3c87a7eade7ca273.zip
Make % and mod handle bignums
* src/data.c (Frem, Fmod): Handle bignums. * src/lisp.h (CHECK_INTEGER_COERCE_MARKER): New macro. * test/src/data-tests.el (data-tests-check-sign) (data-tests-%-mod): New tests.
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c112
1 files changed, 97 insertions, 15 deletions
diff --git a/src/data.c b/src/data.c
index 7ded8366e32..ac74ff5547f 100644
--- a/src/data.c
+++ b/src/data.c
@@ -3073,13 +3073,47 @@ Both must be integers or markers. */)
3073{ 3073{
3074 Lisp_Object val; 3074 Lisp_Object val;
3075 3075
3076 CHECK_FIXNUM_COERCE_MARKER (x); 3076 CHECK_INTEGER_COERCE_MARKER (x);
3077 CHECK_FIXNUM_COERCE_MARKER (y); 3077 CHECK_INTEGER_COERCE_MARKER (y);
3078 3078
3079 if (XINT (y) == 0) 3079 /* Note that a bignum can never be 0, so we don't need to check that
3080 case. */
3081 if (FIXNUMP (y) && XINT (y) == 0)
3080 xsignal0 (Qarith_error); 3082 xsignal0 (Qarith_error);
3081 3083
3082 XSETINT (val, XINT (x) % XINT (y)); 3084 if (FIXNUMP (x) && FIXNUMP (y))
3085 XSETINT (val, XINT (x) % XINT (y));
3086 else
3087 {
3088 mpz_t xm, ym, *xmp, *ymp;
3089 mpz_t result;
3090
3091 if (BIGNUMP (x))
3092 xmp = &XBIGNUM (x)->value;
3093 else
3094 {
3095 mpz_init_set_si (xm, XINT (x));
3096 xmp = &xm;
3097 }
3098
3099 if (BIGNUMP (y))
3100 ymp = &XBIGNUM (y)->value;
3101 else
3102 {
3103 mpz_init_set_si (ym, XINT (y));
3104 ymp = &ym;
3105 }
3106
3107 mpz_init (result);
3108 mpz_tdiv_r (result, *xmp, *ymp);
3109 val = make_number (result);
3110 mpz_clear (result);
3111
3112 if (xmp == &xm)
3113 mpz_clear (xm);
3114 if (ymp == &ym)
3115 mpz_clear (ym);
3116 }
3083 return val; 3117 return val;
3084} 3118}
3085 3119
@@ -3092,25 +3126,73 @@ Both X and Y must be numbers or markers. */)
3092 Lisp_Object val; 3126 Lisp_Object val;
3093 EMACS_INT i1, i2; 3127 EMACS_INT i1, i2;
3094 3128
3095 CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER (x); 3129 CHECK_NUMBER_COERCE_MARKER (x);
3096 CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER (y); 3130 CHECK_NUMBER_COERCE_MARKER (y);
3131
3132 /* Note that a bignum can never be 0, so we don't need to check that
3133 case. */
3134 if (FIXNUMP (y) && XINT (y) == 0)
3135 xsignal0 (Qarith_error);
3097 3136
3098 if (FLOATP (x) || FLOATP (y)) 3137 if (FLOATP (x) || FLOATP (y))
3099 return fmod_float (x, y); 3138 return fmod_float (x, y);
3100 3139
3101 i1 = XINT (x); 3140 if (FIXNUMP (x) && FIXNUMP (y))
3102 i2 = XINT (y); 3141 {
3142 i1 = XINT (x);
3143 i2 = XINT (y);
3103 3144
3104 if (i2 == 0) 3145 if (i2 == 0)
3105 xsignal0 (Qarith_error); 3146 xsignal0 (Qarith_error);
3106 3147
3107 i1 %= i2; 3148 i1 %= i2;
3108 3149
3109 /* If the "remainder" comes out with the wrong sign, fix it. */ 3150 /* If the "remainder" comes out with the wrong sign, fix it. */
3110 if (i2 < 0 ? i1 > 0 : i1 < 0) 3151 if (i2 < 0 ? i1 > 0 : i1 < 0)
3111 i1 += i2; 3152 i1 += i2;
3153
3154 XSETINT (val, i1);
3155 }
3156 else
3157 {
3158 mpz_t xm, ym, *xmp, *ymp;
3159 mpz_t result;
3160 int cmpr, cmpy;
3161
3162 if (BIGNUMP (x))
3163 xmp = &XBIGNUM (x)->value;
3164 else
3165 {
3166 mpz_init_set_si (xm, XINT (x));
3167 xmp = &xm;
3168 }
3169
3170 if (BIGNUMP (y))
3171 ymp = &XBIGNUM (y)->value;
3172 else
3173 {
3174 mpz_init_set_si (ym, XINT (y));
3175 ymp = &ym;
3176 }
3177
3178 mpz_init (result);
3179 mpz_mod (result, *xmp, *ymp);
3180
3181 /* Fix the sign if needed. */
3182 cmpr = mpz_cmp_si (result, 0);
3183 cmpy = mpz_cmp_si (*ymp, 0);
3184 if (cmpy < 0 ? cmpr > 0 : cmpr < 0)
3185 mpz_add (result, result, *ymp);
3186
3187 val = make_number (result);
3188 mpz_clear (result);
3189
3190 if (xmp == &xm)
3191 mpz_clear (xm);
3192 if (ymp == &ym)
3193 mpz_clear (ym);
3194 }
3112 3195
3113 XSETINT (val, i1);
3114 return val; 3196 return val;
3115} 3197}
3116 3198