Changeset 555b03 in git
- Timestamp:
- Aug 30, 2010, 4:29:37 PM (13 years ago)
- Branches:
- (u'jengelh-datetime', 'ceac47cbc86fe4a15902392bdbb9bd2ae0ea02c6')(u'spielwiese', 'a657104b677b4c461d018cbf3204d72d34ad66a9')
- Children:
- 5e016e27b98b70a42edca584335f57145f3a8dc0
- Parents:
- f9bb6862e22f14387a67696733ad2d1024a69ade
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/iparith.cc
rf9bb68 r555b03 3187 3187 static BOOLEAN jjPFAC2(leftv res, leftv u, leftv v) 3188 3188 { 3189 number m = (number)u->Data(); 3190 int bound = (int)(long)v->Data(); 3191 number n; 3192 if ((u->Typ() == BIGINT_CMD) 3193 || ((u->Typ()==NUMBER_CMD) && rField_is_Q())) 3194 { 3195 n = nlCopy(m); 3189 number n1; number n2; number temp; int i; 3190 3191 if ((u->Typ() == BIGINT_CMD) || 3192 ((u->Typ() == NUMBER_CMD) && rField_is_Q())) 3193 { 3194 temp = (number)u->Data(); 3195 n1 = nlCopy(temp); 3196 } 3197 else if (u->Typ() == INT_CMD) 3198 { 3199 i = (int)(long)u->Data(); 3200 n1 = nlInit(i, NULL); 3196 3201 } 3197 3202 else 3198 3203 { 3199 /* then, we expect some other type of number inside m; 3200 it needs to be converted to bigint; we do this via 'int' */ 3201 int i = n_Int(m, currRing); 3202 n = nlInit(i, NULL); 3203 } 3204 lists l = primeFactorisation(n, bound); 3205 nlDelete(&n,NULL); 3206 res->data=(char*)l; 3204 WerrorS("wrong type: expected int, bigint, or number as 1st argument"); 3205 return TRUE; 3206 } 3207 3208 if ((v->Typ() == BIGINT_CMD) || 3209 ((v->Typ() == NUMBER_CMD) && rField_is_Q())) 3210 { 3211 temp = (number)v->Data(); 3212 n2 = nlCopy(temp); 3213 } 3214 else if (v->Typ() == INT_CMD) 3215 { 3216 i = (int)(long)v->Data(); 3217 n2 = nlInit(i, NULL); 3218 } 3219 else 3220 { 3221 WerrorS("wrong type: expected int, bigint, or number as 2nd argument"); 3222 return TRUE; 3223 } 3224 3225 lists l = primeFactorisation(n1, n2); 3226 nlDelete(&n1, NULL); nlDelete(&n2, NULL); 3227 res->data = (char*)l; 3207 3228 return FALSE; 3208 3229 } … … 3721 3742 ,{jjRES, MRES_CMD, RESOLUTION_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} 3722 3743 //,{nuMPResMat, MPRES_CMD, MODUL_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} 3723 ,{jjPFAC2, PFAC_CMD, LIST_CMD, BIGINT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} 3724 ,{jjPFAC2, PFAC_CMD, LIST_CMD, NUMBER_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} 3744 ,{jjPFAC2, PFAC_CMD, LIST_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL |ALLOW_RING} 3745 ,{jjPFAC2, PFAC_CMD, LIST_CMD, NUMBER_CMD, BIGINT_CMD, ALLOW_PLURAL |ALLOW_RING} 3746 ,{jjPFAC2, PFAC_CMD, LIST_CMD, BIGINT_CMD, NUMBER_CMD, ALLOW_PLURAL |ALLOW_RING} 3747 ,{jjPFAC2, PFAC_CMD, LIST_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL |ALLOW_RING} 3725 3748 #ifdef HAVE_PLURAL 3726 3749 ,{jjPlural_num_poly, NCALGEBRA_CMD,NONE, POLY_CMD, POLY_CMD , NO_PLURAL |NO_RING} … … 4514 4537 static BOOLEAN jjPFAC1(leftv res, leftv v) 4515 4538 { 4539 /* call method jjPFAC2 with second argument = 0 (meaning that no 4540 valid bound for the prime factors has been given) */ 4516 4541 sleftv tmp; 4517 memset(&tmp, 0,sizeof(tmp));4518 tmp.rtyp =INT_CMD;4519 return jjPFAC2(res, v,&tmp);4542 memset(&tmp, 0, sizeof(tmp)); 4543 tmp.rtyp = INT_CMD; 4544 return jjPFAC2(res, v, &tmp); 4520 4545 } 4521 4546 static BOOLEAN jjLU_DECOMP(leftv res, leftv v) -
Singular/misc_ip.cc
rf9bb68 r555b03 22 22 #include <Singular/misc_ip.h> 23 23 24 /* This works by Newton iteration, i.e., 25 a(1) = n; 26 a(i+1) = a(i)/2 + n/2/a(i), i > 0. 27 This sequence is guaranteed to decrease monotonously and 28 it is known to converge fast. 29 All used numbers are bigints. */ 30 number approximateSqrt(const number n) 31 { 32 if (nlIsZero(n)) { number zero = nlInit(0, NULL); return zero; } 33 number temp1; number temp2; 34 number one = nlInit(1, NULL); 35 number two = nlInit(2, NULL); 36 number m = nlCopy(n); 37 number mOld = nlSub(m, one); /* initially required to be different from m */ 38 number nHalf = nlIntDiv(n, two); 39 bool check = true; 40 while (!nlEqual(m, mOld) && check) 41 { 42 temp1 = nlIntDiv(m, two); 43 temp2 = nlIntDiv(nHalf, m); 44 mOld = m; 45 m = nlAdd(temp1, temp2); 46 nlDelete(&temp1, NULL); nlDelete(&temp2, NULL); 47 temp1 = nlMult(m, m); 48 check = nlGreater(temp1, n); 49 nlDelete(&temp1, NULL); 50 } 51 nlDelete(&mOld, NULL); nlDelete(&two, NULL); nlDelete(&nHalf, NULL); 52 while (!check) 53 { 54 temp1 = nlAdd(m, one); 55 nlDelete(&m, NULL); 56 m = temp1; 57 temp1 = nlMult(m, m); 58 check = nlGreater(temp1, n); 59 nlDelete(&temp1, NULL); 60 } 61 temp1 = nlSub(m, one); 62 nlDelete(&m, NULL); 63 nlDelete(&one, NULL); 64 m = temp1; 65 return m; 66 } 67 68 /* returns the quotient resulting from division of n by the prime as many 69 times as possible without remainder; afterwards, the parameter times 70 will contain the highest exponent e of p such that p^e divides n 71 e.g., divTimes(48, 4, t) = 3 with t = 2, since 48 = 4*4*3; 72 n is expected to be a bigint; returned type is also bigint */ 73 number divTimes(const number n, const int p, int* times) 74 { 75 number nn = nlCopy(n); 76 number dd = nlInit(p, NULL); 77 number rr = nlIntMod(nn, dd); 24 void number2mpz(number n, mpz_t m) 25 { 26 if (nlIsZero(n)) mpz_init_set_si(m, 0); 27 else 28 { 29 int nAsInt = nlInt(n, NULL); 30 if (nAsInt != 0) mpz_init_set_si(m, nAsInt); /* n fits in an int */ 31 else mpz_init_set(m, (mpz_ptr)n->z); 32 } 33 } 34 35 number mpz2number(mpz_t m) 36 { 37 number z = (number)omAllocBin(rnumber_bin); 38 mpz_init_set(z->z, m); 39 mpz_init_set_ui(z->n, 1); 40 z->s = 3; 41 return z; 42 } 43 44 void divTimes(mpz_t n, mpz_t d, int* times) 45 { 78 46 *times = 0; 79 while (nlIsZero(rr)) 47 mpz_t r; mpz_init(r); 48 mpz_t q; mpz_init(q); 49 mpz_fdiv_qr(q, r, n, d); 50 while (mpz_cmp_ui(r, 0) == 0) 80 51 { 81 52 (*times)++; 82 number temp = nlIntDiv(nn, dd); 83 nlDelete(&nn, NULL); 84 nn = temp; 85 nlDelete(&rr, NULL); 86 rr = nlIntMod(nn, dd); 87 } 88 nlDelete(&rr, NULL); nlDelete(&dd, NULL); 89 return nn; 53 mpz_set(n, q); 54 mpz_fdiv_qr(q, r, n, d); 55 } 56 mpz_clear(r); 57 mpz_clear(q); 90 58 } 91 59 92 60 /* returns an object of type lists which contains the entries 93 theInts[0..(length-1)] as INT_CMDs */61 theInts[0..(length-1)] as INT_CMDs */ 94 62 lists makeListsObject(const int* theInts, int length) 95 63 { … … 101 69 } 102 70 103 /* returns the i-th bit of the binary number which arises by 104 concatenating array[length-1], ..., array[1], array[0], 105 where array[0] contains the 32 lowest bits etc.; 106 i is assumed to be small enough to address a valid index 107 in the given array */ 108 bool getValue(const unsigned i, const unsigned int* ii) 109 { 110 if (i==2) return true; 111 if ((i & 1)==0) return false; 112 unsigned I= i/2; 113 unsigned index = I / 32; 114 unsigned offset = I % 32; 115 unsigned int v = 1 << offset; 116 return ((ii[index] & v) != 0); 117 } 118 119 /* sets the i-th bit of the binary number which arises by 120 concatenating array[length-1], ..., array[1], array[0], 121 where array[0] contains the 32 lowest bits etc.; 122 i is assumed to be small enough to address a valid index 123 in the given array */ 124 void setValue(const unsigned i, bool value, unsigned int* ii) 125 { 126 if ((i&1)==0) return; // ignore odd numbers 127 unsigned I=i/2; 128 unsigned index = I / 32; 129 unsigned offset = I % 32; 130 unsigned int v = 1 << offset; 131 if (value) { ii[index] |= v; } 132 else { ii[index] &= ~v; } 133 } 134 135 /* returns whether i is less than or equal to the bigint number n */ 136 bool isLeq(const int i, const number n) 137 { 138 number iN = nlInit(i - 1, NULL); 139 bool result = nlGreater(n, iN); 140 nlDelete(&iN, NULL); 141 return result; 142 } 143 144 #if 0 145 lists primeFactorisation(const number n, const int pBound) 146 { 147 number nn = nlCopy(n); int i; 148 int pCounter = 0; /* for counting the number of mutually distinct 149 prime factors in n */ 150 /* we assume that there are at most 1000 mutually distinct prime 151 factors in n */ 152 int* primes = new int[1000]; int* multiplicities = new int[1000]; 153 154 /* extra treatment for the primes 2 and 3; 155 all other primes are equal to +1/-1 mod 6 */ 156 int e; number temp; 157 temp = divTimes(nn, 2, &e); nlDelete(&nn, NULL); nn = temp; 158 if (e > 0) { primes[pCounter] = 2; multiplicities[pCounter++] = e; } 159 temp = divTimes(nn, 3, &e); nlDelete(&nn, NULL); nn = temp; 160 if (e > 0) { primes[pCounter] = 3; multiplicities[pCounter++] = e; } 161 162 /* now we simultaneously: 163 - build the sieve of Erathostenes up to s, 164 - divide out each prime factor of nn that we find along the way 165 (This may result in an earlier termination.) */ 166 167 int s = 1<<25; /* = 2^25 */ 168 int maxP = 2147483647; /* = 2^31 - 1, by the way a Mersenne prime */ 169 if ((pBound != 0) && (pBound < maxP)) 170 { 171 maxP = pBound; 172 } 173 if (maxP< (2147483647-63) ) s=(maxP+63)/64; 174 else s=2147483647/64+1; 175 unsigned int* isPrime = new unsigned int[s]; 176 /* the lowest bit of isPrime[0] stores whether 1 is a prime, 177 next bit is for 3, next for 5, etc. i.e. 178 intended usage is: isPrime[0] = ... 179 We shall make use only of bits which correspond to numbers = 180 -1 or +1 mod 6. */ 181 //for (i = 0; i < s; i++) isPrime[i] = ~0;/*4294967295*/; /* all 32 bits set */ 182 memset(isPrime,0xff,s*sizeof(unsigned int)); 183 int p=9; while((p<maxP) && (p>0)) { setValue(p,false,isPrime); p+=6; } 184 p = 5; bool add2 = true; 185 /* due to possible overflows, we need to check whether p > 0, and 186 likewise i > 0 below */ 187 while ((0 < p) && (p <= maxP) && (isLeq(p, nn))) 188 { 189 /* at this point, p is guaranteed to be a prime; 190 we divide nn by the highest power of p and store p 191 if nn is at all divisible by p */ 192 temp = divTimes(nn, p, &e); 193 nlDelete(&nn, NULL); nn = temp; 194 if (e > 0) 195 { primes[pCounter] = p; multiplicities[pCounter++] = e; } 196 /* invalidate all multiples of p, starting with 2*p */ 197 i = 2 * p; 198 while ((0 < i) && (i < maxP)) { setValue(i, false, isPrime); i += p; } 199 /* move on to the next prime in the sieve; we either add 2 or 4 200 in order to visit just the numbers equal to -1/+1 mod 6 */ 201 if (add2) { p += 2; add2 = false; } 202 else { p += 4; add2 = true; } 203 while ((0 < p) && (p <= maxP) && (isLeq(p, nn)) && (!getValue(p, isPrime))) 204 { 205 if (add2) { p += 2; add2 = false; } 206 else { p += 4; add2 = true; } 207 } 208 } 209 210 /* build return structure and clean up */ 211 delete [] isPrime; 212 lists primesL = makeListsObject(primes, pCounter); 213 lists multiplicitiesL = makeListsObject(multiplicities, pCounter); 214 delete [] primes; delete [] multiplicities; 215 lists L=(lists)omAllocBin(slists_bin); 216 L->Init(3); 217 L->m[0].rtyp = BIGINT_CMD; L->m[0].data = (void *)nn; 71 void setListEntry(lists L, int index, mpz_t n) 72 { /* assumes n > 0 */ 73 number nn = mpz2number(n); 74 L->m[index].rtyp = BIGINT_CMD; L->m[index].data = (void*)nn; 218 75 /* try to fit nn into an int: */ 219 76 int nnAsInt = nlInt(nn, NULL); 220 if (nlIsZero(nn) || (nnAsInt != 0)) 221 { 222 nlDelete(&nn,NULL); 223 L->m[0].rtyp = INT_CMD; 224 L->m[0].data = (void *)nnAsInt; 225 } 226 L->m[1].rtyp = LIST_CMD; L->m[1].data = (void *)primesL; 227 L->m[2].rtyp = LIST_CMD; L->m[2].data = (void *)multiplicitiesL; 77 if (nnAsInt != 0) 78 { 79 nlDelete(&nn, NULL); 80 L->m[index].rtyp = INT_CMD; L->m[index].data = (void*)nnAsInt; 81 } 82 } 83 84 /* true iff p is prime */ 85 /* 86 bool isPrime(mpz_t p) 87 { 88 if (mpz_cmp_ui(p, 2) == 0) return true; 89 if (mpz_cmp_ui(p, 3) == 0) return true; 90 if (mpz_cmp_ui(p, 5) < 0) return false; 91 92 mpz_t d; mpz_init_set_ui(d, 5); int add = 2; 93 mpz_t sr; mpz_init(sr); mpz_sqrt(sr, p); 94 mpz_t r; mpz_init(r); 95 while (mpz_cmp(d, sr) <= 0) 96 { 97 mpz_cdiv_r(r, p, d); 98 if (mpz_cmp_ui(r, 0) == 0) 99 { 100 mpz_clear(d); mpz_clear(sr); mpz_clear(r); 101 return false; 102 } 103 mpz_add_ui(d, d, add); 104 add += 2; if (add == 6) add = 2; 105 } 106 mpz_clear(d); mpz_clear(sr); mpz_clear(r); 107 return true; 108 } 109 */ 110 111 /* finds the next prime q, bound >= q >= p; 112 in case of success, puts q into p; 113 otherwise sets q = bound + 1; 114 e.g. p = 24; nextPrime(p, 30) produces p = 29 (success), 115 p = 24; nextPrime(p, 29) produces p = 29 (success), 116 p = 24; nextPrime(p, 28) produces p = 29 (no success), 117 p = 24; nextPrime(p, 27) produces p = 28 (no success) */ 118 /* 119 void nextPrime(mpz_t p, mpz_t bound) 120 { 121 int add; 122 mpz_t r; mpz_init(r); mpz_cdiv_r_ui(r, p, 6); // r = p mod 6, 0 <= r <= 5 123 if (mpz_cmp_ui(r, 0) == 0) { mpz_add_ui(p, p, 1); add = 4; } 124 if (mpz_cmp_ui(r, 1) == 0) { add = 4; } 125 if (mpz_cmp_ui(r, 2) == 0) { mpz_add_ui(p, p, 3); add = 2; } 126 if (mpz_cmp_ui(r, 3) == 0) { mpz_add_ui(p, p, 2); add = 2; } 127 if (mpz_cmp_ui(r, 4) == 0) { mpz_add_ui(p, p, 1); add = 2; } 128 if (mpz_cmp_ui(r, 5) == 0) { add = 2; } 129 130 while (mpz_cmp(p, bound) <= 0) 131 { 132 if (isPrime(p)) { mpz_clear(r); return; } 133 mpz_add_ui(p, p, add); 134 add += 2; if (add == 6) add = 2; 135 } 136 mpz_set(p, bound); 137 mpz_add_ui(p, p, 1); 138 mpz_clear(r); 139 return; 140 } 141 */ 142 143 /* n and pBound are assumed to be bigint numbers */ 144 lists primeFactorisation(const number n, const number pBound) 145 { 146 mpz_t nn; number2mpz(n, nn); 147 mpz_t pb; number2mpz(pBound, pb); 148 mpz_t b; number2mpz(pBound, b); 149 mpz_t p; mpz_init(p); int tt; 150 mpz_t sr; mpz_init(sr); int index = 0; int add; 151 lists primes = (lists)omAllocBin(slists_bin); primes->Init(1000); 152 int* multiplicities = new int[1000]; 153 154 mpz_set_ui(p, 2); 155 if ((mpz_cmp_ui(b, 0) == 0) || (mpz_cmp(p, b) <= 0)) 156 { 157 divTimes(nn, p, &tt); 158 if (tt > 0) 159 { 160 setListEntry(primes, index, p); 161 multiplicities[index++] = tt; 162 } 163 } 164 165 mpz_set_ui(p, 3); 166 if ((mpz_cmp_ui(b, 0) == 0) || (mpz_cmp(p, b) <= 0)) 167 { 168 divTimes(nn, p, &tt); 169 if (tt > 0) 170 { 171 setListEntry(primes, index, p); 172 multiplicities[index++] = tt; 173 } 174 } 175 176 mpz_set_ui(p, 5); add = 2; 177 mpz_sqrt(sr, nn); 178 if ((mpz_cmp_ui(b, 0) == 0) || (mpz_cmp(pb, sr) > 0)) mpz_set(pb, sr); 179 while (mpz_cmp(pb, p) >= 0) 180 { 181 divTimes(nn, p, &tt); 182 if (tt > 0) 183 { 184 setListEntry(primes, index, p); 185 multiplicities[index++] = tt; 186 mpz_sqrt(sr, nn); 187 if ((mpz_cmp_ui(b, 0) == 0) || (mpz_cmp(pb, sr) > 0)) mpz_set(pb, sr); 188 } 189 mpz_add_ui(p, p, add); 190 add += 2; if (add == 6) add = 2; 191 } 192 if ((mpz_cmp_ui(nn, 1) > 0) && 193 ((mpz_cmp_ui(b, 0) == 0) || (mpz_cmp(nn, b) <= 0))) 194 { 195 setListEntry(primes, index, nn); 196 multiplicities[index++] = 1; 197 mpz_set_ui(nn, 1); 198 } 199 200 lists primesL = (lists)omAllocBin(slists_bin); 201 primesL->Init(index); 202 for (int i = 0; i < index; i++) 203 { 204 primesL->m[i].rtyp = primes->m[i].rtyp; 205 primesL->m[i].data = primes->m[i].data; 206 } 207 omFreeSize((ADDRESS)primes->m, (primes->nr + 1) * sizeof(sleftv)); 208 omFreeBin((ADDRESS)primes, slists_bin); 209 210 lists multiplicitiesL = (lists)omAllocBin(slists_bin); 211 multiplicitiesL->Init(index); 212 for (int i = 0; i < index; i++) 213 { 214 multiplicitiesL->m[i].rtyp = INT_CMD; 215 multiplicitiesL->m[i].data = (void*)multiplicities[i]; 216 } 217 delete[] multiplicities; 218 219 lists L=(lists)omAllocBin(slists_bin); 220 L->Init(4); 221 setListEntry(L, 0, nn); 222 L->m[1].rtyp = LIST_CMD; L->m[1].data = (void*)primesL; 223 L->m[2].rtyp = LIST_CMD; L->m[2].data = (void*)multiplicitiesL; 224 int probTest = 0; 225 if (mpz_probab_prime_p(nn, 25) != 0) probTest = 1; 226 L->m[3].rtyp = INT_CMD; L->m[3].data = (void*)probTest; 227 mpz_clear(nn); mpz_clear(pb); mpz_clear(b); mpz_clear(p); mpz_clear(sr); 228 228 229 return L; 229 230 } 230 #else231 /* Factoring , from gmp-demos232 233 Copyright 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free Software234 Foundation, Inc.235 236 This program is free software; you can redistribute it and/or modify it under237 the terms of the GNU General Public License as published by the Free Software238 Foundation; either version 3 of the License, or (at your option) any later239 version.240 241 This program is distributed in the hope that it will be useful, but WITHOUT ANY242 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A243 PARTICULAR PURPOSE. See the GNU General Public License for more details.244 245 You should have received a copy of the GNU General Public License along with246 this program. If not, see http://www.gnu.org/licenses/. */247 248 249 #include <stdlib.h>250 #include <stdio.h>251 #include <string.h>252 253 #include <kernel/si_gmp.h>254 255 static unsigned add[] = {4, 2, 4, 2, 4, 6, 2, 6};256 257 void factor_using_division (mpz_t t, unsigned int limit, int *L, int &L_ind, int *ex)258 {259 mpz_t q, r;260 unsigned long int f;261 int ai;262 unsigned *addv = add;263 unsigned int failures;264 265 mpz_init (q);266 mpz_init (r);267 268 f = mpz_scan1 (t, 0);269 mpz_div_2exp (t, t, f);270 while (f)271 {272 if ((L_ind>0) && (L[L_ind-1]==2)) ex[L_ind-1]++;273 else274 {275 L[L_ind]=2;276 L_ind++;277 }278 --f;279 }280 281 for (;;)282 {283 mpz_tdiv_qr_ui (q, r, t, 3);284 if (mpz_cmp_ui (r, 0) != 0) break;285 mpz_set (t, q);286 if ((L_ind>0) && (L[L_ind-1]==3)) ex[L_ind-1]++;287 else288 {289 L[L_ind]=3;290 L_ind++;291 }292 }293 294 for (;;)295 {296 mpz_tdiv_qr_ui (q, r, t, 5);297 if (mpz_cmp_ui (r, 0) != 0) break;298 mpz_set (t, q);299 if ((L_ind>0) && (L[L_ind-1]==5)) ex[L_ind-1]++;300 else301 {302 L[L_ind]=5;303 L_ind++;304 }305 }306 307 failures = 0;308 f = 7;309 ai = 0;310 while (mpz_cmp_ui (t, 1) != 0)311 {312 if (f>=((unsigned long)1 <<28)) break;313 if (mpz_cmp_ui (t, f) < 0) break;314 mpz_tdiv_qr_ui (q, r, t, f);315 if (mpz_cmp_ui (r, 0) != 0)316 {317 f += addv[ai];318 ai = (ai + 1) & 7;319 failures++;320 if (failures > limit) break;321 }322 else323 {324 mpz_swap (t, q);325 //gmp_printf("%d: %Zd\n",f,t);326 // here: f in 0,,2^28-1:327 if ((L_ind>0) && (L[L_ind-1]==(int)f)) ex[L_ind-1]++;328 else329 {330 L[L_ind]=f;331 L_ind++;332 }333 failures = 0;334 }335 }336 337 mpz_clear (q);338 mpz_clear (r);339 }340 341 void factor_using_pollard_rho (mpz_t n, int a_int, int *L, int &L_ind, int *ex)342 {343 mpz_t x, x1, y, P;344 mpz_t a;345 mpz_t g;346 mpz_t t1, t2;347 int k, l, c, i;348 349 mpz_init (g);350 mpz_init (t1);351 mpz_init (t2);352 353 mpz_init_set_si (a, a_int);354 mpz_init_set_si (y, 2);355 mpz_init_set_si (x, 2);356 mpz_init_set_si (x1, 2);357 k = 1;358 l = 1;359 mpz_init_set_ui (P, 1);360 c = 0;361 362 while (mpz_cmp_ui (n, 1) != 0)363 {364 S2:365 mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n);366 mpz_sub (t1, x1, x); mpz_mul (t2, P, t1); mpz_mod (P, t2, n);367 c++;368 if (c == 20)369 {370 c = 0;371 mpz_gcd (g, P, n);372 if (mpz_cmp_ui (g, 1) != 0) goto S4;373 mpz_set (y, x);374 }375 S3:376 k--;377 if (k > 0) goto S2;378 379 mpz_gcd (g, P, n);380 if (mpz_cmp_ui (g, 1) != 0) goto S4;381 382 mpz_set (x1, x);383 k = l;384 l = 2 * l;385 for (i = 0; i < k; i++)386 {387 mpz_mul (x, x, x); mpz_add (x, x, a); mpz_mod (x, x, n);388 }389 mpz_set (y, x);390 c = 0;391 goto S2;392 S4:393 do394 {395 mpz_mul (y, y, y); mpz_add (y, y, a); mpz_mod (y, y, n);396 mpz_sub (t1, x1, y); mpz_gcd (g, t1, n);397 }398 while (mpz_cmp_ui (g, 1) == 0);399 400 mpz_div (n, n, g); /* divide by g, before g is overwritten */401 402 if (!mpz_probab_prime_p (g, 10))403 {404 do405 {406 mp_limb_t a_limb;407 mpn_random (&a_limb, (mp_size_t) 1);408 a_int = (int) a_limb;409 }410 while (a_int == -2 || a_int == 0);411 412 factor_using_pollard_rho (g, a_int,L,L_ind,ex);413 }414 else415 {416 if ((L_ind>0) && (mpz_cmp_si(g,L[L_ind-1])==0)) ex[L_ind-1]++;417 else418 {419 L[L_ind]=mpz_get_si(g);420 L_ind++;421 }422 }423 mpz_mod (x, x, n);424 mpz_mod (x1, x1, n);425 mpz_mod (y, y, n);426 if (mpz_probab_prime_p (n, 10))427 {428 int te=mpz_get_si(n);429 if (mpz_cmp_si(n,te)==0) /* does it fit into an int ? */430 {431 if ((L_ind>0) && (mpz_cmp_si(n,L[L_ind-1])==0)) ex[L_ind-1]++;432 else433 {434 L[L_ind]=mpz_get_si(n);435 L_ind++;436 }437 mpz_set_si(n,1); // add n itself the list of divisors, rest is 1438 }439 break;440 }441 }442 443 mpz_clear (g);444 mpz_clear (P);445 mpz_clear (t2);446 mpz_clear (t1);447 mpz_clear (a);448 mpz_clear (x1);449 mpz_clear (x);450 mpz_clear (y);451 }452 453 void mpz_factor (mpz_t t, int *L, int & L_ind, int *ex)454 {455 unsigned int division_limit;456 457 if (mpz_sgn (t) == 0)458 return;459 460 /* Set the trial division limit according the size of t. */461 division_limit = mpz_sizeinbase (t, 2);462 if (division_limit > 1000)463 division_limit = 1000 * 1000;464 else465 division_limit = division_limit * division_limit;466 467 factor_using_division (t, division_limit, L, L_ind, ex);468 469 if (mpz_cmp_ui (t, 1) != 0)470 {471 if (mpz_probab_prime_p (t, 10))472 {473 int tt=mpz_get_si(t);474 // check if t fits into int:475 if ((mpz_size1(t)==1)&&(mpz_cmp_si(t,tt)==0))476 {477 L[L_ind]=mpz_get_si(t);478 L_ind++;479 mpz_set_si(t,1);480 }481 }482 else483 factor_using_pollard_rho (t, 1, L,L_ind,ex);484 }485 }486 487 lists primeFactorisation(const number n, const int pBound)488 {489 mpz_t t;490 number nn = nlCopy(n);491 lists L=(lists)omAllocBin(slists_bin);492 L->Init(3);493 L->m[0].rtyp = BIGINT_CMD; L->m[0].data = (void *)nn;494 /* try to fit nn into an int: */495 int nnAsInt = nlInt(nn, NULL);496 if (nlIsZero(nn) || (nnAsInt != 0))497 {498 mpz_init_set_si(t,nnAsInt);499 }500 else501 {502 mpz_init_set(t,(mpz_ptr)nn->z);503 }504 int *LL=(int*)omAlloc0(1000*sizeof(int));505 int *ex=(int*)omAlloc0(1000*sizeof(int));506 int L_ind=0;507 mpz_factor (t,LL,L_ind,ex);508 509 nnAsInt = mpz_get_si(t);510 if ((mpz_size1(t)==1) && (mpz_cmp_si(t,nnAsInt)==0))511 {512 nlDelete(&nn,NULL);513 L->m[0].rtyp = INT_CMD;514 L->m[0].data = (void *)nnAsInt;515 }516 else517 {518 mpz_set(nn->z,t);519 L->m[0].rtyp = BIGINT_CMD;520 L->m[0].data = (void *)nn;521 }522 mpz_clear(t);523 int i;524 for(i=0;i<L_ind;i++) ex[i]++;525 L->m[1].rtyp = LIST_CMD; L->m[1].data = (void *)makeListsObject(LL,L_ind);526 L->m[2].rtyp = LIST_CMD; L->m[2].data = (void *)makeListsObject(ex,L_ind);527 return L;528 }529 #endif530 231 531 232 #include <string.h> -
Singular/misc_ip.h
rf9bb68 r555b03 29 29 30 30 /** 31 * Co mputes an approximation of the square root of a bigintnumber.31 * Converts a non-negative bigint number into a GMP number. 32 32 * 33 * Expects a non-negative bigint number n and returns the bigint 34 * number m which satisfies m*m <= n < (m+1)*(m+1). This implementation 35 * does not require a valid currRing. 33 **/ 34 void number2mpz(number n, /**< [in] a bigint number >= 0 */ 35 mpz_t m /**< [out] the GMP equivalent */ 36 ); 37 38 /** 39 * Converts a non-negative GMP number into a bigint number. 36 40 * 37 * @return an approximation of the square root of n41 * @return the bigint number representing the given GMP number 38 42 **/ 39 number approximateSqrt(const number n /**< [in] a number */ 40 ); 43 number mpz2number(mpz_t m /**< [in] a GMP number >= 0 */ 44 ); 45 46 /** 47 * Divides 'n' as many times as possible by 'd' and returns the number 48 * of divisions (without remainder) in 'times', 49 * e.g., n = 48, d = 4, divTimes(n, d, t) = 3 produces n = 3, t = 2, 50 * since 48 = 4*4*3; 51 * assumes that d is positive 52 **/ 53 void divTimes(mpz_t n, /**< [in] a GMP number >= 0 */ 54 mpz_t d, /**< [in] the divisor, a GMP number >= 0 */ 55 int* times /**< [out] number of divisions without remainder */ 56 ); 41 57 42 58 /** … … 44 60 * than or equal to a given bound, with corresponding multiplicities. 45 61 * 46 * The method is capable of finding only prime factors < 2^31, and it looks 47 * only for those less than or equal the given bound, if this bound is not 0. 48 * Therefore, after dividing out all prime factors which have been found, 49 * some number m > 1 may survive. 50 * The method returns a list L filled with three entries: 51 * L[1] contains m as int or bigint, depending on the size, 52 * L[2] a list; L[2][i] contains the i-th prime factor as int 62 * The method finds all prime factors with multiplicities. If a non-zero 63 * bound is given, then only the prime factors <= pBound are being found. 64 * In this case, there may remain an unfactored portion m of n. 65 * The method returns a list L filled with four entries: 66 * L[1] contains the remainder m as int or bigint, depending on the size, 67 * L[2] a list; L[2][i] contains the i-th prime factor as int or bigint 53 68 * (sorted in ascending order), 54 69 * L[3] a list; L[3][i] contains the multiplicity of L[2, i] in n as int 70 * L[4] 1 iff the remainder m is probably a prime, 0 otherwise 55 71 * 56 72 * We thus have: n = L[1] * L[2][1]^L[3][1] * ... * L[2][k]^L[3][k], where 57 * k is the number of mutually distinct prime factors < 2^31 and <= the58 * provided bound (if this is not zero).73 * k is the number of mutually distinct prime factors (<= a provided non- 74 * zero bound). 59 75 * 60 * @return the factorisation data in a list76 * @return the factorisation data in a SINGULAR-internal list 61 77 **/ 62 78 lists primeFactorisation( 63 const number n, /**< [in] the bigint to be factorised */ 64 const int pBound /**< [in] bound on the prime factors seeked */ 79 const number n, /**< [in] the bigint > 0 to be factorised */ 80 const number pBound /**< [in] bigint bound on the prime factors 81 seeked */ 65 82 ); 66 83
Note: See TracChangeset
for help on using the changeset viewer.