Changeset bd8dc07 in git
- Timestamp:
- Nov 4, 2016, 12:14:16 PM (7 years ago)
- Branches:
- (u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
- Children:
- 23ca7b7a1c132bcc62bab0c48743fe235bbe1764
- Parents:
- 446a69d5ed9308c77490b1c0193e81aba162e1fb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libpolys/coeffs/rmodulo2m.cc
r446a69 rbd8dc07 25 25 #ifdef HAVE_RINGS 26 26 27 number nr2mCopy (number a, const coeffs r);28 BOOLEAN nr2mGreaterZero (number k, const coeffs r);29 number nr2mMult (number a, number b, const coeffs r);30 number nr2mInit (long i, const coeffs r);31 long nr2mInt (number &n, const coeffs r);32 number nr2mAdd (number a, number b, const coeffs r);33 number nr2mSub (number a, number b, const coeffs r);34 void nr2mPower (number a, int i, number * result, const coeffs r);35 BOOLEAN nr2mIsZero (number a, const coeffs r);36 BOOLEAN nr2mIsOne (number a, const coeffs r);37 BOOLEAN nr2mIsMOne (number a, const coeffs r);38 BOOLEAN nr2mIsUnit (number a, const coeffs r);39 number nr2mGetUnit (number a, const coeffs r);40 number nr2mDiv (number a, number b, const coeffs r);41 number nr2mIntDiv (number a,number b, const coeffs r);42 number nr2mMod (number a,number b, const coeffs r);43 number nr2mNeg (number c, const coeffs r);44 number nr2mInvers (number c, const coeffs r);45 BOOLEAN nr2mGreater (number a, number b, const coeffs r);46 BOOLEAN nr2mDivBy (number a, number b, const coeffs r);47 int nr2mDivComp (number a, number b, const coeffs r);48 BOOLEAN nr2mEqual (number a, number b, const coeffs r);49 number nr2mLcm (number a, number b, const coeffs r);50 number nr2mGcd (number a, number b, const coeffs r);51 number nr2mExtGcd (number a, number b, number *s, number *t, const coeffs r);52 nMapFunc nr2mSetMap (const coeffs src, const coeffs dst);53 void nr2mWrite (number a, const coeffs r);54 const char * nr2mRead (const char *s, number *a, const coeffs r);55 char * nr2mName (number n, const coeffs r);56 void nr2mCoeffWrite (const coeffs r, BOOLEAN details);57 coeffs nr2mQuot1(number c, const coeffs r);58 #ifdef LDEBUG59 BOOLEAN nr2mDBTest (number a, const char *f, const int l, const coeffs r);60 #endif61 void nr2mSetExp(int c, const coeffs r);62 void nr2mInitExp(int c, const coeffs r);63 64 number nr2mMapQ(number from, const coeffs src, const coeffs dst);65 66 27 static inline number nr2mMultM(number a, number b, const coeffs r) 67 28 { … … 88 49 extern omBin gmp_nrz_bin; /* init in rintegers*/ 89 50 90 void nr2mCoeffWrite (const coeffs r, BOOLEAN /*details*/) 51 static char* nr2mCoeffName(const coeffs cf) 52 { 53 static char n2mCoeffName_buf[22]; 54 #ifdef SINGULAR_4_1 55 snprintf(n2mCoeffName_buf,21,"ZZ/(2^%lu)",cf->modExponent); 56 #else 57 snprintf(n2mCoeffName_buf,21,"integer,2,%lu",cf->modExponent); 58 #endif 59 return n2mCoeffName_buf; 60 } 61 62 static void nr2mCoeffWrite (const coeffs r, BOOLEAN /*details*/) 91 63 { 92 64 PrintS("// coeff. ring is : "); … … 94 66 } 95 67 96 BOOLEAN nr2mCoeffIsEqual(const coeffs r, n_coeffType n, void * p)68 static BOOLEAN nr2mCoeffIsEqual(const coeffs r, n_coeffType n, void * p) 97 69 { 98 70 if (n==n_Z2m) … … 117 89 } 118 90 119 coeffs nr2mQuot1(number c, const coeffs r)91 static coeffs nr2mQuot1(number c, const coeffs r) 120 92 { 121 93 coeffs rr; … … 158 130 } 159 131 132 /* TRUE iff 0 < k <= 2^m / 2 */ 133 static BOOLEAN nr2mGreaterZero(number k, const coeffs r) 134 { 135 if ((unsigned long)k == 0) return FALSE; 136 if ((unsigned long)k > ((r->mod2mMask >> 1) + 1)) return FALSE; 137 return TRUE; 138 } 139 140 /* 141 * Multiply two numbers 142 */ 143 static number nr2mMult(number a, number b, const coeffs r) 144 { 145 if (((unsigned long)a == 0) || ((unsigned long)b == 0)) 146 return (number)0; 147 else 148 return nr2mMultM(a, b, r); 149 } 150 160 151 static number nr2mAnn(number b, const coeffs r); 152 /* 153 * Give the smallest k, such that a * x = k = b * y has a solution 154 */ 155 static number nr2mLcm(number a, number b, const coeffs) 156 { 157 unsigned long res = 0; 158 if ((unsigned long)a == 0) a = (number) 1; 159 if ((unsigned long)b == 0) b = (number) 1; 160 while ((unsigned long)a % 2 == 0) 161 { 162 a = (number)((unsigned long)a / 2); 163 if ((unsigned long)b % 2 == 0) b = (number)((unsigned long)b / 2); 164 res++; 165 } 166 while ((unsigned long)b % 2 == 0) 167 { 168 b = (number)((unsigned long)b / 2); 169 res++; 170 } 171 return (number)(1L << res); // (2**res) 172 } 173 174 /* 175 * Give the largest k, such that a = x * k, b = y * k has 176 * a solution. 177 */ 178 static number nr2mGcd(number a, number b, const coeffs) 179 { 180 unsigned long res = 0; 181 if ((unsigned long)a == 0 && (unsigned long)b == 0) return (number)1; 182 while ((unsigned long)a % 2 == 0 && (unsigned long)b % 2 == 0) 183 { 184 a = (number)((unsigned long)a / 2); 185 b = (number)((unsigned long)b / 2); 186 res++; 187 } 188 // if ((unsigned long)b % 2 == 0) 189 // { 190 // return (number)((1L << res)); // * (unsigned long) a); // (2**res)*a a is a unit 191 // } 192 // else 193 // { 194 return (number)((1L << res)); // * (unsigned long) b); // (2**res)*b b is a unit 195 // } 196 } 197 198 /* assumes that 'a' is odd, i.e., a unit in Z/2^m, and computes 199 the extended gcd of 'a' and 2^m, in order to find some 's' 200 and 't' such that a * s + 2^m * t = gcd(a, 2^m) = 1; 201 this code will always find a positive 's' */ 202 static void specialXGCD(unsigned long& s, unsigned long a, const coeffs r) 203 { 204 mpz_ptr u = (mpz_ptr)omAlloc(sizeof(mpz_t)); 205 mpz_init_set_ui(u, a); 206 mpz_ptr u0 = (mpz_ptr)omAlloc(sizeof(mpz_t)); 207 mpz_init(u0); 208 mpz_ptr u1 = (mpz_ptr)omAlloc(sizeof(mpz_t)); 209 mpz_init_set_ui(u1, 1); 210 mpz_ptr u2 = (mpz_ptr)omAlloc(sizeof(mpz_t)); 211 mpz_init(u2); 212 mpz_ptr v = (mpz_ptr)omAlloc(sizeof(mpz_t)); 213 mpz_init_set_ui(v, r->mod2mMask); 214 mpz_add_ui(v, v, 1); /* now: v = 2^m */ 215 mpz_ptr v0 = (mpz_ptr)omAlloc(sizeof(mpz_t)); 216 mpz_init(v0); 217 mpz_ptr v1 = (mpz_ptr)omAlloc(sizeof(mpz_t)); 218 mpz_init(v1); 219 mpz_ptr v2 = (mpz_ptr)omAlloc(sizeof(mpz_t)); 220 mpz_init_set_ui(v2, 1); 221 mpz_ptr q = (mpz_ptr)omAlloc(sizeof(mpz_t)); 222 mpz_init(q); 223 mpz_ptr rr = (mpz_ptr)omAlloc(sizeof(mpz_t)); 224 mpz_init(rr); 225 226 while (mpz_cmp_ui(v, 0) != 0) /* i.e., while v != 0 */ 227 { 228 mpz_div(q, u, v); 229 mpz_mod(rr, u, v); 230 mpz_set(u, v); 231 mpz_set(v, rr); 232 mpz_set(u0, u2); 233 mpz_set(v0, v2); 234 mpz_mul(u2, u2, q); mpz_sub(u2, u1, u2); /* u2 = u1 - q * u2 */ 235 mpz_mul(v2, v2, q); mpz_sub(v2, v1, v2); /* v2 = v1 - q * v2 */ 236 mpz_set(u1, u0); 237 mpz_set(v1, v0); 238 } 239 240 while (mpz_cmp_ui(u1, 0) < 0) /* i.e., while u1 < 0 */ 241 { 242 /* we add 2^m = (2^m - 1) + 1 to u1: */ 243 mpz_add_ui(u1, u1, r->mod2mMask); 244 mpz_add_ui(u1, u1, 1); 245 } 246 s = mpz_get_ui(u1); /* now: 0 <= s <= 2^m - 1 */ 247 248 mpz_clear(u); omFree((ADDRESS)u); 249 mpz_clear(u0); omFree((ADDRESS)u0); 250 mpz_clear(u1); omFree((ADDRESS)u1); 251 mpz_clear(u2); omFree((ADDRESS)u2); 252 mpz_clear(v); omFree((ADDRESS)v); 253 mpz_clear(v0); omFree((ADDRESS)v0); 254 mpz_clear(v1); omFree((ADDRESS)v1); 255 mpz_clear(v2); omFree((ADDRESS)v2); 256 mpz_clear(q); omFree((ADDRESS)q); 257 mpz_clear(rr); omFree((ADDRESS)rr); 258 } 259 260 static unsigned long InvMod(unsigned long a, const coeffs r) 261 { 262 assume((unsigned long)a % 2 != 0); 263 unsigned long s; 264 specialXGCD(s, a, r); 265 return s; 266 } 267 268 static inline number nr2mInversM(number c, const coeffs r) 269 { 270 assume((unsigned long)c % 2 != 0); 271 // Table !!! 272 unsigned long inv; 273 inv = InvMod((unsigned long)c,r); 274 return (number)inv; 275 } 276 277 static number nr2mInvers(number c, const coeffs r) 278 { 279 if ((unsigned long)c % 2 == 0) 280 { 281 WerrorS("division by zero divisor"); 282 return (number)0; 283 } 284 return nr2mInversM(c, r); 285 } 286 287 /* 288 * Give the largest k, such that a = x * k, b = y * k has 289 * a solution. 290 */ 291 static number nr2mExtGcd(number a, number b, number *s, number *t, const coeffs r) 292 { 293 unsigned long res = 0; 294 if ((unsigned long)a == 0 && (unsigned long)b == 0) return (number)1; 295 while ((unsigned long)a % 2 == 0 && (unsigned long)b % 2 == 0) 296 { 297 a = (number)((unsigned long)a / 2); 298 b = (number)((unsigned long)b / 2); 299 res++; 300 } 301 if ((unsigned long)b % 2 == 0) 302 { 303 *t = NULL; 304 *s = nr2mInvers(a,r); 305 return (number)((1L << res)); // * (unsigned long) a); // (2**res)*a a is a unit 306 } 307 else 308 { 309 *s = NULL; 310 *t = nr2mInvers(b,r); 311 return (number)((1L << res)); // * (unsigned long) b); // (2**res)*b b is a unit 312 } 313 } 314 315 static void nr2mPower(number a, int i, number * result, const coeffs r) 316 { 317 if (i == 0) 318 { 319 *(unsigned long *)result = 1; 320 } 321 else if (i == 1) 322 { 323 *result = a; 324 } 325 else 326 { 327 nr2mPower(a, i-1, result, r); 328 *result = nr2mMultM(a, *result, r); 329 } 330 } 331 332 /* 333 * create a number from int 334 */ 335 static number nr2mInit(long i, const coeffs r) 336 { 337 if (i == 0) return (number)(unsigned long)i; 338 339 long ii = i; 340 unsigned long j = (unsigned long)1; 341 if (ii < 0) { j = r->mod2mMask; ii = -ii; } 342 unsigned long k = (unsigned long)ii; 343 k = k & r->mod2mMask; 344 /* now we have: i = j * k mod 2^m */ 345 return (number)nr2mMult((number)j, (number)k, r); 346 } 347 348 /* 349 * convert a number to an int in ]-k/2 .. k/2], 350 * where k = 2^m; i.e., an int in ]-2^(m-1) .. 2^(m-1)]; 351 */ 352 static long nr2mInt(number &n, const coeffs r) 353 { 354 unsigned long nn = (unsigned long)(unsigned long)n & r->mod2mMask; 355 unsigned long l = r->mod2mMask >> 1; l++; /* now: l = 2^(m-1) */ 356 if ((unsigned long)nn > l) 357 return (long)((unsigned long)nn - r->mod2mMask - 1); 358 else 359 return (long)((unsigned long)nn); 360 } 361 362 static number nr2mAdd(number a, number b, const coeffs r) 363 { 364 return nr2mAddM(a, b, r); 365 } 366 367 static number nr2mSub(number a, number b, const coeffs r) 368 { 369 return nr2mSubM(a, b, r); 370 } 371 372 static BOOLEAN nr2mIsUnit(number a, const coeffs) 373 { 374 return ((unsigned long)a % 2 == 1); 375 } 376 377 static number nr2mGetUnit(number k, const coeffs) 378 { 379 if (k == NULL) return (number)1; 380 unsigned long erg = (unsigned long)k; 381 while (erg % 2 == 0) erg = erg / 2; 382 return (number)erg; 383 } 384 385 static BOOLEAN nr2mIsZero(number a, const coeffs) 386 { 387 return 0 == (unsigned long)a; 388 } 389 390 static BOOLEAN nr2mIsOne(number a, const coeffs) 391 { 392 return 1 == (unsigned long)a; 393 } 394 395 static BOOLEAN nr2mIsMOne(number a, const coeffs r) 396 { 397 return ((r->mod2mMask == (unsigned long)a) &&(1L!=(long)a))/*for char 2^1*/; 398 } 399 400 static BOOLEAN nr2mEqual(number a, number b, const coeffs) 401 { 402 return (a == b); 403 } 404 405 static number nr2mDiv(number a, number b, const coeffs r) 406 { 407 if ((unsigned long)a == 0) return (number)0; 408 else if ((unsigned long)b % 2 == 0) 409 { 410 if ((unsigned long)b != 0) 411 { 412 while (((unsigned long)b % 2 == 0) && ((unsigned long)a % 2 == 0)) 413 { 414 a = (number)((unsigned long)a / 2); 415 b = (number)((unsigned long)b / 2); 416 } 417 } 418 if ((unsigned long)b % 2 == 0) 419 { 420 WerrorS("Division not possible, even by cancelling zero divisors."); 421 WerrorS("Result is integer division without remainder."); 422 return (number) ((unsigned long) a / (unsigned long) b); 423 } 424 } 425 return (number)nr2mMult(a, nr2mInversM(b,r),r); 426 } 427 428 /* Is 'a' divisible by 'b'? There are two cases: 429 1) a = 0 mod 2^m; then TRUE iff b = 0 or b is a power of 2 430 2) a, b <> 0; then TRUE iff b/gcd(a, b) is a unit mod 2^m */ 431 static BOOLEAN nr2mDivBy (number a, number b, const coeffs r) 432 { 433 if (a == NULL) 434 { 435 unsigned long c = r->mod2mMask + 1; 436 if (c != 0) /* i.e., if no overflow */ 437 return (c % (unsigned long)b) == 0; 438 else 439 { 440 /* overflow: we need to check whether b 441 is zero or a power of 2: */ 442 c = (unsigned long)b; 443 while (c != 0) 444 { 445 if ((c % 2) != 0) return FALSE; 446 c = c >> 1; 447 } 448 return TRUE; 449 } 450 } 451 else 452 { 453 number n = nr2mGcd(a, b, r); 454 n = nr2mDiv(b, n, r); 455 return nr2mIsUnit(n, r); 456 } 457 } 458 459 static BOOLEAN nr2mGreater(number a, number b, const coeffs r) 460 { 461 return nr2mDivBy(a, b,r); 462 } 463 464 static int nr2mDivComp(number as, number bs, const coeffs) 465 { 466 unsigned long a = (unsigned long)as; 467 unsigned long b = (unsigned long)bs; 468 assume(a != 0 && b != 0); 469 while (a % 2 == 0 && b % 2 == 0) 470 { 471 a = a / 2; 472 b = b / 2; 473 } 474 if (a % 2 == 0) 475 { 476 return -1; 477 } 478 else 479 { 480 if (b % 2 == 1) 481 { 482 return 2; 483 } 484 else 485 { 486 return 1; 487 } 488 } 489 } 490 491 static number nr2mMod(number a, number b, const coeffs r) 492 { 493 /* 494 We need to return the number rr which is uniquely determined by the 495 following two properties: 496 (1) 0 <= rr < |b| (with respect to '<' and '<=' performed in Z x Z) 497 (2) There exists some k in the integers Z such that a = k * b + rr. 498 Consider g := gcd(2^m, |b|). Note that then |b|/g is a unit in Z/2^m. 499 Now, there are three cases: 500 (a) g = 1 501 Then |b| is a unit in Z/2^m, i.e. |b| (and also b) divides a. 502 Thus rr = 0. 503 (b) g <> 1 and g divides a 504 Then a = (a/g) * (|b|/g)^(-1) * b (up to sign), i.e. again rr = 0. 505 (c) g <> 1 and g does not divide a 506 Let's denote the division with remainder of a by g as follows: 507 a = s * g + t. Then t = a - s * g = a - s * (|b|/g)^(-1) * |b| 508 fulfills (1) and (2), i.e. rr := t is the correct result. Hence 509 in this third case, rr is the remainder of division of a by g in Z. 510 This algorithm is the same as for the case Z/n, except that we may 511 compute the gcd of |b| and 2^m "by hand": We just extract the highest 512 power of 2 (<= 2^m) that is contained in b. 513 */ 514 assume((unsigned long) b != 0); 515 unsigned long g = 1; 516 unsigned long b_div = (unsigned long) b; 517 518 /* 519 * b_div is unsigned, so that (b_div < 0) evaluates false at compile-time 520 * 521 if (b_div < 0) b_div = -b_div; // b_div now represents |b|, BUT b_div is unsigned! 522 */ 523 524 unsigned long rr = 0; 525 while ((g < r->mod2mMask ) && (b_div > 0) && (b_div % 2 == 0)) 526 { 527 b_div = b_div >> 1; 528 g = g << 1; 529 } // g is now the gcd of 2^m and |b| 530 531 if (g != 1) rr = (unsigned long)a % g; 532 return (number)rr; 533 } 534 535 static number nr2mIntDiv(number a, number b, const coeffs r) 536 { 537 if ((unsigned long)a == 0) 538 { 539 if ((unsigned long)b == 0) 540 return (number)1; 541 if ((unsigned long)b == 1) 542 return (number)0; 543 unsigned long c = r->mod2mMask + 1; 544 if (c != 0) /* i.e., if no overflow */ 545 return (number)(c / (unsigned long)b); 546 else 547 { 548 /* overflow: c = 2^32 resp. 2^64, depending on platform */ 549 mpz_ptr cc = (mpz_ptr)omAlloc(sizeof(mpz_t)); 550 mpz_init_set_ui(cc, r->mod2mMask); mpz_add_ui(cc, cc, 1); 551 mpz_div_ui(cc, cc, (unsigned long)(unsigned long)b); 552 unsigned long s = mpz_get_ui(cc); 553 mpz_clear(cc); omFree((ADDRESS)cc); 554 return (number)(unsigned long)s; 555 } 556 } 557 else 558 { 559 if ((unsigned long)b == 0) 560 return (number)0; 561 return (number)((unsigned long) a / (unsigned long) b); 562 } 563 } 564 565 static number nr2mAnn(number b, const coeffs r) 566 { 567 if ((unsigned long)b == 0) 568 return NULL; 569 if ((unsigned long)b == 1) 570 return NULL; 571 unsigned long c = r->mod2mMask + 1; 572 if (c != 0) /* i.e., if no overflow */ 573 return (number)(c / (unsigned long)b); 574 else 575 { 576 /* overflow: c = 2^32 resp. 2^64, depending on platform */ 577 mpz_ptr cc = (mpz_ptr)omAlloc(sizeof(mpz_t)); 578 mpz_init_set_ui(cc, r->mod2mMask); mpz_add_ui(cc, cc, 1); 579 mpz_div_ui(cc, cc, (unsigned long)(unsigned long)b); 580 unsigned long s = mpz_get_ui(cc); 581 mpz_clear(cc); omFree((ADDRESS)cc); 582 return (number)(unsigned long)s; 583 } 584 } 585 586 static number nr2mNeg(number c, const coeffs r) 587 { 588 if ((unsigned long)c == 0) return c; 589 return nr2mNegM(c, r); 590 } 591 592 static number nr2mMapMachineInt(number from, const coeffs /*src*/, const coeffs dst) 593 { 594 unsigned long i = ((unsigned long)from) % dst->mod2mMask ; 595 return (number)i; 596 } 597 598 static number nr2mMapProject(number from, const coeffs /*src*/, const coeffs dst) 599 { 600 unsigned long i = ((unsigned long)from) % (dst->mod2mMask + 1); 601 return (number)i; 602 } 603 604 number nr2mMapZp(number from, const coeffs /*src*/, const coeffs dst) 605 { 606 unsigned long j = (unsigned long)1; 607 long ii = (long)from; 608 if (ii < 0) { j = dst->mod2mMask; ii = -ii; } 609 unsigned long i = (unsigned long)ii; 610 i = i & dst->mod2mMask; 611 /* now we have: from = j * i mod 2^m */ 612 return (number)nr2mMult((number)i, (number)j, dst); 613 } 614 615 static number nr2mMapGMP(number from, const coeffs /*src*/, const coeffs dst) 616 { 617 mpz_ptr erg = (mpz_ptr)omAllocBin(gmp_nrz_bin); 618 mpz_init(erg); 619 mpz_ptr k = (mpz_ptr)omAlloc(sizeof(mpz_t)); 620 mpz_init_set_ui(k, dst->mod2mMask); 621 622 mpz_and(erg, (mpz_ptr)from, k); 623 number res = (number) mpz_get_ui(erg); 624 625 mpz_clear(erg); omFree((ADDRESS)erg); 626 mpz_clear(k); omFree((ADDRESS)k); 627 628 return (number)res; 629 } 630 631 static number nr2mMapQ(number from, const coeffs src, const coeffs dst) 632 { 633 mpz_ptr gmp = (mpz_ptr)omAllocBin(gmp_nrz_bin); 634 mpz_init(gmp); 635 nlGMP(from, (number)gmp, src); // FIXME? TODO? // extern void nlGMP(number &i, number n, const coeffs r); // to be replaced with n_MPZ(erg, from, src); // ? 636 number res=nr2mMapGMP((number)gmp,src,dst); 637 mpz_clear(gmp); omFree((ADDRESS)gmp); 638 return res; 639 } 640 641 static number nr2mMapZ(number from, const coeffs src, const coeffs dst) 642 { 643 if (SR_HDL(from) & SR_INT) 644 { 645 long f_i=SR_TO_INT(from); 646 return nr2mInit(f_i,dst); 647 } 648 return nr2mMapGMP(from,src,dst); 649 } 650 651 static nMapFunc nr2mSetMap(const coeffs src, const coeffs dst) 652 { 653 if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src) 654 && (src->mod2mMask == dst->mod2mMask)) 655 { 656 return ndCopyMap; 657 } 658 if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src) 659 && (src->mod2mMask < dst->mod2mMask)) 660 { /* i.e. map an integer mod 2^s into Z mod 2^t, where t < s */ 661 return nr2mMapMachineInt; 662 } 663 if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src) 664 && (src->mod2mMask > dst->mod2mMask)) 665 { /* i.e. map an integer mod 2^s into Z mod 2^t, where t > s */ 666 // to be done 667 return nr2mMapProject; 668 } 669 if ((src->rep==n_rep_gmp) && nCoeff_is_Ring_Z(src)) 670 { 671 return nr2mMapGMP; 672 } 673 if ((src->rep==n_rep_gap_gmp) /*&& nCoeff_is_Ring_Z(src)*/) 674 { 675 return nr2mMapZ; 676 } 677 if ((src->rep==n_rep_gap_rat) && (nCoeff_is_Q(src)||nCoeff_is_Ring_Z(src))) 678 { 679 return nr2mMapQ; 680 } 681 if ((src->rep==n_rep_int) && nCoeff_is_Zp(src) && (src->ch == 2)) 682 { 683 return nr2mMapZp; 684 } 685 if ((src->rep==n_rep_gmp) && 686 (nCoeff_is_Ring_PtoM(src) || nCoeff_is_Ring_ModN(src))) 687 { 688 if (mpz_divisible_2exp_p(src->modNumber,dst->modExponent)) 689 return nr2mMapGMP; 690 } 691 return NULL; // default 692 } 693 694 /* 695 * set the exponent 696 */ 697 698 static void nr2mSetExp(int m, coeffs r) 699 { 700 if (m > 1) 701 { 702 /* we want mod2mMask to be the bit pattern 703 '111..1' consisting of m one's: */ 704 r->modExponent= m; 705 r->mod2mMask = 1; 706 for (int i = 1; i < m; i++) r->mod2mMask = (r->mod2mMask << 1) + 1; 707 } 708 else 709 { 710 r->modExponent= 2; 711 /* code unexpectedly called with m = 1; we continue with m = 2: */ 712 r->mod2mMask = 3; /* i.e., '11' in binary representation */ 713 } 714 } 715 716 static void nr2mInitExp(int m, coeffs r) 717 { 718 nr2mSetExp(m, r); 719 if (m < 2) 720 WarnS("nr2mInitExp unexpectedly called with m = 1 (we continue with Z/2^2"); 721 } 722 723 #ifdef LDEBUG 724 static BOOLEAN nr2mDBTest (number a, const char *, const int, const coeffs r) 725 { 726 //if ((unsigned long)a < 0) return FALSE; // is unsigned! 727 if (((unsigned long)a & r->mod2mMask) != (unsigned long)a) return FALSE; 728 return TRUE; 729 } 730 #endif 731 732 static void nr2mWrite (number a, const coeffs r) 733 { 734 long i = nr2mInt(a, r); 735 StringAppend("%ld", i); 736 } 737 738 static const char* nr2mEati(const char *s, int *i, const coeffs r) 739 { 740 741 if (((*s) >= '0') && ((*s) <= '9')) 742 { 743 (*i) = 0; 744 do 745 { 746 (*i) *= 10; 747 (*i) += *s++ - '0'; 748 if ((*i) >= (MAX_INT_VAL / 10)) (*i) = (*i) & r->mod2mMask; 749 } 750 while (((*s) >= '0') && ((*s) <= '9')); 751 (*i) = (*i) & r->mod2mMask; 752 } 753 else (*i) = 1; 754 return s; 755 } 756 757 static const char * nr2mRead (const char *s, number *a, const coeffs r) 758 { 759 int z; 760 int n=1; 761 762 s = nr2mEati(s, &z,r); 763 if ((*s) == '/') 764 { 765 s++; 766 s = nr2mEati(s, &n,r); 767 } 768 if (n == 1) 769 *a = (number)(long)z; 770 else 771 *a = nr2mDiv((number)(long)z,(number)(long)n,r); 772 return s; 773 } 774 161 775 /* for initializing function pointers */ 162 776 BOOLEAN nr2mInitChar (coeffs r, void* p) … … 213 827 r->cfExtGcd = nr2mExtGcd; 214 828 r->cfCoeffWrite = nr2mCoeffWrite; 829 r->cfCoeffName = nr2mCoeffName; 215 830 r->cfQuot1 = nr2mQuot1; 216 831 #ifdef LDEBUG … … 221 836 } 222 837 223 /*224 * Multiply two numbers225 */226 number nr2mMult(number a, number b, const coeffs r)227 {228 if (((unsigned long)a == 0) || ((unsigned long)b == 0))229 return (number)0;230 else231 return nr2mMultM(a, b, r);232 }233 234 /*235 * Give the smallest k, such that a * x = k = b * y has a solution236 */237 number nr2mLcm(number a, number b, const coeffs)238 {239 unsigned long res = 0;240 if ((unsigned long)a == 0) a = (number) 1;241 if ((unsigned long)b == 0) b = (number) 1;242 while ((unsigned long)a % 2 == 0)243 {244 a = (number)((unsigned long)a / 2);245 if ((unsigned long)b % 2 == 0) b = (number)((unsigned long)b / 2);246 res++;247 }248 while ((unsigned long)b % 2 == 0)249 {250 b = (number)((unsigned long)b / 2);251 res++;252 }253 return (number)(1L << res); // (2**res)254 }255 256 /*257 * Give the largest k, such that a = x * k, b = y * k has258 * a solution.259 */260 number nr2mGcd(number a, number b, const coeffs)261 {262 unsigned long res = 0;263 if ((unsigned long)a == 0 && (unsigned long)b == 0) return (number)1;264 while ((unsigned long)a % 2 == 0 && (unsigned long)b % 2 == 0)265 {266 a = (number)((unsigned long)a / 2);267 b = (number)((unsigned long)b / 2);268 res++;269 }270 // if ((unsigned long)b % 2 == 0)271 // {272 // return (number)((1L << res)); // * (unsigned long) a); // (2**res)*a a is a unit273 // }274 // else275 // {276 return (number)((1L << res)); // * (unsigned long) b); // (2**res)*b b is a unit277 // }278 }279 280 /*281 * Give the largest k, such that a = x * k, b = y * k has282 * a solution.283 */284 number nr2mExtGcd(number a, number b, number *s, number *t, const coeffs r)285 {286 unsigned long res = 0;287 if ((unsigned long)a == 0 && (unsigned long)b == 0) return (number)1;288 while ((unsigned long)a % 2 == 0 && (unsigned long)b % 2 == 0)289 {290 a = (number)((unsigned long)a / 2);291 b = (number)((unsigned long)b / 2);292 res++;293 }294 if ((unsigned long)b % 2 == 0)295 {296 *t = NULL;297 *s = nr2mInvers(a,r);298 return (number)((1L << res)); // * (unsigned long) a); // (2**res)*a a is a unit299 }300 else301 {302 *s = NULL;303 *t = nr2mInvers(b,r);304 return (number)((1L << res)); // * (unsigned long) b); // (2**res)*b b is a unit305 }306 }307 308 void nr2mPower(number a, int i, number * result, const coeffs r)309 {310 if (i == 0)311 {312 *(unsigned long *)result = 1;313 }314 else if (i == 1)315 {316 *result = a;317 }318 else319 {320 nr2mPower(a, i-1, result, r);321 *result = nr2mMultM(a, *result, r);322 }323 }324 325 /*326 * create a number from int327 */328 number nr2mInit(long i, const coeffs r)329 {330 if (i == 0) return (number)(unsigned long)i;331 332 long ii = i;333 unsigned long j = (unsigned long)1;334 if (ii < 0) { j = r->mod2mMask; ii = -ii; }335 unsigned long k = (unsigned long)ii;336 k = k & r->mod2mMask;337 /* now we have: i = j * k mod 2^m */338 return (number)nr2mMult((number)j, (number)k, r);339 }340 341 /*342 * convert a number to an int in ]-k/2 .. k/2],343 * where k = 2^m; i.e., an int in ]-2^(m-1) .. 2^(m-1)];344 */345 long nr2mInt(number &n, const coeffs r)346 {347 unsigned long nn = (unsigned long)(unsigned long)n & r->mod2mMask;348 unsigned long l = r->mod2mMask >> 1; l++; /* now: l = 2^(m-1) */349 if ((unsigned long)nn > l)350 return (long)((unsigned long)nn - r->mod2mMask - 1);351 else352 return (long)((unsigned long)nn);353 }354 355 number nr2mAdd(number a, number b, const coeffs r)356 {357 return nr2mAddM(a, b, r);358 }359 360 number nr2mSub(number a, number b, const coeffs r)361 {362 return nr2mSubM(a, b, r);363 }364 365 BOOLEAN nr2mIsUnit(number a, const coeffs)366 {367 return ((unsigned long)a % 2 == 1);368 }369 370 number nr2mGetUnit(number k, const coeffs)371 {372 if (k == NULL) return (number)1;373 unsigned long erg = (unsigned long)k;374 while (erg % 2 == 0) erg = erg / 2;375 return (number)erg;376 }377 378 BOOLEAN nr2mIsZero(number a, const coeffs)379 {380 return 0 == (unsigned long)a;381 }382 383 BOOLEAN nr2mIsOne(number a, const coeffs)384 {385 return 1 == (unsigned long)a;386 }387 388 BOOLEAN nr2mIsMOne(number a, const coeffs r)389 {390 return ((r->mod2mMask == (unsigned long)a) &&(1L!=(long)a))/*for char 2^1*/;391 }392 393 BOOLEAN nr2mEqual(number a, number b, const coeffs)394 {395 return (a == b);396 }397 398 BOOLEAN nr2mGreater(number a, number b, const coeffs r)399 {400 return nr2mDivBy(a, b,r);401 }402 403 /* Is 'a' divisible by 'b'? There are two cases:404 1) a = 0 mod 2^m; then TRUE iff b = 0 or b is a power of 2405 2) a, b <> 0; then TRUE iff b/gcd(a, b) is a unit mod 2^m */406 BOOLEAN nr2mDivBy (number a, number b, const coeffs r)407 {408 if (a == NULL)409 {410 unsigned long c = r->mod2mMask + 1;411 if (c != 0) /* i.e., if no overflow */412 return (c % (unsigned long)b) == 0;413 else414 {415 /* overflow: we need to check whether b416 is zero or a power of 2: */417 c = (unsigned long)b;418 while (c != 0)419 {420 if ((c % 2) != 0) return FALSE;421 c = c >> 1;422 }423 return TRUE;424 }425 }426 else427 {428 number n = nr2mGcd(a, b, r);429 n = nr2mDiv(b, n, r);430 return nr2mIsUnit(n, r);431 }432 }433 434 int nr2mDivComp(number as, number bs, const coeffs)435 {436 unsigned long a = (unsigned long)as;437 unsigned long b = (unsigned long)bs;438 assume(a != 0 && b != 0);439 while (a % 2 == 0 && b % 2 == 0)440 {441 a = a / 2;442 b = b / 2;443 }444 if (a % 2 == 0)445 {446 return -1;447 }448 else449 {450 if (b % 2 == 1)451 {452 return 2;453 }454 else455 {456 return 1;457 }458 }459 }460 461 /* TRUE iff 0 < k <= 2^m / 2 */462 BOOLEAN nr2mGreaterZero(number k, const coeffs r)463 {464 if ((unsigned long)k == 0) return FALSE;465 if ((unsigned long)k > ((r->mod2mMask >> 1) + 1)) return FALSE;466 return TRUE;467 }468 469 /* assumes that 'a' is odd, i.e., a unit in Z/2^m, and computes470 the extended gcd of 'a' and 2^m, in order to find some 's'471 and 't' such that a * s + 2^m * t = gcd(a, 2^m) = 1;472 this code will always find a positive 's' */473 void specialXGCD(unsigned long& s, unsigned long a, const coeffs r)474 {475 mpz_ptr u = (mpz_ptr)omAlloc(sizeof(mpz_t));476 mpz_init_set_ui(u, a);477 mpz_ptr u0 = (mpz_ptr)omAlloc(sizeof(mpz_t));478 mpz_init(u0);479 mpz_ptr u1 = (mpz_ptr)omAlloc(sizeof(mpz_t));480 mpz_init_set_ui(u1, 1);481 mpz_ptr u2 = (mpz_ptr)omAlloc(sizeof(mpz_t));482 mpz_init(u2);483 mpz_ptr v = (mpz_ptr)omAlloc(sizeof(mpz_t));484 mpz_init_set_ui(v, r->mod2mMask);485 mpz_add_ui(v, v, 1); /* now: v = 2^m */486 mpz_ptr v0 = (mpz_ptr)omAlloc(sizeof(mpz_t));487 mpz_init(v0);488 mpz_ptr v1 = (mpz_ptr)omAlloc(sizeof(mpz_t));489 mpz_init(v1);490 mpz_ptr v2 = (mpz_ptr)omAlloc(sizeof(mpz_t));491 mpz_init_set_ui(v2, 1);492 mpz_ptr q = (mpz_ptr)omAlloc(sizeof(mpz_t));493 mpz_init(q);494 mpz_ptr rr = (mpz_ptr)omAlloc(sizeof(mpz_t));495 mpz_init(rr);496 497 while (mpz_cmp_ui(v, 0) != 0) /* i.e., while v != 0 */498 {499 mpz_div(q, u, v);500 mpz_mod(rr, u, v);501 mpz_set(u, v);502 mpz_set(v, rr);503 mpz_set(u0, u2);504 mpz_set(v0, v2);505 mpz_mul(u2, u2, q); mpz_sub(u2, u1, u2); /* u2 = u1 - q * u2 */506 mpz_mul(v2, v2, q); mpz_sub(v2, v1, v2); /* v2 = v1 - q * v2 */507 mpz_set(u1, u0);508 mpz_set(v1, v0);509 }510 511 while (mpz_cmp_ui(u1, 0) < 0) /* i.e., while u1 < 0 */512 {513 /* we add 2^m = (2^m - 1) + 1 to u1: */514 mpz_add_ui(u1, u1, r->mod2mMask);515 mpz_add_ui(u1, u1, 1);516 }517 s = mpz_get_ui(u1); /* now: 0 <= s <= 2^m - 1 */518 519 mpz_clear(u); omFree((ADDRESS)u);520 mpz_clear(u0); omFree((ADDRESS)u0);521 mpz_clear(u1); omFree((ADDRESS)u1);522 mpz_clear(u2); omFree((ADDRESS)u2);523 mpz_clear(v); omFree((ADDRESS)v);524 mpz_clear(v0); omFree((ADDRESS)v0);525 mpz_clear(v1); omFree((ADDRESS)v1);526 mpz_clear(v2); omFree((ADDRESS)v2);527 mpz_clear(q); omFree((ADDRESS)q);528 mpz_clear(rr); omFree((ADDRESS)rr);529 }530 531 unsigned long InvMod(unsigned long a, const coeffs r)532 {533 assume((unsigned long)a % 2 != 0);534 unsigned long s;535 specialXGCD(s, a, r);536 return s;537 }538 //#endif539 540 inline number nr2mInversM(number c, const coeffs r)541 {542 assume((unsigned long)c % 2 != 0);543 // Table !!!544 unsigned long inv;545 inv = InvMod((unsigned long)c,r);546 return (number)inv;547 }548 549 number nr2mDiv(number a, number b, const coeffs r)550 {551 if ((unsigned long)a == 0) return (number)0;552 else if ((unsigned long)b % 2 == 0)553 {554 if ((unsigned long)b != 0)555 {556 while (((unsigned long)b % 2 == 0) && ((unsigned long)a % 2 == 0))557 {558 a = (number)((unsigned long)a / 2);559 b = (number)((unsigned long)b / 2);560 }561 }562 if ((unsigned long)b % 2 == 0)563 {564 WerrorS("Division not possible, even by cancelling zero divisors.");565 WerrorS("Result is integer division without remainder.");566 return (number) ((unsigned long) a / (unsigned long) b);567 }568 }569 return (number)nr2mMult(a, nr2mInversM(b,r),r);570 }571 572 number nr2mMod(number a, number b, const coeffs r)573 {574 /*575 We need to return the number rr which is uniquely determined by the576 following two properties:577 (1) 0 <= rr < |b| (with respect to '<' and '<=' performed in Z x Z)578 (2) There exists some k in the integers Z such that a = k * b + rr.579 Consider g := gcd(2^m, |b|). Note that then |b|/g is a unit in Z/2^m.580 Now, there are three cases:581 (a) g = 1582 Then |b| is a unit in Z/2^m, i.e. |b| (and also b) divides a.583 Thus rr = 0.584 (b) g <> 1 and g divides a585 Then a = (a/g) * (|b|/g)^(-1) * b (up to sign), i.e. again rr = 0.586 (c) g <> 1 and g does not divide a587 Let's denote the division with remainder of a by g as follows:588 a = s * g + t. Then t = a - s * g = a - s * (|b|/g)^(-1) * |b|589 fulfills (1) and (2), i.e. rr := t is the correct result. Hence590 in this third case, rr is the remainder of division of a by g in Z.591 This algorithm is the same as for the case Z/n, except that we may592 compute the gcd of |b| and 2^m "by hand": We just extract the highest593 power of 2 (<= 2^m) that is contained in b.594 */595 assume((unsigned long) b != 0);596 unsigned long g = 1;597 unsigned long b_div = (unsigned long) b;598 599 /*600 * b_div is unsigned, so that (b_div < 0) evaluates false at compile-time601 *602 if (b_div < 0) b_div = -b_div; // b_div now represents |b|, BUT b_div is unsigned!603 */604 605 unsigned long rr = 0;606 while ((g < r->mod2mMask ) && (b_div > 0) && (b_div % 2 == 0))607 {608 b_div = b_div >> 1;609 g = g << 1;610 } // g is now the gcd of 2^m and |b|611 612 if (g != 1) rr = (unsigned long)a % g;613 return (number)rr;614 }615 616 number nr2mIntDiv(number a, number b, const coeffs r)617 {618 if ((unsigned long)a == 0)619 {620 if ((unsigned long)b == 0)621 return (number)1;622 if ((unsigned long)b == 1)623 return (number)0;624 unsigned long c = r->mod2mMask + 1;625 if (c != 0) /* i.e., if no overflow */626 return (number)(c / (unsigned long)b);627 else628 {629 /* overflow: c = 2^32 resp. 2^64, depending on platform */630 mpz_ptr cc = (mpz_ptr)omAlloc(sizeof(mpz_t));631 mpz_init_set_ui(cc, r->mod2mMask); mpz_add_ui(cc, cc, 1);632 mpz_div_ui(cc, cc, (unsigned long)(unsigned long)b);633 unsigned long s = mpz_get_ui(cc);634 mpz_clear(cc); omFree((ADDRESS)cc);635 return (number)(unsigned long)s;636 }637 }638 else639 {640 if ((unsigned long)b == 0)641 return (number)0;642 return (number)((unsigned long) a / (unsigned long) b);643 }644 }645 646 static number nr2mAnn(number b, const coeffs r)647 {648 if ((unsigned long)b == 0)649 return NULL;650 if ((unsigned long)b == 1)651 return NULL;652 unsigned long c = r->mod2mMask + 1;653 if (c != 0) /* i.e., if no overflow */654 return (number)(c / (unsigned long)b);655 else656 {657 /* overflow: c = 2^32 resp. 2^64, depending on platform */658 mpz_ptr cc = (mpz_ptr)omAlloc(sizeof(mpz_t));659 mpz_init_set_ui(cc, r->mod2mMask); mpz_add_ui(cc, cc, 1);660 mpz_div_ui(cc, cc, (unsigned long)(unsigned long)b);661 unsigned long s = mpz_get_ui(cc);662 mpz_clear(cc); omFree((ADDRESS)cc);663 return (number)(unsigned long)s;664 }665 }666 667 number nr2mInvers(number c, const coeffs r)668 {669 if ((unsigned long)c % 2 == 0)670 {671 WerrorS("division by zero divisor");672 return (number)0;673 }674 return nr2mInversM(c, r);675 }676 677 number nr2mNeg(number c, const coeffs r)678 {679 if ((unsigned long)c == 0) return c;680 return nr2mNegM(c, r);681 }682 683 number nr2mMapMachineInt(number from, const coeffs /*src*/, const coeffs dst)684 {685 unsigned long i = ((unsigned long)from) % dst->mod2mMask ;686 return (number)i;687 }688 689 number nr2mMapProject(number from, const coeffs /*src*/, const coeffs dst)690 {691 unsigned long i = ((unsigned long)from) % (dst->mod2mMask + 1);692 return (number)i;693 }694 695 number nr2mMapZp(number from, const coeffs /*src*/, const coeffs dst)696 {697 unsigned long j = (unsigned long)1;698 long ii = (long)from;699 if (ii < 0) { j = dst->mod2mMask; ii = -ii; }700 unsigned long i = (unsigned long)ii;701 i = i & dst->mod2mMask;702 /* now we have: from = j * i mod 2^m */703 return (number)nr2mMult((number)i, (number)j, dst);704 }705 706 number nr2mMapGMP(number from, const coeffs /*src*/, const coeffs dst)707 {708 mpz_ptr erg = (mpz_ptr)omAllocBin(gmp_nrz_bin);709 mpz_init(erg);710 mpz_ptr k = (mpz_ptr)omAlloc(sizeof(mpz_t));711 mpz_init_set_ui(k, dst->mod2mMask);712 713 mpz_and(erg, (mpz_ptr)from, k);714 number res = (number) mpz_get_ui(erg);715 716 mpz_clear(erg); omFree((ADDRESS)erg);717 mpz_clear(k); omFree((ADDRESS)k);718 719 return (number)res;720 }721 722 number nr2mMapQ(number from, const coeffs src, const coeffs dst)723 {724 mpz_ptr gmp = (mpz_ptr)omAllocBin(gmp_nrz_bin);725 mpz_init(gmp);726 nlGMP(from, (number)gmp, src); // FIXME? TODO? // extern void nlGMP(number &i, number n, const coeffs r); // to be replaced with n_MPZ(erg, from, src); // ?727 number res=nr2mMapGMP((number)gmp,src,dst);728 mpz_clear(gmp); omFree((ADDRESS)gmp);729 return res;730 }731 732 number nr2mMapZ(number from, const coeffs src, const coeffs dst)733 {734 if (SR_HDL(from) & SR_INT)735 {736 long f_i=SR_TO_INT(from);737 return nr2mInit(f_i,dst);738 }739 return nr2mMapGMP(from,src,dst);740 }741 742 nMapFunc nr2mSetMap(const coeffs src, const coeffs dst)743 {744 if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src)745 && (src->mod2mMask == dst->mod2mMask))746 {747 return ndCopyMap;748 }749 if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src)750 && (src->mod2mMask < dst->mod2mMask))751 { /* i.e. map an integer mod 2^s into Z mod 2^t, where t < s */752 return nr2mMapMachineInt;753 }754 if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src)755 && (src->mod2mMask > dst->mod2mMask))756 { /* i.e. map an integer mod 2^s into Z mod 2^t, where t > s */757 // to be done758 return nr2mMapProject;759 }760 if ((src->rep==n_rep_gmp) && nCoeff_is_Ring_Z(src))761 {762 return nr2mMapGMP;763 }764 if ((src->rep==n_rep_gap_gmp) /*&& nCoeff_is_Ring_Z(src)*/)765 {766 return nr2mMapZ;767 }768 if ((src->rep==n_rep_gap_rat) && (nCoeff_is_Q(src)||nCoeff_is_Ring_Z(src)))769 {770 return nr2mMapQ;771 }772 if ((src->rep==n_rep_int) && nCoeff_is_Zp(src) && (src->ch == 2))773 {774 return nr2mMapZp;775 }776 if ((src->rep==n_rep_gmp) &&777 (nCoeff_is_Ring_PtoM(src) || nCoeff_is_Ring_ModN(src)))778 {779 if (mpz_divisible_2exp_p(src->modNumber,dst->modExponent))780 return nr2mMapGMP;781 }782 return NULL; // default783 }784 785 /*786 * set the exponent787 */788 789 void nr2mSetExp(int m, coeffs r)790 {791 if (m > 1)792 {793 /* we want mod2mMask to be the bit pattern794 '111..1' consisting of m one's: */795 r->modExponent= m;796 r->mod2mMask = 1;797 for (int i = 1; i < m; i++) r->mod2mMask = (r->mod2mMask << 1) + 1;798 }799 else800 {801 r->modExponent= 2;802 /* code unexpectedly called with m = 1; we continue with m = 2: */803 r->mod2mMask = 3; /* i.e., '11' in binary representation */804 }805 }806 807 void nr2mInitExp(int m, coeffs r)808 {809 nr2mSetExp(m, r);810 if (m < 2)811 WarnS("nr2mInitExp unexpectedly called with m = 1 (we continue with Z/2^2");812 }813 814 #ifdef LDEBUG815 BOOLEAN nr2mDBTest (number a, const char *, const int, const coeffs r)816 {817 //if ((unsigned long)a < 0) return FALSE; // is unsigned!818 if (((unsigned long)a & r->mod2mMask) != (unsigned long)a) return FALSE;819 return TRUE;820 }821 #endif822 823 void nr2mWrite (number a, const coeffs r)824 {825 long i = nr2mInt(a, r);826 StringAppend("%ld", i);827 }828 829 static const char* nr2mEati(const char *s, int *i, const coeffs r)830 {831 832 if (((*s) >= '0') && ((*s) <= '9'))833 {834 (*i) = 0;835 do836 {837 (*i) *= 10;838 (*i) += *s++ - '0';839 if ((*i) >= (MAX_INT_VAL / 10)) (*i) = (*i) & r->mod2mMask;840 }841 while (((*s) >= '0') && ((*s) <= '9'));842 (*i) = (*i) & r->mod2mMask;843 }844 else (*i) = 1;845 return s;846 }847 848 const char * nr2mRead (const char *s, number *a, const coeffs r)849 {850 int z;851 int n=1;852 853 s = nr2mEati(s, &z,r);854 if ((*s) == '/')855 {856 s++;857 s = nr2mEati(s, &n,r);858 }859 if (n == 1)860 *a = (number)(long)z;861 else862 *a = nr2mDiv((number)(long)z,(number)(long)n,r);863 return s;864 }865 838 #endif 866 839 /* #ifdef HAVE_RINGS */
Note: See TracChangeset
for help on using the changeset viewer.