1 // Symbolic multiplication
6 extern void append(void);
7 static void parse_p1(void);
8 static void parse_p2(void);
9 static void __normalize_radical_factors(int);
15 stop("escape key stop");
16 if (isnum(stack
[tos
- 2]) && isnum(stack
[tos
- 1]))
37 // is either operand zero?
39 if (iszero(p1
) || iszero(p2
)) {
44 // is either operand a sum?
46 if (expanding
&& isadd(p1
)) {
59 if (expanding
&& isadd(p2
)) {
72 // scalar times tensor?
74 if (!istensor(p1
) && istensor(p2
)) {
77 scalar_times_tensor();
81 // tensor times scalar?
83 if (istensor(p1
) && !istensor(p2
)) {
86 tensor_times_scalar();
92 if (car(p1
) == symbol(MULTIPLY
))
100 if (car(p2
) == symbol(MULTIPLY
))
108 // handle numerical coefficients
110 if (isnum(car(p1
)) && isnum(car(p2
))) {
116 } else if (isnum(car(p1
))) {
119 } else if (isnum(car(p2
))) {
128 while (iscons(p1
) && iscons(p2
)) {
130 // if (car(p1)->gamma && car(p2)->gamma) {
131 // combine_gammas(h);
139 if (caar(p1
) == symbol(OPERATOR
) && caar(p2
) == symbol(OPERATOR
)) {
140 push_symbol(OPERATOR
);
152 switch (cmp_expr(p3
, p4
)) {
171 stop("internal error 2");
176 // push remaining factors, if any
188 // normalize radical factors
190 // example: 2*2(-1/2) -> 2^(1/2)
192 // must be done after merge because merge may produce radical
194 // example: 2^(1/2-a)*2^a -> 2^(1/2)
196 __normalize_radical_factors(h
);
198 // this hack should not be necessary, unless power returns a multiply
200 //for (i = h; i < tos; i++) {
201 // if (car(stack[i]) == symbol(MULTIPLY)) {
202 // multiply_all(tos - h);
208 for (i
= h
; i
< tos
; i
++) {
209 if (isadd(stack
[i
])) {
210 multiply_all(tos
- h
);
216 // n is the number of result factors on the stack
225 if (isrational(stack
[h
]) && equaln(stack
[h
], 1)) {
231 stack
[h
] = symbol(MULTIPLY
);
239 push_symbol(MULTIPLY
);
244 // Decompose a factor into base and power.
246 // input: car(p1) factor
248 // output: p3 factor's base
250 // p5 factor's power (possibly 1)
257 if (car(p3
) == symbol(POWER
)) {
263 // Decompose a factor into base and power.
265 // input: car(p2) factor
267 // output: p4 factor's base
269 // p6 factor's power (possibly 1)
276 if (car(p4
) == symbol(POWER
)) {
283 combine_factors(int h
)
296 } else if (car(p7
) == symbol(MULTIPLY
)) {
297 // power can return number * factor (i.e. -1 * i)
298 if (isnum(cadr(p7
)) && cdddr(p7
) == symbol(NIL
)) {
311 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
312 {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
313 {0,0,1,-6,-7,-8,-3,-4,-5,13,14,15,-16,9,10,11,-12},
314 {0,0,6,-1,-11,10,-2,-15,14,12,-5,4,-9,16,-8,7,-13},
315 {0,0,7,11,-1,-9,15,-2,-13,5,12,-3,-10,8,16,-6,-14},
316 {0,0,8,-10,9,-1,-14,13,-2,-4,3,12,-11,-7,6,16,-15},
317 {0,0,3,2,15,-14,1,11,-10,16,-8,7,13,12,-5,4,9},
318 {0,0,4,-15,2,13,-11,1,9,8,16,-6,14,5,12,-3,10},
319 {0,0,5,14,-13,2,10,-9,1,-7,6,16,15,-4,3,12,11},
320 {0,0,13,12,-5,4,16,-8,7,-1,-11,10,-3,-2,-15,14,-6},
321 {0,0,14,5,12,-3,8,16,-6,11,-1,-9,-4,15,-2,-13,-7},
322 {0,0,15,-4,3,12,-7,6,16,-10,9,-1,-5,-14,13,-2,-8},
323 {0,0,16,-9,-10,-11,-13,-14,-15,-3,-4,-5,1,-6,-7,-8,2},
324 {0,0,9,-16,8,-7,-12,5,-4,-2,-15,14,6,-1,-11,10,3},
325 {0,0,10,-8,-16,6,-5,-12,3,15,-2,-13,7,11,-1,-9,4},
326 {0,0,11,7,-6,-16,4,-3,-12,-14,13,-2,8,-10,9,-1,5},
327 {0,0,12,13,14,15,9,10,11,-6,-7,-8,-2,-3,-4,-5,-1}
333 combine_gammas(int h
)
336 n
= gp
[(int) p1
->gamma
][(int) p2
->gamma
];
350 multiply_noexpand(void)
359 // multiply n factors on stack
373 for (i
= 1; i
< n
; i
++) {
382 multiply_all_noexpand(int n
)
391 //-----------------------------------------------------------------------------
395 // Input: Dividend and divisor on stack
397 // Output: Quotient on stack
399 //-----------------------------------------------------------------------------
404 if (isnum(stack
[tos
- 2]) && isnum(stack
[tos
- 1]))
415 if (isnum(stack
[tos
- 1]))
426 if (isnum(stack
[tos
- 1]))
437 if (isnum(stack
[tos
- 1]))
456 negate_noexpand(void)
465 //-----------------------------------------------------------------------------
467 // Normalize radical factors
469 // Input: stack[h] Coefficient factor, possibly 1
471 // stack[h + 1] Second factor
473 // stack[tos - 1] Last factor
475 // Output: Reduced coefficent and normalized radicals (maybe)
477 // Example: 2*2^(-1/2) -> 2^(1/2)
479 // (power number number) is guaranteed to have the following properties:
481 // 1. Base is an integer
483 // 2. Absolute value of exponent < 1
485 // These properties are assured by the power function.
487 //-----------------------------------------------------------------------------
497 static int __is_radical_number(U
*);
500 __normalize_radical_factors(int h
)
504 // if coeff is 1 or floating then don't bother
506 if (isplusone(stack
[h
]) || isminusone(stack
[h
]) || isdouble(stack
[h
]))
509 // if no radicals then don't bother
511 for (i
= h
+ 1; i
< tos
; i
++)
512 if (__is_radical_number(stack
[i
]))
518 // ok, try to simplify
528 for (i
= h
+ 1; i
< tos
; i
++) {
530 if (isplusone(A
) || isminusone(A
))
533 if (!__is_radical_number(stack
[i
]))
536 BASE
= cadr(stack
[i
]);
537 EXPO
= caddr(stack
[i
]);
539 // exponent must be negative
541 if (!isnegativenumber(EXPO
))
544 // numerator divisible by BASE?
576 for (i
= h
+ 1; i
< tos
; i
++) {
581 if (!__is_radical_number(stack
[i
]))
584 BASE
= cadr(stack
[i
]);
585 EXPO
= caddr(stack
[i
]);
587 // exponent must be positive
589 if (isnegativenumber(EXPO
))
592 // denominator divisible by BASE?
603 // reduce denominator
618 // reconstitute the coefficient
631 __is_radical_number(U
*p
)
635 if (car(p
) == symbol(POWER
) && isnum(cadr(p
)) && isnum(caddr(p
)) && !isminusone(cadr(p
)))
641 //-----------------------------------------------------------------------------
644 // ((a,1/2*a),(1/2*a,1/3*a))
646 // Note that "a" is presumed to be a scalar. Is this correct?
648 // Yes, because "*" has no meaning if "a" is a tensor.
649 // To multiply tensors, "dot" or "outer" should be used.
651 // > dot(a,hilbert(2))
652 // dot(a,((1,1/2),(1/2,1/3)))
654 // In this case "a" could be a scalar or tensor so the result is not
657 //-----------------------------------------------------------------------------
687 "2^a*2^(3-a)", // symbolic exponents cancel
708 // ensure 1.0 is not discarded
720 test(__FILE__
, s
, sizeof s
/ sizeof (char *));