aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--NEWS8
-rw-r--r--awk.h9
-rw-r--r--awklib/eg/test-programs/gen-float-table.awk59
-rw-r--r--awklib/eg/test-programs/gen-float-table.c60
-rw-r--r--awklib/eg/test-programs/gen-float-table.py42
-rw-r--r--builtin.c4
-rw-r--r--doc/ChangeLog27
-rw-r--r--doc/gawk.info1284
-rw-r--r--doc/gawk.texi273
-rw-r--r--doc/gawktexi.in273
-rw-r--r--doc/it/ChangeLog4
-rwxr-xr-x[-rw-r--r--]doc/it/gawktexi.in308
-rw-r--r--doc/wordlist2
-rw-r--r--eval.c96
-rw-r--r--interpret.h12
-rw-r--r--mpfr.c44
-rw-r--r--node.c5
18 files changed, 1804 insertions, 719 deletions
diff --git a/ChangeLog b/ChangeLog
index 5caf828c..4e36e5b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
2020-11-02 Arnold D. Robbins <arnold@skeeve.com>
+ Make gawk numeric comparisons act like C doubles.
+ MPFR differs from doubles w.r.t. NaN, not sure why yet.
+
+ * awk.h (scalar_cmp_t): New enum.
+ * builtin.c (format_nan_inf): Use mpfr_signbit, not mpfr_sgn.
+ * eval.c (cmp_doubles): New routine.
+ (cmp_scalars): Change type to bool, rework logic.
+ * interpret.h (r_interpret): Rework scalar comparisons.
+ * mpfr.c (mpg_cmp_as_numbers): New routine.
+ * node.c: Use <math.h>, not "math.h", minor comment edits.
+
+2020-11-02 Arnold D. Robbins <arnold@skeeve.com>
+
* re.c (make_regexp): Cast len parameter to int to avoid
compiler warnings.
diff --git a/NEWS b/NEWS
index b96cea7c..1d0a00b4 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,14 @@
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved.
+Changes from 5.1.x to 5.2.0
+---------------------------
+
+1. Numeric scalars now compare in the same way as C for the relational
+operators. Comparison order for sorting has not changed. This only
+makes a difference when comparing Infinity and NaN values with
+regular numbers; it should not be noticeable most of the time.
+
Changes from 5.1.0 to 5.1.1
---------------------------
diff --git a/awk.h b/awk.h
index cf06d490..0540ead7 100644
--- a/awk.h
+++ b/awk.h
@@ -1574,6 +1574,15 @@ typedef enum {
extern field_sep_type current_field_sep(void);
extern const char *current_field_sep_str(void);
+typedef enum {
+ SCALAR_EQ,
+ SCALAR_NEQ,
+ SCALAR_LT,
+ SCALAR_LE,
+ SCALAR_GT,
+ SCALAR_GE,
+} scalar_cmp_t;
+
/* gawkapi.c: */
extern gawk_api_t api_impl;
extern void init_ext_api(void);
diff --git a/awklib/eg/test-programs/gen-float-table.awk b/awklib/eg/test-programs/gen-float-table.awk
new file mode 100644
index 00000000..c35f2dff
--- /dev/null
+++ b/awklib/eg/test-programs/gen-float-table.awk
@@ -0,0 +1,59 @@
+function eq(left, right)
+{
+ return left == right
+}
+
+function ne(left, right)
+{
+ return left != right
+}
+
+function lt(left, right)
+{
+ return left < right
+}
+
+function le(left, right)
+{
+ return left <= right
+}
+
+function gt(left, right)
+{
+ return left > right
+}
+
+function ge(left, right)
+{
+ return left >= right
+}
+
+BEGIN {
+ nan = sqrt(-1)
+ inf = -log(0)
+ split("== != < <= > >=", names)
+ names[3] = names[3] " "
+ names[5] = names[5] " "
+ split("eq ne lt le gt ge", funcs)
+
+ compare[1] = 2.0
+ compare[2] = values[1] = -sqrt(-1.0) # nan
+ compare[3] = values[2] = sqrt(-1.0) # -nan
+ compare[4] = values[3] = -log(0.0) # inf
+ compare[5] = values[4] = log(0.0) # -inf
+
+ for (i = 1; i in values; i++) {
+ for (j = 1; j in compare; j++) {
+ for (k = 1; k in names; k++) {
+ the_func = funcs[k]
+ printf("%g %s %g -> %s\n",
+ values[i],
+ names[k],
+ compare[j],
+ the_func(values[i], compare[j]) ?
+ "true" : "false");
+ }
+ printf("\n");
+ }
+ }
+}
diff --git a/awklib/eg/test-programs/gen-float-table.c b/awklib/eg/test-programs/gen-float-table.c
new file mode 100644
index 00000000..ae1d5dd4
--- /dev/null
+++ b/awklib/eg/test-programs/gen-float-table.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <math.h>
+#include <stdbool.h>
+
+#define def_func(name, op) \
+ bool name(double left, double right) { \
+ return left op right; \
+ }
+
+def_func(eq, ==)
+def_func(ne, !=)
+def_func(lt, <)
+def_func(le, <=)
+def_func(gt, >)
+def_func(ge, >=)
+
+struct {
+ const char *name;
+ bool (*func)(double left, double right);
+} functions[] = {
+ { "==", eq },
+ { "!=", ne },
+ { "< ", lt },
+ { "<=", le },
+ { "> ", gt },
+ { ">=", ge },
+ { 0, 0 }
+};
+
+int main()
+{
+ double values[] = {
+ -sqrt(-1), // nan
+ sqrt(-1), // -nan
+ -log(0.0), // inf
+ log(0.0) // -inf
+ };
+ double compare[] = { 2.0,
+ -sqrt(-1), // nan
+ sqrt(-1), // -nan
+ -log(0.0), // inf
+ log(0.0) // -inf
+ };
+
+ int i, j, k;
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 5; j++) {
+ for (k = 0; functions[k].name != NULL; k++) {
+ printf("%g %s %g -> %s\n", values[i],
+ functions[k].name,
+ compare[j],
+ functions[k].func(values[i], compare[j]) ? "true" : "false");
+ }
+ printf("\n");
+ }
+ }
+
+ return 0;
+}
diff --git a/awklib/eg/test-programs/gen-float-table.py b/awklib/eg/test-programs/gen-float-table.py
new file mode 100644
index 00000000..8631b817
--- /dev/null
+++ b/awklib/eg/test-programs/gen-float-table.py
@@ -0,0 +1,42 @@
+from math import *
+
+nan = float('NaN')
+inf = float('Inf')
+
+def eq(left, right):
+ return left == right
+
+def ne(left, right):
+ return left != right
+
+def lt(left, right):
+ return left < right
+
+def le(left, right):
+ return left <= right
+
+def gt(left, right):
+ return left > right
+
+def ge(left, right):
+ return left >= right
+
+func_map = {
+ "==": eq,
+ "!=": ne,
+ "< ": lt,
+ "<=": le,
+ "> ": gt,
+ ">=": ge,
+}
+
+compare = [2.0, nan, -nan, inf, -inf]
+values = [nan, -nan, inf, -inf]
+
+for i in range(len(values)):
+ for j in range(len(compare)):
+ for op in func_map:
+ print("%g %s %g -> %s" %
+ (values[i], op, compare[j], func_map[op](values[i], compare[j])))
+
+ print("")
diff --git a/builtin.c b/builtin.c
index afd866ac..caf3d3b9 100644
--- a/builtin.c
+++ b/builtin.c
@@ -4293,11 +4293,11 @@ format_nan_inf(NODE *n, char format)
return NULL;
else if (is_mpg_float(n)) {
if (mpfr_nan_p(n->mpg_numbr)) {
- strcpy(buf, mpfr_sgn(n->mpg_numbr) < 0 ? "-nan" : "+nan");
+ strcpy(buf, mpfr_signbit(n->mpg_numbr) ? "-nan" : "+nan");
goto fmt;
} else if (mpfr_inf_p(n->mpg_numbr)) {
- strcpy(buf, mpfr_sgn(n->mpg_numbr) < 0 ? "-inf" : "+inf");
+ strcpy(buf, mpfr_signbit(n->mpg_numbr) ? "-inf" : "+inf");
goto fmt;
} else
diff --git a/doc/ChangeLog b/doc/ChangeLog
index 39d32ce3..de71baa5 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -24,12 +24,39 @@
* gawkworkflow.texi: Add an additional web resource.
* gawktexi.in: More edits in sample programs chapter.
+2020-11-20 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Strange values): Correct the description of what
+ happens with infinity. Thanks to Antonio Columbo for pointing
+ out the problem.
+
2020-11-16 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in (Nextfile Statement): Clarify what happens in
a BEGINFILE rule.
* gawktexi.in: Additional small fixes.
+2020-11-15 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Strange values): Add test programs inside
+ @ignore; extracted to example directory.
+
+2020-11-09 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in: Samll improvement in strange numbers section.
+
+2020-11-04 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Strange values): New section on NaN and infinity.
+ Update some other bits to point to it.
+ * wordlist: Updated with more words.
+
+2020-11-16 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Nextfile Statement): Clarify what happens in
+ a BEGINFILE rule.
+>>>>>>> master
+
2020-10-31 Arnold D. Robbins <arnold@skeeve.com>
* texinfo.tex: Updated from GNULIB.
diff --git a/doc/gawk.info b/doc/gawk.info
index 7a01d25a..258ddf71 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -547,6 +547,7 @@ in (a) below. A copy of the license is included in the section entitled
* Inexact representation:: Numbers are not exactly represented.
* Comparing FP Values:: How to compare floating point values.
* Errors accumulate:: Errors get bigger as they go.
+* Strange values:: A few words about infinities and NaNs.
* Getting Accuracy:: Getting more accuracy takes some work.
* Try To Round:: Add digits and round.
* Setting precision:: How to set the precision.
@@ -6914,8 +6915,8 @@ width. Here is a list of the format-control letters:
On systems supporting IEEE 754 floating-point format, values
representing negative infinity are formatted as '-inf' or
'-infinity', and positive infinity as 'inf' or 'infinity'. The
- special "not a number" value formats as '-nan' or 'nan' (*note Math
- Definitions::).
+ special "not a number" value formats as '-nan' or 'nan' (*note
+ Strange values::).
'%F'
Like '%f', but the infinity and "not a number" values are spelled
@@ -12807,7 +12808,7 @@ brackets ([ ]):
'log(X)'
Return the natural logarithm of X, if X is positive; otherwise,
- return 'NaN' ("not a number") on IEEE 754 systems. Additionally,
+ return NaN ("not a number") on IEEE 754 systems. Additionally,
'gawk' prints a warning message when 'x' is negative.
'rand()'
@@ -24190,18 +24191,10 @@ material here:
another number and infinity produce infinity.
"NaN"
- "Not a number."(1) A special value that results from attempting a
- calculation that has no answer as a real number. In such a case,
- programs can either receive a floating-point exception, or get
- 'NaN' back as the result. The IEEE 754 standard recommends that
- systems return 'NaN'. Some examples:
-
- 'sqrt(-1)'
- This makes sense in the range of complex numbers, but not in
- the range of real numbers, so the result is 'NaN'.
-
- 'log(-8)'
- -8 is out of the domain of 'log()', so the result is 'NaN'.
+ "Not a number." A special value that results from attempting a
+ calculation that has no answer as a real number. *Note Strange
+ values::, for more information about infinity and not-a-number
+ values.
"Normalized"
How the significand (see later in this list) is usually stored.
@@ -24260,11 +24253,6 @@ Table 16.3: Basic IEEE format values
NOTE: The precision numbers include the implied leading one that
gives them one extra bit of significand.
- ---------- Footnotes ----------
-
- (1) Thanks to Michael Brennan for this description, which we have
-paraphrased, and for the examples.
-

File: gawk.info, Node: MPFR features, Next: FP Math Caution, Prev: Math Definitions, Up: Arbitrary Precision Arithmetic
@@ -24357,6 +24345,7 @@ be sure of the number of significant decimal places in the final result.
* Inexact representation:: Numbers are not exactly represented.
* Comparing FP Values:: How to compare floating point values.
* Errors accumulate:: Errors get bigger as they go.
+* Strange values:: A few words about infinities and NaNs.

File: gawk.info, Node: Inexact representation, Next: Comparing FP Values, Up: Inexactness of computations
@@ -24421,7 +24410,7 @@ values with a delta, you should be sure to use 'difference < abs(delta)'
in case someone passes in a negative delta value.

-File: gawk.info, Node: Errors accumulate, Prev: Comparing FP Values, Up: Inexactness of computations
+File: gawk.info, Node: Errors accumulate, Next: Strange values, Prev: Comparing FP Values, Up: Inexactness of computations
16.4.1.3 Errors Accumulate
..........................
@@ -24469,6 +24458,64 @@ representations yield an unexpected result:
-| 4

