Blame mini-gmp/tests/t-div.c

Packit 5c3484
/*
Packit 5c3484
Packit 5c3484
Copyright 2012, 2013 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library test suite.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is free software; you can redistribute it
Packit 5c3484
and/or modify it under the terms of the GNU General Public License as
Packit 5c3484
published by the Free Software Foundation; either version 3 of the License,
Packit 5c3484
or (at your option) any later version.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is distributed in the hope that it will be
Packit 5c3484
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5c3484
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Packit 5c3484
Public License for more details.
Packit 5c3484
Packit 5c3484
You should have received a copy of the GNU General Public License along with
Packit 5c3484
the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
#include <assert.h>
Packit 5c3484
#include <stdlib.h>
Packit 5c3484
#include <stdio.h>
Packit 5c3484
Packit 5c3484
#include "testutils.h"
Packit 5c3484
Packit 5c3484
#define MAXBITS 400
Packit 5c3484
#define COUNT 10000
Packit 5c3484
Packit 5c3484
typedef void div_qr_func (mpz_t, mpz_t, const mpz_t, const mpz_t);
Packit 5c3484
typedef unsigned long div_qr_ui_func (mpz_t, mpz_t, const mpz_t, unsigned long);
Packit 5c3484
typedef void div_func (mpz_t, const mpz_t, const mpz_t);
Packit 5c3484
typedef unsigned long div_x_ui_func (mpz_t, const mpz_t, unsigned long);
Packit 5c3484
typedef unsigned long div_ui_func (const mpz_t, unsigned long);
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
testmain (int argc, char **argv)
Packit 5c3484
{
Packit 5c3484
  unsigned i;
Packit 5c3484
  mpz_t a, b, q, r, rq, rr;
Packit 5c3484
  int div_p;
Packit 5c3484
Packit 5c3484
  mpz_init (a);
Packit 5c3484
  mpz_init (b);
Packit 5c3484
  mpz_init (r);
Packit 5c3484
  mpz_init (q);
Packit 5c3484
  mpz_init (rr);
Packit 5c3484
  mpz_init (rq);
Packit 5c3484
Packit 5c3484
  for (i = 0; i < COUNT; i++)
Packit 5c3484
    {
Packit 5c3484
      unsigned j;
Packit 5c3484
      for (j = 0; j < 3; j++)
Packit 5c3484
	{
Packit 5c3484
	  static const enum hex_random_op ops[3] = { OP_CDIV, OP_FDIV, OP_TDIV };
Packit 5c3484
	  static const char name[3] = { 'c', 'f', 't'};
Packit 5c3484
	  static div_qr_func * const div_qr [3] =
Packit 5c3484
	    {
Packit 5c3484
	      mpz_cdiv_qr, mpz_fdiv_qr, mpz_tdiv_qr
Packit 5c3484
	    };
Packit 5c3484
	  static div_qr_ui_func  *div_qr_ui[3] =
Packit 5c3484
	    {
Packit 5c3484
	      mpz_cdiv_qr_ui, mpz_fdiv_qr_ui, mpz_tdiv_qr_ui
Packit 5c3484
	    };
Packit 5c3484
	  static div_func * const div_q [3] =
Packit 5c3484
	    {
Packit 5c3484
	      mpz_cdiv_q, mpz_fdiv_q, mpz_tdiv_q
Packit 5c3484
	    };
Packit 5c3484
	  static div_x_ui_func  *div_q_ui[3] =
Packit 5c3484
	    {
Packit 5c3484
	      mpz_cdiv_q_ui, mpz_fdiv_q_ui, mpz_tdiv_q_ui
Packit 5c3484
	    };
Packit 5c3484
	  static div_func * const div_r [3] =
Packit 5c3484
	    {
Packit 5c3484
	      mpz_cdiv_r, mpz_fdiv_r, mpz_tdiv_r
Packit 5c3484
	    };
Packit 5c3484
	  static div_x_ui_func  *div_r_ui[3] =
Packit 5c3484
	    {
Packit 5c3484
	      mpz_cdiv_r_ui, mpz_fdiv_r_ui, mpz_tdiv_r_ui
Packit 5c3484
	    };
Packit 5c3484
	  static div_ui_func  *div_ui[3] =
Packit 5c3484
	    {
Packit 5c3484
	      mpz_cdiv_ui, mpz_fdiv_ui, mpz_tdiv_ui
Packit 5c3484
	    };
Packit 5c3484
Packit 5c3484
	  mini_random_op4 (ops[j], MAXBITS, a, b, rq, rr);
Packit 5c3484
	  div_qr[j] (q, r, a, b);
Packit 5c3484
	  if (mpz_cmp (r, rr) || mpz_cmp (q, rq))
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_%cdiv_qr failed:\n", name[j]);
Packit 5c3484
	      dump ("a", a);
Packit 5c3484
	      dump ("b", b);
Packit 5c3484
	      dump ("r   ", r);
Packit 5c3484
	      dump ("rref", rr);
Packit 5c3484
	      dump ("q   ", q);
Packit 5c3484
	      dump ("qref", rq);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
	  mpz_set_si (q, -5);
Packit 5c3484
	  div_q[j] (q, a, b);
Packit 5c3484
	  if (mpz_cmp (q, rq))
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_%cdiv_q failed:\n", name[j]);
Packit 5c3484
	      dump ("a", a);
Packit 5c3484
	      dump ("b", b);
Packit 5c3484
	      dump ("q   ", q);
Packit 5c3484
	      dump ("qref", rq);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
	  mpz_set_ui (r, ~5);
Packit 5c3484
	  div_r[j] (r, a, b);
Packit 5c3484
	  if (mpz_cmp (r, rr))
Packit 5c3484
	    {
Packit 5c3484
	      fprintf (stderr, "mpz_%cdiv_r failed:\n", name[j]);
Packit 5c3484
	      dump ("a", a);
Packit 5c3484
	      dump ("b", b);
Packit 5c3484
	      dump ("r   ", r);
Packit 5c3484
	      dump ("rref", rr);
Packit 5c3484
	      abort ();
Packit 5c3484
	    }
Packit 5c3484
Packit 5c3484
	  if (j == 0)		/* do this once, not for all roundings */
