diff --git a/src/spicelib/parser/inpptree.c b/src/spicelib/parser/inpptree.c index 0d8bef123..4d2725837 100644 --- a/src/spicelib/parser/inpptree.c +++ b/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