+File: gawk.info, Node: Strange values, Prev: Errors accumulate, Up: Inexactness of computations
+
+16.4.1.4 Floating Point Values They Didn't Talk About In School
+...............................................................
+
+Both IEEE 754 floating-point hardware, and MPFR, support two kinds of
+values that you probably didn't learn about in school. The first is
+"infinity", a special value, that can be either negative or positive,
+and which is either smaller than any other value (negative infinity), or
+larger than any other value (positive infinity). When such values are
+generated, 'gawk' prints them as either '-inf' or '+inf', respectively.
+It accepts those strings as data input and converts them to the proper
+floating-point values internally.
+
+ Infinity values of the same sign compare as equal to each other.
+Otherwise, operations (addition, subtraction, etc.) involving another
+number and infinity produce mathematically reasonable results.
+
+ The second kind of value is "not a number", or NaN for short.(1)
+This is a special value that results from attempting a calculation that
+has no answer as a real number. In such a case, programs can either
+receive a floating-point exception, or get NaN back as the result. The
+IEEE 754 standard recommends that systems return NaN. Some examples:
+
+'sqrt(-1)'
+ This makes sense in the range of complex numbers, but not in the
+ range of real numbers, so the result is NaN.
+
+'log(-8)'
+ -8 is out of the domain of 'log()', so the result is NaN.
+
+ NaN values are strange. In particular, they cannot be compared with
+other floating point values; any such comparison, except for "is not
+equal to", returns false. NaN values are so much unequal to other
+values that even comparing two identical NaN values with '!=' returns
+true!
+
+ NaN values can also be signed, although it depends upon the
+implementation as to which sign you get for any operation that returns a
+NaN. For example, on some systems, 'sqrt(-1)' returns a negative NaN. On
+others, it returns a positive NaN.
+
+ When such values are generated, 'gawk' prints them as either '-nan'
+or '+nan', respectively. Here too, 'gawk' accepts those strings as data
+input and converts them to the proper floating-point values internally.
+
+ If you want to dive more deeply into this topic, you can find test
+programs in C, 'awk' and Python in the directory
+'awklib/eg/test-programs' in the 'gawk' distribution. These programs
+enable comparison among programming languages as to how they handle NaN
+and infinity values.
+
+ ---------- Footnotes ----------
+
+ (1) Thanks to Michael Brennan for this description, which we have
+paraphrased, and for the examples.
+
+
File: gawk.info, Node: Getting Accuracy, Next: Try To Round, Prev: Inexactness of computations, Up: FP Math Caution
16.4.2 Getting the Accuracy You Need
@@ -37971,603 +38018,604 @@ Index