Packit 5c3484
	    {
Packit 5c3484
	      div_p = mpz_divisible_p (a, b);
Packit 5c3484
	      if ((mpz_sgn (r) == 0) ^ (div_p != 0))
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpz_divisible_p failed:\n");
Packit 5c3484
		  dump ("a", a);
Packit 5c3484
		  dump ("b", b);
Packit 5c3484
		  dump ("r   ", r);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
	    }
Packit 5c3484
Packit 5c3484
	  if (j == 0 && mpz_sgn (b) < 0)  /* ceil, negative divisor */
Packit 5c3484
	    {
Packit 5c3484
	      mpz_mod (r, a, b);
Packit 5c3484
	      if (mpz_cmp (r, rr))
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpz_mod failed:\n");
Packit 5c3484
		  dump ("a", a);
Packit 5c3484
		  dump ("b", b);
Packit 5c3484
		  dump ("r   ", r);
Packit 5c3484
		  dump ("rref", rr);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
	    }
Packit 5c3484
Packit 5c3484
	  if (j == 1 && mpz_sgn (b) > 0) /* floor, positive divisor */
Packit 5c3484
	    {
Packit 5c3484
	      mpz_mod (r, a, b);
Packit 5c3484
	      if (mpz_cmp (r, rr))
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpz_mod failed:\n");
Packit 5c3484
		  dump ("a", a);
Packit 5c3484
		  dump ("b", b);
Packit 5c3484
		  dump ("r   ", r);
Packit 5c3484
		  dump ("rref", rr);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
	    }
Packit 5c3484
Packit 5c3484
	  if (mpz_fits_ulong_p (b))
