# $Source: /u/maple/research/lib/DEtools/diffop/src/RCS/g_ext,v $ # $Notify: mvanhoei@daisy.uwaterloo.ca $ # Procedures for users # none # Procedures for use only in the rest of the diffop package: # g_ext, g_normal, g_factors, modm, g_solve, g_quotient, g_rem, # g_quo, g_expand, normal_coeffs, truncate_x # differentiate # Procedures for use only in this file: # none macro( solve=`solve/linear` ): # Purpose of this file: same as `algcurves/g_expand`, namely # procedures to allow code that works over different kinds of ground # fields. So for example g_expand looks what kind of expression is given, # and then decides what to do, expand, or evala(Expand()), or expanding # with normalization of the lowest coefficient etcetera. # Variables: # g_conversion1: subs(g_conversion1,A) converts A to the internal syntax for # algebraic numbers. # g_conversion2: subs(g_conversion2,A) converts A to the RootOf syntax for # algebraic numbers. # modulus: if this variable <> 0 then some procedures (the ones needed # for lifting a factorization, not the ones for producing a # factorization) will work modulo this modulus. # rootof.i: Stands for an algebraic number, can be converted to RootOf(..) # by g_conversion2 # Typical variable names in procedures: # ext: This variable describes the algebraic extension over the # field Q. The RootOfs have been replaced by variables # `algcurves/rootof`.i (i integer) and evala(Expand( )) is replaced # by g_expand(expression,ext). # ram: This variable gives the ramification. The Laurent series # procedures can not handle things like x^(1/2). If a # ramification of an expression A is needed it will sometimes # be denoted as: [A,ext,ram,`alg over k((x))`]. This means that # x in A does not stand for x but ram (which is equal to a # constant times x^n) stands for x. So if ram=3*x^5 then x in A # stands for RootOf(3*y^5-x,y). # Tools: # modm : reduce mod modulus if modulus <> 0. # g_solve : solve linear equations, also modular # g_quotient : compute a/b mod x^n, also modular # g_rem : remainder, only char 0 # g_quo : quotient # g_expand : expand, not modular. # uses g_evala and g_evala_rem # g_normal : normal, not modular # truncate_x : mod x^n, without expand or modm # g_ext : This procedure gives a list describing the algebraic # extensions over Q of a given expression. # macro's for g_ext: macro( modulus=`DEtools/diffop/modulus`, x=`DEtools/diffop/x`, DF=`DEtools/diffop/DF`, xDF=`DEtools/diffop/xDF` ): macro( g_conversion1=`algcurves/g_conversion1`, g_conversion2=`algcurves/g_conversion2`, g_evala=`algcurves/g_evala` ); macro( normal_coeffs=`DEtools/diffop/normal_coeffs`, new_laurent2=`DEtools/diffop/new_laurent2`, differentiate=`DEtools/diffop/differentiate`, g_ext=`DEtools/diffop/g_ext`, g_factors=`DEtools/diffop/g_factors`, g_normal=`DEtools/diffop/g_normal`, set_laurents=`DEtools/diffop/set_laurents`, description_laurent=`DEtools/diffop/description_laurent`, modm=`DEtools/diffop/modm`, g_solve=`DEtools/diffop/g_solve`, g_quotient=`DEtools/diffop/g_quotient`, g_rem=`DEtools/diffop/g_rem`, g_quo=`DEtools/diffop/g_quo`, truncate_x=`DEtools/diffop/truncate_x`, g_expand=`DEtools/diffop/g_expand` ): modulus:=0: # For modular computation # Gives the algebraic extensions appearing in aa. # For laurent series, the groundfield must be given in their descriptions. g_ext:=proc(aa) local v,i; options remember, `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; v:=aa; if indets(aa) intersect set_laurents<>{} then for i in indets(aa) intersect set_laurents do v:=subs(i=description_laurent[i],v) od; fi; `algcurves/g_ext`(v) end: g_normal:=proc(aa) local a; option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; if has(aa,RootOf) then return evala(Normal(aa),'independent') fi; if modulus<>0 then a:=subs(g_conversion2,Normal(aa) mod modulus); if has(a,RootOf) then subs(g_conversion1,evala(Normal(a),'independent')) else a fi else a:=subs(g_conversion2,aa); if has(a,RootOf) then subs(g_conversion1,evala(Normal(a),'independent')) else normal(a) fi fi end: # Factorization over the groundfield # Both RootOf and rootof syntax # ext: describes the groundfield # Make the factors monic. g_factors:=proc(f,x,ext) local i; option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; [seq([collect(i[1]/lcoeff(i[1],x),x,g_normal),i[2]] ,i=`algcurves/g_factors`(args))] end: #---------------------------------------------------------------------- modm:=proc() option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; if modulus=0 then args else args mod modulus fi end: g_solve:=proc() local v,w,res,i,a,ext; option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; if nargs<3 then # The "if" is to avoid that this message gets repeated in the recursion userinfo(10,'diffop',`solving linear equations`) fi; if modulus=0 then subs(g_conversion1,evala(solve(op(subs(g_conversion2,[args[1 ..min(2,nargs)]]))))) else # Solving linear equations modulo a number, not very efficiently written. v:=args[1]; if nargs=3 then ext:=args[3] else ext:=g_ext(v) fi; if nargs>=2 then w:=args[2] else w:=indets(v,'name') minus {op(ext)} fi; v:=modm(map(g_expand,v,ext)) minus {0}; if v={} then return v fi; a:=v[1]; i:=indets(a,'name') intersect w; if i=[] then return NULL fi; i:=i[1]; res:=g_normal(-coeff(a,i,0)/coeff(a,i,1)); a:=g_solve(subs(i=res,v minus {a}),w minus {i},ext); if a=NULL then a else a union {i=modm(g_expand(subs(a,res),ext))} fi fi end: # Compute the quotient of two truncated power series. g_quotient:=proc(aa,bb,n,ext) global x; local a,b,res,i,g,la,lb; option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; a:=modm(g_expand(aa,ext,x)); b:=modm(g_expand(bb,ext,x)); if a=0 or b=0 then return 0 fi; g:=g_normal(1/tcoeff(b,x)); res:=0; la:=ldegree(a,x); lb:=ldegree(b,x); for i from la-lb to n-1 do res:=res+g*x^i*coeff(a,x,i+lb); a:=a-g_expand(b*g*x^i*coeff(a,x,i+lb),ext) od; modm(g_expand(res,ext,x)) end: g_rem:=proc(a,b,y,ext) option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; g_expand(rem(g_expand(a,ext),b,y),ext,y) end: g_quo:=proc(a,b,y,ext) option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; modm(g_expand(quo(g_expand(a,ext),modm(g_expand(b,ext)),y),ext,y)) end: # Same as in the algcurves package, with normal_tcoeff replaced by normal_coeffs # evala(Expand( )) # Give 3'rd argument x for normalizing the coefficients in x # So then ldegree(result,x) gives the right answer g_expand:=proc(a,ext) option `Copyright (c) 1996 Waterloo Maple Inc. All rights reserved.`; if type(a,polynom) then g_evala(expand(a),ext) elif nargs=3 and type(a,polynom(anything,ext)) then normal_coeffs(g_evala(expand(a),ext),args[3]) elif nargs=3 then normal_coeffs(procname(a,ext),args[3]) else subs(g_conversion1,evala(Expand(subs(g_conversion2,a)) ,'independent')) fi end: # Normalize all coefficients normal_coeffs:=proc(a,x) option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; if type(a,polynom) then a else collect(a,x,g_normal) fi end: # Input should already be collected w.r.t. x. # Output: f mod x^n truncate_x:=proc(a,f,n) global x; local dummy; option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; convert([seq(x^dummy*coeff(f,x,dummy),dummy=ldegree(f,x)..n-1)],`+`) end: # Gives the derivative of an expression differentiate:=proc(ff) global x; local f,dummy,v; option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; v:=indets(ff) intersect set_laurents; if v={} then if has(subs(g_conversion2,subs(x=dummy,ff)),x) then # algebraic functions in the input: return subs(g_conversion1,diff(subs(g_conversion2,ff),x)) else return diff(ff,x) fi fi; v:=[op(v)]; v:=v[1]; f:=collect(ff,v); if type(f,polynom(anything,v)) then expand(convert([seq(procname(coeff(f,v,dummy))*v^dummy +dummy*v^(dummy-1)*coeff(f,v,dummy)*new_laurent2(v ,differentiate,g_ext(v)),dummy=0..degree(f,v))],`+`)) else f:=g_normal(f); g_normal((denom(f)*procname(numer(f))-numer(f) *procname(denom(f)))/denom(f)^2) fi end: set_laurents:={}: # Purpose: make the userinfo output more readable by replacing the # long names `DEtools/diffop/x` by short names: `DEtools/diffop/infosubs`:=proc() global xDF,DF,x,g_conversion2; local a; option `Copyright (c) 1997 Waterloo Maple Inc. All rights reserved.`; a:=_Envdiffopdomain; if type(a,list) then op(subs(DF=a[1],x=a[2],xDF=cat(a[2],a[1]) ,g_conversion2,[args])) else args fi end: #savelib('modulus','g_ext','g_normal','g_factors','modm','g_solve', \ 'g_quotient','g_rem','g_quo','g_expand','normal_coeffs','truncate_x', \ '`DEtools/diffop/infosubs`', \ 'differentiate','set_laurents'):