Next: setoptions() Up: MacAnova Help File Previous: setlabels()   Contents


odometer <- setodometer([lower:L,] upper:U [,ndigits:M, ] [,place:N]),
  L and U integer scalars or vectors, integer M > 0, N >= 0
odometer <- setodometer(odometer, place:N), odometer a structure with
  integer components 'digits', 'lower', 'upper', 'place'
odometer <- setodometer(odometer [,step:n]), integer n, default 1

Keywords: general, macros
                       Description of an odometer
Function setodometer() is used to create or modify an "odometer".  An
odometer is a structure of the form

  structure(digits:D, lower:L, upper:U, place:N)

where D is a vector of M integers and L and U are integer vectors of
length M or scalars.  D, L and U satisfy L[i] <= D[i] <= U[i], where L
and U are interpreted as rep(L, M) and rep(U, M) when they are scalars.

See topics 'scalars', 'vectors' and 'structures' for information on
these types of variables.

See below for how to use setodometer() to create, set and advance an

In the following, when L and/or U are scalars, L[i] and U[i] should be
interpreted as L and/or U (rep(L,M)[i] and/or rep(U,M)[i]).

Note: L[i] = U[i] is permitted.

An odometer is modeled on the distance display in an automobile, with
the M elements of D corresponding to the digits in the display.  It
differs in that D[i] runs from L[i] to U[i] instead of from 0 to 9, and
the digits are in reverse order (D[1] is the least significant, D[M] is
the most significant).  N corresponds to the distance traveled.  When N
= 0, D = vector(L[1], L[2], ..., L[M]) (rep(L,M) when L is a scalar).

Let I = D - L and let R = U - L + 1 (rep(U - L + 1, M) when U and L are
scalars) and define Size = prod(R).

When 0 <= N < Size, the elements of I are the 'digits' of N in a mixed
radix representation with radices R[i], in reverse order.  For example,
when M = 3, N = I[1] + I[2]*R[1] + I[3]*R[1]*R[2].  When L = 0 and U =
m-1 are scalars, the elements of I are the base m digits of N, in order
from least to most significant.  When N < 0 or N >= Size, the elements
of I are the digits of N modulo Size (N - Size*floor(N/Size)).

                          Creating an odometer
O <- setodometer(lower:L, upper:U, ndigits:M) creates an odometer O.  M
> 0 must be an integer, and L and U must be integer scalars or vectors
of length M, with a scalar L or U interpreted as rep(U,M) or rep(L,M).
L and U must satisfy L[i] <= U[i], R[i] = U[i] - L[i] + 1 < 2^31, and
Size = prod(R) < 2^52.  These limits may be different on some computer

Component 'digits' is initialized to L (or rep(L,M) when L is a scalar).
Components 'lower' and 'upper' are initialized to L and U, respectively,
and component 'place' is initialized to 0.

O <- setodometer(lower:L, upper:U), without 'ndigits:M', is equivalent
to O <- setodometer(lower:L,upper:U,ndigits:max(length(L),length(U))).

O <- setodometer(upper:U [,ndigits:M]) is equivalent to O <-
setodometer(lower:0, upper:U [,ndigits:M]); that is, the default value
for 'lower' is 0.

O <- setodometer([lower:L,] upper:U [,ndigits:M], place:N) does the
same, except O$place is set to N and O$digits is set to L + mixed radix
digits of N.  N must satisfy 0 <= N < Size = prod(U-L+1).

                   Setting and advancing an odometer
O1 <- setodometer(O, place:N) is equivalent to O1 <-
odometer(lower:O$lower,upper:O$upper,ndigits:length(O$digits), place:N);
that is, it creates an odometer O1 with the same L and U as O, but at
place N.

O1 <- setodometer(O, step:n), where O is an odometer and n is an
integer, creates an odometer O1 with O1$place = O$place + n.  O1$digits
is computed by stepping O$digits forward n steps when n >= 0, or
backward by -n steps when n < 0.  n must satisfy abs(n) < Size =
prod(U-L+1).  When abs(n) is large, this may take some time since it is
computed as a sequence of single forward or backward steps.

O1 <- setodometer(O) is equivalent to O1 <- setodometer(O, step:1); that
is the odometer is advanced by 1.

When 0 <= O$place + n < Size, setodometer(O, step:n) is equivalent to
setodometer(O, place:O$place + n), except that setodometer(O, step:n)
can be much slower when abs(n) is large.

 Step through the various factor combinations of a 2^k design:
   Cmd> counter <- setodometer(upper:1,ndigits:k) #lower is 0

   Cmd> for(i,run(2^k)){
          levels <- counter$digits
          # do something with levels
          counter <- setodometer(counter);; # step by 1

 Find hexadecimal representation
   Cmd> N <- 9 + 3*16 + 11*16^2 + 15*16^3; N
   (1)       64313

   Cmd> O <- setodometer(upper:15,ndigits:8,place:N); O # lower is 0
   component: digits
   (1)           9           3          11          15           0
   (6)           0           0           0
   component: lower
   (1)           0
   component: upper
   (1)          15
   component: place
   (1)       64313

   Cmd> letters <- vector("0","1","2","3","4","5","6","7","8","9",\

   Cmd> paste(letters[reverse(O$digits)+1],sep:"")
   (1) "0000FB39"

   Cmd> O <- setodometer(lower:1,upper:16,ndigits:8,place:N); O #lower 1
   component: digits
   (1)          10           4          12          16           1
   (6)           1           1           1
   component: lower
   (1)           1
   component: upper
   (1)          16
   component: place
   (1)       64313

   Cmd> paste(letters[reverse(O$digits)],sep:"") # +1 not needed now
   (1) "0000FB39"

 Macro to find binary bits of integer from most to least significant
   Cmd> bits <- macro("@N <- argvalue($1,\"N\",\"pos int scalar\")
      @ndigits <- ceiling(log(@N+1)/log(2))

   Cmd> bits(N)
    (1)           1           1           1           1           1
    (6)           0           1           1           0           0
   (11)           1           1           1           0           0
   (16)           1

See also paste(), prod(), reverse(), max(), macro(), 'macros',

Gary Oehlert 2003-01-15