Packit 5c3484
	    {
Packit 5c3484
	      mp_limb_t rl;
Packit 5c3484
Packit 5c3484
	      rl = div_qr_ui[j] (q, r, a, mpz_get_ui (b));
Packit 5c3484
	      if (rl != mpz_get_ui (rr)
Packit 5c3484
		  || mpz_cmp (r, rr) || mpz_cmp (q, rq))
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpz_%cdiv_qr_ui failed:\n", name[j]);
Packit 5c3484
		  dump ("a", a);
Packit 5c3484
		  dump ("b", b);
Packit 5c3484
		  fprintf(stderr, "rl   = %lx\n", rl);
Packit 5c3484
		  dump ("r   ", r);
Packit 5c3484
		  dump ("rref", rr);
Packit 5c3484
		  dump ("q   ", q);
Packit 5c3484
		  dump ("qref", rq);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
Packit 5c3484
	      mpz_set_si (q, 3);
Packit 5c3484
	      rl = div_q_ui[j] (q, a, mpz_get_ui (b));
Packit 5c3484
	      if (rl != mpz_get_ui (rr) || mpz_cmp (q, rq))
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpz_%cdiv_q_ui failed:\n", name[j]);
Packit 5c3484
		  dump ("a", a);
Packit 5c3484
		  dump ("b", b);
Packit 5c3484
		  fprintf(stderr, "rl   = %lx\n", rl);
Packit 5c3484
		  dump ("rref", rr);
Packit 5c3484
		  dump ("q   ", q);
Packit 5c3484
		  dump ("qref", rq);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
Packit 5c3484
	      mpz_set_ui (r, 7);
Packit 5c3484
	      rl = div_r_ui[j] (r, a, mpz_get_ui (b));
Packit 5c3484
	      if (rl != mpz_get_ui (rr) || mpz_cmp (r, rr))
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpz_%cdiv_qr_ui failed:\n", name[j]);
Packit 5c3484
		  dump ("a", a);
Packit 5c3484
		  dump ("b", b);
Packit 5c3484
		  fprintf(stderr, "rl   = %lx\n", rl);
Packit 5c3484
		  dump ("r   ", r);
Packit 5c3484
		  dump ("rref", rr);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
Packit 5c3484
	      rl = div_ui[j] (a, mpz_get_ui (b));
Packit 5c3484
	      if (rl != mpz_get_ui (rr))
Packit 5c3484
		{
Packit 5c3484
		  fprintf (stderr, "mpz_%cdiv_qr_ui failed:\n", name[j]);
Packit 5c3484
		  dump ("a", a);
Packit 5c3484
		  dump ("b", b);
Packit 5c3484
		  fprintf(stderr, "rl   = %lx\n", rl);
Packit 5c3484
		  dump ("rref", rr);
Packit 5c3484
		  abort ();
Packit 5c3484
		}
Packit 5c3484
Packit 5c3484
	      if (j == 0)	/* do this once, not for all roundings */
Packit 5c3484
		{
Packit 5c3484
		  div_p = mpz_divisible_ui_p (a, mpz_get_ui (b));
Packit 5c3484
		  if ((mpz_sgn (r) == 0) ^ (div_p != 0))
Packit 5c3484
		    {
Packit 5c3484
		      fprintf (stderr, "mpz_divisible_ui_p failed:\n");
Packit 5c3484
		      dump ("a", a);
Packit 5c3484
		      dump ("b", b);
Packit 5c3484
		      dump ("r   ", r);
Packit 5c3484
		      abort ();
Packit 5c3484
		    }
Packit 5c3484
		}
Packit 5c3484
Packit 5c3484
	      if (j == 1)	/* floor */
Packit 5c3484
		{
Packit 5c3484
		  mpz_mod_ui (r, a, mpz_get_ui (b));
Packit 5c3484
		  if (mpz_cmp (r, rr))
Packit 5c3484
		    {
Packit 5c3484
		      fprintf (stderr, "mpz_mod failed:\n");
Packit 5c3484
		      dump ("a", a);
Packit 5c3484
		      dump ("b", b);
Packit 5c3484
		      dump ("r   ", r);
Packit 5c3484
		      dump ("rref", rr);
Packit 5c3484
		      abort ();
Packit 5c3484
		    }
Packit 5c3484
		}
Packit 5c3484
	    }
Packit 5c3484
	}
Packit 5c3484
    }
Packit 5c3484
  mpz_clear (a);
Packit 5c3484
  mpz_clear (b);
Packit 5c3484
  mpz_clear (r);
Packit 5c3484
  mpz_clear (q);
Packit 5c3484
  mpz_clear (rr);
Packit 5c3484
  mpz_clear (rq);
Packit 5c3484
}