parser/*.c: implement a signed power function `pwr' for controlled sources
This commit is contained in:
parent
7857a300ad
commit
91ab0a3c74
|
|
@ -123,10 +123,11 @@ void INPptPrint(char *str, IFparseTree * ptree);
|
|||
#define PTF_GE0 28
|
||||
#define PTF_LE0 29
|
||||
#define PTF_POW 30
|
||||
#define PTF_MIN 31
|
||||
#define PTF_MAX 32
|
||||
#define PTF_CEIL 33
|
||||
#define PTF_FLOOR 34
|
||||
#define PTF_PWR 31
|
||||
#define PTF_MIN 32
|
||||
#define PTF_MAX 33
|
||||
#define PTF_CEIL 34
|
||||
#define PTF_FLOOR 35
|
||||
|
||||
/* The following things are used by the parser -- these are the token types the
|
||||
* lexer returns.
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ PTeval(INPparseNode * tree, double gmin, double *res, double *vals)
|
|||
switch(tree->funcnum) {
|
||||
|
||||
case PTF_POW:
|
||||
case PTF_PWR:
|
||||
case PTF_MIN:
|
||||
case PTF_MAX:
|
||||
err = PTeval(tree->left->left, gmin, &r1, vals);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ static INPparseNode *mksnode(const char *string, void *ckt);
|
|||
static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum);
|
||||
|
||||
static void free_tree(INPparseNode *);
|
||||
static void printTree(INPparseNode *);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -167,6 +168,7 @@ static struct func {
|
|||
{ "ge0", PTF_GE0, (void(*)(void)) PTge0},
|
||||
{ "le0", PTF_LE0, (void(*)(void)) PTle0},
|
||||
{ "pow", PTF_POW, (void(*)(void)) PTpower},
|
||||
{ "pwr", PTF_PWR, (void(*)(void)) PTpwr},
|
||||
{ "min", PTF_MIN, (void(*)(void)) PTmin},
|
||||
{ "max", PTF_MAX, (void(*)(void)) PTmax},
|
||||
} ;
|
||||
|
|
@ -523,8 +525,6 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
|||
INPparseNode *b = p->left->right;
|
||||
int comparison = (p->funcnum == PTF_MIN) ? PTF_LT0 : PTF_GT0;
|
||||
#ifdef TRACE
|
||||
extern void printTree(INPparseNode *);
|
||||
|
||||
printf("debug: %s, PTF_MIN: ", __func__);
|
||||
printTree(p);
|
||||
printf("\n");
|
||||
|
|
@ -568,6 +568,11 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
|||
mkb(PT_POWER, p->left->left,
|
||||
mkcon(p->left->right->constant - 1))),
|
||||
arg1);
|
||||
#ifdef TRACE
|
||||
printf("pow, %s, returns; ", __func__);
|
||||
printTree(newp);
|
||||
printf("\n");
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* D(f^g) = D(exp(g*ln(f)))
|
||||
|
|
@ -587,6 +592,59 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
|||
return mkfirst(newp, p);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PTF_PWR:
|
||||
{
|
||||
/*
|
||||
pwr(a,b)
|
||||
p->left: ',' p->left->left: a p->left->right: b
|
||||
*/
|
||||
|
||||
if (p->left->right->type == PT_CONSTANT) {
|
||||
/*
|
||||
* f(a,b) = signum(a) * abs(a)^b
|
||||
* D(f(a,b)) = signum(a) * abs(a)^b * b / a
|
||||
*
|
||||
*/
|
||||
arg1 = PTdifferentiate(p->left->left, varnum);
|
||||
|
||||
newp = mkb(PT_TIMES,
|
||||
mkf(PTF_SGN, p->left->left),
|
||||
mkb(PT_DIVIDE, mkb(PT_TIMES,
|
||||
mkcon(p->left->right->constant),
|
||||
mkb(PT_POWER,
|
||||
mkf(PTF_ABS, p->left->left),
|
||||
mkcon(p->left->right->constant))),
|
||||
p->left->left));
|
||||
#ifdef TRACE
|
||||
printf("pwr, %s, returns; ", __func__);
|
||||
printTree(newp);
|
||||
printf("\n");
|
||||
#endif
|
||||
} else {
|
||||
/*
|
||||
* f(g) = signum(a) * abs(a)^g
|
||||
* D(f^g) = signum(a) * D(exp(g*ln(f)))
|
||||
* = signum(a) * exp(g*ln(f)) * D(g*ln(f))
|
||||
* = signum(a) * exp(g*ln(f)) * (D(g)*ln(f) + g*D(f)/f)
|
||||
*/
|
||||
arg1 = PTdifferentiate(p->left->left, varnum);
|
||||
arg2 = PTdifferentiate(p->left->right, varnum);
|
||||
|
||||
newp = mkb(PT_TIMES,
|
||||
mkf(PTF_SGN, p->left->left),
|
||||
mkb(PT_TIMES, mkf(PTF_EXP, mkb(PT_TIMES,
|
||||
p->left->right, mkf(PTF_LN,
|
||||
p->left->left))),
|
||||
mkb(PT_PLUS,
|
||||
mkb(PT_TIMES, p->left->right,
|
||||
mkb(PT_DIVIDE, arg1, p->left->left)),
|
||||
mkb(PT_TIMES, arg2, mkf(PTF_LN, p->left->left)))));
|
||||
}
|
||||
return mkfirst(newp, p);
|
||||
}
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Internal Error: bad function # %d\n",
|
||||
p->funcnum);
|
||||
|
|
@ -1387,8 +1445,6 @@ void free_tree(INPparseNode *pt)
|
|||
|
||||
/* Debugging stuff. */
|
||||
|
||||
void printTree(INPparseNode *);
|
||||
|
||||
void INPptPrint(char *str, IFparseTree * ptree)
|
||||
{
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ double PTminus(double arg1, double arg2);
|
|||
double PTtimes(double arg1, double arg2);
|
||||
double PTdivide(double arg1, double arg2);
|
||||
double PTpower(double arg1, double arg2);
|
||||
double PTpwr(double arg1, double arg2);
|
||||
double PTacos(double arg);
|
||||
double PTacosh(double arg);
|
||||
double PTasin(double arg);
|
||||
|
|
|
|||
|
|
@ -83,6 +83,15 @@ PTpower(double arg1, double arg2)
|
|||
return (pow(arg1, arg2));
|
||||
}
|
||||
|
||||
double
|
||||
PTpwr(double arg1, double arg2)
|
||||
{
|
||||
if (arg1 < 0.0)
|
||||
return (-pow(-arg1, arg2));
|
||||
else
|
||||
return (pow(arg1, arg2));
|
||||
}
|
||||
|
||||
double
|
||||
PTmin(double arg1, double arg2)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue