1 // SPDX-License-Identifier: GPL-2.0-or-later 1 2 /* mpihelp-div.c - MPI helper functions 3 * Copyright (C) 1994, 1996 Free Software 4 * Copyright (C) 1998, 1999 Free Software 5 * 6 * This file is part of GnuPG. 7 * 8 * Note: This code is heavily based on the GNU 9 * Actually it's the same code with only 10 * way the data is stored; this is to su 11 * of an optional secure memory allocati 12 * to avoid revealing of sensitive data 13 * The GNU MP Library itself is publishe 14 * however I decided to publish this cod 15 */ 16 17 #include "mpi-internal.h" 18 #include "longlong.h" 19 20 #ifndef UMUL_TIME 21 #define UMUL_TIME 1 22 #endif 23 #ifndef UDIV_TIME 24 #define UDIV_TIME UMUL_TIME 25 #endif 26 27 28 mpi_limb_t 29 mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size 30 mpi_limb_t divisor_lim 31 { 32 mpi_size_t i; 33 mpi_limb_t n1, n0, r; 34 mpi_limb_t dummy __maybe_unused; 35 36 /* Botch: Should this be handled at al 37 if (!dividend_size) 38 return 0; 39 40 /* If multiplication is much faster th 41 * dividend is large, pre-invert the d 42 * only multiplications in the inner l 43 * 44 * This test should be read: 45 * Does it ever help to use udiv 46 * && Does what we save compen 47 */ 48 if (UDIV_TIME > (2 * UMUL_TIME + 6) 49 && (UDIV_TIME - (2 * U 50 int normalization_steps; 51 52 normalization_steps = count_le 53 if (normalization_steps) { 54 mpi_limb_t divisor_lim 55 56 divisor_limb <<= norma 57 58 /* Compute (2**2N - 2* 59 * result is a (N+1)-b 60 * most significant bi 61 * 62 * Special case for DI 63 */ 64 if (!(divisor_limb << 65 divisor_limb_i 66 else 67 udiv_qrnnd(div 68 69 70 n1 = dividend_ptr[divi 71 r = n1 >> (BITS_PER_MP 72 73 /* Possible optimizati 74 * if (r == 0 75 * && divisor_limb > ( 76 * 77 * ...one division les 78 */ 79 for (i = dividend_size 80 n0 = dividend_ 81 UDIV_QRNND_PRE 82 83 84 85 n1 = n0; 86 } 87 UDIV_QRNND_PREINV(dumm 88 n1 << 89 diviso 90 return r >> normalizat 91 } else { 92 mpi_limb_t divisor_lim 93 94 /* Compute (2**2N - 2* 95 * result is a (N+1)-b 96 * most significant bi 97 * 98 * Special case for DI 99 */ 100 if (!(divisor_limb << 101 divisor_limb_i 102 else 103 udiv_qrnnd(div 104 105 106 i = dividend_size - 1; 107 r = dividend_ptr[i]; 108 109 if (r >= divisor_limb) 110 r = 0; 111 else 112 i--; 113 114 for ( ; i >= 0; i--) { 115 n0 = dividend_ 116 UDIV_QRNND_PRE 117 118 } 119 return r; 120 } 121 } else { 122 if (UDIV_NEEDS_NORMALIZATION) 123 int normalization_step 124 125 normalization_steps = 126 if (normalization_step 127 divisor_limb < 128 129 n1 = dividend_ 130 r = n1 >> (BIT 131 132 /* Possible op 133 * if (r == 0 134 * && divisor_ 135 * 136 * ...one divi 137 */ 138 for (i = divid 139 n0 = d 140 udiv_q 141 142 143 144 n1 = n 145 } 146 udiv_qrnnd(dum 147 148 149 return r >> no 150 } 151 } 152 /* No normalization needed, ei 153 * it, or because DIVISOR_LIMB 154 */ 155 i = dividend_size - 1; 156 r = dividend_ptr[i]; 157 158 if (r >= divisor_limb) 159 r = 0; 160 else 161 i--; 162 163 for (; i >= 0; i--) { 164 n0 = dividend_ptr[i]; 165 udiv_qrnnd(dummy, r, r 166 } 167 return r; 168 } 169 } 170 171 /* Divide num (NP/NSIZE) by den (DP/DSIZE) and 172 * the NSIZE-DSIZE least significant quotient 173 * and the DSIZE long remainder at NP. If QEX 174 * non-zero, generate that many fraction bits 175 * other quotient limbs. 176 * Return the most significant limb of the quo 177 * 178 * Preconditions: 179 * 0. NSIZE >= DSIZE. 180 * 1. The most significant bit of the divisor 181 * 2. QP must either not overlap with the inpu 182 * QP + DSIZE >= NP must hold true. (This 183 * possible to put the quotient in the high 184 * remainder in NUM. 185 * 3. NSIZE >= DSIZE, even if QEXTRA_LIMBS is 186 */ 187 188 mpi_limb_t 189 mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra 190 mpi_ptr_t np, mpi_size_t nsize, 191 { 192 mpi_limb_t most_significant_q_limb = 0 193 194 switch (dsize) { 195 case 0: 196 /* We are asked to divide by z 197 the compiler not remove thi 198 /* 199 * existing clients of this fu 200 * not to call it with dsize = 201 */ 202 return 1 / dsize; 203 204 case 1: 205 { 206 mpi_size_t i; 207 mpi_limb_t n1; 208 mpi_limb_t d; 209 210 d = dp[0]; 211 n1 = np[nsize - 1]; 212 213 if (n1 >= d) { 214 n1 -= d; 215 most_significa 216 } 217 218 qp += qextra_limbs; 219 for (i = nsize - 2; i 220 udiv_qrnnd(qp[ 221 qp -= qextra_limbs; 222 223 for (i = qextra_limbs 224 udiv_qrnnd(qp[ 225 226 np[0] = n1; 227 } 228 break; 229 230 case 2: 231 { 232 mpi_size_t i; 233 mpi_limb_t n1, n0, n2; 234 mpi_limb_t d1, d0; 235 236 np += nsize - 2; 237 d1 = dp[1]; 238 d0 = dp[0]; 239 n1 = np[1]; 240 n0 = np[0]; 241 242 if (n1 >= d1 && (n1 > 243 sub_ddmmss(n1, 244 most_significa 245 } 246 247 for (i = qextra_limbs 248 mpi_limb_t q; 249 mpi_limb_t r; 250 251 if (i >= qextr 252 np--; 253 else 254 np[0] 255 256 if (n1 == d1) 257 /* Q s 258 * tre 259 * giv 260 q = ~( 261 262 r = n0 263 if (r 264 265 266 267 268 } 269 n1 = d 270 n0 = - 271 } else { 272 udiv_q 273 umul_p 274 } 275 276 n2 = np[0]; 277 q_test: 278 if (n1 > r || 279 /* The 280 q--; 281 sub_dd 282 r += d 283 if (r 284 285 } 286 287 qp[i] = q; 288 sub_ddmmss(n1, 289 } 290 np[1] = n1; 291 np[0] = n0; 292 } 293 break; 294 295 default: 296 { 297 mpi_size_t i; 298 mpi_limb_t dX, d1, n0; 299 300 np += nsize - dsize; 301 dX = dp[dsize - 1]; 302 d1 = dp[dsize - 2]; 303 n0 = np[dsize - 1]; 304 305 if (n0 >= dX) { 306 if (n0 > dX 307 || mpihelp 308 mpihel 309 n0 = n 310 most_s 311 } 312 } 313 314 for (i = qextra_limbs 315 mpi_limb_t q; 316 mpi_limb_t n1, 317 mpi_limb_t cy_ 318 319 if (i >= qextr 320 np--; 321 n2 = n 322 } else { 323 n2 = n 324 MPN_CO 325 np[0] 326 } 327 328 if (n0 == dX) 329 /* Thi 330 * the 331 q = ~( 332 } else { 333 mpi_li 334 335 udiv_q 336 umul_p 337 338 while 339 340 341 342 343 344 345 346 347 } 348 } 349 350 /* Possible op 351 * after the c 352 * could make 353 cy_limb = mpih 354 355 if (n2 != cy_l 356 mpihel 357 q--; 358 } 359 360 qp[i] = q; 361 n0 = np[dsize 362 } 363 } 364 } 365 366 return most_significant_q_limb; 367 } 368 369 /**************** 370 * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIV 371 * Write DIVIDEND_SIZE limbs of quotient at QU 372 * Return the single-limb remainder. 373 * There are no constraints on the value of th 374 * 375 * QUOT_PTR and DIVIDEND_PTR might point to th 376 */ 377 378 mpi_limb_t 379 mpihelp_divmod_1(mpi_ptr_t quot_ptr, 380 mpi_ptr_t dividend_ptr, mpi_si 381 mpi_limb_t divisor_limb) 382 { 383 mpi_size_t i; 384 mpi_limb_t n1, n0, r; 385 mpi_limb_t dummy __maybe_unused; 386 387 if (!dividend_size) 388 return 0; 389 390 /* If multiplication is much faster th 391 * dividend is large, pre-invert the d 392 * only multiplications in the inner l 393 * 394 * This test should be read: 395 * Does it ever help to use udiv_qrnnd 396 * && Does what we save compensate for 397 */ 398 if (UDIV_TIME > (2 * UMUL_TIME + 6) 399 && (UDIV_TIME - (2 * U 400 int normalization_steps; 401 402 normalization_steps = count_le 403 if (normalization_steps) { 404 mpi_limb_t divisor_lim 405 406 divisor_limb <<= norma 407 408 /* Compute (2**2N - 2* 409 * result is a (N+1)-b 410 * most significant bi 411 */ 412 /* Special case for DI 413 if (!(divisor_limb << 414 divisor_limb_i 415 else 416 udiv_qrnnd(div 417 418 419 n1 = dividend_ptr[divi 420 r = n1 >> (BITS_PER_MP 421 422 /* Possible optimizati 423 * if (r == 0 424 * && divisor_limb > ( 425 * 426 * ...one division les 427 */ 428 for (i = dividend_size 429 n0 = dividend_ 430 UDIV_QRNND_PRE 431 432 433 434 n1 = n0; 435 } 436 UDIV_QRNND_PREINV(quot 437 n1 << 438 diviso 439 return r >> normalizat 440 } else { 441 mpi_limb_t divisor_lim 442 443 /* Compute (2**2N - 2* 444 * result is a (N+1)-b 445 * most significant bi 446 */ 447 /* Special case for DI 448 if (!(divisor_limb << 449 divisor_limb_i 450 else 451 udiv_qrnnd(div 452 453 454 i = dividend_size - 1; 455 r = dividend_ptr[i]; 456 457 if (r >= divisor_limb) 458 r = 0; 459 else 460 quot_ptr[i--] 461 462 for ( ; i >= 0; i--) { 463 n0 = dividend_ 464 UDIV_QRNND_PRE 465 466 } 467 return r; 468 } 469 } else { 470 if (UDIV_NEEDS_NORMALIZATION) 471 int normalization_step 472 473 normalization_steps = 474 if (normalization_step 475 divisor_limb < 476 477 n1 = dividend_ 478 r = n1 >> (BIT 479 480 /* Possible op 481 * if (r == 0 482 * && divisor_ 483 * 484 * ...one divi 485 */ 486 for (i = divid 487 n0 = d 488 udiv_q 489 490 491 492 n1 = n 493 } 494 udiv_qrnnd(quo 495 496 497 return r >> no 498 } 499 } 500 /* No normalization needed, ei 501 * it, or because DIVISOR_LIMB 502 */ 503 i = dividend_size - 1; 504 r = dividend_ptr[i]; 505 506 if (r >= divisor_limb) 507 r = 0; 508 else 509 quot_ptr[i--] = 0; 510 511 for (; i >= 0; i--) { 512 n0 = dividend_ptr[i]; 513 udiv_qrnnd(quot_ptr[i] 514 } 515 return r; 516 } 517 } 518
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.