You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
3.9 KiB

/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
$Id$
**********/
#include "ngspice.h"
#include <stdio.h>
#include "ifsim.h"
#include "inpmacs.h"
#include "fteext.h"
#include "iferrmsg.h"
#include "inpptree.h"
#include "inp.h"
#include "cktdefs.h"
/* Uncomment to allow tracing */
/*#define TRACE*/
extern double PTfudge_factor;
static int PTeval(INPparseNode * tree, double gmin, double *res,
double *vals);
int
IFeval(IFparseTree * tree, double gmin, double *result, double *vals,
double *derivs)
{
int i, err;
INPparseTree *myTree = (INPparseTree *) tree;;
#ifdef TRACE
INPptPrint("calling PTeval, tree = ", tree);
printf("values:");
for (i = 0; i < myTree->p.numVars; i++)
printf("\tvar%d = %lg\n", i, vals[i]);
#endif
if ((err = PTeval(myTree->tree, gmin, result, vals)) != OK)
return (err);
for (i = 0; i < myTree->p.numVars; i++)
if ((err = PTeval(myTree->derivs[i], gmin, &derivs[i], vals)) !=
OK) return (err);
#ifdef TRACE
printf("results: function = %lg\n", *result);
for (i = 0; i < myTree->p.numVars; i++)
printf("\td / d var%d = %lg\n", i, derivs[i]);
#endif
return (OK);
}
static int
PTeval(INPparseNode * tree, double gmin, double *res, double *vals)
{
double r1, r2;
int err;
PTfudge_factor = gmin;
switch (tree->type) {
case PT_CONSTANT:
*res = tree->constant;
break;
case PT_VAR:
*res = vals[tree->valueIndex];
break;
case PT_FUNCTION:
switch(tree->funcnum) {
case PTF_POW:
case PTF_MIN:
case PTF_MAX:
err = PTeval(tree->left->left, gmin, &r1, vals);
if (err != OK)
return (err);
err = PTeval(tree->left->right, gmin, &r2, vals);
if (err != OK)
return (err);
*res = PTbinary(tree -> function) (r1, r2);
if (*res == HUGE) {
fprintf(stderr, "Error: %g, %g out of range for %s\n",
r1, r2, tree->funcname);
return (E_PARMVAL);
}
break;
/* fcns with single argument */
default:
err = PTeval(tree->left, gmin, &r1, vals);
if (err != OK)
return (err);
if(tree->data == NULL)
*res = PTunary(tree -> function) (r1);
else
*res = PTunary_with_private(tree -> function) (r1, tree->data);
if (*res == HUGE) {
fprintf(stderr, "Error: %g out of range for %s\n",
r1, tree->funcname);
return (E_PARMVAL);
}
break;
}
break;
case PT_TERN:
{
INPparseNode *arg1 = tree->left;
INPparseNode *arg2 = tree->right->left;
INPparseNode *arg3 = tree->right->right;
err = PTeval(arg1, gmin, &r1, vals);
if (err != OK)
return (err);
/*FIXME > 0.0, >= 0.5, != 0.0 or what ? */
err = PTeval((r1 != 0.0) ? arg2 : arg3, gmin, &r2, vals);
if (err != OK)
return (err);
*res = r2;
break;
}
case PT_PLUS:
case PT_MINUS:
case PT_TIMES:
case PT_DIVIDE:
case PT_POWER:
err = PTeval(tree->left, gmin, &r1, vals);
if (err != OK)
return (err);
err = PTeval(tree->right, gmin, &r2, vals);
if (err != OK)
return (err);
*res = PTbinary(tree -> function) (r1, r2);
if (*res == HUGE) {
fprintf(stderr, "Error: %g, %g out of range for %s\n",
r1, r2, tree->funcname);
return (E_PARMVAL);
}
break;
case PT_TIME:
*res = ((CKTcircuit*) tree->data) -> CKTtime;
break;
case PT_TEMPERATURE:
*res = ((CKTcircuit*) tree->data) -> CKTtemp;
break;
case PT_FREQUENCY:
*res = (((CKTcircuit*) tree->data) -> CKTomega)/2./M_PI;
break;
default:
fprintf(stderr, "Internal Error: bad node type %d\n", tree->type);
return (E_PANIC);
}
return (OK);
}