Changeset 511f2d in git
- Timestamp:
- Jan 23, 2013, 5:57:20 PM (10 years ago)
- Branches:
- (u'jengelh-datetime', 'ceac47cbc86fe4a15902392bdbb9bd2ae0ea02c6')(u'spielwiese', 'a800fe4b3e9d37a38c5a10cc0ae9dfa0c15a4ee6')
- Children:
- 4def554e55ce8709cb931c050a80a944fe9a7633
- Parents:
- 8b57f5e1c589185d90380ede5c9b3a0b2a44ff97fd85113e6317e9d03532a7ec8affbc338a502ea3
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/iparith.cc
r8b57f5 r511f2d 3152 3152 static BOOLEAN jjPFAC2(leftv res, leftv u, leftv v) 3153 3153 { 3154 number n1; number n2; number temp;int i;3154 number n1; int i; 3155 3155 3156 3156 if ((u->Typ() == BIGINT_CMD) || 3157 3157 ((u->Typ() == NUMBER_CMD) && rField_is_Q(currRing))) 3158 3158 { 3159 temp = (number)u->Data(); 3160 n1 = n_Copy(temp,coeffs_BIGINT); 3159 n1 = (number)u->CopyD(); 3161 3160 } 3162 3161 else if (u->Typ() == INT_CMD) … … 3167 3166 else 3168 3167 { 3169 WerrorS("wrong type: expected int, bigint, or number as 1st argument"); 3170 return TRUE; 3171 } 3172 3173 if ((v->Typ() == BIGINT_CMD) || 3174 ((v->Typ() == NUMBER_CMD) && rField_is_Q(currRing))) 3175 { 3176 temp = (number)v->Data(); 3177 n2 = n_Copy(temp,coeffs_BIGINT); 3178 } 3179 else if (v->Typ() == INT_CMD) 3180 { 3181 i = (int)(long)v->Data(); 3182 n2 = n_Init(i, coeffs_BIGINT); 3183 } 3184 else 3185 { 3186 WerrorS("wrong type: expected int, bigint, or number as 2nd argument"); 3187 return TRUE; 3188 } 3189 3190 lists l = primeFactorisation(n1, n2); 3191 n_Delete(&n1, coeffs_BIGINT); n_Delete(&n2, coeffs_BIGINT); 3168 return TRUE; 3169 } 3170 3171 i = (int)(long)v->Data(); 3172 3173 lists l = primeFactorisation(n1, i); 3174 n_Delete(&n1, coeffs_BIGINT); 3192 3175 res->data = (char*)l; 3193 3176 return FALSE; -
Singular/misc_ip.cc
r8b57f5 r511f2d 37 37 38 38 39 void divTimes(mpz_t n, mpz_t d, int* times)40 {41 *times = 0;42 mpz_t r; mpz_init(r);43 mpz_t q; mpz_init(q);44 mpz_fdiv_qr(q, r, n, d);45 while (mpz_cmp_ui(r, 0) == 0)46 {47 (*times)++;48 mpz_set(n, q);49 mpz_fdiv_qr(q, r, n, d);50 }51 mpz_clear(r);52 mpz_clear(q);53 }54 55 void divTimes_ui(mpz_t n, unsigned long d, int* times)56 {57 *times = 0;58 mpz_t r; mpz_init(r);59 mpz_t q; mpz_init(q);60 mpz_fdiv_qr_ui(q, r, n, d);61 while (mpz_cmp_ui(r, 0) == 0)62 {63 (*times)++;64 mpz_set(n, q);65 mpz_fdiv_qr_ui(q, r, n, d);66 }67 mpz_clear(r);68 mpz_clear(q);69 }70 71 static inline void divTimes_ui_ui(unsigned long *n, unsigned long d, int* times)72 {73 *times = 0;74 unsigned long q=(*n) / d;75 unsigned long r=(*n) % d;76 while (r==0)77 {78 (*times)++;79 (*n)=q;80 q=(*n)/d; r=(*n)%d;81 }82 }83 84 39 void setListEntry(lists L, int index, mpz_t n) 85 40 { /* assumes n > 0 */ … … 114 69 } 115 70 116 /* true iff p is prime */ 117 /* 118 bool isPrime(mpz_t p) 119 { 120 if (mpz_cmp_ui(p, 2) == 0) return true; 121 if (mpz_cmp_ui(p, 3) == 0) return true; 122 if (mpz_cmp_ui(p, 5) < 0) return false; 123 124 mpz_t d; mpz_init_set_ui(d, 5); int add = 2; 125 mpz_t sr; mpz_init(sr); mpz_sqrt(sr, p); 126 mpz_t r; mpz_init(r); 127 while (mpz_cmp(d, sr) <= 0) 128 { 129 mpz_cdiv_r(r, p, d); 130 if (mpz_cmp_ui(r, 0) == 0) 131 { 132 mpz_clear(d); mpz_clear(sr); mpz_clear(r); 133 return false; 134 } 135 mpz_add_ui(d, d, add); 136 add += 2; if (add == 6) add = 2; 137 } 138 mpz_clear(d); mpz_clear(sr); mpz_clear(r); 139 return true; 140 } 141 */ 142 143 /* finds the next prime q, bound >= q >= p; 144 in case of success, puts q into p; 145 otherwise sets q = bound + 1; 146 e.g. p = 24; nextPrime(p, 30) produces p = 29 (success), 147 p = 24; nextPrime(p, 29) produces p = 29 (success), 148 p = 24; nextPrime(p, 28) produces p = 29 (no success), 149 p = 24; nextPrime(p, 27) produces p = 28 (no success) */ 150 /* 151 void nextPrime(mpz_t p, mpz_t bound) 152 { 153 int add; 154 mpz_t r; mpz_init(r); mpz_cdiv_r_ui(r, p, 6); // r = p mod 6, 0 <= r <= 5 155 if (mpz_cmp_ui(r, 0) == 0) { mpz_add_ui(p, p, 1); add = 4; } 156 if (mpz_cmp_ui(r, 1) == 0) { add = 4; } 157 if (mpz_cmp_ui(r, 2) == 0) { mpz_add_ui(p, p, 3); add = 2; } 158 if (mpz_cmp_ui(r, 3) == 0) { mpz_add_ui(p, p, 2); add = 2; } 159 if (mpz_cmp_ui(r, 4) == 0) { mpz_add_ui(p, p, 1); add = 2; } 160 if (mpz_cmp_ui(r, 5) == 0) { add = 2; } 161 162 while (mpz_cmp(p, bound) <= 0) 163 { 164 if (isPrime(p)) { mpz_clear(r); return; } 165 mpz_add_ui(p, p, add); 166 add += 2; if (add == 6) add = 2; 167 } 168 mpz_set(p, bound); 169 mpz_add_ui(p, p, 1); 170 mpz_clear(r); 171 return; 172 } 173 */ 174 175 176 71 /* Factoring with Pollard's rho method. stolen from GMP/demos */ 72 static unsigned add[] = {4, 2, 4, 2, 4, 6, 2, 6}; 73 74 static int factor_using_division (mpz_t t, unsigned int limit,lists primes, int *multiplicities,int &index, unsigned long bound) 75 { 76 mpz_t q, r; 77 unsigned long int f; 78 int ai; 79 unsigned *addv = add; 80 unsigned int failures; 81 int bound_not_reached=1; 82 83 mpz_init (q); 84 mpz_init (r); 85 86 f = mpz_scan1 (t, 0); 87 mpz_div_2exp (t, t, f); 88 if (f>0) 89 { 90 setListEntry_ui(primes, index, 2); 91 multiplicities[index++] = f; 92 } 93 94 f=0; 95 loop 96 { 97 mpz_tdiv_qr_ui (q, r, t, 3); 98 if (mpz_cmp_ui (r, 0) != 0) 99 break; 100 mpz_set (t, q); 101 f++; 102 } 103 if (f>0) 104 { 105 setListEntry_ui(primes, index, 3); 106 multiplicities[index++] = f; 107 } 108 f=0; 109 loop 110 { 111 mpz_tdiv_qr_ui (q, r, t, 5); 112 if (mpz_cmp_ui (r, 0) != 0) 113 break; 114 mpz_set (t, q); 115 f++; 116 } 117 if (f>0) 118 { 119 setListEntry_ui(primes, index, 5); 120 multiplicities[index++] = f; 121 } 122 123 failures = 0; 124 f = 7; 125 ai = 0; 126 unsigned long last_f=0; 127 while (mpz_cmp_ui (t, 1) != 0) 128 { 129 mpz_tdiv_qr_ui (q, r, t, f); 130 if (mpz_cmp_ui (r, 0) != 0) 131 { 132 f += addv[ai]; 133 if (mpz_cmp_ui (t, f) < 0) 134 break; 135 ai = (ai + 1) & 7; 136 failures++; 137 if (failures > limit) 138 break; 139 if ((bound!=0) && (f>bound)) 140 { 141 bound_not_reached=0; 142 break; 143 } 144 } 145 else 146 { 147 mpz_swap (t, q); 148 if (f!=last_f) 149 { 150 setListEntry_ui(primes, index, f); 151 multiplicities[index]++; 152 index++; 153 } 154 else 155 { 156 multiplicities[index-1]++; 157 } 158 last_f=f; 159 failures = 0; 160 } 161 } 162 163 mpz_clear (q); 164 mpz_clear (r); 165 //printf("bound=%d,f=%d,failures=%d, reached=%d\n",bound,f,failures,bound_not_reached); 166 return bound_not_reached; 167 } 168 169 static void factor_using_pollard_rho (mpz_t n, unsigned long a, lists primes, int * multiplicities,int &index) 170 { 171 mpz_t x, x1, y, P; 172 mpz_t t1, t2; 173 mpz_t last_f; 174 unsigned long long k, l, i; 175 176 mpz_init (t1); 177 mpz_init (t2); 178 mpz_init_set_si (last_f, 0); 179 mpz_init_set_si (y, 2); 180 mpz_init_set_si (x, 2); 181 mpz_init_set_si (x1, 2); 182 mpz_init_set_ui (P, 1); 183 k = 1; 184 l = 1; 185 186 while (mpz_cmp_ui (n, 1) != 0) 187 { 188 loop 189 { 190 do 191 { 192 mpz_mul (t1, x, x); 193 mpz_mod (x, t1, n); 194 mpz_add_ui (x, x, a); 195 mpz_sub (t1, x1, x); 196 mpz_mul (t2, P, t1); 197 mpz_mod (P, t2, n); 198 199 if (k % 32 == 1) 200 { 201 mpz_gcd (t1, P, n); 202 if (mpz_cmp_ui (t1, 1) != 0) 203 goto factor_found; 204 mpz_set (y, x); 205 } 206 } 207 while (--k != 0); 208 209 mpz_gcd (t1, P, n); 210 if (mpz_cmp_ui (t1, 1) != 0) 211 goto factor_found; 212 213 mpz_set (x1, x); 214 k = l; 215 l = 2 * l; 216 for (i = 0; i < k; i++) 217 { 218 mpz_mul (t1, x, x); 219 mpz_mod (x, t1, n); 220 mpz_add_ui (x, x, a); 221 } 222 mpz_set (y, x); 223 } 224 225 factor_found: 226 do 227 { 228 mpz_mul (t1, y, y); 229 mpz_mod (y, t1, n); 230 mpz_add_ui (y, y, a); 231 mpz_sub (t1, x1, y); 232 mpz_gcd (t1, t1, n); 233 } 234 while (mpz_cmp_ui (t1, 1) == 0); 235 236 mpz_divexact (n, n, t1); /* divide by t1, before t1 is overwritten */ 237 238 if (!mpz_probab_prime_p (t1, 10)) 239 { 240 do 241 { 242 mp_limb_t a_limb; 243 mpn_random (&a_limb, (mp_size_t) 1); 244 a = a_limb; 245 } 246 while (a == 0); 247 248 factor_using_pollard_rho (t1, a, primes,multiplicities,index); 249 } 250 else 251 { 252 if (mpz_cmp(t1,last_f)==0) 253 { 254 multiplicities[index-1]++; 255 } 256 else 257 { 258 mpz_set(last_f,t1); 259 setListEntry(primes, index, t1); 260 multiplicities[index++] = 1; 261 } 262 } 263 mpz_mod (x, x, n); 264 mpz_mod (x1, x1, n); 265 mpz_mod (y, y, n); 266 if (mpz_probab_prime_p (n, 10)) 267 { 268 if (mpz_cmp(n,last_f)==0) 269 { 270 multiplicities[index-1]++; 271 } 272 else 273 { 274 mpz_set(last_f,n); 275 setListEntry(primes, index, n); 276 multiplicities[index++] = 1; 277 } 278 mpz_set_ui(n,1); 279 break; 280 } 281 } 282 283 mpz_clear (P); 284 mpz_clear (t2); 285 mpz_clear (t1); 286 mpz_clear (x1); 287 mpz_clear (x); 288 mpz_clear (y); 289 mpz_clear (last_f); 290 } 291 292 static void factor_gmp (mpz_t t,lists primes,int *multiplicities,int &index,unsigned long bound) 293 { 294 unsigned int division_limit; 295 296 if (mpz_sgn (t) == 0) 297 return; 298 299 /* Set the trial division limit according the size of t. */ 300 division_limit = mpz_sizeinbase (t, 2); 301 if (division_limit > 1000) 302 division_limit = 1000 * 1000; 303 else 304 division_limit = division_limit * division_limit; 305 306 if (factor_using_division (t, division_limit,primes,multiplicities,index,bound)) 307 { 308 if (mpz_cmp_ui (t, 1) != 0) 309 { 310 if (mpz_probab_prime_p (t, 10)) 311 { 312 setListEntry(primes, index, t); 313 multiplicities[index++] = 1; 314 mpz_set_ui(t,1); 315 } 316 else 317 factor_using_pollard_rho (t, 1L, primes,multiplicities,index); 318 } 319 } 320 } 177 321 /* n and pBound are assumed to be bigint numbers */ 178 lists primeFactorisation(const number n, const number pBound) 179 { 322 lists primeFactorisation(const number n, const int pBound) 323 { 324 int i; 325 int index=0; 180 326 mpz_t nn; number2mpz(n, nn); 181 mpz_t pb; number2mpz(pBound, pb);182 mpz_t b; number2mpz(pBound, b);183 mpz_t p; mpz_init(p); int tt;184 mpz_t sr; mpz_init(sr); int index = 0; int add;185 327 lists primes = (lists)omAllocBin(slists_bin); primes->Init(1000); 186 int* multiplicities = new int[1000];187 int positive=1; int probTest = 0;328 int* multiplicities = (int*)omAlloc0(1000*sizeof(int)); 329 int positive=1; 188 330 189 331 if (!n_IsZero(n, coeffs_BIGINT)) … … 194 336 mpz_neg(nn,nn); 195 337 } 196 divTimes_ui(nn, 2, &tt); 197 if (tt > 0) 198 { 199 setListEntry_ui(primes, index, 2); 200 multiplicities[index++] = tt; 201 } 202 203 divTimes_ui(nn, 3, &tt); 204 if (tt > 0) 205 { 206 setListEntry_ui(primes, index, 3); 207 multiplicities[index++] = tt; 208 } 209 210 unsigned long p_ui=5; add = 2; 211 BOOLEAN b_is_0=(mpz_cmp_ui(b, 0) == 0); 212 BOOLEAN sr_sets_pb=FALSE; 213 mpz_sqrt(sr, nn); 214 // there are 3 possible limits, we take the minimum: 215 // - argument pBound (if >0) 216 // - sr = sqrt(nn) 217 // - 1<<31 218 unsigned long limit=~(0L); 219 if (b_is_0 || (mpz_cmp(pb, sr) > 0)) 220 { 221 mpz_set(pb, sr); 222 sr_sets_pb=TRUE; 223 } 224 if (mpz_cmp_ui(pb, limit)<0) 225 { 226 limit=mpz_get_ui(pb); 227 } 228 else 229 { 230 mpz_set_ui(pb,limit); 231 } 232 while (p_ui <=limit) 233 { 234 divTimes_ui(nn, p_ui, &tt); 235 if (tt > 0) 236 { 237 setListEntry_ui(primes, index, p_ui); 238 multiplicities[index++] = tt; 239 //mpz_sqrt(sr, nn); 240 //if ((mpz_cmp_ui(b, 0) == 0) || (mpz_cmp(pb, sr) > 0)) mpz_set(pb, sr); 241 if (mpz_size1(nn)<=2) 242 { 243 mpz_sqrt(sr, nn); 244 if (sr_sets_pb || (mpz_cmp(pb, sr) > 0)) mpz_set(pb, sr); 245 unsigned long l=mpz_get_ui(sr); 246 if (l<limit) { limit=l; } 247 if (mpz_size1(nn)<=1) 248 { 249 unsigned long nn_ui=mpz_get_ui(nn); 250 while (p_ui <=limit) 251 { 252 divTimes_ui_ui(&nn_ui, p_ui, &tt); 253 if (tt > 0) 254 { 255 setListEntry_ui(primes, index, p_ui); 256 multiplicities[index++] = tt; 257 if (nn_ui==1) break; 258 if (nn_ui<(limit/6)) { limit=nn_ui/6;} 259 } 260 p_ui +=add; 261 //add += 2; if (add == 6) add = 2; 262 add =2+2*(add==2); 263 } 264 mpz_set_ui(nn,nn_ui); 265 break; 266 } 267 } 268 } 269 p_ui +=add; 270 //add += 2; if (add == 6) add = 2; 271 add =2+2*(add==2); 272 } 273 mpz_set_ui(p, p_ui); 274 mpz_sqrt(sr, nn); 275 if (b_is_0 || sr_sets_pb || (mpz_cmp(pb, sr) > 0)) mpz_set(pb, sr); 276 while (mpz_cmp(pb, p) >= 0) 277 { 278 divTimes(nn, p, &tt); 279 if (tt > 0) 280 { 281 setListEntry(primes, index, p); 282 multiplicities[index++] = tt; 283 if (mpz_cmp_ui(nn,1)==0) break; 284 mpz_sqrt(sr, nn); 285 if (b_is_0 || sr_sets_pb || (mpz_cmp(pb, sr) > 0)) mpz_set(pb, sr); 286 } 287 mpz_add_ui(p, p, add); 288 //add += 2; if (add == 6) add = 2; 289 add =2+2*(add==2); 290 } 291 if ((mpz_cmp_ui(nn, 1) > 0) && 292 (b_is_0 || (mpz_cmp(nn, b) <= 0))) 293 { 294 setListEntry(primes, index, nn); 295 multiplicities[index++] = 1; 296 mpz_set_ui(nn, 1); 297 } 298 if ((mpz_cmp_ui(nn, 1) > 0) && (mpz_probab_prime_p(nn, 25) != 0)) 299 probTest = 1; 338 factor_gmp(nn,primes,multiplicities,index,pBound); 300 339 } 301 340 302 341 lists primesL = (lists)omAllocBin(slists_bin); 303 342 primesL->Init(index); 304 for (i nt i= 0; i < index; i++)343 for (i = 0; i < index; i++) 305 344 { 306 345 primesL->m[i].rtyp = primes->m[i].rtyp; 307 346 primesL->m[i].data = primes->m[i].data; 308 } 309 omFreeSize((ADDRESS)primes->m, (primes->nr + 1) * sizeof(sleftv)); 310 omFreeBin((ADDRESS)primes, slists_bin); 347 primes->m[i].rtyp=0; 348 primes->m[i].data=NULL; 349 } 350 primes->Clean(NULL); 311 351 312 352 lists multiplicitiesL = (lists)omAllocBin(slists_bin); 313 353 multiplicitiesL->Init(index); 314 for (i nt i= 0; i < index; i++)354 for (i = 0; i < index; i++) 315 355 { 316 356 multiplicitiesL->m[i].rtyp = INT_CMD; 317 357 multiplicitiesL->m[i].data = (void*)multiplicities[i]; 318 358 } 319 delete[] multiplicities;359 omFree(multiplicities); 320 360 321 361 lists L=(lists)omAllocBin(slists_bin); 322 L->Init( 4);362 L->Init(3); 323 363 if (positive==-1) mpz_neg(nn,nn); 324 364 L->m[0].rtyp = LIST_CMD; L->m[0].data = (void*)primesL; 325 365 L->m[1].rtyp = LIST_CMD; L->m[1].data = (void*)multiplicitiesL; 326 366 setListEntry(L, 2, nn); 327 L->m[3].rtyp = INT_CMD; L->m[3].data = (void*)probTest; 328 mpz_clear(nn); mpz_clear(pb); mpz_clear(b); mpz_clear(p); mpz_clear(sr);367 368 mpz_clear(nn); 329 369 330 370 return L; -
Singular/misc_ip.h
r8b57f5 r511f2d 32 32 33 33 /** 34 * Divides 'n' as many times as possible by 'd' and returns the number35 * of divisions (without remainder) in 'times',36 * e.g., n = 48, d = 4, divTimes(n, d, t) = 3 produces n = 3, t = 2,37 * since 48 = 4*4*3;38 * assumes that d is positive39 **/40 void divTimes(mpz_t n, /**< [in] a GMP number >= 0 */41 mpz_t d, /**< [in] the divisor, a GMP number >= 0 */42 int* times /**< [out] number of divisions without remainder */43 );44 45 /**46 34 * Factorises a given bigint number n into its prime factors less 47 35 * than or equal to a given bound, with corresponding multiplicities. … … 52 40 * Also, when n is negative, m will contain the sign. If n is zero, m will 53 41 * be zero. 54 * The method returns a list L filled with fourentries:42 * The method returns a list L filled with three entries: 55 43 * L[1] a list; L[1][i] contains the i-th prime factor of |n| as int or 56 44 * bigint (sorted in ascending order), 57 45 * L[2] a list; L[2][i] contains the multiplicity of L[1, i] in |n| as int 58 46 * L[3] contains the remainder m as int or bigint, depending on the size, 59 * L[4] 1 iff |m| is probably a prime, 0 otherwise60 47 * 61 * We thus have: n = L[1][1]^L[2][1] * ... * L[1][k]^L[2][k] * L[ 1], where48 * We thus have: n = L[1][1]^L[2][1] * ... * L[1][k]^L[2][k] * L[3], where 62 49 * k is the number of mutually distinct prime factors (<= a provided non- 63 50 * zero bound). 64 * Note that for n = 0, L[ 2] and L[3] will be emtpy lists and L[4] will be51 * Note that for n = 0, L[1] and L[2] will be emtpy lists and L[3] will be 65 52 * zero. 66 53 * … … 69 56 lists primeFactorisation( 70 57 const number n, /**< [in] the bigint > 0 to be factorised */ 71 const number pBound /**< [in] bigintbound on the prime factors58 const int pBound /**< [in] bound on the prime factors 72 59 seeked */ 73 60 ); -
Singular/table.h
r8b57f5 r511f2d 609 609 ,{D(jjRES), MRES_CMD, RESOLUTION_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} 610 610 //,{D(nuMPResMat), MPRES_CMD, MODUL_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} 611 ,{D(jjPFAC2), PFAC_CMD, LIST_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL |ALLOW_RING} 612 ,{D(jjPFAC2), PFAC_CMD, LIST_CMD, NUMBER_CMD, BIGINT_CMD, ALLOW_PLURAL |ALLOW_RING} 613 ,{D(jjPFAC2), PFAC_CMD, LIST_CMD, BIGINT_CMD, NUMBER_CMD, ALLOW_PLURAL |ALLOW_RING} 614 ,{D(jjPFAC2), PFAC_CMD, LIST_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL |ALLOW_RING} 611 ,{D(jjPFAC2), PFAC_CMD, LIST_CMD, BIGINT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} 612 ,{D(jjPFAC2), PFAC_CMD, LIST_CMD, NUMBER_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} 615 613 #ifdef HAVE_PLURAL 616 614 ,{D(jjPlural_num_poly), NCALGEBRA_CMD,NONE, POLY_CMD, POLY_CMD , NO_PLURAL |NO_RING} -
factory/cf_gcd_smallp.cc
r8b57f5 r511f2d 4606 4606 maxeval= tmin (2*ipower (p, getGFDegree()), maxNumEval); 4607 4607 } 4608 else if (p < 50 && algExtension && !CFFactory::gettype() == GaloisFieldDomain)4608 else if (p < 50 && algExtension && CFFactory::gettype() != GaloisFieldDomain) 4609 4609 { 4610 4610 int d= degree (getMipo (a));
Note: See TracChangeset
for help on using the changeset viewer.