4 /* numbers and constants */
68 sign(x^2 + sqrt(5) + 101);
71 sign(%pi * x^2 + sqrt(5) + 101);
74 sign((sqrt(97) - 1) * x^2 + sqrt(5) + 101);
80 sign(x^2 - 2 * x + 1);
83 sign(-x^2 + 2 * x - 1);
89 sign(x^2 + 2 * x * y + y^2);
92 sign(x^2 + 2 * x * y + y^2 + 1);
95 sign((x+y)^2 + (z-x)^2);
98 sign(sqrt(2) * (x+y)^2 + %e * (z-x)^2);
101 sign(-(x+y)^2 - (z-x)^2);
104 sign(-(x+y)^2 - (z-x)^2 - %pi);
107 sign(-sqrt(2) * (x+y)^2 - %phi * (z-x)^2 - %pi);
133 (assume(a < b, b < c, c < d),0);
154 sign(7*(c-a) + %pi * (d-b));
157 sign(-7*(c-a) - %pi * (d-b));
166 (forget(a < b, b < c, c < d),0);
177 sign(sqrt(a) + sqrt(b));
189 sign(-(x^(1/4) + 1));
259 (assume(x >= -1), assume(x < 1),0);
265 (forget(x >= -1), forget(x < 1),0);
268 (assume(x > 0), assume(x <= 1),0);
277 (forget(x > 0), forget(x <= 1),0);
280 (assume(x >= -1), assume(x <= 0),0);
289 (forget(x >= -1), forget(x <= 0),0);
293 (assume(xpos > 0), assume(xneg < 0), assume(xpz >= 0), assume(xnz <= 0), assume(notequal(xpn, 0)), assume(equal(xzero, 0)), declare(xeven, even), declare(xodd, odd),0);
296 create_list(errcatch(sign(x^y)),
297 x, [xpos, xneg, xpz, xnz, xpn, xzero, xpnz],
298 y, [xpos, xneg, xpz, xnz, xpn, xzero, xpnz, xeven, xodd]);
299 [[pos], [pos], [pos], [pos], [pos], [pos], [pos], [pos], [pos], /* xpos^y */
300 [pn], [pn], [pn], [pn], [pn], [pos], [pn], [pos], [neg], /* xneg^y */
301 [pz], [pos], [pz], [pos], [pz], [pos], [pz], [pz], [pz], /* xpz^y */
302 [pnz], [pn], [pnz], [pn], [pnz], [pos], [pnz], [pz], [nz], /* xnz^y */
303 [pn], [pn], [pn], [pn], [pn], [pos], [pn], [pos], [pn], /* xpn^y */
304 [zero], [], [zero], [], [zero], [], [zero], [zero], [zero], /* xzero^y */
305 [pnz], [pn], [pnz], [pn], [pnz], [pos], [pnz], [pz], [pnz]]$ /* xpnz^y */
307 (forget(xpos > 0), forget(xneg < 0), forget(xpz >= 0), forget(xnz <= 0), forget(notequal(xpn, 0)), forget(equal(xzero, 0)), remove(xeven, even), remove(xodd, odd),0);
312 sign(sqrt(2)/2 - 1/sqrt(2));
316 * This case is fixed in compar.lisp revision 1.76.
317 * Adding some more examples.
320 (assume(a > 1, b > 1),0);
330 (forget(a > 1, b > 1),0);
333 (assume(a < -1, b < -1),0);
343 (forget(x < -1, y < -1),0);
348 (aaa : 'bbb, bbb : 'ccc, ccc : 23.5,0);
357 (remvalue(aaa, bbb, ccc),0);
369 /* [ 1981623 ] wrong sign of sqrt() */
370 (assume(xx >= 0, xx <= 1), 0);
377 /*****************************************************************************
379 Add tests for the function $csign
381 First: We repeat all tests which give a correct result for $sign.
382 The tests which are expected to fail are commented out.
384 ******************************************************************************/
389 /* numbers and constants */
453 csign(x^2 + sqrt(5) + 101);
456 csign(%pi * x^2 + sqrt(5) + 101);
459 csign((sqrt(97) - 1) * x^2 + sqrt(5) + 101);
462 csign(-x^2 + x - 42);
465 csign(x^2 - 2 * x + 1);
468 csign(-x^2 + 2 * x - 1);
474 csign(x^2 + 2 * x * y + y^2);
477 csign(x^2 + 2 * x * y + y^2 + 1);
480 csign((x+y)^2 + (z-x)^2);
483 csign(sqrt(2) * (x+y)^2 + %e * (z-x)^2);
486 csign(-(x+y)^2 - (z-x)^2);
489 csign(-(x+y)^2 - (z-x)^2 - %pi);
492 csign(-sqrt(2) * (x+y)^2 - %phi * (z-x)^2 - %pi);
510 csign(1 + x/(1+x^2));
518 (assume(a < b, b < c, c < d),0);
539 csign(7*(c-a) + %pi * (d-b));
542 csign(-7*(c-a) - %pi * (d-b));
545 csign((b-a) * (d-a));
551 (forget(a < b, b < c, c < d),0);
559 csign(sqrt(x^2 + 1));
562 csign(sqrt(a) + sqrt(b));
574 csign(-(x^(1/4) + 1));
653 (assume(x >= -1), assume(x <= 1),0);
665 (forget(x >= -1), forget(x <= 1),0);
668 (assume(x >= -1), assume(x < 1),0);
674 (forget(x >= -1), forget(x < 1),0);
677 (assume(x > 0), assume(x <= 1),0);
686 (forget(x > 0), forget(x <= 1),0);
689 (assume(x >= -1), assume(x <= 0),0);
698 (forget(x >= -1), forget(x <= 0),0);
702 (assume(xpos > 0), assume(xneg < 0), assume(xpz >= 0), assume(xnz <= 0), assume(notequal(xpn, 0)), assume(equal(xzero, 0)),
703 declare(xeven, even), declare(xodd, odd), declare(ximag, imaginary), declare(xcomplex, complex),0);
706 create_list(errcatch(csign(x^y)),
707 x, [xpos, xneg, xpz, xnz, xpn, xzero, xpnz, ximag, xcomplex],
708 y, [xpos, xneg, xpz, xnz, xpn, xzero, xpnz, xeven, xodd, ximag, xcomplex]);
709 [[pos], [pos], [pos], [pos], [pos], [pos], [pos], [pos], [pos], [complex], [complex], /* xpos^y */
710 [complex], [complex], [complex], [complex], [complex], [pos], [complex], [pos], [neg], [complex], [complex], /* xneg^y */
711 [pz], [pos], [pz], [pos], [pz], [pos], [pz], [pz], [pz], [complex], [complex], /* xpz^y */
712 [complex], [complex], [complex], [complex], [complex], [pos], [complex], [pz], [nz], [complex], [complex], /* xnz^y */
713 [complex], [complex], [complex], [complex], [complex], [pos], [complex], [pos], [pn], [complex], [complex], /* xpn^y */
714 [zero], [], [zero], [], [zero], [], [zero], [zero], [zero], [zero], [zero], /* xzero^y */
715 [complex], [complex], [complex], [complex], [complex], [pos], [complex], [pz], [pnz], [complex], [complex], /* xpnz^y */
716 [complex], [complex], [complex], [complex], [complex], [pos], [complex], [complex], [complex], [complex], [complex], /* ximag^y */
717 [complex], [complex], [complex], [complex], [complex], [pos], [complex], [complex], [complex], [complex], [complex]]$ /* xcomplex^y */
719 (forget(xpos > 0), forget(xneg < 0), forget(xpz >= 0), forget(xnz <= 0), forget(notequal(xpn, 0)), forget(equal(xzero, 0)),
720 remove(xeven, even), remove(xodd, odd), remove(ximag, imaginary), remove(xcomplex, complex),0);
725 csign(sqrt(2)/2 - 1/sqrt(2));
730 (assume(a > 1, b > 1),0);
736 (forget(a > 1, b > 1),0);
741 (aaa : 'bbb, bbb : 'ccc, ccc : 23.5,0);
750 (remvalue(aaa, bbb, ccc),0);
762 /******************************************************************************
763 Second: $csign with complex expressions.
764 ******************************************************************************/
766 declare(n,integer,x,real,j,imaginary,z,complex);
769 /* We test the constants. UND and IND do not give a result, but an error. */
770 map(csign, [%e,%gamma,%phi,%i, minf,inf,infinity]);
771 [pos,pos,pos,imaginary,neg,pos,complex];
773 /* Symbols declcared as integeger, real, imaginary or complex */
774 map(csign, [n,x,j,z]);
775 [pnz,pnz,imaginary,complex];
777 /* Some arithmetic with pure imaginary numbers and symbols */
779 map(csign,[%i,sqrt(-1),10*%i,x*%i,%i^2,%i^3,%i^4,%i^5]);
780 [imaginary,imaginary,imaginary,imaginary,neg,imaginary,pos,imaginary];
782 map(csign,[j,sqrt(-1),10*j,x*j,j^2,j^3,j^4,j^5]);
783 [imaginary,imaginary,imaginary,imaginary,nz,imaginary,pz,imaginary];
785 /* negative base and half integral exponent */
786 map(csign,[(-1)^(1/2),(-1)^(3/2),(-1)^(5/2), (-1)^(7/2), (-1)^(9/2)]);
787 [imaginary,imaginary,imaginary,imaginary,imaginary];
789 /* the same with an negative expression */
790 (assume(xneg < 0, xpos>0),done);
792 map(csign,[(xneg)^(1/2),(xneg)^(3/2),(xneg)^(5/2),(xneg)^(7/2)]);
793 [imaginary,imaginary,imaginary,imaginary];
795 map(csign,[(-xpos)^(1/2),(-xpos)^(3/2),(-xpos)^(5/2),(-xpos)^(7/2)]);
796 [imaginary,imaginary,imaginary,imaginary];
798 map(csign,[(-1)^xpos, (-1)^xneg]);
801 map(sign,[(-1)^xpos, (-1)^xneg]);
804 /* Expressions with an addition */
810 csign((x+%i*y)^(1/2));
813 csign((a+x+%i*y)/(b-y*%i));
816 /* More expressions */
826 csign((10*a+(c/j)^2)^n);
828 csign((10*a+(c/j)^3)^n);
831 /* This does not work correctly.
832 The answer complex is not really wrong, but could be better.
833 To achieve this we have first to improve the function rectform. */
835 csign((1+%i)*(1-%i));
836 complex; /* should be pos */
838 csign(expand((1+%i)*(1-%i)));
839 pos; /* after expansion correct */
841 /* Functions which are declared to be complex give the sign $complex */
845 csign(conjugate(x)); /* x is real */
853 /* realpart and imagpart are real valued */
861 * Examples for assumptions with abs(x)<a, a is positive
886 assume(a>0,abs(x)<a);
911 assume(abs(x)<2*a+1);
921 forget(abs(x)<2*a+1);
946 assume(sin(abs(x)) < 1);
958 forget(sin(abs(x)) < 1);
961 assume(cos(abs(x)) < 1);
973 forget(cos(abs(x)) < 1);
976 assume(abs(sin(x)) < 1);
988 forget(abs(sin(x)) < 1);
991 assume(abs(cos(x)) < 1);
1003 forget(abs(cos(x)) <1);
1006 csign(log((1 + %i)/sqrt(2)));
1009 /* Examples to show that learn-numer works
1010 * Related bug report:
1011 * Bug ID: 2477795 - "assume":problems with fractions or multiples of %pi and %e
1015 assume(a>0,a<%pi/2);
1023 assume(b>0,b<2*%pi);
1028 /* An example involving a numerical constant, the value of a function
1029 * and the abs function.
1030 * This example no longer works because of revision 1.62 of compar.lisp
1032 assume(abs(x) < sin(1)+%e/2);
1033 [sin(1)+%e/2>abs(x)];
1038 (forget(abs(x)<sin(1)+%e/2),done);
1041 /* Bug ID: 2876382 - sign(a+b+sin(1)) unknown */
1042 (assume(a>0,b>0),done);
1046 (forget(a>0,b>0),done);
1049 /* Bug ID: 2184396 - Wrong factorization of sqrt()
1050 * This is the example from the bug report which has triggered the bug in sign
1051 * sqrt(1-(2-sqrt(2))/x * ((2+sqrt(2))/x-1));
1052 * The expression has factored wrongly. This example is now correct.
1054 sign(1-(1+sqrt(2))*x);
1056 sign(1-(1+sqrt(2))/x);
1059 /* Bug ID: 1038624 - askinteger ignores asksign database
1060 * With revision 1.64 of compar.lisp code has been added, which looks for
1061 * integer and noninteger facts into the database.
1063 (assume(equal(a,0), equal(b,2), equal(c,1/3), equal(d,1.5), equal(e,3.0b0)),
1067 map(askinteger, [a, b, 2*b, 2+b, c, d, e]);
1068 [yes, yes, yes, yes, no, no, no];
1071 (forget(equal(a,0), equal(b,2), equal(c,1/3), equal(d,1.5), equal(e,3.0b0)),
1075 /* Bug ID: 3376603 - sign of declared imaginary */
1076 declare(f,imaginary, g,complex);
1085 /* Check adding new equaltiy does not make old inequality disappear */
1089 assume(notequal(a,b));
1095 (assume(equal(a, x+y)), 0);
1101 /* Check fix for bug 2547 (declare constant messes up sign calculations) */
1102 (declare (x, constant), declare (y, constant), assume (x > y), is (x>y));
1105 /* facts in assume database not cleaned up by 'sign' */
1107 (kill (foo), foo : %e^(abs(uu)+uu)*(uu/abs(uu)+1)+%e^(abs(uu)-uu)*(uu/abs(uu)-1), 0);
1110 block ([bar, baz], bar : copy (facts (initial)), is (equal (foo, 0)), baz : facts (initial), is (bar = baz));
1113 /* tnx to Barton Willis for the next couple of tests */
1115 map('sign,[sqrt(x),x]);
1119 buddy(p,q) := expand(if p >= 0 then q else q,0,0),
1120 buddy(sqrt(x),abs(x)));
1123 /* Ensure that asksign1 deals correctly with squared expressions */
1124 (assume (notequal(n, 1)), 0);
1130 /* Here are some calls to asksign & askinteger -- these don't cause
1131 * an interactive prompt. Interactive examples are in rtest_ask.mac.
1134 map(askinteger,[0,1/2,sqrt(17)]);
1137 /* Known constants */
1138 map(askinteger,[%pi,%e,%phi,%gamma,%i]);
1141 map(asksign,[%pi,%e,%phi,%gamma,inf,minf]);
1142 [pos,pos,pos,pos,pos,neg]$
1144 errcatch(asksign(%i));
1145 []$ /* argument cannot be imaginary. */
1147 errcatch(asksign(infinity));
1148 []$ /* sign of infinity is undefined. */
1152 (declare(o, oddfun),0);
1155 (assume(equal(q, 0)),0);
1161 (remove(o, oddfun),0);
1164 (forget(equal(q, 0)),0);
1167 /* Increasing and decreasing functions */
1169 (declare(i, increasing, d, decreasing),0);
1181 (remove(i, increasing, d, decreasing),0);
1187 /* Increasing and decreasing odd functions */
1189 (declare(i, [oddfun, increasing], d, [oddfun, decreasing]),0);
1192 (assume(q < 0, r > 0),0);
1207 (remove(i, [oddfun, increasing], d, [oddfun, decreasing]),0);
1210 (forget(q < 0, r > 0),0);
1213 /* Bug #3109: is(sin(x) <= 1) returns "unknown", is(sin(x) <= 1.00001) returns "true" */
1233 /* Assumptions and queries involving multiple unknowns */
1240 assume(notequal(2*a*b,10));
1242 is(equal(10*a*b,50));
1247 /* Exponents in inequality assumptions and queries */
1252 (declare(e, even, o, odd), 0);
1264 assume(f^(1/3)*g^h<0);
1269 /* The csign of a product with a complex factor and a zero factor used
1270 * to depend on the order of the factors: if the zero came first then
1271 * the sign was zero, but if the complex came first then the sign was
1275 (declare (a, complex), assume (equal (b, 0)), 0)$
1279 (remove (a, complex), forget (equal (b, 0)), 0)$
1282 (declare (b, complex), assume (equal (a, 0)), 0)$
1286 (remove (b, complex), forget (equal (a, 0)), 0)$
1289 /* SF bug report #3583: "Stack overflow for equality testing with assumptions" */
1292 myctxt: newcontext (),
1293 assume (x > 0, y > 0),
1294 is(equal(y*(x-y),0)));
1298 is(equal(y*(x-y),0)));
1301 (killcontext (myctxt),
1306 /* Bug #3417: sign(1/zero) => 0 (where equal(zero,0)) */
1308 (assume (equal (zero, 0), equal (q, r)), 0)$
1311 errcatch (sign (1 / (q - r)))$
1314 /* This used to return zero */
1315 errcatch (sign (1 / zero))$
1318 (forget (equal (zero, 0), equal (q, r)), 0)$
1321 /* bug reported to mailing list 2021-06-27: "ev(xxx,pred) vs is(xxx)" */
1323 xxx: '((0 < 1) or (0 < 2));
1335 yyy: '((0 < 1) and (0 < 2));
1336 (0 < 1) and (0 < 2);
1341 zzz: '((0 > 1) or (0 < 2));
1347 aaa: '((0 > 1) and (0 < 2));
1348 (0 > 1) and (0 < 2);
1353 bbb: '((0 > 1) or (0 > 2));
1359 (kill(xyz), ccc: '((xyz > 4) or (3 > 2)));
1360 (xyz > 4) or (3 > 2);
1365 ddd: '((2 < 1) or (2 < 2) or (1 < 3) and (2 < 4));
1366 (2 < 1) or (2 < 2) or ((1 < 3) and (2 < 4));
1371 /* SF bug #3324: "Stack overflow in sign() when domain complex" */
1373 (kill(a, b, c, xxx, yyy, zzz, aaa, bbb, ccc, ddd),
1375 declare([a,b,c], real),
1376 mycontext: newcontext (),
1377 assume(a>0, b>0, c>0),
1378 sign(c - b^(1/3)*c^(1/3)));
1381 sign(c - (b*c)^(1/3));
1384 (killcontext (mycontext), remvalue(mycontext),0);
1387 /* SF bug #3440: "complex domain + real variable = seg-fault"
1388 * possibly related to #3324
1391 (kill (m1, m2, m3, r12, r13, r23, A),
1392 mycontext: newcontext (),
1394 declare([m1,m2,m3],real),
1395 declare([r12,r13,r23],real),
1396 assume(r12>0,r13>0,r23>0),
1397 assume(r12<r13+r23,r13<r12+r23,r23<r12+r13),
1398 assume(m1>0,m2>0,m3>0),
1399 A : (-((((-r23^2)+r13^2+r12^2)*(r23^2-r13^2+r12^2))/((m2+m1)*r12^2*r13*r23)+(2*((-r23^2)-r13^2+r12^2))/(m3*r13*r23))^2/(4*((4*(m3+m1))/(m1*m3)-(m2*((-r23^2)+r13^2+r12^2)^2)/(m1*(m2+m1)*r12^2*r13^2))))-(m1*(r23^2-r13^2+r12^2)^2)/(4*m2*(m2+m1)*r12^2*r23^2)+(m3+m2)/(m2*m3),
1404 killcontext (mycontext),
1406 remvalue(mycontext), 0);
1409 /* SF bug #4120: is("foo"<3) gives internal error */
1411 block ([prederror: false], is("foo"<3));
1414 errcatch (block ([prederror: true], is("foo"<3)));
1417 block ([prederror: false], is(3 < "foo"));
1420 errcatch (block ([prederror: true], is(3 < "foo")));
1423 block ([prederror: false],
1425 [is ("foo" < 3), is ("foo" < foo), is ("foo" < sin (foo))]);
1426 [false, false, false];
1428 block ([prederror: true],
1429 [errcatch (is ("foo" < 3)), errcatch (is ("foo" < foo)), errcatch (is ("foo" < sin (foo)))]);
1432 block ([prederror: false], is("foo"<=3));
1435 errcatch (block ([prederror: true], is("foo"<=3)));
1438 block ([prederror: false], is(3 <= "foo"));
1441 errcatch (block ([prederror: true], is(3 <= "foo")));
1444 block ([prederror: false],
1445 [is ("foo" <= 3), is ("foo" <= foo), is ("foo" <= sin (foo))]);
1446 [false, false, false];
1448 block ([prederror: true],
1449 [errcatch (is ("foo" <= 3)), errcatch (is ("foo" <= foo)), errcatch (is ("foo" <= sin (foo)))]);
1452 block ([prederror: false],
1453 [is ("abc" > "ab"), is ("abc" > "abc"), is ("abc" > "abcd")]);
1454 [true, false, false];
1456 block ([prederror: true],
1457 [is ("abc" > "ab"), is ("abc" > "abc"), is ("abc" > "abcd")]);
1458 [true, false, false];
1460 block ([prederror: false],
1461 [is ("abc" >= "ab"), is ("abc" >= "abc"), is ("abc" >= "abcd")]);
1462 [true, true, false];
1464 block ([prederror: true],
1465 [is ("abc" >= "ab"), is ("abc" >= "abc"), is ("abc" >= "abcd")]);
1466 [true, true, false];
1468 block ([prederror: false], sort (["xyz", "xy", "vwxy", "vw", "uvwxyz", "uv"], ">"));
1469 ["xyz", "xy", "vwxy", "vw", "uvwxyz", "uv"];
1471 /* Consistency check for `is(expr >= 0)` and `sign(expr)` */
1476 /* Tests for sign-cos & sign-sin */
1483 block([ans], assume(0 < z, z < %pi), ans : sign(sin(z)), forget(0 < z, z < %pi), ans);
1486 block([ans], assume(0 <= z, z <= %pi), ans : sign(sin(z)), forget(0 <= z, z <= %pi), ans);
1489 block([ans], assume(0 < z, z < %pi), ans : sign(sin(z)), forget(0 < z, z < %pi), ans);
1492 block([ans], assume(-%pi < z, z < 0), ans : sign(sin(z)), forget(-%pi < z, z < 0), ans);
1495 block([ans], assume(-%pi <= z, z <= 0), ans : sign(sin(z)), forget(-%pi <= z, z <= 0), ans);
1498 csign(sin(-28/3 +%i));
1507 block([ans], assume(-%pi/2 < z, z < %pi/2), ans : sign(cos(z)), forget(-%pi/2 < z, z < %pi/2), ans);
1510 block([ans], assume(-%pi/2 <= z, z <= %pi/2), ans : sign(cos(z)), forget(-%pi/2 <= z, z <= %pi/2), ans);
1513 block([ans], assume(%pi/2 < z, z < 3*%pi/2), ans : sign(cos(z)), forget(%pi/2 < z, z < 3*%pi/2), ans);
1516 block([ans], assume(%pi/2 <= z, z <= 3*%pi/2), ans : sign(cos(z)), forget(%pi/2 <= z, z <= 3*%pi/2), ans);
1519 csign(cos(11/5 +%i));
1522 /* Tests for sign of ceiling & floor */
1524 block([ans], assume(x >= 0), ans : sign(floor(x)), forget(x >= 0), ans);
1527 block([ans], assume(x >= 1), ans : sign(floor(x)), forget(x >= 1), ans);
1530 block([ans], assume(x > 1), ans : sign(floor(x)), forget(x > 1), ans);
1533 block([ans], assume(x < 0), ans : sign(floor(x)), forget(x < 0), ans);
1536 block([ans], assume(x <= 0), ans : sign(floor(x)), forget(x <= 0), ans);
1539 block([ans], assume(x > 0), ans : sign(ceiling(x)), forget(x > 0), ans);
1542 block([ans], assume(x > -1), ans : sign(ceiling(x)), forget(x > -1), ans);
1545 block([ans], assume(x <= -1), ans : sign(ceiling(x)), forget(x <= -1), ans);
1548 block([ans], assume(x < 0), ans : sign(ceiling(x)), forget(x < 0), ans);
1554 (kill(a,b,c),killcontext(learndata),0);