// ---------------------------------------------------------------------------
// - t_relatif.cpp                                                           -
// - standard object library - relatif class tester module                   -
// ---------------------------------------------------------------------------
// - This program is free software;  you can redistribute it  and/or  modify -
// - it provided that this copyright notice is kept intact.                  -
// -                                                                         -
// - This program  is  distributed in  the hope  that it will be useful, but -
// - without  any  warranty;  without  even   the   implied    warranty   of -
// - merchantability or fitness for a particular purpose.  In no event shall -
// - the copyright holder be liable for any  direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software.     -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2008 amaury darsch                                   -
// ---------------------------------------------------------------------------

#include "Relatif.hpp"
#include "Exception.hpp"

int main (int, char**) {
  using namespace afnix;

  // create a default relatif
  Relatif x =   0;
  Relatif y =   1;
  Relatif z =  -1;
  Relatif a = 65536;
  Relatif b =  1024;
  Relatif c =   256;
  Relatif d =   128;

  // check for relatif to string conversion
  if (x.tostring () !=     "0") return 1;
  if (y.tostring () !=     "1") return 1;
  if (z.tostring () !=    "-1") return 1;
  if (a.tostring () != "65536") return 1;
  if (b.tostring () !=  "1024") return 1;
  if (c.tostring () !=   "256") return 1;

  // check for string to relatif conversion
  if ((Relatif ("0"))      !=    0) return 1;
  if ((Relatif ("1"))      !=    1) return 1;
  if ((Relatif ("-1"))     !=   -1) return 1;
  if ((Relatif ("2000"))   != 2000) return 1;
  if ((Relatif ("256"))    !=  256) return 1;
  if ((Relatif ("0xff"))   !=  255) return 1;
  if ((Relatif ("0b1111")) !=   15) return 1;

  // check for native integer conversion
  if (x.tointeger () !=     0) return 1;
  if (y.tointeger () !=     1) return 1;
  if (z.tointeger () !=    -1) return 1;
  if (a.tointeger () != 65536) return 1;
  if (b.tointeger () !=  1024) return 1;
  if (c.tointeger () !=   256) return 1;

  // check for operators
  if (x >  y) return 1;
  if (x >= y) return 1;
  if (x <  z) return 1;
  if (x <= z) return 1;
  if (c <  d) return 1;
  if (c <= d) return 1;
  if (d >  c) return 1;
  if (d >= c) return 1;

  // simple checks
  if (x != 0)            return 1;
  if (y != 1)            return 1;

  // simple add checks
  if ((x + y)     != 1)  return 1;
  if ((y + z)     != 0)  return 1;
  if ((x + z)     != -1) return 1;
  if ((x + y + z) != 0)  return 1;

  // simple sub checks
  if ((x - y)     != -1) return 1;
  if ((y - z)     != 2)  return 1;
  if ((x - z)     != 1)  return 1;
  if ((x - y - z) != 0)  return 1;

  // simple mul checks
  if ((x * y)     != 0)  return 1;
  if ((y * z)     != -1) return 1;
  if ((x * z)     != 0)  return 1;
  if ((x * y * z) != 0)  return 1;

  // simple div checks
  if ((x / y)     != 0)   return 1;
  if ((y / z)     != -1)  return 1;
  if ((a / a)     != 1)   return 1;
  if ((a / b)     != 64)  return 1;
  if ((a / c)     != 256) return 1;

  // simple modulo checks
  if ((x % y)     != 0)   return 1;
  if ((y % z)     != 0)   return 1;
  if ((a % a)     != 0)   return 1;
  if ((a % b)     != 0)   return 1;
  if ((a % c)     != 0)   return 1;

  // simple shift left checks
  if (x.shl (8)   != 0)    return 1;
  if (y.shl (1)   != 2)    return 1;
  if (y.shl (8)   != 256)  return 1;
  if (y.shl (9)   != 512)  return 1;
  if (y.shl (10)  != 1024) return 1;

  // simple shift right checks
  if (x.shr (8)   != 0)    return 1;
  if (y.shr (1)   != 0)    return 1;
  if (b.shr (8)   != 4)    return 1;
  if (c.shr (1)   != 128)  return 1;
  if (c.shr (2)   !=  64)  return 1;

  // simple mehod check
  if (x.isodd  () == true)  return 1;
  if (x.iseven () == false) return 1;
  if (y.isodd  () == false) return 1;
  if (y.iseven () == true)  return 1;

  // random checks
  long    lx = 1234;
  long    ly = 5678;
  Relatif rx = lx;
  Relatif ry = ly;
  if ((rx + ry) != (lx + ly)) return 1;
  if ((rx - ry) != (lx - ly)) return 1;
  if ((ry - rx) != (ly - lx)) return 1;
  if ((rx * ry) != (lx * ly)) return 1;
  if ((rx / ry) != (lx / ly)) return 1;
  if ((ry / rx) != (ly / lx)) return 1;
  if ((rx % ry) != (lx % ly)) return 1;
  if ((ry % rx) != (ly % lx)) return 1;

  // large add checks
  Relatif ra;
  Relatif rb;
  for (long i = 0; i < 256; i++) {
    long j = 65336 + i;
    ra = i;
    rb = j;
    if ((ra + rb) != (i + j)) return 1;
  }

  // large sub checks
  for (long i = 0; i < 256; i++) {
    long j = 65336 + i;
    ra = i;
    rb = j;
    if ((ra - rb) != (i - j)) return 1;
    if ((rb - ra) != (j - i)) return 1;
  }

  // large mul checks
  for (long i = 0; i < 256; i++) {
    long j = 65336 + i;
    ra = i;
    rb = j;
    if ((ra * rb) != (i * j)) return 1;
  }

  // large div checks
  for (long i = 1; i <= 256; i++) {
    long j = 1048576 + i;
    ra = j;
    rb = i;
    if ((ra / rb) != (j / i)) return 1;
  }

  // large modulo checks
  for (long i = 1; i <= 256; i++) {
    long j = 1048576 + i;
    ra = j;
    rb = i;
    if ((ra % rb) != (j % i)) return 1;
  }

  // everything is fine
  return 0;
}
