(root)/
gmp-6.3.0/
mini-gmp/
tests/
t-mpq_muldiv_2exp.c
       1  /*
       2  
       3  Copyright 2012, 2013, 2018 Free Software Foundation, Inc.
       4  
       5  This file is part of the GNU MP Library test suite.
       6  
       7  The GNU MP Library test suite is free software; you can redistribute it
       8  and/or modify it under the terms of the GNU General Public License as
       9  published by the Free Software Foundation; either version 3 of the License,
      10  or (at your option) any later version.
      11  
      12  The GNU MP Library test suite is distributed in the hope that it will be
      13  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
      14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
      15  Public License for more details.
      16  
      17  You should have received a copy of the GNU General Public License along with
      18  the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
      19  
      20  #include <assert.h>
      21  #include <stdlib.h>
      22  #include <stdio.h>
      23  
      24  #include "testutils.h"
      25  #include "../mini-mpq.h"
      26  
      27  #define MAXBITS 300
      28  #define COUNT 10000
      29  
      30  static void
      31  _mpq_set_zz (mpq_t q, mpz_t n, mpz_t d)
      32  {
      33    if (mpz_fits_ulong_p (d) && mpz_fits_slong_p (n))
      34      {
      35        mpq_set_si (q, mpz_get_si (n), mpz_get_ui (d));
      36      }
      37    else if (mpz_fits_ulong_p (d) && mpz_fits_ulong_p (n))
      38      {
      39        mpq_set_ui (q, mpz_get_ui (n), mpz_get_ui (d));
      40      }
      41    else
      42      {
      43        mpq_set_num (q, n);
      44        mpq_set_den (q, d);
      45      }
      46    mpq_canonicalize (q);
      47  }
      48  
      49  void
      50  testmain (int argc, char **argv)
      51  {
      52    unsigned i;
      53    mpz_t a, b, t;
      54    mpq_t aq, rq, tq;
      55    mp_bitcnt_t e;
      56    long int e2, t1, t2;
      57  
      58    mpz_init (a);
      59    mpz_init (b);
      60    mpz_init (t);
      61    mpq_init (aq);
      62    mpq_init (rq);
      63    mpq_init (tq);
      64  
      65    for (i = 0; i < COUNT; i++)
      66      {
      67        do {
      68  	mini_random_bit_op (OP_COMBIT, MAXBITS, a, &e, b);
      69        } while (mpz_sgn (a) == 0 || mpz_sgn (b) == 0);
      70  
      71        _mpq_set_zz (aq, a, b);
      72        e2 = mpz_scan1 (a, 0);
      73        e2-= mpz_scan1 (b, 0);
      74  
      75        mpq_mul_2exp (rq, aq, e);
      76        t1 = mpz_scan1 (mpq_numref (rq), 0);
      77        t2 = mpz_scan1 (mpq_denref (rq), 0);
      78        mpq_neg (tq, rq);
      79        mpq_div (tq, aq, tq);
      80        mpq_get_den (t, tq);
      81  
      82        if (e2 + e != t1 - t2 || (t2 != 0 && t1 != 0) || mpz_scan1 (t, 0) != e
      83  	  || mpz_sizeinbase (t, 2) - 1 != e || mpz_cmp_si (mpq_numref (tq), -1) != 0)
      84  	{
      85  	  fprintf (stderr, "mpq_mul_2exp failed: %lu\n", e);
      86  	  dump ("na", a);
      87  	  dump ("da", b);
      88  	  dump ("nr", mpq_numref (rq));
      89  	  dump ("dr", mpq_denref (rq));
      90  	  abort ();
      91  	}
      92  
      93        mpq_div_2exp (rq, aq, e);
      94        t1 = mpz_scan1 (mpq_numref (rq), 0);
      95        t2 = mpz_scan1 (mpq_denref (rq), 0);
      96        mpq_div (aq, aq, rq);
      97        mpq_get_num (t, aq);
      98  
      99        if (e2 != t1 - t2 + e || (t2 != 0 && t1 != 0) || mpz_scan1 (t, 0) != e
     100  	  || mpz_sizeinbase (t, 2) - 1 != e || mpz_cmp_ui (mpq_denref (aq), 1) != 0)
     101  	{
     102  	  fprintf (stderr, "mpq_div_2exp failed: %lu\n", e);
     103  	  fprintf (stderr, "%li %li %lu %zu\n", e2, t2, mpz_scan1 (t, 0), mpz_sizeinbase (t, 2));
     104  	  dump ("na", a);
     105  	  dump ("da", b);
     106  	  dump ("nr", mpq_numref (rq));
     107  	  dump ("dr", mpq_denref (rq));
     108  	  abort ();
     109  	}
     110  
     111        mpq_set_ui (aq, 0, 1);
     112        mpq_set_ui (rq, 6, 7);
     113        mpq_set (tq, aq);
     114        mpq_div_2exp (rq, aq, e);
     115  
     116        if (!mpq_equal (tq, rq))
     117  	{
     118  	  fprintf (stderr, "mpq_div_2exp failed on zero: %lu\n", e);
     119  	  abort ();
     120  	}
     121  
     122        mpq_set_ui (rq, 7, 6);
     123        mpq_mul_2exp (rq, aq, e);
     124  
     125        if (!mpq_equal (rq, tq))
     126  	{
     127  	  fprintf (stderr, "mpq_mul_2exp failed on zero: %lu\n", e);
     128  	  abort ();
     129  	}
     130      }
     131  
     132    mpz_clear (a);
     133    mpz_clear (b);
     134    mpz_clear (t);
     135    mpq_clear (aq);
     136    mpq_clear (rq);
     137    mpq_clear (tq);
     138  }