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_GE0 28
|
||||||
#define PTF_LE0 29
|
#define PTF_LE0 29
|
||||||
#define PTF_POW 30
|
#define PTF_POW 30
|
||||||
#define PTF_MIN 31
|
#define PTF_PWR 31
|
||||||
#define PTF_MAX 32
|
#define PTF_MIN 32
|
||||||
#define PTF_CEIL 33
|
#define PTF_MAX 33
|
||||||
#define PTF_FLOOR 34
|
#define PTF_CEIL 34
|
||||||
|
#define PTF_FLOOR 35
|
||||||
|
|
||||||
/* The following things are used by the parser -- these are the token types the
|
/* The following things are used by the parser -- these are the token types the
|
||||||
* lexer returns.
|
* lexer returns.
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ PTeval(INPparseNode * tree, double gmin, double *res, double *vals)
|
||||||
switch(tree->funcnum) {
|
switch(tree->funcnum) {
|
||||||
|
|
||||||
case PTF_POW:
|
case PTF_POW:
|
||||||
|
case PTF_PWR:
|
||||||
case PTF_MIN:
|
case PTF_MIN:
|
||||||
case PTF_MAX:
|
case PTF_MAX:
|
||||||
err = PTeval(tree->left->left, gmin, &r1, vals);
|
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 INPparseNode *PTdifferentiate(INPparseNode * p, int varnum);
|
||||||
|
|
||||||
static void free_tree(INPparseNode *);
|
static void free_tree(INPparseNode *);
|
||||||
|
static void printTree(INPparseNode *);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -167,6 +168,7 @@ static struct func {
|
||||||
{ "ge0", PTF_GE0, (void(*)(void)) PTge0},
|
{ "ge0", PTF_GE0, (void(*)(void)) PTge0},
|
||||||
{ "le0", PTF_LE0, (void(*)(void)) PTle0},
|
{ "le0", PTF_LE0, (void(*)(void)) PTle0},
|
||||||
{ "pow", PTF_POW, (void(*)(void)) PTpower},
|
{ "pow", PTF_POW, (void(*)(void)) PTpower},
|
||||||
|
{ "pwr", PTF_PWR, (void(*)(void)) PTpwr},
|
||||||
{ "min", PTF_MIN, (void(*)(void)) PTmin},
|
{ "min", PTF_MIN, (void(*)(void)) PTmin},
|
||||||
{ "max", PTF_MAX, (void(*)(void)) PTmax},
|
{ "max", PTF_MAX, (void(*)(void)) PTmax},
|
||||||
} ;
|
} ;
|
||||||
|
|
@ -523,8 +525,6 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
||||||
INPparseNode *b = p->left->right;
|
INPparseNode *b = p->left->right;
|
||||||
int comparison = (p->funcnum == PTF_MIN) ? PTF_LT0 : PTF_GT0;
|
int comparison = (p->funcnum == PTF_MIN) ? PTF_LT0 : PTF_GT0;
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
extern void printTree(INPparseNode *);
|
|
||||||
|
|
||||||
printf("debug: %s, PTF_MIN: ", __func__);
|
printf("debug: %s, PTF_MIN: ", __func__);
|
||||||
printTree(p);
|
printTree(p);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
@ -568,6 +568,11 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
||||||
mkb(PT_POWER, p->left->left,
|
mkb(PT_POWER, p->left->left,
|
||||||
mkcon(p->left->right->constant - 1))),
|
mkcon(p->left->right->constant - 1))),
|
||||||
arg1);
|
arg1);
|
||||||
|
#ifdef TRACE
|
||||||
|
printf("pow, %s, returns; ", __func__);
|
||||||
|
printTree(newp);
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* D(f^g) = D(exp(g*ln(f)))
|
* D(f^g) = D(exp(g*ln(f)))
|
||||||
|
|
@ -587,6 +592,59 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum)
|
||||||
return mkfirst(newp, p);
|
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:
|
default:
|
||||||
fprintf(stderr, "Internal Error: bad function # %d\n",
|
fprintf(stderr, "Internal Error: bad function # %d\n",
|
||||||
p->funcnum);
|
p->funcnum);
|
||||||
|
|
@ -1387,8 +1445,6 @@ void free_tree(INPparseNode *pt)
|
||||||
|
|
||||||
/* Debugging stuff. */
|
/* Debugging stuff. */
|
||||||
|
|
||||||
void printTree(INPparseNode *);
|
|
||||||
|
|
||||||
void INPptPrint(char *str, IFparseTree * ptree)
|
void INPptPrint(char *str, IFparseTree * ptree)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ double PTminus(double arg1, double arg2);
|
||||||
double PTtimes(double arg1, double arg2);
|
double PTtimes(double arg1, double arg2);
|
||||||
double PTdivide(double arg1, double arg2);
|
double PTdivide(double arg1, double arg2);
|
||||||
double PTpower(double arg1, double arg2);
|
double PTpower(double arg1, double arg2);
|
||||||
|
double PTpwr(double arg1, double arg2);
|
||||||
double PTacos(double arg);
|
double PTacos(double arg);
|
||||||
double PTacosh(double arg);
|
double PTacosh(double arg);
|
||||||
double PTasin(double arg);
|
double PTasin(double arg);
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,15 @@ PTpower(double arg1, double arg2)
|
||||||
return (pow(arg1, 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
|
double
|
||||||
PTmin(double arg1, double arg2)
|
PTmin(double arg1, double arg2)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue