1221807Sstas/* Test mpz_pow_ui and mpz_ui_pow_ui. 2221807Sstas 3221807SstasCopyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc. 4221807Sstas 5221807SstasThis file is part of the GNU MP Library. 6221807Sstas 7221807SstasThe GNU MP Library is free software; you can redistribute it and/or modify 8221807Sstasit under the terms of the GNU Lesser General Public License as published by 9221807Sstasthe Free Software Foundation; either version 3 of the License, or (at your 10221807Sstasoption) any later version. 11221807Sstas 12221807SstasThe GNU MP Library is distributed in the hope that it will be useful, but 13221807SstasWITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14221807Sstasor FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15221807SstasLicense for more details. 16221807Sstas 17221807SstasYou should have received a copy of the GNU Lesser General Public License 18221807Sstasalong with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 19221807Sstas 20221807Sstas#include <stdio.h> 21221807Sstas#include <stdlib.h> 22221807Sstas 23221807Sstas#include "gmp.h" 24221807Sstas#include "gmp-impl.h" 25221807Sstas#include "tests.h" 26221807Sstas 27221807Sstas 28221807Sstasvoid 29221807Sstascheck_one (mpz_srcptr want, mpz_srcptr base, unsigned long exp) 30221807Sstas{ 31221807Sstas mpz_t got; 32221807Sstas 33221807Sstas mpz_init (got); 34221807Sstas 35221807Sstas MPZ_CHECK_FORMAT (want); 36221807Sstas 37249679Strociny mpz_pow_ui (got, base, exp); 38249679Strociny if (mpz_cmp (got, want)) 39249666Strociny { 40221807Sstas printf ("mpz_pow_ui wrong\n"); 41221807Sstas mpz_trace (" base", base); 42221807Sstas printf (" exp = %lu (0x%lX)\n", exp, exp); 43 mpz_trace (" got ", got); 44 mpz_trace (" want", want); 45 abort (); 46 } 47 48 mpz_set (got, base); 49 mpz_pow_ui (got, got, exp); 50 if (mpz_cmp (got, want)) 51 { 52 printf ("mpz_pow_ui wrong\n"); 53 mpz_trace (" base", base); 54 printf (" exp = %lu (0x%lX)\n", exp, exp); 55 mpz_trace (" got ", got); 56 mpz_trace (" want", want); 57 abort (); 58 } 59 60 if (mpz_fits_ulong_p (base)) 61 { 62 unsigned long base_u = mpz_get_ui (base); 63 mpz_ui_pow_ui (got, base_u, exp); 64 if (mpz_cmp (got, want)) 65 { 66 printf ("mpz_ui_pow_ui wrong\n"); 67 printf (" base=%lu (0x%lX)\n", base_u, base_u); 68 printf (" exp = %lu (0x%lX)\n", exp, exp); 69 mpz_trace (" got ", got); 70 mpz_trace (" want", want); 71 abort (); 72 } 73 } 74 75 mpz_clear (got); 76} 77 78void 79check_base (mpz_srcptr base) 80{ 81 unsigned long exp; 82 mpz_t want; 83 84 mpz_init (want); 85 mpz_set_ui (want, 1L); 86 87 for (exp = 0; exp < 20; exp++) 88 { 89 check_one (want, base, exp); 90 mpz_mul (want, want, base); 91 } 92 93 mpz_clear (want); 94} 95 96void 97check_various (void) 98{ 99 static const struct { 100 const char *base; 101 } data[] = { 102 { "0" }, 103 { "1" }, 104 { "2" }, 105 { "3" }, 106 { "4" }, 107 { "5" }, 108 { "6" }, 109 { "10" }, 110 { "15" }, 111 { "16" }, 112 113 { "0x1F" }, 114 { "0xFF" }, 115 { "0x1001" }, 116 { "0xFFFF" }, 117 { "0x10000001" }, 118 { "0x1000000000000001" }, 119 120 /* actual size closest to estimate */ 121 { "0xFFFFFFFF" }, 122 { "0xFFFFFFFFFFFFFFFF" }, 123 124 /* same after rshift */ 125 { "0xFFFFFFFF0" }, 126 { "0xFFFFFFFF00" }, 127 { "0xFFFFFFFFFFFFFFFF0" }, 128 { "0xFFFFFFFFFFFFFFFF00" }, 129 130 /* change from 2 limbs to 1 after rshift */ 131 { "0x180000000" }, 132 { "0x18000000000000000" }, 133 134 /* change from 3 limbs to 2 after rshift */ 135 { "0x18000000100000000" }, 136 { "0x180000000000000010000000000000000" }, 137 138 /* handling of absolute value */ 139 { "-0x80000000" }, 140 { "-0x8000000000000000" }, 141 142 /* low zero limb, and size>2, checking argument overlap detection */ 143 { "0x3000000000000000300000000000000030000000000000000" }, 144 }; 145 146 mpz_t base; 147 int i; 148 149 mpz_init (base); 150 151 for (i = 0; i < numberof (data); i++) 152 { 153 mpz_set_str_or_abort (base, data[i].base, 0); 154 check_base (base); 155 } 156 157 mpz_clear (base); 158} 159 160void 161check_random (int reps) 162{ 163 mpz_t base, want; 164 mp_size_t base_size; 165 int i; 166 unsigned long size_range, exp; 167 gmp_randstate_ptr rands = RANDS; 168 169 mpz_init (base); 170 mpz_init (want); 171 172 for (i = 0; i < reps; i++) 173 { 174 /* exponentially random 0 to 2^13 bits for base */ 175 mpz_urandomb (want, rands, 32); 176 size_range = mpz_get_ui (want) % 12 + 2; 177 mpz_urandomb (want, rands, size_range); 178 base_size = mpz_get_ui (want); 179 mpz_rrandomb (base, rands, base_size); 180 181 /* randomly signed base */ 182 mpz_urandomb (want, rands, 2); 183 if ((mpz_get_ui (want) & 1) != 0) 184 mpz_neg (base, base); 185 186 /* random 5 bits for exponent */ 187 mpz_urandomb (want, rands, 5L); 188 exp = mpz_get_ui (want); 189 190 refmpz_pow_ui (want, base, exp); 191 check_one (want, base, exp); 192 } 193 194 mpz_clear (base); 195 mpz_clear (want); 196} 197 198int 199main (int argc, char **argv) 200{ 201 int reps = 5000; 202 203 /* dummy call to drag in refmpn.o for testing mpz/n_pow_ui.c with 204 refmpn_mul_2 */ 205 refmpn_zero_p (NULL, (mp_size_t) 0); 206 207 tests_start (); 208 mp_trace_base = -16; 209 210 if (argc == 2) 211 reps = atoi (argv[1]); 212 213 check_various (); 214 check_random (reps); 215 216 tests_end (); 217 exit (0); 218} 219