TTYOFF:TRUE $ LOAD(QUALSP)$ MATCHDECLARE([UTRUE,VTRUE,WTRUE],TRUE)$ TELLSIMP(QUAL(UTRUE), QUAL1(UTRUE, LISTOFVARS(UTRUE))) $ TELLSIMP(QUAL(UTRUE,VTRUE),QUAL1(UTRUE,LISTIFY(VTRUE))) $ TELLSIMP(REVELATION(UTRUE), REVELATION1(UTRUE,200,300)) $ TELLSIMP(REVELATION(UTRUE,VTRUE), REVELATION1(UTRUE,VTRUE,300))$ TELLSIMP(REVELATION(UTRUE,VTRUE,WTRUE), REVELATION1(UTRUE,VTRUE,WTRUE)) $ TELLSIMP(SLOPES(UTRUE),SLOPES1(UTRUE,LISTOFVARS(UTRUE)))$ TELLSIMP(SLOPES(UTRUE,VTRUE),SLOPES1(UTRUE,LISTIFY(VTRUE)))$ TELLSIMP(SYMMETRY(UTRUE),SYMMETRY1(UTRUE,LISTOFVARS(UTRUE)))$ TELLSIMP(SYMMETRY(UTRUE,VTRUE),SYMMETRY1(UTRUE,LISTIFY(VTRUE)))$ TELLSIMP(PERIODS(UTRUE), PERIODS1(UTRUE,LISTOFVARS(UTRUE))) $ TELLSIMP(PERIODS(UTRUE,VTRUE),PERIODS1(UTRUE,LISTIFY(VTRUE))) $ TELLSIMP(LIMITS(UTRUE),LIMITS1(UTRUE,LISTOFVARS(UTRUE)))$ TELLSIMP(LIMITS(UTRUE,VTRUE),LIMITS1(UTRUE,LISTIFY(VTRUE)))$ TELLSIMP(STATIONARYPOINTS(UTRUE),STATIONARYPOINTS1(UTRUE, LISTOFVARS(UTRUE)))$ TELLSIMP(STATIONARYPOINTS(UTRUE,VTRUE),STATIONARYPOINTS1(UTRUE, LISTIFY(VTRUE))) $ VARIABLEP(U) := IS(ATOM(U) AND NOT NUMBERP(U) OR SUBVARP(U)) $ LISTIFY(U) := IF LISTP(U) THEN U ELSE [U] $ QUAL1(U,V) := BLOCK( REVELATION1(U, 200, 300), RETURN([FIRST(LDISP(BOUNDS=BOUNDS(U))), SLOPES1(U,V), LDISP(CURVATURE=CURVATURE(U)), SYMMETRY1(U:RADCAN(U),V), PERIODS1(U,V), ZEROSANDSINGULARITIES(U), LIMITS1(U,V), STATIONARYPOINTS1(U,V)])) $ REVELATION1(U,UMIN,REVMAX) := BLOCK( [REV, LOLD, LNEW, LU], IF (LU:LENGTH(?MAKSTRING(U)))>UMIN THEN (LOLD:-1, FOR J:1 STEP 1 WHILE (LNEW:LENGTH(?MAKSTRING(REV:REVEAL(U,J)))) <=REVMAX AND LNEW#LOLD AND LNEW=1: */ IF GE1L(U[1]) THEN RETURN(BNDGE1TO(U,V)) ELSE IF LE1U(U[2]) THEN RETURN(BNDRECIP(BNDGE1TO(BNDRECIP(U), V))) ELSE IF GE1U(U[2]) THEN /* 0<=U[1]<1 and U[2]>1. Try standardizing lower bound of 2nd arg to nonnegative: */ IF NONNEGL(V[1]) THEN RETURN(BNDSPAN1TONN(U,V)) ELSE IF NONPOSU(V[2]) THEN RETURN(BNDRECIP(BNDSPAN1TONN(U, BNDMINUS(V)))) /* V[1]<1 or symbolic & V[2]>1 or symbolic. Standardize nonsymbolic args of ** to nonneg: */ ELSE RETURN([MIN(NNTONN(U[1],V[2]),RECIPL(NNTONN(U[2],NEG8( V[1])))), MAX(NNTONN(U[2],V[2]),RECIPU(NNTONN(U[1],NEG8( V[1]))))]) /* 0<=U[1]<1 & U[2] symbolic. Try standardizing lower bound of 2nd arg to nonegative: */ ELSE IF NONNEGL(V[1]) THEN RETURN(BNDMAYSPAN1TONN(U,V)) ELSE IF NONPOSU(V[2]) THEN RETURN(BNDRECIP(BNDMAYSPAN1TONN(U,BNDMINUS(V)))) /* U[1]<1 & U[2] symbolic: */ ELSE IF POSU(V[2]) THEN IF NEGL(V[1]) THEN RETURN([MIN(NNTONN(U[1],V[2]),U[2]**V[1]), MAX(RECIPU(NNTONN(U[1],NEG8(V[1]))), U[2]**V[2])]) /* V[1] symbolic too, so another possible upperbound:*/ ELSE RETURN([MIN(NNTONN(U[1],V[2]), U[2]**V[1]), MAX(U[1]**V[1], U[2]**V[2], U[2]**V[1])]) ELSE IF NEGL(V[1]) THEN RETURN([MIN(U[1]**V[2],U[2]**V[2],U[2] **V[1]),MAX(RECIPU(NNTONN(U[1],NEG8(V[1]))),U[2]**V[2])]) /* V[1] & V[2] symbolic. 3 symbolic possibilities for each bound: */ ELSE RETURN([MIN(U[1]**V[2], U[2]**V[2], U[2]**V[1]), MAX(U[1]**V[1], U[2]**V[2], U[2]**V[1])]) /* U[1]=0 or symbolic. Negatives must not be raised to nonintegers: */ ELSE IF INTEGERP(V[1]) AND INTEGERP(V[2]) THEN IF V[1]=V[2] THEN /* interval ** integer: */ IF V[1]>=0 THEN IF EVNP(V[1]) THEN IF NONPOSU(U[2]) THEN RETURN([NNTONN(NEG8(U[2]),V[1]), NNTONN(NEG8(U[1]),V[1])]) /* interval spanning 0 ** nonnegative integer: */ ELSE IF NEGL(U[1]) AND POSU(U[2]) THEN RETURN([0, MAX(NNTONN(U[2],V[1]), NNTONN(NEG8(U[1]),V[1]))]) /* U[1] or U[2] symbolic so that maybespan0 ** nonnegative even integer: */ ELSE RETURN([IF POSU(U[2]) THEN 0 ELSE U[2]**V[2], MAX(NNTONN(NEG8(U[1]),V[2]), U[2]**V[2])]) ELSE RETURN([NEG8(NNTONN(NEG8(U[1]),V[1])), /* allow for symbolic or either-signed upper bound of U: */ IF NEGU(U[2]) THEN NEG8(NNTONN(NEG8(U[2]),V[1])) ELSE NNTONN(U[2],V[1])]) /* U[1]<0: */ ELSE IF NONPOSU(U[2]) THEN IF EVNP(V[1]) THEN RETURN(BNDRECIP(BNDGE1TONN(BNDMINUS(U), BNDMINUS(V)))) ELSE RETURN(BNDMINUS(BNDRECIP(BNDGE1TONN(BNDMINUS(U), BNDMINUS(V))))) ELSE RETURN([MINF,INF]) ELSE IF NEGU(U[2]) THEN /* Try standardizing lowerbound of 1st arg <=-1: */ IF LEM1U(U[2]) THEN RETURN(BNDLEM1TO(U,V)) ELSE IF GEM1L(U[1]) THEN RETURN(BNDLEM1TO(BNDRECIP(U) ,BNDMINUS(V))) ELSE IF LEM1L(U[1]) THEN /* U[1]<-1 & U[2]>-1. Try standardizing lower bound of V to nonnegative: */ IF NONNEGL(V[1]) THEN RETURN(BNDSPANM1TONN(U,V)) ELSE IF NONPOSU(V[2]) THEN RETURN(BNDRECIP(BNDSPANM1TONN( U, BNDMINUS(V)))) ELSE (W: BNDLEM1TONN(U,V), /* V[1]<0 or symbolic & V[2]>0 or symbolic: */ U: BNDLEM1TONN(BNDRECIP(U),BNDMINUS(V)), RETURN([MIN(U[1],W[1]), MAX(U[2],W[2])])) /* U[1] algebraic: */ ELSE RETURN([LB(W),UB(W)]) ELSE IF V[1]>=0 THEN ( /* 0<=V[1]=-1 THEN TRUE ELSE FALSE $ GE1L(LB) := /* LB is a lowerbound. Returns TRUE if it is >=1, FALSE otherwise. */ IF NUMBERP(LB) AND LB>=1 OR INPART(LB,0)='STRICT AND NUMBERP( INPART(LB,1)) AND PIECE>=1 THEN TRUE ELSE FALSE $ GE1U(UB) := /* UB is an upperbound. Returns TRUE if it is >=1, FALSE otherwise. */ IF UB=INF OR NUMBERP(UB) AND UB>=1 OR INPART(UB,0)='STRICT AND (NUMBERP(BOUNDS1(INPART(UB,1))) AND PIECE>1 OR PIECE=INF)THEN TRUE ELSE FALSE $ /*LBATOM(W) := BLOCK(/* W is an indeterminate. Returns its lowerbound, printing a message and establishing it as MINF if none existed. */ [ANS], ANS: GET(W, LOWERBOUND), IF ANS=FALSE THEN (PRINT("DOING PUT(", W, ", MINF, LOWERBOUND)"), PUT(W, MINF, LOWERBOUND), ANS:MINF), RETURN (ANS)) $*/ LBATOM(W) := BLOCK( [ANS], IF W=%E THEN RETURN(2.718281), IF W=%PI THEN RETURN(3.141592), ANS: GREATERS(W), IF ANS=[] THEN (ANS:GEQS(W), IF ANS=[] THEN ANS:'MINF ELSE ANS: FIRST(ANS)) ELSE ANS: STRICT(FIRST(ANS)), RETURN(ANS)) $ LEM1L(LB) := /* LB is a lowerbound. Returns TRUE if it's <=-1, FALSE otherwise. */ IF NUMBERP(LB) AND LB<=-1 OR LB=MINF OR INPART(LB,0)='STRICT AND (INPART(LB,1)=MINF OR NUMBERP(PIECE) AND PIECE<1) THEN TRUE ELSE FALSE $ LEM1U(UB) := /* UB is an upperbound. Returns TRUE if it's <=-1, FALSE otherwise. */ IF NUMBERP(UB) AND UB<=-1 OR INPART(UB,0)='STRICT AND NUMBERP(INPART(UB,1)) AND PIECE<=-1 THEN TRUE ELSE FALSE $ LE1U(UB) := /* UB is an upperbound. Returns TRUE if it is <=1, FALSE otherwise. */ IF NUMBERP(UB) AND UB<=1 OR INPART(UB,0)='STRICT AND NUMBERP(INPART(UB,1)) AND PIECE<=1 THEN TRUE ELSE FALSE $ MGEZ(X,Y) := /* X & Y are bounds. Returns X*Y. */ IF X=0 OR Y=0 THEN 0 ELSE IF X=INF OR Y=INF THEN INF ELSE IF INPART(X,0)='STRICT THEN IF INPART(Y,0)='STRICT THEN STRICT(MGEZ(INPART(X,1),INPART(Y,1))) ELSE STRICT(MGEZ(INPART(X,1),Y)) ELSE IF INPART(Y,0)='STRICT THEN STRICT(MGEZ(X,INPART(Y,1))) ELSE X*Y $ NEGL(LB) := /* LB is a lowerbound. Returns TRUE if it is <0, FALSE otherwise. */ IF LB=MINF OR NUMBERP(LB) AND LB<0 OR INPART(LB,0)='STRICT AND (INPART(LB,1)=MINF OR NUMBERP(PIECE) AND PIECE<0) THEN TRUE ELSE FALSE $ NEGU(UB) := /* UB is an upperbound. Returns TRUE if it is <0 FALSE otherwise. */ IF NUMBERP(UB) AND UB<0 OR INPART(UB,0)='STRICT AND NUMBERP(INPART(UB,1)) AND PIECE<=0 THEN TRUE ELSE FALSE $ NEG8(B) := /* B is a bound. Returns its negative. */ IF VARIABLEP(B) THEN IF B=INF THEN MINF ELSE IF B=MINF THEN INF ELSE -B ELSE IF INPART(B,0)='STRICT THEN STRICT(NEG8(INPART(B,1))) ELSE -B $ NNTONN(X,Y) := /* X & Y are nonnegative bounds. Returns X**Y. */ IF Y=0 THEN 1 ELSE IF X=0 THEN 0 ELSE IF X=INF THEN INF ELSE IF X=1 THEN 1 ELSE IF Y=INF THEN IF NUMBERP(X) AND X<1 OR INPART(X,0)='STRICT AND NUMBERP(INPART(X,1)) AND PIECE<1 THEN 0 ELSE INF ELSE IF INPART(X,0)='STRICT THEN IF INPART(Y,0)='STRICT THEN STRICT(NNTONN(INPART(X,1),INPART(Y,1))) ELSE STRICT(NNTONN(INPART(X,1),Y)) ELSE IF INPART(Y,0)='STRICT THEN STRICT(NNTONN(X,INPART(Y,1))) ELSE EV(X**Y,NUMER) $ NONNEGL(LB) := /* LB is a lower bound. Returns TRUE if it is nonnegative, FALSE otherwise. */ IF LB=0 OR POSL(LB) THEN TRUE ELSE FALSE $ NONPOSU(UB) := /* UB is an upperbound. Returns TRUE if it is positive, FALSE otehrwise. */ IF UB=0 OR NEGU(UB) THEN TRUE ELSE FALSE $ POSL(LB) := /* LB is a lowerbound. Returns TRUE if it is >0, FALSE otherwise. */ IF NUMBERP(LB) AND LB>0 OR INPART(LB,0)='STRICT AND NUMBERP(INPART(LB,1)) AND PIECE>=0 THEN TRUE ELSE FALSE $ POSU(UB) := /* UB is an upperbound. Returns TRUE if >0, FALSE otherwise. */ IF UB=INF OR NUMBERP(UB) AND UB>0 OR INPART(UB,0)='STRICT AND (INPART(UB,1)=INF OR NUMBERP(PIECE) AND PIECE>=0) THEN TRUE ELSE FALSE $ RECIPL(UB) := /* UB is an upperbound. Returns its 1/UB. */ IF UB=INF THEN 0 ELSE IF UB=0 THEN MINF ELSE IF INPART(UB,0)='STRICT THEN STRICT(RECIPL(INPART(UB,1))) ELSE 1/UB $ RECIPU(LB) := /* LB is a lowerbound. Returnns its 1/LB. */ IF LB=MINF THEN 0 ELSE IF LB=0 THEN INF ELSE IF INPART(LB,0)='STRICT THEN STRICT(RECIPU(INPART(LB,1))) ELSE 1/LB $ /*UBATOM(W) := BLOCK(/* W is an indeterminate. Returns its upperbound, printing a message & establishing it as INF if none existed. */ [ANS], ANS: GET(W, UPPERBOUND), IF ANS=FALSE THEN (PRINT("DOING PUT(", W, ", INF, UPPERBOUND)"), PUT(W,INF,UPPERBOUND), ANS: INF), RETURN(ANS)) $*/ UBATOM(W) := BLOCK( [ANS], IF W=%E THEN RETURN(2.718282), IF W=%PI THEN RETURN(3.141593), ANS: LESSES(W), IF ANS=[] THEN (ANS:LEQS(W), IF ANS=[] THEN ANS:'INF ELSE ANS: FIRST(ANS)) ELSE ANS: STRICT(FIRST(ANS)), RETURN(ANS)) $ UNARYBND(NAME, B, D) := BLOCK(/* NAME is name of a univariate nondecreasing function like LOG, B is a bound of its argument, and D is PLUS for a lower bound or MINUS for an upperbound. Returns the corresponding bound of NAME(argument). */ [ARG], IF INPART(B,0) = 'STRICT THEN ARG: STRICT(LIMIT(APPLY(NAME,[ARG]), ARG, INPART(B,1), D)) ELSE ARG: LIMIT(APPLY(NAME,[ARG]), ARG, B, D), RETURN(EV(ARG,NUMER))) $ DEFINITECODE(A) := BLOCK( /*LAGRANGE'S */ [N, PERM, B, II, JJ, KK, NPOS, NNEG, NZERO, NNPOS, NNNEG, NUNKN, PARTSWITCH, PREDERROR], PREDERROR:FALSE, PARTSWITCH: TRUE, N: LENGTH(A), PERM: [], NPOS: NNEG: NZERO: NNPOS: NNNEG: NUNKN: 0, FOR I:N STEP -1 THRU 1 DO PERM: CONS(I, PERM), FOR I:1 THRU N WHILE (NPOS=0 OR NNEG=0) DO( JJ: I, WHILE JJ<=N AND A[II:PERM[JJ],II]=0 DO JJ: JJ+1, IF JJ>N THEN (NZERO: N+1-I, FOR J:I THRU N WHILE NPOS=0 OR NNEG=0 DO(II: PERM[J], FOR K:I THRU N DO IF A[II,PERM[K]]#0 THEN NPOS:NNEG:1)) ELSE (PERM[JJ]:PERM[I], PERM[I]:II, B: BOUNDS1(A[II,II]), IF POSL(B[1]) THEN NPOS: NPOS+1 ELSE IF NEGU(B[2]) THEN NNEG: NNEG+1 ELSE IF B[1]=0 THEN IF B[2]=0 THEN NZERO:NZERO+1 ELSE NNNEG: NNNEG+1 ELSE IF B[2]=0 THEN NNPOS: NNPOS+1 ELSE NUNKN: NUNKN+1, FOR J:I+1 THRU N DO (JJ: PERM[J], B: -A[JJ,II]/A[II,II], FOR K:I+1 THRU N DO (KK: PERM[K], A[JJ,KK]: A[JJ,KK] + B*A[II,KK])))), IF NPOS>0 THEN IF NNEG>0 THEN RETURN(/*indefinite*/ 8) ELSE IF NNPOS>0 THEN RETURN(/*pos semi or indef*/ 5) ELSE IF NUNKN=0 THEN IF NZERO=0 AND NNNEG=0 THEN RETURN(/*pos def*/ 7) ELSE RETURN(/*pos semi*/ 6) ELSE RETURN(/*pos def, pos semi, or indef*/ 5) ELSE IF NNEG>0 THEN IF NNNEG>0 THEN RETURN(/*neg semi or indef*/ 3) ELSE IF NUNKN=0 THEN IF NZERO=0 AND NNPOS=0 THEN RETURN(/*neg def*/ 1) ELSE RETURN(/*neg semi*/ 2) ELSE RETURN(/*neg def, neg semi, or indef*/ 3) ELSE IF NUNKN=0 THEN IF NNPOS=0 THEN IF NNNEG=0 THEN RETURN(/*rank 0*/ 4) ELSE RETURN(/*pos semi*/ 6) ELSE IF NNNEG=0 AND NZERO=0 THEN RETURN(/*neg def or semi*/ 2) ELSE RETURN(/*unknown*/ 9) ELSE RETURN(/*unknown*/ 9)) $ TTYOFF:FALSE $