1 Star 0 Fork 0

zhouxs1023/eigenmath_pratt

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
power.cpp 8.51 KB
一键复制 编辑 原始数据 按行查看 历史
Calin Barbat 提交于 2018-02-24 10:52 . Initial commit.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
/* Power function
Input: push Base
push Exponent
Output: Result on stack
*/
#include "stdafx.h"
#include "defs.h"
void
eval_power(void)
{
push(cadr(p1));
eval();
push(caddr(p1));
eval();
power();
}
void
power(void)
{
save();
yypower();
restore();
}
void
yypower(void)
{
int n;
p2 = pop();
p1 = pop();
// both base and exponent are rational numbers?
if (isrational(p1) && isrational(p2)) {
push(p1);
push(p2);
qpow();
return;
}
// both base and exponent are either rational or double?
if (isnum(p1) && isnum(p2)) {
push(p1);
push(p2);
dpow();
return;
}
if (istensor(p1)) {
power_tensor();
return;
}
if (p1 == symbol(E) && car(p2) == symbol(LOG)) {
push(cadr(p2));
return;
}
if (p1 == symbol(E) && isdouble(p2)) {
push_double(exp(p2->u.d));
return;
}
// 1 ^ a -> 1
// a ^ 0 -> 1
if (equal(p1, one) || iszero(p2)) {
push(one);
return;
}
// a ^ 1 -> a
if (equal(p2, one)) {
push(p1);
return;
}
// (a * b) ^ c -> (a ^ c) * (b ^ c)
if (car(p1) == symbol(MULTIPLY)) {
p1 = cdr(p1);
push(car(p1));
push(p2);
power();
p1 = cdr(p1);
while (iscons(p1)) {
push(car(p1));
push(p2);
power();
multiply();
p1 = cdr(p1);
}
return;
}
// (a ^ b) ^ c -> a ^ (b * c)
if (car(p1) == symbol(POWER)) {
push(cadr(p1));
push(caddr(p1));
push(p2);
multiply();
power();
return;
}
// (a + b) ^ n -> (a + b) * (a + b) ...
if (expanding && isadd(p1) && isnum(p2)) {
push(p2);
n = pop_integer();
// this && n != 0x80000000 added by DDC
// as it's not always the case that 0x80000000
// is negative
if (n > 1 && ((unsigned int)n) != 0x80000000) {
power_sum(n);
return;
}
}
// sin(x) ^ 2n -> (1 - cos(x) ^ 2) ^ n
if (trigmode == 1 && car(p1) == symbol(SIN) && iseveninteger(p2)) {
push_integer(1);
push(cadr(p1));
cosine();
push_integer(2);
power();
subtract();
push(p2);
push_rational(1, 2);
multiply();
power();
return;
}
// cos(x) ^ 2n -> (1 - sin(x) ^ 2) ^ n
if (trigmode == 2 && car(p1) == symbol(COS) && iseveninteger(p2)) {
push_integer(1);
push(cadr(p1));
sine();
push_integer(2);
power();
subtract();
push(p2);
push_rational(1, 2);
multiply();
power();
return;
}
// complex number? (just number, not expression)
if (iscomplexnumber(p1)) {
// integer power?
// n will be negative here, positive n already handled
if (isinteger(p2)) {
// / \ n
// -n | a - ib |
// (a + ib) = | -------- |
// | 2 2 |
// \ a + b /
push(p1);
conjugate();
p3 = pop();
push(p3);
push(p3);
push(p1);
multiply();
divide();
push(p2);
negate();
power();
return;
}
// noninteger or floating power?
if (isnum(p2)) {
#if 1 // use polar form
push(p1);
mag();
push(p2);
power();
push_integer(-1);
push(p1);
arg();
push(p2);
multiply();
push(symbol(PI));
divide();
power();
multiply();
#else // use exponential form
push(p1);
mag();
push(p2);
power();
push(symbol(E));
push(p1);
arg();
push(p2);
multiply();
push(imaginaryunit);
multiply();
power();
multiply();
#endif
return;
}
}
if (simplify_polar())
return;
push_symbol(POWER);
push(p1);
push(p2);
list(3);
}
//-----------------------------------------------------------------------------
//
// Compute the power of a sum
//
// Input: p1 sum
//
// n exponent
//
// Output: Result on stack
//
// Note:
//
// Uses the multinomial series (see Math World)
//
// n n! n1 n2 nk
// (a1 + a2 + ... + ak) = sum (--------------- a1 a2 ... ak )
// n1! n2! ... nk!
//
// The sum is over all n1 ... nk such that n1 + n2 + ... + nk = n.
//
//-----------------------------------------------------------------------------
// first index is the term number 0..k-1, second index is the exponent 0..n
#define A(i, j) frame[(i) * (n + 1) + (j)]
void
power_sum(int n)
{
int *a, i, j, k;
// number of terms in the sum
k = length(p1) - 1;
// local frame
push_frame(k * (n + 1));
// array of powers
p1 = cdr(p1);
for (i = 0; i < k; i++) {
for (j = 0; j <= n; j++) {
push(car(p1));
push_integer(j);
power();
A(i, j) = pop();
}
p1 = cdr(p1);
}
push_integer(n);
factorial();
p1 = pop();
a = (int *) malloc(k * sizeof (int));
if (a == NULL)
stop("malloc failure");
push(zero);
multinomial_sum(k, n, a, 0, n);
free(a);
pop_frame(k * (n + 1));
}
//-----------------------------------------------------------------------------
//
// Compute multinomial sum
//
// Input: k number of factors
//
// n overall exponent
//
// a partition array
//
// i partition array index
//
// m partition remainder
//
// p1 n!
//
// A factor array
//
// Output: Result on stack
//
// Note:
//
// Uses recursive descent to fill the partition array.
//
//-----------------------------------------------------------------------------
void
multinomial_sum(int k, int n, int *a, int i, int m)
{
int j;
if (i < k - 1) {
for (j = 0; j <= m; j++) {
a[i] = j;
multinomial_sum(k, n, a, i + 1, m - j);
}
return;
}
a[i] = m;
// coefficient
push(p1);
for (j = 0; j < k; j++) {
push_integer(a[j]);
factorial();
divide();
}
// factors
for (j = 0; j < k; j++) {
push(A(j, a[j]));
multiply();
}
add();
}
// exp(n/2 i pi) ?
// p2 is the exponent expression
// clobbers p3
int
simplify_polar(void)
{
int n;
n = isquarterturn(p2);
switch(n) {
case 0:
break;
case 1:
push_integer(1);
return 1;
case 2:
push_integer(-1);
return 1;
case 3:
push(imaginaryunit);
return 1;
case 4:
push(imaginaryunit);
negate();
return 1;
}
if (car(p2) == symbol(ADD)) {
p3 = cdr(p2);
while (iscons(p3)) {
n = isquarterturn(car(p3));
if (n)
break;
p3 = cdr(p3);
}
switch (n) {
case 0:
return 0;
case 1:
push_integer(1);
break;
case 2:
push_integer(-1);
break;
case 3:
push(imaginaryunit);
break;
case 4:
push(imaginaryunit);
negate();
break;
}
push(p2);
push(car(p3));
subtract();
exponential();
multiply();
return 1;
}
return 0;
}
#if SELFTEST
static const char *s[] = {
"2^(1/2)",
"2^(1/2)",
"2^(3/2)",
"2*2^(1/2)",
"(-2)^(1/2)",
"i*2^(1/2)",
"3^(4/3)",
"3*3^(1/3)",
"3^(-4/3)",
"1/(3*3^(1/3))",
"3^(5/3)",
"3*3^(2/3)",
"3^(2/3)-9^(1/3)",
"0",
"3^(10/3)",
"27*3^(1/3)",
"3^(-10/3)",
"1/(27*3^(1/3))",
"(1/3)^(10/3)",
"1/(27*3^(1/3))",
"(1/3)^(-10/3)",
"27*3^(1/3)",
"27^(2/3)",
"9",
"27^(-2/3)",
"1/9",
"102^(1/2)",
"2^(1/2)*3^(1/2)*17^(1/2)",
"32^(1/3)",
"2*2^(2/3)",
"9999^(1/2)",
"3*11^(1/2)*101^(1/2)",
"10000^(1/3)",
"10*2^(1/3)*5^(1/3)",
"sqrt(1000000)",
"1000",
"sqrt(-1000000)",
"1000*i",
"sqrt(2^60)",
"1073741824",
// this is why we factor irrationals
"6^(1/3) 3^(2/3)",
"3*2^(1/3)",
// inverse of complex numbers
"1/(2+3*i)",
"2/13-3/13*i",
"1/(2+3*i)^2",
"-5/169-12/169*i",
"(-1+3i)/(2-i)",
"-1+i",
// other
"(0.0)^(0.0)",
"1",
"(-4.0)^(1.5)",
"-8*i",
"(-4.0)^(0.5)",
"2*i",
"(-4.0)^(-0.5)",
"-0.5*i",
"(-4.0)^(-1.5)",
"0.125*i",
// more complex number cases
"(1+i)^2",
"2*i",
"(1+i)^(-2)",
"-1/2*i",
"(1+i)^(1/2)",
"(-1)^(1/8)*2^(1/4)",
"(1+i)^(-1/2)",
"-(-1)^(7/8)/(2^(1/4))",
"(1+i)^(0.5)",
"1.09868+0.45509*i",
"(1+i)^(-0.5)",
"0.776887-0.321797*i",
// test cases for simplification of polar forms, counterclockwise
"exp(i*pi/2)",
"i",
"exp(i*pi)",
"-1",
"exp(i*3*pi/2)",
"-i",
"exp(i*2*pi)",
"1",
"exp(i*5*pi/2)",
"i",
"exp(i*3*pi)",
"-1",
"exp(i*7*pi/2)",
"-i",
"exp(i*4*pi)",
"1",
"exp(A+i*pi/2)",
"i*exp(A)",
"exp(A+i*pi)",
"-exp(A)",
"exp(A+i*3*pi/2)",
"-i*exp(A)",
"exp(A+i*2*pi)",
"exp(A)",
"exp(A+i*5*pi/2)",
"i*exp(A)",
"exp(A+i*3*pi)",
"-exp(A)",
"exp(A+i*7*pi/2)",
"-i*exp(A)",
"exp(A+i*4*pi)",
"exp(A)",
// test cases for simplification of polar forms, clockwise
"exp(-i*pi/2)",
"-i",
"exp(-i*pi)",
"-1",
"exp(-i*3*pi/2)",
"i",
"exp(-i*2*pi)",
"1",
"exp(-i*5*pi/2)",
"-i",
"exp(-i*3*pi)",
"-1",
"exp(-i*7*pi/2)",
"i",
"exp(-i*4*pi)",
"1",
"exp(A-i*pi/2)",
"-i*exp(A)",
"exp(A-i*pi)",
"-exp(A)",
"exp(A-i*3*pi/2)",
"i*exp(A)",
"exp(A-i*2*pi)",
"exp(A)",
"exp(A-i*5*pi/2)",
"-i*exp(A)",
"exp(A-i*3*pi)",
"-exp(A)",
"exp(A-i*7*pi/2)",
"i*exp(A)",
"exp(A-i*4*pi)",
"exp(A)",
};
void
test_power(void)
{
test(__FILE__, s, sizeof s / sizeof (char *));
}
#endif
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/zhouxs1023/eigenmath_pratt.git
git@gitee.com:zhouxs1023/eigenmath_pratt.git
zhouxs1023
eigenmath_pratt
eigenmath_pratt
master

搜索帮助