1 /* ---------------------------------------------------------------- */
2 /* SARAG - Sign Determination */
3 /* by Fabrizio Caruso modified by Alexandre Le Meur and Marie-Françoise Roy */
6 /* ----------------------------------------- */
7 /* Backward compatibility issues since 5.9.2 */
9 /* Auxiliary floor function */
16 /* Auxiliary ceiling function */
18 if x=float(fix(x)) then
23 /* Uncenter the modulo representation */
24 /* It works for both odd and even positive integer m */
32 /* ----------------------------------------------------------- */
33 /* Realization of sign conditions */
43 /* Auxiliary block matrix computation */
44 /* defined for blocks of same size */
46 /* nRows,nCols : number of rows/cols of the result */
47 /* nBlockRows, nBlockCols : number of rows/cols in the blocks */
48 /* inBlockRowIndex, inBlockColIndex : row/col in the block */
50 block([nRows,rCols,nBlockRows,i,j,rowRes,res,
51 blockRow,blockCol,inBlockRows, inBlockCols,
52 inBlockRowIndex,inBlockColIndex, nCols],
53 nBlockRows : length(descr),
54 nBlockCols : length(first(descr)),
55 inBlockRows : length(first(first(descr))),
56 nRows : nBlockRows*inBlockRows,
57 inBlockCols : length(first(first(first(descr)))),
58 nCols : nBlockCols*inBlockCols,
61 for i : 1 thru nRows do
64 for j : 1 thru nCols do
66 blockRow : ceilFract(i,inBlockRows),
67 blockCol : ceilFract(j,inBlockCols),
69 if inBlockRows = 1 then
74 inBlockRowIndex : mod(i-1,inBlockRows)+1,
76 /* before 5.9.2 but also forwards-compatible */
77 inBlockRowIndex : comp_uncenter(mod(i-1,inBlockRows),inBlockRows)+1,
78 if inBlockCols = 1 then
83 inBlockColIndex : mod(j-1,inBlockCols)+1,
85 /* before 5.9.2 but also forwards-compatible */
86 inBlockColIndex : comp_uncenter(mod(j-1,inBlockCols),inBlockRows)+1,
88 descr[blockRow][blockCol][inBlockRowIndex][inBlockColIndex],
91 res : endcons(rowRes,res)
98 /* Matrix tensor product */
99 /* Notation as in Notation 2.63 */
100 tensorProduct(m,mPrime) :=
101 block([i,j,nBlockRows,nBlockCols,bm],
102 nBlockRows : length(mPrime),
103 nBlockCols : length(first(mPrime)),
104 bm : makelist(makelist(mPrime[i][j]*m,j,1,nBlockCols),i,1,nBlockRows),
105 return(blockMatrix(bm))
110 /* Matrix of signs for the case Sign(P,Z) = {-1,1} */
111 matrixOfSignsForOnePolyNonZero :
114 /* Matrix of signs for the case Sign(P,Z) = {0,1} */
115 matrixOfSignsForOnePolyNonNegative :
118 /* Matrix of signs for the case Sign(P,Z) = {0,-1} */
119 matrixOfSignsForOnePolyNonPositive :
123 /* Matrix of signs for one polynomial */
124 matrixOfSignsForOnePolyAllSigns :
125 [[1,1,1],[0,1,-1],[0,1,1]];
127 /* Matrix of signs of P^A */
128 naiveMatrixOfSigns(nPols) :=
130 matrixOfSignsForOnePolyAllSigns
132 tensorProduct(naiveMatrixOfSigns(nPols-1),
133 matrixOfSignsForOnePolyAllSigns);
137 /* It produces the product coefficient terms */
138 /* i.e. the terms of the coefficients of the products */
139 composeVector(lhs,rhs) :=
140 block([lhsLen,rhsLen,i,j,prodRes,listRes],
141 lhsLen : length(lhs),
142 rhsLen : length(rhs),
144 for i : 1 thru rhsLen do
146 for j : 1 thru lhsLen do
148 prodRes : lhs[j]*rhs[i],
149 listRes : endcons(prodRes,listRes)
157 /* Auxiliary function */
158 tarskiQueryComposition(polList) :=
159 block([i,j,res,prodRes,card],
160 if length(polList) = 1 then
161 [1,polList[1],polList[1]^2]
163 return(composeVector([1,first(polList),first(polList)^2],
164 tarskiQueryComposition(rest(polList)))
169 /* Tarski Query Vector */
170 /* In the book: SQ(P^a,Z) */
171 /* tarskiQueryAlg can be for instance : sSubResTarskiQuery(Q,P,var) */
172 naiveTarskiQueryVector(polList,ptSet,tarskiQueryAlg,var) :=
175 sQConv : tarskiQueryComposition(reverse(polList)),
177 res : map(lambda([y],tarskiQueryAlg(expand(y),expand(ptSet),var)),
185 /* Naive Sign Determination */
187 naiveSignDetermination(polList,ptSet,sqAlg,var) :=
188 naiveSignConv(solveSys(naiveMatrixOfSigns(length(polList)),
189 naiveTarskiQueryVector(polList,ptSet,sqAlg,var),LINEAR_SOLVER));
193 collectSimilarAux(item,checkList,newCheckList,res) :=
197 if rest(item)=rest(first(checkList)) then
198 collectSimilarAux(item,rest(checkList),
199 newCheckList,endcons(first(checkList),res))
201 collectSimilarAux(item,rest(checkList),
202 endcons(first(checkList),newCheckList),res);
204 collectSimilar(item,checkList) :=
205 collectSimilarAux(item,checkList,[],[]);
207 extractExt(extSignDet) :=
208 block([signList,listLen,item,simRes,simList,ext2,ext3],
209 signList : extSignDet,
212 while not(signList=[]) do
215 listLen : length(signList),
216 item : first(signList),
217 signList : rest(signList),
218 simRes : collectSimilar(item,signList),
220 signList : simRes[2],
222 if length(simList)>=1 then
223 ext2 : endcons(rest(item),ext2),
224 if length(simList)=2 then
225 ext3 : endcons(rest(item),ext3)
231 signs2exps(signCondList) := signCondListConv(signCondList);
233 exps2signs(exps) := signCondListBackConv(exps);
235 signConv(singleSign) :=
236 if singleSign = -1 then
241 signCondConv(signList) :=
242 map(signConv,signList);
244 signCondListConv(signCondList) :=
245 map(signCondConv,signCondList);
247 signBackConv(singleSign) :=
248 if singleSign = 2 then
253 signCondBackConv(signList) :=
254 map(signBackConv,signList);
256 signCondListBackConv(signCondList) :=
257 map(signCondBackConv,signCondList);
260 if base=0 and expo = 0 then
265 signAt(signCond,adaExp) :=
266 product(genExp(signCond[i],adaExp[i]),i,1,length(signCond));
268 matrixOfSigns(adaExpList,signCondList) :=
269 block([i,j,nSigns,nExp,newRow,res],
270 nSigns : length(signCondList),
271 nExp : length(adaExpList),
272 signCondList : signCondListBackConv(
273 sort(signCondListConv(signCondList))),
274 adaExpList : sort(adaExpList),
277 for i : 1 thru nExp do
279 newRow : makelist(signAt(signCondList[j],adaExpList[i]),j,1,nSigns),
281 res : endcons(newRow,res)
286 tarskiQueryVector(adaExpList,polList,var,sqAlg,ptSet) :=
288 adaExpList : sort(adaExpList),
290 map(lambda([y],sqAlg(expand(y),expand(ptSet),var)),
292 product(polList[i]^adaExpList[j][i],
293 i,1,length(polList)),j,1,length(adaExpList))))
296 extendByOneExponent(newExp,oldExpList) :=
297 if oldExpList = [] then
300 sort(makelist(cons(newExp,oldExpList[i]),i,1,length(oldExpList)));
303 extendExponents(newExpList,oldExpList) :=
306 if length(newExpList) = 0 then
308 if length(oldExpList) = 0 then
309 return(makelist([newExpList[i]],i,1,length(newExpList))),
310 for i : 1 thru length(newExpList) do
311 for j : 1 thru length(oldExpList) do
312 res : cons(cons(newExpList[i],oldExpList[j]),res),
317 extendSigns(newSgnList,oldSgnList) :=
318 exps2signs(extendExponents(signCondConv(newSgnList),signs2exps(oldSgnList)));
321 extendAdaptedFamily(extSignDet,ada) :=
322 block([ext2,ext3,r1,r2,r3,m2,m3,ada2,ada3,extRes,trN,i,j,indList,trM],
323 if extSignDet=[] then
325 if length(extSignDet[1])=1 then
326 if length(extSignDet)= 1 then
329 if length(extSignDet)=2 then
332 return([[0],[1],[2]]),
333 extRes : extractExt(extSignDet),
341 m2 : matrixOfSigns(ada,ext2),
346 while length(indList) < r2 /* and i<= length(trM[1]) */ do
348 if not(member(i-1,trM[3])) then
349 indList : endcons(i,indList),
353 ada2 : makelist(ada[indList[j]],j,1,length(indList)), /* it was r2 before */
354 m3 : matrixOfSigns(ada,ext3),
359 while length(indList)<r3 /* and i<=length(trM[1]) */ do /* it was r2 before */
361 if not(member(i-1,trM[3])) then
362 indList : endcons(i,indList),
366 ada3 : makelist(ada[indList[j]],j,1,length(indList)), /* it was r3 before */
369 return(sort(append(extendByOneExponent(0,ada),
370 extendByOneExponent(1,ada2),
371 extendByOneExponent(2,ada3))))
376 smartSignDetermination(polList,ptSet,sqAlg,var) :=
377 block([sqOne,sqPexp1,sqPexp2,cVect,i,j,
378 nPols,adaOnePoly,sgnsOnePoly,sgns,oldSgns,allSgns,
379 nSigns,solOne,mtx,mtxOnePoly,ada,
380 extMtx,extSysSol,sqVect,solExt,allSigns],
382 sqOne : sqAlg(1,ptSet,var),
385 nPols : length(polList),
387 sgns : [], oldSgns : [],
388 for i : nPols thru 1 step -1 do
390 sqPexp1 : sqAlg(polList[i],ptSet,var),
392 sqPexp2 : sqAlg(expand(polList[i]^2),ptSet,var),
393 solOne : solveSys(matrixOfSignsForOnePolyAllSigns,
394 [sqOne,sqPexp1,sqPexp2],LINEAR_SOLVER),
401 sgnsOnePoly : endcons(1,sgnsOnePoly),
403 sgnsOnePoly : endcons(-1,sgnsOnePoly),
404 nSigns : length(sgnsOnePoly),
405 adaOnePoly : makelist(j,j,0,nSigns-1),
407 mtxOnePoly : matrixOfSigns(makelist([adaOnePoly[j]],
408 j,1,length(adaOnePoly)),
409 makelist([sgnsOnePoly[j]],
410 j,1,length(sgnsOnePoly))),
414 sqVect : tarskiQueryVector(extendExponents(adaOnePoly,ada),
415 makelist(polList[j],j,i,nPols),
418 extMtx : tensorProduct(mtx,mtxOnePoly),
421 solExt : solveSys(extMtx,sqVect,LINEAR_SOLVER),
423 allSigns : extendSigns(sgnsOnePoly,sgns),
425 for j : 1 thru length(allSigns) do
426 if not(solExt[j] = 0) then
427 sgns : endcons(allSigns[j],sgns),
428 ada : extendAdaptedFamily(sgns,ada),
431 mtx : matrixOfSigns(ada,sgns)
436 sgns : makelist([sgnsOnePoly[j]],j,1,length(sgnsOnePoly)),
438 ada : makelist([adaOnePoly[j]],j,1,length(adaOnePoly))
454 log3(n) := log3aux(n,0);
456 naiveSignConv(naiveSignList) :=
457 block([res,i,j,nPols,tsign,tpol,item,propag,copyItem,prInd],
458 nPols : log3(length(naiveSignList)),
462 item : makelist(0,i,1,nPols),
463 for i : 1 thru length(naiveSignList) do
472 if item[prInd] < 2 then
474 item[prInd] : item[prInd]+1,
484 if naiveSignList[i] > 0 then
486 copyItem : copylist(item),
488 res : cons(copyItem,res)
495 return(exps2signs(res))
500 adaptedFamily(signDet) :=
501 block([partSignDet,i,partAda],
502 numPols : length(signDet[1]),
504 for i : numPols thru 1 step - 1 do
506 partSignDet : listify(setify(map(lambda([x],rest(x,i-1)),signDet))),
509 partAda : makelist([i],i,0,length(partSignDet)-1)
511 partAda : extendAdaptedFamily(partSignDet,partAda)
517 /* -------------------------------------------------- */
518 /* Thom Encoding related-functions */
521 /* Thom Encoding sorting */
524 thomLessAux(rest(lhs,-1),rest(rhs,-1),last(lhs));
527 thomLessAux(lhs,rhs,lastSgn) :=
528 if lhs = [] and rhs = [] then
531 if last(lhs)=last(rhs) then
532 thomLessAux(rest(lhs,-1),rest(rhs,-1),last(lhs))
535 if last(lhs)<last(rhs) then
540 if last(lhs)<last(rhs) then
545 thomSort(thomList) :=
546 sort(thomList,thomLess);
550 thomEncoding(pol,var) :=
551 thomSort(THOM_SIGN_DET_ALG(rest(derSeq(pol,var)),pol,
552 sSubResTarskiQuery,var));
556 extThomEncoding(p,q,var) :=
558 prepro : append(derSeq(q,var),rest(derSeq(p,var))),
560 return(THOM_SIGN_DET_ALG(prepro,p,sSubResTarskiQuery,var))
565 /* Merge two thom-sorted encodings and remove duplicates */
566 thomMerge(lhs,rhs) :=
567 mergeSorted(lhs,rhs,thomLess);
570 extThomMerge(lhs,degLhs,rhs,degRhs) :=
571 block([i,j,k,lhsLen,rhsLen,res,lhsComm,rhsComm,
572 lhsSign,lhsSignAtRhs,rhsSign,rhsSignAtLhs,numOfSigns],
573 lhsLen : length(lhs),
574 rhsLen : length(rhs),
575 numOfSigns : degLhs + degRhs+1,
579 while (i<= lhsLen) and (j<= rhsLen) do
581 lhsSign : makelist(lhs[i][k],k,degRhs+2,numOfSigns),
583 lhsSignAtRhs : makelist(lhs[i][k],k,2,degRhs+1),
585 rhsSign : makelist(rhs[j][k],k,degLhs+2,numOfSigns),
587 rhsSignAtLhs : makelist(rhs[j][k],k,2,degLhs+1),
591 while(not(rhs[j][1]=0)) do
593 res : endcons([2,rhsSign],res),
595 rhsSign : makelist(rhs[j][k],k,degLhs+2,numOfSigns)
597 res : endcons([0,lhsSign,rhsSign],res),
604 while(not(lhs[i][1]=0)) do
606 res : endcons([1,lhsSign],res),
608 lhsSign : makelist(lhs[i][k],k,degRhs+2,numOfSigns)
610 res : endcons([0,lhsSign,rhsSign],res),
616 if not(lhsSign=rhsSignAtLhs) then
617 if thomLess(lhsSign,rhsSignAtLhs) then
620 res : endcons([1,lhsSign],res),
625 res : endcons([2,rhsSign],res),
629 if thomLess(rhsSign,lhsSignAtRhs) then
632 res : endcons([2,rhsSign],res),
638 res : endcons([1,lhsSign],res),
645 res : append(res, makelist([1,
646 makelist(lhs[k][j],j,degRhs+2,numOfSigns)],
650 res : append(res, makelist([2,
651 makelist(rhs[k][j],j,degLhs+2,numOfSigns)],
657 /* It verifies whether a root of p is a common root */
658 /* with the polynomial used for the extended Thom encoding */
659 thomComm(pol,var,extThomEnc) :=
660 if(extThomEnc[degree(pol,var)+1]=0) then
666 /* Root Comparison */
667 thomCompare(p,q,var) :=
668 block([pSign,qSign, exP, exQ],
673 pSign : thomSort(extThomEncoding(exP,exQ,var)),
675 qSign : thomSort(extThomEncoding(exQ,exP,var)),
677 return(extThomMerge(pSign,degree(exP,var),qSign,degree(exQ,var)))
681 thomComparePrettyPrint(thomCompareOutput) :=
689 ["Com",x[2]]),thomCompareOutput);
692 /* For every Thom encoding of P it computes the signs of q */
694 thomSignsAtRoots(thomP,p,q,var) :=
695 block([adaQAux,qSigns,adaQ,adaDerPmP,
696 taQVect,mtxQ,mtxDerPmP,mtxExt,solExt,allSigns,
698 qSigns : smartSignDetermination([q],p,sSubResTarskiQuery,var),
700 adaQ : adaptedFamily(qSignsAux),
701 adaQAux : makelist(first(adaQ[i]),i,1,length(adaQ)),
703 adaDerPmP : adaptedFamily(thomP), /* Ada(Der(P)\{P}) */
705 taQVect : tarskiQueryVector(extendExponents(adaQAux,adaDerPmP),
706 cons(q,makelist(diff(p,var,i),i,1,degree(p,var))),
707 var,sSubResTarskiQuery,p),
709 mtxQ : matrixOfSigns(adaQ,qSigns),
712 mtxDerPmP : matrixOfSigns(adaDerPmP,thomP),
715 mtxExt : tensorProduct(mtxQ,mtxDerPmP),
717 solExt : solveSys(mtxExt,taQVect,LINEAR_SOLVER),
720 allSigns : extendSigns(qSigns,thomP),
723 for i : 1 thru length(allSigns) do
724 if not(solExt[i]=0) then
725 res : endcons([rest(allSigns[i]),first(allSigns[i])],res),
732 /* It computes the thom Encodings of p with */
733 /* with the sign of q at each Thom Encoding */
734 thomEncodingWithSigns(p,q,var) :=
737 signDetRes : smartSignDetermination(append(rest(derSeq(p,var)),[q]),p,
741 return(map(lambda([x],[rest(x,-1),last(x)]),