/***********************************************************************
     "int.o": manual implementation of sort Int
***********************************************************************/

/***********************************
  (C) Copyright 1994; dit/upm
   Distributed under the conditions stated in the
   TOPO General Public License (see file LICENSE)
 ***********************************/

/* LINTLIBRARY */

#define int_IMP

#include <stdio.h>
#include <assert.h>
#include <kaos.hh>
#include "int.hh"

PUBLIC int
INTequal (p1, p2)
  udatum p1, p2;
{
  return p1->ino == p2->ino;
}

PUBLIC char *
INTdraw(p)
  udatum p;
{
  static char r[20];

  (void) sprintf(r, "%d", p->ino);
  return r;
}

PUBLIC int
INTparse(ptr, r)
  char **ptr;
  udatum *r;
{
  int d, l;

  if (sscanf(*ptr, "%d%n", &d, &l) == 1)
  { *ptr+= l;
    (*r)= ud_alloc();
    (*r)->ino= d;
    return TRUE;
  }
  else
    return FALSE;
}

PUBLIC udatum
INTdatum (v)
  int v;
{
  static udatum _buf[101]= { NULL };
  static udatum *buf= _buf + (sizeof(buf) / sizeof(buf[0]) - 1) / 2;
  static int min= -(sizeof(buf) / sizeof(buf[0]) - 1) / 2;
  static int max=  (sizeof(buf) / sizeof(buf[0]) - 1) / 2;

  if (v < min || v > max)
  { udatum p;

    p= ud_alloc();
    p->ino= v;
    return p;
  }
  if (buf[v] == NULL)
  { buf[v]= ud_alloc();
    buf[v]->ino= v;
    (void) ud_const(Int, buf[v]);
  }
  return buf[v];
}

PUBLIC int
INTvalue (p)
  udatum p;
{
  int v;

  v= p->ino;
  ud_free(Int, p);
  return v;
}

PUBLIC udatum
INTpower (p1, p2)
  udatum p1, p2;
{
  int v1, v2;
  int r;
  int i;

  v1= INTvalue(p1);
  v2= INTvalue(p2);
  assert(v2 >= 0);
  r= 1;
  for (i= 0; i < v2; ++i)
    r*= v1;
  return INTdatum(r);
}

PUBLIC udatum
INTdivision (p1, p2)
  udatum p1, p2;
{
  int v1, v2;
  int r;

  v1= INTvalue(p1);
  v2= INTvalue(p2);
  assert(v2 != 0);
  r= abs(v1) / abs(v2);
  if ((v1 > 0) != (v2 > 0))
    r= -r;
  return INTdatum(r);
}

PUBLIC udatum
INTmodulus (p1, p2)
  udatum p1, p2;
{
  int v1, v2;
  int r;

  v1= INTvalue(p1);
  v2= INTvalue(p2);
  assert(v2 != 0);
  r= abs(v1) % abs(v2);
  if (v1 < 0)
    r= -r;
  return INTdatum(r);
}

PUBLIC udatum
INTorder (p)
  udatum p;
{
  int v;
  int r;

  v= INTvalue(p);
  if (v < 0)
    v= -v;
  for (r= 0; (v/= 10) != 0; ++r)
    ;
  return INTdatum(r);
}

PUBLIC udatum
INTfactorial (p)
  udatum p;
{
  int v;
  int r;

  v= INTvalue(p);
  assert(v >= 0);
  if (v < 0)
    v= -v;
  r= 1;
  for (; v > 0; --v)
    r*= v;
  return INTdatum(r);
}
