Changing default RPM built to GCL.
[maxima.git] / tests / rtest_sign.mac
blob061cfde8f50a8253651a3a0a2f54919136041842
1 (kill(all),0);
2 0$
4 /* numbers and constants */
6 sign(minf);
7 neg$
9 sign(-1);
10 neg$
12 sign(-1.0);
13 neg$
15 sign(-1.0b0);
16 neg$
18 sign(0);
19 zero$
21 sign(0.0);
22 zero$
24 sign(0.0b0);
25 zero$
27 sign(1);
28 pos$
30 sign(1.0);
31 pos$
33 sign(1.0b0);
34 pos$
36 sign(inf);
37 pos$
39 sign(%pi);
40 pos$
42 sign(%e);
43 pos$
45 sign(%phi);
46 pos$
48 /* polynomials */
50 sign(x);
51 pnz$
53 sign(x^2);
54 pz$
56 sign(x^3);
57 pnz$
59 sign(x^4);
60 pz$
62 sign(x^2 + x);
63 pnz$
65 sign(x^2 + x + 42);
66 pos$
68 sign(x^2 + sqrt(5) + 101);
69 pos$
71 sign(%pi * x^2 + sqrt(5) + 101);
72 pos$
74 sign((sqrt(97) - 1) * x^2 + sqrt(5) + 101);
75 pos$
77 sign(-x^2 + x - 42);
78 neg$
80 sign(x^2 - 2 * x + 1);
81 pz$
83 sign(-x^2 + 2 * x - 1);
84 nz$
86 sign(x+y);
87 pnz$
89 sign(x^2 + 2 * x * y + y^2);
90 pz$
92 sign(x^2 + 2 * x * y + y^2 + 1);
93 pos$
95 sign((x+y)^2 + (z-x)^2);
96 pz$
98 sign(sqrt(2) * (x+y)^2 + %e * (z-x)^2);
99 pz$
101 sign(-(x+y)^2 - (z-x)^2);
104 sign(-(x+y)^2 - (z-x)^2 - %pi);
105 neg$
107 sign(-sqrt(2) * (x+y)^2 - %phi * (z-x)^2 - %pi);
108 neg$
111 /* rational */
113 sign(1/x);
116 sign(1/(x-1));
119 sign(1/x + 1);
120 pnz$
122 sign(x/(1+x^2));
123 pnz$
125 sign(1 + x/(1+x^2));
126 pos$
128 sign((1+x^2)/x);
131 /* assumptions */
133 (assume(a < b, b < c, c < d),0);
136 sign(b-a);
137 pos$
139 sign(a-b);
140 neg$
142 sign(c-a);
143 pos$
145 sign(a-c);
146 neg$
148 sign(d-b);
149 pos$
151 sign(b-d);
152 neg$
154 sign(7*(c-a) + %pi * (d-b));
155 pos$
157 sign(-7*(c-a) - %pi * (d-b));
158 neg$
160 sign((b-a) * (d-a));
161 pos$
163 sign((b-a)/(c-b));
164 pos$
166 (forget(a < b, b < c, c < d),0);
169 /* algebraic */
171 sign(sqrt(x));
174 sign(sqrt(x^2 + 1));
175 pos$
177 sign(sqrt(a) + sqrt(b));
180 sign(x^(1/3));
181 pnz$
183 sign(x^(1/4));
186 sign(x^(1/4) + 1);
187 pos$
189 sign(-(x^(1/4) + 1));
190 neg$
192 /* exp-like */
194 sign(cos(x));
195 pnz$
197 sign(cos(x) + 42);
198 pos$
200 sign(sin(x) - 42);
201 neg$
203 sign(cosh(x));
204 pos$
206 sign(cosh(x)-1);
209 sign(sinh(x));
210 pnz$
212 sign(tanh(x));
213 pnz$
215 sign(exp(x));
216 pos$
218 sign(exp(-x^2));
219 pos$
221 sign(exp(-x) - 1);
222 pnz$
224 sign(exp(-x) + 1);
225 pos$
227 /* log-like */
229 sign(acos(x));
232 sign(asin(x));
233 pnz$
235 sign(atan(x));
236 pnz$
238 sign(log(x));
239 pnz$
241 (assume(x >= 1),0);
244 sign(log(x));
247 (forget(x >= 1),0);
250 sign(acosh(x));
253 sign(asinh(x));
254 pnz$
256 sign(tanh(x));
257 pnz$
261 /* SF bug 798571 */
263 sign(sqrt(2)/2 - 1/sqrt(2));
264 zero$
266 /* SF bug 1045920 
267  * This case is fixed in compar.lisp revision 1.76.
268  * Adding some more examples.
269  */
271 (assume(a > 1, b > 1),0);
274 sign(a+b-2);
275 pos;
276 sign(2*a+b-3);
277 pos;
278 sign(2*a+b-4);
279 pnz;
281 (forget(a > 1, b > 1),0);
284 (assume(a < -1, b < -1),0);
287 sign(a+b+2);
288 neg;
289 sign(2*a+b+3);
290 neg;
291 sign(2*a+b+4);
292 pnz;
294 (forget(x < -1, y < -1),0);
297 /* SF bug 1724592  */
299 (aaa : 'bbb, bbb : 'ccc, ccc : 23.5,0);
302 sign(1.0*aaa);
303 pnz$
305 sign(1.0*bbb);
306 pnz$
308 (remvalue(aaa, bbb, ccc),0);
311 assume(x32 > 3/2);
312 [x32 > 3/2];
314 kill(all);
315 done;
317 assume(x32 < 1);
318 [x32 < 1];
320 /* [ 1981623 ] wrong sign of sqrt() */
321 (assume(xx >= 0, xx <= 1), 0);
324 sqrt(a/(xx-1)^2);
325 sqrt(a)/(1-xx);
328 /*****************************************************************************
330  Add tests for the function $csign
332  First: We repeat all tests which give a correct result for $sign.
333         The tests which are expected to fail are commented out.
335 ******************************************************************************/
337 (kill(all),0);
340 /* numbers and constants */
342 csign(minf);
343 neg$
345 csign(-1);
346 neg$
348 csign(-1.0);
349 neg$
351 csign(-1.0b0);
352 neg$
354 csign(0);
355 zero$
357 csign(0.0);
358 zero$
360 csign(0.0b0);
361 zero$
363 csign(1);
364 pos$
366 csign(1.0);
367 pos$
369 csign(1.0b0);
370 pos$
372 csign(inf);
373 pos$
375 csign(%pi);
376 pos$
378 csign(%e);
379 pos$
381 csign(%phi);
382 pos$
384 /* polynomials */
386 csign(x);
387 pnz$
389 csign(x^2);
392 csign(x^3);
393 pnz$
395 csign(x^4);
398 csign(x^2 + x);
399 pnz$
401 /* This is expected to be wrong
402 csign(x^2 + x + 42);
403 pos$
406 csign(x^2 + sqrt(5) + 101);
407 pos$
409 csign(%pi * x^2 + sqrt(5) + 101);
410 pos$
412 csign((sqrt(97) - 1) * x^2 + sqrt(5) + 101);
413 pos$
415 /* This is expected to be wrong
416 csign(-x^2 + x - 42);
417 neg$
420 csign(x^2 - 2 * x + 1);
423 csign(-x^2 + 2 * x - 1);
426 csign(x+y);
427 pnz$
429 csign(x^2 + 2 * x * y + y^2);
432 /* This is expected to be wrong.
433 csign(x^2 + 2 * x * y + y^2 + 1);
434 pos$
437 csign((x+y)^2 + (z-x)^2);
440 csign(sqrt(2) * (x+y)^2 + %e * (z-x)^2);
443 csign(-(x+y)^2 - (z-x)^2);
446 csign(-(x+y)^2 - (z-x)^2 - %pi);
447 neg$
449 csign(-sqrt(2) * (x+y)^2 - %phi * (z-x)^2 - %pi);
450 neg$
453 /* rational */
455 csign(1/x);
458 csign(1/(x-1));
461 csign(1/x + 1);
462 pnz$
464 csign(x/(1+x^2));
465 pnz$
467 /* This is expected to be wrong.
468 csign(1 + x/(1+x^2));
469 pos$
472 csign((1+x^2)/x);
475 /* assumptions */
477 (assume(a < b, b < c, c < d),0);
480 csign(b-a);
481 pos$
483 csign(a-b);
484 neg$
486 csign(c-a);
487 pos$
489 csign(a-c);
490 neg$
492 csign(d-b);
493 pos$
495 csign(b-d);
496 neg$
498 csign(7*(c-a) + %pi * (d-b));
499 pos$
501 csign(-7*(c-a) - %pi * (d-b));
502 neg$
504 csign((b-a) * (d-a));
505 pos$
507 csign((b-a)/(c-b));
508 pos$
510 (forget(a < b, b < c, c < d),0);
513 /* algebraic */
515 csign(sqrt(x));
518 csign(sqrt(x^2 + 1));
519 pos$
521 csign(sqrt(a) + sqrt(b));
524 csign(x^(1/3));
525 pnz$
527 csign(x^(1/4));
530 csign(x^(1/4) + 1);
531 pos$
533 csign(-(x^(1/4) + 1));
534 neg$
536 /* exp-like */
538 csign(cos(x));
539 pnz$
541 /* This is expected to be wrong.
542 csign(cos(x) + 42);
543 pos$
546 /* This is expected to be wrong.
547 csign(sin(x) - 42);
548 neg$
551 csign(cosh(x));
552 pos$
554 /* This is exprected to be wrong.
555 csign(cosh(x)-1);
559 csign(sinh(x));
560 pnz$
562 csign(tanh(x));
563 pnz$
565 csign(exp(x));
566 pos$
568 csign(exp(-x^2));
569 pos$
571 csign(exp(-x) - 1);
572 pnz$
574 csign(exp(-x) + 1);
575 pos$
577 /* log-like */
579 /* This is expected to be wrong.
580 csign(acos(x));
584 csign(asin(x));
585 pnz$
587 csign(atan(x));
588 pnz$
590 csign(log(x));
591 complex$
593 (assume(x > 0),0);
596 csign(log(x));
597 pnz$
599 (forget(x > 0),0);
602 (assume(x >= 1),0);
605 csign(log(x));
608 (forget(x >= 1),0);
611 /* This is expected to be wrong.
612 csign(acosh(x));
616 csign(asinh(x));
617 pnz$
619 csign(tanh(x));
620 pnz$
622 /* SF bug 798571 */
624 csign(sqrt(2)/2 - 1/sqrt(2));
625 zero$
627 /* SF bug 1045920 */
629 /* 
631 (assume(a > 1, b > 1),0);
634 csign(a + b -2);
635 pos$
637 (forget(a > 1, b > 1),0);
642 /* SF bug 1724592  */
644 (aaa : 'bbb, bbb : 'ccc, ccc : 23.5,0);
647 csign(1.0*aaa);
648 pnz$
650 csign(1.0*bbb);
651 pnz$
653 (remvalue(aaa, bbb, ccc),0);
656 assume(x32 > 3/2);
657 [x32 > 3/2];
659 kill(all);
660 done;
662 assume(x32 < 1);
663 [x32 < 1];
665 /******************************************************************************
666   Second: $csign with complex expressions.
667 ******************************************************************************/
669 declare(n,integer,x,real,j,imaginary,z,complex);
670 done;
672 /* We test the constants. UND and IND do not give a result, but an error. */
673 map(csign, [%e,%gamma,%phi,%i, minf,inf,infinity]);
674 [pos,pos,pos,imaginary,neg,pos,complex];
676 /* Symbols declcared as integeger, real, imaginary or complex */
677 map(csign, [n,x,j,z]);
678 [pnz,pnz,imaginary,complex];
680 /* Some arithmetic with pure imaginary numbers and symbols */
682 map(csign,[%i,sqrt(-1),10*%i,x*%i,%i^2,%i^3,%i^4,%i^5]);
683 [imaginary,imaginary,imaginary,imaginary,neg,imaginary,pos,imaginary];
685 map(csign,[j,sqrt(-1),10*j,x*j,j^2,j^3,j^4,j^5]);
686 [imaginary,imaginary,imaginary,imaginary,nz,imaginary,pz,imaginary];
688 /* negative base and half integral exponent */
689 map(csign,[(-1)^(1/2),(-1)^(3/2),(-1)^(5/2), (-1)^(7/2), (-1)^(9/2)]);
690 [imaginary,imaginary,imaginary,imaginary,imaginary];
692 /* the same with an negative expression */
693 (assume(xneg < 0, xpos>0),done);
694 done;
695 map(csign,[(xneg)^(1/2),(xneg)^(3/2),(xneg)^(5/2),(xneg)^(7/2)]);
696 [imaginary,imaginary,imaginary,imaginary];
698 map(csign,[(-xpos)^(1/2),(-xpos)^(3/2),(-xpos)^(5/2),(-xpos)^(7/2)]);
699 [imaginary,imaginary,imaginary,imaginary];
701 map(csign,[(-1)^xpos, (-1)^xneg]);
702 [complex,complex];
704 map(sign,[(-1)^xpos, (-1)^xneg]);
705 [pn,pn];
707 /* Expressions with an addition */
709 csign(x+%i*y);
710 complex;
711 csign((x+%i*y)^2);
712 complex;
713 csign((x+%i*y)^(1/2));
714 complex;
716 csign((a+x+%i*y)/(b-y*%i));
717 complex;
719 /* More expressions */
721 csign(1/z);
722 complex;
723 csign(1/j);
724 imaginary;
725 csign(10*a+c/z);
726 complex;
727 csign(10*a+c/j);
728 complex;
729 csign((10*a+(c/j)^2)^n);
730 pnz;
731 csign((10*a+(c/j)^3)^n);
732 complex;
734 /* This does not work correctly. 
735    The answer complex is not really wrong, but could be better.
736    To achieve this we have first to improve the function rectform. */
738 csign((1+%i)*(1-%i));
739 complex; /* shoule be pos */
741 csign(expand((1+%i)*(1-%i)));
742 pos; /* after expansion correct */
744 /* Functions which are declared to be complex give the sign $complex */
746 csign(conjugate(z));
747 complex;
748 csign(conjugate(x)); /* x is real */
749 pnz;
751 declare(f,complex);
752 done;
753 csign(f(x));
754 complex;
756 /* realpart and imagpart are real valued */
758 csign(realpart(z));
759 pnz;
760 csign(imagpart(z));
761 pnz;
764  * Examples for assumptions with abs(x)<a, a is positive
766  */
768 kill(all);
769 done;
771 assume(abs(x)<1);
772 [abs(x)<1];
774 sign(1-x);
775 pos;
776 sign(2-x);
777 pos;
778 sign(x-1);
779 neg;
780 sign(x-2);
781 neg;
783 forget(abs(x)<1);
784 [abs(x)<1];
786 facts();
789 assume(a>0,abs(x)<a);
790 [a>0,a>abs(x)];
792 sign(a-x);
793 pos;
794 sign(x-a);
795 neg;
797 forget(abs(x)<a);
798 [a>abs(x)];
800 facts();
801 [a>0];
803 assume(a*abs(x)<1);
804 [a*abs(x)<1];
806 sign(1/a-x);
807 pos;
808 sign(x-1/a);
809 neg;
811 forget(a*abs(x)<1);
812 [a*abs(x)<1];
814 assume(abs(x)<2*a+1);
815 [2*a-abs(x)+1>0];
817 sign(2*a+1-x);
818 pos;
819 sign(2*a+1+x);
820 pos;
821 sign(a*(2*a+1-x));
822 pos;
824 forget(abs(x)<2*a+1);
825 [2*a-abs(x)+1>0];
827 facts();
828 [a>0];
830 assume(b>0,b<1);
831 [b>0,b<1];
833 assume(abs(x)<b);
834 [b>abs(x)];
836 is(x<1);
837 true;
838 sign(1-x);
839 pos;
840 sign(x-1);
841 neg;
843 forget(abs(x)<b);
844 [b>abs(x)];
846 facts();
847 [a>0,b>0,1>b];
849 assume(sin(abs(x)) < 1);
850 [sin(abs(x))<1];
852 sign(1-sin(x));
853 pos;
854 sign(2-sin(x));
855 pos;
856 sign(sin(x)-1);
857 neg;
858 sign(sin(x)-2);
859 neg;
861 forget(sin(abs(x)) < 1);
862 [sin(abs(x))<1];
864 assume(cos(abs(x)) < 1);
865 [cos(abs(x))<1];
867 sign(1-cos(x));
868 pos;
869 sign(2-cos(x));
870 pos;
871 sign(cos(x)-1);
872 neg;
873 sign(cos(x)-2);
874 neg;
876 forget(cos(abs(x)) < 1);
877 [cos(abs(x))<1];
879 assume(abs(sin(x)) < 1);
880 [abs(sin(x))<1];
882 sign(1-sin(x));
883 pos;
884 sign(2-sin(x));
885 pos;
886 sign(sin(x)-1);
887 neg;
888 sign(sin(x)-2);
889 neg;
891 forget(abs(sin(x)) < 1);
892 [abs(sin(x))<1];
894 assume(abs(cos(x)) < 1);
895 [abs(cos(x))<1];
897 sign(1-cos(x));
898 pos;
899 sign(2-cos(x));
900 pos;
901 sign(cos(x)-1);
902 neg;
903 sign(cos(x)-2);
904 neg;
906 forget(abs(cos(x)) <1);
907 [abs(cos(x))<1];
909 csign(log((1 + %i)/sqrt(2)));
910 imaginary$
912 /* Examples to show that learn-numer works
913  * Related bug report:
914  * Bug ID: 2477795 - "assume":problems with fractions or multiples of %pi and %e
915  */
916 kill(all);
917 done;
918 assume(a>0,a<%pi/2);
919 [a>0,%pi/2>a];
921 is(a>%pi/2);
922 false;
923 is(a>%pi);
924 false;
926 assume(b>0,b<2*%pi);
927 [b>0, 2*%pi>b];
928 is(b>3*%pi);
929 false;
931 /* An example involving a numerical constant, the value of a function
932  * and the abs function.
933  * This example no longer works because of revision 1.62 of compar.lisp
934  */
935 assume(abs(x) < sin(1)+%e/2);
936 [sin(1)+%e/2>abs(x)];
937 is(x<2*%e);
938 true;
939 is(x>-2*%e);
940 true;
941 (forget(abs(x)<sin(1)+%e/2),done);
942 done;
944 /* Bug ID: 2876382 - sign(a+b+sin(1)) unknown */
945 (assume(a>0,b>0),done);
946 done;
947 sign(a+b+sin(1));
948 pos;
949 (forget(a>0,b>0),done);
950 done;
952 /* Bug ID: 2184396 - Wrong factorization of sqrt()
953  * This is the example from the bug report which has triggered the bug in sign
954  *      sqrt(1-(2-sqrt(2))/x * ((2+sqrt(2))/x-1));
955  * The expression has factored wrongly. This example is now correct.
956  */
957 sign(1-(1+sqrt(2))*x);
958 'pnz;
959 sign(1-(1+sqrt(2))/x);
960 'pnz;
962 /* Bug ID: 1038624 - askinteger ignores asksign database
963  * With revison 1.64 of compar.lisp code has been added, which looks for
964  * integer and noninteger facts into the database.
965  */
966 (assume(equal(a,0), equal(b,2), equal(c,1/3), equal(d,1.5), equal(e,3.0b0)),
967  done);
968 done;
970 map(askinteger, [a, b, 2*b, 2+b, c, d, e]);
971 [yes, yes, yes, yes, no, no, no];
974 (forget(equal(a,0), equal(b,2), equal(c,1/3), equal(d,1.5), equal(e,3.0b0)), 
975  done);
976 done;
978 /* Bug ID: 3376603 - sign of declared imaginary */
979 declare(f,imaginary, g,complex);
980 done$
981 csign(f(x));
982 imaginary$
983 csign(g(x));
984 complex$
985 kill(f,g);
986 done$
988 /* Check adding new equaltiy does not make old inequality disappear */
989 kill(all);
990 done;
992 assume(notequal(a,b));
993 [notequal(a, b)];
995 is(equal(a,b));
996 false;
998 (assume(equal(a, x+y)), 0);
1001 is(equal(a,b));
1002 false;
1004 /* Check fix for bug 2547 (declare constant messes up sign calculations) */
1005 (declare (x, constant), declare (y, constant), assume (x > y), is (x>y));
1006 true$
1008 /* facts in assume database not cleaned up by 'sign' */
1010 (kill (foo), foo : %e^(abs(uu)+uu)*(uu/abs(uu)+1)+%e^(abs(uu)-uu)*(uu/abs(uu)-1), 0);
1013 block ([bar, baz], bar : copy (facts (initial)), is (equal (foo, 0)), baz : facts (initial), is (bar = baz));
1014 true;
1016 /* tnx to Barton Willis for the next couple of tests */
1018 map('sign,[sqrt(x),x]);
1019 [pz, pnz];
1021 (kill(buddy),
1022  buddy(p,q) := expand(if p >= 0 then q else q,0,0),
1023  buddy(sqrt(x),abs(x)));
1024 abs(x);
1026 /* Ensure that asksign1 deals correctly with squared expressions */
1027 (assume (notequal(n, 1)), 0);
1030 is ((n-1)^2 > 0);
1031 true$
1033 /* Here are some calls to asksign & askinteger -- these don't cause
1034  * an interactive prompt. Interactive examples are in rtest_ask.mac.
1035  */
1037 map(askinteger,[0,1/2,sqrt(17)]);
1038 [yes,no,no]$
1040 /* Known constants */
1041 map(askinteger,[%pi,%e,%phi,%gamma,%i]);
1042 [no,no,no,no,no]$
1044 map(asksign,[%pi,%e,%phi,%gamma,inf,minf]);
1045 [pos,pos,pos,pos,pos,neg]$
1047 errcatch(asksign(%i));
1048 []$ /* argument cannot be imaginary. */
1050 errcatch(asksign(infinity));
1051 []$ /* sign of infinity is undefined. */
1053 /* Odd functions */
1055 (declare(o, oddfun),0);
1058 (assume(equal(q, 0)),0);
1061 sign(o(q));
1062 zero$
1064 (remove(o, oddfun),0);
1067 (forget(equal(q, 0)),0);
1070 /* Increasing and decreasing functions */
1072 (declare(i, increasing, d, decreasing),0);
1075 (assume(r > q),0);
1078 is(i(r) > i(q));
1079 true$
1081 is(d(r) < d(q));
1082 true$
1084 (remove(i, increasing, d, decreasing),0);
1087 (forget(r > q), 0);
1090 /* Increasing and decreasing odd functions */
1092 (declare(i, [oddfun, increasing], d, [oddfun, decreasing]),0);
1095 (assume(q < 0, r > 0),0);
1098 sign(i(q));
1099 neg$
1101 sign(i(r));
1102 pos$
1104 sign(d(q));
1105 pos$
1107 sign(d(r));
1108 neg$
1110 (remove(i, [oddfun, increasing], d, [oddfun, decreasing]),0);
1113 (forget(q < 0, r > 0),0);
1116 /* Bug #3109: is(sin(x) <= 1) returns "unknown", is(sin(x) <= 1.00001) returns "true" */
1117 (kill(all),0);
1119 is(sin(x) <= 1);
1120 true$
1121 is(cos(x) <= 1);
1122 true$
1123 is(sin(x) >= -1);
1124 true$
1125 is(cos(x) >= -1);
1126 true$
1127 sign(sin(x)+1);
1129 sign(cos(x)+1);
1131 sign(sin(x)-1);
1133 sign(cos(x)-1);
1136 /* Assumptions and queries involving multiple unknowns */
1137 assume(-2*x*y>10);
1138 [x*y<-5]$
1139 is(10*x*y<-50);
1140 true$
1141 assume(3*x*y>0);
1142 [inconsistent]$
1143 assume(notequal(2*a*b,10));
1144 [notequal(a*b,5)]$
1145 is(equal(10*a*b,50));
1146 false$
1147 (kill(all),0);
1150 /* Exponents in inequality assumptions and queries  */
1151 assume(x^3/y>=0);
1152 [x*y>=0]$
1153 sign(y^3/x);
1155 (declare(e, even, o, odd), 0);
1157 assume(a^o>0);
1158 [a>0]$
1159 sign(-2*a^o);
1160 neg$
1161 assume(b^(e+1)<0);
1162 [b<0]$
1163 sign(-b^(e+1));
1164 pos$
1165 assume(c^m/d^n<=0);
1166 [c^m*d^n<=0]$
1167 assume(f^(1/3)*g^h<0);
1168 [f*g^h<0]$
1169 (kill(all),0);
1172 /* The csign of a product with a complex factor and a zero factor used
1173  * to depend on the order of the factors: if the zero came first then
1174  * the sign was zero, but if the complex came first then the sign was
1175  * complex.
1176  */
1178 (declare (a, complex), assume (equal (b, 0)), 0)$
1180 csign (a * b);
1181 zero;
1182 (remove (a, complex), forget (equal (b, 0)), 0)$
1185 (declare (b, complex), assume (equal (a, 0)), 0)$
1187 csign (a * b);
1188 zero;
1189 (remove (b, complex), forget (equal (a, 0)), 0)$