(import (rnrs)) ;R6RS (import (rnrs arithmetic bitwise)) ;R6RS (import (rnrs arithmetic fixnums)) ;R6RS
(bitwise-arithmetic-shift n amount) (bitwise-arithmetic-shift-left n amount) (bitwise-arithmetic-shift-right n amount) (fxarithmetic-shift n amount) (fxarithmetic-shift-left n amount) (fxarithmetic-shift-right n amount)
More precisely, these procedures compute the result of the following expression. The -right variants first negate amount.
(floor (* n (expt 2 amount)))
The variants with -left or -right require a non-negative amount. The fixnum variants raise an exception if the result would not be a fixnum. They also restrict amount, see below.
(fxarithmetic-shift-left #b110011 1) => #b1100110 (bitwise-arithmetic-shift -6 -1) => -3 (bitwise-arithmetic-shift -5 -1) => -3 (bitwise-arithmetic-shift -4 -1) => -2 (bitwise-arithmetic-shift -3 -1) => -2 (bitwise-arithmetic-shift -2 -1) => -1 (bitwise-arithmetic-shift -1 -1) => -1
Truncating left shift can be achieved by masking the input so that only the remaining bits are kept, before calling the left shift procedure.
Fixnums are only guaranteed to have 24-bit precision, so code dealing with e.g. 32-bit integers should be prepared to use the generic variants.
These procedures are not available in R7RS-small. See SRFI-60 and SRFI-151.
https://github.com/schemedoc/manpages/
.
These procedures have been known to give bad results for unusual combinations of inputs. Here is a list of some of them so that you may compare with your own implementation.
(bitwise-arithmetic-shift-right -2 (+ (greatest-fixnum) 1)) => -2 ;WRONG
(fxarithmetic-shift-left #xB00000000000000 2) => #xC00000000000000 ;WRONG (fxarithmetic-shift-left #x-500000000000000 3) => #x-800000000000000 ;WRONG
(bitwise-arithmetic-shift-right 42 (+ 1 (greatest-fixnum))) => 42 ;WRONG
(bitwise-arithmetic-shift-right -1 (+ (greatest-fixnum) 1)) => an exception is raised ;WRONG
(fxarithmetic-shift-right 42 (fixnum-width)) => 42 ;WRONG
(bitwise-arithmetic-shift 0 65) => 0 ;WRONG: a bignum zero