Tag Table:
Node: Top1200
-Node: Foreword344559
-Node: Foreword449001
-Node: Preface50533
-Ref: Preface-Footnote-153392
-Ref: Preface-Footnote-253501
-Ref: Preface-Footnote-353735
-Node: History53877
-Node: Names56229
-Ref: Names-Footnote-157333
-Node: This Manual57480
-Ref: This Manual-Footnote-164119
-Node: Conventions64219
-Node: Manual History66588
-Ref: Manual History-Footnote-169585
-Ref: Manual History-Footnote-269626
-Node: How To Contribute69700
-Node: Acknowledgments70626
-Node: Getting Started75563
-Node: Running gawk78002
-Node: One-shot79192
-Node: Read Terminal80455
-Node: Long82448
-Node: Executable Scripts83961
-Ref: Executable Scripts-Footnote-186594
-Node: Comments86697
-Node: Quoting89181
-Node: DOS Quoting94707
-Node: Sample Data Files96763
-Node: Very Simple99358
-Node: Two Rules105460
-Node: More Complex107345
-Node: Statements/Lines109677
-Ref: Statements/Lines-Footnote-1114161
-Node: Other Features114426
-Node: When115362
-Ref: When-Footnote-1117116
-Node: Intro Summary117181
-Node: Invoking Gawk118065
-Node: Command Line119579
-Node: Options120377
-Ref: Options-Footnote-1138291
-Ref: Options-Footnote-2138522
-Node: Other Arguments138547
-Node: Naming Standard Input142558
-Node: Environment Variables143768
-Node: AWKPATH Variable144326
-Ref: AWKPATH Variable-Footnote-1147738
-Ref: AWKPATH Variable-Footnote-2147772
-Node: AWKLIBPATH Variable148143
-Ref: AWKLIBPATH Variable-Footnote-1149840
-Node: Other Environment Variables150215
-Node: Exit Status154036
-Node: Include Files154713
-Node: Loading Shared Libraries158403
-Node: Obsolete159831
-Node: Undocumented160523
-Node: Invoking Summary160820
-Node: Regexp163661
-Node: Regexp Usage165115
-Node: Escape Sequences167152
-Node: Regexp Operators173393
-Node: Regexp Operator Details173878
-Ref: Regexp Operator Details-Footnote-1180310
-Node: Interval Expressions180457
-Ref: Interval Expressions-Footnote-1181878
-Node: Bracket Expressions181976
-Ref: table-char-classes184452
-Node: Leftmost Longest187778
-Node: Computed Regexps189081
-Node: GNU Regexp Operators192508
-Node: Case-sensitivity196245
-Ref: Case-sensitivity-Footnote-1199111
-Ref: Case-sensitivity-Footnote-2199346
-Node: Regexp Summary199454
-Node: Reading Files200920
-Node: Records203189
-Node: awk split records204264
-Node: gawk split records208964
-Ref: gawk split records-Footnote-1213697
-Node: Fields213734
-Node: Nonconstant Fields216475
-Ref: Nonconstant Fields-Footnote-1218711
-Node: Changing Fields218915
-Node: Field Separators224946
-Node: Default Field Splitting227644
-Node: Regexp Field Splitting228762
-Node: Single Character Fields232115
-Node: Command Line Field Separator233175
-Node: Full Line Fields236393
-Ref: Full Line Fields-Footnote-1237915
-Ref: Full Line Fields-Footnote-2237961
-Node: Field Splitting Summary238062
-Node: Constant Size240136
-Node: Fixed width data240868
-Node: Skipping intervening244335
-Node: Allowing trailing data245133
-Node: Fields with fixed data246170
-Node: Splitting By Content247688
-Ref: Splitting By Content-Footnote-1251471
-Node: More CSV251634
-Node: Testing field creation252944
-Node: Multiple Line254569
-Node: Getline260846
-Node: Plain Getline263315
-Node: Getline/Variable265888
-Node: Getline/File267039
-Node: Getline/Variable/File268427
-Ref: Getline/Variable/File-Footnote-1270032
-Node: Getline/Pipe270120
-Node: Getline/Variable/Pipe272824
-Node: Getline/Coprocess273959
-Node: Getline/Variable/Coprocess275226
-Node: Getline Notes275968
-Node: Getline Summary278765
-Ref: table-getline-variants279189
-Node: Read Timeout279937
-Ref: Read Timeout-Footnote-1283843
-Node: Retrying Input283901
-Node: Command-line directories285100
-Node: Input Summary286006
-Node: Input Exercises289178
-Node: Printing289612
-Node: Print291446
-Node: Print Examples292903
-Node: Output Separators295683
-Node: OFMT297700
-Node: Printf299056
-Node: Basic Printf299841
-Node: Control Letters301415
-Node: Format Modifiers306579
-Node: Printf Examples312594
-Node: Redirection315080
-Node: Special FD321921
-Ref: Special FD-Footnote-1325089
-Node: Special Files325163
-Node: Other Inherited Files325780
-Node: Special Network326781
-Node: Special Caveats327641
-Node: Close Files And Pipes328590
-Ref: table-close-pipe-return-values335497
-Ref: Close Files And Pipes-Footnote-1336310
-Ref: Close Files And Pipes-Footnote-2336458
-Node: Nonfatal336610
-Node: Output Summary338948
-Node: Output Exercises340170
-Node: Expressions340849
-Node: Values342037
-Node: Constants342715
-Node: Scalar Constants343406
-Ref: Scalar Constants-Footnote-1345916
-Node: Nondecimal-numbers346166
-Node: Regexp Constants349167
-Node: Using Constant Regexps349693
-Node: Standard Regexp Constants350315
-Node: Strong Regexp Constants353503
-Node: Variables356515
-Node: Using Variables357172
-Node: Assignment Options359082
-Node: Conversion361553
-Node: Strings And Numbers362077
-Ref: Strings And Numbers-Footnote-1365140
-Node: Locale influences conversions365249
-Ref: table-locale-affects368007
-Node: All Operators368625
-Node: Arithmetic Ops369254
-Node: Concatenation371970
-Ref: Concatenation-Footnote-1374817
-Node: Assignment Ops374924
-Ref: table-assign-ops379915
-Node: Increment Ops381228
-Node: Truth Values and Conditions384688
-Node: Truth Values385762
-Node: Typing and Comparison386810
-Node: Variable Typing387630
-Ref: Variable Typing-Footnote-1394093
-Ref: Variable Typing-Footnote-2394165
-Node: Comparison Operators394242
-Ref: table-relational-ops394661
-Node: POSIX String Comparison398156
-Ref: POSIX String Comparison-Footnote-1399851
-Ref: POSIX String Comparison-Footnote-2399990
-Node: Boolean Ops400074
-Ref: Boolean Ops-Footnote-1404556
-Node: Conditional Exp404648
-Node: Function Calls406384
-Node: Precedence410261
-Node: Locales413920
-Node: Expressions Summary415552
-Node: Patterns and Actions418125
-Node: Pattern Overview419245
-Node: Regexp Patterns420922
-Node: Expression Patterns421464
-Node: Ranges425245
-Node: BEGIN/END428353
-Node: Using BEGIN/END429114
-Ref: Using BEGIN/END-Footnote-1431868
-Node: I/O And BEGIN/END431974
-Node: BEGINFILE/ENDFILE434287
-Node: Empty437518
-Node: Using Shell Variables437835
-Node: Action Overview440109
-Node: Statements442434
-Node: If Statement444282
-Node: While Statement445777
-Node: Do Statement447805
-Node: For Statement448953
-Node: Switch Statement452124
-Node: Break Statement454565
-Node: Continue Statement456657
-Node: Next Statement458484
-Node: Nextfile Statement460867
-Node: Exit Statement463556
-Node: Built-in Variables465959
-Node: User-modified467092
-Node: Auto-set474859
-Ref: Auto-set-Footnote-1491666
-Ref: Auto-set-Footnote-2491872
-Node: ARGC and ARGV491928
-Node: Pattern Action Summary496141
-Node: Arrays498571
-Node: Array Basics499900
-Node: Array Intro500744
-Ref: figure-array-elements502719
-Ref: Array Intro-Footnote-1505423
-Node: Reference to Elements505551
-Node: Assigning Elements508015
-Node: Array Example508506
-Node: Scanning an Array510265
-Node: Controlling Scanning513287
-Ref: Controlling Scanning-Footnote-1519743
-Node: Numeric Array Subscripts520059
-Node: Uninitialized Subscripts522243
-Node: Delete523862
-Ref: Delete-Footnote-1526614
-Node: Multidimensional526671
-Node: Multiscanning529766
-Node: Arrays of Arrays531357
-Node: Arrays Summary536125
-Node: Functions538218
-Node: Built-in539256
-Node: Calling Built-in540337
-Node: Numeric Functions542333
-Ref: Numeric Functions-Footnote-1546361
-Ref: Numeric Functions-Footnote-2547009
-Ref: Numeric Functions-Footnote-3547057
-Node: String Functions547329
-Ref: String Functions-Footnote-1571470
-Ref: String Functions-Footnote-2571598
-Ref: String Functions-Footnote-3571846
-Node: Gory Details571933
-Ref: table-sub-escapes573724
-Ref: table-sub-proposed575243
-Ref: table-posix-sub576606
-Ref: table-gensub-escapes578147
-Ref: Gory Details-Footnote-1578970
-Node: I/O Functions579124
-Ref: table-system-return-values585578
-Ref: I/O Functions-Footnote-1587658
-Ref: I/O Functions-Footnote-2587806
-Node: Time Functions587926
-Ref: Time Functions-Footnote-1598597
-Ref: Time Functions-Footnote-2598665
-Ref: Time Functions-Footnote-3598823
-Ref: Time Functions-Footnote-4598934
-Ref: Time Functions-Footnote-5599046
-Ref: Time Functions-Footnote-6599273
-Node: Bitwise Functions599539
-Ref: table-bitwise-ops600133
-Ref: Bitwise Functions-Footnote-1606196
-Ref: Bitwise Functions-Footnote-2606369
-Node: Type Functions606560
-Node: I18N Functions609423
-Node: User-defined611074
-Node: Definition Syntax611886
-Ref: Definition Syntax-Footnote-1617580
-Node: Function Example617651
-Ref: Function Example-Footnote-1620573
-Node: Function Calling620595
-Node: Calling A Function621183
-Node: Variable Scope622141
-Node: Pass By Value/Reference625135
-Node: Function Caveats627779
-Ref: Function Caveats-Footnote-1629826
-Node: Return Statement629946
-Node: Dynamic Typing632925
-Node: Indirect Calls633855
-Ref: Indirect Calls-Footnote-1644107
-Node: Functions Summary644235
-Node: Library Functions646940
-Ref: Library Functions-Footnote-1650547
-Ref: Library Functions-Footnote-2650690
-Node: Library Names650861
-Ref: Library Names-Footnote-1654528
-Ref: Library Names-Footnote-2654751
-Node: General Functions654837
-Node: Strtonum Function655940
-Node: Assert Function658962
-Node: Round Function662288
-Node: Cliff Random Function663828
-Node: Ordinal Functions664844
-Ref: Ordinal Functions-Footnote-1667907
-Ref: Ordinal Functions-Footnote-2668159
-Node: Join Function668369
-Ref: Join Function-Footnote-1670139
-Node: Getlocaltime Function670339
-Node: Readfile Function674081
-Node: Shell Quoting676058
-Node: Data File Management677459
-Node: Filetrans Function678091
-Node: Rewind Function682187
-Node: File Checking684096
-Ref: File Checking-Footnote-1685430
-Node: Empty Files685631
-Node: Ignoring Assigns687610
-Node: Getopt Function689160
-Ref: Getopt Function-Footnote-1704371
-Node: Passwd Functions704571
-Ref: Passwd Functions-Footnote-1713410
-Node: Group Functions713498
-Ref: Group Functions-Footnote-1721396
-Node: Walking Arrays721603
-Node: Library Functions Summary724611
-Node: Library Exercises726017
-Node: Sample Programs726482
-Node: Running Examples727252
-Node: Clones727980
-Node: Cut Program729204
-Node: Egrep Program739344
-Node: Id Program748355
-Node: Split Program758302
-Ref: Split Program-Footnote-1768192
-Node: Tee Program768365
-Node: Uniq Program771155
-Node: Wc Program778743
-Node: Bytes vs. Characters779140
-Node: Using extensions780688
-Node: wc program781442
-Node: Miscellaneous Programs786307
-Node: Dupword Program787520
-Node: Alarm Program789550
-Node: Translate Program794405
-Ref: Translate Program-Footnote-1798970
-Node: Labels Program799240
-Ref: Labels Program-Footnote-1802591
-Node: Word Sorting802675
-Node: History Sorting806747
-Node: Extract Program808972
-Node: Simple Sed817026
-Node: Igawk Program820100
-Ref: Igawk Program-Footnote-1834431
-Ref: Igawk Program-Footnote-2834633
-Ref: Igawk Program-Footnote-3834755
-Node: Anagram Program834870
-Node: Signature Program837932
-Node: Programs Summary839179
-Node: Programs Exercises840393
-Ref: Programs Exercises-Footnote-1844523
-Node: Advanced Features844609
-Node: Nondecimal Data846676
-Node: Array Sorting848267
-Node: Controlling Array Traversal848967
-Ref: Controlling Array Traversal-Footnote-1857335
-Node: Array Sorting Functions857453
-Ref: Array Sorting Functions-Footnote-1862544
-Node: Two-way I/O862740
-Ref: Two-way I/O-Footnote-1870461
-Ref: Two-way I/O-Footnote-2870648
-Node: TCP/IP Networking870730
-Node: Profiling873848
-Node: Extension Philosophy883157
-Node: Advanced Features Summary884608
-Node: Internationalization886607
-Node: I18N and L10N888087
-Node: Explaining gettext888774
-Ref: Explaining gettext-Footnote-1894666
-Ref: Explaining gettext-Footnote-2894851
-Node: Programmer i18n895016
-Ref: Programmer i18n-Footnote-1899965
-Node: Translator i18n900014
-Node: String Extraction900808
-Ref: String Extraction-Footnote-1901940
-Node: Printf Ordering902026
-Ref: Printf Ordering-Footnote-1904812
-Node: I18N Portability904876
-Ref: I18N Portability-Footnote-1907332
-Node: I18N Example907395
-Ref: I18N Example-Footnote-1910670
-Ref: I18N Example-Footnote-2910743
-Node: Gawk I18N910852
-Node: I18N Summary911501
-Node: Debugger912842
-Node: Debugging913842
-Node: Debugging Concepts914283
-Node: Debugging Terms916092
-Node: Awk Debugging918667
-Ref: Awk Debugging-Footnote-1919612
-Node: Sample Debugging Session919744
-Node: Debugger Invocation920278
-Node: Finding The Bug921664
-Node: List of Debugger Commands928138
-Node: Breakpoint Control929471
-Node: Debugger Execution Control933165
-Node: Viewing And Changing Data936527
-Node: Execution Stack940068
-Node: Debugger Info941705
-Node: Miscellaneous Debugger Commands945776
-Node: Readline Support950838
-Node: Limitations951734
-Node: Debugging Summary954288
-Node: Namespaces955567
-Node: Global Namespace956678
-Node: Qualified Names958076
-Node: Default Namespace959075
-Node: Changing The Namespace959816
-Node: Naming Rules961430
-Node: Internal Name Management963278
-Node: Namespace Example964320
-Node: Namespace And Features966882
-Node: Namespace Summary968317
-Node: Arbitrary Precision Arithmetic969794
-Node: Computer Arithmetic971281
-Ref: table-numeric-ranges975047
-Ref: table-floating-point-ranges975540
-Ref: Computer Arithmetic-Footnote-1976198
-Node: Math Definitions976255
-Ref: table-ieee-formats979571
-Ref: Math Definitions-Footnote-1980174
-Node: MPFR features980279
-Node: FP Math Caution981997
-Ref: FP Math Caution-Footnote-1983069
-Node: Inexactness of computations983438
-Node: Inexact representation984398
-Node: Comparing FP Values985758
-Node: Errors accumulate986999
-Node: Getting Accuracy988432
-Node: Try To Round991142
-Node: Setting precision992041
-Ref: table-predefined-precision-strings992738
-Node: Setting the rounding mode994568
-Ref: table-gawk-rounding-modes994942
-Ref: Setting the rounding mode-Footnote-1998873
-Node: Arbitrary Precision Integers999052
-Ref: Arbitrary Precision Integers-Footnote-11002227
-Node: Checking for MPFR1002376
-Node: POSIX Floating Point Problems1003850
-Ref: POSIX Floating Point Problems-Footnote-11008135
-Node: Floating point summary1008173
-Node: Dynamic Extensions1010363
-Node: Extension Intro1011916
-Node: Plugin License1013182
-Node: Extension Mechanism Outline1013979
-Ref: figure-load-extension1014418
-Ref: figure-register-new-function1015983
-Ref: figure-call-new-function1017075
-Node: Extension API Description1019137
-Node: Extension API Functions Introduction1020850
-Ref: table-api-std-headers1022686
-Node: General Data Types1026935
-Ref: General Data Types-Footnote-11035565
-Node: Memory Allocation Functions1035864
-Ref: Memory Allocation Functions-Footnote-11040365
-Node: Constructor Functions1040464
-Node: API Ownership of MPFR and GMP Values1043930
-Node: Registration Functions1045243
-Node: Extension Functions1045943
-Node: Exit Callback Functions1051265
-Node: Extension Version String1052515
-Node: Input Parsers1053178
-Node: Output Wrappers1065899
-Node: Two-way processors1070411
-Node: Printing Messages1072676
-Ref: Printing Messages-Footnote-11073847
-Node: Updating ERRNO1074000
-Node: Requesting Values1074739
-Ref: table-value-types-returned1075476
-Node: Accessing Parameters1076412
-Node: Symbol Table Access1077649
-Node: Symbol table by name1078161
-Ref: Symbol table by name-Footnote-11081185
-Node: Symbol table by cookie1081313
-Ref: Symbol table by cookie-Footnote-11085498
-Node: Cached values1085562
-Ref: Cached values-Footnote-11089098
-Node: Array Manipulation1089251
-Ref: Array Manipulation-Footnote-11090342
-Node: Array Data Types1090379
-Ref: Array Data Types-Footnote-11093037
-Node: Array Functions1093129
-Node: Flattening Arrays1097627
-Node: Creating Arrays1104603
-Node: Redirection API1109370
-Node: Extension API Variables1112203
-Node: Extension Versioning1112914
-Ref: gawk-api-version1113343
-Node: Extension GMP/MPFR Versioning1115074
-Node: Extension API Informational Variables1116702
-Node: Extension API Boilerplate1117775
-Node: Changes from API V11121749
-Node: Finding Extensions1123321
-Node: Extension Example1123880
-Node: Internal File Description1124678
-Node: Internal File Ops1128758
-Ref: Internal File Ops-Footnote-11140108
-Node: Using Internal File Ops1140248
-Ref: Using Internal File Ops-Footnote-11142631
-Node: Extension Samples1142905
-Node: Extension Sample File Functions1144434
-Node: Extension Sample Fnmatch1152083
-Node: Extension Sample Fork1153570
-Node: Extension Sample Inplace1154788
-Node: Extension Sample Ord1158414
-Node: Extension Sample Readdir1159250
-Ref: table-readdir-file-types1160139
-Node: Extension Sample Revout1161206
-Node: Extension Sample Rev2way1161795
-Node: Extension Sample Read write array1162535
-Node: Extension Sample Readfile1164477
-Node: Extension Sample Time1165572
-Node: Extension Sample API Tests1167324
-Node: gawkextlib1167816
-Node: Extension summary1170734
-Node: Extension Exercises1174436
-Node: Language History1175678
-Node: V7/SVR3.11177334
-Node: SVR41179486
-Node: POSIX1180920
-Node: BTL1182301
-Node: POSIX/GNU1183030
-Node: Feature History1188808
-Node: Common Extensions1205127
-Node: Ranges and Locales1206410
-Ref: Ranges and Locales-Footnote-11211026
-Ref: Ranges and Locales-Footnote-21211053
-Ref: Ranges and Locales-Footnote-31211288
-Node: Contributors1211511
-Node: History summary1217508
-Node: Installation1218888
-Node: Gawk Distribution1219832
-Node: Getting1220316
-Node: Extracting1221279
-Node: Distribution contents1222917
-Node: Unix Installation1229397
-Node: Quick Installation1230079
-Node: Shell Startup Files1232493
-Node: Additional Configuration Options1233582
-Node: Configuration Philosophy1235897
-Node: Non-Unix Installation1238266
-Node: PC Installation1238726
-Node: PC Binary Installation1239564
-Node: PC Compiling1239999
-Node: PC Using1241116
-Node: Cygwin1244669
-Node: MSYS1245893
-Node: VMS Installation1246495
-Node: VMS Compilation1247286
-Ref: VMS Compilation-Footnote-11248515
-Node: VMS Dynamic Extensions1248573
-Node: VMS Installation Details1250258
-Node: VMS Running1252511
-Node: VMS GNV1256790
-Node: VMS Old Gawk1257525
-Node: Bugs1257996
-Node: Bug address1258659
-Node: Usenet1261641
-Node: Maintainers1262645
-Node: Other Versions1263830
-Node: Installation summary1270918
-Node: Notes1272127
-Node: Compatibility Mode1272921
-Node: Additions1273703
-Node: Accessing The Source1274628
-Node: Adding Code1276065
-Node: New Ports1282284
-Node: Derived Files1286659
-Ref: Derived Files-Footnote-11292319
-Ref: Derived Files-Footnote-21292354
-Ref: Derived Files-Footnote-31292952
-Node: Future Extensions1293066
-Node: Implementation Limitations1293724
-Node: Extension Design1294934
-Node: Old Extension Problems1296078
-Ref: Old Extension Problems-Footnote-11297596
-Node: Extension New Mechanism Goals1297653
-Ref: Extension New Mechanism Goals-Footnote-11301017
-Node: Extension Other Design Decisions1301206
-Node: Extension Future Growth1303319
-Node: Notes summary1303925
-Node: Basic Concepts1305083
-Node: Basic High Level1305764
-Ref: figure-general-flow1306046
-Ref: figure-process-flow1306731
-Ref: Basic High Level-Footnote-11310032
-Node: Basic Data Typing1310217
-Node: Glossary1313545
-Node: Copying1345430
-Node: GNU Free Documentation License1382973
-Node: Index1408093
+Node: Foreword344638
+Node: Foreword449080
+Node: Preface50612
+Ref: Preface-Footnote-153471
+Ref: Preface-Footnote-253580
+Ref: Preface-Footnote-353814
+Node: History53956
+Node: Names56308
+Ref: Names-Footnote-157412
+Node: This Manual57559
+Ref: This Manual-Footnote-164198
+Node: Conventions64298
+Node: Manual History66667
+Ref: Manual History-Footnote-169664
+Ref: Manual History-Footnote-269705
+Node: How To Contribute69779
+Node: Acknowledgments70705
+Node: Getting Started75642
+Node: Running gawk78081
+Node: One-shot79271
+Node: Read Terminal80534
+Node: Long82527
+Node: Executable Scripts84040
+Ref: Executable Scripts-Footnote-186673
+Node: Comments86776
+Node: Quoting89260
+Node: DOS Quoting94786
+Node: Sample Data Files96842
+Node: Very Simple99437
+Node: Two Rules105539
+Node: More Complex107424
+Node: Statements/Lines109756
+Ref: Statements/Lines-Footnote-1114240
+Node: Other Features114505
+Node: When115441
+Ref: When-Footnote-1117195
+Node: Intro Summary117260
+Node: Invoking Gawk118144
+Node: Command Line119658
+Node: Options120456
+Ref: Options-Footnote-1138370
+Ref: Options-Footnote-2138601
+Node: Other Arguments138626
+Node: Naming Standard Input142637
+Node: Environment Variables143847
+Node: AWKPATH Variable144405
+Ref: AWKPATH Variable-Footnote-1147817
+Ref: AWKPATH Variable-Footnote-2147851
+Node: AWKLIBPATH Variable148222
+Ref: AWKLIBPATH Variable-Footnote-1149919
+Node: Other Environment Variables150294
+Node: Exit Status154115
+Node: Include Files154792
+Node: Loading Shared Libraries158482
+Node: Obsolete159910
+Node: Undocumented160602
+Node: Invoking Summary160899
+Node: Regexp163740
+Node: Regexp Usage165194
+Node: Escape Sequences167231
+Node: Regexp Operators173472
+Node: Regexp Operator Details173957
+Ref: Regexp Operator Details-Footnote-1180389
+Node: Interval Expressions180536
+Ref: Interval Expressions-Footnote-1181957
+Node: Bracket Expressions182055
+Ref: table-char-classes184531
+Node: Leftmost Longest187857
+Node: Computed Regexps189160
+Node: GNU Regexp Operators192587
+Node: Case-sensitivity196324
+Ref: Case-sensitivity-Footnote-1199190
+Ref: Case-sensitivity-Footnote-2199425
+Node: Regexp Summary199533
+Node: Reading Files200999
+Node: Records203268
+Node: awk split records204343
+Node: gawk split records209043
+Ref: gawk split records-Footnote-1213776
+Node: Fields213813
+Node: Nonconstant Fields216554
+Ref: Nonconstant Fields-Footnote-1218790
+Node: Changing Fields218994
+Node: Field Separators225025
+Node: Default Field Splitting227723
+Node: Regexp Field Splitting228841
+Node: Single Character Fields232194
+Node: Command Line Field Separator233254
+Node: Full Line Fields236472
+Ref: Full Line Fields-Footnote-1237994
+Ref: Full Line Fields-Footnote-2238040
+Node: Field Splitting Summary238141
+Node: Constant Size240215
+Node: Fixed width data240947
+Node: Skipping intervening244414
+Node: Allowing trailing data245212
+Node: Fields with fixed data246249
+Node: Splitting By Content247767
+Ref: Splitting By Content-Footnote-1251550
+Node: More CSV251713
+Node: Testing field creation253023
+Node: Multiple Line254648
+Node: Getline260925
+Node: Plain Getline263394
+Node: Getline/Variable265967
+Node: Getline/File267118
+Node: Getline/Variable/File268506
+Ref: Getline/Variable/File-Footnote-1270111
+Node: Getline/Pipe270199
+Node: Getline/Variable/Pipe272903
+Node: Getline/Coprocess274038
+Node: Getline/Variable/Coprocess275305
+Node: Getline Notes276047
+Node: Getline Summary278844
+Ref: table-getline-variants279268
+Node: Read Timeout280016
+Ref: Read Timeout-Footnote-1283922
+Node: Retrying Input283980
+Node: Command-line directories285179
+Node: Input Summary286085
+Node: Input Exercises289257
+Node: Printing289691
+Node: Print291525
+Node: Print Examples292982
+Node: Output Separators295762
+Node: OFMT297779
+Node: Printf299135
+Node: Basic Printf299920
+Node: Control Letters301494
+Node: Format Modifiers306656
+Node: Printf Examples312671
+Node: Redirection315157
+Node: Special FD321998
+Ref: Special FD-Footnote-1325166
+Node: Special Files325240
+Node: Other Inherited Files325857
+Node: Special Network326858
+Node: Special Caveats327718
+Node: Close Files And Pipes328667
+Ref: table-close-pipe-return-values335574
+Ref: Close Files And Pipes-Footnote-1336387
+Ref: Close Files And Pipes-Footnote-2336535
+Node: Nonfatal336687
+Node: Output Summary339025
+Node: Output Exercises340247
+Node: Expressions340926
+Node: Values342114
+Node: Constants342792
+Node: Scalar Constants343483
+Ref: Scalar Constants-Footnote-1345993
+Node: Nondecimal-numbers346243
+Node: Regexp Constants349244
+Node: Using Constant Regexps349770
+Node: Standard Regexp Constants350392
+Node: Strong Regexp Constants353580
+Node: Variables356592
+Node: Using Variables357249
+Node: Assignment Options359159
+Node: Conversion361630
+Node: Strings And Numbers362154
+Ref: Strings And Numbers-Footnote-1365217
+Node: Locale influences conversions365326
+Ref: table-locale-affects368084
+Node: All Operators368702
+Node: Arithmetic Ops369331
+Node: Concatenation372047
+Ref: Concatenation-Footnote-1374894
+Node: Assignment Ops375001
+Ref: table-assign-ops379992
+Node: Increment Ops381305
+Node: Truth Values and Conditions384765
+Node: Truth Values385839
+Node: Typing and Comparison386887
+Node: Variable Typing387707
+Ref: Variable Typing-Footnote-1394170
+Ref: Variable Typing-Footnote-2394242
+Node: Comparison Operators394319
+Ref: table-relational-ops394738
+Node: POSIX String Comparison398233
+Ref: POSIX String Comparison-Footnote-1399928
+Ref: POSIX String Comparison-Footnote-2400067
+Node: Boolean Ops400151
+Ref: Boolean Ops-Footnote-1404633
+Node: Conditional Exp404725
+Node: Function Calls406461
+Node: Precedence410338
+Node: Locales413997
+Node: Expressions Summary415629
+Node: Patterns and Actions418202
+Node: Pattern Overview419322
+Node: Regexp Patterns420999
+Node: Expression Patterns421541
+Node: Ranges425322
+Node: BEGIN/END428430
+Node: Using BEGIN/END429191
+Ref: Using BEGIN/END-Footnote-1431945
+Node: I/O And BEGIN/END432051
+Node: BEGINFILE/ENDFILE434364
+Node: Empty437595
+Node: Using Shell Variables437912
+Node: Action Overview440186
+Node: Statements442511
+Node: If Statement444359
+Node: While Statement445854
+Node: Do Statement447882
+Node: For Statement449030
+Node: Switch Statement452201
+Node: Break Statement454642
+Node: Continue Statement456734
+Node: Next Statement458561
+Node: Nextfile Statement460944
+Node: Exit Statement463633
+Node: Built-in Variables466036
+Node: User-modified467169
+Node: Auto-set474936
+Ref: Auto-set-Footnote-1491743
+Ref: Auto-set-Footnote-2491949
+Node: ARGC and ARGV492005
+Node: Pattern Action Summary496218
+Node: Arrays498648
+Node: Array Basics499977
+Node: Array Intro500821
+Ref: figure-array-elements502796
+Ref: Array Intro-Footnote-1505500
+Node: Reference to Elements505628
+Node: Assigning Elements508092
+Node: Array Example508583
+Node: Scanning an Array510342
+Node: Controlling Scanning513364
+Ref: Controlling Scanning-Footnote-1519820
+Node: Numeric Array Subscripts520136
+Node: Uninitialized Subscripts522320
+Node: Delete523939
+Ref: Delete-Footnote-1526691
+Node: Multidimensional526748
+Node: Multiscanning529843
+Node: Arrays of Arrays531434
+Node: Arrays Summary536202
+Node: Functions538295
+Node: Built-in539333
+Node: Calling Built-in540414
+Node: Numeric Functions542410
+Ref: Numeric Functions-Footnote-1546436
+Ref: Numeric Functions-Footnote-2547084
+Ref: Numeric Functions-Footnote-3547132
+Node: String Functions547404
+Ref: String Functions-Footnote-1571545
+Ref: String Functions-Footnote-2571673
+Ref: String Functions-Footnote-3571921
+Node: Gory Details572008
+Ref: table-sub-escapes573799
+Ref: table-sub-proposed575318
+Ref: table-posix-sub576681
+Ref: table-gensub-escapes578222
+Ref: Gory Details-Footnote-1579045
+Node: I/O Functions579199
+Ref: table-system-return-values585653
+Ref: I/O Functions-Footnote-1587733
+Ref: I/O Functions-Footnote-2587881
+Node: Time Functions588001
+Ref: Time Functions-Footnote-1598672
+Ref: Time Functions-Footnote-2598740
+Ref: Time Functions-Footnote-3598898
+Ref: Time Functions-Footnote-4599009
+Ref: Time Functions-Footnote-5599121
+Ref: Time Functions-Footnote-6599348
+Node: Bitwise Functions599614
+Ref: table-bitwise-ops600208
+Ref: Bitwise Functions-Footnote-1606271
+Ref: Bitwise Functions-Footnote-2606444
+Node: Type Functions606635
+Node: I18N Functions609498
+Node: User-defined611149
+Node: Definition Syntax611961
+Ref: Definition Syntax-Footnote-1617655
+Node: Function Example617726
+Ref: Function Example-Footnote-1620648
+Node: Function Calling620670
+Node: Calling A Function621258
+Node: Variable Scope622216
+Node: Pass By Value/Reference625210
+Node: Function Caveats627854
+Ref: Function Caveats-Footnote-1629901
+Node: Return Statement630021
+Node: Dynamic Typing633000
+Node: Indirect Calls633930
+Ref: Indirect Calls-Footnote-1644182
+Node: Functions Summary644310
+Node: Library Functions647015
+Ref: Library Functions-Footnote-1650622
+Ref: Library Functions-Footnote-2650765
+Node: Library Names650936
+Ref: Library Names-Footnote-1654603
+Ref: Library Names-Footnote-2654826
+Node: General Functions654912
+Node: Strtonum Function656015
+Node: Assert Function659037
+Node: Round Function662363
+Node: Cliff Random Function663903
+Node: Ordinal Functions664919
+Ref: Ordinal Functions-Footnote-1667982
+Ref: Ordinal Functions-Footnote-2668234
+Node: Join Function668444
+Ref: Join Function-Footnote-1670214
+Node: Getlocaltime Function670414
+Node: Readfile Function674156
+Node: Shell Quoting676133
+Node: Data File Management677534
+Node: Filetrans Function678166
+Node: Rewind Function682262
+Node: File Checking684171
+Ref: File Checking-Footnote-1685505
+Node: Empty Files685706
+Node: Ignoring Assigns687685
+Node: Getopt Function689235
+Ref: Getopt Function-Footnote-1704446
+Node: Passwd Functions704646
+Ref: Passwd Functions-Footnote-1713485
+Node: Group Functions713573
+Ref: Group Functions-Footnote-1721471
+Node: Walking Arrays721678
+Node: Library Functions Summary724686
+Node: Library Exercises726092
+Node: Sample Programs726557
+Node: Running Examples727327
+Node: Clones728055
+Node: Cut Program729279
+Node: Egrep Program739419
+Node: Id Program748430
+Node: Split Program758377
+Ref: Split Program-Footnote-1768267
+Node: Tee Program768440
+Node: Uniq Program771230
+Node: Wc Program778818
+Node: Bytes vs. Characters779215
+Node: Using extensions780763
+Node: wc program781517
+Node: Miscellaneous Programs786382
+Node: Dupword Program787595
+Node: Alarm Program789625
+Node: Translate Program794480
+Ref: Translate Program-Footnote-1799045
+Node: Labels Program799315
+Ref: Labels Program-Footnote-1802666
+Node: Word Sorting802750
+Node: History Sorting806822
+Node: Extract Program809047
+Node: Simple Sed817101
+Node: Igawk Program820175
+Ref: Igawk Program-Footnote-1834506
+Ref: Igawk Program-Footnote-2834708
+Ref: Igawk Program-Footnote-3834830
+Node: Anagram Program834945
+Node: Signature Program838007
+Node: Programs Summary839254
+Node: Programs Exercises840468
+Ref: Programs Exercises-Footnote-1844598
+Node: Advanced Features844684
+Node: Nondecimal Data846751
+Node: Array Sorting848342
+Node: Controlling Array Traversal849042
+Ref: Controlling Array Traversal-Footnote-1857410
+Node: Array Sorting Functions857528
+Ref: Array Sorting Functions-Footnote-1862619
+Node: Two-way I/O862815
+Ref: Two-way I/O-Footnote-1870536
+Ref: Two-way I/O-Footnote-2870723
+Node: TCP/IP Networking870805
+Node: Profiling873923
+Node: Extension Philosophy883232
+Node: Advanced Features Summary884683
+Node: Internationalization886682
+Node: I18N and L10N888162
+Node: Explaining gettext888849
+Ref: Explaining gettext-Footnote-1894741
+Ref: Explaining gettext-Footnote-2894926
+Node: Programmer i18n895091
+Ref: Programmer i18n-Footnote-1900040
+Node: Translator i18n900089
+Node: String Extraction900883
+Ref: String Extraction-Footnote-1902015
+Node: Printf Ordering902101
+Ref: Printf Ordering-Footnote-1904887
+Node: I18N Portability904951
+Ref: I18N Portability-Footnote-1907407
+Node: I18N Example907470
+Ref: I18N Example-Footnote-1910745
+Ref: I18N Example-Footnote-2910818
+Node: Gawk I18N910927
+Node: I18N Summary911576
+Node: Debugger912917
+Node: Debugging913917
+Node: Debugging Concepts914358
+Node: Debugging Terms916167
+Node: Awk Debugging918742
+Ref: Awk Debugging-Footnote-1919687
+Node: Sample Debugging Session919819
+Node: Debugger Invocation920353
+Node: Finding The Bug921739
+Node: List of Debugger Commands928213
+Node: Breakpoint Control929546
+Node: Debugger Execution Control933240
+Node: Viewing And Changing Data936602
+Node: Execution Stack940143
+Node: Debugger Info941780
+Node: Miscellaneous Debugger Commands945851
+Node: Readline Support950913
+Node: Limitations951809
+Node: Debugging Summary954363
+Node: Namespaces955642
+Node: Global Namespace956753
+Node: Qualified Names958151
+Node: Default Namespace959150
+Node: Changing The Namespace959891
+Node: Naming Rules961505
+Node: Internal Name Management963353
+Node: Namespace Example964395
+Node: Namespace And Features966957
+Node: Namespace Summary968392
+Node: Arbitrary Precision Arithmetic969869
+Node: Computer Arithmetic971356
+Ref: table-numeric-ranges975122
+Ref: table-floating-point-ranges975615
+Ref: Computer Arithmetic-Footnote-1976273
+Node: Math Definitions976330
+Ref: table-ieee-formats979306
+Node: MPFR features979873
+Node: FP Math Caution981591
+Ref: FP Math Caution-Footnote-1982663
+Node: Inexactness of computations983032
+Node: Inexact representation984063
+Node: Comparing FP Values985423
+Node: Errors accumulate986664
+Node: Strange values988120
+Ref: Strange values-Footnote-1990708
+Node: Getting Accuracy990813
+Node: Try To Round993523
+Node: Setting precision994422
+Ref: table-predefined-precision-strings995119
+Node: Setting the rounding mode996949
+Ref: table-gawk-rounding-modes997323
+Ref: Setting the rounding mode-Footnote-11001254
+Node: Arbitrary Precision Integers1001433
+Ref: Arbitrary Precision Integers-Footnote-11004608
+Node: Checking for MPFR1004757
+Node: POSIX Floating Point Problems1006231
+Ref: POSIX Floating Point Problems-Footnote-11010516
+Node: Floating point summary1010554
+Node: Dynamic Extensions1012744
+Node: Extension Intro1014297
+Node: Plugin License1015563
+Node: Extension Mechanism Outline1016360
+Ref: figure-load-extension1016799
+Ref: figure-register-new-function1018364
+Ref: figure-call-new-function1019456
+Node: Extension API Description1021518
+Node: Extension API Functions Introduction1023231
+Ref: table-api-std-headers1025067
+Node: General Data Types1029316
+Ref: General Data Types-Footnote-11037946
+Node: Memory Allocation Functions1038245
+Ref: Memory Allocation Functions-Footnote-11042746
+Node: Constructor Functions1042845
+Node: API Ownership of MPFR and GMP Values1046311
+Node: Registration Functions1047624
+Node: Extension Functions1048324
+Node: Exit Callback Functions1053646
+Node: Extension Version String1054896
+Node: Input Parsers1055559
+Node: Output Wrappers1068280
+Node: Two-way processors1072792
+Node: Printing Messages1075057
+Ref: Printing Messages-Footnote-11076228
+Node: Updating ERRNO1076381
+Node: Requesting Values1077120
+Ref: table-value-types-returned1077857
+Node: Accessing Parameters1078793
+Node: Symbol Table Access1080030
+Node: Symbol table by name1080542
+Ref: Symbol table by name-Footnote-11083566
+Node: Symbol table by cookie1083694
+Ref: Symbol table by cookie-Footnote-11087879
+Node: Cached values1087943
+Ref: Cached values-Footnote-11091479
+Node: Array Manipulation1091632
+Ref: Array Manipulation-Footnote-11092723
+Node: Array Data Types1092760
+Ref: Array Data Types-Footnote-11095418
+Node: Array Functions1095510
+Node: Flattening Arrays1100008
+Node: Creating Arrays1106984
+Node: Redirection API1111751
+Node: Extension API Variables1114584
+Node: Extension Versioning1115295
+Ref: gawk-api-version1115724
+Node: Extension GMP/MPFR Versioning1117455
+Node: Extension API Informational Variables1119083
+Node: Extension API Boilerplate1120156
+Node: Changes from API V11124130
+Node: Finding Extensions1125702
+Node: Extension Example1126261
+Node: Internal File Description1127059
+Node: Internal File Ops1131139
+Ref: Internal File Ops-Footnote-11142489
+Node: Using Internal File Ops1142629
+Ref: Using Internal File Ops-Footnote-11145012
+Node: Extension Samples1145286
+Node: Extension Sample File Functions1146815
+Node: Extension Sample Fnmatch1154464
+Node: Extension Sample Fork1155951
+Node: Extension Sample Inplace1157169
+Node: Extension Sample Ord1160795
+Node: Extension Sample Readdir1161631
+Ref: table-readdir-file-types1162520
+Node: Extension Sample Revout1163587
+Node: Extension Sample Rev2way1164176
+Node: Extension Sample Read write array1164916
+Node: Extension Sample Readfile1166858
+Node: Extension Sample Time1167953
+Node: Extension Sample API Tests1169705
+Node: gawkextlib1170197
+Node: Extension summary1173115
+Node: Extension Exercises1176817
+Node: Language History1178059
+Node: V7/SVR3.11179715
+Node: SVR41181867
+Node: POSIX1183301
+Node: BTL1184682
+Node: POSIX/GNU1185411
+Node: Feature History1191189
+Node: Common Extensions1207508
+Node: Ranges and Locales1208791
+Ref: Ranges and Locales-Footnote-11213407
+Ref: Ranges and Locales-Footnote-21213434
+Ref: Ranges and Locales-Footnote-31213669
+Node: Contributors1213892
+Node: History summary1219889
+Node: Installation1221269
+Node: Gawk Distribution1222213
+Node: Getting1222697
+Node: Extracting1223660
+Node: Distribution contents1225298
+Node: Unix Installation1231778
+Node: Quick Installation1232460
+Node: Shell Startup Files1234874
+Node: Additional Configuration Options1235963
+Node: Configuration Philosophy1238278
+Node: Non-Unix Installation1240647
+Node: PC Installation1241107
+Node: PC Binary Installation1241945
+Node: PC Compiling1242380
+Node: PC Using1243497
+Node: Cygwin1247050
+Node: MSYS1248274
+Node: VMS Installation1248876
+Node: VMS Compilation1249667
+Ref: VMS Compilation-Footnote-11250896
+Node: VMS Dynamic Extensions1250954
+Node: VMS Installation Details1252639
+Node: VMS Running1254892
+Node: VMS GNV1259171
+Node: VMS Old Gawk1259906
+Node: Bugs1260377
+Node: Bug address1261040
+Node: Usenet1264022
+Node: Maintainers1265026
+Node: Other Versions1266211
+Node: Installation summary1273299
+Node: Notes1274508
+Node: Compatibility Mode1275302
+Node: Additions1276084
+Node: Accessing The Source1277009
+Node: Adding Code1278446
+Node: New Ports1284665
+Node: Derived Files1289040
+Ref: Derived Files-Footnote-11294700
+Ref: Derived Files-Footnote-21294735
+Ref: Derived Files-Footnote-31295333
+Node: Future Extensions1295447
+Node: Implementation Limitations1296105
+Node: Extension Design1297315
+Node: Old Extension Problems1298459
+Ref: Old Extension Problems-Footnote-11299977
+Node: Extension New Mechanism Goals1300034
+Ref: Extension New Mechanism Goals-Footnote-11303398
+Node: Extension Other Design Decisions1303587
+Node: Extension Future Growth1305700
+Node: Notes summary1306306
+Node: Basic Concepts1307464
+Node: Basic High Level1308145
+Ref: figure-general-flow1308427
+Ref: figure-process-flow1309112
+Ref: Basic High Level-Footnote-11312413
+Node: Basic Data Typing1312598
+Node: Glossary1315926
+Node: Copying1347811
+Node: GNU Free Documentation License1385354
+Node: Index1410474

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index a6f49cb5..b8fcff00 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -920,6 +920,7 @@ particular records in a file and perform operations upon them.
* Inexact representation:: Numbers are not exactly represented.
* Comparing FP Values:: How to compare floating point values.
* Errors accumulate:: Errors get bigger as they go.
+* Strange values:: A few words about infinities and NaNs.
* Getting Accuracy:: Getting more accuracy takes some work.
* Try To Round:: Add digits and round.
* Setting precision:: How to set the precision.
@@ -3136,11 +3137,12 @@ column means that the person is a friend.
An @samp{R} means that the person is a relative:
@example
-@c system if test ! -d eg ; then mkdir eg ; fi
-@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi
-@c system if test ! -d eg/data ; then mkdir eg/data ; fi
-@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi
-@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi
+@c system if test ! -d eg ; then mkdir eg ; fi
+@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi
+@c system if test ! -d eg/data ; then mkdir eg/data ; fi
+@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi
+@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi
+@c system if test ! -d eg/test-programs ; then mkdir eg/test-programs ; fi
@c file eg/data/mail-list
Amelia 555-5553 amelia.zodiacusque@@gmail.com F
Anthony 555-3412 anthony.asserturo@@hotmail.com A
@@ -8398,7 +8400,7 @@ FPAT = "([^,]*)|(\"[^\"]+\")"
@c Per email from Ed Morton <mortoneccc@comcast.net>
@c
@c WONTFIX: 10/2020
-@c This is too much work. FPAT and CSV files are very flakey and
+@c This is too much work. FPAT and CSV files are very flaky and
@c fragile. Doing something like this is merely inviting trouble.
As with @code{FS}, the @code{IGNORECASE} variable (@pxref{User-modified})
@@ -10048,7 +10050,7 @@ infinity are formatted as
and positive infinity as
@samp{inf} or @samp{infinity}.
The special ``not a number'' value formats as @samp{-nan} or @samp{nan}
-(@pxref{Math Definitions}).
+(@pxref{Strange values}).
@item @code{%F}
Like @samp{%f}, but the infinity and ``not a number'' values are spelled
@@ -18284,7 +18286,7 @@ compatibility mode (@pxref{Options}).
@cindexawkfunc{log}
@cindex logarithm
Return the natural logarithm of @var{x}, if @var{x} is positive;
-otherwise, return @code{NaN} (``not a number'') on IEEE 754 systems.
+otherwise, return NaN (``not a number'') on IEEE 754 systems.
Additionally, @command{gawk} prints a warning message when @code{x}
is negative.
@@ -33631,21 +33633,9 @@ A special value representing infinity. Operations involving another
number and infinity produce infinity.
@item NaN
-``Not a number.''@footnote{Thanks to Michael Brennan for this description,
-which we have paraphrased, and for the examples.} A special value that
-results from attempting a calculation that has no answer as a real number.
-In such a case, programs can either receive a floating-point exception,
-or get @code{NaN} back as the result. The IEEE 754 standard recommends
-that systems return @code{NaN}. Some examples:
-
-@table @code
-@item sqrt(-1)
-This makes sense in the range of complex numbers, but not in the
-range of real numbers, so the result is @code{NaN}.
-
-@item log(-8)
-@minus{}8 is out of the domain of @code{log()}, so the result is @code{NaN}.
-@end table
+``Not a number.'' A special value that results from attempting a
+calculation that has no answer as a real number. @xref{Strange values},
+for more information about infinity and not-a-number values.
@item Normalized
How the significand (see later in this list) is usually stored. The
@@ -33814,6 +33804,7 @@ decimal places in the final result.
* Inexact representation:: Numbers are not exactly represented.
* Comparing FP Values:: How to compare floating point values.
* Errors accumulate:: Errors get bigger as they go.
+* Strange values:: A few words about infinities and NaNs.
@end menu
@node Inexact representation
@@ -33935,6 +33926,242 @@ $ @kbd{gawk 'BEGIN @{}
@print{} 4
@end example
+@node Strange values
+@subsubsection Floating Point Values They Didn't Talk About In School
+
+Both IEEE 754 floating-point hardware, and MPFR, support two kinds of
+values that you probably didn't learn about in school. The first is
+@dfn{infinity}, a special value, that can be either negative or positive,
+and which is either smaller than any other value (negative infinity),
+or larger than any other value (positive infinity). When such values
+are generated, @command{gawk} prints them as either @samp{-inf} or
+@samp{+inf}, respectively. It accepts those strings as data input and
+converts them to the proper floating-point values internally.
+
+Infinity values of the same sign compare as equal to each other.
+Otherwise, operations (addition, subtraction, etc.) involving another
+number and infinity produce mathematically reasonable results.
+
+The second kind of value is ``not a number'', or NaN for
+short.@footnote{Thanks to Michael Brennan for this description, which we
+have paraphrased, and for the examples.} This is a special value that results
+from attempting a calculation that has no answer as a real number.
+In such a case, programs can either receive a floating-point exception,
+or get NaN back as the result. The IEEE 754 standard recommends
+that systems return NaN. Some examples:
+
+@table @code
+@item sqrt(-1)
+@iftex
+The @math{\sqrt{-1}}
+@end iftex
+@ifnottex
+This
+@end ifnottex
+makes sense in the range of complex numbers, but not in the
+range of real numbers, so the result is NaN.
+
+@item log(-8)
+@minus{}8 is out of the domain of @code{log()}, so the result is NaN.
+@end table
+
+NaN values are strange. In particular, they cannot be compared with other
+floating point values; any such comparison, except for ``is not equal
+to'', returns false. NaN values are so much unequal to other values that
+even comparing two identical NaN values with @code{!=} returns true!
+
+NaN values can also be signed, although it depends upon the implementation
+as to which sign you get for any operation that returns a NaN. For
+example, on some systems, @code{sqrt(-1)} returns a negative NaN. On
+others, it returns a positive NaN.
+
+When such values are generated, @command{gawk} prints them as either
+@samp{-nan} or @samp{+nan}, respectively. Here too, @command{gawk}
+accepts those strings as data input and converts them to the proper
+floating-point values internally.
+
+If you want to dive more deeply into this topic, you can find
+test programs in C, @command{awk} and Python in the directory
+@file{awklib/eg/test-programs} in the @command{gawk} distribution.
+These programs enable comparison among programming languages as to how
+they handle NaN and infinity values.
+
+@ignore
+@c file eg/test-programs/gen-float-table.awk
+function eq(left, right)
+{
+ return left == right
+}
+
+function ne(left, right)
+{
+ return left != right
+}
+
+function lt(left, right)
+{
+ return left < right
+}
+
+function le(left, right)
+{
+ return left <= right
+}
+
+function gt(left, right)
+{
+ return left > right
+}
+
+function ge(left, right)
+{
+ return left >= right
+}
+
+BEGIN {
+ nan = sqrt(-1)
+ inf = -log(0)
+ split("== != < <= > >=", names)
+ names[3] = names[3] " "
+ names[5] = names[5] " "
+ split("eq ne lt le gt ge", funcs)
+
+ compare[1] = 2.0
+ compare[2] = values[1] = -sqrt(-1.0) # nan
+ compare[3] = values[2] = sqrt(-1.0) # -nan
+ compare[4] = values[3] = -log(0.0) # inf
+ compare[5] = values[4] = log(0.0) # -inf
+
+ for (i = 1; i in values; i++) {
+ for (j = 1; j in compare; j++) {
+ for (k = 1; k in names; k++) {
+ the_func = funcs[k]
+ printf("%g %s %g -> %s\n",
+ values[i],
+ names[k],
+ compare[j],
+ @the_func(values[i], compare[j]) ?
+ "true" : "false");
+ }
+ printf("\n");
+ }
+ }
+}
+@c endfile
+@end ignore
+
+@ignore
+@c file eg/test-programs/gen-float-table.c
+#include <stdio.h>
+#include <math.h>
+#include <stdbool.h>
+
+#define def_func(name, op) \
+ bool name(double left, double right) { \
+ return left op right; \
+ }
+
+def_func(eq, ==)
+def_func(ne, !=)
+def_func(lt, <)
+def_func(le, <=)
+def_func(gt, >)
+def_func(ge, >=)
+
+struct {
+ const char *name;
+ bool (*func)(double left, double right);
+} functions[] = {
+ { "==", eq },
+ { "!=", ne },
+ { "< ", lt },
+ { "<=", le },
+ { "> ", gt },
+ { ">=", ge },
+ { 0, 0 }
+};
+
+int main()
+{
+ double values[] = {
+ -sqrt(-1), // nan
+ sqrt(-1), // -nan
+ -log(0.0), // inf
+ log(0.0) // -inf
+ };
+ double compare[] = { 2.0,
+ -sqrt(-1), // nan
+ sqrt(-1), // -nan
+ -log(0.0), // inf
+ log(0.0) // -inf
+ };
+
+ int i, j, k;
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 5; j++) {
+ for (k = 0; functions[k].name != NULL; k++) {
+ printf("%g %s %g -> %s\n", values[i],
+ functions[k].name,
+ compare[j],
+ functions[k].func(values[i], compare[j]) ? "true" : "false");
+ }
+ printf("\n");
+ }
+ }
+
+ return 0;
+}
+@c endfile
+@end ignore
+
+@ignore
+@c file eg/test-programs/gen-float-table.py
+from math import *
+
+nan = float('NaN')
+inf = float('Inf')
+
+def eq(left, right):
+ return left == right
+
+def ne(left, right):
+ return left != right
+
+def lt(left, right):
+ return left < right
+
+def le(left, right):
+ return left <= right
+
+def gt(left, right):
+ return left > right
+
+def ge(left, right):
+ return left >= right
+
+func_map = {
+ "==": eq,
+ "!=": ne,
+ "< ": lt,
+ "<=": le,
+ "> ": gt,
+ ">=": ge,
+}
+
+compare = [2.0, nan, -nan, inf, -inf]
+values = [nan, -nan, inf, -inf]
+
+for i in range(len(values)):
+ for j in range(len(compare)):
+ for op in func_map:
+ print("%g %s %g -> %s" %
+ (values[i], op, compare[j], func_map[op](values[i], compare[j])))
+
+ print("")
+@c endfile
+@end ignore
+
@node Getting Accuracy
@subsection Getting the Accuracy You Need
diff --git a/doc/gawktexi.in b/doc/gawktexi.in
index 78a28be1..eb9e794e 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -915,6 +915,7 @@ particular records in a file and perform operations upon them.
* Inexact representation:: Numbers are not exactly represented.
* Comparing FP Values:: How to compare floating point values.
* Errors accumulate:: Errors get bigger as they go.
+* Strange values:: A few words about infinities and NaNs.
* Getting Accuracy:: Getting more accuracy takes some work.
* Try To Round:: Add digits and round.
* Setting precision:: How to set the precision.
@@ -3046,11 +3047,12 @@ column means that the person is a friend.
An @samp{R} means that the person is a relative:
@example
-@c system if test ! -d eg ; then mkdir eg ; fi
-@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi
-@c system if test ! -d eg/data ; then mkdir eg/data ; fi
-@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi
-@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi
+@c system if test ! -d eg ; then mkdir eg ; fi
+@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi
+@c system if test ! -d eg/data ; then mkdir eg/data ; fi
+@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi
+@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi
+@c system if test ! -d eg/test-programs ; then mkdir eg/test-programs ; fi
@c file eg/data/mail-list
Amelia 555-5553 amelia.zodiacusque@@gmail.com F
Anthony 555-3412 anthony.asserturo@@hotmail.com A
@@ -7951,7 +7953,7 @@ FPAT = "([^,]*)|(\"[^\"]+\")"
@c Per email from Ed Morton <mortoneccc@comcast.net>
@c
@c WONTFIX: 10/2020
-@c This is too much work. FPAT and CSV files are very flakey and
+@c This is too much work. FPAT and CSV files are very flaky and
@c fragile. Doing something like this is merely inviting trouble.
As with @code{FS}, the @code{IGNORECASE} variable (@pxref{User-modified})
@@ -9601,7 +9603,7 @@ infinity are formatted as
and positive infinity as
@samp{inf} or @samp{infinity}.
The special ``not a number'' value formats as @samp{-nan} or @samp{nan}
-(@pxref{Math Definitions}).
+(@pxref{Strange values}).
@item @code{%F}
Like @samp{%f}, but the infinity and ``not a number'' values are spelled
@@ -17509,7 +17511,7 @@ compatibility mode (@pxref{Options}).
@cindexawkfunc{log}
@cindex logarithm
Return the natural logarithm of @var{x}, if @var{x} is positive;
-otherwise, return @code{NaN} (``not a number'') on IEEE 754 systems.
+otherwise, return NaN (``not a number'') on IEEE 754 systems.
Additionally, @command{gawk} prints a warning message when @code{x}
is negative.
@@ -32597,21 +32599,9 @@ A special value representing infinity. Operations involving another
number and infinity produce infinity.
@item NaN
-``Not a number.''@footnote{Thanks to Michael Brennan for this description,
-which we have paraphrased, and for the examples.} A special value that
-results from attempting a calculation that has no answer as a real number.
-In such a case, programs can either receive a floating-point exception,
-or get @code{NaN} back as the result. The IEEE 754 standard recommends
-that systems return @code{NaN}. Some examples:
-
-@table @code
-@item sqrt(-1)
-This makes sense in the range of complex numbers, but not in the
-range of real numbers, so the result is @code{NaN}.
-
-@item log(-8)
-@minus{}8 is out of the domain of @code{log()}, so the result is @code{NaN}.
-@end table
+``Not a number.'' A special value that results from attempting a
+calculation that has no answer as a real number. @xref{Strange values},
+for more information about infinity and not-a-number values.
@item Normalized
How the significand (see later in this list) is usually stored. The
@@ -32780,6 +32770,7 @@ decimal places in the final result.
* Inexact representation:: Numbers are not exactly represented.
* Comparing FP Values:: How to compare floating point values.
* Errors accumulate:: Errors get bigger as they go.
+* Strange values:: A few words about infinities and NaNs.
@end menu
@node Inexact representation
@@ -32901,6 +32892,242 @@ $ @kbd{gawk 'BEGIN @{}
@print{} 4
@end example
+@node Strange values
+@subsubsection Floating Point Values They Didn't Talk About In School
+
+Both IEEE 754 floating-point hardware, and MPFR, support two kinds of
+values that you probably didn't learn about in school. The first is
+@dfn{infinity}, a special value, that can be either negative or positive,
+and which is either smaller than any other value (negative infinity),
+or larger than any other value (positive infinity). When such values
+are generated, @command{gawk} prints them as either @samp{-inf} or
+@samp{+inf}, respectively. It accepts those strings as data input and
+converts them to the proper floating-point values internally.
+
+Infinity values of the same sign compare as equal to each other.
+Otherwise, operations (addition, subtraction, etc.) involving another
+number and infinity produce mathematically reasonable results.
+
+The second kind of value is ``not a number'', or NaN for
+short.@footnote{Thanks to Michael Brennan for this description, which we
+have paraphrased, and for the examples.} This is a special value that results
+from attempting a calculation that has no answer as a real number.
+In such a case, programs can either receive a floating-point exception,
+or get NaN back as the result. The IEEE 754 standard recommends
+that systems return NaN. Some examples:
+
+@table @code
+@item sqrt(-1)
+@iftex
+The @math{\sqrt{-1}}
+@end iftex
+@ifnottex
+This
+@end ifnottex
+makes sense in the range of complex numbers, but not in the
+range of real numbers, so the result is NaN.
+
+@item log(-8)
+@minus{}8 is out of the domain of @code{log()}, so the result is NaN.
+@end table
+
+NaN values are strange. In particular, they cannot be compared with other
+floating point values; any such comparison, except for ``is not equal
+to'', returns false. NaN values are so much unequal to other values that
+even comparing two identical NaN values with @code{!=} returns true!
+
+NaN values can also be signed, although it depends upon the implementation
+as to which sign you get for any operation that returns a NaN. For
+example, on some systems, @code{sqrt(-1)} returns a negative NaN. On
+others, it returns a positive NaN.
+
+When such values are generated, @command{gawk} prints them as either
+@samp{-nan} or @samp{+nan}, respectively. Here too, @command{gawk}
+accepts those strings as data input and converts them to the proper
+floating-point values internally.
+
+If you want to dive more deeply into this topic, you can find
+test programs in C, @command{awk} and Python in the directory
+@file{awklib/eg/test-programs} in the @command{gawk} distribution.
+These programs enable comparison among programming languages as to how
+they handle NaN and infinity values.
+
+@ignore
+@c file eg/test-programs/gen-float-table.awk
+function eq(left, right)
+{
+ return left == right
+}
+
+function ne(left, right)
+{
+ return left != right
+}
+
+function lt(left, right)
+{
+ return left < right
+}
+
+function le(left, right)
+{
+ return left <= right
+}
+
+function gt(left, right)
+{
+ return left > right
+}
+
+function ge(left, right)
+{
+ return left >= right
+}
+
+BEGIN {
+ nan = sqrt(-1)
+ inf = -log(0)
+ split("== != < <= > >=", names)
+ names[3] = names[3] " "
+ names[5] = names[5] " "
+ split("eq ne lt le gt ge", funcs)
+
+ compare[1] = 2.0
+ compare[2] = values[1] = -sqrt(-1.0) # nan
+ compare[3] = values[2] = sqrt(-1.0) # -nan
+ compare[4] = values[3] = -log(0.0) # inf
+ compare[5] = values[4] = log(0.0) # -inf
+
+ for (i = 1; i in values; i++) {
+ for (j = 1; j in compare; j++) {
+ for (k = 1; k in names; k++) {
+ the_func = funcs[k]
+ printf("%g %s %g -> %s\n",
+ values[i],
+ names[k],
+ compare[j],
+ @the_func(values[i], compare[j]) ?
+ "true" : "false");
+ }
+ printf("\n");
+ }
+ }
+}
+@c endfile
+@end ignore
+
+@ignore
+@c file eg/test-programs/gen-float-table.c
+#include <stdio.h>
+#include <math.h>
+#include <stdbool.h>
+
+#define def_func(name, op) \
+ bool name(double left, double right) { \
+ return left op right; \
+ }
+
+def_func(eq, ==)
+def_func(ne, !=)
+def_func(lt, <)
+def_func(le, <=)
+def_func(gt, >)
+def_func(ge, >=)
+
+struct {
+ const char *name;
+ bool (*func)(double left, double right);
+} functions[] = {
+ { "==", eq },
+ { "!=", ne },
+ { "< ", lt },
+ { "<=", le },
+ { "> ", gt },
+ { ">=", ge },
+ { 0, 0 }
+};
+
+int main()
+{
+ double values[] = {
+ -sqrt(-1), // nan
+ sqrt(-1), // -nan
+ -log(0.0), // inf
+ log(0.0) // -inf
+ };
+ double compare[] = { 2.0,
+ -sqrt(-1), // nan
+ sqrt(-1), // -nan
+ -log(0.0), // inf
+ log(0.0) // -inf
+ };
+
+ int i, j, k;
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 5; j++) {
+ for (k = 0; functions[k].name != NULL; k++) {
+ printf("%g %s %g -> %s\n", values[i],
+ functions[k].name,
+ compare[j],
+ functions[k].func(values[i], compare[j]) ? "true" : "false");
+ }
+ printf("\n");
+ }
+ }
+
+ return 0;
+}
+@c endfile
+@end ignore
+
+@ignore
+@c file eg/test-programs/gen-float-table.py
+from math import *
+
+nan = float('NaN')
+inf = float('Inf')
+
+def eq(left, right):
+ return left == right
+
+def ne(left, right):
+ return left != right
+
+def lt(left, right):
+ return left < right
+
+def le(left, right):
+ return left <= right
+
+def gt(left, right):
+ return left > right
+
+def ge(left, right):
+ return left >= right
+
+func_map = {
+ "==": eq,
+ "!=": ne,
+ "< ": lt,
+ "<=": le,
+ "> ": gt,
+ ">=": ge,
+}
+
+compare = [2.0, nan, -nan, inf, -inf]
+values = [nan, -nan, inf, -inf]
+
+for i in range(len(values)):
+ for j in range(len(compare)):
+ for op in func_map:
+ print("%g %s %g -> %s" %
+ (values[i], op, compare[j], func_map[op](values[i], compare[j])))
+
+ print("")
+@c endfile
+@end ignore
+
@node Getting Accuracy
@subsection Getting the Accuracy You Need
diff --git a/doc/it/ChangeLog b/doc/it/ChangeLog
index 863eef47..5a6bd03d 100644
--- a/doc/it/ChangeLog
+++ b/doc/it/ChangeLog
@@ -1,3 +1,7 @@
+2020-11-20 Antonio Giovanni Colombo <azc100@gmail.com>
+
+ * gawktexi.in: Updated.
+
2020-11-01 Antonio Giovanni Colombo <azc100@gmail.com>
* texinfo.tex: Updated.
diff --git a/doc/it/gawktexi.in b/doc/it/gawktexi.in
index fe7c6b29..a8c0874f 100644..100755
--- a/doc/it/gawktexi.in
+++ b/doc/it/gawktexi.in
@@ -1065,13 +1065,14 @@ Copyright dell'edizione italiana @copyright{} 2016 -- Free Software Foundation,
esattamente.
* Confronti tra valori in VM:: Come confrontare valori in virgola mobile.
* Gli errori si sommano:: Gli errori diventano sempre maggiori.
+* Valori strani:: Un cenno riguardo ai valori infiniti e a NaN [``non @`e un numero''].
* Ottenere la precisione:: Ottenere la precisione voluta.
* Tentare di arrotondare:: Tentare di aggiungere bit di precisione e
arrotondare.
* Impostare la precisione:: Impostare la precisione.
* Impostare modo di arrotondare:: Impostare la modalit@`a di
arrotondamento.
-* Controllare disponibilit@`a MPFR:: Come controllare se MPFR @`e disponibile.
+* Controllare disponibilit@`a MPFR:: Come controllare se MPFR @`e disponibile.
* Interi a precisione arbitraria:: Aritmetica dei numeri interi a precisione
arbitraria con @command{gawk}.
* Problemi virgola mobile POSIX:: Confronto tra standard e uso corrente.
@@ -3338,11 +3339,12 @@ persona @`e un amico [Friend]. Una @samp{R} vuol dire che quella persona @`e
un parente [Relative]:
@example
-@c system if test ! -d eg ; then mkdir eg ; fi
-@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi
-@c system if test ! -d eg/data ; then mkdir eg/data ; fi
-@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi
-@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi
+@c system if test ! -d eg ; then mkdir eg ; fi
+@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi
+@c system if test ! -d eg/data ; then mkdir eg/data ; fi
+@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi
+@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi
+@c system if test ! -d eg/test-programs ; then mkdir eg/test-programs ; fi
@c file eg/data/mail-list
Amelia 555-5553 amelia.zodiacusque@@gmail.com F
Anthony 555-3412 anthony.asserturo@@hotmail.com A
@@ -8710,7 +8712,7 @@ FPAT = "([^,]*)|(\"[^\"]+\")"
@c Per email from Ed Morton <mortoneccc@comcast.net>
@c
@c WONTFIX: 10/2020
-@c This is too much work. FPAT and CSV files are very flakey and
+@c This is too much work. FPAT and CSV files are very flaky and
@c fragile. Doing something like this is merely inviting trouble.
Come per @code{FS}, la variabile @code{IGNORECASE}
@@ -10473,9 +10475,9 @@ dallo standard IEEE 754, il valore infinito negativo @`e rappresentato come
@samp{-inf} o @samp{-infinity},
e l'infinito positivo come
@samp{inf} o @samp{infinity}.
-Il valore speciale ``not a number'' [non @`e un numero] viene scritto come
+Il valore speciale ``not a number'' ["non @`e un numero"] viene scritto come
@samp{-nan} o @samp{nan}
-(@pxref{Definizioni matematiche}).
+(@pxref{Valori strani}).
@item @code{%F}
Come @samp{%f}, ma i valori di infinito e di ``not a number'' sono scritti
@@ -16060,16 +16062,17 @@ risultato.
In @command{gawk}, l'esecuzione di @code{nextfile} produce ulteriori effetti:
le eventuali regole @code{ENDFILE}
sono eseguite se @command{gawk} non
-si trova correntemente all'interno di una regola @code{END} o
-@code{BEGINFILE}; @code{ARGIND} @`e
+si trova correntemente all'interno di una regola @code{END},
+@code{ARGIND} @`e
incrementato e le eventuali regole @code{BEGINFILE} sono eseguite.
(@code{ARGIND} non @`e stato ancora trattato.
@xref{Variabili predefinite}.)
-In @command{gawk}, @code{nextfile} @`e utile all'interno di una regola
+C'@`e un ulteriore caso speciale di utilizzo in @command{gawk}.
+@code{nextfile} @`e utile all'interno di una regola
@code{BEGINFILE} per evitare di elaborare un file che altrimenti causerebbe
un errore fatale in @command{gawk}.
-In questo caso, le regole @code{ENDFILE} non vengono eseguite.
+In questo caso speciale, le regole @code{ENDFILE} non vengono eseguite.
@xref{BEGINFILE/ENDFILE}.
Sebbene possa sembrare che @samp{close(FILENAME)} ottenga lo stesso
@@ -19051,8 +19054,8 @@ modalit@`a compatibile (@pxref{Opzioni}).
@cindexawkfunc{log}
@cindex logaritmo
Restituisce il logaritmo naturale di @var{x}, se @var{x} @`e positivo;
-altrimenti, restituisce @code{NaN} (``not a number'') sui sistemi che
-implementano lo standard IEEE 754.
+altrimenti, restituisce NaN (``not a number'',[``non @`e un numero''])
+sui sistemi che implementano lo standard IEEE 754.
Inoltre, @command{gawk} stampa un messaggio di avvertimento qualora @code{x}
sia negativo.
@@ -35366,23 +35369,10 @@ Come i numeri vanno arrotondati, per eccesso o per difetto, quando necessario.
Maggiori dettagli verranno forniti in seguito.
@item NaN
-``Not a number'' (Non un Numero).@footnote{Grazie a Michael
-Brennan per questa descrizione, che abbiamo parafrasato, e per gli esempi.} Un
-valore speciale che risulta da un calcolo che non ha risposta come numero
-reale. In tal caso, i programmi possono o ricevere un'eccezione di virgola
-mobile, o restituire @code{NaN} come risultato. Lo standard IEEE 754
-consiglia che i sistemi restituiscano @code{NaN}. Alcuni esempi:
-
-@table @code
-@item sqrt(-1)
-La radice quadrata di @minus{}1 ha senso nell'insieme dei numeri complessi,
-ma non nell'insieme dei numeri reali,
-per cui il risultato @`e @code{NaN}.
-
-@item log(-8)
-Il logaritmo di @minus{}8 @`e fuori dal dominio di @code{log()},
-per cui il risultato @`e @code{NaN}.
-@end table
+``Not a number'' (``non @`e un numero''). Un valore speciale
+che risulta da un calcolo che non ha come risposta un numero
+reale. @xref{Valori strani}, per maggiori informazioni riguardo
+ai valori infiniti e ai valori ``non-un-numero''.
@item Normalizzato (formato)
Come la mantissa (vedi oltre in questa lista) @`e usualmente memorizzata. Il
@@ -35534,8 +35524,7 @@ ottenere ulteriori informazioni, e non basarsi solo su quanto qui detto.
* Ottenere la precisione:: Ottenere pi@`u precisione richiede qualche
sforzo.
* Tentare di arrotondare:: Aggiungere cifre di precisione e arrotondare.
-* Impostare la precisione:: Come impostare la precisione.
-* Impostare modo di arrotondare:: Impostare le modalit@`a di arrotondamento.
+* Valori strani:: Un cenno riguardo ai valori infiniti e a NaN [``non @`e un numero''].
@end menu
@node Inesattezza nei calcoli
@@ -35682,6 +35671,257 @@ $ @kbd{gawk 'BEGIN @{}
@print{} 4
@end example
+@node Valori strani
+@subsubsection Valori in virgola mobile non spiegati a scuola
+
+Sia l'hardware che implementa lo standard per i numeri in virgola
+mobili IEEE 754, che la libreria matematica MPFR, prevedono due
+tipi di valori di cui probabilmente non vi hanno parlato a scuola.
+Il primo @`e il valore @dfn{infinity} (``infinito''), un valore speciale
+che pu@`o avere un segno sia negativo che positivo, e che @`e pi@`u
+piccolo di ogni altro valore (infinito negativo), o maggiore di ogni
+altro valore (infinito positivo). Quando vengono generati tali valori
+@command{gawk} li stampa come @samp{-inf} o @samp{+inf}, rispettivamente.
+@command{gawk} accetta queste stringhe come dati in input, e li converte
+internamente all'appropriato valore in virgola mobile.
+
+Valori di infinito che abbiano lo stesso segno risultano uguali
+quando sono confrontati fra loro.
+Per il resto, altre operazioni (addizione, sottrazione, etc.)
+che hanno come operando un infinito e un altro numero producono
+risultati matematicamente ragionevoli.
+
+Il secondo tipo di valore @`e ``not a number'' [``non @`e un numero'']
+scritto in forma abbreviata come NaN.@footnote{Grazie a Michael Brennan
+per questa descrizione, che abbiamo parafrasato, e per gli esempi.}
+
+Questo @`e un valore speciale che risulta da un calcolo che non ha come
+risposta un numero reale. In tal caso, i programmi possono o ricevere
+un’eccezione di virgola mobile, o restituire NaN come risultato.
+Lo standard IEEE 754 consiglia che i sistemi restituiscano NaN.
+Alcuni esempi:
+
+@table @code
+@item sqrt(-1)
+@iftex
+La funzione @math{\sqrt{-1}}
+@end iftex
+@ifnottex
+Questa funzione
+@end ifnottex
+ha senso nell'insieme dei numeri complessi,
+ma non nell'insieme dei numeri reali,
+per cui il risultato @`e @code{NaN}.
+
+@item log(-8)
+Il logaritmo di @minus{}8 @`e fuori dal dominio di @code{log()},
+per cui il risultato @`e @code{NaN}.
+@end table
+
+I valori Nan sono strani. In particolare, non possono essere confrontati
+con altri numeri in virgola mobile; ogni confronto di questo tipo, eccetto
+quello ``non uguale a'', restituisce il valore ``falso''.
+I valori NaN sono talmente differenti da altri valori che perfino il
+confronto di due valori NaN identici fra loro con @code{!=} restituisce
+il valore ``vero''!
+
+I valori NaN possono anche avere un segno (positivo o negativo),
+anche se dipende dall'implementazione quale segno viene restituito
+da qualsiasi operazione il cui risultato sia un valore NaN.
+Per esempio, su alcuni sistemi la funzione @code{sqrt(-1)}
+restituisce un NaN negativo. Su altri sistemi il NaN restituito
+@`e invece positivo.
+
+Quando tali valori vengono generati, @command{gawk} li stampa
+come @samp{-nan} o @samp{+nan}, rispettivamente. Anche per
+questi valori, @command{gawk} accetta queste stringhe come
+dati in input e le converte internamente ai valori loro
+assegnati come numeri in virgola mobile.
+
+Se si desidera approfondire ulteriormente questo argomento, si possono
+trovare programmi di test scritti in C, @command{awk} e Python
+nella directory @file{awklib/eg/test-programs} disponibile
+nella distribuzione di @command{gawk}.
+Tali programmi permettono un confronto tra i linguaggi di
+programmazione, riguardo al modo con cui vengono trattati
+i valori di infinito e quelli NaN.
+
+@ignore
+@c file eg/test-programs/gen-float-table.awk
+function eq(left, right)
+{
+ return left == right
+}
+
+function ne(left, right)
+{
+ return left != right
+}
+
+function lt(left, right)
+{
+ return left < right
+}
+
+function le(left, right)
+{
+ return left <= right
+}
+
+function gt(left, right)
+{
+ return left > right
+}
+
+function ge(left, right)
+{
+ return left >= right
+}
+
+BEGIN {
+ nan = sqrt(-1)
+ inf = -log(0)
+ split("== != < <= > >=", names)
+ names[3] = names[3] " "
+ names[5] = names[5] " "
+ split("eq ne lt le gt ge", funcs)
+
+ compare[1] = 2.0
+ compare[2] = values[1] = -sqrt(-1.0) # nan
+ compare[3] = values[2] = sqrt(-1.0) # -nan
+ compare[4] = values[3] = -log(0.0) # inf
+ compare[5] = values[4] = log(0.0) # -inf
+
+ for (i = 1; i in values; i++) {
+ for (j = 1; j in compare; j++) {
+ for (k = 1; k in names; k++) {
+ the_func = funcs[k]
+ printf("%g %s %g -> %s\n",
+ values[i],
+ names[k],
+ compare[j],
+ @the_func(values[i], compare[j]) ?
+ "true" : "false");
+ }
+ printf("\n");
+ }
+ }
+}
+@c endfile
+@end ignore
+
+@ignore
+@c file eg/test-programs/gen-float-table.c
+#include <stdio.h>
+#include <math.h>
+#include <stdbool.h>
+
+#define def_func(name, op) \
+ bool name(double left, double right) { \
+ return left op right; \
+ }
+
+def_func(eq, ==)
+def_func(ne, !=)
+def_func(lt, <)
+def_func(le, <=)
+def_func(gt, >)
+def_func(ge, >=)
+
+struct {
+ const char *name;
+ bool (*func)(double left, double right);
+} functions[] = {
+ { "==", eq },
+ { "!=", ne },
+ { "< ", lt },
+ { "<=", le },
+ { "> ", gt },
+ { ">=", ge },
+ { 0, 0 }
+};
+
+int main()
+{
+ double values[] = {
+ -sqrt(-1), // nan
+ sqrt(-1), // -nan
+ -log(0.0), // inf
+ log(0.0) // -inf
+ };
+ double compare[] = { 2.0,
+ -sqrt(-1), // nan
+ sqrt(-1), // -nan
+ -log(0.0), // inf
+ log(0.0) // -inf
+ };
+
+ int i, j, k;
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 5; j++) {
+ for (k = 0; functions[k].name != NULL; k++) {
+ printf("%g %s %g -> %s\n", values[i],
+ functions[k].name,
+ compare[j],
+ functions[k].func(values[i], compare[j]) ? "true" : "false");
+ }
+ printf("\n");
+ }
+ }
+
+ return 0;
+}
+@c endfile
+@end ignore
+
+@ignore
+@c file eg/test-programs/gen-float-table.py
+from math import *
+
+nan = float('NaN')
+inf = float('Inf')
+
+def eq(left, right):
+ return left == right
+
+def ne(left, right):
+ return left != right
+
+def lt(left, right):
+ return left < right
+
+def le(left, right):
+ return left <= right
+
+def gt(left, right):
+ return left > right
+
+def ge(left, right):
+ return left >= right
+
+func_map = {
+ "==": eq,
+ "!=": ne,
+ "< ": lt,
+ "<=": le,
+ "> ": gt,
+ ">=": ge,
+}
+
+compare = [2.0, nan, -nan, inf, -inf]
+values = [nan, -nan, inf, -inf]
+
+for i in range(len(values)):
+ for j in range(len(compare)):
+ for op in func_map:
+ print("%g %s %g -> %s" %
+ (values[i], op, compare[j], func_map[op](values[i], compare[j])))
+
+ print("")
+@c endfile
+@end ignore
+
@node Ottenere la precisione
@subsection Ottenere la precisione voluta
diff --git a/doc/wordlist b/doc/wordlist
index c93eda53..9ce31188 100644
--- a/doc/wordlist
+++ b/doc/wordlist
@@ -316,6 +316,7 @@ NR
NT
NUMCUR
NaN
+NaNs
Nachum
Neacsu
Neacsu's
@@ -483,6 +484,7 @@ VT
Versioning
Vinschen
WIPO
+WONTFIX
Walamazoo
Wallin
Watchpoint
diff --git a/eval.c b/eval.c
index 558c021e..83d71dd8 100644
--- a/eval.c
+++ b/eval.c
@@ -24,10 +24,8 @@
*/
#include "awk.h"
+#include <math.h>
-extern double pow(double x, double y);
-extern double modf(double x, double *yp);
-extern double fmod(double x, double y);
NODE **fcall_list = NULL;
long fcall_count = 0;
int currule = 0;
@@ -1520,18 +1518,17 @@ eval_condition(NODE *t)
return boolval(t);
}
-typedef enum {
- SCALAR_EQ_NEQ,
- SCALAR_RELATIONAL
-} scalar_cmp_t;
+static bool cmp_doubles(const NODE *t1, const NODE *t2, scalar_cmp_t comparison_type);
+extern bool mpg_cmp_as_numbers(const NODE *t1, const NODE *t2, scalar_cmp_t comparison_type);
/* cmp_scalars -- compare two nodes on the stack */
-static inline int
+static bool
cmp_scalars(scalar_cmp_t comparison_type)
{
NODE *t1, *t2;
int di;
+ bool ret;
t2 = POP_SCALAR();
t1 = TOP();
@@ -1539,12 +1536,91 @@ cmp_scalars(scalar_cmp_t comparison_type)
DEREF(t2);
fatal(_("attempt to use array `%s' in a scalar context"), array_vname(t1));
}
- di = cmp_nodes(t1, t2, comparison_type == SCALAR_EQ_NEQ);
+
+ if ((t1->flags & STRING) != 0 || (t2->flags & STRING) != 0) {
+ bool use_strcmp = (comparison_type == SCALAR_EQ || comparison_type == SCALAR_NEQ);
+ di = cmp_nodes(t1, t2, use_strcmp);
+
+ switch (comparison_type) {
+ case SCALAR_EQ:
+ ret = (di == 0);
+ break;
+ case SCALAR_NEQ:
+ ret = (di != 0);
+ break;
+ case SCALAR_LT:
+ ret = (di < 0);
+ break;
+ case SCALAR_LE:
+ ret = (di <= 0);
+ break;
+ case SCALAR_GT:
+ ret = (di > 0);
+ break;
+ case SCALAR_GE:
+ ret = (di >= 0);
+ break;
+ }
+ } else {
+ fixtype(t1);
+ fixtype(t2);
+
+#ifdef HAVE_MPFR
+ if (do_mpfr)
+ ret = mpg_cmp_as_numbers(t1, t2, comparison_type);
+ else
+#endif
+ ret = cmp_doubles(t1, t2, comparison_type);
+ }
+
DEREF(t1);
DEREF(t2);
- return di;
+ return ret;
}
+
+/* cmp_doubles --- compare two doubles */
+
+static bool
+cmp_doubles(const NODE *t1, const NODE *t2, scalar_cmp_t comparison_type)
+{
+ /*
+ * This routine provides numeric comparisons that should work
+ * the same as in C. It should NOT be used for sorting.
+ */
+
+ bool t1_nan = isnan(t1->numbr);
+ bool t2_nan = isnan(t2->numbr);
+ int ret;
+
+ if ((t1_nan || t2_nan) && comparison_type != SCALAR_NEQ)
+ return false;
+
+ switch (comparison_type) {
+ case SCALAR_EQ:
+ ret = (t1->numbr == t2->numbr);
+ break;
+ case SCALAR_NEQ:
+ ret = (t1->numbr != t2->numbr);
+ break;
+ case SCALAR_LT:
+ ret = (t1->numbr < t2->numbr);
+ break;
+ case SCALAR_LE:
+ ret = (t1->numbr <= t2->numbr);
+ break;
+ case SCALAR_GT:
+ ret = (t1->numbr > t2->numbr);
+ break;
+ case SCALAR_GE:
+ ret = (t1->numbr >= t2->numbr);
+ break;
+ }
+
+ return ret;
+}
+
+
/* op_assign --- assignment operators excluding = */
static void
diff --git a/interpret.h b/interpret.h
index fedf5255..40dd39d6 100644
--- a/interpret.h
+++ b/interpret.h
@@ -486,37 +486,37 @@ uninitialized_scalar:
break;
case Op_equal:
- r = node_Boolean[cmp_scalars(SCALAR_EQ_NEQ) == 0];
+ r = node_Boolean[cmp_scalars(SCALAR_EQ)];
UPREF(r);
REPLACE(r);
break;
case Op_notequal:
- r = node_Boolean[cmp_scalars(SCALAR_EQ_NEQ) != 0];
+ r = node_Boolean[cmp_scalars(SCALAR_NEQ)];
UPREF(r);
REPLACE(r);
break;
case Op_less:
- r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) < 0];
+ r = node_Boolean[cmp_scalars(SCALAR_LT)];
UPREF(r);
REPLACE(r);
break;
case Op_greater:
- r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) > 0];
+ r = node_Boolean[cmp_scalars(SCALAR_GT)];
UPREF(r);
REPLACE(r);
break;
case Op_leq:
- r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) <= 0];
+ r = node_Boolean[cmp_scalars(SCALAR_LE)];
UPREF(r);
REPLACE(r);
break;
case Op_geq:
- r = node_Boolean[cmp_scalars(SCALAR_RELATIONAL) >= 0];
+ r = node_Boolean[cmp_scalars(SCALAR_GE)];
UPREF(r);
REPLACE(r);
break;
diff --git a/mpfr.c b/mpfr.c
index 38f38a3a..2dfff447 100644
--- a/mpfr.c
+++ b/mpfr.c
@@ -433,6 +433,50 @@ mpg_cmp(const NODE *t1, const NODE *t2)
return cmp_awknums(t1, t2);
}
+/* mpg_cmp_as_numbers --- compare two numbers, similar to doubles */
+
+bool
+mpg_cmp_as_numbers(const NODE *t1, const NODE *t2, scalar_cmp_t comparison_type)
+{
+ /*
+ * This routine provides numeric comparisons that should work
+ * the same as in C. It should NOT be used for sorting.
+ */
+
+ bool t1_nan = mpfr_nan_p(t1->mpg_numbr);
+ bool t2_nan = mpfr_nan_p(t2->mpg_numbr);
+ int ret;
+
+ // MPFR is different than native doubles...
+ if (t1_nan || t2_nan)
+ return comparison_type == SCALAR_NEQ;
+
+ int di = mpg_cmp(t1, t2);
+
+ switch (comparison_type) {
+ case SCALAR_EQ:
+ ret = (di == 0);
+ break;
+ case SCALAR_NEQ:
+ ret = (di != 0);
+ break;
+ case SCALAR_LT:
+ ret = (di < 0);
+ break;
+ case SCALAR_LE:
+ ret = (di <= 0);
+ break;
+ case SCALAR_GT:
+ ret = (di > 0);
+ break;
+ case SCALAR_GE:
+ ret = (di >= 0);
+ break;
+ }
+
+ return ret;
+}
+
/*
* mpg_update_var --- update NR or FNR.
diff --git a/node.c b/node.c
index 707d106d..772131a2 100644
--- a/node.c
+++ b/node.c
@@ -25,7 +25,7 @@
*/
#include "awk.h"
-#include "math.h"
+#include <math.h>
#include "floatmagic.h" /* definition of isnan */
static int is_ieee_magic_val(const char *val);
@@ -367,7 +367,7 @@ int
cmp_awknums(const NODE *t1, const NODE *t2)
{
/*
- * This routine is also used to sort numeric array indices or values.
+ * This routine is used to sort numeric array indices or values.
* For the purposes of sorting, NaN is considered greater than
* any other value, and all NaN values are considered equivalent and equal.
* This isn't in compliance with IEEE standard, but compliance w.r.t. NaN
@@ -387,7 +387,6 @@ cmp_awknums(const NODE *t1, const NODE *t2)
return 1;
}
-
/* make_str_node --- make a string node */
NODE *