For Gauche 0.9.5


Next: , Previous: , Up: Core library   [Contents][Index]

6.3 Numbers

Gauche supports the following types of numbers

multi-precision exact integer

There’s no limit of the size of number except the memory of the machine.

multi-precision exact non-integral rational numbers.

Both denominator and numerator are represented by exact integers. There’s no limit of the size of number except the memory of the machine.

inexact floating-point real numbers

Using double-type of underlying C compiler, usually IEEE 64-bit floating point number.

inexact floating-point complex numbers

Real part and imaginary part are represented by inexact floating-point real numbers.


Next: , Previous: , Up: Numbers   [Contents][Index]

6.3.1 Number classes

Builtin Class: <number>
Builtin Class: <complex>
Builtin Class: <real>
Builtin Class: <rational>
Builtin Class: <integer>

These classes consist a class hierarchy of number objects. <complex> inherits <number>, <real> inherits <complex>,<rational> inherits <real> and <integer> inherits <rational>.

Note that these classes do not exactly correspond to the number hierarchy defined in R7RS. Especially, only exact integers are the instances of the <integer> class. That is,

(integer? 1)        ⇒ #t
(is-a? 1 <integer>) ⇒ #t
(is-a? 1 <real>)    ⇒ #t

(integer? 1.0)        ⇒ #t
(is-a? 1.0 <integer>) ⇒ #f
(is-a? 1.0 <real>)    ⇒ #t

(class-of (expt 2 100)) ⇒ #<class <integer>>
(class-of (sqrt -3)) ⇒ #<class <complex>>

Next: , Previous: , Up: Numbers   [Contents][Index]

6.3.2 Numerical predicates

Function: number? obj
Function: complex? obj
Function: real? obj
Function: rational? obj
Function: integer? obj

[R7RS] Returns #t if obj is a number, a complex number, a real number, a rational number or an integer, respectively. In Gauche, a set of numbers is the same as a set of complex numbers. A set of rational numbers is the same as a set of real numbers, except +inf.0, -inf.0 and +nan.0 (since we have only limited-precision floating numbers).

(complex? 3+4i)   ⇒ #t
(complex? 3)      ⇒ #t
(real? 3)         ⇒ #t
(real? -2.5+0.0i) ⇒ #t
(real? #e1e10)    ⇒ #t
(integer? 3+0i)   ⇒ #t
(integer? 3.0)    ⇒ #t

(real? +inf.0)     ⇒ #t
(real? +nan.0)     ⇒ #t
(rational? +inf.0) ⇒ #f
(rational? +nan.0) ⇒ #f

Note: R6RS adopts more strict definition on exactness, and notably, it defines a complex number with non-exact zero imaginary part is not a real number. Currently Gauche doesn’t have exact complex numbers, and automatically coerces complex numbers with zero imaginary part to a real number. Thus R6RS code that relies on the fact that (real? 1+0.0i) is #f won’t work with Gauche.

Function: real-valued? obj
Function: rational-valued? obj
Function: integer-valued? obj

[R6RS] In Gauche these are just an alias of real?, rational? and integer?. They are provided for R6RS compatibility.

The difference of those and non -valued versions in R6RS is that these returns #t if obj is a complex number with nonexact zero imaginary part. Since Gauche doesn’t distinguish complex numbers with zero imaginary part and real numbers, we don’t have the difference.

Function: exact? obj
Function: inexact? obj

[R7RS] Returns #t if obj is an exact number and an inexact number, respectively.

(exact? 1)       ⇒ #t
(exact? 1.0)     ⇒ #f
(inexact? 1)     ⇒ #f
(inexact? 1.0)   ⇒ #t

(exact? (modulo 5 3)) ⇒ #t
(inexact? (modulo 5 3.0)) ⇒ #f
Function: exact-integer? obj

[R7RS] Same as (and (exact? obj) (integer? obj)), but more efficient.

Function: zero? z

[R7RS] Returns #t if a number z equals to zero.

(zero? 1)        ⇒ #f
(zero? 0)        ⇒ #t
(zero? 0.0)      ⇒ #t
(zero? 0.0+0.0i) ⇒ #t
Function: positive? x
Function: negative? x

[R7RS] Returns #t if a real number x is positive and negative, respectively. It is an error to pass a non-real number.

Function: finite? z
Function: infinite? z
Function: nan? z

[R7RS] For real numbers, returns #f iff the given number is finite, infinite, or NaN, respectively.

For non-real complex numbers, finite? returns #t iff both real and imaginary components are finite, infinite? returns #t if at least either real or imaginary component is infinite, and nan? returns #t if at least either real or imaginary component is NaN. (Note: It is incompatible to R6RS, in which these procedures must raise an error if the given argument is non-real number.)

In R7RS, these procedures are in (scheme inexact) library.

Function: odd? n
Function: even? n

[R7RS] Returns #t if an integer n is odd and even, respectively. It is an error to pass a non-integral number.

(odd? 3)     ⇒ #t
(even? 3)    ⇒ #f
(odd? 3.0)   ⇒ #t
Function: fixnum? n
Function: bignum? n

Returns #t iff n is an exact integer whose internal representation is fixnum and bignum, respectively. Portable Scheme programs don’t need to care about the internal representation of integer. These are for certain low-level routines that does particular optimization.


Next: , Previous: , Up: Numbers   [Contents][Index]

6.3.3 Numerical comparison

Function: = z1 z2 z3 …

[R7RS] If all the numbers z are equal, returns #t.

(= 2 2)          ⇒ #t
(= 2 3)          ⇒ #f
(= 2 2.0)        ⇒ #t
(= 2 2.0 2.0+0i) ⇒ #t
(= 2/4 1/2)      ⇒ #t
Function: < x1 x2 x3 …
Function: <= x1 x2 x3 …
Function: > x1 x2 x3 …
Function: >= x1 x2 x3 …

[R7RS] Returns #t If all the real numbers x are monotonically increasing, monotonically nondecreasing, monotonically decreasing, or monotonically nonincreasing, respectively.

Function: max x1 x2 …
Function: min x1 x2 …

[R7RS] Returns a maximum or minimum number in the given real numbers, respectively. If any of the arguments are NaN, NaN is returned.

See also find-min and find-max in Selection and searching in collection.

Function: min&max x1 x2 …

Returns a maximum and minimum number in the given real numbers.

See also find-min&max in Selection and searching in collection.


Next: , Previous: , Up: Numbers   [Contents][Index]

6.3.4 Arithmetics

Function: + z …
Function: * z …

[R7RS] Returns the sum or the product of given numbers, respectively. If no argument is given, (+) yields 0 and (*) yields 1.

Function: - z1 z2 …
Function: / z1 z2 …

[R7RS] If only one number z1 is given, returns its negation and reciprocal, respectively.

If more than one number are given, returns:

z1 - z2 - z3z1 / z2 / z3

respectively.

(- 3)       ⇒ -3
(- -3.0)    ⇒ 3.0
(- 5+2i)    ⇒ -5.0-2.0i
(/ 3)       ⇒ 1/3
(/ 5+2i)    ⇒ 0.172413793103448-0.0689655172413793i

(- 5 2 1)     ⇒ 2
(- 5 2.0 1)   ⇒ 2.0
(- 5+3i -i)   ⇒ 5.0+2.0i
(/ 14 6)      ⇒ 7/3
(/ 6+2i 2)    ⇒ 3.0+1.0i

Note: Gauche didn’t have exact rational number support until 0.8.8; before that, / coerced the result to inexact even if both divisor and dividend were exact numbers, when the result wasn’t a whole number. It is not the case anymore.

If the existing code relies on the old behavior, it runs very slowly on the newer versions of Gauche, since the calculation proceeds with exact rational arithmetics that is much slower than floating point arithmetics. You want to use /. below to use fast inexact arithmetics (unless you need exact results).

Function: +. z …
Function: *. z …
Function: -. z1 z2 …
Function: /. z1 z2 …

Like +, *, -, and /, but the arguments are coerced to inexact number. So they always return inexact number. These are useful when you know you don’t need exact calculation and want to avoid accidental overhead of bignums and/or exact rational numbers.

Function: abs z

[R7RS+] For real number z, returns an absolute value of it. For complex number z, returns the magnitude of the number. The complex part is Gauche extension.

(abs -1)   ⇒ 1
(abs -1.0) ⇒ 1.0
(abs 1+i)  ⇒ 1.4142135623731
Function: quotient n1 n2
Function: remainder n1 n2
Function: modulo n1 n2

[R7RS] Returns the quotient, remainder and modulo of dividing an integer n1 by an integer n2. The result is an exact number only if both n1 and n2 are exact numbers.

Remainder and modulo differ when either one of the arguments is negative. Remainder R and quotient Q have the following relationship.

  n1 = Q * n2 + R

where abs(Q) = floor(abs(n1)/abs(n2)). Consequently, R’s sign is always the same as n1’s.

On the other hand, modulo works as expected for positive n2, regardless of the sign of n1 (e.g. (modulo -1 n2) == n2 - 1). If n2 is negative, it is mapped to the positive case by the following relationship.

  modulo(n1, n2) = -modulo(-n1, -n2)

Consequently, modulo’s sign is always the same as n2’s.

(remainder 10 3)    ⇒ 1
(modulo 10 3)       ⇒ 1

(remainder -10 3)   ⇒ -1
(modulo -10 3)      ⇒ 2

(remainder 10 -3)   ⇒ 1
(modulo 10 -3)      ⇒ -2

(remainder -10 -3)  ⇒ -1
(modulo -10 -3)     ⇒ -1
Function: quotient&remainder n1 n2

Calculates the quotient and the remainder of dividing integer n1 by integer n2 simultaneously, and returns them as two values.

Function: div x y
Function: mod x y
Function: div-and-mod x y
Function: div0 x y
Function: mod0 x y
Function: div0-and-mod0 x y

[R6RS] These are integer division procedures introduced in R6RS. Unlike quotient, modulo and remainder, these procedures can take non-integral values. The dividend x can be an arbitrary real number, and the divisor y can be non-zero real number.

div returns an integer n, and mod returns a real number m, such that:

Examples:

(div 123 10)     ⇒ 12
(mod 123 10)     ⇒ 3

(div 123 -10)    ⇒ -12
(mod 123 -10)    ⇒ 3

(div -123 10)    ⇒ -13
(mod -123 10)    ⇒ 7

(div -123 -10)   ⇒ 13
(mod -123 -10)   ⇒ 7

(div 123/7 10/9) ⇒ 15
(mod 123/7 10/9) ⇒ 19/21
;; 123/7 = 10/9 * 15 + 19/21

(div 14.625 3.75) ⇒ 3.0
(mod 14.625 3.75) ⇒ 3.375
;; 14.625 = 3.75 * 3.0 + 3.375

For a nonnegative integer x and an integer y, The results of div and mod matches those of quotient and remainder. If x is negative, they differ, though.

div-and-mod calculates both div and mod and returns their results in two values.

div0 and mod0 are similar, except the range of m:

(div0 123 10)   ⇒ 12
(mod0 123 10)   ⇒ 3

(div0 127 10)   ⇒ 13
(mod0 127 10)   ⇒ -3

(div0 127 -10)  ⇒ -13
(mod0 127 -10)  ⇒ -3

(div0 -127 10)  ⇒ -13
(mod0 -127 10)  ⇒ 3

(div0 -127 -10) ⇒ 13
(mod0 -127 -10) ⇒ 3

div0-and-mod0 calculates both div0 and mod0 and returns their results in two values.

Here’s a visualization of R6RS and R7RS division and modulo operations: http://blog.practical-scheme.net/gauche/20100618-integer-divisions It might help to grasp how they works.

Function: gcd n …
Function: lcm n …

[R7RS] Returns the greatest common divisor or the least common multiplier of the given integers, respectively

Arguments must be integers, but doesn’t need to be exact. If any of arguments is inexact, the result is inexact.

Function: continued-fraction x

Returns a lazy sequence of regular continued fraction expansion of finite real number x. An error is raised if x is infinite or NaN, or not a real number. The returned sequence is lazy, so the terms are calculated as needed.

(continued-fraction 13579/2468)
  ⇒ (5 1 1 122 1 9)

(+ 5 (/ (+ 1 (/ (+ 1 (/ (+ 122 (/ (+ 1 (/ 9))))))))))
  ⇒ 13579/2468

(continued-fraction (exact 3.141592653589793))
  ⇒ (3 7 15 1 292 1 1 1 2 1 3 1 14 3 3 2 1 3 3 7 2 1 1 3 2 42 2)

(continued-fraction 1.5625)
  ⇒ (1.0 1.0 1.0 3.0 2.0)
Function: numerator q
Function: denominator q

[R7RS] Returns the numerator and denominator of a rational number q.

Function: rationalize x ebound

[R7RS] Returns the simplest rational approximation q of a real number x, such that the difference between x and q is no more than the error bound ebound.

Note that Gauche doesn’t have inexact rational number, so if x and/or ebound is inexact, the result is coerced to floating point representation.

(rationalize 1234/5678 1/1000) ⇒ 5/23

(rationalize 3.141592653589793 1/10000)
  ⇒ 3.141509433962264
(rationalize (exact 3.141592653589793) 1/10000)
  ⇒ 333/106
(rationalize (exact 3.141592653589793) 1/10000000)
  ⇒ 75948/24175

;; Some edge cases
(rationalize 2 +inf.0) ⇒ 0
(rationalize +inf.0 0) ⇒ +inf.0
(rationalize +inf.0 +inf.0) ⇒ +nan.0
Function: floor x
Function: ceiling x
Function: truncate x
Function: round x

[R7RS] The argument x must be a real number. Floor and ceiling return a maximum integer that isn’t greater than x and a minimum integer that isn’t less than x, respectively. Truncate returns an integer that truncates x towards zero. Round returns an integer that is closest to x. If fractional part of x is exactly 0.5, round returns the closest even integer.

Following Scheme’s general rule, the result is inexact if x is an inexact number; e.g. (round 2.3) is 2.0. If you need an exact integer by rounding an inexact number, you have to use exact on the result, or use one of the following procedure ((floor->exact etc).

Function: floor->exact x
Function: ceiling->exact x
Function: truncate->exact x
Function: round->exact x

These are convenience procedures of the popular phrase (exact (floor x)) etc.

Function: clamp x :optional min max

Returns

 min if x < min
 x   if min <= x <= max
 max if max < x

If min or max is omitted or #f, it is regarded as -inf.0 or +inf.0, respectively. Returns an exact integer only if all the given numbers are exact integers.

(clamp 3.1 0.0 1.0) ⇒ 1.0
(clamp 0.5 0.0 1.0) ⇒ 0.5
(clamp -0.3 0.0 1.0) ⇒ 0.0
(clamp -5 0)        ⇒ 0
(clamp 3724 #f 256) ⇒ 256
Function: exp z
Function: log z
Function: log z1 z2
Function: sin z
Function: cos z
Function: tan z
Function: asin z
Function: acos z
Function: atan z
Function: atan y x

[R7RS] Transcendental functions. Work for complex numbers as well. In R7RS, these procedures are in the (scheme inexact) module.

The two-argument version of log is added in R6RS, and returns base-z2 logarithm of z1.

The two-argument version of atan returns (angle (make-rectangular x y)) for the real numbers x and y.

Function: sinh z
Function: cosh z
Function: tanh z
Function: asinh z
Function: acosh z
Function: atanh z

Hyperbolic trigonometric functions. Work for complex numbers as well.

Function: sqrt z

[R7RS] Returns a square root of a complex number z. The branch cut scheme is the same as Common Lisp. For real numbers, it returns a positive root.

If z is the square of an exact real number, the return value is also an exact number.

(sqrt 2)      ⇒ 1.4142135623730951
(sqrt -2)     ⇒ 0.0+1.4142135623730951i
(sqrt 256)    ⇒ 16
(sqrt 256.0)  ⇒ 16.0
(sqrt 81/169) ⇒ 9/13
Function: exact-integer-sqrt k

[R7RS] Given an exact nonnegative integer k, returns two exact nonnegative integer s and r that satisfy the following equations:

k = (+ (* s s) r)
k < (* (+ s 1) (+ s 1))
(exact-integer-sqrt 782763574)
  ⇒ 27977 and 51045
Function: expt z1 z2

[R7RS] Returns z1^z2 (z1 powered by z2), where z1 and z2 are complex numbers.

Function: expt-mod base exponent mod

Calculates (modulo (expt base exponent) mod) efficiently.

The next example shows the last 10 digits of a mersenne prime M_74207281 (2^74207281 - 1)

(- (expt-mod 2 74207281 #e1e10) 1)
 ⇒ 1086436351
Function: gamma x
Function: lgamma x

Gamma function and natural logarithmic of absolute value of Gamma function.

NB: Mathematically these functions are defined in complex domain, but currently we only supports real number argument.

Function: fixnum-width
Function: greatest-fixnum
Function: least-fixnum

[R6RS] These procedures return the width of fixnum (w), the greatest integer representable by fixnum (2^(w-1) - 1), and the least integer representable by fixnum (- 2^(w-1)), respectively. You might want to care the fixnum range when you are writing a performance-critical section.

These names are defined in R6RS. Common Lisp and ChezScheme have most-positive-fixnum and most-negative-fixnum.

NB: Before 0.9.5, fixnum-width had a bug to return one smaller than the supposed value.


Next: , Previous: , Up: Numbers   [Contents][Index]

6.3.5 Numerical conversions

Function: make-rectangular x1 x2
Function: make-polar x1 x2

[R7RS] Creates a complex number from two real numbers, x1 and x2. make-rectangular returns x1 + ix2. make-polar returns x1e^(ix2).

In R7RS, these procedures are in the (scheme complex) library.

Function: real-part z
Function: imag-part z
Function: magnitude z
Function: angle z

[R7RS] Decompose a complex number z and returns a real number. real-part and imag-part return z’s real and imaginary part, respectively. magnitude and angle return z’s magnitude and angle, respectively.

In R7RS, these procedures are in the (scheme complex) library.

Function: decode-float x

For a given finite floating-point number, returns a vector of three exact integers, #(m, e, sign), where

  x = (* sign m (expt 2.0 e))
  sign is either 1, 0 or -1.

If x is +inf.0 or -inf.0, m is #t. If x is +nan.0, m is #f.

The API is taken from ChezScheme.

(decode-float 3.1415926)
 ⇒ #(7074237631354954 -51 1)
(* 7074237631354954 (expt 2.0 -51))
 ⇒ 3.1415926

(decode-float +nan.0)
 ⇒ #(#f 0 -1)
Function: encode-float vector

This is an inverse of decode-float. Vector must be a three-element vector as returned from decode-float.

(encode-float '#(7074237631354954 -51 1))
 ⇒ 3.1415926

(encode-float '#(#t 0 1))
 ⇒ +inf.0
Function: fmod x y
Function: modf x
Function: frexp x
Function: ldexp x n

[POSIX] These procedures can be used to compose and decompose floating point numbers. Fmod computes the remainder of dividing x by y, that is, it returns x-n*y where n is the quotient of x/y rounded towards zero to an integer. Modf returns two values; a fractional part of x and an integral part of x. Frexp returns two values, fraction and exponent of x, where x = fraction * 2^exponent, and 0.5 <= |fraction| < 1.0, unless x is zero. (When x is zero, both fraction and exponent are zero). Ldexp is a reverse operation of frexp; it returns a real number x * 2^n.

(fmod 32.1 10.0)  ⇒ 2.1
(fmod 1.5 1.4)    ⇒ 0.1
(modf 12.5)       ⇒ 0.5 and 12.0
(frexp 3.14)      ⇒ 0.785 and 2
(ldexp 0.785 2)   ⇒ 3.14
Function: exact z
Function: inexact z

[R7RS] Returns an exact or an inexact representation of the given number z, respectively. Passing an exact number to exact, and an inexact number to inexact, are no-op.

Gauche doesn’t have exact complex number with non-zero imaginary part, nor exact infinites and NaNs, so passing those to exact raises an error.

(inexact 1)    ⇒ 1.0
(inexact 1/10) ⇒ 0.1

If an inexact finite real number is passed to exact, the simplest exact rational number within the precision of the floating point representation is returned.

(exact 1.0)     ⇒ 1
(exact 0.1)     ⇒ 1/10
(exact (/ 3.0)) ⇒ 1/3

For all finite inexact real number x, (inexact (exact x)) is always eqv? to the original number x.

(Note that the inverse doesn’t hold, that is, an exact number n and (exact (inexact n)) aren’t necessarily the same. It’s because many (actually, infinite number of) exact numbers can be mapped to one inexact number.)

To specify the error tolerance when converting inexact real numbers to exact rational numbers, use rationalize or real->rational.

Function: exact->inexact z
Function: inexact->exact z

[R5RS] Converts exact number to inexact one, and vice versa.

In fact, exact->inexact returns the argument as is if an inexact number is passed, and inexact->exact returns the argument if an exact number is passed, so in Gauche they are equivalent to inexact and exact, respectively. Note that other R5RS implementation may raise an error if passing an inexact number to exact->inexact, for example.

Generally exact and inexact are preferred, for they are more concise, and you don’t need to care whether the argument is exact or inexact numbers. These procedures are for compatibility with R5RS programs.

Function: real->rational x :optional hi lo open?

Find the simplest rational representation of a finite real number x within the specified error bounds. This is the low-level routine called by rationalize and exact.

The result rational value r satisfies the following condition:

(<= (- x lo) r (+ x hi))   ; when open? is #f
(<  (- x lo) r (+ x hi))   ; otherwise

Note that both hi and lo must be nonnegative.

If hi and/or lo is omitted, it is determined by x: if x is exact, hi and lo are defaulted to zero; if x is inexact, hi and lo depend on the precision of the floating point representation of x. In the latter case, the open? also depends on x—it is true if the mantissa of x is odd, and false otherwise, reflecting the round-to-even rule. So, if you call real->rational with one finite number, you’ll get the same result as exact:

(real->rational 0.1) ⇒ 1/10

Passing zeros to the error bounds makes it return the exact conversion of the floating number itself (that is, the exact calculation of (* sign mantissa (expt 2 exponent))).

(real->rational 0.1 0 0) ⇒ 3602879701896397/36028797018963968

(If you give both hi and lo, but omit open?, we assume closed range.)

Function: number->string z :optional radix use-upper?
Function: string->number string :optional radix

[R7RS+] These procedures convert a number and its string representation in radix radix system. radix must be between 2 and 36 inclusive. If radix is omitted, 10 is assumed.

Number->string takes a number z and returns a string. If z is not an exact integer, radix must be 10. For the numbers with radix more than 10, lower case alphabet character is used for digits, unless the optional argument use-upper? is true, in that case upper case characters are used. The argument use-upper? is Gauche’s extension.

String->number takes a string string and parses it as a number in radix radix system. If the number looks like non-exact number, only radix 10 is allowed. If the given string can’t be a number, #f is returned.

Generic Function: x->number obj
Generic Function: x->integer obj

Generic coercion functions. Returns ‘natural’ interpretation of obj as a number or an exact integer, respectively. The default methods are defined for numbers and strings; a string is interpreted by string->number, and if the string can’t be interpreted as a number, 0 is returned. Other obj is simply converted to 0. If obj is naturally interpreted as a number that is not an exact integer, x->integer uses round and inexact->exact to obtain an integer.

Other class may provide a method to customize the behavior.


Next: , Previous: , Up: Numbers   [Contents][Index]

6.3.6 Bitwise operations

These procedures treat integers as half-open bit vectors. If an integer is positive, it is regarded as if infinite number of zeros are padded to the left. If an integer is negative, it is regarded in 2’s complement form, and infinite number of 1’s are padded to the left.

In regard to the names of those operations, there are two groups in the Scheme world; Gauche follows the names of the original SLIB’s “logical” module, which was rooted in CL. Another group uses a bit long but descriptive name such as arithmetic-shift.

SRFI-60 (see Integers as bits) defines both names, and also some additional procedures. If you’re porting libraries written for other Scheme, you might want to check it.

Function: ash n count

[SRFI-60] Shifts integer n left with count bits. If count is negative, ash shifts n right with -count bits.

; Note: 6  ≡ [...00110], and
;       -6 ≡ [...11010]
(ash 6 2)   ⇒ 24  ;[...0011000]
(ash 6 -2)  ⇒ 1   ;[...0000001]
(ash -6 2)  ⇒ -24 ;[...1101000]
(ash -6 -2) ⇒ -2  ;[...1111110]
Function: logand n1 …
Function: logior n1 …
Function: logxor n1 …

[SRFI-60] Returns bitwise and, bitwise inclusive or and bitwise exclusive or of integers n1 …. If no arguments are given, logand returns -1, and logior and logxor returns 0.

Function: lognot n

[SRFI-60] Returns bitwise not of an integer n.

Function: logtest n1 n2 …

[SRFI-60] ≡ (not (zero? (logand n1 n2 …)))

Function: logbit? index n

[SRFI-60] Returns #t if index-th bit of integer n is 1, #f otherwise.

Function: bit-field n start end

[SRFI-60] Extracts start-th bit (inclusive) to end-th bit (exclusive) from an exact integer n, where start < end.

Function: copy-bit index n bit

[SRFI-60] If bit is true, sets index-th bit of an exact integer n. If bit is false, resets index-th bit of an exact integer n.

Function: copy-bit-field n from start end

[SRFI-60] Returns an exact integer, each bit of which is the same as n except the start-th bit (inclusive) to end-th bit (exclusive), which is a copy of the lower (end-start)-th bits of an exact integer from.

(number->string (copy-bit-field #b10000000 -1 1 5) 2)
  ⇒ "10011110"

(number->string (copy-bit-field #b10000000 #b010101010 1 7) 2)
  ⇒ "11010100"

Note: The API of this procedure was originally taken from SLIB, and at that time, the argument order was (copy-bit-field n start end from). During the discussion of SRFI-60 the argument order was changed for the consistency, and the new versions of SLIB followed it. We didn’t realize the change until recently - before 0.9.4, this procedure had the old argument order. Code that is using this procedure needs to be fixed. If you need your code to work with both versions of Gauche, have the following definition in your code.

(define (copy-bit-field to from start end)
  (if (< start end)
    (let1 mask (- (ash 1 (- end start)) 1)
      (logior (logand to (lognot (ash mask start)))
              (ash (logand from mask) start)))
    from))
Function: logcount n

[SRFI-60] If n is positive, returns the number of 1’s in the bits of n. If n is negative, returns the number of 0’s in the bits of 2’s complement representation of n.

(logcount 0)      ⇒ 0
(logcount #b0010) ⇒ 1
(logcount #b0110) ⇒ 2
(logcount #b1111) ⇒ 4

(logcount #b-0001) ⇒ 0  ;; 2's complement:  ....111111
(logcount #b-0010) ⇒ 1  ;; 2's complement:  ....111110
(logcount #b-0011) ⇒ 1  ;; 2's complement:  ....111101
(logcount #b-0100) ⇒ 2  ;; 2's complement:  ....111100
Function: integer-length n

[SRFI-60] Returns the minimum number of bits required to represent an exact integer n. Negative integer is assumed to be in 2’s complement form. A sign bit is not considered.

(integer-length 255)  ⇒ 8
(integer-length 256)  ⇒ 9

(integer-length -256)  ⇒ 8
(integer-length -257)  ⇒ 9
Function: twos-exponent n

If n is a power of two, that is, (expt 2 k) and k >= 0, then returns k. Returns #f if n is not a power of two.

Function: twos-exponent-factor n

Returns maximum k such that (expt 2 k) is a factor of n. In other words, returns the number of consecutive zero bits from LSB of n. If n is zero, zero is returned.

This can be calculated by the following expression; this procedure is for speed to save creating intermediate numbers when n is bignum.

(- (integer-length (logxor n (- n 1))) 1)

Previous: , Up: Numbers   [Contents][Index]

6.3.7 Endianness

In the Scheme world you rarely need to know about how the numbers are represented inside the machine. However, it matters when you have to exchange data to/from the outer world in binary representation.

Gauche’s binary I/O procedures, such as in the binary.io module (see Binary I/O) and write-uvector/read-uvector! (see Uniform vectors), take optional endian argument to specify the endianness.

Currently Gauche recognizes the following endiannesses.

big-endian

Big endian. With this endianness, a 32-bit integer #x12345678 will be written out as an octet sequence #x12 #x34 #x56 #x78.

little-endian

Little endian. With this endianness, a 32-bit integer #x12345678 is written out as an octet sequence #x78 #x56 #x34 #x12.

arm-little-endian

This is a variation of little-endian, and used in ARM processors in some specific modes. It works just like little-endian, except reading/writing double-precision floating point number (f64), which is written as two little-endian 32bit words ordered by big-endian (e.g. If machine register’s representation is #x0102030405060708, it is written as #x04 #x03 #x02 #x01 #x08 #x07 #x06 #x05.

When the endian argument is omitted, those procedures use the parameter default-endian:

Parameter: default-endian

This is a dynamic parameter (see Parameters) to specify the endianness the binary I/O routines use when its endian argument is omitted. The initial value of this parameter is the system’s native endianness.

The system’s native endianness can be queried with the following procedure:

Function: native-endian

Returns a symbol representing the system’s endianness.


Previous: , Up: Numbers   [Contents][Index]