[731582] | 1 | #include "misc/auxiliary.h" |
---|
| 2 | |
---|
| 3 | #include "misc/intvec.h" |
---|
| 4 | #include "misc/options.h" |
---|
| 5 | #include "polys/monomials/p_polys.h" |
---|
| 6 | #include "polys/matpol.h" |
---|
| 7 | #include "polys/simpleideals.h" |
---|
| 8 | #include "coeffs/longrat.h" |
---|
| 9 | #include "Singular/feOpt.h" |
---|
| 10 | #include "kernel/polys.h" |
---|
[4b1552] | 11 | #include "kernel/mod2.h" |
---|
[731582] | 12 | |
---|
[4b1552] | 13 | #ifdef HAVE_VSPACE |
---|
[59d96d] | 14 | |
---|
[731582] | 15 | #define mpz_isNeg(A) ((A)->_mp_size<0) |
---|
| 16 | number nlRInit (long i); |
---|
| 17 | |
---|
| 18 | #include "kernel/oswrapper/vspace.h" |
---|
[7090a8b] | 19 | #include "kernel/ideals.h" |
---|
[731582] | 20 | #include <sys/types.h> |
---|
| 21 | #include <sys/wait.h> |
---|
[2c69a8e] | 22 | #include <unistd.h> |
---|
[731582] | 23 | |
---|
| 24 | // send a number via a string s |
---|
| 25 | static char *send_number(char *s, number n) |
---|
| 26 | { |
---|
| 27 | long *d=(long*)s; |
---|
| 28 | if (SR_HDL(n) & SR_INT) |
---|
| 29 | { |
---|
| 30 | *d=(long)n; |
---|
| 31 | s+=SIZEOF_LONG; |
---|
| 32 | } |
---|
| 33 | else |
---|
| 34 | { |
---|
| 35 | *d=n->s*2;/* n->s in 0..3: 0..6, use +8 for neg. numbers */ |
---|
| 36 | s+=SIZEOF_LONG; |
---|
| 37 | if (mpz_isNeg(n->z)) { *d+=8; mpz_neg(n->z,n->z); } |
---|
| 38 | size_t l; |
---|
| 39 | d=(long*)s; |
---|
| 40 | s+=SIZEOF_LONG; |
---|
| 41 | mpz_export(s,&l,-1,sizeof(mp_limb_t),0,0,n->z); |
---|
| 42 | *d=l; |
---|
| 43 | s+=l*sizeof(mp_limb_t); |
---|
| 44 | if (n->s!=3) |
---|
| 45 | { |
---|
| 46 | d=(long*)s; |
---|
| 47 | s+=SIZEOF_LONG; |
---|
| 48 | mpz_export(s,&l,-1,sizeof(mp_limb_t),0,0,n->n); |
---|
| 49 | *d=l; |
---|
| 50 | s+=l*sizeof(mp_limb_t); |
---|
| 51 | } |
---|
| 52 | } |
---|
| 53 | return s; |
---|
| 54 | } |
---|
| 55 | |
---|
| 56 | static char * get_number(char *s, number *n) |
---|
| 57 | { |
---|
| 58 | // format: last bit 1: imm. number (long) |
---|
| 59 | // otherwise: 0,2: size(long) mpz, size(long) mpz |
---|
| 60 | // 6: size(long) mpz |
---|
| 61 | // 8,10: size(long) -mpz, size(long) mpz |
---|
| 62 | // 14: size(long) -mpz |
---|
| 63 | long *d=(long*)s; |
---|
| 64 | s+=SIZEOF_LONG; |
---|
| 65 | if (((*d)&1)==1) // immidiate number |
---|
| 66 | { |
---|
[572022] | 67 | *n=(number)(*d); |
---|
[731582] | 68 | } |
---|
| 69 | else |
---|
| 70 | { |
---|
| 71 | *n=nlRInit(0); |
---|
| 72 | BOOLEAN neg=(*d>=8); |
---|
| 73 | if (neg) *d-=8; |
---|
| 74 | (*n)->s=(*d)/2; |
---|
| 75 | d=(long*)s; |
---|
| 76 | s+=SIZEOF_LONG; |
---|
| 77 | size_t l=*d; |
---|
| 78 | mpz_realloc2((*n)->z,l*sizeof(mp_limb_t)*8); |
---|
| 79 | mpz_import((*n)->z,l,-1,sizeof(mp_limb_t),0,0,s); |
---|
| 80 | if (neg) mpz_neg((*n)->z,(*n)->z); |
---|
| 81 | s+=l*sizeof(mp_limb_t); |
---|
| 82 | if ((*n)->s!=3) |
---|
| 83 | { |
---|
| 84 | d=(long*)s; |
---|
| 85 | s+=SIZEOF_LONG; |
---|
| 86 | l=*d; |
---|
| 87 | mpz_init2((*n)->n,l*sizeof(mp_limb_t)*8); |
---|
| 88 | mpz_import((*n)->n,l,-1,sizeof(mp_limb_t),0,0,s); |
---|
| 89 | s+=l*sizeof(mp_limb_t); |
---|
| 90 | } |
---|
| 91 | } |
---|
| 92 | return s; |
---|
| 93 | } |
---|
| 94 | |
---|
| 95 | static long size_number(number n) |
---|
| 96 | { |
---|
| 97 | long ll=SIZEOF_LONG; |
---|
| 98 | if (SR_HDL(n) & SR_INT) |
---|
| 99 | { |
---|
| 100 | return SIZEOF_LONG; |
---|
| 101 | } |
---|
| 102 | else |
---|
| 103 | { |
---|
[572022] | 104 | if (n->s==3) |
---|
[731582] | 105 | { |
---|
[ec23b4] | 106 | ll+=SIZEOF_LONG*2; /* n->s, mpz size */ |
---|
[731582] | 107 | long l=mpz_size1(n->z); |
---|
| 108 | ll+=l*sizeof(mp_limb_t); |
---|
| 109 | } |
---|
| 110 | else |
---|
| 111 | { |
---|
[ec23b4] | 112 | ll+=SIZEOF_LONG*3; /* n->s, mpz size(n->z) mpz size(n->n)*/ |
---|
| 113 | size_t l=mpz_size1(n->z); |
---|
[731582] | 114 | ll+=l*sizeof(mp_limb_t); |
---|
| 115 | l=mpz_size1(n->n); |
---|
| 116 | ll+=l*sizeof(mp_limb_t); |
---|
| 117 | } |
---|
| 118 | } |
---|
| 119 | return ll; |
---|
| 120 | } |
---|
| 121 | |
---|
| 122 | static char* send_mon(char *s, poly m, const ring r) |
---|
| 123 | { |
---|
| 124 | // format: number exp[0..r->ExpL_Size] |
---|
| 125 | s=send_number(s,p_GetCoeff(m,r)); |
---|
| 126 | memcpy(s,m->exp,r->ExpL_Size*sizeof(long)); |
---|
| 127 | s+=r->ExpL_Size*sizeof(long); |
---|
| 128 | return s; |
---|
| 129 | } |
---|
| 130 | |
---|
| 131 | static char* get_mon(char *s, poly *m, const ring r) |
---|
| 132 | { |
---|
| 133 | (*m)=p_Init(r); |
---|
| 134 | s=get_number(s,&p_GetCoeff(*m,r)); |
---|
| 135 | memcpy((*m)->exp,s,r->ExpL_Size*sizeof(long)); |
---|
| 136 | s+=r->ExpL_Size*sizeof(long); |
---|
| 137 | return s; |
---|
| 138 | } |
---|
| 139 | |
---|
| 140 | static long size_mon(poly m, const ring r) |
---|
| 141 | { |
---|
| 142 | long ll=size_number(p_GetCoeff(m,r)); |
---|
| 143 | ll+=r->ExpL_Size*sizeof(long); |
---|
| 144 | return ll; |
---|
| 145 | } |
---|
| 146 | |
---|
| 147 | static char* send_poly(char *s, int ind, poly p, const ring r) |
---|
| 148 | { |
---|
| 149 | // format: index(long) length(long) mon... |
---|
| 150 | //p_Write(p,r);PrintLn(); |
---|
| 151 | long *d=(long*)s; |
---|
| 152 | *d=ind; |
---|
| 153 | s+=SIZEOF_LONG; |
---|
| 154 | long l=pLength(p); |
---|
| 155 | d=(long*)s; |
---|
| 156 | *d=l; |
---|
| 157 | s+=SIZEOF_LONG; |
---|
| 158 | while(p!=NULL) |
---|
| 159 | { |
---|
| 160 | s=send_mon(s,p,r); |
---|
| 161 | pIter(p); |
---|
| 162 | } |
---|
| 163 | return s; |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | static char* get_poly(char *s,int &ind, poly *p,const ring r) |
---|
| 167 | { |
---|
| 168 | long *d=(long*)s; |
---|
| 169 | ind=*d; |
---|
| 170 | s+=SIZEOF_LONG; |
---|
| 171 | d=(long*)s; |
---|
| 172 | long l=*d; |
---|
| 173 | s+=SIZEOF_LONG; |
---|
| 174 | for(long i=0;i<l;i++) |
---|
| 175 | { |
---|
| 176 | poly m; |
---|
| 177 | s=get_mon(s,&m,r); |
---|
| 178 | pNext(m)=*p; |
---|
| 179 | *p=m; |
---|
| 180 | } |
---|
| 181 | *p=pReverse(*p); |
---|
| 182 | return s; |
---|
| 183 | } |
---|
| 184 | |
---|
| 185 | static long size_poly(poly p, const ring r) |
---|
| 186 | { |
---|
| 187 | long l=SIZEOF_LONG*2; |
---|
| 188 | while(p!=NULL) |
---|
| 189 | { |
---|
| 190 | l+=size_mon(p,r); |
---|
| 191 | pIter(p); |
---|
| 192 | } |
---|
| 193 | return l; |
---|
| 194 | } |
---|
| 195 | |
---|
| 196 | ideal id_ChineseRemainder_0(ideal *xx, number *q, int rl, const ring r) |
---|
| 197 | { |
---|
| 198 | int cnt=0;int rw=0; int cl=0; |
---|
| 199 | // find max. size of xx[.]: |
---|
[7090a8b] | 200 | for(int j=rl-1;j>=0;j--) |
---|
[731582] | 201 | { |
---|
[7090a8b] | 202 | int i=IDELEMS(xx[j])*xx[j]->nrows; |
---|
[731582] | 203 | if (i>cnt) cnt=i; |
---|
| 204 | if (xx[j]->nrows >rw) rw=xx[j]->nrows; // for lifting matrices |
---|
| 205 | if (xx[j]->ncols >cl) cl=xx[j]->ncols; // for lifting matrices |
---|
| 206 | } |
---|
| 207 | if (rw*cl !=cnt) |
---|
| 208 | { |
---|
| 209 | WerrorS("format mismatch in CRT"); |
---|
| 210 | return NULL; |
---|
| 211 | } |
---|
[ec23b4] | 212 | int cpus=(int)(long)feOptValue(FE_OPT_CPUS); |
---|
[017498] | 213 | if (cpus>=vspace::internals::MAX_PROCESS) |
---|
| 214 | cpus=vspace::internals::MAX_PROCESS-1; |
---|
| 215 | /* start no more than MAX_PROCESS-1 children */ |
---|
[478cfe] | 216 | if ((cpus==1) || (2*cpus>=cnt)) |
---|
| 217 | /* at least 2 polys for each process, or switch to seriell version */ |
---|
[ec23b4] | 218 | return id_ChineseRemainder(xx,q,rl,r); |
---|
[731582] | 219 | ideal result=idInit(cnt,xx[0]->rank); |
---|
| 220 | result->nrows=rw; // for lifting matrices |
---|
| 221 | result->ncols=cl; // for lifting matrices |
---|
| 222 | int parent_pid=getpid(); |
---|
| 223 | using namespace vspace; |
---|
| 224 | vmem_init(); |
---|
| 225 | // Create a queue of int |
---|
| 226 | VRef<Queue<int> > queue = vnew<Queue<int> >(); |
---|
[7090a8b] | 227 | for(int i=cnt-1;i>=0; i--) |
---|
[731582] | 228 | { |
---|
[7090a8b] | 229 | queue->enqueue(i); // the tasks: construct poly p[i] |
---|
[731582] | 230 | } |
---|
| 231 | for(int i=cpus;i>=0;i--) |
---|
| 232 | { |
---|
| 233 | queue->enqueue(-1); // stop sign, one for each child |
---|
| 234 | } |
---|
| 235 | // Create a queue of polys |
---|
| 236 | VRef<Queue<VRef<VString> > > rqueue = vnew<Queue<VRef<VString> > >(); |
---|
[7090a8b] | 237 | for (int i=0;i<cpus;i++) |
---|
[731582] | 238 | { |
---|
| 239 | int pid = fork_process(); |
---|
| 240 | if (pid==0) break; //child |
---|
| 241 | } |
---|
| 242 | if (parent_pid!=getpid()) // child ------------------------------------------ |
---|
| 243 | { |
---|
| 244 | number *x=(number *)omAlloc(rl*sizeof(number)); |
---|
| 245 | poly *p=(poly *)omAlloc(rl*sizeof(poly)); |
---|
| 246 | CFArray inv_cache(rl); |
---|
| 247 | EXTERN_VAR int n_SwitchChinRem; |
---|
| 248 | n_SwitchChinRem=1; |
---|
| 249 | loop |
---|
| 250 | { |
---|
| 251 | int ind=queue->dequeue(); |
---|
| 252 | if (ind== -1) |
---|
| 253 | { |
---|
| 254 | exit(0); |
---|
| 255 | } |
---|
| 256 | |
---|
[7090a8b] | 257 | for(int j=rl-1;j>=0;j--) |
---|
[731582] | 258 | { |
---|
| 259 | if(ind>=IDELEMS(xx[j])*xx[j]->nrows) // out of range of this ideal |
---|
| 260 | p[j]=NULL; |
---|
| 261 | else |
---|
| 262 | p[j]=xx[j]->m[ind]; |
---|
| 263 | } |
---|
| 264 | poly res=p_ChineseRemainder(p,x,q,rl,inv_cache,r); |
---|
| 265 | long l=size_poly(res,r); |
---|
| 266 | //printf("size: %ld kB\n",(l+1023)/1024); |
---|
| 267 | VRef<VString> msg = vstring(l+1); |
---|
| 268 | char *s=(char*)msg->str(); |
---|
| 269 | send_poly(s,ind,res,r); |
---|
| 270 | rqueue->enqueue(msg); |
---|
| 271 | if (TEST_OPT_PROT) printf("."); |
---|
[7090a8b] | 272 | } |
---|
| 273 | } |
---|
| 274 | else // parent --------------------------------------------------- |
---|
| 275 | { |
---|
[1540e9] | 276 | if (TEST_OPT_PROT) printf("%d children created\n",cpus); |
---|
[7090a8b] | 277 | VRef<VString> msg; |
---|
| 278 | while(cnt>0) |
---|
| 279 | { |
---|
| 280 | msg=rqueue->dequeue(); |
---|
| 281 | char *s=(char*)msg->str(); |
---|
| 282 | int ind; |
---|
| 283 | poly p=NULL; |
---|
| 284 | get_poly(s,ind,&p,r); |
---|
| 285 | //printf("got res[%d]\n",ind); |
---|
| 286 | result->m[ind]=p; |
---|
| 287 | msg.free(); |
---|
| 288 | cnt--; |
---|
| 289 | } |
---|
| 290 | // removes queues |
---|
| 291 | queue.free(); |
---|
| 292 | rqueue.free(); |
---|
| 293 | vmem_deinit(); |
---|
| 294 | } |
---|
| 295 | return result; |
---|
| 296 | } |
---|
| 297 | |
---|
| 298 | ideal id_Farey_0(ideal x, number N, const ring r) |
---|
| 299 | { |
---|
| 300 | int cnt=IDELEMS(x)*x->nrows; |
---|
| 301 | int cpus=(int)(long)feOptValue(FE_OPT_CPUS); |
---|
[2dfae4] | 302 | if (cpus>=vspace::internals::MAX_PROCESS) |
---|
| 303 | cpus=vspace::internals::MAX_PROCESS-1; |
---|
[4c486e] | 304 | /* start no more than MAX_PROCESS-1 children */ |
---|
[572022] | 305 | if (2*cpus>=cnt) /* at least 2 polys for each process, |
---|
[7090a8b] | 306 | or switch to seriell version */ |
---|
| 307 | return id_Farey(x,N,r); |
---|
| 308 | ideal result=idInit(cnt,x->rank); |
---|
| 309 | result->nrows=x->nrows; // for lifting matrices |
---|
| 310 | result->ncols=x->ncols; // for lifting matrices |
---|
| 311 | |
---|
| 312 | int parent_pid=getpid(); |
---|
| 313 | using namespace vspace; |
---|
| 314 | vmem_init(); |
---|
| 315 | // Create a queue of int |
---|
| 316 | VRef<Queue<int> > queue = vnew<Queue<int> >(); |
---|
| 317 | for(int i=cnt-1;i>=0; i--) |
---|
| 318 | { |
---|
| 319 | queue->enqueue(i); // the tasks: construct poly p[i] |
---|
| 320 | } |
---|
| 321 | for(int i=cpus;i>=0;i--) |
---|
| 322 | { |
---|
| 323 | queue->enqueue(-1); // stop sign, one for each child |
---|
| 324 | } |
---|
| 325 | // Create a queue of polys |
---|
| 326 | VRef<Queue<VRef<VString> > > rqueue = vnew<Queue<VRef<VString> > >(); |
---|
| 327 | for (int i=0;i<cpus;i++) |
---|
| 328 | { |
---|
| 329 | int pid = fork_process(); |
---|
| 330 | if (pid==0) break; //child |
---|
| 331 | } |
---|
| 332 | if (parent_pid!=getpid()) // child ------------------------------------------ |
---|
| 333 | { |
---|
| 334 | loop |
---|
| 335 | { |
---|
| 336 | int ind=queue->dequeue(); |
---|
| 337 | if (ind== -1) |
---|
| 338 | { |
---|
| 339 | exit(0); |
---|
| 340 | } |
---|
| 341 | |
---|
| 342 | poly res=p_Farey(x->m[ind],N,r); |
---|
| 343 | long l=size_poly(res,r); |
---|
| 344 | VRef<VString> msg = vstring(l+1); |
---|
| 345 | char *s=(char*)msg->str(); |
---|
| 346 | send_poly(s,ind,res,r); |
---|
| 347 | rqueue->enqueue(msg); |
---|
| 348 | if (TEST_OPT_PROT) printf("."); |
---|
[731582] | 349 | } |
---|
| 350 | } |
---|
| 351 | else // parent --------------------------------------------------- |
---|
| 352 | { |
---|
[1540e9] | 353 | if (TEST_OPT_PROT) printf("%d children created\n",cpus); |
---|
[731582] | 354 | VRef<VString> msg; |
---|
| 355 | while(cnt>0) |
---|
| 356 | { |
---|
| 357 | msg=rqueue->dequeue(); |
---|
| 358 | char *s=(char*)msg->str(); |
---|
| 359 | int ind; |
---|
| 360 | poly p=NULL; |
---|
| 361 | get_poly(s,ind,&p,r); |
---|
| 362 | //printf("got res[%d]\n",ind); |
---|
| 363 | result->m[ind]=p; |
---|
| 364 | msg.free(); |
---|
| 365 | cnt--; |
---|
| 366 | } |
---|
[749d24] | 367 | // wait for the children to finish |
---|
| 368 | sleep(1); |
---|
[731582] | 369 | // removes queues |
---|
| 370 | queue.free(); |
---|
| 371 | rqueue.free(); |
---|
| 372 | vmem_deinit(); |
---|
| 373 | } |
---|
| 374 | return result; |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | void test_n(poly n) |
---|
| 378 | { |
---|
| 379 | p_Write(n,currRing); |
---|
| 380 | char *buf=(char*)omAlloc0(2048*1000); |
---|
| 381 | int ll=size_poly(n,currRing); |
---|
| 382 | printf("size: %d\n",ll); |
---|
| 383 | char *s=send_poly(buf,12345,n,currRing); |
---|
| 384 | printf("send len: %d\n",(int)(s-buf)); |
---|
| 385 | long *d=(long*)buf; |
---|
[ec23b4] | 386 | for(int i=0;i<=ll/SIZEOF_LONG;i++) printf("%ld ",d[i]); |
---|
[731582] | 387 | printf("\n"); |
---|
| 388 | n=NULL; |
---|
| 389 | s=get_poly(buf,ll,&n,currRing); |
---|
| 390 | printf("read len: %d\n",(int)(s-buf)); |
---|
| 391 | Print(":index: %d\n",ll); |
---|
| 392 | p_Write(n,currRing); |
---|
| 393 | PrintLn(); |
---|
[ec23b4] | 394 | omFree(buf); |
---|
[731582] | 395 | } |
---|
[59d96d] | 396 | #endif |
---|