@@ -615,39 +615,59 @@ cdef class fmpq_mpoly(flint_mpoly):
615615
616616 def subs (self , dict_args ) -> fmpq_mpoly:
617617 """
618- Partial evaluate this polynomial.
618+ Partial evaluate this polynomial with select constants. Keys must be generator names ,
619+ all values must be fmpq.
620+
621+ >>> from flint import Ordering
622+ >>> ctx = fmpq_mpoly_ctx.get_context(2 , Ordering.lex, ' x' )
623+ >>> f = ctx.from_dict({(0 , 0 ): 1 , (1 , 0 ): 2 , (0 , 1 ): 3 , (1 , 1 ): 4 })
624+ >>> f.subs({"x1": 0})
625+ 2*x0 + 1
626+
619627 """
620628 cdef:
621629 fmpq_mpoly res
622630 slong i , nargs
623631
624- partial_args = tuple ((i, dict_args[x]) for i, x in enumerate (self .ctx.names()) if x in dict_args)
625- nargs = len (partial_args )
632+ args = tuple ((i, dict_args[x]) for i, x in enumerate (self .ctx.names()) if x in dict_args)
633+ nargs = len (args )
626634
627- # If we've been provided with an invalid keyword arg then the length of our filter
635+ # If we've been provided with an invalid generator name then the length of our filter
628636 # args will be less than what we've been provided with.
629- # If the length is equal to the number of variables then all arguments have been provided
630- # otherwise we need to do partial application
631637 if nargs < len(dict_args ):
632- raise ValueError (" Unknown keyword argument provided" )
638+ raise ValueError (" unknown generator name provided" )
633639
634- args_fmpq = tuple (any_as_fmpq(v) for _, v in partial_args )
640+ args_fmpq = tuple (any_as_fmpq(v) for _, v in args )
635641 for arg in args_fmpq:
636642 if arg is NotImplemented :
637- raise TypeError (f" Cannot coerce argument ('{arg}') to fmpq" )
643+ raise TypeError (f" cannot coerce argument ('{arg}') to fmpq" )
638644
639- # Partial application with args in Z . We evaluate the polynomial one variable at a time
645+ # Partial application with args in Q . We evaluate the polynomial one variable at a time
640646 res = create_fmpq_mpoly(self .ctx)
641647
642648 fmpq_mpoly_set(res.val, self .val, self .ctx.val)
643- for (i, _), arg in zip (partial_args , args_fmpq):
649+ for (i, _), arg in zip (args , args_fmpq):
644650 if fmpq_mpoly_evaluate_one_fmpq(res.val, res.val, i, (< fmpq> arg).val, self .ctx.val) == 0 :
645- raise ValueError (" Unreasonably large polynomial" ) # pragma: no cover
651+ raise ValueError (" unreasonably large polynomial" ) # pragma: no cover
646652 return res
647653
648654 def compose (self , *args ) -> fmpq_mpoly:
649655 """
650- Compose this polynomial with other fmpq_mpolys. Takes positional arguments.
656+ Compose this polynomial with other fmpq_mpolys. All arguments must share the same context , it may different
657+ from this polynomials context.
658+
659+ >>> from flint import Ordering
660+ >>> ctx = fmpq_mpoly_ctx.get_context(1 , Ordering.lex, ' x' )
661+ >>> ctx1 = fmpq_mpoly_ctx.get_context(2 , Ordering.lex, ' y' )
662+ >>> f = ctx.from_dict({(2 ,): 1 })
663+ >>> g = ctx1.from_dict({(1 , 0 ): 1 , (0 , 1 ): 1 })
664+ >>> f
665+ x^2
666+ >>> g
667+ y0 + y1
668+ >>> f.compose(g )
669+ y0^2 + 2*y0*y1 + y1^2
670+
651671 """
652672 cdef:
653673 fmpq_mpoly res
@@ -666,8 +686,8 @@ cdef class fmpq_mpoly(flint_mpoly):
666686 if not all ((< fmpq_mpoly> args[i]).ctx is res_ctx for i in range (1 , len (args))):
667687 raise IncompatibleContextError(" All arguments must share the same context" )
668688
669- C = fmpq_mpoly_vec(args, self .ctx , double_indirect = True )
670- res = create_fmpq_mpoly(self .ctx )
689+ C = fmpq_mpoly_vec(args, res_ctx , double_indirect = True )
690+ res = create_fmpq_mpoly(res_ctx )
671691 if fmpq_mpoly_compose_fmpq_mpoly(res.val, self .val, C.double_indirect, self .ctx.val, res_ctx.val) == 0 :
672692 raise ValueError (" Unreasonably large polynomial" ) # pragma: no cover
673693 return res
0 commit comments