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 %lu\n", e2, t2, mpz_scan1 (t, 0), (unsigned long) 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 } 139