@@ -94,6 +94,22 @@ cdef class fmpq_mpoly_ctx(flint_mpoly_context):
94
94
fmpq_mpoly_ctx_init(self .val, nvars, ordering_py_to_c(ordering))
95
95
super ().__init__(nvars, names)
96
96
97
+ def any_as_scalar (self , other ):
98
+ if isinstance (other, int ):
99
+ return any_as_fmpq(other)
100
+ elif typecheck(other, fmpz):
101
+ return any_as_fmpq(other)
102
+ elif typecheck(other, fmpq):
103
+ res = fmpq.__new__ (fmpq)
104
+ fmpq_set((< fmpq> res).val, (< fmpq> other).val)
105
+ return res
106
+ else :
107
+ return NotImplemented
108
+
109
+ def scalar_as_mpoly (self , other: fmpq ):
110
+ # non-fmpq scalars should first be converted via self.any_as_scalar
111
+ return self .constant(< fmpq> other)
112
+
97
113
def nvars (self ):
98
114
"""
99
115
Return the number of variables in the context
@@ -336,205 +352,77 @@ cdef class fmpq_mpoly(flint_mpoly):
336
352
fmpq_mpoly_neg(res.val, (< fmpq_mpoly> self ).val, res.ctx.val)
337
353
return res
338
354
339
- def __add__ (self , other ):
340
- cdef fmpq_mpoly res
341
- if typecheck(other, fmpq_mpoly):
342
- if (< fmpq_mpoly> self ).ctx is not (< fmpq_mpoly> other).ctx:
343
- raise IncompatibleContextError(f" {(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}" )
344
- res = create_fmpq_mpoly(self .ctx)
345
- fmpq_mpoly_add(res.val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, res.ctx.val)
346
- return res
347
- else :
348
- other = any_as_fmpq(other)
349
- if other is not NotImplemented :
350
- res = create_fmpq_mpoly(self .ctx)
351
- fmpq_mpoly_add_fmpq(res.val, (< fmpq_mpoly> self ).val, (< fmpq> other).val, res.ctx.val)
352
- return res
353
- return NotImplemented
354
-
355
- def __radd__ (self , other ):
356
- cdef fmpq_mpoly res
357
- other = any_as_fmpq(other)
358
- if other is not NotImplemented :
359
- res = create_fmpq_mpoly(self .ctx)
360
- fmpq_mpoly_add_fmpq(res.val, (< fmpq_mpoly> self ).val, (< fmpq> other).val, res.ctx.val)
361
- return res
362
- return NotImplemented
363
355
364
- def __sub__ (self , other ):
365
- cdef fmpq_mpoly res
366
- if typecheck(other, fmpq_mpoly):
367
- if (< fmpq_mpoly> self ).ctx is not (< fmpq_mpoly> other).ctx:
368
- raise IncompatibleContextError(f" {(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}" )
369
- res = create_fmpq_mpoly(self .ctx)
370
- fmpq_mpoly_sub(res.val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, res.ctx.val)
371
- return res
372
- else :
373
- other = any_as_fmpq(other)
374
- if other is not NotImplemented :
375
- res = create_fmpq_mpoly(self .ctx)
376
- fmpq_mpoly_sub_fmpq(res.val, (< fmpq_mpoly> self ).val, (< fmpq> other).val, res.ctx.val)
377
- return res
378
- return NotImplemented
379
-
380
- def __rsub__ (self , other ):
381
- cdef fmpq_mpoly res
382
- other = any_as_fmpq(other)
383
- if other is not NotImplemented :
384
- res = create_fmpq_mpoly(self .ctx)
385
- fmpq_mpoly_sub_fmpq(res.val, (< fmpq_mpoly> self ).val, (< fmpq> other).val, res.ctx.val)
386
- return - res
387
- return NotImplemented
388
-
389
- def __mul__ (self , other ):
390
- cdef fmpq_mpoly res
391
- if typecheck(other, fmpq_mpoly):
392
- if (< fmpq_mpoly> self ).ctx is not (< fmpq_mpoly> other).ctx:
393
- raise IncompatibleContextError(f" {(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}" )
394
- res = create_fmpq_mpoly(self .ctx)
395
- fmpq_mpoly_mul(res.val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, res.ctx.val)
396
- return res
397
- else :
398
- other = any_as_fmpq(other)
399
- if other is not NotImplemented :
400
- res = create_fmpq_mpoly(self .ctx)
401
- fmpq_mpoly_scalar_mul_fmpq(res.val, (< fmpq_mpoly> self ).val, (< fmpq> other).val, res.ctx.val)
402
- return res
403
- return NotImplemented
404
-
405
- def __rmul__ (self , other ):
356
+ def _add_scalar_ (self , other: fmpq ):
406
357
cdef fmpq_mpoly res
407
- other = any_as_fmpq(other)
408
- if other is not NotImplemented :
409
- res = create_fmpq_mpoly(self .ctx)
410
- fmpq_mpoly_scalar_mul_fmpq(res.val, (< fmpq_mpoly> self ).val, (< fmpq> other).val, res.ctx.val)
411
- return res
412
- return NotImplemented
358
+ res = create_fmpq_mpoly(self .ctx)
359
+ fmpq_mpoly_add_fmpq(res.val, self .val, other.val, self .ctx.val)
360
+ return res
413
361
414
- def __pow__ (self , other , modulus ):
362
+ def _add_mpoly_ (self , other: fmpq_mpoly ):
415
363
cdef fmpq_mpoly res
416
- if modulus is not None :
417
- raise NotImplementedError
418
- other = any_as_fmpz(other)
419
- if other is NotImplemented :
420
- return other
421
- if other < 0 :
422
- raise ValueError (" cannot raise fmpq_mpoly to negative power" )
423
364
res = create_fmpq_mpoly(self .ctx)
424
- if fmpq_mpoly_pow_fmpz(res.val, (< fmpq_mpoly> self ).val, (< fmpz> other).val, res.ctx.val) == 0 :
425
- raise ValueError (" unreasonably large polynomial" ) # pragma: no cover
365
+ fmpq_mpoly_add(res.val, self .val, other.val, res.ctx.val)
426
366
return res
427
367
428
- def __divmod__ (self , other ):
429
- cdef fmpq_mpoly res, res2
430
- if typecheck(other, fmpq_mpoly):
431
- if not other:
432
- raise ZeroDivisionError (" fmpq_mpoly division by zero" )
433
- elif (< fmpq_mpoly> self ).ctx is not (< fmpq_mpoly> other).ctx:
434
- raise IncompatibleContextError(f" {(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}" )
435
- res = create_fmpq_mpoly(self .ctx)
436
- res2 = create_fmpq_mpoly(self .ctx)
437
- fmpq_mpoly_divrem(res.val, res2.val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, res.ctx.val)
438
- return (res, res2)
439
- else :
440
- other = any_as_fmpq(other)
441
- if other is not NotImplemented :
442
- other = fmpq_mpoly(other, self .ctx)
443
- if not other:
444
- raise ZeroDivisionError (" fmpq_mpoly division by zero" )
445
- res = create_fmpq_mpoly(self .ctx)
446
- res2 = create_fmpq_mpoly(self .ctx)
447
- fmpq_mpoly_divrem(res.val, res2.val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, res.ctx.val)
448
- return (res, res2)
449
- return NotImplemented
450
-
451
- def __rdivmod__ (self , other ):
452
- cdef fmpq_mpoly res, res2
453
- if not self :
454
- raise ZeroDivisionError (" fmpq_mpoly division by zero" )
455
- other = any_as_fmpq(other)
456
- if other is not NotImplemented :
457
- other = fmpq_mpoly(other, self .ctx)
458
- res = create_fmpq_mpoly(self .ctx)
459
- res2 = create_fmpq_mpoly(self .ctx)
460
- fmpq_mpoly_divrem(res.val, res2.val, (< fmpq_mpoly> other).val, (< fmpq_mpoly> self ).val, res.ctx.val)
461
- return (res, res2)
462
- return NotImplemented
463
-
464
- def __floordiv__ (self , other ):
368
+ def _sub_scalar_ (self , other: fmpq ):
465
369
cdef fmpq_mpoly res
466
- if typecheck(other, fmpq_mpoly):
467
- if not other:
468
- raise ZeroDivisionError (" fmpq_mpoly division by zero" )
469
- elif (< fmpq_mpoly> self ).ctx is not (< fmpq_mpoly> other).ctx:
470
- raise IncompatibleContextError(f" {(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}" )
471
- res = create_fmpq_mpoly(self .ctx)
472
- fmpq_mpoly_div(res.val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, res.ctx.val)
473
- return res
474
- else :
475
- other = any_as_fmpq(other)
476
- if other is not NotImplemented :
477
- if not other:
478
- raise ZeroDivisionError (" fmpq_mpoly division by zero" )
479
- other = fmpq_mpoly(other, self .ctx)
480
- res = create_fmpq_mpoly(self .ctx)
481
- fmpq_mpoly_div(res.val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, res.ctx.val)
482
- return res
483
- return NotImplemented
484
-
485
- def __rfloordiv__ (self , other ):
486
- cdef fmpq_mpoly res
487
- if not self :
488
- raise ZeroDivisionError (" fmpq_mpoly division by zero" )
489
- other = any_as_fmpq(other)
490
- if other is not NotImplemented :
491
- other = fmpq_mpoly(other, self .ctx)
492
- res = create_fmpq_mpoly(self .ctx)
493
- fmpq_mpoly_div(res.val, (< fmpq_mpoly> other).val, self .val, res.ctx.val)
494
- return res
495
- return NotImplemented
370
+ res = create_fmpq_mpoly(self .ctx)
371
+ fmpq_mpoly_sub_fmpq(res.val, self .val, other.val, self .ctx.val)
372
+ return res
496
373
497
- def __truediv__ (self , other ):
498
- cdef:
499
- fmpq_mpoly res
374
+ def _sub_mpoly_ (self , other: fmpq_mpoly ):
375
+ cdef fmpq_mpoly res
376
+ res = create_fmpq_mpoly(self .ctx)
377
+ fmpq_mpoly_sub(res.val, self .val, other.val, res.ctx.val)
378
+ return res
500
379
501
- if typecheck(other, fmpq_mpoly ):
502
- if not other:
503
- raise ZeroDivisionError ( " fmpq_mpoly division by zero " )
504
- elif self .ctx is not ( < fmpq_mpoly > other). ctx:
505
- raise IncompatibleContextError(f " {self.ctx} is not {(<fmpq_mpoly>other).ctx} " )
380
+ def _mul_scalar_ ( self , other: fmpq ):
381
+ cdef fmpq_mpoly res
382
+ res = create_fmpq_mpoly( self .ctx )
383
+ fmpq_mpoly_scalar_mul_fmpq(res.val, self .val, other.val, self . ctx.val)
384
+ return res
506
385
507
- res = create_fmpq_mpoly(self .ctx)
508
- if fmpq_mpoly_divides(res.val, self .val, (< fmpq_mpoly> other).val, self .ctx.val):
509
- return res
510
- else :
511
- raise DomainError(" fmpq_mpoly division is not exact" )
512
- else :
513
- o = any_as_fmpq(other)
514
- if o is NotImplemented :
515
- return NotImplemented
516
- elif not o:
517
- raise ZeroDivisionError (" fmpq_mpoly division by zero" )
518
- res = create_fmpq_mpoly(self .ctx)
519
- fmpq_mpoly_scalar_div_fmpq(res.val, self .val, (< fmpq> o).val, self .ctx.val)
520
- return res
386
+ def _mul_mpoly_ (self , other: fmpq_mpoly ):
387
+ cdef fmpq_mpoly res
388
+ res = create_fmpq_mpoly(self .ctx)
389
+ fmpq_mpoly_mul(res.val, self .val, other.val, res.ctx.val)
390
+ return res
521
391
522
- def __rtruediv__ (self , other ):
392
+ def _pow_ (self , other: fmpz ):
523
393
cdef fmpq_mpoly res
524
- if not self :
525
- raise ZeroDivisionError (" fmpq_mpoly division by zero" )
526
- o = any_as_fmpq(other)
527
- if o is NotImplemented :
528
- return NotImplemented
529
394
res = create_fmpq_mpoly(self .ctx)
530
- fmpq_mpoly_set_fmpq(res.val, (< fmpq> o).val, self .ctx.val)
531
- return res / self
395
+ if fmpq_mpoly_pow_fmpz(res.val, self .val, other.val, res.ctx.val) == 0 :
396
+ raise ValueError (" unreasonably large polynomial" ) # pragma: no cover
397
+ return res
532
398
533
- def __mod__ (self , other ):
534
- return divmod (self , other)[1 ]
399
+ def _divmod_mpoly_ (self , other: fmpq_mpoly ):
400
+ cdef fmpq_mpoly quotient, remainder
401
+ quotient = create_fmpq_mpoly(self .ctx)
402
+ remainder = create_fmpq_mpoly(self .ctx)
403
+ fmpq_mpoly_divrem(quotient.val, remainder.val, self .val, other.val, self .ctx.val)
404
+ return (quotient, remainder)
405
+
406
+ def _floordiv_mpoly_ (self , other: fmpq_mpoly ):
407
+ cdef fmpq_mpoly quotient
408
+ quotient = create_fmpq_mpoly(self .ctx)
409
+ fmpq_mpoly_div(quotient.val, self .val, other.val, self .ctx.val)
410
+ return quotient
411
+
412
+ def _truediv_mpoly_ (self , other: fmpq_mpoly ):
413
+ cdef fmpq_mpoly quotient
414
+ quotient = create_fmpq_mpoly(self .ctx)
415
+ if fmpq_mpoly_divides(quotient.val, self .val, other.val, self .ctx.val):
416
+ return quotient
417
+ else :
418
+ raise DomainError(" fmpq_mpoly division is not exact" )
535
419
536
- def __rmod__ (self , other ):
537
- return divmod (other, self )[1 ]
420
+ def _mod_mpoly_ (self , other: fmpq_mpoly ):
421
+ cdef fmpq_mpoly quotient, remainder
422
+ quotient = create_fmpq_mpoly(self .ctx)
423
+ remainder = create_fmpq_mpoly(self .ctx)
424
+ fmpq_mpoly_divrem(quotient.val, remainder.val, self .val, other.val, self .ctx.val)
425
+ return remainder
538
426
539
427
def __call__ (self , *args ) -> fmpq:
540
428
cdef:
@@ -551,83 +439,23 @@ cdef class fmpq_mpoly(flint_mpoly):
551
439
raise ValueError("unreasonably large polynomial") # pragma: no cover
552
440
return vres
553
441
554
- def iadd(self , other ):
555
- """
556
- In-place addition, mutates self.
442
+ def _iadd_scalar_(self , other: fmpq ):
443
+ fmpq_mpoly_add_fmpq(self .val, self .val, other.val, self .ctx.val)
557
444
558
- >>> from flint import Ordering
559
- >>> ctx = fmpq_mpoly_ctx.get_context(2, Ordering.lex, 'x')
560
- >>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
561
- >>> f
562
- 4*x0*x1 + 2*x0 + 3*x1
563
- >>> f.iadd(5)
564
- >>> f
565
- 4*x0*x1 + 2*x0 + 3*x1 + 5
445
+ def _iadd_mpoly_ (self , other: fmpq_mpoly ):
446
+ fmpq_mpoly_add(self .val, self .val, other.val, self .ctx.val)
566
447
567
- """
568
- if typecheck(other, fmpq_mpoly):
569
- if (< fmpq_mpoly> self ).ctx is not (< fmpq_mpoly> other).ctx:
570
- raise IncompatibleContextError(f" {(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}" )
571
- fmpq_mpoly_add((< fmpq_mpoly> self ).val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, self .ctx.val)
572
- return
573
- else :
574
- other = any_as_fmpq(other)
575
- if other is not NotImplemented :
576
- fmpq_mpoly_add_fmpq((< fmpq_mpoly> self ).val, (< fmpq_mpoly> self ).val, (< fmpq> other).val, self .ctx.val)
577
- return
578
- raise NotImplementedError (f" in-place addition not implemented between {type(self)} and {type(other)}" )
579
-
580
- def isub (self , other ):
581
- """
582
- In-place subtraction, mutates self.
583
-
584
- >>> from flint import Ordering
585
- >>> ctx = fmpq_mpoly_ctx.get_context(2, Ordering.lex, 'x')
586
- >>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
587
- >>> f
588
- 4*x0*x1 + 2*x0 + 3*x1
589
- >>> f.isub(5)
590
- >>> f
591
- 4*x0*x1 + 2*x0 + 3*x1 - 5
592
-
593
- """
594
- if typecheck(other, fmpq_mpoly):
595
- if (< fmpq_mpoly> self ).ctx is not (< fmpq_mpoly> other).ctx:
596
- raise IncompatibleContextError(f" {(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}" )
597
- fmpq_mpoly_sub((< fmpq_mpoly> self ).val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, self .ctx.val)
598
- return
599
- else :
600
- other = any_as_fmpq(other)
601
- if other is not NotImplemented :
602
- fmpq_mpoly_sub_fmpq((< fmpq_mpoly> self ).val, (< fmpq_mpoly> self ).val, (< fmpq> other).val, self .ctx.val)
603
- return
604
- raise NotImplementedError (f" in-place subtraction not implemented between {type(self)} and {type(other)}" )
448
+ def _isub_scalar_ (self , other: fmpq ):
449
+ fmpq_mpoly_sub_fmpq(self .val, self .val, other.val, self .ctx.val)
605
450
606
- def imul (self , other ):
607
- """
608
- In-place multiplication, mutates self.
451
+ def _isub_mpoly_ (self , other: fmpq_mpoly ):
452
+ fmpq_mpoly_sub(self .val, self .val, other.val, self .ctx.val)
609
453
610
- >>> from flint import Ordering
611
- >>> ctx = fmpq_mpoly_ctx.get_context(2, Ordering.lex, 'x')
612
- >>> f = ctx.from_dict({(1, 0): 2, (0, 1): 3, (1, 1): 4})
613
- >>> f
614
- 4*x0*x1 + 2*x0 + 3*x1
615
- >>> f.imul(2)
616
- >>> f
617
- 8*x0*x1 + 4*x0 + 6*x1
454
+ def _imul_scalar_ (self , other: fmpq ):
455
+ fmpq_mpoly_scalar_mul_fmpq(self .val, self .val, other.val, self .ctx.val)
618
456
619
- """
620
- if typecheck(other, fmpq_mpoly):
621
- if (< fmpq_mpoly> self ).ctx is not (< fmpq_mpoly> other).ctx:
622
- raise IncompatibleContextError(f" {(<fmpq_mpoly>self).ctx} is not {(<fmpq_mpoly>other).ctx}" )
623
- fmpq_mpoly_mul((< fmpq_mpoly> self ).val, (< fmpq_mpoly> self ).val, (< fmpq_mpoly> other).val, self .ctx.val)
624
- return
625
- else :
626
- other = any_as_fmpq(other)
627
- if other is not NotImplemented :
628
- fmpq_mpoly_scalar_mul_fmpq(self .val, (< fmpq_mpoly> self ).val, (< fmpq> other).val, self .ctx.val)
629
- return
630
- raise NotImplementedError (f" in-place multiplication not implemented between {type(self)} and {type(other)}" )
457
+ def _imul_mpoly_ (self , other: fmpq_mpoly ):
458
+ fmpq_mpoly_mul(self .val, self .val, other.val, self .ctx.val)
631
459
632
460
def monoms (self ):
633
461
"""
0 commit comments