Changeset 58603f in git for libpolys/polys/flint_mpoly.cc
- Timestamp:
- Aug 4, 2019, 9:34:39 PM (5 years ago)
- Branches:
- (u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
- Children:
- 2f9e3f171a90f561e7a3c81734eb72998dc8fe82
- Parents:
- 112c79d4f91036791f523bcfbb261d1ba63c2d8f557b878dd8c840afb5ec95de122ba27a0ec99926
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libpolys/polys/flint_mpoly.cc
r112c79 r58603f 65 65 #if 1 66 66 // memory allocation is not thread safe; singular polynomials must be constructed in serial 67 68 /* 69 We agree the that result of a singular -> fmpq_mpoly conversion is 70 readonly. This restricts the usage of the result in flint functions to 71 const arguments. However, the real readonly conversion is currently only 72 implemented in the threaded conversion below since it requires a scan of 73 all coefficients anyways. The _fmpq_mpoly_clear_readonly_sing needs to 74 be provided for a consistent interface in the polynomial operations. 75 */ 76 static void _fmpq_mpoly_clear_readonly_sing(fmpq_mpoly_t a, fmpq_mpoly_ctx_t ctx) 77 { 78 fmpq_mpoly_clear(a, ctx); 79 } 67 80 68 81 void convSingPFlintMP(fmpq_mpoly_t res, fmpq_mpoly_ctx_t ctx, poly p, int lp, const ring r) … … 186 199 } 187 200 201 202 /* 203 In order that flint may sometimes borrow the large integer coeffs of 204 polynomials over QQ (borrow means: simply point to the same GMP structs 205 that singular has already allocated), we define the result of a 206 singular -> fmpq_mpoly conversion to be readonly. This means we agree 207 that 208 - it can only be used as an const argument to a flint function 209 - singular must not mutate the original coeffs while the readonly object is in use 210 */ 211 212 static void _fmpq_mpoly_clear_readonly_sing(fmpq_mpoly_t a, fmpq_mpoly_ctx_t ctx) 213 { 214 if (fmpq_is_one(a->content)) 215 { 216 if (a->zpoly->alloc > 0) 217 { 218 flint_free(a->zpoly->coeffs); 219 flint_free(a->zpoly->exps); 220 } 221 222 fmpq_clear(a->content); 223 } 224 else 225 { 226 fmpq_mpoly_clear(a, ctx); 227 } 228 } 229 188 230 /* singular -> fmpq_mpoly conversion */ 189 231 … … 197 239 std::vector<poly> markers; 198 240 ring r; 199 200 convert_sing_to_fmpq_mpoly_base(slong num_threads_, fmpq_mpoly_struct * res_, 201 const fmpq_mpoly_ctx_struct * ctx_, const ring r_, poly p) 202 : num_threads(num_threads_), 241 fmpq_t content; 242 243 convert_sing_to_fmpq_mpoly_base(fmpq_mpoly_struct * res_, 244 const fmpq_mpoly_ctx_struct * ctx_, const ring r_, poly p) 245 : num_threads(0), 203 246 res(res_), 204 247 ctx(ctx_), 205 248 r(r_) 206 249 { 250 fmpq_t c; 251 fmpq_init(c); 252 fmpq_init(content); 253 fmpq_zero(content); 254 207 255 length = 0; 208 256 while (1) 209 257 { 210 258 if ((length % 4096) == 0) 259 { 260 my_convSingNFlintN_QQ(c, number(pGetCoeff(p))); 261 fmpq_gcd(content, content, c); 211 262 markers.push_back(p); 263 } 212 264 if (p == NULL) 213 265 return; … … 215 267 pIter(p); 216 268 } 269 270 fmpq_clear(c); 271 } 272 273 ~convert_sing_to_fmpq_mpoly_base() 274 { 275 fmpq_clear(content); 217 276 } 218 277 }; … … 248 307 249 308 flint_bitcnt_t required_bits = MPOLY_MIN_BITS; 250 fmpq_ zero(arg->content);309 fmpq_set(arg->content, base->content); 251 310 252 311 while (idx < arg->end_idx) 253 312 { 254 my_convSingNFlintN_QQ(c, number(pGetCoeff(p))); 255 fmpq_gcd(arg->content, arg->content, c); 313 number n = number(pGetCoeff(p)); 314 315 if (fmpq_is_one(arg->content) && (SR_HDL(n)&SR_INT || n->s >= 3)) 316 { 317 /* content is 1 and n is an integer, nothing to do */ 318 } 319 else 320 { 321 my_convSingNFlintN_QQ(c, n); 322 fmpq_gcd(arg->content, arg->content, c); 323 } 256 324 257 325 #if SIZEOF_LONG==8 … … 293 361 } 294 362 363 slong N = mpoly_words_per_exp(base->res->zpoly->bits, base->ctx->zctx->minfo); 364 fmpz * res_coeffs = base->res->zpoly->coeffs; 365 ulong * res_exps = base->res->zpoly->exps; 366 flint_bitcnt_t res_bits = base->res->zpoly->bits; 367 295 368 while (idx < arg->end_idx) 296 369 { 297 my_convSingNFlintN_QQ(c, number(pGetCoeff(p))); 298 FLINT_ASSERT(!fmpq_is_zero(base->res->content)); 299 fmpq_div(t, c, base->res->content); 300 FLINT_ASSERT(fmpz_is_one(fmpq_denref(t))); 301 302 slong N = mpoly_words_per_exp(base->res->zpoly->bits, base->ctx->zctx->minfo); 303 fmpz_swap(base->res->zpoly->coeffs + idx, fmpq_numref(t)); 370 if (fmpq_is_one(base->res->content)) 371 { 372 // borrowing singular integers 373 // the entry res_coeffs[idx] is junk, we should just overwrite it 374 375 number n = number(pGetCoeff(p)); 376 377 if (SR_HDL(n)&SR_INT) 378 { 379 // n is a singular-small integer 380 res_coeffs[idx] = SR_TO_INT(n); 381 } 382 else if (n->s<3) 383 { 384 // n is an element of QQ \ ZZ, should not happen 385 assume(false); 386 } 387 else 388 { 389 // n is a singular-large integer, n may be flint-small 390 res_coeffs[idx] = PTR_TO_COEFF(n->z); 391 if (fmpz_fits_si(res_coeffs + idx)) 392 { 393 slong val = fmpz_get_si(res_coeffs + idx); 394 if (val >= COEFF_MIN && val <= COEFF_MAX) 395 res_coeffs[idx] = val; 396 } 397 } 398 } 399 else 400 { 401 my_convSingNFlintN_QQ(c, number(pGetCoeff(p))); 402 FLINT_ASSERT(!fmpq_is_zero(base->res->content)); 403 fmpq_div(t, c, base->res->content); 404 FLINT_ASSERT(fmpz_is_one(fmpq_denref(t))); 405 fmpz_swap(res_coeffs + idx, fmpq_numref(t)); 406 } 407 304 408 #if SIZEOF_LONG==8 305 409 p_GetExpVL(p, (int64*)exp, base->r); 306 mpoly_set_monomial_ui( base->res->zpoly->exps + N*idx, exp, base->res->zpoly->bits, base->ctx->zctx->minfo);410 mpoly_set_monomial_ui(res_exps + N*idx, exp, res_bits, base->ctx->zctx->minfo); 307 411 #else 308 412 p_GetExpV(p, (int*)exp, base->r); 309 mpoly_set_monomial_ui( base->res->zpoly->exps + N*idx, &(exp[1]), base->res->zpoly->bits, base->ctx->minfo);413 mpoly_set_monomial_ui(res_exps + N*idx, &(exp[1]), res_bits, base->ctx->minfo); 310 414 #endif 311 415 … … 324 428 thread_pool_handle * handles; 325 429 slong num_handles; 326 slong thread_limit = 1000; 327 328 /* get workers */ 430 slong thread_limit = 1000; // TODO: should be paramter to this function 431 432 /* the constructor works out the length of p and sets some markers */ 433 convert_sing_to_fmpq_mpoly_base base(res, ctx, r, p); 434 435 /* sensibly limit thread count and get workers */ 436 thread_limit = FLINT_MIN(thread_limit, base.length/1024); 329 437 handles = NULL; 330 438 num_handles = 0; … … 340 448 } 341 449 342 convert_sing_to_fmpq_mpoly_base base(num_handles + 1, res, ctx, r, p);343 344 450 /* fill in thread division points */ 451 base.num_threads = 1 + num_handles; 345 452 convert_sing_to_fmpq_mpoly_arg * args = new convert_sing_to_fmpq_mpoly_arg[base.num_threads]; 346 453 slong cur_idx = 0; … … 348 455 { 349 456 slong next_idx = i + 1 < base.num_threads ? (i + 1)*base.length/base.num_threads : base.length; 457 FLINT_ASSERT(cur_idx <= base.length); 350 458 next_idx = FLINT_MAX(next_idx, cur_idx); 351 459 next_idx = FLINT_MIN(next_idx, base.length); … … 367 475 required_bits = FLINT_MAX(required_bits, args[i].required_bits); 368 476 369 /* initialize res with optimal bits */370 fmpq_mpoly_init3(res, base.length, mpoly_fix_bits(required_bits, ctx->zctx->minfo), ctx);371 372 477 /* sign of content should match sign of first coeff */ 373 fmpq_zero(base.res->content); 478 fmpq_t content; 479 fmpq_init(content); 480 fmpq_zero(content); 374 481 for (slong i = 0; i < base.num_threads; i++) 375 fmpq_gcd( base.res->content, base.res->content, args[i].content);482 fmpq_gcd(content, content, args[i].content); 376 483 if (p != NULL) 377 484 { … … 380 487 my_convSingNFlintN_QQ(c, number(pGetCoeff(p))); 381 488 if (fmpq_sgn(c) < 0) 382 fmpq_neg( base.res->content, base.res->content);489 fmpq_neg(content, content); 383 490 fmpq_clear(c); 384 491 } 492 493 /* initialize res with optimal bits */ 494 required_bits = mpoly_fix_bits(required_bits, ctx->zctx->minfo); 495 if (fmpq_is_one(content)) 496 { 497 /* initialize borrowed coeffs */ 498 slong N = mpoly_words_per_exp(required_bits, ctx->zctx->minfo); 499 slong alloc = base.length; 500 if (alloc != 0) 501 { 502 res->zpoly->coeffs = (fmpz *) flint_malloc(alloc*sizeof(fmpz)); 503 res->zpoly->exps = (ulong *) flint_malloc(alloc*N*sizeof(ulong)); 504 } 505 else 506 { 507 res->zpoly->coeffs = NULL; 508 res->zpoly->exps = NULL; 509 } 510 res->zpoly->alloc = alloc; 511 res->zpoly->length = 0; 512 res->zpoly->bits = required_bits; 513 514 fmpq_init(res->content); 515 fmpq_one(res->content); 516 } 517 else 518 { 519 /* initialize coeffs that will be created and destroyed */ 520 fmpq_mpoly_init3(res, base.length, required_bits, ctx); 521 fmpq_swap(res->content, content); 522 } 523 524 fmpq_clear(content); 385 525 386 526 /* fill in res->zpoly */ … … 468 608 thread_pool_handle * handles; 469 609 slong num_handles; 470 slong thread_limit = 1000; 471 472 /* get workers */ 610 slong thread_limit = 1000;// TODO: should be paramter to this function 611 612 /* sensibly limit threads and get workers */ 613 thread_limit = FLINT_MIN(thread_limit, f->zpoly->length/1024); 473 614 handles = NULL; 474 615 num_handles = 0; … … 485 626 486 627 convert_fmpq_mpoly_to_sing_base base(num_handles + 1, f, ctx, r); 487 488 628 convert_fmpq_mpoly_to_sing_arg * args = new convert_fmpq_mpoly_to_sing_arg[base.num_threads]; 489 629 slong cur_idx = 0; … … 492 632 slong next_idx = i + 1 < base.num_threads ? (i + 1)*base.f->zpoly->length/base.num_threads 493 633 : base.f->zpoly->length; 634 FLINT_ASSERT(cur_idx <= base.f->zpoly->length); 494 635 next_idx = FLINT_MAX(next_idx, cur_idx); 495 636 next_idx = FLINT_MIN(next_idx, base.f->zpoly->length); … … 542 683 ring r; 543 684 544 convert_sing_to_nmod_mpoly_base( slong num_threads_,nmod_mpoly_struct * res_,545 546 : num_threads( num_threads_),685 convert_sing_to_nmod_mpoly_base(nmod_mpoly_struct * res_, 686 const nmod_mpoly_ctx_struct * ctx_, const ring r_, poly p) 687 : num_threads(0), 547 688 res(res_), 548 689 ctx(ctx_), … … 624 765 } 625 766 767 slong N = mpoly_words_per_exp(base->res->bits, base->ctx->minfo); 768 ulong * res_coeffs = base->res->coeffs; 769 ulong * res_exps = base->res->exps; 770 flint_bitcnt_t res_bits = base->res->bits; 771 626 772 while (idx < arg->end_idx) 627 773 { 628 slong N = mpoly_words_per_exp(base->res->bits, base->ctx->minfo);629 774 #if SIZEOF_LONG==8 630 775 p_GetExpVL(p, (int64*)exp, base->r); 631 mpoly_set_monomial_ui( base->res->exps + N*idx, exp, base->res->bits, base->ctx->minfo);776 mpoly_set_monomial_ui(res_exps + N*idx, exp, res_bits, base->ctx->minfo); 632 777 #else 633 778 p_GetExpV(p, (int*)exp, base->r); 634 mpoly_set_monomial_ui( base->res->exps + N*idx, &(exp[1]), base->res->bits, base->ctx->minfo);779 mpoly_set_monomial_ui(res_exps + N*idx, &(exp[1]), res_bits, base->ctx->minfo); 635 780 #endif 636 781 637 base->res->coeffs[idx] = (ulong)(number(pGetCoeff(p)));782 res_coeffs[idx] = (ulong)(number(pGetCoeff(p))); 638 783 639 784 pIter(p); … … 649 794 thread_pool_handle * handles; 650 795 slong num_handles; 651 slong thread_limit = 1000; 652 653 /* get workers */ 796 slong thread_limit = 1000; // TODO: should be paramter to this function 797 798 /* the constructor works out the length of p and sets some markers */ 799 convert_sing_to_nmod_mpoly_base base(res, ctx, r, p); 800 801 /* sensibly limit thread count and get workers */ 802 thread_limit = FLINT_MIN(thread_limit, base.length/1024); 654 803 handles = NULL; 655 804 num_handles = 0; … … 665 814 } 666 815 667 convert_sing_to_nmod_mpoly_base base(num_handles + 1, res, ctx, r, p);668 669 816 /* fill in thread division points */ 817 base.num_threads = 1 + num_handles; 670 818 convert_sing_to_nmod_mpoly_arg * args = new convert_sing_to_nmod_mpoly_arg[base.num_threads]; 671 819 slong cur_idx = 0; … … 674 822 slong next_idx = i + 1 < base.num_threads ? (i + 1)*base.length/base.num_threads 675 823 : base.length; 824 FLINT_ASSERT(cur_idx <= base.length); 676 825 next_idx = FLINT_MAX(next_idx, cur_idx); 677 826 next_idx = FLINT_MIN(next_idx, base.length); … … 777 926 thread_pool_handle * handles; 778 927 slong num_handles; 779 slong thread_limit = 1000; 780 781 /* get workers */ 928 slong thread_limit = 1000; // TODO: should be paramter to this function 929 930 /* sensibly limit threads and get workers */ 931 thread_limit = FLINT_MIN(thread_limit, f->length/1024); 782 932 handles = NULL; 783 933 num_handles = 0; … … 794 944 795 945 convert_nmod_mpoly_to_sing_base base(num_handles + 1, f, ctx, r); 796 797 946 convert_nmod_mpoly_to_sing_arg * args = new convert_nmod_mpoly_to_sing_arg[base.num_threads]; 798 947 slong cur_idx = 0; … … 801 950 slong next_idx = i + 1 < base.num_threads ? (i + 1)*base.f->length/base.num_threads 802 951 : base.f->length; 952 FLINT_ASSERT(cur_idx <= base.f->length); 803 953 next_idx = FLINT_MAX(next_idx, cur_idx); 804 954 next_idx = FLINT_MIN(next_idx, base.f->length); … … 845 995 { 846 996 fmpq_mpoly_t pp,qq,res; 847 convSingPFlintMP(pp,ctx,p,lp,r); 848 convSingPFlintMP(qq,ctx,q,lq,r); 997 convSingPFlintMP(pp,ctx,p,lp,r); // pp read only 998 convSingPFlintMP(qq,ctx,q,lq,r); // qq read only 849 999 fmpq_mpoly_init(res,ctx); 850 1000 fmpq_mpoly_mul(res,pp,qq,ctx); 851 1001 poly pres=convFlintMPSingP(res,ctx,r); 852 1002 fmpq_mpoly_clear(res,ctx); 853 fmpq_mpoly_clear(pp,ctx);854 fmpq_mpoly_clear(qq,ctx);1003 _fmpq_mpoly_clear_readonly_sing(pp,ctx); 1004 _fmpq_mpoly_clear_readonly_sing(qq,ctx); 855 1005 fmpq_mpoly_ctx_clear(ctx); 856 1006 p_Test(pres,r); … … 878 1028 { 879 1029 fmpq_mpoly_t pp,qq,res; 880 convSingPFlintMP(pp,ctx,p,lp,r); 881 convSingPFlintMP(qq,ctx,q,lq,r); 1030 convSingPFlintMP(pp,ctx,p,lp,r); // pp read only 1031 convSingPFlintMP(qq,ctx,q,lq,r); // qq read only 882 1032 fmpq_mpoly_init(res,ctx); 883 1033 fmpq_mpoly_divides(res,pp,qq,ctx); 884 1034 poly pres = convFlintMPSingP(res,ctx,r); 885 1035 fmpq_mpoly_clear(res,ctx); 886 fmpq_mpoly_clear(pp,ctx);887 fmpq_mpoly_clear(qq,ctx);1036 _fmpq_mpoly_clear_readonly_sing(pp,ctx); 1037 _fmpq_mpoly_clear_readonly_sing(qq,ctx); 888 1038 fmpq_mpoly_ctx_clear(ctx); 889 1039 p_Test(pres,r); … … 934 1084 { 935 1085 fmpq_mpoly_t pp,qq,res; 936 convSingPFlintMP(pp,ctx,p,lp,r); 937 convSingPFlintMP(qq,ctx,q,lq,r); 1086 convSingPFlintMP(pp,ctx,p,lp,r); // pp read only 1087 convSingPFlintMP(qq,ctx,q,lq,r); // qq read only 938 1088 fmpq_mpoly_init(res,ctx); 939 1089 int ok=fmpq_mpoly_gcd(res,pp,qq,ctx); … … 959 1109 } 960 1110 fmpq_mpoly_clear(res,ctx); 961 fmpq_mpoly_clear(pp,ctx);962 fmpq_mpoly_clear(qq,ctx);1111 _fmpq_mpoly_clear_readonly_sing(pp,ctx); 1112 _fmpq_mpoly_clear_readonly_sing(qq,ctx); 963 1113 fmpq_mpoly_ctx_clear(ctx); 964 1114 return pres;
Note: See TracChangeset
for help on using the changeset viewer.