Blame mini-gmp/tests/hex-random.c

Packit 5c3484
/*
Packit 5c3484
Packit 5c3484
Copyright 2011, 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 <stdio.h>
Packit 5c3484
#include <stdlib.h>
Packit 5c3484
Packit 5c3484
#include <time.h>
Packit 5c3484
Packit 5c3484
#ifdef __unix__
Packit 5c3484
# include <unistd.h>
Packit 5c3484
# include <sys/time.h>
Packit 5c3484
#endif
Packit 5c3484
Packit 5c3484
#include "gmp.h"
Packit 5c3484
Packit 5c3484
#include "hex-random.h"
Packit 5c3484
Packit 5c3484
static gmp_randstate_t state;
Packit 5c3484
Packit 5c3484
static void
Packit 5c3484
mkseed (mpz_t seed)
Packit 5c3484
{
Packit 5c3484
  FILE *f = fopen ("/dev/urandom", "rb");
Packit 5c3484
  if (f)
Packit 5c3484
    {
Packit 5c3484
      unsigned char buf[6];
Packit 5c3484
      size_t res;
Packit 5c3484
Packit 5c3484
      setbuf (f, NULL);
Packit 5c3484
      res = fread (buf, sizeof(buf), 1, f);
Packit 5c3484
      fclose (f);
Packit 5c3484
Packit 5c3484
      if (res == 1)
Packit 5c3484
	{
Packit 5c3484
	  mpz_import (seed, sizeof(buf), 1, 1, 0, 0, buf);
Packit 5c3484
	  return;
Packit 5c3484
	}
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
#ifdef __unix__
Packit 5c3484
  {
Packit 5c3484
    struct timeval tv;
Packit 5c3484
    mpz_t usec;
Packit 5c3484
    mpz_init (usec);
Packit 5c3484
Packit 5c3484
    gettimeofday (&tv, NULL);
Packit 5c3484
    mpz_set_ui (seed, tv.tv_sec);
Packit 5c3484
    mpz_set_ui (usec, tv.tv_usec);
Packit 5c3484
    /* usec fits in 20 bits, shift left to make it 48 bits. */
Packit 5c3484
    mpz_mul_2exp (usec, usec, 28);
Packit 5c3484
    mpz_xor (seed, seed, usec);
Packit 5c3484
Packit 5c3484
    mpz_clear (usec);
Packit 5c3484
  }
Packit 5c3484
#else
Packit 5c3484
  mpz_set_ui (seed, time (NULL));
