diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index 6480996f2..6d3363e6a 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -85,13 +85,13 @@ limit(double nominal_val, double abs_variation) static const char *fmathS = /* all math functions */ "SQR SQRT SIN COS EXP LN ARCTAN ABS POW PWR MAX MIN INT LOG SINH COSH" " TANH TERNARY_FCN AGAUSS SGN GAUSS UNIF AUNIF LIMIT CEIL FLOOR" - " ASIN ACOS ATAN ASINH ACOSH ATANH TAN"; + " ASIN ACOS ATAN ASINH ACOSH ATANH TAN NINT"; enum { XFU_SQR = 1, XFU_SQRT, XFU_SIN, XFU_COS, XFU_EXP, XFU_LN, XFU_ARCTAN, XFU_ABS, XFU_POW, XFU_PWR, XFU_MAX, XFU_MIN, XFU_INT, XFU_LOG, XFU_SINH, XFU_COSH, XFU_TANH, XFU_TERNARY_FCN, XFU_AGAUSS, XFU_SGN, XFU_GAUSS, XFU_UNIF, XFU_AUNIF, XFU_LIMIT, XFU_CEIL, XFU_FLOOR, - XFU_ASIN, XFU_ACOS, XFU_ATAN, XFU_ASINH, XFU_ACOSH, XFU_ATANH, XFU_TAN, + XFU_ASIN, XFU_ACOS, XFU_ATAN, XFU_ASINH, XFU_ACOSH, XFU_ATANH, XFU_TAN, XFU_NINT }; @@ -141,6 +141,13 @@ mathfunction(int f, double z, double x) case XFU_INT: y = trunc(x); break; + case XFU_NINT: + /* round to "nearest integer", + * round half-integers to the nearest even integer + * rely on default rounding mode of IEEE 754 to do so + */ + y = nearbyint(x); + break; case XFU_LOG: y = log(x); break; diff --git a/src/include/ngspice/ngspice.h b/src/include/ngspice/ngspice.h index 4434159de..ef2ca418b 100644 --- a/src/include/ngspice/ngspice.h +++ b/src/include/ngspice/ngspice.h @@ -160,6 +160,8 @@ extern void SetAnalyse(char *Analyse, int Percent); #include #define trunc x_trunc extern double x_trunc(double); +#define nearbyint x_nearbyint +extern double x_nearbyint(double); #define asinh x_asinh extern double x_asinh(double); #define acosh x_acosh diff --git a/tests/regression/parser/xpressn-1.cir b/tests/regression/parser/xpressn-1.cir index d6dc71238..a680633cd 100644 --- a/tests/regression/parser/xpressn-1.cir +++ b/tests/regression/parser/xpressn-1.cir @@ -303,47 +303,88 @@ v1082_g n1082_g 0 '-1' v1083_g n1083_g 0 '-2' -v1084_t n1084_t 0 'floor(2.1)' -v1085_t n1085_t 0 'floor(1.9)' -v1086_t n1086_t 0 'floor(0)' -v1087_t n1087_t 0 'floor(-1.9)' -v1088_t n1088_t 0 'floor(-2.1)' +v1084_t n1084_t 0 'nint(2.6)' +v1085_t n1085_t 0 'nint(2.5)' +v1086_t n1086_t 0 'nint(2.4)' +v1087_t n1087_t 0 'nint(1.6)' +v1088_t n1088_t 0 'nint(1.5)' +v1089_t n1089_t 0 'nint(1.4)' +v1090_t n1090_t 0 'nint(0.6)' +v1091_t n1091_t 0 'nint(0.5)' +v1092_t n1092_t 0 'nint(0.4)' +v1093_t n1093_t 0 'nint(0)' +v1094_t n1094_t 0 'nint(-0.4)' +v1095_t n1095_t 0 'nint(-0.5)' +v1096_t n1096_t 0 'nint(-0.6)' +v1097_t n1097_t 0 'nint(-1.4)' +v1098_t n1098_t 0 'nint(-1.5)' +v1099_t n1099_t 0 'nint(-1.6)' +v1100_t n1100_t 0 'nint(-2.4)' +v1101_t n1101_t 0 'nint(-2.5)' +v1102_t n1102_t 0 'nint(-2.6)' -v1084_g n1084_g 0 '2' -v1085_g n1085_g 0 '1' -v1086_g n1086_g 0 '0' -v1087_g n1087_g 0 '-2' -v1088_g n1088_g 0 '-3' - - -v1089_t n1089_t 0 'ceil(2.1)' -v1090_t n1090_t 0 'ceil(1.9)' -v1091_t n1091_t 0 'ceil(0)' -v1092_t n1092_t 0 'ceil(-1.9)' -v1093_t n1093_t 0 'ceil(-2.1)' - -v1089_g n1089_g 0 '3' -v1090_g n1090_g 0 '2' +v1084_g n1084_g 0 '3' +v1085_g n1085_g 0 '2' +v1086_g n1086_g 0 '2' +v1087_g n1087_g 0 '2' +v1088_g n1088_g 0 '2' +v1089_g n1089_g 0 '1' +v1090_g n1090_g 0 '1' v1091_g n1091_g 0 '0' -v1092_g n1092_g 0 '-1' -v1093_g n1093_g 0 '-2' +v1092_g n1092_g 0 '0' +v1093_g n1093_g 0 '0' +v1094_g n1094_g 0 '0' +v1095_g n1095_g 0 '0' +v1096_g n1096_g 0 '-1' +v1097_g n1097_g 0 '-1' +v1098_g n1098_g 0 '-2' +v1099_g n1099_g 0 '-2' +v1100_g n1100_g 0 '-2' +v1101_g n1101_g 0 '-2' +v1102_g n1102_g 0 '-3' + + +v1103_t n1103_t 0 'floor(2.1)' +v1104_t n1104_t 0 'floor(1.9)' +v1105_t n1105_t 0 'floor(0)' +v1106_t n1106_t 0 'floor(-1.9)' +v1107_t n1107_t 0 'floor(-2.1)' + +v1103_g n1103_g 0 '2' +v1104_g n1104_g 0 '1' +v1105_g n1105_g 0 '0' +v1106_g n1106_g 0 '-2' +v1107_g n1107_g 0 '-3' + + +v1108_t n1108_t 0 'ceil(2.1)' +v1109_t n1109_t 0 'ceil(1.9)' +v1110_t n1110_t 0 'ceil(0)' +v1111_t n1111_t 0 'ceil(-1.9)' +v1112_t n1112_t 0 'ceil(-2.1)' + +v1108_g n1108_g 0 '3' +v1109_g n1109_g 0 '2' +v1110_g n1110_g 0 '0' +v1111_g n1111_g 0 '-1' +v1112_g n1112_g 0 '-2' * ---------------------------------------- * min(a,b) max(a,b) -v1094_t n1094_t 0 'min(1.1, 2.1)' -v1095_t n1095_t 0 'min(2.1, 1.1)' +v1113_t n1113_t 0 'min(1.1, 2.1)' +v1114_t n1114_t 0 'min(2.1, 1.1)' -v1094_g n1094_g 0 '1.1' -v1095_g n1095_g 0 '1.1' +v1113_g n1113_g 0 '1.1' +v1114_g n1114_g 0 '1.1' -v1096_t n1096_t 0 'max(1.1, 2.1)' -v1097_t n1097_t 0 'max(2.1, 1.1)' +v1115_t n1115_t 0 'max(1.1, 2.1)' +v1116_t n1116_t 0 'max(2.1, 1.1)' -v1096_g n1096_g 0 '2.1' -v1097_g n1097_g 0 '2.1' +v1115_g n1115_g 0 '2.1' +v1116_g n1116_g 0 '2.1' * ---------------------------------------- @@ -357,7 +398,7 @@ op let total_count = 0 let fail_count = 0 -let tests = 1001 + vector(97) +let tests = 1001 + vector(116) foreach n $&tests set n_test = "n{$n}_t" diff --git a/visualc/msvc-compat.c b/visualc/msvc-compat.c index a68754f3c..6a20aa995 100644 --- a/visualc/msvc-compat.c +++ b/visualc/msvc-compat.c @@ -12,6 +12,14 @@ x_trunc(double x) } +double +x_nearbyint(double x) +{ + /* thats grossly incorrect, anyway, don't worry, be crappy ... */ + return floor(x + 0.5); +} + + double x_asinh(double x) {