aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/data.c')
-rw-r--r--src/data.c60
1 files changed, 24 insertions, 36 deletions
diff --git a/src/data.c b/src/data.c
index 5a355d9787c..a39978ab1dc 100644
--- a/src/data.c
+++ b/src/data.c
@@ -3365,30 +3365,44 @@ representation. */)
3365 : count_one_bits_ll (v)); 3365 : count_one_bits_ll (v));
3366} 3366}
3367 3367
3368static Lisp_Object 3368DEFUN ("ash", Fash, Sash, 2, 2, 0,
3369ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh) 3369 doc: /* Return VALUE with its bits shifted left by COUNT.
3370If COUNT is negative, shifting is actually to the right.
3371In this case, the sign bit is duplicated. */)
3372 (Lisp_Object value, Lisp_Object count)
3370{ 3373{
3371 /* This code assumes that signed right shifts are arithmetic. */
3372 verify ((EMACS_INT) -1 >> 1 == -1);
3373
3374 Lisp_Object val; 3374 Lisp_Object val;
3375 3375
3376 /* The negative of the minimum value of COUNT that fits into a fixnum,
3377 such that mpz_fdiv_q_exp supports -COUNT. */
3378 EMACS_INT minus_count_min = min (-MOST_NEGATIVE_FIXNUM,
3379 TYPE_MAXIMUM (mp_bitcnt_t));
3376 CHECK_INTEGER (value); 3380 CHECK_INTEGER (value);
3377 CHECK_FIXNUM (count); 3381 CHECK_RANGED_INTEGER (count, - minus_count_min, TYPE_MAXIMUM (mp_bitcnt_t));
3378 3382
3379 if (BIGNUMP (value)) 3383 if (BIGNUMP (value))
3380 { 3384 {
3385 if (XFIXNUM (count) == 0)
3386 return value;
3381 mpz_t result; 3387 mpz_t result;
3382 mpz_init (result); 3388 mpz_init (result);
3383 if (XFIXNUM (count) >= 0) 3389 if (XFIXNUM (count) > 0)
3384 mpz_mul_2exp (result, XBIGNUM (value)->value, XFIXNUM (count)); 3390 mpz_mul_2exp (result, XBIGNUM (value)->value, XFIXNUM (count));
3385 else if (lsh)
3386 mpz_tdiv_q_2exp (result, XBIGNUM (value)->value, - XFIXNUM (count));
3387 else 3391 else
3388 mpz_fdiv_q_2exp (result, XBIGNUM (value)->value, - XFIXNUM (count)); 3392 mpz_fdiv_q_2exp (result, XBIGNUM (value)->value, - XFIXNUM (count));
3389 val = make_number (result); 3393 val = make_number (result);
3390 mpz_clear (result); 3394 mpz_clear (result);
3391 } 3395 }
3396 else if (XFIXNUM (count) <= 0)
3397 {
3398 /* This code assumes that signed right shifts are arithmetic. */
3399 verify ((EMACS_INT) -1 >> 1 == -1);
3400
3401 EMACS_INT shift = -XFIXNUM (count);
3402 EMACS_INT result = (shift < EMACS_INT_WIDTH ? XFIXNUM (value) >> shift
3403 : XFIXNUM (value) < 0 ? -1 : 0);
3404 val = make_fixnum (result);
3405 }
3392 else 3406 else
3393 { 3407 {
3394 /* Just do the work as bignums to make the code simpler. */ 3408 /* Just do the work as bignums to make the code simpler. */
@@ -3400,14 +3414,7 @@ ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh)
3400 3414
3401 if (XFIXNUM (count) >= 0) 3415 if (XFIXNUM (count) >= 0)
3402 mpz_mul_2exp (result, result, XFIXNUM (count)); 3416 mpz_mul_2exp (result, result, XFIXNUM (count));
3403 else if (lsh) 3417 else
3404 {
3405 if (mpz_sgn (result) > 0)
3406 mpz_fdiv_q_2exp (result, result, - XFIXNUM (count));
3407 else
3408 mpz_fdiv_q_2exp (result, result, - XFIXNUM (count));
3409 }
3410 else /* ash */
3411 mpz_fdiv_q_2exp (result, result, - XFIXNUM (count)); 3418 mpz_fdiv_q_2exp (result, result, - XFIXNUM (count));
3412 3419
3413 val = make_number (result); 3420 val = make_number (result);
@@ -3417,24 +3424,6 @@ ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh)
3417 return val; 3424 return val;
3418} 3425}
3419 3426
3420DEFUN ("ash", Fash, Sash, 2, 2, 0,
3421 doc: /* Return VALUE with its bits shifted left by COUNT.
3422If COUNT is negative, shifting is actually to the right.
3423In this case, the sign bit is duplicated. */)
3424 (register Lisp_Object value, Lisp_Object count)
3425{
3426 return ash_lsh_impl (value, count, false);
3427}
3428
3429DEFUN ("lsh", Flsh, Slsh, 2, 2, 0,
3430 doc: /* Return VALUE with its bits shifted left by COUNT.
3431If COUNT is negative, shifting is actually to the right.
3432In this case, zeros are shifted in on the left. */)
3433 (register Lisp_Object value, Lisp_Object count)
3434{
3435 return ash_lsh_impl (value, count, true);
3436}
3437
3438DEFUN ("1+", Fadd1, Sadd1, 1, 1, 0, 3427DEFUN ("1+", Fadd1, Sadd1, 1, 1, 0,
3439 doc: /* Return NUMBER plus one. NUMBER may be a number or a marker. 3428 doc: /* Return NUMBER plus one. NUMBER may be a number or a marker.
3440Markers are converted to integers. */) 3429Markers are converted to integers. */)
@@ -4235,7 +4224,6 @@ syms_of_data (void)
4235 defsubr (&Slogior); 4224 defsubr (&Slogior);
4236 defsubr (&Slogxor); 4225 defsubr (&Slogxor);
4237 defsubr (&Slogcount); 4226 defsubr (&Slogcount);
4238 defsubr (&Slsh);
4239 defsubr (&Sash); 4227 defsubr (&Sash);
4240 defsubr (&Sadd1); 4228 defsubr (&Sadd1);
4241 defsubr (&Ssub1); 4229 defsubr (&Ssub1);