1 /* Test mpz_pow_ui and mpz_ui_pow_ui. 2 3 Copyright 1997, 1999-2001 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 <stdio.h> 21 #include <stdlib.h> 22 23 #include "gmp-impl.h" 24 #include "tests.h" 25 26 27 void 28 check_one (mpz_srcptr want, mpz_srcptr base, unsigned long exp) 29 { 30 mpz_t got; 31 32 mpz_init (got); 33 34 MPZ_CHECK_FORMAT (want); 35 36 mpz_pow_ui (got, base, exp); 37 if (mpz_cmp (got, want)) 38 { 39 printf ("mpz_pow_ui wrong\n"); 40 mpz_trace (" base", base); 41 printf (" exp = %lu (0x%lX)\n", exp, exp); 42 mpz_trace (" got ", got); 43 mpz_trace (" want", want); 44 abort (); 45 } 46 47 mpz_set (got, base); 48 mpz_pow_ui (got, got, exp); 49 if (mpz_cmp (got, want)) 50 { 51 printf ("mpz_pow_ui wrong\n"); 52 mpz_trace (" base", base); 53 printf (" exp = %lu (0x%lX)\n", exp, exp); 54 mpz_trace (" got ", got); 55 mpz_trace (" want", want); 56 abort (); 57 } 58 59 if (mpz_fits_ulong_p (base)) 60 { 61 unsigned long base_u = mpz_get_ui (base); 62 mpz_ui_pow_ui (got, base_u, exp); 63 if (mpz_cmp (got, want)) 64 { 65 printf ("mpz_ui_pow_ui wrong\n"); 66 printf (" base=%lu (0x%lX)\n", base_u, base_u); 67 printf (" exp = %lu (0x%lX)\n", exp, exp); 68 mpz_trace (" got ", got); 69 mpz_trace (" want", want); 70 abort (); 71 } 72 } 73 74 mpz_clear (got); 75 } 76 77 void 78 check_base (mpz_srcptr base) 79 { 80 unsigned long exp; 81 mpz_t want; 82 83 mpz_init (want); 84 mpz_set_ui (want, 1L); 85 86 for (exp = 0; exp < 20; exp++) 87 { 88 check_one (want, base, exp); 89 mpz_mul (want, want, base); 90 } 91 92 mpz_clear (want); 93 } 94 95 void 96 check_various (void) 97 { 98 static const struct { 99 const char *base; 100 } data[] = { 101 { "0" }, 102 { "1" }, 103 { "2" }, 104 { "3" }, 105 { "4" }, 106 { "5" }, 107 { "6" }, 108 { "10" }, 109 { "15" }, 110 { "16" }, 111 112 { "0x1F" }, 113 { "0xFF" }, 114 { "0x1001" }, 115 { "0xFFFF" }, 116 { "0x10000001" }, 117 { "0x1000000000000001" }, 118 119 /* actual size closest to estimate */ 120 { "0xFFFFFFFF" }, 121 { "0xFFFFFFFFFFFFFFFF" }, 122 123 /* same after rshift */ 124 { "0xFFFFFFFF0" }, 125 { "0xFFFFFFFF00" }, 126 { "0xFFFFFFFFFFFFFFFF0" }, 127 { "0xFFFFFFFFFFFFFFFF00" }, 128 129 /* change from 2 limbs to 1 after rshift */ 130 { "0x180000000" }, 131 { "0x18000000000000000" }, 132 133 /* change from 3 limbs to 2 after rshift */ 134 { "0x18000000100000000" }, 135 { "0x180000000000000010000000000000000" }, 136 137 /* handling of absolute value */ 138 { "-0x80000000" }, 139 { "-0x8000000000000000" }, 140 141 /* low zero limb, and size>2, checking argument overlap detection */ 142 { "0x3000000000000000300000000000000030000000000000000" }, 143 }; 144 145 mpz_t base; 146 int i; 147 148 mpz_init (base); 149 150 for (i = 0; i < numberof (data); i++) 151 { 152 mpz_set_str_or_abort (base, data[i].base, 0); 153 check_base (base); 154 } 155 156 mpz_clear (base); 157 } 158 159 void 160 check_random (int reps) 161 { 162 mpz_t base, want; 163 mp_size_t base_size; 164 int i; 165 unsigned long size_range, exp; 166 gmp_randstate_ptr rands = RANDS; 167 168 mpz_init (base); 169 mpz_init (want); 170 171 for (i = 0; i < reps; i++) 172 { 173 /* exponentially random 0 to 2^13 bits for base */ 174 mpz_urandomb (want, rands, 32); 175 size_range = mpz_get_ui (want) % 12 + 2; 176 mpz_urandomb (want, rands, size_range); 177 base_size = mpz_get_ui (want); 178 mpz_rrandomb (base, rands, base_size); 179 180 /* randomly signed base */ 181 mpz_urandomb (want, rands, 2); 182 if ((mpz_get_ui (want) & 1) != 0) 183 mpz_neg (base, base); 184 185 /* random 5 bits for exponent */ 186 mpz_urandomb (want, rands, 5L); 187 exp = mpz_get_ui (want); 188 189 refmpz_pow_ui (want, base, exp); 190 check_one (want, base, exp); 191 } 192 193 mpz_clear (base); 194 mpz_clear (want); 195 } 196 197 int 198 main (int argc, char **argv) 199 { 200 int reps = 5000; 201 202 /* dummy call to drag in refmpn.o for testing mpz/n_pow_ui.c with 203 refmpn_mul_2 */ 204 refmpn_zero_p (NULL, (mp_size_t) 0); 205 206 tests_start (); 207 mp_trace_base = -16; 208 209 if (argc == 2) 210 reps = atoi (argv[1]); 211 212 check_various (); 213 check_random (reps); 214 215 tests_end (); 216 exit (0); 217 } 218