triple-int Functions
====================


triple-int General Information
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. manpage:: 7 ggidev-triple-int


Synopsis
--------

::

  #include <ggi/internal/triple-int.h>


Description
-----------

`triple-int` is a collection of math routines that operates on an
array of 3 unsigned integers, treating them as a single integer
with triple precision.

`triple-int` uses a 2-complement representation for negative values.

The most significant part of the `triple-int` is stored at the
highest index in the array representation.

A `triple-int` is typically declared as follows::

  unsigned x[3];

Don't let the above unsigned keyword fool you, all the routines
operate as if the `triple-int` is signed.


See Also
--------
:man:`ggidev-assign_3(3)`, :man:`ggidev-assign_int_3(3)`, :man:`ggidev-assign_unsigned_3(3)`,
:man:`ggidev-sign_3(3)`, :man:`ggidev-bits_3(3)`, :man:`ggidev-eq0_3(3)`, :man:`ggidev-gt0_3(3)`,
:man:`ggidev-ge0_3(3)`, :man:`ggidev-lt0_3(3)`, :man:`ggidev-le0_3(3)`,
:man:`ggidev-eq_3(3)`, :man:`ggidev-ge_3(3)`,
:man:`ggidev-invert_3(3)`, :man:`ggidev-lshift_3(3)`, :man:`ggidev-rshift_3(3)`,
:man:`ggidev-inc_3(3)`, :man:`ggidev-dec_3(3)`, :man:`ggidev-negate_3(3)`, :man:`ggidev-abs_3(3)`,
:man:`ggidev-add_3(3)`, :man:`ggidev-sub_3(3)`, :man:`ggidev-mul_3(3)`, :man:`ggidev-divmod_3(3)`




Initialize a triple-int
~~~~~~~~~~~~~~~~~~~~~~~

.. manpage:: 3 ggidev-assign_3 ggidev-assign_int_3 ggidev-assign_unsigned_3


Synopsis
--------

::

  #include <ggi/internal/triple-int.h>

  unsigned *assign_3(unsigned l[3], unsigned r[3]);

  unsigned *assign_int_3(unsigned l[3], int r);

  unsigned *assign_unsigned_3(unsigned l[3], unsigned r);


Description
-----------

`assign_3` assigns the value of one existing `triple-int` `r` to another
`triple-int` `l`.

`assign_int_3` and `assign_unsigned_3` assigns the argument `r` to
the least significant position of the `triple-int` `l`. `assign_int_3`
extends the sign, while `assign_unsigned_3` does not.


Return value
------------

`assign_3`, `assign_int_3` and `assign_unsigned_3` all return a pointer
to the freshly assigned `triple-int` `x`.
    

Examples
--------

Assign some values to `triple-ints`::

  unsigned x[3], y[3], z[3];

  assign_int_3(x, -42);
  assign_unsigned_3(y, 17);
  assign_3(z, x);


See Also
--------

:man:`ggidev-triple-int(7)`




triple-int properties
~~~~~~~~~~~~~~~~~~~~~

.. manpage:: 3 ggidev-sign_3 ggidev-bits_3 ggidev-eq0_3 ggidev-gt0_3 ggidev-ge0_3 ggidev-lt0_3 ggidev-le0_3


Synopsis
--------

::

  #include <ggi/internal/triple-int.h>

  int sign_3(unsigned x[3]);

  int bits_3(unsigned x[3]);

  int eq0_3(unsigned x[3]);
  int gt0_3(unsigned x[3]);
  int ge0_3(unsigned x[3]);
  int lt0_3(unsigned x[3]);
  int le0_3(unsigned x[3]);


Description
-----------

`sign_3` checks the sign of `x`.

`bits_3` counts the number of significant bits of `x`. I.e.
leading zeros in a positive value and leading ones in a negative value
are not counted.

`eq0_3`, `gt0_3`, `ge0_3`, `lt0_3` and `le0_3` tests the relation
between `x` and zero. `eq0_3` tests if `x` is equal to zero, `gt0_3` if
`x` is greater than zero, `ge0_3` if `x` is greater than or equal to
zero, `lt0_3` if `x` is less than zero and last but not least `le0_3`
tests if `x` is less than or equal to zero.


Return value
------------

`sign_3` returns -1 for negative values, 0 for zero values and 1 for
positive values.

`bits_3` returns 0 for `x` equal to 0 or -1, 1 for `x` equal to 1 and
-2, 2 for `x` equal to 2, 3, -3 and -4 etc.

`eq0_3`, `gt0_3`, `ge0_3`, `lt0_3` and `le0_3` all returns non-zero if
the relation is true, and zero otherwise.


Examples
--------

Some `triple-int` tests::

  unsigned x[3];

  assign_int_3(x, 5);
  ASSERT(sign_3(x) == 1);
  ASSERT(bits_3(x) == 3);
  ASSERT(!eq0_3(x));
  ASSERT(gt0_3(x));
  ASSERT(ge0_3(x));
  ASSERT(!lt0_3(x));
  ASSERT(!le0_3(x));


See Also
--------

:man:`ggidev-triple-int(7)`, :man:`ggidev-assign_int_3(3)`




triple-int comparisons
~~~~~~~~~~~~~~~~~~~~~~

.. manpage:: 3 ggidev-eq_3 ggidev-ge_3


Synopsis
--------

::

  #include <ggi/internal/triple-int.h>

  int eq_3(unsigned l[3], unsigned r[3]);
  int ge_3(unsigned l[3], unsigned r[3]);


Description
-----------

`eq_3` tests if `l` and `r` are equal. Equivalent to l==r.

