diff options
-rw-r--r-- | ChangeLog | 28 | ||||
-rw-r--r-- | array.c | 5 | ||||
-rw-r--r-- | awk.h | 17 | ||||
-rw-r--r-- | awkgram.c | 3 | ||||
-rw-r--r-- | awkgram.y | 5 | ||||
-rw-r--r-- | builtin.c | 9 | ||||
-rw-r--r-- | doc/ChangeLog | 8 | ||||
-rw-r--r-- | doc/gawk.info | 333 | ||||
-rw-r--r-- | doc/gawk.texi | 65 | ||||
-rw-r--r-- | doc/gawktexi.in | 26 | ||||
-rw-r--r-- | field.c | 5 | ||||
-rw-r--r-- | gawkapi.c | 5 | ||||
-rw-r--r-- | interpret.h | 5 | ||||
-rw-r--r-- | mpfr.c | 7 | ||||
-rw-r--r-- | node.c | 11 | ||||
-rw-r--r-- | str_array.c | 4 | ||||
-rw-r--r-- | symbol.c | 5 | ||||
-rw-r--r-- | test/ChangeLog | 7 | ||||
-rw-r--r-- | test/Makefile.am | 9 | ||||
-rw-r--r-- | test/Makefile.in | 9 | ||||
-rw-r--r-- | test/mpfrrndeval.awk | 35 | ||||
-rw-r--r-- | test/mpfrrndeval.ok | 18 |
22 files changed, 443 insertions, 176 deletions
@@ -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 @@ -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 @@ -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); } @@ -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; @@ -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; @@ -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 @@ -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) { @@ -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; @@ -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); } @@ -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; @@ -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 |