//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995 by the LiDIA Group
//
// File        : newton_root.c 
// Author      : Thomas Papanikolaou (TP)
// Last change : TP, Feb 7 1995, initial version
//               VM, Jan 6 1997, added break statements
//

#include <LiDIA/bigint.h>

void
newton_root(bigint & b, const bigint & a, int n)
{
  bigint c, d;

  if (n < 0)
    lidia_error_handler("bigint", "newton_root::negative n.");
  switch (n)
  {
  case 0:
    b.assign_one();
    break;
  case 1:
    b.assign(a);
    break;
  case 2:
    sqrt(b, a);
    break;
  default:
    b.assign_one();
    shift_left(b, b, (unsigned int)((a.bit_length() + n - 1) / n));
    do
    {
      power(c, b, n - 1);
      div_rem(c, d, a, c);
      subtract(c, b, c);
      divide(c, c, n);
      subtract(b, b, c);
    } while (c.sign() > 0);
    power(c, b, n);
    if (c.compare(a) > 0)
      dec(b);
    break;
  }
}
