summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2018-01-03 22:28:39 +0200
committerArnold D. Robbins <arnold@skeeve.com>2018-01-03 22:28:39 +0200
commita5f04737b4a5fce89ab7bd9264ba5b4813473121 (patch)
tree1fdc4b049f5eab73b15af306069a52eac110934b
parentc182937de92dc028a12a6c9350773dced1841751 (diff)
downloadgawk-a5f04737b4a5fce89ab7bd9264ba5b4813473121.tar.gz
Changes to ROUNDMODE now invalidate cached string values.
-rw-r--r--ChangeLog28
-rw-r--r--array.c5
-rw-r--r--awk.h17
-rw-r--r--awkgram.c3
-rw-r--r--awkgram.y5
-rw-r--r--builtin.c9
-rw-r--r--doc/ChangeLog8
-rw-r--r--doc/gawk.info333
-rw-r--r--doc/gawk.texi65
-rw-r--r--doc/gawktexi.in26
-rw-r--r--field.c5
-rw-r--r--gawkapi.c5
-rw-r--r--interpret.h5
-rw-r--r--mpfr.c7
-rw-r--r--node.c11
-rw-r--r--str_array.c4
-rw-r--r--symbol.c5
-rw-r--r--test/ChangeLog7
-rw-r--r--test/Makefile.am9
-rw-r--r--test/Makefile.in9
-rw-r--r--test/mpfrrndeval.awk35
-rw-r--r--test/mpfrrndeval.ok18
22 files changed, 443 insertions, 176 deletions
diff --git a/ChangeLog b/ChangeLog
index 759c375f..d3771c2f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2018-01-02 Arnold D. Robbins <arnold@skeeve.com>
+
+ If ROUNDMODE changes, cause cached string conversions
+ to become invalid. Thanks to Nethox <nethox@gmail.com>
+ for the report. Day 1 bug from 4.1.0 release.
+
+ In all the below files, bump copyright year, too.
+
+ * array.c (value_info): Include strndmode in the output.
+ * awk.h (NODE): New member, strndmode.
+ (MPFR_round_mode): Add extern declaration.
+ (force_string_fmt): Check s->strnmode against MPFR_round_mode.
+ * awkgram.y (set_profile_text): Set n->strndmode to MPFR_round_mode.
+ * builtin.c (do_print): Remove tests and just call force_string_fmt.
+ * field.c (set_record): Set n->strndmode to MPFR_round_mode.
+ * gawk_api.c (api_sym_update_scalar): Set r->strndmode to
+ MPFR_round_mode.
+ * interpret.h (r_interpret): For Op_assign_concat, set t1->strndmode
+ to MPFR_round_mode.
+ * mpfr.c (MPFR_round_mode): Define and initialize.
+ (mpfr_format_val): Set s->strndmode to MPFR_round_mode.
+ (set_ROUNDMODE): Update MPFR_round_mode when ROUNDMODE changes
+ successfully.
+ * node.c (r_format_val): Set s->strndmode to MPFR_round_mode.
+ (make_str_node): Set r->strndmode to MPFR_round_mode.
+ * str_array.c (str_kilobytes): Update a comment.
+ * symbol.c (check_param_names): Set n.strndmode to MPFR_round_mode.
+
2017-12-24 Arnold D. Robbins <arnold@skeeve.com>
Avoid some compiler warnings. Thanks to Michal Jaegermann
diff --git a/array.c b/array.c
index 4ad52c9c..5d953c04 100644
--- a/array.c
+++ b/array.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2014, 2016, 2017,
+ * Copyright (C) 1986, 1988, 1989, 1991-2014, 2016, 2018,
* the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
@@ -716,6 +716,9 @@ value_info(NODE *n)
fprintf(output_fp, "FMT=\"%s\"",
n->stfmt == STFMT_UNUSED ? "<unused>"
: fmt_list[n->stfmt]->stptr);
+#ifdef HAVE_MPFR
+ fprintf(output_fp, ", RNDMODE=\"%c\"", n->strndmode);
+#endif
}
#undef PREC_NUM
diff --git a/awk.h b/awk.h
index 5eec241e..3b351c25 100644
--- a/awk.h
+++ b/awk.h
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2017 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2018 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -369,6 +369,7 @@ typedef struct exp_node {
mpfr_t mpnum;
mpz_t mpi;
} nm;
+ int rndmode;
#else
AWKNUM fltnum;
#endif
@@ -493,6 +494,7 @@ typedef struct exp_node {
#define stlen sub.val.slen
#define valref sub.val.sref
#define stfmt sub.val.idx
+#define strndmode sub.val.rndmode
#define wstptr sub.val.wsp
#define wstlen sub.val.wslen
#ifdef HAVE_MPFR
@@ -1101,6 +1103,9 @@ extern char *OFMT;
extern char *CONVFMT;
extern int CONVFMTidx;
extern int OFMTidx;
+#ifdef HAVE_MPFR
+extern int MPFR_round_mode;
+#endif
extern char *TEXTDOMAIN;
extern NODE *BINMODE_node, *CONVFMT_node, *FIELDWIDTHS_node, *FILENAME_node;
extern NODE *FNR_node, *FS_node, *IGNORECASE_node, *NF_node;
@@ -1856,14 +1861,20 @@ dupnode(NODE *n)
* and OFMT values. But if the value entered gawk as a string or strnum, then
* stfmt should be set to STFMT_UNUSED, and the string representation should
* not change.
+ *
+ * Additional twist: If ROUNDMODE changed at some point we have to
+ * recompute also.
*/
static inline NODE *
force_string_fmt(NODE *s, const char *fmtstr, int fmtidx)
{
if ((s->flags & STRCUR) != 0
- && (s->stfmt == STFMT_UNUSED || s->stfmt == fmtidx)
- )
+ && (s->stfmt == STFMT_UNUSED || (s->stfmt == fmtidx
+#ifdef HAVE_MPFR
+ && s->strndmode == MPFR_round_mode
+#endif
+ )))
return s;
return format_val(fmtstr, fmtidx, s);
}
diff --git a/awkgram.c b/awkgram.c
index 3bc19645..52821eab 100644
--- a/awkgram.c
+++ b/awkgram.c
@@ -8771,6 +8771,9 @@ set_profile_text(NODE *n, const char *str, size_t len)
// Thanks and a tip of the hatlo to valgrind.
n->flags |= (NUMCONSTSTR|STRCUR);
n->stfmt = STFMT_UNUSED;
+#ifdef HAVE_MPFR
+ n->strndmode = MPFR_round_mode;
+#endif
}
return n;
diff --git a/awkgram.y b/awkgram.y
index bbc598dd..ad830a5d 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2017 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2018 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -6351,6 +6351,9 @@ set_profile_text(NODE *n, const char *str, size_t len)
// Thanks and a tip of the hatlo to valgrind.
n->flags |= (NUMCONSTSTR|STRCUR);
n->stfmt = STFMT_UNUSED;
+#ifdef HAVE_MPFR
+ n->strndmode = MPFR_round_mode;
+#endif
}
return n;
diff --git a/builtin.c b/builtin.c
index fc948276..54d202d6 100644
--- a/builtin.c
+++ b/builtin.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2017 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2018 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -2242,10 +2242,9 @@ do_print(int nargs, int redirtype)
DEREF(args_array[i]);
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(tmp));
}
- if ( (tmp->flags & STRCUR) == 0
- || ( tmp->stfmt != STFMT_UNUSED
- && tmp->stfmt != OFMTidx))
- args_array[i] = force_string_ofmt(tmp);
+ // Let force_string_ofmt handle checking if things
+ // are already valid.
+ args_array[i] = force_string_ofmt(tmp);
}
if (redir_exp != NULL) {
diff --git a/doc/ChangeLog b/doc/ChangeLog
index c675db61..9baa3641 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,3 +1,9 @@
+2018-01-02 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Setting the rounding mode): Add a sidebar
+ with sample code (courtesy of <nethox@gmail.com>) to
+ demonstrate how ROUNDMODE affects number to string conversion.
+
2017-12-28 Arnold D. Robbins <arnold@skeeve.com>
* texinfo.tex: Updated.
@@ -49,7 +55,7 @@
2017-11-17 Arnold D. Robbins <arnold@skeeve.com>
- * gawktexi.in(Changes from API V1): Give a list of things
+ * gawktexi.in (Changes from API V1): Give a list of things
that changed, with xrefs. Thanks to Andrew Schorr for the push.
2017-11-09 Arnold D. Robbins <arnold@skeeve.com>
diff --git a/doc/gawk.info b/doc/gawk.info
index 68aa1848..b42f26e5 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -23137,6 +23137,25 @@ cause any accumulating round-off error to cancel itself out. This is
the default rounding mode for IEEE 754 computing functions and
operators.
+ Rounding Modes and Conversion
+
+ It's important to understand that, along with 'CONVFMT' and 'OFMT',
+the rounding mode affects how numbers are converted to strings. For
+example, consider the following program:
+
+ BEGIN {
+ pi = 3.1416
+ OFMT = "%.f" # Print value as integer
+ print pi # ROUNDMODE = "N" by default.
+ ROUNDMODE = "U" # Now change ROUNDMODE
+ print pi
+ }
+
+Running this program produces this output:
+
+ $ gawk -M -f roundmode.awk
+ -| 3
+ -| 4
The other rounding modes are rarely used. Rounding toward positive
infinity ('roundTowardPositive') and toward negative infinity
('roundTowardNegative') are often used to implement interval arithmetic,
@@ -35423,6 +35442,8 @@ Index
* round() user-defined function: Round Function. (line 16)
* rounding numbers: Round Function. (line 6)
* ROUNDMODE variable: User-modified. (line 131)
+* ROUNDMODE variable <1>: Setting the rounding mode.
+ (line 6)
* RS variable: awk split records. (line 12)
* RS variable <1>: User-modified. (line 136)
* RS variable, multiline records and: Multiple Line. (line 17)
@@ -35550,6 +35571,8 @@ Index
* sidebar, Pre-POSIX awk Used OFMT for String Conversion: Strings And Numbers.
(line 54)
* sidebar, Recipe for a Programming Language: History. (line 6)
+* sidebar, Rounding Modes and Conversion: Setting the rounding mode.
+ (line 65)
* sidebar, RS = "\0" Is Not Portable: gawk split records. (line 63)
* sidebar, So Why Does gawk Have BEGINFILE and ENDFILE?: Filetrans Function.
(line 83)
@@ -36375,160 +36398,160 @@ Node: Setting precision933040
Ref: table-predefined-precision-strings933737
Node: Setting the rounding mode935567
Ref: table-gawk-rounding-modes935941
-Ref: Setting the rounding mode-Footnote-1939316
-Node: Arbitrary Precision Integers939495
-Ref: Arbitrary Precision Integers-Footnote-1942670
-Node: Checking for MPFR942819
-Node: POSIX Floating Point Problems944116
-Ref: POSIX Floating Point Problems-Footnote-1947987
-Node: Floating point summary948025
-Node: Dynamic Extensions950215
-Node: Extension Intro951768
-Node: Plugin License953034
-Node: Extension Mechanism Outline953831
-Ref: figure-load-extension954270
-Ref: figure-register-new-function955835
-Ref: figure-call-new-function956927
-Node: Extension API Description958989
-Node: Extension API Functions Introduction960631
-Node: General Data Types966171
-Ref: General Data Types-Footnote-1974532
-Node: Memory Allocation Functions974831
-Ref: Memory Allocation Functions-Footnote-1979041
-Node: Constructor Functions979140
-Node: Registration Functions982726
-Node: Extension Functions983411
-Node: Exit Callback Functions988626
-Node: Extension Version String989876
-Node: Input Parsers990539
-Node: Output Wrappers1003260
-Node: Two-way processors1007772
-Node: Printing Messages1010037
-Ref: Printing Messages-Footnote-11011208
-Node: Updating ERRNO1011361
-Node: Requesting Values1012100
-Ref: table-value-types-returned1012837
-Node: Accessing Parameters1013773
-Node: Symbol Table Access1015008
-Node: Symbol table by name1015520
-Node: Symbol table by cookie1017309
-Ref: Symbol table by cookie-Footnote-11021494
-Node: Cached values1021558
-Ref: Cached values-Footnote-11025094
-Node: Array Manipulation1025247
-Ref: Array Manipulation-Footnote-11026338
-Node: Array Data Types1026375
-Ref: Array Data Types-Footnote-11029033
-Node: Array Functions1029125
-Node: Flattening Arrays1033623
-Node: Creating Arrays1040599
-Node: Redirection API1045366
-Node: Extension API Variables1048199
-Node: Extension Versioning1048910
-Ref: gawk-api-version1049339
-Node: Extension GMP/MPFR Versioning1051070
-Node: Extension API Informational Variables1052698
-Node: Extension API Boilerplate1053771
-Node: Changes from API V11057745
-Node: Finding Extensions1059317
-Node: Extension Example1059876
-Node: Internal File Description1060674
-Node: Internal File Ops1064754
-Ref: Internal File Ops-Footnote-11076105
-Node: Using Internal File Ops1076245
-Ref: Using Internal File Ops-Footnote-11078628
-Node: Extension Samples1078902
-Node: Extension Sample File Functions1080431
-Node: Extension Sample Fnmatch1088080
-Node: Extension Sample Fork1089567
-Node: Extension Sample Inplace1090785
-Node: Extension Sample Ord1094002
-Node: Extension Sample Readdir1094838
-Ref: table-readdir-file-types1095727
-Node: Extension Sample Revout1096532
-Node: Extension Sample Rev2way1097121
-Node: Extension Sample Read write array1097861
-Node: Extension Sample Readfile1099803
-Node: Extension Sample Time1100898
-Node: Extension Sample API Tests1102246
-Node: gawkextlib1102738
-Node: Extension summary1105194
-Node: Extension Exercises1108896
-Node: Language History1110394
-Node: V7/SVR3.11112050
-Node: SVR41114202
-Node: POSIX1115636
-Node: BTL1117016
-Node: POSIX/GNU1117745
-Node: Feature History1123523
-Node: Common Extensions1139382
-Node: Ranges and Locales1140665
-Ref: Ranges and Locales-Footnote-11145281
-Ref: Ranges and Locales-Footnote-21145308
-Ref: Ranges and Locales-Footnote-31145543
-Node: Contributors1145764
-Node: History summary1151709
-Node: Installation1153089
-Node: Gawk Distribution1154033
-Node: Getting1154517
-Node: Extracting1155480
-Node: Distribution contents1157118
-Node: Unix Installation1163598
-Node: Quick Installation1164280
-Node: Shell Startup Files1166694
-Node: Additional Configuration Options1167783
-Node: Configuration Philosophy1170076
-Node: Non-Unix Installation1172445
-Node: PC Installation1172905
-Node: PC Binary Installation1173743
-Node: PC Compiling1174178
-Node: PC Using1175295
-Node: Cygwin1178340
-Node: MSYS1179110
-Node: VMS Installation1179611
-Node: VMS Compilation1180402
-Ref: VMS Compilation-Footnote-11181631
-Node: VMS Dynamic Extensions1181689
-Node: VMS Installation Details1183374
-Node: VMS Running1185627
-Node: VMS GNV1189906
-Node: VMS Old Gawk1190641
-Node: Bugs1191112
-Node: Bug address1191775
-Node: Usenet1194567
-Node: Maintainers1195344
-Node: Other Versions1196605
-Node: Installation summary1203367
-Node: Notes1204569
-Node: Compatibility Mode1205434
-Node: Additions1206216
-Node: Accessing The Source1207141
-Node: Adding Code1208578
-Node: New Ports1214797
-Node: Derived Files1219285
-Ref: Derived Files-Footnote-11224931
-Ref: Derived Files-Footnote-21224966
-Ref: Derived Files-Footnote-31225564
-Node: Future Extensions1225678
-Node: Implementation Limitations1226336
-Node: Extension Design1227519
-Node: Old Extension Problems1228673
-Ref: Old Extension Problems-Footnote-11230191
-Node: Extension New Mechanism Goals1230248
-Ref: Extension New Mechanism Goals-Footnote-11233612
-Node: Extension Other Design Decisions1233801
-Node: Extension Future Growth1235914
-Node: Old Extension Mechanism1236750
-Node: Notes summary1238513
-Node: Basic Concepts1239695
-Node: Basic High Level1240376
-Ref: figure-general-flow1240658
-Ref: figure-process-flow1241343
-Ref: Basic High Level-Footnote-11244644
-Node: Basic Data Typing1244829
-Node: Glossary1248157
-Node: Copying1279995
-Node: GNU Free Documentation License1317534
-Node: Index1342652
+Ref: Setting the rounding mode-Footnote-1939871
+Node: Arbitrary Precision Integers940050
+Ref: Arbitrary Precision Integers-Footnote-1943225
+Node: Checking for MPFR943374
+Node: POSIX Floating Point Problems944671
+Ref: POSIX Floating Point Problems-Footnote-1948542
+Node: Floating point summary948580
+Node: Dynamic Extensions950770
+Node: Extension Intro952323
+Node: Plugin License953589
+Node: Extension Mechanism Outline954386
+Ref: figure-load-extension954825
+Ref: figure-register-new-function956390
+Ref: figure-call-new-function957482
+Node: Extension API Description959544
+Node: Extension API Functions Introduction961186
+Node: General Data Types966726
+Ref: General Data Types-Footnote-1975087
+Node: Memory Allocation Functions975386
+Ref: Memory Allocation Functions-Footnote-1979596
+Node: Constructor Functions979695
+Node: Registration Functions983281
+Node: Extension Functions983966
+Node: Exit Callback Functions989181
+Node: Extension Version String990431
+Node: Input Parsers991094
+Node: Output Wrappers1003815
+Node: Two-way processors1008327
+Node: Printing Messages1010592
+Ref: Printing Messages-Footnote-11011763
+Node: Updating ERRNO1011916
+Node: Requesting Values1012655
+Ref: table-value-types-returned1013392
+Node: Accessing Parameters1014328
+Node: Symbol Table Access1015563
+Node: Symbol table by name1016075
+Node: Symbol table by cookie1017864
+Ref: Symbol table by cookie-Footnote-11022049
+Node: Cached values1022113
+Ref: Cached values-Footnote-11025649
+Node: Array Manipulation1025802
+Ref: Array Manipulation-Footnote-11026893
+Node: Array Data Types1026930
+Ref: Array Data Types-Footnote-11029588
+Node: Array Functions1029680
+Node: Flattening Arrays1034178
+Node: Creating Arrays1041154
+Node: Redirection API1045921
+Node: Extension API Variables1048754
+Node: Extension Versioning1049465
+Ref: gawk-api-version1049894
+Node: Extension GMP/MPFR Versioning1051625
+Node: Extension API Informational Variables1053253
+Node: Extension API Boilerplate1054326
+Node: Changes from API V11058300
+Node: Finding Extensions1059872
+Node: Extension Example1060431
+Node: Internal File Description1061229
+Node: Internal File Ops1065309
+Ref: Internal File Ops-Footnote-11076660
+Node: Using Internal File Ops1076800
+Ref: Using Internal File Ops-Footnote-11079183
+Node: Extension Samples1079457
+Node: Extension Sample File Functions1080986
+Node: Extension Sample Fnmatch1088635
+Node: Extension Sample Fork1090122
+Node: Extension Sample Inplace1091340
+Node: Extension Sample Ord1094557
+Node: Extension Sample Readdir1095393
+Ref: table-readdir-file-types1096282
+Node: Extension Sample Revout1097087
+Node: Extension Sample Rev2way1097676
+Node: Extension Sample Read write array1098416
+Node: Extension Sample Readfile1100358
+Node: Extension Sample Time1101453
+Node: Extension Sample API Tests1102801
+Node: gawkextlib1103293
+Node: Extension summary1105749
+Node: Extension Exercises1109451
+Node: Language History1110949
+Node: V7/SVR3.11112605
+Node: SVR41114757
+Node: POSIX1116191
+Node: BTL1117571
+Node: POSIX/GNU1118300
+Node: Feature History1124078
+Node: Common Extensions1139937
+Node: Ranges and Locales1141220
+Ref: Ranges and Locales-Footnote-11145836
+Ref: Ranges and Locales-Footnote-21145863
+Ref: Ranges and Locales-Footnote-31146098
+Node: Contributors1146319
+Node: History summary1152264
+Node: Installation1153644
+Node: Gawk Distribution1154588
+Node: Getting1155072
+Node: Extracting1156035
+Node: Distribution contents1157673
+Node: Unix Installation1164153
+Node: Quick Installation1164835
+Node: Shell Startup Files1167249
+Node: Additional Configuration Options1168338
+Node: Configuration Philosophy1170631
+Node: Non-Unix Installation1173000
+Node: PC Installation1173460
+Node: PC Binary Installation1174298
+Node: PC Compiling1174733
+Node: PC Using1175850
+Node: Cygwin1178895
+Node: MSYS1179665
+Node: VMS Installation1180166
+Node: VMS Compilation1180957
+Ref: VMS Compilation-Footnote-11182186
+Node: VMS Dynamic Extensions1182244
+Node: VMS Installation Details1183929
+Node: VMS Running1186182
+Node: VMS GNV1190461
+Node: VMS Old Gawk1191196
+Node: Bugs1191667
+Node: Bug address1192330
+Node: Usenet1195122
+Node: Maintainers1195899
+Node: Other Versions1197160
+Node: Installation summary1203922
+Node: Notes1205124
+Node: Compatibility Mode1205989
+Node: Additions1206771
+Node: Accessing The Source1207696
+Node: Adding Code1209133
+Node: New Ports1215352
+Node: Derived Files1219840
+Ref: Derived Files-Footnote-11225486
+Ref: Derived Files-Footnote-21225521
+Ref: Derived Files-Footnote-31226119
+Node: Future Extensions1226233
+Node: Implementation Limitations1226891
+Node: Extension Design1228074
+Node: Old Extension Problems1229228
+Ref: Old Extension Problems-Footnote-11230746
+Node: Extension New Mechanism Goals1230803
+Ref: Extension New Mechanism Goals-Footnote-11234167
+Node: Extension Other Design Decisions1234356
+Node: Extension Future Growth1236469
+Node: Old Extension Mechanism1237305
+Node: Notes summary1239068
+Node: Basic Concepts1240250
+Node: Basic High Level1240931
+Ref: figure-general-flow1241213
+Ref: figure-process-flow1241898
+Ref: Basic High Level-Footnote-11245199
+Node: Basic Data Typing1245384
+Node: Glossary1248712
+Node: Copying1280550
+Node: GNU Free Documentation License1318089
+Node: Index1343207

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index f0a0c26d..3ee8d042 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -32028,6 +32028,7 @@ $ @kbd{gawk -M 'BEGIN @{ PREC = 113; printf("%0.25f\n", 1/10) @}'}
@node Setting the rounding mode
@subsection Setting the Rounding Mode
+@cindex @code{ROUNDMODE} variable
The @code{ROUNDMODE} variable provides
program-level control over the rounding mode.
The correspondence between @code{ROUNDMODE} and the IEEE
@@ -32100,6 +32101,70 @@ distributes upward and downward rounds of exact halves, which might
cause any accumulating round-off error to cancel itself out. This is the
default rounding mode for IEEE 754 computing functions and operators.
+@c January 2018. Thanks to nethox@gmail.com for the example.
+@cindex sidebar, Rounding Modes and Conversion
+@ifdocbook
+@docbook
+<sidebar><title>Rounding Modes and Conversion</title>
+@end docbook
+
+It's important to understand that, along with @code{CONVFMT} and
+@code{OFMT}, the rounding mode affects how numbers are converted to strings.
+For example, consider the following program:
+
+@example
+BEGIN @{
+ pi = 3.1416
+ OFMT = "%.f" # Print value as integer
+ print pi # ROUNDMODE = "N" by default.
+ ROUNDMODE = "U" # Now change ROUNDMODE
+ print pi
+@}
+@end example
+
+@noindent
+Running this program produces this output:
+
+@example
+$ @kbd{gawk -M -f roundmode.awk}
+@print{} 3
+@print{} 4
+@end example
+
+@docbook
+</sidebar>
+@end docbook
+@end ifdocbook
+
+@ifnotdocbook
+@cartouche
+@center @b{Rounding Modes and Conversion}
+
+
+It's important to understand that, along with @code{CONVFMT} and
+@code{OFMT}, the rounding mode affects how numbers are converted to strings.
+For example, consider the following program:
+
+@example
+BEGIN @{
+ pi = 3.1416
+ OFMT = "%.f" # Print value as integer
+ print pi # ROUNDMODE = "N" by default.
+ ROUNDMODE = "U" # Now change ROUNDMODE
+ print pi
+@}
+@end example
+
+@noindent
+Running this program produces this output:
+
+@example
+$ @kbd{gawk -M -f roundmode.awk}
+@print{} 3
+@print{} 4
+@end example
+@end cartouche
+@end ifnotdocbook
The other rounding modes are rarely used. Rounding toward positive infinity
(@code{roundTowardPositive}) and toward negative infinity
(@code{roundTowardNegative}) are often used to implement interval
diff --git a/doc/gawktexi.in b/doc/gawktexi.in
index a7406d62..d2325305 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -31041,6 +31041,7 @@ $ @kbd{gawk -M 'BEGIN @{ PREC = 113; printf("%0.25f\n", 1/10) @}'}
@node Setting the rounding mode
@subsection Setting the Rounding Mode
+@cindex @code{ROUNDMODE} variable
The @code{ROUNDMODE} variable provides
program-level control over the rounding mode.
The correspondence between @code{ROUNDMODE} and the IEEE
@@ -31113,6 +31114,31 @@ distributes upward and downward rounds of exact halves, which might
cause any accumulating round-off error to cancel itself out. This is the
default rounding mode for IEEE 754 computing functions and operators.
+@c January 2018. Thanks to nethox@gmail.com for the example.
+@sidebar Rounding Modes and Conversion
+It's important to understand that, along with @code{CONVFMT} and
+@code{OFMT}, the rounding mode affects how numbers are converted to strings.
+For example, consider the following program:
+
+@example
+BEGIN @{
+ pi = 3.1416
+ OFMT = "%.f" # Print value as integer
+ print pi # ROUNDMODE = "N" by default.
+ ROUNDMODE = "U" # Now change ROUNDMODE
+ print pi
+@}
+@end example
+
+@noindent
+Running this program produces this output:
+
+@example
+$ @kbd{gawk -M -f roundmode.awk}
+@print{} 3
+@print{} 4
+@end example
+@end sidebar
The other rounding modes are rarely used. Rounding toward positive infinity
(@code{roundTowardPositive}) and toward negative infinity
(@code{roundTowardNegative}) are often used to implement interval
diff --git a/field.c b/field.c
index 5263cc61..0d7e6330 100644
--- a/field.c
+++ b/field.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2017 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2018 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -308,6 +308,9 @@ set_record(const char *buf, int cnt, const awk_fieldwidth_info_t *fw)
n->valref = 1;
n->type = Node_val;
n->stfmt = STFMT_UNUSED;
+#ifdef HAVE_MPFR
+ n->strndmode = MPFR_round_mode;
+#endif
n->flags = (STRING|STRCUR|USER_INPUT); /* do not set MALLOC */
fields_arr[0] = n;
if (fw != api_fw) {
diff --git a/gawkapi.c b/gawkapi.c
index f8964db2..80d3ebca 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 2012-2017 the Free Software Foundation, Inc.
+ * Copyright (C) 2012-2018 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -925,6 +925,9 @@ api_sym_update_scalar(awk_ext_id_t id,
r->stfmt = STFMT_UNUSED;
r->stptr = value->str_value.str;
r->stlen = value->str_value.len;
+#ifdef HAVE_MPFR
+ r->strndmode = MPFR_round_mode;
+#endif
return awk_true;
}
break;
diff --git a/interpret.h b/interpret.h
index 4b140c28..2ee68112 100644
--- a/interpret.h
+++ b/interpret.h
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2017 the Free Software Foundation, Inc.
+ * Copyright (C) 1986, 1988, 1989, 1991-2018 the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -735,6 +735,9 @@ mod:
/* configure as a string as in make_str_node */
t1->flags |= (MALLOC|STRING|STRCUR);
t1->stfmt = STFMT_UNUSED;
+#ifdef HAVE_MPFR
+ t1->strndmode = MPFR_round_mode;
+#endif
if ((t1->flags & WSTRCUR) != 0 && (t2->flags & WSTRCUR) != 0) {
size_t wlen = t1->wstlen + t2->wstlen;
diff --git a/mpfr.c b/mpfr.c
index b9208a6b..1c4a2b9b 100644
--- a/mpfr.c
+++ b/mpfr.c
@@ -3,7 +3,8 @@
*/
/*
- * Copyright (C) 2012, 2013, 2015, 2017, the Free Software Foundation, Inc.
+ * Copyright (C) 2012, 2013, 2015, 2017, 2018,
+ * the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
* AWK Programming Language.
@@ -27,6 +28,8 @@
#ifdef HAVE_MPFR
+int MPFR_round_mode = 'N'; // default value
+
#if !defined(MPFR_VERSION_MAJOR) || MPFR_VERSION_MAJOR < 3
typedef mp_exp_t mpfr_exp_t;
#endif
@@ -373,6 +376,7 @@ mpg_format_val(const char *format, int index, NODE *s)
efree(s->stptr);
s->stptr = r->stptr;
s->flags |= STRCUR;
+ s->strndmode = MPFR_round_mode;
freenode(r); /* Do not unref(r)! We want to keep s->stptr == r->stpr. */
free_wstr(s);
return s;
@@ -596,6 +600,7 @@ set_ROUNDMODE()
if (rndm != -1) {
mpfr_set_default_rounding_mode(rndm);
ROUND_MODE = rndm;
+ MPFR_round_mode = n->stptr[0];
} else
warning(_("RNDMODE value `%.*s' is invalid"), (int) n->stlen, n->stptr);
}
diff --git a/node.c b/node.c
index f64bd9eb..add959f7 100644
--- a/node.c
+++ b/node.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2001, 2003-2015, 2017,
+ * Copyright (C) 1986, 1988, 1989, 1991-2001, 2003-2015, 2017, 2018,
* the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
@@ -252,6 +252,9 @@ r_format_val(const char *format, int index, NODE *s)
if ((s->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR))
efree(s->stptr);
s->stptr = r->stptr;
+#ifdef HAVE_MPFR
+ s->strndmode = MPFR_round_mode;
+#endif
freenode(r); /* Do not unref(r)! We want to keep s->stptr == r->stpr. */
goto no_malloc;
@@ -273,6 +276,9 @@ r_format_val(const char *format, int index, NODE *s)
s->flags &= ~(INTIND|NUMBER);
s->flags |= STRING;
}
+#ifdef HAVE_MPFR
+ s->strndmode = MPFR_round_mode;
+#endif
}
if ((s->flags & (MALLOC|STRCUR)) == (MALLOC|STRCUR))
efree(s->stptr);
@@ -377,6 +383,9 @@ make_str_node(const char *s, size_t len, int flags)
r->flags = (MALLOC|STRING|STRCUR);
r->valref = 1;
r->stfmt = STFMT_UNUSED;
+#ifdef HAVE_MPFR
+ r->strndmode = MPFR_round_mode;
+#endif
r->wstptr = NULL;
r->wstlen = 0;
diff --git a/str_array.c b/str_array.c
index 8d6d2b01..bc6584d2 100644
--- a/str_array.c
+++ b/str_array.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2013, 2016, 2017,
+ * Copyright (C) 1986, 1988, 1989, 1991-2013, 2016, 2017, 2018,
* the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
@@ -444,7 +444,7 @@ str_kilobytes(NODE *symbol)
bucket_cnt = symbol->table_size;
- /* This does not include extra memory for indices with stfmt != -1 */
+ /* This does not include extra memory for indices with stfmt != STFMT_UNUSED */
kb = (((AWKNUM) bucket_cnt) * sizeof (BUCKET) +
((AWKNUM) symbol->array_size) * sizeof (BUCKET *)) / 1024.0;
return kb;
diff --git a/symbol.c b/symbol.c
index 55b17397..797b5ec4 100644
--- a/symbol.c
+++ b/symbol.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 1986, 1988, 1989, 1991-2015, 2017,
+ * Copyright (C) 1986, 1988, 1989, 1991-2015, 2017, 2018,
* the Free Software Foundation, Inc.
*
* This file is part of GAWK, the GNU implementation of the
@@ -653,6 +653,9 @@ check_param_names(void)
n.type = Node_val;
n.flags = STRING|STRCUR;
n.stfmt = STFMT_UNUSED;
+#ifdef HAVE_MPFR
+ n.strndmode = MPFR_round_mode;
+#endif
/*
* assoc_list() returns an array with two elements per awk array
diff --git a/test/ChangeLog b/test/ChangeLog
index 1e1cf7ea..c64dc5bc 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,10 @@
+2018-01-02 Arnold D. Robbins <arnold@skeeve.com>
+
+ Thanks to Nethox <nethox@gmail.com> for this test.
+
+ * Makefile.am (mpfrrndeval): New test.
+ * mpfrrndeval.awk, mpfrrndeval.ok: New files.
+
2017-11-14 Andrew J. Schorr <aschorr@telemetry-investments.com>
* Makefile.am (EXTRA_DIST): Add new tests setrec0 and setrec1.
diff --git a/test/Makefile.am b/test/Makefile.am
index 1438e083..1ec63a20 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -666,6 +666,8 @@ EXTRA_DIST = \
mpfrrem.ok \
mpfrrnd.awk \
mpfrrnd.ok \
+ mpfrrndeval.awk \
+ mpfrrndeval.ok \
mpfrsort.awk \
mpfrsort.ok \
mpfrsqrt.awk \
@@ -1285,7 +1287,7 @@ INET_TESTS = inetdayu inetdayt inetechu inetecht
MACHINE_TESTS = double1 double2 fmtspcl intformat
-MPFR_TESTS = mpfrnr mpfrnegzero mpfrmemok1 mpfrrem mpfrrnd mpfrieee
+MPFR_TESTS = mpfrnr mpfrnegzero mpfrmemok1 mpfrrem mpfrrnd mpfrrndeval mpfrieee
mpfrexprange mpfrsort mpfrsqrt mpfrbigint mpfrstrtonum mpgforcenum
LOCALE_CHARSET_TESTS = \
@@ -2073,6 +2075,11 @@ mpfrrnd:
@$(AWK) -M -vPREC=53 -f "$(srcdir)"/$@.awk > _$@ 2>&1
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+mpfrrndeval:
+ @echo $@
+ @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
mpfrnegzero:
@echo $@
@$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
diff --git a/test/Makefile.in b/test/Makefile.in
index 5a190d7a..9775fd5b 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -924,6 +924,8 @@ EXTRA_DIST = \
mpfrrem.ok \
mpfrrnd.awk \
mpfrrnd.ok \
+ mpfrrndeval.awk \
+ mpfrrndeval.ok \
mpfrsort.awk \
mpfrsort.ok \
mpfrsqrt.awk \
@@ -1538,7 +1540,7 @@ ARRAYDEBUG_TESTS = arrdbg
EXTRA_TESTS = inftest regtest ignrcas3
INET_TESTS = inetdayu inetdayt inetechu inetecht
MACHINE_TESTS = double1 double2 fmtspcl intformat
-MPFR_TESTS = mpfrnr mpfrnegzero mpfrmemok1 mpfrrem mpfrrnd mpfrieee
+MPFR_TESTS = mpfrnr mpfrnegzero mpfrmemok1 mpfrrem mpfrrnd mpfrrndeval mpfrieee
LOCALE_CHARSET_TESTS = \
asort asorti backbigs1 backsmalls1 backsmalls2 \
fmttest fnarydel fnparydl jarebug lc_num1 mbfw1 \
@@ -2512,6 +2514,11 @@ mpfrrnd:
@$(AWK) -M -vPREC=53 -f "$(srcdir)"/$@.awk > _$@ 2>&1
@-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+mpfrrndeval:
+ @echo $@
+ @$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
+ @-$(CMP) "$(srcdir)"/$@.ok _$@ && rm -f _$@
+
mpfrnegzero:
@echo $@
@$(AWK) -M -f "$(srcdir)"/$@.awk > _$@ 2>&1
diff --git a/test/mpfrrndeval.awk b/test/mpfrrndeval.awk
new file mode 100644
index 00000000..12010052
--- /dev/null
+++ b/test/mpfrrndeval.awk
@@ -0,0 +1,35 @@
+# Tests side effects (like caching) on the evaluation (formatting and
+# rounding) of MPFR variables vs literals.
+BEGIN {
+ pi = 3.1416
+ e = 2.7183
+ golden = 1.6180
+
+ # Evaluated as number with (default) OFMT.
+ print pi
+ print e
+ print golden
+ printf "\n"
+
+ # Evaluated as number with (custom) OFMT.
+ OFMT = "%.f"
+ ROUNDMODE = "U"; print "Variable pi U:", pi
+ ROUNDMODE = "D"; print "Variable pi D:", pi
+ ROUNDMODE = "U"; print "Literal pi U:", 3.1416
+ ROUNDMODE = "D"; print "Literal pi D:", 3.1416
+ printf "\n"
+
+ # Evaluated as string with (custom) CONVFMT. Absent comma.
+ CONVFMT = "%.f"
+ ROUNDMODE = "D"; print "Variable e D: " e
+ ROUNDMODE = "U"; print "Variable e U: " e
+ ROUNDMODE = "D"; print "Literal e D: " 2.7183
+ ROUNDMODE = "U"; print "Literal e U: " 2.7183
+ printf "\n"
+
+ # Evaluated as number with (hardcoded) printf conversion.
+ ROUNDMODE = "N"; printf "Variable golden N: %.f\n", golden
+ ROUNDMODE = "Z"; printf "Variable golden Z: %.f\n", golden
+ ROUNDMODE = "N"; printf "Literal golden N: %.f\n", 1.6180
+ ROUNDMODE = "Z"; printf "Literal golden Z: %.f\n", 1.6180
+}
diff --git a/test/mpfrrndeval.ok b/test/mpfrrndeval.ok
new file mode 100644
index 00000000..034b21e0
--- /dev/null
+++ b/test/mpfrrndeval.ok
@@ -0,0 +1,18 @@
+3.1416
+2.7183
+1.618
+
+Variable pi U: 4
+Variable pi D: 3
+Literal pi U: 4
+Literal pi D: 3
+
+Variable e D: 2
+Variable e U: 3
+Literal e D: 2
+Literal e U: 3
+
+Variable golden N: 2
+Variable golden Z: 1
+Literal golden N: 2
+Literal golden Z: 1