From 93a76d8e216014905bf4944dcd504cfe7c7abbaa Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 13 Apr 2020 11:05:03 +0200 Subject: [PATCH] add a limit exp(arg) to the exp function. If arg is larger than 14 (arbitrarily selected), continue with linear response. --- src/include/ngspice/inpptree.h | 4 ++++ src/spicelib/parser/inpptree.c | 14 ++++++++++++-- src/spicelib/parser/ptfuncs.c | 6 +++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/include/ngspice/inpptree.h b/src/include/ngspice/inpptree.h index 2aaffbb46..81686a492 100644 --- a/src/include/ngspice/inpptree.h +++ b/src/include/ngspice/inpptree.h @@ -166,6 +166,10 @@ typedef struct PTelement { #define PT_STACKSIZE 200 +/* limits for exp function */ +#define EXPARGMAX 14. +#define EXPMAX 1202604.284 + /* And in IFeval.c */ extern int IFeval(IFparseTree *tree, double gmin, double *result, double *vals, double *derivs); diff --git a/src/spicelib/parser/inpptree.c b/src/spicelib/parser/inpptree.c index 92e1d8766..0d8bef123 100644 --- a/src/spicelib/parser/inpptree.c +++ b/src/spicelib/parser/inpptree.c @@ -434,8 +434,18 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum) arg1 = mkf(PTF_SINH, p->left); break; - case PTF_EXP: /* exp(u) */ - arg1 = mkf(PTF_EXP, p->left); + case PTF_EXP: /* u > EXPARGMAX -> EXPMAX, that is exp(EXPARGMAX), else exp(u) */ + arg1 = mkb(PT_TERN, + mkf(PTF_GT0, mkb(PT_MINUS, p->left, mkcon(EXPARGMAX))), + mkb(PT_COMMA, + mkcon(EXPMAX), + mkf(PTF_EXP, p->left))); + +#ifdef TRACE + printf("debug, %s, returns; ", __func__); + printTree(arg1); + printf("\n"); +#endif break; case PTF_LOG: /* 1 / u */ diff --git a/src/spicelib/parser/ptfuncs.c b/src/spicelib/parser/ptfuncs.c index d3f945756..9e0011057 100644 --- a/src/spicelib/parser/ptfuncs.c +++ b/src/spicelib/parser/ptfuncs.c @@ -217,10 +217,14 @@ PTcosh(double arg) return (cosh(arg)); } +/* Limit the exp: If arg > EXPARGMAX (arbitrarily selected to 14), continue with linear output */ double PTexp(double arg) { - return (exp(arg)); + if (arg > EXPARGMAX) + return EXPMAX * (arg - EXPARGMAX + 1.); + else + return (exp(arg)); } double