diff options
Diffstat (limited to 'src/interp/i-coerfn.boot.pamphlet')
-rw-r--r-- | src/interp/i-coerfn.boot.pamphlet | 2309 |
1 files changed, 2309 insertions, 0 deletions
diff --git a/src/interp/i-coerfn.boot.pamphlet b/src/interp/i-coerfn.boot.pamphlet new file mode 100644 index 00000000..034067d3 --- /dev/null +++ b/src/interp/i-coerfn.boot.pamphlet @@ -0,0 +1,2309 @@ +\documentclass{article} +\usepackage{axiom} + +\title{\File{src/interp/i-coerfn.boot} Pamphlet} +\author{The Axiom Team} + +\begin{document} +\maketitle +\begin{abstract} +\end{abstract} +\eject +\tableofcontents +\eject + +\begin{verbatim} +Special coercion routines + +This is the newly revised set of coercion functions to work with +the new library and the new runtime system. + +coerceByTable is driven off $CoerceTable which is used to match +the top-level constructors of the source and object types. The +form of $CoerceTable is an alist where the "properties" are the +source top-level constructors and the values are triples + target-domain coercion-type function +where target-domain is the top-level constructor of the target, +coercion-type is one of 'total, 'partial or 'indeterm, and +function is the name of the function to call to handle the +coercion. coercion-type is used by canCoerce and friends: 'total +means that a coercion can definitely be performed, 'partial means +that one cannot tell whether a coercion can be performed unless +you have the actual data (like telling whether a Polynomial Integer +can be coerced to an Integer: you have to know whether it is a +constant polynomial), and 'indeterm means that you might be able +to tell without data, but you need to call the function with the +argument "$fromCoerceable$" for a response of true or false. As an +example of this last kind, you may be able to coerce a list to a +vector but you have to know what the underlying types are. So +List Integer is coerceable to Vector Integer but List Float is +not necessarily coerceable to Vector Integer. + +The functions always take three arguments: + value this is the unwrapped source object + source-type this is the type of the source + target-type this is the requested type of the target +For ethical reasons and to avoid eternal damnation, we try to use +library functions to perform a lot of the structure manipulations. +However, we sometimes cheat for efficiency reasons, particularly to +avoid intermediate instantiations. + +the following are older comments: + +This file contains the special coercion routines that convert from +one datatype to another in the interpreter. The choice of the +primary special routine is made by the function coerceByTable. Note +that not all coercions use these functions, as some are done via SPAD +algebra code and controlled by the function coerceByFunction. See +the file COERCE BOOT for more information. + +some assumption about the call of commute and embed functions: +embed functions are called for one level embedding only, + e.g. I to P I, but not I to P G I +commute functions are called for two types which differ only in the + permutation of the two top type constructors + e.g. G P RN to P G RN, but not G P I to P G RN or + P[x] G RN to G P RN + +all functions in this file should call canCoerce and coerceInt, as + opposed to canCoerceFrom and coerceInteractive + +all these coercion functions have the following result: +1. if u=$fromCoerceable$, then TRUE or NIL +2. if the coercion succeeds, the coerced value (this may be NIL) +3. if the coercion fails, they throw to a catch point in + coerceByTable + +\end{verbatim} +\section{License} +<<license>>= +-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd. +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are +-- met: +-- +-- - Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- +-- - Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in +-- the documentation and/or other materials provided with the +-- distribution. +-- +-- - Neither the name of The Numerical ALgorithms Group Ltd. nor the +-- names of its contributors may be used to endorse or promote products +-- derived from this software without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +@ +<<*>>= +<<license>> + +SETANDFILEQ($coerceFailure,GENSYM()) + +position1(x,y) == + -- this is used where we want to assume a 1-based index + 1 + position(x,y) + +--% Direct Product, New and Old + +DP2DP(u,source is [.,n,S],target is [.,m,T]) == + n ^= m => nil + u = '_$fromCoerceable_$ => canCoerce(S,T) + null (u' := coerceInt(objNewWrap(u,['Vector,S]),['Vector,T])) => + coercionFailure() + objValUnwrap u' + +--% Distributed Multivariate Polynomials, New and Old + +Dmp2Dmp(u,source is [dmp,v1,S], target is [.,v2,T]) == + -- the variable lists must share some variables, or u is a constant + u = '_$fromCoerceable_$ => + v:= intersection(v1,v2) + v and + w2:= SETDIFFERENCE(v2,v) + t1:= if w1 then [dmp,w1,S] else S + t2:= if w2 then [dmp,w2,T] else T + canCoerce(t1,t2) + null u => domainZero(target) + u is [[e,:c]] and e=LIST2VEC [0 for v in v1] => + z:= coerceInt(objNewWrap(c,S),target) => objValUnwrap(z) + coercionFailure() + v:= intersection(v1,v2) => + w1:= SETDIFFERENCE(v1,v) => + coerceDmp1(u,source,target,v,w1) + coerceDmp2(u,source,target) + coercionFailure() + +coerceDmp1(u,source is [.,v1,S],target is [.,v2,T],v,w) == + -- coerces one Dmp to another, where v1 is not a subset of v2 + -- v is the intersection, w the complement of v1 and v2 + t:= ['DistributedMultivariatePolynomial,w,S] + x:= domainZero(target) + one:= domainOne(T) + plusfunc:= getFunctionFromDomain('_+,target,[target,target]) + multfunc:= getFunctionFromDomain('_*,target,[target,target]) + pat1:= [member(x,v) for x in v1] + pat2:= [member(x,w) for x in v1] + pat3:= [member(x,v) and POSN1(x,v) for x in v2] + for [e,:c] in u until not z repeat + exp:= LIST2VEC [y for x in pat2 for y in VEC2LIST e | x] + z:= coerceInt(objNewWrap([CONS(exp,c)],t),target) => + li:= [y for x in pat1 for y in VEC2LIST e | x] + a:= [CONS(LIST2VEC [if x then li.x else 0 for x in pat3],one)] + x:= SPADCALL(x,SPADCALL(objValUnwrap(z),a,multfunc),plusfunc) + z => x + coercionFailure() + +coerceDmp2(u,source is [.,v1,S],target is [.,v2,T]) == + -- coerces one Dmp to another, where v1 is included in v2 + x:= domainZero(target) + one:= domainOne(T) + plusfunc:= getFunctionFromDomain('_+,target,[target,target]) + multfunc:= getFunctionFromDomain('_*,target,[target,target]) + pat:= [member(x,v1) and POSN1(x,v1) for x in v2] + for [e,:c] in u until not z repeat + z:= coerceInt(objNewWrap(c,S),target) => + li:= VEC2LIST e + a:= [CONS(LIST2VEC [if x then li.x else 0 for x in pat],one)] + x:= SPADCALL(x,SPADCALL(objValUnwrap(z),a,multfunc),plusfunc) + NIL + z => x + coercionFailure() + +Dmp2Expr(u,source is [dmp,vars,S], target is [Expr,T]) == + u = '_$fromCoerceable_$ => canCoerce(S, target) + + null vars => + [[., :c]] := u + not (c := coerceInt(objNewWrap(c, S), target)) => coercionFailure() + objValUnwrap(c) + + syms := [objValUnwrap coerceInt(objNewWrap(var, $Symbol), target) for + var in vars] + sum := domainZero(target) + + plus := getFunctionFromDomain("+", target, [target, target]) + mult := getFunctionFromDomain("*", target, [target, target]) + expn := getFunctionFromDomain("**", target, [target, $Integer]) + + for [e, :c] in u repeat + not (c := coerceInt(objNewWrap(c, S), target)) => coercionFailure() + c := objValUnwrap(c) + term := domainOne(target) + for i in 0.. for sym in syms repeat + exp := e.i + e.i > 0 => term := SPADCALL(term, SPADCALL(sym, e.i, expn), mult) + sum := SPADCALL(sum, SPADCALL(c, term, mult), plus) + + sum + +Dmp2Mp(u, source is [dmp, x, S], target is [mp, y, T]) == + source' := [dmp,y,T] + u = '_$fromCoerceable_$ => + x = y => canCoerce(S,T) + canCoerce(source',target) + null u => domainZero(target) -- 0 dmp is = nil + x ^= y => + (u' := coerceInt(objNewWrap(u,source),source')) or coercionFailure() + (u' := coerceInt(u',target)) or coercionFailure() + objValUnwrap(u') + + -- slight optimization for case #u = 1, x=y , #x =1 and S=T + -- I know it's pathological, but it may avoid an instantiation + (x=y) and (1 = #u) and (1 = #x) and (S = T) => + [1,1,[(CAAR u).0,0,:CDAR u]] + + (u' := coerceDmpCoeffs(u,S,T)) = 'failed => + coercionFailure() + plusfunc := getFunctionFromDomain("+",target,[target,target]) + u'' := genMpFromDmpTerm(u'.0, 0) + for i in 1..(#u' - 1) repeat + u'' := SPADCALL(u'',genMpFromDmpTerm(u'.i, 0),plusfunc) + u'' + +coerceDmpCoeffs(u,S,T) == + -- u is a dmp, S is domain of coeffs, T is domain to coerce coeffs to + S = T => u + u' := nil + bad := nil + for [e,:c] in u repeat + bad => nil + null (c' := coerceInt(objNewWrap(c,S),T)) => return (bad := true) + u' := [[e,:objValUnwrap(c')],:u'] + bad => 'failed + nreverse u' + +sortAndReorderDmpExponents(u,vl) == + vl' := reverse MSORT vl + n := (-1) + #vl + pos := LIST2VEC LZeros (n+1) + for i in 0..n repeat pos.i := position(vl.i,vl') + u' := nil + for [e,:c] in u repeat + e' := LIST2VEC LZeros (n+1) + for i in 0..n repeat e'.(pos.i) := e.i + u' := [[e',:c],:u'] + reverse u' + +domain2NDmp(u, source, target is [., y, T]) == + target' := ['DistributedMultivariatePolynomial,y,T] + u = '_$fromCoerceable_$ => canCoerce(source,target') + (u' := coerceInt(objNewWrap(u,source),target')) => + (u'' := coerceInt(u',target)) => + objValUnwrap(u'') + coercionFailure() + coercionFailure() + +Dmp2NDmp(u,source is [dmp,x,S],target is [ndmp,y,T]) == + -- a null DMP = 0 + null u => domainZero(target) + target' := [dmp,y,T] + u = '_$fromCoerceable_$ => Dmp2Dmp(u,source,target') + (u' := Dmp2Dmp(u,source,target')) => addDmpLikeTermsAsTarget(u',target) + coercionFailure() + +addDmpLikeTermsAsTarget(u,target) == + u' := domainZero(target) + func := getFunctionFromDomain("+",target,[target,target]) + for t in u repeat u' := SPADCALL(u',[t],func) + u' + +-- rewrite ? +Dmp2P(u, source is [dmp,vl, S], target is [.,T]) == + -- a null DMP = 0 + null u => domainZero(target) + u = '_$fromCoerceable_$ => + t := canCoerce(S,T) + null t => canCoerce(S,target) + t + + S is ['Polynomial,.] => + mp := coerceInt(objNewWrap(u,source),['MultivariatePolynomial,vl,S]) + or coercionFailure() + p := coerceInt(mp,target) or coercionFailure() + objValUnwrap p + + -- slight optimization for case #u = 1, #vl =1 and S=T + -- I know it's pathological, but it may avoid an instantiation + (1 = #u) and (1 = #vl) and (S = T) => + (lexp:= (CAAR u).0) = 0 => [1,:CDAR u] + [1,vl.0,[lexp,0,:CDAR u]] + + vl' := reverse MSORT vl + source' := [dmp,vl',S] + target' := ['MultivariatePolynomial,vl',S] + u' := sortAndReorderDmpExponents(u,vl) + u' := coerceInt(objNewWrap(u',source'),target') + if u' then + u' := translateMpVars2PVars (objValUnwrap(u'),vl') + u' := coerceInt(objNewWrap(u',['Polynomial,S]),target) + u' => objValUnwrap(u') + -- get drastic. create monomials + source' := [dmp,vl,T] + u' := domainZero(target) + oneT := domainOne(T) + plusfunc := getFunctionFromDomain("+",target,[target,target]) + multfunc := getFunctionFromDomain("*",target,[target,target]) + for [e,:c] in u repeat + (c' := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + (e' := coerceInt(objNewWrap([[e,:oneT]],source'),target)) or + coercionFailure() + t := SPADCALL(objValUnwrap(e'),objValUnwrap(c'),multfunc) + u' := SPADCALL(u',t,plusfunc) + coercionFailure() + +translateMpVars2PVars (u, vl) == + u is [ =1, v, :termlist] => + [ 1, vl.(v-1), + :[[e,:translateMpVars2PVars(c,vl)] for [e,:c] in termlist]] + u + +Dmp2Up(u, source is [dmp,vl,S],target is [up,var,T]) == + null u => -- this is true if u = 0 + domainZero(target) + + u = '_$fromCoerceable_$ => + member(var,vl) => + vl' := remove(vl,var) + null vl' => -- no remaining variables + canCoerce(S,T) + null rest vl' => -- one remaining variable + canCoerce([up,first vl',S],T) + canCoerce([dmp,vl',S], T) + canCoerce(source,T) + + -- check constant case + (null rest u) and (first(u) is [e,:c]) and + ( and/[(0 = e.i) for i in 0..(-1 + #vl)] ) => + (x := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + objValUnwrap(x) + + -- check non-member case + null member(var,vl) => + (u' := coerceInt(objNewWrap(u,source),T)) or coercionFailure() + [[0,:objValUnwrap u']] + + vl' := remove(vl,var) + + -- only one variable in DMP case + null vl' => + u' := nreverse SORTBY('CAR,[[e.0,:c] for [e,:c] in u]) + (u' := coerceInt(objNewWrap(u',[up,var,S]),target)) or + coercionFailure() + objValUnwrap u' + + S1 := [dmp,vl',S] + plusfunc:= getFunctionFromDomain('_+,T,[T,T]) + zero := getConstantFromDomain('(Zero),T) + x := NIL + pos:= POSN1(var,vl) + for [e,:c] in u until not y repeat + exp:= e.pos + e1:= removeVectorElt(e,pos) + y:= coerceInt(objNewWrap([[e1,:c]],S1),T) => + -- need to be careful about zeros + p:= ASSQ(exp,x) => + c' := SPADCALL(CDR p,objValUnwrap(y),plusfunc) + c' = zero => x := REMALIST(x,exp) + RPLACD(p,c') + zero = objValUnwrap(y) => 'iterate + x := CONS(CONS(exp,objValUnwrap(y)),x) + y => nreverse SORTBY('CAR,x) + coercionFailure() + +removeVectorElt(v,pos) == + -- removes the pos'th element from vector v + LIST2VEC [x for x in VEC2LIST v for y in 0.. | not (y=pos)] + +removeListElt(l,pos) == + pos = 0 => CDR l + [CAR l, :removeListElt(CDR l,pos-1)] + +NDmp2domain(u,source is [ndmp,x,S],target) == + -- a null NDMP = 0 + null u => domainZero(target) + dmp := 'DistributedMultivariatePolynomial + source' := [dmp,x,S] + u = '_$fromCoerceable_$ => canCoerce(source',target) + u' := addDmpLikeTermsAsTarget(u,source') + (u'' := coerceInt(objNewWrap(u',source'),target)) => + objValUnwrap(u'') + coercionFailure() + +NDmp2NDmp(u,source is [ndmp,x,S],target is [.,y,T]) == + -- a null NDMP = 0 + null u => domainZero(target) + dmp := 'DistributedMultivariatePolynomial + source' := [dmp,x,S] + target' := [dmp,y,T] + u = '_$fromCoerceable_$ => canCoerce(source',target') + u' := addDmpLikeTermsAsTarget(u,source') + (u'' := coerceInt(objNewWrap(u',source'),target')) => + addDmpLikeTermsAsTarget(objValUnwrap(u''),target) + coercionFailure() + +--% Expression + +Expr2Complex(u,source is [.,S], target is [.,T]) == + u = '_$fromCoerceable_$ => nil -- can't tell, in general + + not member(S, [$Integer, $Float, $DoubleFloat]) => coercionFailure() + not member(T, [$Float, $DoubleFloat]) => coercionFailure() + + complexNumeric := getFunctionFromDomain("complexNumeric", ['Numeric, S], [source]) + + -- the following might fail + cf := SPADCALL(u,complexNumeric) -- returns a Float + T = $DoubleFloat => + null (z := coerceInt(objNewWrap(cf, ['Complex, $Float]), ['Complex, $DoubleFloat])) => + coercionFailure() + objValUnwrap z + cf + +Expr2Dmp(u,source is [Expr,S], target is [dmp,v2,T]) == + u = '_$fromCoerceable_$ => canCoerce(source, T) + + null v2 => + not (z := coerceInt(objNewWrap(u, source), T)) => coercionFailure() + [[LIST2VEC NIL, :objValUnwrap z]] + + obj := objNewWrap(u, source) + univ := coerceInt(obj, ['UnivariatePolynomial, first v2, T]) + not univ => + T = source => coercionFailure() + not (z := coerceInt(obj, [dmp, v2, source])) => + coercionFailure() + z := objValUnwrap z + for term in z repeat + [., :c] := term + not (c := coerceInt(objNewWrap(c, source), T)) => coercionFailure() + RPLACD(term, objValUnwrap c) + z + + univ := objValUnwrap univ + + -- only one variable + + null rest v2 => + for term in univ repeat + RPLACA(term, VECTOR CAR term) + univ + + -- more than one variable + + summands := nil + for [e,:c] in univ repeat + summands := Expr2Dmp1(summands, + LIST2VEC [e, :[0 for v in rest v2]], c, T, 1, rest v2, T) + + plus := getFunctionFromDomain("+", target, [target, target]) + sum := domainZero target + for summand in summands repeat + sum := SPADCALL([summand], sum, plus) + sum + +Expr2Dmp1(summands, vec, c, source, index, varList, T) == + if null varList then + if not (source = T) then + not (c := coerceInt(objNewWrap(c, source), T)) => coercionFailure() + c := objValUnwrap c + summands := [[vec, :c], :summands] + else + univ := coerceInt(objNewWrap(c, source), + ['UnivariatePolynomial, first varList, T]) + univ := objValUnwrap univ + + for [e,:c] in univ repeat + vec := COPY_-SEQ vec + vec.index := e + summands := Expr2Dmp1(summands, vec, c, T, index+1, rest varList, T) + summands + +Expr2Mp(u,source is [Expr,S], target is [.,v2,T]) == + u = '_$fromCoerceable_$ => canCoerce(source, T) + + dmp := ['DistributedMultivariatePolynomial,v2,T] + d := Expr2Dmp(u,source, dmp) + not (m := coerceInt(objNewWrap(d, dmp), target)) => coercionFailure() + objValUnwrap m + +Expr2Up(u,source is [Expr,S], target is [.,var,T]) == + u = '_$fromCoerceable_$ => canCoerce(source, T) + kernelFunc := getFunctionFromDomain("kernels", source, [source]) + kernelDom := ['Kernel, source] + nameFunc := getFunctionFromDomain("name", kernelDom, [kernelDom]) + kernels := SPADCALL(u,kernelFunc) + v1 := [SPADCALL(kernel, nameFunc) for kernel in kernels] + + not member(var, v1) => coercionFailure() + + -- variable is a kernel + + varKernel := kernels.(POSN1(var, v1)) + univFunc := getFunctionFromDomain("univariate", source, [source, kernelDom]) + sup := ['SparseUnivariatePolynomial, source] + + fracUniv := SPADCALL(u, varKernel, univFunc) + denom := CDR fracUniv + + not equalOne(denom, sup) => coercionFailure() + + numer := CAR fracUniv + uniType := ['UnivariatePolynomial, var, source] + (z := coerceInt(objNewWrap(numer, uniType), target)) => objValUnwrap z + coercionFailure() + +--% Kernels over Expr + +Ker2Ker(u,source is [.,S], target is [.,T]) == + u = '_$fromCoerceable_$ => canCoerce(S, T) + not (m := coerceInt(objNewWrap(u, source), S)) => coercionFailure() + u' := objValUnwrap m + not (m' := coerceInt(objNewWrap(u', S), T)) => coercionFailure() + u'' := objValUnwrap m' + not (m'' := coerceInt(objNewWrap(u'', T), target)) => coercionFailure() + objValUnwrap m'' + +Ker2Expr(u,source is [.,S], target) == + u = '_$fromCoerceable_$ => canCoerce(S, target) + not (m := coerceByFunction(objNewWrap(u, source), S)) => coercionFailure() + u':= objValUnwrap m + not (m' := coerceInt(objNewWrap(u', S), target)) => coercionFailure() + objValUnwrap m' + + +--% Factored objects + +Factored2Factored(u,oldmode,newmode) == + [.,oldargmode,:.]:= oldmode + [.,newargmode,:.]:= newmode + u = '_$fromCoerceable_$ => canCoerce(oldargmode,newargmode) + u' := unwrap u + unit' := coerceInt(objNewWrap(first u',oldargmode),newargmode) + null unit' => coercionFailure() + factors := KDR u' + factors' := [(coerceFFE(x,oldargmode,newargmode)) for x in factors] + member('failed,factors') => coercionFailure() + [objValUnwrap(unit'),:factors'] + +coerceFFE(ffe, oldmode, newmode) == + fac' := coerceInt(objNewWrap(ffe.1,oldmode),newmode) + null fac' => 'failed + LIST2VEC [ffe.0,objValUnwrap(fac'),ffe.2] + +--% Complex + +Complex2underDomain(u,[.,S],target) == + u = '_$fromCoerceable_$ => nil + [r,:i] := u + i=domainZero(S) => + [r',.,.]:= coerceInt(objNewWrap(r,S),target) or + coercionFailure() + r' + coercionFailure() + +Complex2FR(u,S is [.,R],target is [.,T]) == + u = '_$fromCoerceable_$ => + S ^= T => nil + R = $Integer => true + nil + S ^= T => coercionFailure() + package := + R = $Integer => ['GaussianFactorizationPackage] + coercionFailure() + factor := getFunctionFromDomain('factor,package,[S]) + SPADCALL(u,factor) + +Complex2Expr(u, source is [.,S], target is [., T]) == + u = '_$fromCoerceable_$ => + T is ['Complex, T1] and canCoerceFrom(S, T1) or coercionFailure() + E := defaultTargetFE source + negOne := coerceInt(objNewWrap(-1, $Integer), E) + null negOne => coercionFailure() + sqrtFun := getFunctionFromDomain('sqrt, E, [E]) + i := SPADCALL(objValUnwrap negOne, sqrtFun) + realFun := getFunctionFromDomain('real, source, [source]) + imagFun := getFunctionFromDomain('imag, source, [source]) + real := SPADCALL(u, realFun) + imag := SPADCALL(u, imagFun) + realExp := coerceInt(objNewWrap(real, S), E) + null realExp => coercionFailure() + imagExp := coerceInt(objNewWrap(imag, S), E) + null imagExp => coercionFailure() + timesFun := getFunctionFromDomain('_*, E, [E, E]) + plusFun := getFunctionFromDomain('_+, E, [E, E]) + newVal := SPADCALL(objValUnwrap(realExp), + SPADCALL(i, objValUnwrap imagExp, timesFun), plusFun) + newObj := objNewWrap(newVal, E) + finalObj := coerceInt(newObj, target) + finalObj => objValUnwrap finalObj + coercionFailure() + +--% Integer + +I2EI(n,source,target) == + n = '_$fromCoerceable_$ => nil + if not ODDP(n) then n else coercionFailure() + +I2OI(n,source,target) == + n = '_$fromCoerceable_$ => nil + if ODDP(n) then n else coercionFailure() + +I2PI(n,source,target) == + n = '_$fromCoerceable_$ => nil + if n > 0 then n else coercionFailure() + +I2NNI(n,source,target) == + n = '_$fromCoerceable_$ => nil + if n >= 0 then n else coercionFailure() + +--% List + +L2Tuple(val, source is [.,S], target is [.,T]) == + val = '_$fromCoerceable_$ => canCoerce(S,T) + null (object := coerceInt1(mkObjWrap(val,source), ['List, T])) => + coercionFailure() + asTupleNew0 objValUnwrap object + +L2DP(l, source is [.,S], target is [.,n,T]) == + -- need to know size of the list + l = '_$fromCoerceable_$ => nil + n ^= SIZE l => coercionFailure() + (v := coerceInt(objNewWrap(LIST2VEC l,['Vector,S]),['Vector,T])) or + coercionFailure() + V2DP(objValUnwrap v, ['Vector, T], target) + +V2DP(v, source is [.,S], target is [.,n,T]) == + -- need to know size of the vector + v = '_$fromCoerceable_$ => nil + n ^= SIZE v => coercionFailure() + (v1 := coerceInt(objNewWrap(v,source),['Vector,T])) or + coercionFailure() + dpFun := getFunctionFromDomain('directProduct, target, [['Vector,T]]) + SPADCALL(objValUnwrap v1, dpFun) + +L2V(l, source is [.,S], target is [.,T]) == + l = '_$fromCoerceable_$ => canCoerce(S,T) + (v := coerceInt(objNewWrap(LIST2VEC l,['Vector,S]),target)) or + coercionFailure() + objValUnwrap(v) + +V2L(v, source is [.,S], target is [.,T]) == + v = '_$fromCoerceable_$ => canCoerce(S,T) + (l := coerceInt(objNewWrap(VEC2LIST v,['List,S]),target)) or + coercionFailure() + objValUnwrap(l) + +L2M(u,[.,D],[.,R]) == + u = '_$fromCoerceable_$ => nil + D is ['List,E] and isRectangularList(u,#u,# first u) => + u' := nil + for x in u repeat + x' := nil + for y in x repeat + (y' := coerceInt(objNewWrap(y,E),R)) or coercionFailure() + x' := [objValUnwrap(y'),:x'] + u' := [LIST2VEC reverse x',:u'] + LIST2VEC reverse u' + coercionFailure() + +L2Record(l,[.,D],[.,:al]) == + l = '_$fromCoerceable_$ => nil + #l = #al => + v:= [u for x in l for [":",.,D'] in al] where u == + T:= coerceInt(objNewWrap(x,D),D') or return 'failed + objValUnwrap(T) + v = 'failed => coercionFailure() + #v = 2 => [v.0,:v.1] + LIST2VEC v + coercionFailure() + +L2Rm(u,source is [.,D],target is [.,n,m,R]) == + u = '_$fromCoerceable_$ => nil + D is ['List,E] and isRectangularList(u,n,m) => + L2M(u,source,['Matrix,R]) + coercionFailure() + +L2Sm(u,source is [.,D],[.,n,R]) == + u = '_$fromCoerceable_$ => nil + D is ['List,E] and isRectangularList(u,n,n) => + L2M(u,source,['Matrix,R]) + coercionFailure() + +L2Set(x,source is [.,S],target is [.,T]) == + x = '_$fromCoerceable_$ => canCoerce(S,T) + -- call library function brace to get a set + target' := ['Set,S] + u := objNewWrap( + SPADCALL(x,getFunctionFromDomain('brace,target',[source])), + target') + (u := coerceInt(u,target)) or coercionFailure() + objValUnwrap u + +Set2L(x,source is [.,S],target is [.,T]) == + x = '_$fromCoerceable_$ => canCoerce(S,T) + -- call library function destruct to get a list + u := objNewWrap( + SPADCALL(x,getFunctionFromDomain('destruct,source,[source])), + ['List,S]) + (u := coerceInt(u,target)) or coercionFailure() + objValUnwrap u + +Agg2Agg(x,source is [agg1,S],target is [.,T]) == + x = '_$fromCoerceable_$ => canCoerce(S,T) + S = T => coercionFailure() -- library function + target' := [agg1,T] + (u := coerceInt(objNewWrap(x,source),target')) or coercionFailure() + (u := coerceInt(u,target)) or coercionFailure() + objValUnwrap u + +Agg2L2Agg(x,source is [.,S],target) == + -- tries to use list as an intermediate type + mid := ['List,S] + x = '_$fromCoerceable_$ => + canCoerce(source,mid) and canCoerce(mid,target) + (u := coerceInt(objNewWrap(x,source),mid)) or coercionFailure() + (u := coerceInt(u,target)) or coercionFailure() + objValUnwrap u + +isRectangularList(x,p,q) == + p=0 or p=#x => + n:= #first x + and/[n=#y for y in rest x] => p=0 or q=n + +--% Matrix + +M2L(x,[.,S],target) == + mid := ['Vector,['Vector,S]] + x = '_$fromCoerceable_$ => canCoerce(mid,target) + (u := coerceInt(objNewWrap(x,mid),target)) or coercionFailure() + objValUnwrap u + +M2M(x,[.,R],[.,S]) == + x = '_$fromCoerceable_$ => canCoerce(R,S) + n := # x + m := # x.0 + v := nil + for i in 0..(n-1) repeat + u := nil + for j in 0..(m-1) repeat + y := x.i.j + (y' := coerceInt(objNewWrap(y,R),S)) or coercionFailure() + u := [objValUnwrap y',:u] + v := [LIST2VEC reverse u,:v] + LIST2VEC reverse v + +M2Rm(x,source is [.,R],[.,p,q,S]) == + x = '_$fromCoerceable_$ => nil + n:= #x + m:= #x.0 + n=p and m=q => M2M(x,source,[nil,S]) + coercionFailure() + +M2Sm(x,source is [.,R],[.,p,S]) == + x = '_$fromCoerceable_$ => nil + n:= #x + m:= #x.(0) + n=m and m=p => M2M(x,source,[nil,S]) + coercionFailure() + +M2V(x,[.,S],target) == + mid := ['Vector,['Vector,S]] + x = '_$fromCoerceable_$ => canCoerce(mid,target) + (u := coerceInt(objNewWrap(x,mid),target)) or coercionFailure() + objValUnwrap u + +--% Multivariate Polynomial + +Mp2Dmp(u, source is [., x, S], target is [dmp, y, T]) == + -- Change the representation to a DMP with the same variables and + -- coerce. + target' := [dmp,x,S] + u = '_$fromCoerceable_$ => canCoerce(target',target) + + -- check if we have a constant + u is [ =0,:c] => + null (u' := coerceInt(objNewWrap(c,S),target)) => + coercionFailure() + objValUnwrap(u') + + plus := getFunctionFromDomain('_+,target',[target',target']) + mult := getFunctionFromDomain('_*,target',[target',target']) + one := domainOne(S) + zero := domainZero(S) + (u' := coerceInt(objNewWrap(Mp2SimilarDmp(u,S,#x,plus,mult,one,zero), + target'),target)) or coercionFailure() + objValUnwrap(u') + +Mp2SimilarDmp(u,S,n,plus,mult,one,zero) == + u is [ =0,:c] => + c = zero => NIL -- zero for dmp + [[LIST2VEC LZeros n,:c]] + u is [ =1,x,:terms] => + u' := NIL -- zero for dmp + for [e,:c] in terms repeat + e' := LIST2VEC LZeros n + e'.(x-1) := e + t := [[e',:one]] + t := SPADCALL(t,Mp2SimilarDmp(c,S,n,plus,mult,one,zero),mult) + u' := SPADCALL(u',t,plus) + u' + +Mp2Expr(u,source is [mp,vars,S], target is [Expr,T]) == + u = '_$fromCoerceable_$ => canCoerce(S, target) + + dmp := ['DistributedMultivariatePolynomial, vars, S] + not (d := coerceInt(objNewWrap(u, source), dmp)) => coercionFailure() + Dmp2Expr(objValUnwrap d, dmp, target) + +Mp2FR(u,S is [.,vl,R],[.,T]) == + u = '_$fromCoerceable_$ => + S ^= T => nil + R in '((Integer) (Fraction (Integer))) => true + nil + S ^= T => coercionFailure() + package := + R = $Integer => + ovl := ['OrderedVariableList, vl] + ['MultivariateFactorize,ovl, ['IndexedExponents, ovl],R,S] + R is ['Fraction, D] => + ovl := ['OrderedVariableList, vl] + package := ['MRationalFactorize,['IndexedExponents, ovl], ovl, D, S] + coercionFailure() + factor := getFunctionFromDomain('factor,package,[S]) + SPADCALL(u,factor) + +Mp2Mp(u,source is [mp,x,S], target is [.,y,T]) == + -- need not deal with case of x = y (coerceByMapping) + common := intersection(y,x) + x' := SETDIFFERENCE(x,common) + y' := SETDIFFERENCE(y,common) + + u = '_$fromCoerceable_$ => + x = y => canCoerce(S,T) + null common => canCoerce(source,T) + null x' => canCoerce(S,target) + null y' => canCoerce([mp,x',S],T) + canCoerce([mp,x',S],[mp,y',T]) + + -- first check for constant case + u is [ =0,:c] => + (u' := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + objValUnwrap(u') + + plus := getFunctionFromDomain('_+,target,[target,target]) + + -- now no-common-variables case + + null common => + times := getFunctionFromDomain('_*,target,[target,target]) + expn := getFunctionFromDomain('_*_*,target, + [target,$NonNegativeInteger]) + Mp2MpAux0(u,S,target,x,plus,times,expn) + + -- if source vars are all in target + null x' => + monom := getFunctionFromDomain('monomial,target, + [target,['OrderedVariableList,y],$NonNegativeInteger]) + Mp2MpAux1(u,S,target,x,y,plus,monom) + + -- if target vars are all in source + null y' => -- change source to MP[common] MP[x'] S + univariate := getFunctionFromDomain('univariate, + source,[source,['OrderedVariableList,x]]) + u' := Mp2MpAux2(u,x,common,x',common,x',univariate,S,NIL) + (u' := coerceInt(objNewWrap(u', [mp,common,[mp,x',S]]),target)) or + coercionFailure() + objValUnwrap(u') + + -- we have a mixture + (u' := coerceInt(objNewWrap(u,source),[mp,common,[mp,x',S]])) or + coercionFailure() + (u' := coerceInt(u',target)) or coercionFailure() + objValUnwrap(u') + +Mp2MpAux0(u,S,target,vars,plus,times,expn) == + -- for case when no common variables + u is [ =0,:c] => + (u' := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + objValUnwrap(u') + [.,var,:terms] := u + [mp,.,T] := target + x := coerceInt(objNewWrap(vars.(var-1),['Variable,vars.(var-1)]), + [mp,vars,$Integer]) or coercionFailure() + (x := coerceInt(x,T)) or coercionFailure() + x := [0,:objValUnwrap x] + sum := domainZero(target) + for [e,:c] in terms repeat + prod := SPADCALL(SPADCALL(x,e,expn), + Mp2MpAux0(c,S,target,vars,plus,times,expn),times) + sum := SPADCALL(sum,prod,plus) + sum + +Mp2MpAux1(u,S,target,varl1,varl2,plus,monom) == + -- for case when source vars are all in target + u is [ =0,:c] => + (u' := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + objValUnwrap(u') + [.,var,:terms] := u + sum := domainZero(target) + for [e,:c] in terms repeat + mon := SPADCALL( Mp2MpAux1(c,S,target,varl1,varl2,plus,monom), + position1(varl1.(var-1), varl2),e,monom) + sum := SPADCALL(sum,mon,plus) + sum + +Mp2MpAux2(u,x,oldcomm,oldrest,common,restvars,univariate,S,isUnder) == + -- target vars are all in source + mp2 := ['MultivariatePolynomial,oldcomm,['MultivariatePolynomial, + oldrest,S]] + common => + u is [ =0,:c] => + (u' := coerceInt(objNewWrap(c,S),mp2)) or coercionFailure() + objValUnwrap(u') + [var,:common] := common + u' := SPADCALL(u,position1(var,x),univariate) + null(rest(u')) and (first(first(u')) = 0) => + Mp2MpAux2(u,x,oldcomm,oldrest,common,restvars,univariate,S,isUnder) + [1,position1(var,oldcomm),:[[e,:Mp2MpAux2(c,x,oldcomm,oldrest, + common,restvars,univariate,S,isUnder)] for [e,:c] in u']] + null isUnder => + [0,:Mp2MpAux2(u,x,oldcomm,oldrest,common,restvars,univariate,S,true)] + -- just treat like elt of [mp,x',S] + u is [ =0,:c] => u + [var,:restvars] := restvars + u' := SPADCALL(u,position1(var,x),univariate) + null(rest(u')) and (first(first(u')) = 0) => + Mp2MpAux2(u,x,oldcomm,oldrest,common,restvars,univariate,S,isUnder) + [1,position1(var,oldrest),:[[e,:Mp2MpAux2(c,x,oldcomm,oldrest, + common,restvars,univariate,S,isUnder)] for [e,:c] in u']] + +genMpFromDmpTerm(u, oldlen) == + + -- given one term of a DMP representation of a polynomial, this creates + -- the corresponding MP term. + + patlen := oldlen + [e,:c] := u + numexps := # e + patlen >= numexps => [0, :c] + for i in patlen..(numexps - 1) repeat + e.i = 0 => patlen := patlen + 1 + return nil + patlen >= numexps => [0, :c] + [1, 1+patlen, [e.patlen,:genMpFromDmpTerm(u,patlen+1)]] + +Mp2P(u, source is [mp,vl, S], target is [p,R]) == + u = '_$fromCoerceable_$ => canCoerce(S,target) + S is ['Polynomial,.] => MpP2P(u,vl,S,R) + vl' := REVERSE MSORT vl + -- if Mp2Mp fails, a THROW will occur + u' := Mp2Mp(u,source,[mp,vl',S]) + u' := translateMpVars2PVars (u',vl') + (u' := coerceInt(objNewWrap(u',[p,S]),target)) or coercionFailure() + objValUnwrap(u') + +MpP2P(u,vl,PS,R) == + -- u has type MP(vl,PS). Want to coerce to P R. + PR := ['Polynomial,R] + u is [ =0,:c] => + (u' :=coerceInt(objNewWrap(c,PS),PR)) or + coercionFailure() + objValUnwrap u' + [ .,pos,:ec] := u + multivariate := getFunctionFromDomain('multivariate, + PR,[['SparseUnivariatePolynomial,PR],$Symbol]) + sup := [[e,:MpP2P(c,vl,PS,R)] for [e,:c] in ec] + p := SPADCALL(sup,vl.(pos-1),multivariate) + --(p' :=coerceInt(objNewWrap(p,PS),['Polynomial,R])) or coercionFailure() + --objValUnwrap(p') + +Mp2Up(u,source is [mp,vl,S],target is [up,x,T]) == + u = '_$fromCoerceable_$ => + member(x,vl) => + vl = [x] => canCoerce(S,T) + canCoerce([mp,delete(x,vl),S],T) + canCoerce(source,T) + + u is [ =0,:c] => -- constant polynomial? + (u' := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + objValUnwrap u' + + null member(x,vl) => + (u' := coerceInt(objNewWrap(u,source),T)) or coercionFailure() + [[0,:objValUnwrap(u')]] + + vl = [x] => + u' := [[e,:c] for [e,.,:c] in CDDR u] + (u' := coerceInt(objNewWrap(u',[up,x,S]),target)) + or coercionFailure() + objValUnwrap u' + + -- do a univariate to transform u to a UP(x,P S) and then coerce again + var := position1(x,vl) + UPP := ['UnivariatePolynomial,x,source] + univariate := getFunctionFromDomain('univariate, + source,[source,['OrderedVariableList,vl]]) + upU := SPADCALL(u,var,univariate) -- we may assume this has type UPP + (u' := coerceInt(objNewWrap(upU,UPP),target)) or coercionFailure() + objValUnwrap u' + +--% OrderedVariableList + +OV2OV(u,source is [.,svl], target is [.,tvl]) == + svl = intersection(svl,tvl) => + u = '_$fromCoerceable_$ => true + position1(svl.(u-1),tvl) + u = '_$fromCoerceable_$ => nil + coercionFailure() + +OV2P(u,source is [.,svl], target is [.,T]) == + u = '_$fromCoerceable_$ => true + v := svl.(unwrap(u)-1) + [1,v,[1,0,:domainOne(T)]] + +OV2poly(u,source is [.,svl], target is [p,vl,T]) == + u = '_$fromCoerceable_$ => + p = 'UnivariatePolynomial => (# svl = 1) and (p = svl.0) + and/[member(v,vl) for v in svl] + v := svl.(unwrap(u)-1) + val' := [1,:domainOne(T)] + p = 'UnivariatePolynomial => + v ^= vl => coercionFailure() + [[1,:domainOne(T)]] + null member(v,vl) => coercionFailure() + val' := [[1,:domainOne(T)]] + source' := ['UnivariatePolynomial,v,T] + (u' := coerceInt(objNewWrap(val',source'),target)) or + coercionFailure() + objValUnwrap(u') + +OV2SE(u,source is [.,svl], target) == + u = '_$fromCoerceable_$ => true + svl.(unwrap(u)-1) + +OV2Sy(u,source is [.,svl], target) == + u = '_$fromCoerceable_$ => true + svl.(unwrap(u)-1) + +--% Polynomial + +varsInPoly(u) == + u is [ =1, v, :termlist] => + [v,:varsInPoly(c) for [e,:c] in termlist] + nil + +P2FR(u,S is [.,R],[.,T]) == + u = '_$fromCoerceable_$ => + S ^= T => nil + R in '((Integer) (Fraction (Integer))) => true + nil + S ^= T => coercionFailure() + package := + R = $Integer => + ['MultivariateFactorize,$Symbol,['IndexedExponents, $Symbol],R,S] + R is ['Fraction, D] => + package := ['MRationalFactorize,['IndexedExponents, $Symbol],$Symbol, + D, S] + coercionFailure() + factor := getFunctionFromDomain('factor,package,[S]) + SPADCALL(u,factor) + +P2Dmp(u, source is [., S], target is [., y, T]) == + u = '_$fromCoerceable_$ => + -- might be able to say yes + canCoerce(source,T) + u is [ =0,:c] => -- polynomial is a constant + (u' := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + objValUnwrap(u') + univariate := getFunctionFromDomain('univariate, + source,[source,$Symbol]) + plus := getFunctionFromDomain("+",target,[target,target]) + monom := getFunctionFromDomain('monomial,target, + [target,['OrderedVariableList,y],$NonNegativeInteger]) + P2DmpAux(u,source,S,target,copy y,y,T,univariate,plus,monom) + +P2Expr(u, source is [.,S], target is [., T]) == + u = '_$fromCoerceable_$ => + canCoerce(S, T) + S = T => coercionFailure() + newS := ['Polynomial, T] + val := coerceInt(objNewWrap(u, source), newS) + null val => coercionFailure() + val := coerceInt(val, target) + null val => coercionFailure() + objValUnwrap val + +P2DmpAux(u,source,S,target,varlist,vars,T,univariate,plus,monom) == + u is [ =0,:c] => -- polynomial is a constant + (u' := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + objValUnwrap(u') + + -- if no variables left, try to go to underdomain of target (T) + null vars => + (u' := coerceInt(objNewWrap(u,source),T)) or coercionFailure() + -- if successful, embed + (u' := coerceByFunction(u',target)) or coercionFailure() + objValUnwrap(u') + + -- there are variables, so get them out of u + [x,:vars] := vars + sup := SPADCALL(u,x,univariate) -- this is a SUP P S + null sup => -- zero? unlikely. + domainZero(target) + -- degree 0 polynomial? (variable did not occur) + null(rest(sup)) and first(sup) is [ =0,:c] => + -- call again, but with one less var + P2DmpAux(c,source,S,target,varlist,vars,T,univariate,plus,monom) + var := position1(x,varlist) + u' := domainZero(target) + for [e,:c] in sup repeat + u'' := SPADCALL( + P2DmpAux(c,source,S,target,varlist,vars,T,univariate,plus,monom), + var,e,monom) + u' := SPADCALL(u',u'',plus) + u' + +P2Mp(u, source is [., S], target is [., y, T]) == + u = '_$fromCoerceable_$ => + -- might be able to say yes + canCoerce(source,T) + univariate := getFunctionFromDomain('univariate, + source,[source,$Symbol]) + P2MpAux(u,source,S,target,copy y,y,T,univariate) + +P2MpAux(u,source,S,target,varlist,vars,T,univariate) == + u is [ =0,:c] => -- polynomial is a constant + (u' := coerceInt(objNewWrap(c,S),target)) or + coercionFailure() + objValUnwrap(u') + + -- if no variables left, try to go to underdomain of target (T) + null vars => + (u' := coerceInt(objNewWrap(u,source),T)) or + coercionFailure() + -- if successful, embed + [ 0,:objValUnwrap(u')] + + -- there are variables, so get them out of u + [x,:vars] := vars + sup := SPADCALL(u,x,univariate) -- this is a SUP P S + null sup => -- zero? unlikely. + domainZero(target) + -- degree 0 polynomial? (variable did not occur) + null(rest(sup)) and first(sup) is [ =0,:c] => + -- call again, but with one less var + P2MpAux(c,source,S,target,varlist,vars,T,univariate) + terms := [[e,:P2MpAux(c,source,S,target,varlist,vars,T,univariate)] for + [e,:c] in sup] + [1, position1(x,varlist), :terms] + +varIsOnlyVarInPoly(u, var) == + u is [ =1, v, :termlist] => + v ^= var => nil + and/[varIsOnlyVarInPoly(c,var) for [e,:c] in termlist] + true + +P2Up(u,source is [.,S],target is [.,x,T]) == + u = '_$fromCoerceable_$ => canCoerce(source,T) + u is [ =0,:c] => + (u' := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + objValUnwrap(u') + + -- see if the target var is the polynomial vars + varsFun := getFunctionFromDomain('variables,source,[source]) + vars := SPADCALL(u,varsFun) + not member(x,vars) => + (u' := coerceInt(objNewWrap(u,source),T)) or coercionFailure() + [[0,:objValUnwrap(u')]] + + -- do a univariate to transform u to a UP(x,P S) and then coerce again + UPP := ['UnivariatePolynomial,x,source] + univariate := getFunctionFromDomain('univariate, + source,[source,$Symbol]) + upU := SPADCALL(u,x,univariate) -- we may assume this has type UPP + (u' := coerceInt(objNewWrap(upU,UPP),target)) or coercionFailure() + objValUnwrap(u') + +--% Fraction + +Qf2PF(u,source is [.,D],target) == + u = '_$fromCoerceable_$ => canCoerce(D,target) + [num,:den] := u + num':= coerceInt(objNewWrap(num,D),target) or + coercionFailure() + num' := objValUnwrap num' + den':= coerceInt(objNewWrap(den,D),target) or + coercionFailure() + den' := objValUnwrap den' + equalZero(den', target) => throwKeyedMsg("S2IA0001",NIL) + SPADCALL(num',den', getFunctionFromDomain("/",target,[target,target])) + +Qf2F(u,source is [.,D,:.],target) == + D = $Integer => + u = '_$fromCoerceable_$ => true + Rn2F(u,source,target) + u = '_$fromCoerceable_$ => canCoerce(D,target) + [num,:den] := u + [.,:num']:= coerceInt(objNewWrap(num,D),target) or + coercionFailure() + [.,:den']:= coerceInt(objNewWrap(den,D),target) or + coercionFailure() + (unwrap num') * 1.0 / (unwrap den') + +Rn2F(rnum, source, target) == + float(CAR(rnum)/CDR(rnum)) + +-- next function is needed in RN algebra code +--Rn2F([a,:b],source,target) == +-- al:=if LINTP a then QLENGTHCODE a else 4 +-- bl:=if LINTP b then QLENGTHCODE b else 4 +-- MAX(al,bl) < 36 => FLOAT a / FLOAT b +-- sl:=0 +-- if al>32 then +-- sl:=35*(al-32)/4 +-- a:=a/2**sl +-- if bl>32 then +-- sbl:=35*(bl-32)/4 +-- b:=b/2**sbl +-- sl:=sl-sbl +-- ans:=FLOAT a /FLOAT b +-- sl=0 => ans +-- ans*2**sl + +Qf2domain(u,source is [.,D],target) == + -- tests whether it is an element of the underlying domain + useUnder := (ut := underDomainOf target) and canCoerce(source,ut) + u = '_$fromCoerceable_$ => useUnder + not (containsPolynomial(D) and containsPolynomial(target)) and + useUnder => coercionFailure() -- let other mechanism handle it + [num, :den] := u + (num' := coerceInt(objNewWrap(num,D),target)) or coercionFailure() + num' := objValUnwrap(num') + equalOne(den,D) => num' + (target is [.,[=$QuotientField,T]]) or + (target is [.,.,[=$QuotientField,T]]) => + (den' := coerceInt(objNewWrap(den,D),T)) or coercionFailure() + den' := [domainOne(T),:objValUnwrap(den')] + timesfunc:= getFunctionFromDomain('_*,target, + [[$QuotientField,T],target]) + SPADCALL(den',num',timesfunc) + coercionFailure() + +Qf2EF(u,[.,S],target) == + u = '_$fromCoerceable_$ => canCoerce(S,target) + [num,:den] := u + (num' := coerceInt(objNewWrap(num,S),target)) or + coercionFailure() + (den' := coerceInt(objNewWrap(den,S),target)) or + coercionFailure() + divfun := getFunctionFromDomain("/",target,[target,target]) + SPADCALL(objValUnwrap(num'),objValUnwrap(den'),divfun) + +Qf2Qf(u0,[.,S],target is [.,T]) == + u0 = '_$fromCoerceable_$ => + S = ['Polynomial, [$QuotientField, $Integer]] and + T = '(Polynomial (Integer)) => true + canCoerce(S,T) + [a,:b] := u0 + S = ['Polynomial, [$QuotientField, $Integer]] and + T = '(Polynomial (Integer)) => + (a' := coerceInt(objNewWrap(a,S),target)) => + (b' := coerceInt(objNewWrap(b,S),target)) => + divfunc:= getFunctionFromDomain('_/,target,[target,target]) + SPADCALL(objValUnwrap(a'),objValUnwrap(b'),divfunc) + coercionFailure() + coercionFailure() + (a' := coerceInt(objNewWrap(a,S),T)) => + (b' := coerceInt(objNewWrap(b,S),T)) => + [objValUnwrap(a'),:objValUnwrap(b')] + coercionFailure() + coercionFailure() + +-- partOf(x,i) == +-- VECP x => x.i +-- i=0 => first x +-- i=1 => rest x +-- systemError '"partOf" + +--% RectangularMatrix + +Rm2L(x,[.,.,.,R],target) == M2L(x,['Matrix,R],target) + +Rm2M(x,[.,.,.,R],target is [.,S]) == M2M(x,[nil,R],target) + +Rm2Sm(x,[.,n,m,S],[.,p,R]) == + x = '_$fromCoerceable_$ => n=m and m=p and canCoerce(S,R) + n=m and m=p => + M2M(x,[nil,S],[nil,R]) + coercionFailure() + +Rm2V(x,[.,.,.,R],target) == M2V(x,['Matrix,R],target) + +--% Script + +Scr2Scr(u, source is [.,S], target is [.,T]) == + u = '_$fromCoerceable_$ => canCoerce(S,T) + null (v := coerceInt(objNewWrap(CDR u,S),T)) => + coercionFailure() + [CAR u, :objValUnwrap(v)] + +--% SparseUnivariatePolynomialnimial + +SUP2Up(u,source is [.,S],target is [.,x,T]) == + u = '_$fromCoerceable_$ => canCoerce(source,T) or canCoerce(S,T) + null u => u + S = T => u + -- try to go underneath first + null (u' := coerceInt(objNewWrap(u,source),T)) => + -- must be careful in case any of the coeffs come back 0 + u' := NIL + zero := getConstantFromDomain('(Zero),T) + for [e,:c] in u repeat + c' := objValUnwrap (coerceInt(objNewWrap(c,S),T) or + coercionFailure()) + c' = zero => 'iterate + u' := [[e,:c'],:u'] + nreverse u' + [[0,:objValUnwrap u']] + +--% SquareMatrix + +Sm2L(x,[.,.,R],target) == M2L(x,['Matrix,R],target) + +Sm2M(x,[.,n,R],target is [.,S]) == M2M(x,[nil,R],target) + +Sm2PolyType(u,source is [sm,n,S], target is [pol,vl,T]) == + -- only really handles cases like: + -- SM[2] P I -> P[x,y] SM[2] P I + -- works for UP, MP, DMP and NDMP + u = '_$fromCoerceable_$ => canCoerce(source,T) + -- first want to check case S is Polynomial + S is ['Polynomial,S'] => + -- check to see if variable occurs in any of the terms + if ATOM vl + then vl' := [vl] + else vl' := vl + novars := true + for i in 0..(n-1) while novars repeat + for j in 0..(n-1) while novars repeat + varsUsed := varsInPoly u.i.j + or/[member(x,varsUsed) for x in vl'] => novars := nil + novars => coercionFailure() + source' := [sm,n,[pol,vl,S]] + null (u' := coerceInt(objNewWrap(u,source),source')) => + coercionFailure() + null (u' := coerceInt(u',target)) => + coercionFailure() + objValUnwrap(u') + -- let other cases be handled by standard machinery + coercionFailure() + +Sm2Rm(x,[.,n,R],[.,p,q,S]) == + x = '_$fromCoerceable_$ => p=q and p=n and canCoerce(R,S) + p=q and p=n => + M2M(x,[nil,R],[nil,S]) + coercionFailure() + +Sm2V(x,[.,.,R],target) == M2V(x,['Matrix,R],target) + +--% Symbol + +Sy2OV(u,source,target is [.,vl]) == + u = '_$fromCoerceable_$ => nil + position1(u,vl) + +Sy2Dmp(u,source,target is [dmp,vl,S]) == + u = '_$fromCoerceable_$ => canCoerce(source,S) + len:= #vl + -1^=(n:= position(u,vl)) => + u:= wrap LIST [LIST2VEC [(n=i => 1; 0) for i in 0..len-1],:1] + objValUnwrap(coerceInt(objNew(u,[dmp,vl,$Integer]),target)) + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [[Zeros len,:objValUnwrap u]] + +Sy2Mp(u,source,target is [mp,vl,S]) == + u = '_$fromCoerceable_$ => canCoerce(source,S) + (n:= position1(u,vl)) ^= 0 => + [1,n,[1,0,:domainOne(S)]] + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [0,:objValUnwrap(u)] + +Sy2NDmp(u,source,target is [ndmp,vl,S]) == + u = '_$fromCoerceable_$ => canCoerce(source,S) + len:= #vl + -1^=(n:= position(u,vl)) => + u:= wrap LIST [LIST2VEC [(n=i => 1; 0) for i in 0..len-1],:1] + objValUnwrap(coerceInt(objNew(u,[ndmp,vl,$Integer]),target)) + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [[Zeros len,:objValUnwrap(u)]] + +Sy2P(u,source,target is [poly,S]) == + u = '_$fromCoerceable_$ => true + -- first try to get it into an underdomain + if (S ^= $Integer) then + u' := coerceInt(objNewWrap(u,source),S) + if u' then return [0,:objValUnwrap(u')] + -- if that failed, return it as a polynomial variable + [1,u,[1,0,:domainOne(S)]] + +Sy2Up(u,source,target is [up,x,S]) == + u = '_$fromCoerceable_$ => canCoerce(source,S) + u=x => [[1,:domainOne(S)]] + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [[0,:objValUnwrap u]] + +Sy2Var(u,source,target is [.,x]) == + u = '_$fromCoerceable_$ => NIL + u=x => u + coercionFailure() + +--% Univariate Polynomial + +Up2Dmp(u,source is ['UnivariatePolynomial,var,S], + target is ['DistributedMultivariatePolynomial,vl,T]) == + -- var must be a member of vl, or u is a constant + u = '_$fromCoerceable_$ => member(var,vl) and canCoerce(S,target) + null u => domainZero(target) + u is [[e,:c]] and e=0 => + z:= coerceInt(objNewWrap(c,S),target) => objValUnwrap(z) + coercionFailure() + member(var,vl) => + x:= domainZero(target) + one:= domainOne(T) + plusfunc:= getFunctionFromDomain('_+,target,[target,target]) + multfunc:= getFunctionFromDomain('_*,target,[target,target]) + n:= #vl ; p:= POSN1(var,vl) + l1:= not (p=0) and [0 for m in 1..p] + l2:= not (p=n-1) and [0 for m in p..n-2] + for [e,:c] in u until not z repeat + z:= coerceInt(objNewWrap(c,S),target) => + y:= SPADCALL(objValUnwrap(z), + [[LIST2VEC [:l1,e,:l2],:one]],multfunc) + x:= SPADCALL(x,y,plusfunc) + z => x + coercionFailure() + coercionFailure() + +Up2Expr(u,source is [up,var,S], target is [Expr,T]) == + u = '_$fromCoerceable_$ => canCoerce(S, target) + + null u => domainZero(target) + + u is [[e,:c]] and e=0 => + (z := coerceInt(objNewWrap(c, S), target)) => objValUnwrap(z) + coercionFailure() + + sym := objValUnwrap coerceInt(objNewWrap(var, $Symbol), target) + + plus := getFunctionFromDomain("+", target, [target, target]) + mult := getFunctionFromDomain("*", target, [target, target]) + expn := getFunctionFromDomain("**", target, [target, $Integer]) + + -- coerce via Horner's rule + + [e1, :c1] := first u + if not (S = target) then + not (c1 := coerceInt(objNewWrap(c1, S), target)) => coercionFailure() + c1 := objValUnwrap(c1) + + for [e2, :c2] in rest u repeat + coef := + e1 - e2 = 1 => sym + SPADCALL(sym, e1-e2, expn) + if not (S = target) then + not (c2 := coerceInt(objNewWrap(c2, S), target)) => + coercionFailure() + c2 := objValUnwrap(c2) + coef := SPADCALL(SPADCALL(c1, coef, mult), c2, plus) + e1 := e2 + c1 := coef + + e1 = 0 => c1 + e1 = 1 => SPADCALL(sym, c1, mult) + SPADCALL(SPADCALL(sym, e1, expn), c1, mult) + +Up2FR(u,S is [.,x,R],target is [.,T]) == + u = '_$fromCoerceable_$ => + S ^= T => nil + R in '((Integer) (Fraction (Integer))) => true + nil + S ^= T => coercionFailure() + package := + R = $Integer => ['UnivariateFactorize,S] + R = $RationalNumber => package := ['RationalFactorize,S] + coercionFailure() + factor := getFunctionFromDomain('factor,package,[S]) + SPADCALL(u,factor) + +Up2Mp(u,source is [.,x,S], target is [.,vl,T]) == + u = '_$fromCoerceable_$ => + member(x,vl) => canCoerce(S,T) + canCoerce(source,T) + + null u => domainZero(target) + + null(rest(u)) and (first(u) is [e,:c]) and e=0 => + x:= coerceInt(objNewWrap(c,S),target) => objValUnwrap(x) + coercionFailure() + + null member(x,vl) => + (x := coerceInt(objNewWrap(u,source),T)) or coercionFailure() + [0,:objValUnwrap(x)] + + plus := getFunctionFromDomain('_+,target,[target,target]) + monom := getFunctionFromDomain('monomial,target, + [target,['OrderedVariableList,vl],$NonNegativeInteger]) + sum := domainZero(target) + pos := position1(x,vl) + + for [e,:c] in u repeat + (p := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + mon := SPADCALL(objValUnwrap(p),pos,e,monom) + sum := SPADCALL(sum,mon,plus) + sum + +Up2P(u,source is [.,var,S],target is [.,T]) == + u = '_$fromCoerceable_$ => canCoerce(S,target) + null u => domainZero(target) + u is [[e,:c]] and e=0 => + x:= coerceInt(objNewWrap(c,S),target) => objValUnwrap(x) + coercionFailure() + pol:= domainZero(target) + one:= domainOne(T) + plusfunc := getFunctionFromDomain("+",target,[target,target]) + multfunc := getFunctionFromDomain("*",target,[target,target]) + for [e,:c] in u until not x repeat + x:= coerceInt(objNewWrap(c,S),target) => + term:= SPADCALL([1,var,[e,0,:one]],objValUnwrap(x),multfunc) + pol:= SPADCALL(pol,term,plusfunc) + coercionFailure() + x => pol + coercionFailure() + +Up2SUP(u,source is [.,x,S],target is [.,T]) == + u = '_$fromCoerceable_$ => canCoerce(source,T) or canCoerce(S,T) + null u => u + S = T => u + -- try to go underneath first + null (u' := coerceInt(objNewWrap(u,source),T)) => + u' := NIL + zero := getConstantFromDomain('(Zero),T) + for [e,:c] in u repeat + c' := objValUnwrap (coerceInt(objNewWrap(c,S),T) or + coercionFailure()) + c' = zero => 'iterate + u' := [[e,:c'],:u'] + nreverse u' + [[0,:objValUnwrap u']] + +Up2Up(u,source is [.,v1,S], target is [.,v2,T]) == + -- if v1 = v2 then this is handled by coerceIntByMap + -- this only handles case where poly is a constant + u = '_$fromCoerceable_$ => + v1=v2 => canCoerce(S,T) + canCoerce(source,T) + null u => u + u is [[e,:c]] and e=0 => + x:= coerceInt(objNewWrap(c,S),target) => objValUnwrap(x) + coercionFailure() + coercionFailure() + +insertAlist(a,b,l) == + null l => [[a,:b]] + a = l.0.0 => (RPLAC(CDAR l,b);l) + _?ORDER(l.0.0,a) => [[a,:b],:l] + (fn(a,b,l);l) where fn(a,b,l) == + null rest l => RPLAC(rest l,[[a,:b]]) + a = l.1.0 => RPLAC(rest l.1,b) + _?ORDER(l.1.0,a) => RPLAC(rest l,[[a,:b],:rest l]) + fn(a,b,rest l) + +--% Union + +Un2E(x,source,target) == + ['Union,:branches] := source + x = '_$fromCoerceable_$ => + and/[canCoerce(t, target) for t in branches | ^ STRINGP t] + coerceUn2E(x,source) + +--% Variable + +Var2OV(u,source,target is [.,vl]) == + sym := CADR source + u = '_$fromCoerceable_$ => member(sym,vl) + member(sym,vl) => position1(sym,vl) + coercionFailure() + +Var2Dmp(u,source,target is [dmp,vl,S]) == + sym := CADR source + u = '_$fromCoerceable_$ => member(sym,vl) or canCoerce(source,S) + + len := #vl + -1 ^= (n:= position(sym,vl)) => + LIST [LIST2VEC [(n=i => 1; 0) for i in 0..len-1], + :getConstantFromDomain('(One),S)] + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [[Zeros len,:objValUnwrap u]] + +Var2Gdmp(u,source,target is [dmp,vl,S]) == + sym := CADR source + u = '_$fromCoerceable_$ => member(sym,vl) or canCoerce(source,S) + + len := #vl + -1 ^= (n:= position(sym,vl)) => + LIST [LIST2VEC [(n=i => 1; 0) for i in 0..len-1], + :getConstantFromDomain('(One),S)] + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [[Zeros len,:objValUnwrap u]] + +Var2Mp(u,source,target is [mp,vl,S]) == + sym := CADR source + u = '_$fromCoerceable_$ => member(sym,vl) or canCoerce(source,S) + (n:= position1(u,vl)) ^= 0 => + [1,n,[1,0,:getConstantFromDomain('(One),S)]] + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [0,:objValUnwrap u] + +Var2NDmp(u,source,target is [ndmp,vl,S]) == + sym := CADR source + u = '_$fromCoerceable_$ => member(sym,vl) or canCoerce(source,S) + + len:= #vl + -1^=(n:= position(u,vl)) => + LIST [LIST2VEC [(n=i => 1; 0) for i in 0..len-1], + :getConstantFromDomain('(One),S)] + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [[Zeros len,:objValUnwrap(u)]] + +Var2P(u,source,target is [poly,S]) == + sym := CADR source + u = '_$fromCoerceable_$ => true + + -- first try to get it into an underdomain + if (S ^= $Integer) then + u' := coerceInt(objNewWrap(u,source),S) + if u' then return [0,:objValUnwrap(u')] + -- if that failed, return it as a polynomial variable + [1,sym,[1,0,:getConstantFromDomain('(One),S)]] + +Var2QF(u,source,target is [qf,S]) == + u = '_$fromCoerceable_$ => canCoerce(source,S) + + S = $Integer => coercionFailure() + sym := CADR source + (u' := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [objValUnwrap u',:getConstantFromDomain('(One),S)] + +Var2FS(u,source,target is [fs,S]) == + u = '_$fromCoerceable_$ => true + (v := coerceInt(objNewWrap(u,source),['Polynomial,S])) or + coercionFailure() + (v := coerceInt(v,target)) or coercionFailure() + objValUnwrap v + +Var2Up(u,source,target is [up,x,S]) == + sym := CADR source + u = '_$fromCoerceable_$ => (sym = x) or canCoerce(source,S) + + x=sym => [[1,:getConstantFromDomain('(One),S)]] + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [[0,:objValUnwrap u]] + +Var2SUP(u,source,target is [sup,S]) == + sym := CADR source + u = '_$fromCoerceable_$ => (sym = "?") or canCoerce(source,S) + + sym = "?" => [[1,:getConstantFromDomain('(One),S)]] + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + [[0,:objValUnwrap u]] + +Var2UpS(u,source,target is [ups,x,S]) == + sym := CADR source + u = '_$fromCoerceable_$ => (sym = x) or canCoerce(source,S) + + mid := ['UnivariatePolynomial,x,S] + x = sym => + u := Var2Up(u,source,mid) + (u := coerceInt(objNewWrap(u,mid),target)) or coercionFailure() + objValUnwrap u + (u := coerceInt(objNewWrap(u,source),S)) or coercionFailure() + (u := coerceInt(u,target)) or coercionFailure() + objValUnwrap u + +Var2OtherPS(u,source,target is [.,x,S]) == + sym := CADR source + mid := ['UnivariatePowerSeries,x,S] + u = '_$fromCoerceable_$ => + (sym = x) or (canCoerce(source,mid) and canCoerce(mid,target)) + u := Var2UpS(u,source,mid) + (u := coerceInt(objNewWrap(u,mid),target)) or coercionFailure() + objValUnwrap u + +--% Vector + +V2M(u,[.,D],[.,R]) == + u = '_$fromCoerceable_$ => + D is ['Vector,:.] => nil -- don't have data + canCoerce(D,R) + -- first see if we are coercing a vector of vectors + D is ['Vector,E] and + isRectangularVector(u,MAXINDEX u,MAXINDEX u.0) => + LIST2VEC + [LIST2VEC [objValUnwrap(coerceInt(objNewWrap(x.j,E),R)) + for j in 0..MAXINDEX(x:=u.i)] for i in 0..MAXINDEX u] + -- if not, try making it into a 1 by n matrix + coercionFailure() +--LIST2VEC [LIST2VEC [objValUnwrap(coerceInt(objNewWrap(u.i,D),R)) +-- for i in 0..MAXINDEX(u)]] + +V2Rm(u,[.,D],[.,n,m,R]) == + u = '_$fromCoerceable_$ => nil + D is [.,E,:.] and isRectangularVector(u,n-1,m-1) => + LIST2VEC + [LIST2VEC [objValUnwrap(coerceInt(objNewWrap(x.j,E),R)) + for j in 0..MAXINDEX(x:=u.i)] for i in 0..MAXINDEX u] + coercionFailure() + +V2Sm(u,[.,D],[.,n,R]) == + u = '_$fromCoerceable_$ => nil + D is [.,E,:.] and isRectangularVector(u,n-1,n-1) => + LIST2VEC + [LIST2VEC [objValUnwrap(coerceInt(objNewWrap(x.j,E),R)) + for j in 0..MAXINDEX(x:=u.i)] for i in 0..MAXINDEX u] + coercionFailure() + +isRectangularVector(x,p,q) == + MAXINDEX x = p => + and/[q=MAXINDEX x.i for i in 0..p] + +-- Polynomial and Expression to Univariate series types + +P2Uts(u, source, target) == + P2Us(u,source, target, 'taylor) + +P2Uls(u, source, target) == + P2Us(u,source, target, 'laurent) + +P2Upxs(u, source, target) == + P2Us(u,source, target, 'puiseux) + +P2Us(u, source is [.,S], target is [.,T,var,cen], type) == + u = '_$fromCoerceable_$ => + -- might be able to say yes + canCoerce(S,T) + T isnt ['Expression, :.] => coercionFailure() + if S ^= '(Float) then S := $Integer + obj := objNewWrap(u, source) + E := ['Expression, S] + newU := coerceInt(obj, E) + null newU => coercionFailure() + EQtype := ['Equation, E] + eqfun := getFunctionFromDomain('_=, EQtype, [E,E]) + varE := coerceInt(objNewWrap(var, '(Symbol)), E) + null varE => coercionFailure() + cenE := coerceInt(objNewWrap(cen, T), E) + null cenE => coercionFailure() + eq := SPADCALL(objValUnwrap(varE), objValUnwrap(cenE), eqfun) + package := ['ExpressionToUnivariatePowerSeries, S, E] + func := getFunctionFromDomain(type, package, [E, EQtype]) + newObj := SPADCALL(objValUnwrap(newU), eq, func) + newType := CAR newObj + newVal := CDR newObj + newType = target => newVal + finalObj := coerceInt(objNewWrap(newVal, newType), target) + null finalObj => coercionFailure() + objValUnwrap finalObj + + +--% General Coercion Commutation Functions + +-- general commutation functions are called with 5 values +-- u object of type source +-- source type of u +-- S underdomain of source +-- target coercion target type +-- T underdomain of T +-- Because of checking, can always assume S and T have underdomains. + +--% Complex + +commuteComplex(u,source,S,target,T) == + u = '_$fromCoerceable_$ => + canCoerce(S,target) and canCoerce(T,target) + [real,:imag] := u + (real := coerceInt(objNewWrap(real,S),target)) or coercionFailure() + (imag := coerceInt(objNewWrap(imag,S),target)) or coercionFailure() + T' := underDomainOf T + i := [domainZero(T'), + :domainOne(T')] + (i := coerceInt(objNewWrap(i,T),target)) or coercionFailure() + f := getFunctionFromDomain("*",target,[target,target]) + i := SPADCALL(objValUnwrap i, objValUnwrap imag, f) + f := getFunctionFromDomain("+",target,[target,target]) + SPADCALL(objValUnwrap real,i,f) + +--% Quaternion + +commuteQuaternion(u,source,S,target,T) == + u = '_$fromCoerceable_$ => + canCoerce(S,target) and canCoerce(T,target) + c := [objValUnwrap(coerceInt(objNewWrap(x,S),target) + or coercionFailure()) for x in VEC2LIST u] + q := '(Quaternion (Integer)) + e := [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]] + e := [(coerceInt(objNewWrap(LIST2VEC x,q),T) + or coercionFailure()) for x in e] + e :=[objValUnwrap(coerceInt(x,target) or coercionFailure()) for x in e] + u' := domainZero(target) + mult := getFunctionFromDomain("*",target,[target,target]) + plus := getFunctionFromDomain("+",target,[target,target]) + for x in c for y in e repeat + u' := SPADCALL(u',SPADCALL(x,y,mult),plus) + u' + +--% Fraction + +commuteFraction(u,source,S,target,T) == + u = '_$fromCoerceable_$ => + ofCategory(target,'(Field)) => canCoerce(S,target) + canCoerce(S,T) and canCoerce(T,target) + [n,:d] := u + ofCategory(target,'(Field)) => + -- see if denominator can go over to target + (d' := coerceInt(objNewWrap(d,S),target)) or coercionFailure() + -- if so, try to invert it + inv := getFunctionFromDomain('inv,target,[target]) + d' := SPADCALL(objValUnwrap d',inv) + -- now coerce to target + (n' := coerceInt(objNewWrap(n,S),target)) or coercionFailure() + multfunc := getFunctionFromDomain("*",target,[target,target]) + SPADCALL(d',objValUnwrap n',multfunc) + -- see if denominator can go over to QF part of target + (d' := coerceInt(objNewWrap(d,S),T)) or coercionFailure() + -- if so, try to invert it + inv := getFunctionFromDomain('inv,T,[T]) + d' := SPADCALL(objValUnwrap d',inv) + -- now coerce to target + (d' := coerceInt(objNewWrap(d',T),target)) or coercionFailure() + (n' := coerceInt(objNewWrap(n,S),target)) or coercionFailure() + multfunc := getFunctionFromDomain("*",target,[target,target]) + SPADCALL(objValUnwrap d',objValUnwrap n',multfunc) + +--% SquareMatrix + +commuteSquareMatrix(u,source,S,target,T) == + u = '_$fromCoerceable_$ => + canCoerce(S,target) and canCoerce(T,target) + -- commuting matrices of matrices should be a no-op + S is ['SquareMatrix,:.] => + source=target => u + coercionFailure() + u' := domainZero(target) + plusfunc := getFunctionFromDomain("+",target,[target,target]) + multfunc := getFunctionFromDomain("*",target,[target,target]) + zero := domainZero(S) + [sm,n,:.] := source + S' := [sm,n,$Integer] + for i in 0..(n-1) repeat + for j in 0..(n-1) repeat + (e := u.i.j) = zero => 'iterate + (e' := coerceInt(objNewWrap(e,S),target)) or coercionFailure() + (Eij := coerceInt(objNewWrap(makeEijSquareMatrix(i,j,n),S'),T)) or + coercionFailure() + (Eij := coerceInt(Eij,target)) or coercionFailure() + e' := SPADCALL(objValUnwrap(e'),objValUnwrap(Eij),multfunc) + u' := SPADCALL(e',u',plusfunc) + u' + +makeEijSquareMatrix(i, j, dim) == + -- assume using 0 based scale, makes a dim by dim matrix with a + -- 1 in the i,j position, zeros elsewhere + LIST2VEC [LIST2VEC [((i=r) and (j=c) => 1; 0) + for c in 0..(dim-1)] for r in 0..(dim-1)] + +--% Univariate Polynomial and Sparse Univariate Polynomial + +commuteUnivariatePolynomial(u,source,S,target,T) == + commuteSparseUnivariatePolynomial(u,source,S,target,T) + +commuteSparseUnivariatePolynomial(u,source,S,target,T) == + u = '_$fromCoerceable_$ => + canCoerce(S,target) and canCoerce(T,target) + + u' := domainZero(target) + null u => u' + + T' := underDomainOf T + one := domainOne(T') + monom := getFunctionFromDomain('monomial,T,[T',$NonNegativeInteger]) + plus := getFunctionFromDomain("+",target,[target,target]) + times := getFunctionFromDomain("*",target,[target,target]) + + for [e,:c] in u repeat + (c := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + m := SPADCALL(one,e,monom) + (m := coerceInt(objNewWrap(m,T),target)) or coercionFailure() + c := objValUnwrap c + m := objValUnwrap m + u' := SPADCALL(u',SPADCALL(c,m,times),plus) + u' + +--% Multivariate Polynomials + +commutePolynomial(u,source,S,target,T) == + commuteMPolyCat(u,source,S,target,T) + +commuteMultivariatePolynomial(u,source,S,target,T) == + commuteMPolyCat(u,source,S,target,T) + +commuteDistributedMultivariatePolynomial(u,source,S,target,T) == + commuteMPolyCat(u,source,S,target,T) + +commuteNewDistributedMultivariatePolynomial(u,source,S,target,T) == + commuteMPolyCat(u,source,S,target,T) + +commuteMPolyCat(u,source,S,target,T) == + u = '_$fromCoerceable_$ => canCoerce(S,target) + -- check constant case + isconstfun := getFunctionFromDomain("ground?",source,[source]) + SPADCALL(u,isconstfun) => + constfun := getFunctionFromDomain("ground",source,[source]) + c := SPADCALL(u,constfun) + (u' := coerceInt(objNewWrap(c,S),target)) or coercionFailure() + objValUnwrap(u') + + lmfun := getFunctionFromDomain('leadingMonomial,source,[source]) + lm := SPADCALL(u,lmfun) -- has type source, is leading monom + + lcfun := getFunctionFromDomain('leadingCoefficient,source,[source]) + lc := SPADCALL(lm,lcfun) -- has type S, is leading coef + (lc' := coerceInt(objNewWrap(lc,S),target)) or coercionFailure() + + pmfun := getFunctionFromDomain('primitiveMonomials,source,[source]) + lm := first SPADCALL(lm,pmfun) -- now we have removed the leading coef + (lm' := coerceInt(objNewWrap(lm,source),T)) or coercionFailure() + (lm' := coerceInt(lm',target)) or coercionFailure() + + rdfun := getFunctionFromDomain('reductum,source,[source]) + rd := SPADCALL(u,rdfun) -- has type source, is reductum + (rd' := coerceInt(objNewWrap(rd,source),target)) or coercionFailure() + + lc' := objValUnwrap lc' + lm' := objValUnwrap lm' + rd' := objValUnwrap rd' + + plusfun := getFunctionFromDomain("+",target,[target,target]) + multfun := getFunctionFromDomain("*",target,[target,target]) + SPADCALL(SPADCALL(lc',lm',multfun),rd',plusfun) + +------------------------------------------------------------------------ +-- Format for alist member is: domain coercionType function +-- here coercionType can be one of 'total, 'partial or 'indeterm +-- (indeterminant - cannot tell in a simple way). +-- +-- In terms of canCoerceFrom, 'total implies true, 'partial implies +-- false (just cannot tell without actual data) and 'indeterm means +-- to call the function with the data = "$fromCoerceable$" for a +-- response of true or false. +------------------------------------------------------------------------ +-- There are no entries here for RationalNumber or RationalFunction. +-- These should have been changed to QF I and QF P, respectively, by +-- a function like deconstructTower. RSS 8-1-85 +------------------------------------------------------------------------ + +SETANDFILEQ($CoerceTable, '( _ + (Complex . ( _ + (Expression indeterm Complex2Expr) _ + (Factored indeterm Complex2FR) _ + (Integer partial Complex2underDomain) _ + (PrimeField partial Complex2underDomain) _ + ))_ + (DirectProduct . ( _ + (DirectProduct partial DP2DP) _ + )) _ + (DistributedMultivariatePolynomial . ( _ + (DistributedMultivariatePolynomial indeterm Dmp2Dmp) _ + (Expression indeterm Dmp2Expr) _ + (Factored indeterm Mp2FR) _ + (HomogeneousDistributedMultivariatePolynomial indeterm Dmp2NDmp) _ + (MultivariatePolynomial indeterm Dmp2Mp) _ + (Polynomial indeterm Dmp2P) _ + (UnivariatePolynomial indeterm Dmp2Up) _ + ))_ + (Expression . ( + (Complex partial Expr2Complex) _ + (DistributedMultivariatePolynomial indeterm Expr2Dmp) _ + (HomogeneousDistributedMultivariatePolynomial indeterm Expr2Dmp) _ + (MultivariatePolynomial indeterm Expr2Mp) _ + (UnivariateLaurentSeries indeterm P2Uls) _ + (UnivariatePolynomial indeterm Expr2Up) _ + (UnivariatePuiseuxSeries indeterm P2Upxs) _ + (UnivariateTaylorSeries indeterm P2Uts) _ + )) _ + + (Kernel . ( _ + (Kernel indeterm Ker2Ker) _ + (Expression indeterm Ker2Expr) _ + )) _ + + (Factored . ( _ + (Factored indeterm Factored2Factored) _ + ))_ + (Fraction . ( _ + (DistributedMultivariatePolynomial partial Qf2domain) _ + (ElementaryFunction indeterm Qf2EF) _ + (Expression indeterm Qf2EF) _ + (Fraction indeterm Qf2Qf) _ + (HomogeneousDistributedMultivariatePolynomial partial Qf2domain) _ + (Integer partial Qf2domain) _ + (MultivariatePolynomial partial Qf2domain) _ + (Polynomial partial Qf2domain) _ + (PrimeField indeterm Qf2PF) _ + (UnivariateLaurentSeries indeterm P2Uls) _ + (UnivariatePolynomial partial Qf2domain) _ + (UnivariatePuiseuxSeries indeterm P2Upxs) _ + (UnivariateTaylorSeries indeterm P2Uts) _ + ))_ + (Int . ( _ + (Expression total ncI2E) _ + (Integer total ncI2I) _ + ))_ + (Baby . ( _ + (Expression total ncI2E) _ + (Integer total ncI2I) _ + ))_ + (Integer . ( _ + (Baby total I2ncI) _ + (EvenInteger partial I2EI) _ + (Int total I2ncI) _ + (NonNegativeInteger partial I2NNI) _ + (OddInteger partial I2OI) _ + (PositiveInteger partial I2PI) _ + ))_ + (List . ( _ + (DirectProduct indeterm L2DP) _ + (Matrix partial L2M) _ + (Record partial L2Record) _ + (RectangularMatrix partial L2Rm) _ + (Set indeterm L2Set) _ + (SquareMatrix partial L2Sm) _ + (Stream indeterm Agg2Agg) _ + (Tuple indeterm L2Tuple) _ + (Vector indeterm L2V) _ + ))_ + )) + +SETANDFILEQ($CoerceTable,NCONC($CoerceTable,'( _ + (Matrix . ( _ + (List indeterm M2L) _ + (RectangularMatrix partial M2Rm) _ + (SquareMatrix partial M2Sm) _ + (Vector indeterm M2L) _ + ))_ + (MultivariatePolynomial . ( _ + (DistributedMultivariatePolynomial indeterm Mp2Dmp) _ + (Expression indeterm Mp2Expr) _ + (Factored indeterm Mp2FR) _ + (HomogeneousDistributedMultivariatePolynomial indeterm domain2NDmp) _ + (MultivariatePolynomial indeterm Mp2Mp) _ + (Polynomial indeterm Mp2P) _ + (UnivariatePolynomial indeterm Mp2Up) _ + ))_ + (HomogeneousDirectProduct . ( _ + (HomogeneousDirectProduct indeterm DP2DP) _ + ))_ + (HomogeneousDistributedMultivariatePolynomial . ( _ + (Complex indeterm NDmp2domain) _ + (DistributedMultivariatePolynomial indeterm NDmp2domain) _ + (Expression indeterm Dmp2Expr) _ + (Factored indeterm Mp2FR) _ + (Fraction indeterm NDmp2domain) _ + (HomogeneousDistributedMultivariatePolynomial indeterm NDmp2NDmp) _ + (MultivariatePolynomial indeterm NDmp2domain) _ + (Polynomial indeterm NDmp2domain) _ + (Quaternion indeterm NDmp2domain) _ + (UnivariatePolynomial indeterm NDmp2domain) _ + ))_ + (OrderedVariableList . ( _ + (DistributedMultivariatePolynomial indeterm OV2poly) _ + (HomogeneousDistributedMultivariatePolynomial indeterm OV2poly) _ + (MultivariatePolynomial indeterm OV2poly) _ + (OrderedVariableList indeterm OV2OV) _ + (Polynomial total OV2P) _ + (Symbol total OV2Sy) _ + (UnivariatePolynomial indeterm OV2poly) _ + ))_ + (Polynomial . ( _ + (DistributedMultivariatePolynomial indeterm P2Dmp) _ + (Expression indeterm P2Expr) _ + (Factored indeterm P2FR) _ + (HomogeneousDistributedMultivariatePolynomial partial domain2NDmp) _ + (MultivariatePolynomial indeterm P2Mp) _ + (UnivariateLaurentSeries indeterm P2Uls) _ + (UnivariatePolynomial indeterm P2Up) _ + (UnivariatePuiseuxSeries indeterm P2Upxs) _ + (UnivariateTaylorSeries indeterm P2Uts) _ + ))_ + (Set . ( _ + (List indeterm Set2L) _ + (Vector indeterm Agg2L2Agg) _ + ))_ + (RectangularMatrix . ( _ + (List indeterm Rm2L) _ + (Matrix indeterm Rm2M) _ + (SquareMatrix indeterm Rm2Sm) _ + (Vector indeterm Rm2V) _ + ))_ + (SparseUnivariatePolynomial . ( _ + (UnivariatePolynomial indeterm SUP2Up) _ + ))_ + (SquareMatrix . ( + -- ones for polys needed for M[2] P I -> P[x,y] M[2] P I, say + (DistributedMultivariatePolynomial partial Sm2PolyType) _ + (HomogeneousDistributedMultivariatePolynomial partial Sm2PolyType) _ + (List indeterm Sm2L) _ + (Matrix indeterm Sm2M) _ + (MultivariatePolynomial partial Sm2PolyType) _ + (RectangularMatrix indeterm Sm2Rm) _ + (UnivariatePolynomial indeterm Sm2PolyType) _ + (Vector indeterm Sm2V) _ + ) ) _ + (Symbol . ( _ + (DistributedMultivariatePolynomial indeterm Sy2Dmp) _ + (HomogeneousDistributedMultivariatePolynomial indeterm Sy2NDmp) _ + (MultivariatePolynomial indeterm Sy2Mp) _ + (OrderedVariableList partial Sy2OV) _ + (Polynomial total Sy2P) _ + (UnivariatePolynomial indeterm Sy2Up) _ + (Variable indeterm Sy2Var) _ + ) ) _ + (UnivariatePolynomial . ( _ + (DistributedMultivariatePolynomial indeterm Up2Dmp) _ + (Expression indeterm Up2Expr) _ + (Factored indeterm Up2FR) _ + (HomogeneousDistributedMultivariatePolynomial indeterm domain2NDmp) _ + (MultivariatePolynomial indeterm Up2Mp) _ + (Polynomial indeterm Up2P) _ + (SparseUnivariatePolynomial indeterm Up2SUP) _ + (UnivariatePolynomial indeterm Up2Up) _ + ) ) _ + (Variable . ( _ + (AlgebraicFunction total Var2FS) _ + (ContinuedFractionPowerSeries indeterm Var2OtherPS) _ + (DistributedMultivariatePolynomial indeterm Var2Dmp) _ + (ElementaryFunction total Var2FS) _ + (Fraction indeterm Var2QF) _ + (FunctionalExpression total Var2FS) _ + (GeneralDistributedMultivariatePolynomial indeterm Var2Gdmp) _ + (HomogeneousDistributedMultivariatePolynomial indeterm Var2NDmp) _ + (LiouvillianFunction total Var2FS) _ + (MultivariatePolynomial indeterm Var2Mp) _ + (OrderedVariableList indeterm Var2OV) _ + (Polynomial total Var2P) _ + (SparseUnivariatePolynomial indeterm Var2SUP) _ + (Symbol total Identity) _ + (UnivariatePolynomial indeterm Var2Up) _ + (UnivariatePowerSeries indeterm Var2UpS) _ + ) ) _ + (Vector . ( _ + (DirectProduct indeterm V2DP) _ + (List indeterm V2L) _ + (Matrix indeterm V2M) _ + (RectangularMatrix indeterm V2Rm) _ + (Set indeterm Agg2L2Agg) _ + (SquareMatrix indeterm V2Sm) _ + (Stream indeterm Agg2Agg) _ + ) ) _ + ) ) ) + +-- this list is too long for the parser, so it has to be split into parts +-- specifies the commute functions +-- commute stands for partial commute function +--SETANDFILEQ($CommuteTable, '( _ +-- (DistributedMultivariatePolynomial . ( _ +-- (DistributedMultivariatePolynomial commute commuteMultPol) _ +-- (Complex commute commuteMultPol) _ +-- (MultivariatePolynomial commute commuteMultPol) _ +-- (NewDistributedMultivariatePolynomial commute commuteMultPol) _ +-- (Polynomial commute commuteMultPol) _ +-- (Quaternion commute commuteMultPol) _ +-- (Fraction commute commuteMultPol) _ +-- (SquareMatrix commute commuteMultPol) _ +-- (UnivariatePolynomial commute commuteMultPol) _ +-- )) _ +-- (Complex . ( _ +-- (DistributedMultivariatePolynomial commute commuteG2) _ +-- (MultivariatePolynomial commute commuteG2) _ +-- (NewDistributedMultivariatePolynomial commute commuteG2) _ +-- (Polynomial commute commuteG1) _ +-- (Fraction commute commuteG1) _ +-- (SquareMatrix commute commuteG2) _ +-- (UnivariatePolynomial commute commuteG2) _ +-- )) _ +-- (MultivariatePolynomial . ( _ +-- (DistributedMultivariatePolynomial commute commuteMultPol) _ +-- (Complex commute commuteMultPol) _ +-- (MultivariatePolynomial commute commuteMultPol) _ +-- (NewDistributedMultivariatePolynomial commute commuteMultPol) _ +-- (Polynomial commute commuteMultPol) _ +-- (Quaternion commute commuteMultPol) _ +-- (Fraction commute commuteMultPol) _ +-- (SquareMatrix commute commuteMultPol) _ +-- (UnivariatePolynomial commute commuteMultPol) _ +-- )) _ +-- (Polynomial . ( _ +-- (DistributedMultivariatePolynomial commute commuteMultPol) _ +-- (Complex commute commuteMultPol) _ +-- (MultivariatePolynomial commute commuteMultPol) _ +-- (NewDistributedMultivariatePolynomial commute commuteMultPol) _ +-- (Polynomial commute commuteMultPol) _ +-- (Quaternion commute commuteMultPol) _ +-- (Fraction commute commuteMultPol) _ +-- (SquareMatrix commute commuteMultPol) _ +-- (UnivariatePolynomial commute commuteMultPol) _ +-- )) _ +-- (Quaternion . ( _ +-- (DistributedMultivariatePolynomial commute commuteQuat2) _ +-- (MultivariatePolynomial commute commuteQuat2) _ +-- (NewDistributedMultivariatePolynomial commute commuteQuat2) _ +-- (Polynomial commute commuteQuat1) _ +-- (SquareMatrix commute commuteQuat2) _ +-- (UnivariatePolynomial commute commuteQuat2) _ +-- )) _ +-- (SquareMatrix . ( _ +-- (DistributedMultivariatePolynomial commute commuteSm2) _ +-- (Complex commute commuteSm1) _ +-- (MultivariatePolynomial commute commuteSm2) _ +-- (NewDistributedMultivariatePolynomial commute commuteSm2) _ +-- (Polynomial commute commuteSm1) _ +-- (Quaternion commute commuteSm1) _ +-- (SparseUnivariatePolynomial commute commuteSm1) _ +-- (UnivariatePolynomial commute commuteSm2) _ +-- )) _ +-- (UnivariatePolynomial . ( _ +-- (DistributedMultivariatePolynomial commute commuteUp2) _ +-- (Complex commute commuteUp1) _ +-- (MultivariatePolynomial commute commuteUp2) _ +-- (NewDistributedMultivariatePolynomial commute commuteUp2) _ +-- (Polynomial commute commuteUp1) _ +-- (Quaternion commute commuteUp1) _ +-- (Fraction commute commuteUp1) _ +-- (SparseUnivariatePolynomial commute commuteUp1) _ +-- (SquareMatrix commute commuteUp2) _ +-- (UnivariatePolynomial commute commuteUp2) _ +-- )) _ +-- )) + +SETANDFILEQ($CommuteTable, '( _ + (Complex . ( _ + (DistributedMultivariatePolynomial commute commuteG2) _ + (MultivariatePolynomial commute commuteG2) _ + (HomogeneousDistributedMultivariatePolynomial commute commuteG2) _ + (Polynomial commute commuteG1) _ + (Fraction commute commuteG1) _ + (SquareMatrix commute commuteG2) _ + (UnivariatePolynomial commute commuteG2) _ + )) _ + (Polynomial . ( _ + (Complex commute commuteMultPol) _ + (MultivariatePolynomial commute commuteMultPol) _ + (HomogeneousDistributedMultivariatePolynomial commute commuteMultPol)_ + (Polynomial commute commuteMultPol) _ + (Quaternion commute commuteMultPol) _ + (Fraction commute commuteMultPol) _ + (SquareMatrix commute commuteMultPol) _ + (UnivariatePolynomial commute commuteMultPol) _ + )) _ + (SquareMatrix . ( _ + (DistributedMultivariatePolynomial commute commuteSm2) _ + (Complex commute commuteSm1) _ + (MultivariatePolynomial commute commuteSm2) _ + (HomogeneousDistributedMultivariatePolynomial commute commuteSm2)_ + (Polynomial commute commuteSm1) _ + (Quaternion commute commuteSm1) _ + (SparseUnivariatePolynomial commute commuteSm1) _ + (UnivariatePolynomial commute commuteSm2) _ + )) _ + )) + +@ +\eject +\begin{thebibliography}{99} +\bibitem{1} nothing +\end{thebibliography} +\end{document} |