Packit 5c3484
#endif
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
hex_random_init (void)
Packit 5c3484
{
Packit 5c3484
  mpz_t seed;
Packit 5c3484
  char *env_seed;
Packit 5c3484
Packit 5c3484
  mpz_init (seed);
Packit 5c3484
Packit 5c3484
  env_seed = getenv ("GMP_CHECK_RANDOMIZE");
Packit 5c3484
  if (env_seed && env_seed[0])
Packit 5c3484
    {
Packit 5c3484
      mpz_set_str (seed, env_seed, 0);
Packit 5c3484
      if (mpz_cmp_ui (seed, 0) != 0)
Packit 5c3484
	gmp_printf ("Re-seeding with GMP_CHECK_RANDOMIZE=%Zd\n", seed);
Packit 5c3484
      else
Packit 5c3484
	{
Packit 5c3484
	  mkseed (seed);
Packit 5c3484
	  gmp_printf ("Seed GMP_CHECK_RANDOMIZE=%Zd (include this in bug reports)\n", seed);
Packit 5c3484
	}
Packit 5c3484
      fflush (stdout);
Packit 5c3484
    }
Packit 5c3484
  else
Packit 5c3484
    mpz_set_ui (seed, 4711);
Packit 5c3484
Packit 5c3484
  gmp_randinit_default (state);
Packit 5c3484
  gmp_randseed (state, seed);
Packit 5c3484
Packit 5c3484
  mpz_clear (seed);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
char *
Packit 5c3484
hex_urandomb (unsigned long bits)
Packit 5c3484
{
Packit 5c3484
  char *res;
Packit 5c3484
  mpz_t x;
Packit 5c3484
Packit 5c3484
  mpz_init (x);
Packit 5c3484
  mpz_urandomb (x, state, bits);
Packit 5c3484
  gmp_asprintf (&res, "%Zx", x);
Packit 5c3484
  mpz_clear (x);
Packit 5c3484
  return res;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
char *
Packit 5c3484
hex_rrandomb (unsigned long bits)
Packit 5c3484
{
Packit 5c3484
  char *res;
Packit 5c3484
  mpz_t x;
Packit 5c3484
Packit 5c3484
  mpz_init (x);
Packit 5c3484
  mpz_rrandomb (x, state, bits);
Packit 5c3484
  gmp_asprintf (&res, "%Zx", x);
Packit 5c3484
  mpz_clear (x);
Packit 5c3484
  return res;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
char *
Packit 5c3484
hex_rrandomb_export (void *dst, size_t *countp,
Packit 5c3484
		     int order, size_t size, int endian, unsigned long bits)
Packit 5c3484
{
Packit 5c3484
  char *res;
Packit 5c3484
  mpz_t x;
Packit 5c3484
  mpz_init (x);
Packit 5c3484
  mpz_rrandomb (x, state, bits);
Packit 5c3484
  gmp_asprintf (&res, "%Zx", x);
Packit 5c3484
  mpz_export (dst, countp, order, size, endian, 0, x);
Packit 5c3484
  mpz_clear (x);
Packit 5c3484
  return res;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void hex_random_op2 (enum hex_random_op op,  unsigned long maxbits,
Packit 5c3484
		     char **ap, char **rp)
Packit 5c3484
{
Packit 5c3484
  mpz_t a, r;
Packit 5c3484
  unsigned long abits;
Packit 5c3484
  unsigned signs;
Packit 5c3484
Packit 5c3484
  mpz_init (a);
Packit 5c3484
  mpz_init (r);
Packit 5c3484
Packit 5c3484
  abits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
Packit 5c3484
  mpz_rrandomb (a, state, abits);
Packit 5c3484
Packit 5c3484
  signs = gmp_urandomb_ui (state, 1);
Packit 5c3484
  if (signs & 1)
Packit 5c3484
    mpz_neg (a, a);
Packit 5c3484
Packit 5c3484
  switch (op)
Packit 5c3484
    {
Packit 5c3484
    default:
Packit 5c3484
      abort ();
Packit 5c3484
    case OP_SQR:
Packit 5c3484
      mpz_mul (r, a, a);
Packit 5c3484
      break;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  gmp_asprintf (ap, "%Zx", a);
Packit 5c3484
  gmp_asprintf (rp, "%Zx", r);
Packit 5c3484
Packit 5c3484
  mpz_clear (a);
Packit 5c3484
  mpz_clear (r);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
hex_random_op3 (enum hex_random_op op,  unsigned long maxbits,
Packit 5c3484
		char **ap, char **bp, char **rp)
Packit 5c3484
{
Packit 5c3484
  mpz_t a, b, r;
Packit 5c3484
  unsigned long abits, bbits;
Packit 5c3484
  unsigned signs;
Packit 5c3484
Packit 5c3484
  mpz_init (a);
Packit 5c3484
  mpz_init (b);
Packit 5c3484
  mpz_init (r);
Packit 5c3484
Packit 5c3484
  abits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
  bbits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
Packit 5c3484
  mpz_rrandomb (a, state, abits);
Packit 5c3484
  mpz_rrandomb (b, state, bbits);
Packit 5c3484
Packit 5c3484
  signs = gmp_urandomb_ui (state, 3);
Packit 5c3484
  if (signs & 1)
Packit 5c3484
    mpz_neg (a, a);
Packit 5c3484
  if (signs & 2)
Packit 5c3484
    mpz_neg (b, b);
Packit 5c3484
Packit 5c3484
  switch (op)
Packit 5c3484
    {
Packit 5c3484
    default:
Packit 5c3484
      abort ();
Packit 5c3484
    case OP_ADD:
Packit 5c3484
      mpz_add (r, a, b);
Packit 5c3484
      break;
Packit 5c3484
    case OP_SUB:
Packit 5c3484
      mpz_sub (r, a, b);
Packit 5c3484
      break;
Packit 5c3484
    case OP_MUL:
Packit 5c3484
      mpz_mul (r, a, b);
Packit 5c3484
      break;
Packit 5c3484
    case OP_GCD:
Packit 5c3484
      if (signs & 4)
Packit 5c3484
	{
Packit 5c3484
	  /* Produce a large gcd */
Packit 5c3484
	  unsigned long gbits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
	  mpz_rrandomb (r, state, gbits);
Packit 5c3484
	  mpz_mul (a, a, r);
Packit 5c3484
	  mpz_mul (b, b, r);
Packit 5c3484
	}
Packit 5c3484
      mpz_gcd (r, a, b);
Packit 5c3484
      break;
Packit 5c3484
    case OP_LCM:
Packit 5c3484
      if (signs & 4)
Packit 5c3484
	{
Packit 5c3484
	  /* Produce a large gcd */
Packit 5c3484
	  unsigned long gbits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
	  mpz_rrandomb (r, state, gbits);
Packit 5c3484
	  mpz_mul (a, a, r);
Packit 5c3484
	  mpz_mul (b, b, r);
Packit 5c3484
	}
Packit 5c3484
      mpz_lcm (r, a, b);
Packit 5c3484
      break;
Packit 5c3484
    case OP_AND:
Packit 5c3484
      mpz_and (r, a, b);
Packit 5c3484
      break;
Packit 5c3484
    case OP_IOR:
Packit 5c3484
      mpz_ior (r, a, b);
Packit 5c3484
      break;
Packit 5c3484
    case OP_XOR:
Packit 5c3484
      mpz_xor (r, a, b);
Packit 5c3484
      break;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  gmp_asprintf (ap, "%Zx", a);
Packit 5c3484
  gmp_asprintf (bp, "%Zx", b);
Packit 5c3484
  gmp_asprintf (rp, "%Zx", r);
Packit 5c3484
Packit 5c3484
  mpz_clear (a);
Packit 5c3484
  mpz_clear (b);
Packit 5c3484
  mpz_clear (r);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
hex_random_op4 (enum hex_random_op op, unsigned long maxbits,
Packit 5c3484
		char **ap, char **bp, char **cp, char **dp)
Packit 5c3484
{
Packit 5c3484
  mpz_t a, b, c, d;
Packit 5c3484
  unsigned long abits, bbits;
Packit 5c3484
  unsigned signs;
Packit 5c3484
Packit 5c3484
  mpz_init (a);
Packit 5c3484
  mpz_init (b);
Packit 5c3484
  mpz_init (c);
Packit 5c3484
  mpz_init (d);
Packit 5c3484
Packit 5c3484
  if (op == OP_POWM)
Packit 5c3484
    {
Packit 5c3484
      unsigned long cbits;
Packit 5c3484
      abits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
      bbits = 1 + gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
      cbits = 2 + gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
Packit 5c3484
      mpz_rrandomb (a, state, abits);
Packit 5c3484
      mpz_rrandomb (b, state, bbits);
Packit 5c3484
      mpz_rrandomb (c, state, cbits);
Packit 5c3484
Packit 5c3484
      signs = gmp_urandomb_ui (state, 3);
Packit 5c3484
      if (signs & 1)
Packit 5c3484
	mpz_neg (a, a);
Packit 5c3484
      if (signs & 2)
Packit 5c3484
	{
Packit 5c3484
	  mpz_t g;
Packit 5c3484
Packit 5c3484
	  /* If we negate the exponent, must make sure that gcd(a, c) = 1 */
Packit 5c3484
	  if (mpz_sgn (a) == 0)
Packit 5c3484
	    mpz_set_ui (a, 1);
Packit 5c3484
	  else
Packit 5c3484
	    {
Packit 5c3484
	      mpz_init (g);
Packit 5c3484
Packit 5c3484
	      for (;;)
Packit 5c3484
		{
Packit 5c3484
		  mpz_gcd (g, a, c);
Packit 5c3484
		  if (mpz_cmp_ui (g, 1) == 0)
Packit 5c3484
		    break;
Packit 5c3484
		  mpz_divexact (a, a, g);
Packit 5c3484
		}
Packit 5c3484
	      mpz_clear (g);
Packit 5c3484
	    }
Packit 5c3484
	  mpz_neg (b, b);
Packit 5c3484
	}
Packit 5c3484
      if (signs & 4)
Packit 5c3484
	mpz_neg (c, c);
Packit 5c3484
Packit 5c3484
      mpz_powm (d, a, b, c);
Packit 5c3484
    }
Packit 5c3484
  else
Packit 5c3484
    {
Packit 5c3484
      unsigned long qbits;
Packit 5c3484
      bbits = 1 + gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
      qbits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
      abits = bbits + qbits;
Packit 5c3484
      if (abits > 30)
Packit 5c3484
	abits -= 30;
Packit 5c3484
      else
Packit 5c3484
	abits = 0;
Packit 5c3484
Packit 5c3484
      mpz_rrandomb (a, state, abits);
Packit 5c3484
      mpz_rrandomb (b, state, bbits);
Packit 5c3484
Packit 5c3484
      signs = gmp_urandomb_ui (state, 2);
Packit 5c3484
      if (signs & 1)
Packit 5c3484
	mpz_neg (a, a);
Packit 5c3484
      if (signs & 2)
Packit 5c3484
	mpz_neg (b, b);
Packit 5c3484
Packit 5c3484
      switch (op)
Packit 5c3484
	{
Packit 5c3484
	default:
Packit 5c3484
	  abort ();
Packit 5c3484
	case OP_CDIV:
Packit 5c3484
	  mpz_cdiv_qr (c, d, a, b);
Packit 5c3484
	  break;
Packit 5c3484
	case OP_FDIV:
Packit 5c3484
	  mpz_fdiv_qr (c, d, a, b);
Packit 5c3484
	  break;
Packit 5c3484
	case OP_TDIV:
Packit 5c3484
	  mpz_tdiv_qr (c, d, a, b);
Packit 5c3484
	  break;
Packit 5c3484
	}
Packit 5c3484
    }
Packit 5c3484
  gmp_asprintf (ap, "%Zx", a);
Packit 5c3484
  gmp_asprintf (bp, "%Zx", b);
Packit 5c3484
  gmp_asprintf (cp, "%Zx", c);
Packit 5c3484
  gmp_asprintf (dp, "%Zx", d);
Packit 5c3484
Packit 5c3484
  mpz_clear (a);
Packit 5c3484
  mpz_clear (b);
Packit 5c3484
  mpz_clear (c);
Packit 5c3484
  mpz_clear (d);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
hex_random_bit_op (enum hex_random_op op, unsigned long maxbits,
Packit 5c3484
		   char **ap, unsigned long *b, char **rp)
Packit 5c3484
{
Packit 5c3484
  mpz_t a, r;
Packit 5c3484
  unsigned long abits, bbits;
Packit 5c3484
  unsigned signs;
Packit 5c3484
Packit 5c3484
  mpz_init (a);
Packit 5c3484
  mpz_init (r);
Packit 5c3484
Packit 5c3484
  abits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
  bbits = gmp_urandomb_ui (state, 32) % (maxbits + 100);
Packit 5c3484
Packit 5c3484
  mpz_rrandomb (a, state, abits);
Packit 5c3484
Packit 5c3484
  signs = gmp_urandomb_ui (state, 1);
Packit 5c3484
  if (signs & 1)
Packit 5c3484
    mpz_neg (a, a);
Packit 5c3484
Packit 5c3484
  switch (op)
Packit 5c3484
    {
Packit 5c3484
    default:
Packit 5c3484
      abort ();
Packit 5c3484
Packit 5c3484
    case OP_SETBIT:
Packit 5c3484
      mpz_set (r, a);
Packit 5c3484
      mpz_setbit (r, bbits);
Packit 5c3484
      break;
Packit 5c3484
    case OP_CLRBIT:
Packit 5c3484
      mpz_set (r, a);
Packit 5c3484
      mpz_clrbit (r, bbits);
Packit 5c3484
      break;
Packit 5c3484
    case OP_COMBIT:
Packit 5c3484
      mpz_set (r, a);
Packit 5c3484
      mpz_combit (r, bbits);
Packit 5c3484
      break;
Packit 5c3484
    case OP_CDIV_Q_2:
Packit 5c3484
      mpz_cdiv_q_2exp (r, a, bbits);
Packit 5c3484
      break;
Packit 5c3484
    case OP_CDIV_R_2:
Packit 5c3484
      mpz_cdiv_r_2exp (r, a, bbits);
Packit 5c3484
      break;
Packit 5c3484
    case OP_FDIV_Q_2:
Packit 5c3484
      mpz_fdiv_q_2exp (r, a, bbits);
Packit 5c3484
      break;
Packit 5c3484
    case OP_FDIV_R_2:
Packit 5c3484
      mpz_fdiv_r_2exp (r, a, bbits);
Packit 5c3484
      break;
Packit 5c3484
    case OP_TDIV_Q_2:
Packit 5c3484
      mpz_tdiv_q_2exp (r, a, bbits);
Packit 5c3484
      break;
Packit 5c3484
    case OP_TDIV_R_2:
Packit 5c3484
      mpz_tdiv_r_2exp (r, a, bbits);
Packit 5c3484
      break;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  gmp_asprintf (ap, "%Zx", a);
Packit 5c3484
  *b = bbits;
Packit 5c3484
  gmp_asprintf (rp, "%Zx", r);
Packit 5c3484
Packit 5c3484
  mpz_clear (a);
Packit 5c3484
  mpz_clear (r);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
hex_random_scan_op (enum hex_random_op op, unsigned long maxbits,
Packit 5c3484
		    char **ap, unsigned long *b, unsigned long *r)
Packit 5c3484
{
Packit 5c3484
  mpz_t a;
Packit 5c3484
  unsigned long abits, bbits;
Packit 5c3484
  unsigned signs;
Packit 5c3484
Packit 5c3484
  mpz_init (a);
Packit 5c3484
Packit 5c3484
  abits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
  bbits = gmp_urandomb_ui (state, 32) % (maxbits + 100);
Packit 5c3484
Packit 5c3484
  mpz_rrandomb (a, state, abits);
Packit 5c3484
Packit 5c3484
  signs = gmp_urandomb_ui (state, 1);
Packit 5c3484
  if (signs & 1)
Packit 5c3484
    mpz_neg (a, a);
Packit 5c3484
Packit 5c3484
  switch (op)
Packit 5c3484
    {
Packit 5c3484
    default:
Packit 5c3484
      abort ();
Packit 5c3484
Packit 5c3484
    case OP_SCAN0:
Packit 5c3484
      *r = mpz_scan0 (a, bbits);
Packit 5c3484
      break;
Packit 5c3484
    case OP_SCAN1:
Packit 5c3484
      *r = mpz_scan1 (a, bbits);
Packit 5c3484
      break;
Packit 5c3484
    }
Packit 5c3484
  gmp_asprintf (ap, "%Zx", a);
Packit 5c3484
  *b = bbits;
Packit 5c3484
Packit 5c3484
  mpz_clear (a);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
hex_random_str_op (unsigned long maxbits,
Packit 5c3484
		   int base, char **ap, char **rp)
Packit 5c3484
{
Packit 5c3484
  mpz_t a;
Packit 5c3484
  unsigned long abits;
Packit 5c3484
  unsigned signs;
Packit 5c3484
Packit 5c3484
  mpz_init (a);
Packit 5c3484
Packit 5c3484
  abits = gmp_urandomb_ui (state, 32) % maxbits;
Packit 5c3484
Packit 5c3484
  mpz_rrandomb (a, state, abits);
Packit 5c3484
Packit 5c3484
  signs = gmp_urandomb_ui (state, 2);
Packit 5c3484
  if (signs & 1)
Packit 5c3484
    mpz_neg (a, a);
Packit 5c3484
Packit 5c3484
  *ap = mpz_get_str (NULL, 16, a);
Packit 5c3484
  *rp = mpz_get_str (NULL, base, a);
Packit 5c3484
Packit 5c3484
  mpz_clear (a);
Packit 5c3484
}