1 /* Test mpn_add_1 and mpn_sub_1. 2 3 Copyright 2001, 2002 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library. 6 7 The GNU MP Library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU Lesser General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or (at your 10 option) any later version. 11 12 The GNU MP Library is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 License for more details. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 19 20 #include <stdio.h> 21 #include <stdlib.h> 22 23 #include "gmp.h" 24 #include "gmp-impl.h" 25 #include "tests.h" 26 27 28 #define M GMP_NUMB_MAX 29 #define ASIZE 10 30 #define MAGIC 0x1234 31 32 #define SETUP() \ 33 do { \ 34 refmpn_random (got, data[i].size); \ 35 got[data[i].size] = MAGIC; \ 36 } while (0) 37 38 #define SETUP_INPLACE() \ 39 do { \ 40 refmpn_copyi (got, data[i].src, data[i].size); \ 41 got[data[i].size] = MAGIC; \ 42 } while (0) 43 44 #define VERIFY(name) \ 45 do { \ 46 verify (name, i, data[i].src, data[i].n, \ 47 got_c, data[i].want_c, \ 48 got, data[i].want, data[i].size); \ 49 } while (0) 50 51 typedef mp_limb_t (*mpn_aors_1_t) 52 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); 53 mpn_aors_1_t fudge __GMP_PROTO ((mpn_aors_1_t)); 54 55 56 void 57 verify (const char *name, int i, 58 mp_srcptr src, mp_limb_t n, 59 mp_limb_t got_c, mp_limb_t want_c, 60 mp_srcptr got, mp_srcptr want, mp_size_t size) 61 { 62 if (got[size] != MAGIC) 63 { 64 printf ("Overwrite at %s i=%d\n", name, i); 65 abort (); 66 } 67 68 if (got_c != want_c || ! refmpn_equal_anynail (got, want, size)) 69 { 70 printf ("Wrong at %s i=%d size=%ld\n", name, i, size); 71 mpn_trace (" src", src, size); 72 mpn_trace (" n", &n, (mp_size_t) 1); 73 mpn_trace (" got", got, size); 74 mpn_trace (" want", want, size); 75 mpn_trace (" got c", &got_c, (mp_size_t) 1); 76 mpn_trace ("want c", &want_c, (mp_size_t) 1); 77 abort (); 78 } 79 } 80 81 82 void 83 check_add_1 (void) 84 { 85 static const struct { 86 mp_size_t size; 87 mp_limb_t n; 88 const mp_limb_t src[ASIZE]; 89 mp_limb_t want_c; 90 const mp_limb_t want[ASIZE]; 91 } data[] = { 92 { 1, 0, { 0 }, 0, { 0 } }, 93 { 1, 0, { 1 }, 0, { 1 } }, 94 { 1, 1, { 0 }, 0, { 1 } }, 95 { 1, 0, { M }, 0, { M } }, 96 { 1, M, { 0 }, 0, { M } }, 97 { 1, 1, { 123 }, 0, { 124 } }, 98 99 { 1, 1, { M }, 1, { 0 } }, 100 { 1, M, { 1 }, 1, { 0 } }, 101 { 1, M, { M }, 1, { M-1 } }, 102 103 { 2, 0, { 0, 0 }, 0, { 0, 0 } }, 104 { 2, 0, { 1, 0 }, 0, { 1, 0 } }, 105 { 2, 1, { 0, 0 }, 0, { 1, 0 } }, 106 { 2, 0, { M, 0 }, 0, { M, 0 } }, 107 { 2, M, { 0, 0 }, 0, { M, 0 } }, 108 { 2, 1, { M, 0 }, 0, { 0, 1 } }, 109 { 2, M, { 1, 0 }, 0, { 0, 1 } }, 110 { 2, M, { M, 0 }, 0, { M-1, 1 } }, 111 { 2, M, { M, 0 }, 0, { M-1, 1 } }, 112 113 { 2, 1, { M, M }, 1, { 0, 0 } }, 114 { 2, M, { 1, M }, 1, { 0, 0 } }, 115 { 2, M, { M, M }, 1, { M-1, 0 } }, 116 { 2, M, { M, M }, 1, { M-1, 0 } }, 117 118 { 3, 1, { M, M, M }, 1, { 0, 0, 0 } }, 119 { 3, M, { 1, M, M }, 1, { 0, 0, 0 } }, 120 { 3, M, { M, M, M }, 1, { M-1, 0, 0 } }, 121 { 3, M, { M, M, M }, 1, { M-1, 0, 0 } }, 122 123 { 4, 1, { M, M, M, M }, 1, { 0, 0, 0, 0 } }, 124 { 4, M, { 1, M, M, M }, 1, { 0, 0, 0, 0 } }, 125 { 4, M, { M, M, M, M }, 1, { M-1, 0, 0, 0 } }, 126 { 4, M, { M, M, M, M }, 1, { M-1, 0, 0, 0 } }, 127 128 { 4, M, { M, 0, M, M }, 0, { M-1, 1, M, M } }, 129 { 4, M, { M, M-1, M, M }, 0, { M-1, M, M, M } }, 130 131 { 4, M, { M, M, 0, M }, 0, { M-1, 0, 1, M } }, 132 { 4, M, { M, M, M-1, M }, 0, { M-1, 0, M, M } }, 133 }; 134 135 mp_limb_t got[ASIZE]; 136 mp_limb_t got_c; 137 int i; 138 139 for (i = 0; i < numberof (data); i++) 140 { 141 SETUP (); 142 got_c = mpn_add_1 (got, data[i].src, data[i].size, data[i].n); 143 VERIFY ("check_add_1 (separate)"); 144 145 SETUP_INPLACE (); 146 got_c = mpn_add_1 (got, got, data[i].size, data[i].n); 147 VERIFY ("check_add_1 (in-place)"); 148 149 if (data[i].n == 1) 150 { 151 SETUP (); 152 got_c = mpn_add_1 (got, data[i].src, data[i].size, CNST_LIMB(1)); 153 VERIFY ("check_add_1 (separate, const 1)"); 154 155 SETUP_INPLACE (); 156 got_c = mpn_add_1 (got, got, data[i].size, CNST_LIMB(1)); 157 VERIFY ("check_add_1 (in-place, const 1)"); 158 } 159 160 /* Same again on functions, not inlines. */ 161 SETUP (); 162 got_c = (*fudge(mpn_add_1)) (got, data[i].src, data[i].size, data[i].n); 163 VERIFY ("check_add_1 (function, separate)"); 164 165 SETUP_INPLACE (); 166 got_c = (*fudge(mpn_add_1)) (got, got, data[i].size, data[i].n); 167 VERIFY ("check_add_1 (function, in-place)"); 168 } 169 } 170 171 void 172 check_sub_1 (void) 173 { 174 static const struct { 175 mp_size_t size; 176 mp_limb_t n; 177 const mp_limb_t src[ASIZE]; 178 mp_limb_t want_c; 179 const mp_limb_t want[ASIZE]; 180 } data[] = { 181 { 1, 0, { 0 }, 0, { 0 } }, 182 { 1, 0, { 1 }, 0, { 1 } }, 183 { 1, 1, { 1 }, 0, { 0 } }, 184 { 1, 0, { M }, 0, { M } }, 185 { 1, 1, { M }, 0, { M-1 } }, 186 { 1, 1, { 123 }, 0, { 122 } }, 187 188 { 1, 1, { 0 }, 1, { M } }, 189 { 1, M, { 0 }, 1, { 1 } }, 190 191 { 2, 0, { 0, 0 }, 0, { 0, 0 } }, 192 { 2, 0, { 1, 0 }, 0, { 1, 0 } }, 193 { 2, 1, { 1, 0 }, 0, { 0, 0 } }, 194 { 2, 0, { M, 0 }, 0, { M, 0 } }, 195 { 2, 1, { M, 0 }, 0, { M-1, 0 } }, 196 { 2, 1, { 123, 0 }, 0, { 122, 0 } }, 197 198 { 2, 1, { 0, 0 }, 1, { M, M } }, 199 { 2, M, { 0, 0 }, 1, { 1, M } }, 200 201 { 3, 0, { 0, 0, 0 }, 0, { 0, 0, 0 } }, 202 { 3, 0, { 123, 0, 0 }, 0, { 123, 0, 0 } }, 203 204 { 3, 1, { 0, 0, 0 }, 1, { M, M, M } }, 205 { 3, M, { 0, 0, 0 }, 1, { 1, M, M } }, 206 207 { 4, 1, { 0, 0, 0, 0 }, 1, { M, M, M, M } }, 208 { 4, M, { 0, 0, 0, 0 }, 1, { 1, M, M, M } }, 209 210 { 4, 1, { 0, 0, 1, 42 }, 0, { M, M, 0, 42 } }, 211 { 4, M, { 0, 0, 123, 24 }, 0, { 1, M, 122, 24 } }, 212 }; 213 214 mp_limb_t got[ASIZE]; 215 mp_limb_t got_c; 216 int i; 217 218 for (i = 0; i < numberof (data); i++) 219 { 220 SETUP (); 221 got_c = mpn_sub_1 (got, data[i].src, data[i].size, data[i].n); 222 VERIFY ("check_sub_1 (separate)"); 223 224 SETUP_INPLACE (); 225 got_c = mpn_sub_1 (got, got, data[i].size, data[i].n); 226 VERIFY ("check_sub_1 (in-place)"); 227 228 if (data[i].n == 1) 229 { 230 SETUP (); 231 got_c = mpn_sub_1 (got, data[i].src, data[i].size, CNST_LIMB(1)); 232 VERIFY ("check_sub_1 (separate, const 1)"); 233 234 SETUP_INPLACE (); 235 got_c = mpn_sub_1 (got, got, data[i].size, CNST_LIMB(1)); 236 VERIFY ("check_sub_1 (in-place, const 1)"); 237 } 238 239 /* Same again on functions, not inlines. */ 240 SETUP (); 241 got_c = (*fudge(mpn_sub_1)) (got, data[i].src, data[i].size, data[i].n); 242 VERIFY ("check_sub_1 (function, separate)"); 243 244 SETUP_INPLACE (); 245 got_c = (*fudge(mpn_sub_1)) (got, got, data[i].size, data[i].n); 246 VERIFY ("check_sub_1 (function, in-place)"); 247 } 248 } 249 250 /* Try to prevent the optimizer inlining. */ 251 mpn_aors_1_t 252 fudge (mpn_aors_1_t f) 253 { 254 return f; 255 } 256 257 int 258 main (void) 259 { 260 tests_start (); 261 mp_trace_base = -16; 262 263 check_add_1 (); 264 check_sub_1 (); 265 266 tests_end (); 267 exit (0); 268 } 269