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

Packit 5c3484
/* Exercise some mpz_..._si functions.
Packit 5c3484
Packit 5c3484
Copyright 2013, 2016 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 <limits.h>
Packit 5c3484
#include <stdio.h>
Packit 5c3484
#include <stdlib.h>
Packit 5c3484
Packit 5c3484
#include "testutils.h"
Packit 5c3484
Packit 5c3484
/* Always called with sz fitting in a signed long, and si is the
Packit 5c3484
   corresponding value. */ 
Packit 5c3484
int
Packit 5c3484
check_si (const mpz_t sz, long si)
Packit 5c3484
{
Packit 5c3484
  mpz_t t;
Packit 5c3484
Packit 5c3484
  /* Checks on sz/si */
Packit 5c3484
  if ((mpz_cmp_si (sz, si)) != 0)
Packit 5c3484
    {
Packit 5c3484
      printf ("mpz_cmp_si (sz, %ld) != 0.\n", si);
Packit 5c3484
      return 0;
Packit 5c3484
    }
Packit 5c3484
  if (mpz_get_si (sz) != si)
Packit 5c3484
    {
Packit 5c3484
      printf ("mpz_get_si (sz) != %ld.\n", si);
Packit 5c3484
      return 0;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpz_init_set_si (t, si);
Packit 5c3484
Packit 5c3484
  if (mpz_cmp (t, sz) != 0)
Packit 5c3484
    {
Packit 5c3484
      printf ("mpz_init_set_si (%ld) failed.\n", si);
Packit 5c3484
      printf (" got="); mpz_out_str (stdout, 10, t); printf ("\n");
Packit 5c3484
      return 0;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpz_clear (t);
Packit 5c3484
  return 1;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
/* Called with mpz_cmp (sz, oz) == c. If sz fits in a signed long,
Packit 5c3484
   si is the coresponding value, and similarly for oz and oi. */ 
Packit 5c3484
void
Packit 5c3484
check_si_cmp (const mpz_t sz, const mpz_t oz, long si, long oi, int c)
Packit 5c3484
{
Packit 5c3484
  if (mpz_cmp (sz, oz) != c)
Packit 5c3484
    {
Packit 5c3484
      printf ("mpz_cmp (sz, oz) != %i.\n", c);
Packit 5c3484
      goto fail;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  if (mpz_fits_slong_p (sz))
Packit 5c3484
    {
Packit 5c3484
      if (!check_si (sz, si))
Packit 5c3484
	goto fail;
Packit 5c3484
      if (mpz_cmp_si (oz, si) != -c)
Packit 5c3484
	{
Packit 5c3484
	  printf ("mpz_cmp_si (oz, %ld) != %i.\n", si, -c);
Packit 5c3484
	  goto fail;
Packit 5c3484
	}
Packit 5c3484
    }
Packit 5c3484
  else
Packit 5c3484
    {
Packit 5c3484
      if (mpz_cmp_si (sz, si) != c)
Packit 5c3484
	{
Packit 5c3484
	  printf ("mpz_cmp_si (sz, %ld) != %i.\n", si, c);
Packit 5c3484
	  goto fail;
Packit 5c3484
	}
Packit 5c3484
      if (mpz_cmp_si (sz, -c) != c)
Packit 5c3484
	{
Packit 5c3484
	  printf ("mpz_cmp_si (sz, %i) != %i.\n", -c, c);
Packit 5c3484
	  goto fail;
Packit 5c3484
	}
Packit 5c3484
    }
Packit 5c3484
  if (mpz_fits_slong_p (oz)) 
Packit 5c3484
    {
Packit 5c3484
      if (!check_si (oz, oi))
Packit 5c3484
	goto fail;
Packit 5c3484
      if (mpz_cmp_si (sz, oi) != c)
Packit 5c3484
	{
Packit 5c3484
	  printf ("mpz_cmp_si (sz, %ld) != %i.\n", oi, c);
Packit 5c3484
	  goto fail;
Packit 5c3484
	}
Packit 5c3484
    }
Packit 5c3484
  return;
Packit 5c3484
Packit 5c3484
 fail:
Packit 5c3484
  printf (" sz="); mpz_out_str (stdout, 10, sz); printf ("\n");
Packit 5c3484
  printf (" si=%ld\n", si);
Packit 5c3484
  printf (" oz="); mpz_out_str (stdout, 10, oz); printf ("\n");
Packit 5c3484
  printf (" oi=%ld\n", si);
Packit 5c3484
  abort ();
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
try_op_si (int c)
Packit 5c3484
{
Packit 5c3484
  long  si, oi;
Packit 5c3484
  mpz_t sz, oz;
Packit 5c3484
  unsigned overflow_count;
Packit 5c3484
Packit 5c3484
  si = c;
Packit 5c3484
  mpz_init_set_si (sz, si);
Packit 5c3484
Packit 5c3484
  oi = si;
Packit 5c3484
  mpz_init_set (oz, sz);
Packit 5c3484
Packit 5c3484
  /* To get a few tests with operands straddling the border, don't
Packit 5c3484
     stop at the very first operand exceeding a signed long. */
Packit 5c3484
  for (overflow_count = 0; overflow_count < 10; )
Packit 5c3484
    {
Packit 5c3484
      /* c * 2^k */
Packit 5c3484
      mpz_mul_2exp (sz, sz, 1);
Packit 5c3484
      if (mpz_fits_slong_p (sz))
Packit 5c3484
	si *= 2;
Packit 5c3484
      else
Packit 5c3484
	overflow_count++;
Packit 5c3484
Packit 5c3484
      check_si_cmp (sz, oz, si, oi, c);
Packit 5c3484
    
Packit 5c3484
      /* c * (2^k + 1) */
Packit 5c3484
      if (c == -1)
Packit 5c3484
	mpz_sub_ui (oz, sz, 1);
Packit 5c3484
      else
Packit 5c3484
	mpz_add_ui (oz, sz, 1);
Packit 5c3484
      if (mpz_fits_slong_p (oz))
Packit 5c3484
	oi = si + c;      
Packit 5c3484
      else 
Packit 5c3484
	overflow_count++;
Packit 5c3484
      check_si_cmp (oz, sz, oi, si, c);
Packit 5c3484
Packit 5c3484
      /* c * (2^K - 1) */
Packit 5c3484
      mpz_mul_si (oz, sz, 2*c);
Packit 5c3484
      if (c == -1)
Packit 5c3484
	mpz_ui_sub (oz, 1, oz); /* oz = sz * 2 + 1 */
Packit 5c3484
      else
Packit 5c3484
	mpz_sub_ui (oz, oz, 1); /* oz = sz * 2 - 1 */
Packit 5c3484
      if (mpz_fits_slong_p (oz))
Packit 5c3484
	oi = (si - c) * 2 + c; 
Packit 5c3484
      else 
Packit 5c3484
	overflow_count++;
Packit 5c3484
      
Packit 5c3484
      check_si_cmp (oz, sz, oi, si, c);
Packit 5c3484
    };
Packit 5c3484
  
Packit 5c3484
  mpz_clear (sz);
Packit 5c3484
  mpz_clear (oz);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void 
Packit 5c3484
try_fits_slong_p (void)
Packit 5c3484
{
Packit 5c3484
  mpz_t x;
Packit 5c3484
  mpz_init_set_si (x, LONG_MAX);
Packit 5c3484
  if (!mpz_fits_slong_p (x))
Packit 5c3484
    {
Packit 5c3484
      printf ("mpz_fits_slong_p (LONG_MAX) false!\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
  mpz_add_ui (x, x, 1);
Packit 5c3484
  if (mpz_fits_slong_p (x))
Packit 5c3484
    {
Packit 5c3484
      printf ("mpz_fits_slong_p (LONG_MAX + 1) true!\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
  mpz_set_si (x, LONG_MIN);
Packit 5c3484
  if (!mpz_fits_slong_p (x))
Packit 5c3484
    {
Packit 5c3484
      printf ("mpz_fits_slong_p (LONG_MIN) false!\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
  mpz_sub_ui (x, x, 1);
Packit 5c3484
  if (mpz_fits_slong_p (x))
Packit 5c3484
    {
Packit 5c3484
      printf ("mpz_fits_slong_p (LONG_MIN - 1) true!\n");
Packit 5c3484
      abort ();
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpz_clear (x);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
testmain (int argc, char *argv[])
Packit 5c3484
{
Packit 5c3484
  try_fits_slong_p ();
Packit 5c3484
  try_op_si (-1);
Packit 5c3484
  try_op_si (1);
Packit 5c3484
}