parser/*.c: implement a signed power function `pwr' for controlled sources

This commit is contained in:
dwarning 2013-05-31 14:19:05 +02:00 committed by rlar
parent 7857a300ad
commit 91ab0a3c74
5 changed files with 76 additions and 8 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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)
{