multiply an integer by a power of two.
/* -*-C-*-
-$Id: artutl.c,v 1.13 1997/04/22 22:42:16 cph Exp $
+$Id: artutl.c,v 1.14 1997/04/23 05:40:18 cph Exp $
Copyright (c) 1989-97 Massachusetts Institute of Technology
}
}
\f
+static unsigned long
+DEFUN (unsigned_long_length_in_bits, (n), unsigned long n)
+{
+ unsigned long result = 0;
+ while (n > 0)
+ {
+ result += 1;
+ n >>= 1;
+ }
+ return (result);
+}
+
SCHEME_OBJECT
DEFUN (integer_length_in_bits, (n), SCHEME_OBJECT n)
{
if (FIXNUM_P (n))
{
long n1 = (FIXNUM_TO_LONG (n));
- unsigned long n2 = ((n1 < 0) ? (- n1) : n1);
- unsigned long result = ((sizeof (unsigned long)) * CHAR_BIT);
- unsigned long m = (1 << (result - 1));
- while (result > 0)
- {
- if (n2 >= m)
- break;
- result -= 1;
- m >>= 1;
- }
- return (LONG_TO_UNSIGNED_FIXNUM (result));
+ return (LONG_TO_UNSIGNED_FIXNUM
+ (unsigned_long_length_in_bits ((n1 < 0) ? (- n1) : n1)));
}
else
return (bignum_length_in_bits (n));
}
+
+SCHEME_OBJECT
+DEFUN (integer_shift_left, (n, m), SCHEME_OBJECT n AND unsigned long m)
+{
+ if ((m == 0) || (!integer_positive_p (n)))
+ return (n);
+ if (FIXNUM_P (n))
+ {
+ unsigned long n1 = (UNSIGNED_FIXNUM_TO_LONG (n));
+ unsigned long ln = (unsigned_long_length_in_bits (n1));
+ unsigned long lr = (ln + m);
+ return
+ ((lr <= FIXNUM_LENGTH)
+ ? (LONG_TO_UNSIGNED_FIXNUM (n1 << m))
+ : (unsigned_long_to_shifted_bignum (n1, m, 0)));
+ }
+ else
+ return (bignum_shift_left (n, m));
+}
/* -*-C-*-
-$Id: bignum.c,v 9.43 1997/01/02 05:21:30 cph Exp $
+$Id: bignum.c,v 9.44 1997/04/23 05:40:11 cph Exp $
Copyright (c) 1989-97 Massachusetts Institute of Technology
}
\f
bignum_type
+DEFUN (bignum_shift_left, (n, m), bignum_type n AND unsigned long m)
+{
+ unsigned long ln = (BIGNUM_LENGTH (n));
+ unsigned long delta = 0;
+ if (m == 0)
+ return (n);
+ {
+ bignum_digit_type digit = (BIGNUM_REF (n, (ln - 1)));
+ while (digit > 0)
+ {
+ delta += 1;
+ digit >>= 1;
+ }
+ }
+ {
+ unsigned long zeroes = (m / BIGNUM_DIGIT_LENGTH);
+ unsigned long shift = (m % BIGNUM_DIGIT_LENGTH);
+ unsigned long ln2
+ = (((ln - 1) + ((delta + m) / BIGNUM_DIGIT_LENGTH))
+ + (((delta + m) % BIGNUM_DIGIT_LENGTH) != 0));
+ bignum_type result = (bignum_allocate (ln2, (BIGNUM_NEGATIVE_P (n))));
+ bignum_digit_type * scan_n = (BIGNUM_START_PTR (n));
+ bignum_digit_type * end_n = (scan_n + ln);
+ bignum_digit_type * scan_result = (BIGNUM_START_PTR (result));
+ while ((zeroes--) > 0)
+ (*scan_result++) = 0;
+ if (shift == 0)
+ while (scan_n < end_n)
+ (*scan_result++) = (*scan_n++);
+ else
+ {
+ unsigned long temp = 0;
+ while (scan_n < end_n)
+ {
+ bignum_digit_type digit = (*scan_n++);
+ (*scan_result++) = (((digit << shift) & BIGNUM_DIGIT_MASK) | temp);
+ temp = (digit >> (BIGNUM_DIGIT_LENGTH - shift));
+ }
+ if (temp != 0)
+ (*scan_result) = temp;
+ }
+ return (result);
+ }
+}
+
+bignum_type
+DEFUN (unsigned_long_to_shifted_bignum, (n, m, sign),
+ unsigned long n AND
+ unsigned long m AND
+ int sign)
+{
+ unsigned long delta = 0;
+ if (n == 0)
+ return (BIGNUM_ZERO ());
+ {
+ unsigned long n1 = n;
+ while (n1 > 0)
+ {
+ delta += 1;
+ n1 >>= 1;
+ }
+ }
+ {
+ unsigned long zeroes = (m / BIGNUM_DIGIT_LENGTH);
+ unsigned long shift = (m % BIGNUM_DIGIT_LENGTH);
+ unsigned long ln
+ = (((delta + m) / BIGNUM_DIGIT_LENGTH)
+ + (((delta + m) % BIGNUM_DIGIT_LENGTH) != 0));
+ bignum_type result = (bignum_allocate (ln, sign));
+ bignum_digit_type * scan_result = (BIGNUM_START_PTR (result));
+ while ((zeroes--) > 0)
+ (*scan_result++) = 0;
+ (*scan_result++) = ((n << shift) & BIGNUM_DIGIT_MASK);
+ n >>= (BIGNUM_DIGIT_LENGTH - shift);
+ while (n > 0)
+ {
+ (*scan_result++) = (n & BIGNUM_DIGIT_MASK);
+ n >>= BIGNUM_DIGIT_LENGTH;
+ }
+ return (result);
+ }
+}
+\f
+bignum_type
DEFUN (digit_stream_to_bignum,
(n_digits, producer, context, radix, negative_p),
fast unsigned int n_digits
/* -*-C-*-
-$Id: bignum.h,v 9.29 1996/10/02 18:57:02 cph Exp $
+$Id: bignum.h,v 9.30 1997/04/23 05:40:26 cph Exp $
-Copyright (c) 1989-96 Massachusetts Institute of Technology
+Copyright (c) 1989-97 Massachusetts Institute of Technology
This material was developed by the Scheme project at the Massachusetts
Institute of Technology, Department of Electrical Engineering and
int twos_complement_p));
extern bignum_type EXFUN (bignum_length_in_bits, (bignum_type));
extern bignum_type EXFUN (bignum_length_upper_limit, (void));
+extern bignum_type EXFUN (bignum_shift_left, (bignum_type, unsigned long));
+extern bignum_type EXFUN
+ (unsigned_long_to_shifted_bignum, (unsigned long, unsigned long, int));
extern bignum_type EXFUN
(digit_stream_to_bignum,
(unsigned int n_digits,
/* -*-C-*-
-$Id: extern.h,v 9.54 1997/04/22 22:42:25 cph Exp $
+$Id: extern.h,v 9.55 1997/04/23 05:41:03 cph Exp $
Copyright (c) 1987-97 Massachusetts Institute of Technology
extern SCHEME_OBJECT EXFUN (integer_quotient, (SCHEME_OBJECT, SCHEME_OBJECT));
extern SCHEME_OBJECT EXFUN (integer_remainder, (SCHEME_OBJECT, SCHEME_OBJECT));
extern SCHEME_OBJECT EXFUN (integer_length_in_bits, (SCHEME_OBJECT));
+extern SCHEME_OBJECT EXFUN
+ (integer_shift_left, (SCHEME_OBJECT, SCHEME_OBJECT));
/* Character utilities */
extern long EXFUN (char_downcase, (long));
/* -*-C-*-
-$Id: intprm.c,v 1.5 1997/04/22 22:42:41 cph Exp $
+$Id: intprm.c,v 1.6 1997/04/23 05:40:32 cph Exp $
Copyright (c) 1989-97 Massachusetts Institute of Technology
PRIMITIVE_RETURN (SHARP_F);
}
}
+
+DEFINE_PRIMITIVE ("INTEGER-SHIFT-LEFT", Prim_integer_shift_left, 2, 2, 0)
+{
+ PRIMITIVE_HEADER (2);
+ Set_Time_Zone (Zone_Math);
+ CHECK_ARG (1, INTEGER_P);
+ {
+ SCHEME_OBJECT n = (ARG_REF (1));
+ if (integer_negative_p (n))
+ error_bad_range_arg (1);
+ PRIMITIVE_RETURN (integer_shift_left (n, (arg_ulong_integer (2))));
+ }
+}