`ge_3` tests if `l` is greater than or equal to `l`. Equivalent to l>=r.


Return value
------------

`eq_3` and `ge_3` returns non-zero if the relation is true,
and zero otherwise.


Examples
--------

Some `triple-int` comparisons::

  unsigned x[3], y[3], z[3];

  assign_int_3(x, 5);
  assign_int_3(y, 6);
  assign_int_3(z, 6);
  ASSERT(!eq_3(x, y));
  ASSERT(eq_3(y, z));
  ASSERT(ge_3(x, y));
  ASSERT(ge_3(y, z));
  ASSERT(!ge_3(y, x));


See Also
--------

:man:`ggidev-triple-int(7)`, :man:`ggidev-assign_int_3(3)`




Bitwise triple-int operations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. manpage:: 3 ggidev-invert_3 ggidev-lshift_3 ggidev-rshift_3


Synopsis
--------

::

  #include <ggi/internal/triple-int.h>

  unsigned *invert_3(unsigned x[3]);

  unsigned *lshift_3(unsigned l[3], unsigned r);
  unsigned *rshift_3(unsigned l[3], unsigned r);


Description
-----------

`invert_3` inverts all bits of `x`. Equivalent to x=~x.

`lshift_3` shifts `l` to the left by `r` bits. Equivalent to l<<=r.

`rshift_3` shifts `l` to the right by `r` bits. This shift is
arithmetic, so the sign of `l` is kept as is. Equivalent to l>>=r.


Return value
------------

`invert_3` returns a pointer to `x` which has been updated in place.

Both `lshift_3` and `rshift_3` return a pointer to `l` which has
been updated in place.


Examples
--------

Some bitwise operations on `triple-ints`::

  unsigned x[3];

  assign_int_3(x, -4);
  invert_3(x);     /* x is now 3 */
  lshift_3(x, 42); /* x is now 3*2^42, if that fits in a triple-int */
  rshift_3(x, 17); /* x is now 3*2^25 */


See Also
--------

:man:`ggidev-triple-int(7)`, :man:`ggidev-assign_int_3(3)`




Unary arithmetic triple-int operations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. manpage:: 3 ggidev-inc_3 ggidev-dec_3 ggidev-negate_3 ggidev-abs_3


Synopsis
--------

::

  #include <ggi/internal/triple-int.h>

  unsigned *inc_3(unsigned x[3]);
  unsigned *dec_3(unsigned x[3]);

  unsigned *negate_3(unsigned x[3]);
  unsigned *abs_3(unsigned x[3]);


Description
-----------

`inc_3` increments `x` by one. Equivalent to ++x.

`dec_3` decrements `x` by one. Equivalent to --x.

`negate_3` negates `x`. Equivalent to x=-x.

`abs_3` takes the absolute value of `x`. Equivalent to x=x<0?-x:x.


Return value
------------

`inc_3`, `dec_3`, `negate_3` and `abs_3` all return a pointer
to `x` which has been updated in place.


Examples
--------

Some unary arithmetic operations on `triple-ints`::

  unsigned x[3];

  assign_int_3(x, 44);
  negate_3(x);  /* x is now -44 */
  inc_3(x);     /* x is now -43 */
  abs_3(x);     /* x is now 43 */
  dec_3(x);     /* x is now 42 */


See Also
--------

:man:`ggidev-triple-int(7)`, :man:`ggidev-assign_int_3(3)`




Binary arithmetic triple-int operations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. manpage:: 3 ggidev-add_3 ggidev-sub_3 ggidev-mul_3 ggidev-divmod_3


Synopsis
--------

::

  #include <ggi/internal/triple-int.h>

  unsigned *add_3(unsigned l[3], unsigned r[3]);
  unsigned *sub_3(unsigned l[3], unsigned r[3]);

  unsigned *mul_3(unsigned l[3], unsigned r[3]);
  unsigned *divmod_3(unsigned a[3], unsigned b[3],
  	unsigned q[3], unsigned r[3]);


Description
-----------

`add_3` adds `r` to `l`. Equivalent to l+=r.

`sub_3` subtracts `r` from `l`. Equivalent to l-=r.

`mul_3` multiplies `r` with `l`. Equivalent to l*=r.

`divmod_3` calculates the quotient `q` and the remainder `r` of `a`/`b`
such that `a` = `q` * `b` + `r`. Equivalent to r=a%b,q=a/b.

Multiplication and division needs to operate on `limbs` to perform long
multiplication and division. If a type with twice the precision of an
`unsigned` is found (typically the `long long` type), `unsigned` is used
as the `limb`. If not, half the bits of an `unsigned` are used as the
`limb`.

The division algorithm is probably similar to the algorithm described
by Donald E. Knuth in "The Art of Computer Programming", volume 2, but
the author of the code has not actually read that book, only a short
description of the algorithm. The degree of similarity is therefore
uncertain.


Return value
------------

`add_3`, `sub_3` and `mul_3` all return a pointer to `l` which has
been updated in place.

'divmod_3` returns a pointer to the quotient `q`.


Examples
--------

Some binary arithmetic operations on `triple-ints`::

  unsigned x[3], y[3], q[3], r[3];

  assign_int_3(x, 4);
  assign_int_3(y, 5);
  add_3(x, y);          /* x == 9 */
  assign_int_3(q, 3);
  sub_3(x, q);          /* x == 6 */
  mul_3(x, q);          /* x == 18 */
  divmod_3(x, y, q, r); /* q == 3, r == 3 */


See Also
--------

:man:`triple-int(7)`, :man:`assign_int_3(3)`
