Team-Fly
Previous Section Next Section

7.2 All or Nothing: Bitwise Relations

The FLINT/C package contains functions that allow the built-in bitwise C operators &, |, and ^ to be used for the type CLINT as well. However, before we program these functions we would like to understand what their implementation will net us.

From a mathematical viewpoint we are looking at relations of the generalized Boolean functions f : { 0, 1 }k { 0, 1 } that map a k-tuple (x1,..., xk) Î { 0, 1 }k to the value 0 or 1. The effect of a Boolean function is usually presented in the form of a table of values such as that shown in Table 7.1.

Table 7.1: Values of a Boolean function

x1

x2

...

xk

f (x1, ..., xk)

0

0

...

0

0

1

0

...

0

1

0

1

...

0

0

1

1

...

1

1

For the bitwise relations between CLINT types we first regard the variables as bit vectors (x1, ..., xn), and furthermore, the function values of the Boolean functions will be formed into a sequence. Thus we have functions

that map n-bit variables := () and := () by

Click To expand

with fi () := f (), again to an n-bit variable (x1, ..., xn), which is then interpreted as a number of type CLINT.

Decisive for the operation of the function is the definition of the partial functions fi, each of which is defined in terms of a Boolean function f. For the CLINT functions and_l(), or_l(), and xor_l() the Boolean functions that are implemented are defined as in Tables 7.27.4.

Table 7.2: Values of the CLINT function and_l()

x1

x2

f (x1, x2)

0

0

0

0

1

0

1

0

0

1

1

1

Table 7.3: Values of the CLINT function or_l()

x1

x2

f (x1, x2)

0

0

0

0

1

1

1

0

1

1

1

1

Table 7.4: Values of the CLINT function xor_l()

x1

x2

f (x1, x2)

0

0

0

0

1

1

1

0

1

1

1

0

The implementations of these Boolean functions in the three C functions and_l(), or_l(), and xor_l() do not actually proceed bitwise, but process the digits of CLINT variables by means of the standard C operators &, |, and ^. Each of these functions accepts three arguments of CLINT type, where the first two are the operands and the last the result variable.

void
and_l (CLINT a_l, CLINT b_l, CLINT c_l)
{
  CLINT d_l;
  clint *r_l, *s_l, *t_l;
  clint *lastptr_l;
  if (DIGITS_L (a_l) < DIGITS_L (b_l))
    {
      r_l = LSDPTR_L (b_l);
      s_l = LSDPTR_L (a_l);
      lastptr_l = MSDPTR_L (a_l);
    }
  else 
    {
      r_l = LSDPTR_L (a_l);
      s_l = LSDPTR_L (b_l);
      lastptr_l = MSDPTR_L (b_l);
    }
  t_l = LSDPTR_L (d_l);
  SETDIGITS_L (d_l, DIGITS_L (s_l - 1));
  while (s_l <= lastptr_l)
    {
      *t_l++ = *r_l++ & *s_l++;
    }
  cpy_l (c_l, d_l);
}
void
or_l (CLINT a_l, CLINT b_l, CLINT c_l)
{
  CLINT d_l;
  clint *r_l, *s_l, *t_l;
  clint *msdptrr_l;
  clint *msdptrs_l;
  if (DIGITS_L (a_l) < DIGITS_L (b_l))
    {
      r_l = LSDPTR_L (b_l);
      s_l = LSDPTR_L (a_l);
      msdptrr_l = MSDPTR_L (b_l);
      msdptrs_l = MSDPTR_L (a_l);
    }
  else
    {
      r_l = LSDPTR_L (a_l);
      s_l = LSDPTR_L (b_l);
      msdptrr_l = MSDPTR_L (a_l);
      msdptrs_l = MSDPTR_L (b_l);
    }

  t_l = LSDPTR_L (d_l);
  SETDIGITS_L (d_l, DIGITS_L (r_l - 1));
  while (s_l <= msdptrs_l)
    {
      *t_l++ = *r_l++ | *s_l++;
    }
  while (r_l <= msdptrr_l)
    {
      *t_l++ = *r_l++;
    }
  cpy_l (c_l, d_l);
}
void
xor_l (CLINT a_l, CLINT b_l, CLINT c_l)
{
  CLINT d_l;
  clint *r_l, *s_l, *t_l;
  clint *msdptrr_l;
  clint *msdptrs_l;

  if (DIGITS_L (a_l) < DIGITS_L (b_l))
    {
      r_l = LSDPTR_L (b_l);
      s_l = LSDPTR_L (a_l);
      msdptrr_l = MSDPTR_L (b_l);
      msdptrs_l = MSDPTR_L (a_l);
    }
  else
    {
      r_l = LSDPTR_L (a_l);
      s_l = LSDPTR_L (b_l);
      msdptrr_l = MSDPTR_L (a_l);
      msdptrs_l = MSDPTR_L (b_l);
    }

  t_l = LSDPTR_L (d_l);
  SETDIGITS_L (d_l, DIGITS_L (r_l - 1));
  while (s_l <= msdptrs_l)
    {
      *t_l++ = *r_l++ ^ *s_l++;
    }
  while (r_l <= msdptrr_l)
    {
      *t_l++ = *r_l++;
    }
  cpy_l (c_l, d_l);
}

The function and_l() can be used to reduce a number a modulo a power of two 2k by setting a CLINT variable a_l to the value a, a CLINT variable b_l to the value 2k 1, and executing and_l(a_l, b_l, c_l). However, this operation executes faster with the function mod2_l() created for this purpose, which takes into account that the binary representation of 2k 1 consists exclusively of ones (see Section 4.3).


Team-Fly Previous Section Next Section