Browse Source

pow(a,b) function derivative: special case also for a=const

with enhnaced efficiency
introduce TRACE and TRACE1 for debugging
pre-master-46
Holger Vogt 6 years ago
parent
commit
c7e9c3884e
  1. 56
      src/spicelib/parser/inpptree.c

56
src/spicelib/parser/inpptree.c

@ -314,6 +314,12 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
* = pow(a,b) * b * D(a)/(signum(a) * abs(a))
* = pow(a, b-1) * b * D(a) / signum(a)
* = pwr(a, b-1) * b * D(a)
*
* when D(a) == 0, then
*
* D(pow(a,b))
* = pow(a,b) * (D(b)*log(abs(a)) + b*D(a)/a)
* = pow(a,b) * D(b)*log(abs(a))
*/
#define a p->left
#define b p->right
@ -325,7 +331,14 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
mkf(PTF_PWR,
mkb(PT_COMMA, a, mkcon(b->constant - 1.0)))),
arg1);
} else {
}
else if (a->type == PT_CONSTANT){
arg2 = PTdifferentiate(b, varnum);
newp = mkb(PT_TIMES,
mkf(PTF_POW, mkb(PT_COMMA, a, b)),
mkb(PT_TIMES, arg2, mkf(PTF_LOG, mkf(PTF_ABS, a))));
}
else {
arg1 = PTdifferentiate(a, varnum);
arg2 = PTdifferentiate(b, varnum);
newp = mkb(PT_TIMES,
@ -441,8 +454,8 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
mkcon(EXPMAX),
mkf(PTF_EXP, p->left)));
#ifdef TRACE
printf("debug, %s, returns; ", __func__);
#ifdef TRACE1
printf("debug exp, %s, returns; ", __func__);
printTree(arg1);
printf("\n");
#endif
@ -544,7 +557,7 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
INPparseNode *a = p->left->left;
INPparseNode *b = p->left->right;
int comparison = (p->funcnum == PTF_MIN) ? PTF_LT0 : PTF_GT0;
#ifdef TRACE
#ifdef TRACE1
printf("debug: %s, PTF_MIN: ", __func__);
printTree(p);
printf("\n");
@ -560,7 +573,7 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
mkb(PT_COMMA,
PTdifferentiate(a, varnum),
PTdifferentiate(b, varnum)));
#ifdef TRACE
#ifdef TRACE1
printf("debug, %s, returns; ", __func__);
printTree(newp);
printf("\n");
@ -589,6 +602,12 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
* = pow(a,b) * b * D(a)/(signum(a) * abs(a))
* = pow(a, b-1) * b * D(a) / signum(a)
* = pwr(a, b-1) * b * D(a)
*
* when D(a) == 0, then
*
* D(pow(a,b))
* = pow(a,b) * (D(b)*log(abs(a)) + b*D(a)/a)
* = pow(a,b) * D(b)*log(abs(a))
*/
{
/*
@ -606,11 +625,12 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
mkf(PTF_PWR,
mkb(PT_COMMA, a, mkcon(b->constant - 1)))),
arg1);
#ifdef TRACE
printf("pow, %s, returns; ", __func__);
printTree(newp);
printf("\n");
#endif
} else if (a->type == PT_CONSTANT) {
arg2 = PTdifferentiate(b, varnum);
newp = mkb(PT_TIMES,
mkf(PTF_POW, mkb(PT_COMMA, a, b)),
mkb(PT_TIMES, arg2, mkf(PTF_LOG, mkf(PTF_ABS, a))));
} else {
arg1 = PTdifferentiate(a, varnum);
arg2 = PTdifferentiate(b, varnum);
@ -624,6 +644,11 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
arg2,
mkf(PTF_LOG, mkf(PTF_ABS, a)))));
}
#ifdef TRACE
printf("debug pow, %s, returns; ", __func__);
printTree(newp);
printf("\n");
#endif
return mkfirst(newp, p);
#undef b
#undef a
@ -668,11 +693,7 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
mkf(PTF_POW,
mkb(PT_COMMA, a, mkcon(b->constant - 1.0)))),
arg1);
#ifdef TRACE
printf("pwr, %s, returns; ", __func__);
printTree(newp);
printf("\n");
#endif
} else {
arg1 = PTdifferentiate(a, varnum);
arg2 = PTdifferentiate(b, varnum);
@ -682,6 +703,11 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
mkb(PT_TIMES, b, mkb(PT_DIVIDE, arg1, a)),
mkb(PT_TIMES, arg2, mkf(PTF_LOG, mkf(PTF_ABS, a)))));
}
#ifdef TRACE
printf("debug pwr, %s, returns; ", __func__);
printTree(newp);
printf("\n");
#endif
return mkfirst(newp, p);
#undef b
#undef a

Loading…
Cancel
Save