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/ChangeLog21
-rw-r--r--doc/gawk.info1282
-rw-r--r--doc/gawk.texi267
-rw-r--r--doc/gawktexi.in273
-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
16 files changed, 1513 insertions, 684 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 6dad4af7..8d00228d 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -3,6 +3,27 @@
* gawktexi.in (Nextfile Statement): Clarify what happens in
a BEGINFILE rule.
+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 909cf29e..ebae71b7 100644
--- a/doc/gawk.info
+++ b/doc/gawk.info
@@ -546,6 +546,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.
@@ -6926,8 +6927,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
@@ -12819,7 +12820,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()'
@@ -24153,18 +24154,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.
@@ -24223,11 +24216,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
@@ -24320,6 +24308,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
@@ -24384,7 +24373,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
..........................
@@ -24432,6 +24421,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 infinity.
+
+ 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 hanle 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
@@ -37934,602 +37981,603 @@ Index

Tag Table:
Node: Top1200
-Node: Foreword344474
-Node: Foreword448916
-Node: Preface50448
-Ref: Preface-Footnote-153307
-Ref: Preface-Footnote-253416
-Ref: Preface-Footnote-353650
-Node: History53792
-Node: Names56144
-Ref: Names-Footnote-157248
-Node: This Manual57395
-Ref: This Manual-Footnote-164034
-Node: Conventions64134
-Node: Manual History66503
-Ref: Manual History-Footnote-169500
-Ref: Manual History-Footnote-269541
-Node: How To Contribute69615
-Node: Acknowledgments70541
-Node: Getting Started75478
-Node: Running gawk77917
-Node: One-shot79107
-Node: Read Terminal80370
-Node: Long82363
-Node: Executable Scripts83876
-Ref: Executable Scripts-Footnote-186509
-Node: Comments86612
-Node: Quoting89096
-Node: DOS Quoting94622
-Node: Sample Data Files96678
-Node: Very Simple99273
-Node: Two Rules105375
-Node: More Complex107260
-Node: Statements/Lines109592
-Ref: Statements/Lines-Footnote-1114076
-Node: Other Features114341
-Node: When115277
-Ref: When-Footnote-1117031
-Node: Intro Summary117096
-Node: Invoking Gawk117980
-Node: Command Line119494
-Node: Options120292
-Ref: Options-Footnote-1138206
-Ref: Options-Footnote-2138437
-Node: Other Arguments138462
-Node: Naming Standard Input142473
-Node: Environment Variables143683
-Node: AWKPATH Variable144241
-Ref: AWKPATH Variable-Footnote-1147653
-Ref: AWKPATH Variable-Footnote-2147687
-Node: AWKLIBPATH Variable148058
-Ref: AWKLIBPATH Variable-Footnote-1149755
-Node: Other Environment Variables150130
-Node: Exit Status153951
-Node: Include Files154628
-Node: Loading Shared Libraries158318
-Node: Obsolete159746
-Node: Undocumented160438
-Node: Invoking Summary160735
-Node: Regexp163576
-Node: Regexp Usage165030
-Node: Escape Sequences167067
-Node: Regexp Operators173308
-Node: Regexp Operator Details173793
-Ref: Regexp Operator Details-Footnote-1180225
-Node: Interval Expressions180372
-Ref: Interval Expressions-Footnote-1181793
-Node: Bracket Expressions181891
-Ref: table-char-classes184367
-Node: Leftmost Longest187693
-Node: Computed Regexps188996
-Node: GNU Regexp Operators192423
-Node: Case-sensitivity196160
-Ref: Case-sensitivity-Footnote-1199026
-Ref: Case-sensitivity-Footnote-2199261
-Node: Regexp Summary199369
-Node: Reading Files200835
-Node: Records203104
-Node: awk split records204179
-Node: gawk split records209454
-Ref: gawk split records-Footnote-1214187
-Node: Fields214224
-Node: Nonconstant Fields216965
-Ref: Nonconstant Fields-Footnote-1219201
-Node: Changing Fields219405
-Node: Field Separators225436
-Node: Default Field Splitting228134
-Node: Regexp Field Splitting229252
-Node: Single Character Fields232605
-Node: Command Line Field Separator233665
-Node: Full Line Fields236883
-Ref: Full Line Fields-Footnote-1238405
-Ref: Full Line Fields-Footnote-2238451
-Node: Field Splitting Summary238552
-Node: Constant Size240626
-Node: Fixed width data241358
-Node: Skipping intervening244825
-Node: Allowing trailing data245623
-Node: Fields with fixed data246660
-Node: Splitting By Content248178
-Ref: Splitting By Content-Footnote-1251961
-Node: More CSV252124
-Node: Testing field creation253434
-Node: Multiple Line255059
-Node: Getline261336
-Node: Plain Getline263805
-Node: Getline/Variable266378
-Node: Getline/File267529
-Node: Getline/Variable/File268917
-Ref: Getline/Variable/File-Footnote-1270522
-Node: Getline/Pipe270610
-Node: Getline/Variable/Pipe273314
-Node: Getline/Coprocess274449
-Node: Getline/Variable/Coprocess275716
-Node: Getline Notes276458
-Node: Getline Summary279255
-Ref: table-getline-variants279679
-Node: Read Timeout280427
-Ref: Read Timeout-Footnote-1284333
-Node: Retrying Input284391
-Node: Command-line directories285590
-Node: Input Summary286496
-Node: Input Exercises289668
-Node: Printing290102
-Node: Print291936
-Node: Print Examples293393
-Node: Output Separators296173
-Node: OFMT298190
-Node: Printf299546
-Node: Basic Printf300331
-Node: Control Letters301905
-Node: Format Modifiers307069
-Node: Printf Examples313084
-Node: Redirection315570
-Node: Special FD322411
-Ref: Special FD-Footnote-1325579
-Node: Special Files325653
-Node: Other Inherited Files326270
-Node: Special Network327271
-Node: Special Caveats328131
-Node: Close Files And Pipes329080
-Ref: table-close-pipe-return-values335987
-Ref: Close Files And Pipes-Footnote-1336800
-Ref: Close Files And Pipes-Footnote-2336948
-Node: Nonfatal337100
-Node: Output Summary339438
-Node: Output Exercises340660
-Node: Expressions341339
-Node: Values342527
-Node: Constants343205
-Node: Scalar Constants343896
-Ref: Scalar Constants-Footnote-1346406
-Node: Nondecimal-numbers346656
-Node: Regexp Constants349657
-Node: Using Constant Regexps350183
-Node: Standard Regexp Constants350805
-Node: Strong Regexp Constants353993
-Node: Variables357005
-Node: Using Variables357662
-Node: Assignment Options359572
-Node: Conversion362043
-Node: Strings And Numbers362567
-Ref: Strings And Numbers-Footnote-1365630
-Node: Locale influences conversions365739
-Ref: table-locale-affects368497
-Node: All Operators369115
-Node: Arithmetic Ops369744
-Node: Concatenation372460
-Ref: Concatenation-Footnote-1375307
-Node: Assignment Ops375414
-Ref: table-assign-ops380405
-Node: Increment Ops381718
-Node: Truth Values and Conditions385178
-Node: Truth Values386252
-Node: Typing and Comparison387300
-Node: Variable Typing388120
-Ref: Variable Typing-Footnote-1394583
-Ref: Variable Typing-Footnote-2394655
-Node: Comparison Operators394732
-Ref: table-relational-ops395151
-Node: POSIX String Comparison398646
-Ref: POSIX String Comparison-Footnote-1400341
-Ref: POSIX String Comparison-Footnote-2400480
-Node: Boolean Ops400564
-Ref: Boolean Ops-Footnote-1405046
-Node: Conditional Exp405138
-Node: Function Calls406874
-Node: Precedence410751
-Node: Locales414410
-Node: Expressions Summary416042
-Node: Patterns and Actions418615
-Node: Pattern Overview419735
-Node: Regexp Patterns421412
-Node: Expression Patterns421954
-Node: Ranges425735
-Node: BEGIN/END428843
-Node: Using BEGIN/END429604
-Ref: Using BEGIN/END-Footnote-1432358
-Node: I/O And BEGIN/END432464
-Node: BEGINFILE/ENDFILE434777
-Node: Empty438008
-Node: Using Shell Variables438325
-Node: Action Overview440599
-Node: Statements442924
-Node: If Statement444772
-Node: While Statement446267
-Node: Do Statement448295
-Node: For Statement449443
-Node: Switch Statement452614
-Node: Break Statement455055
-Node: Continue Statement457147
-Node: Next Statement458974
-Node: Nextfile Statement461357
-Node: Exit Statement463995
-Node: Built-in Variables466398
-Node: User-modified467531
-Node: Auto-set475298
-Ref: Auto-set-Footnote-1492105
-Ref: Auto-set-Footnote-2492311
-Node: ARGC and ARGV492367
-Node: Pattern Action Summary496580
-Node: Arrays499010
-Node: Array Basics500339
-Node: Array Intro501183
-Ref: figure-array-elements503158
-Ref: Array Intro-Footnote-1505862
-Node: Reference to Elements505990
-Node: Assigning Elements508454
-Node: Array Example508945
-Node: Scanning an Array510704
-Node: Controlling Scanning513726
-Ref: Controlling Scanning-Footnote-1520182
-Node: Numeric Array Subscripts520498
-Node: Uninitialized Subscripts522682
-Node: Delete524301
-Ref: Delete-Footnote-1527053
-Node: Multidimensional527110
-Node: Multiscanning530205
-Node: Arrays of Arrays531796
-Node: Arrays Summary536564
-Node: Functions538657
-Node: Built-in539695
-Node: Calling Built-in540776
-Node: Numeric Functions542772
-Ref: Numeric Functions-Footnote-1546800
-Ref: Numeric Functions-Footnote-2547448
-Ref: Numeric Functions-Footnote-3547496
-Node: String Functions547768
-Ref: String Functions-Footnote-1571909
-Ref: String Functions-Footnote-2572037
-Ref: String Functions-Footnote-3572285
-Node: Gory Details572372
-Ref: table-sub-escapes574163
-Ref: table-sub-proposed575682
-Ref: table-posix-sub577045
-Ref: table-gensub-escapes578586
-Ref: Gory Details-Footnote-1579409
-Node: I/O Functions579563
-Ref: table-system-return-values586017
-Ref: I/O Functions-Footnote-1588097
-Ref: I/O Functions-Footnote-2588245
-Node: Time Functions588365
-Ref: Time Functions-Footnote-1599036
-Ref: Time Functions-Footnote-2599104
-Ref: Time Functions-Footnote-3599262
-Ref: Time Functions-Footnote-4599373
-Ref: Time Functions-Footnote-5599485
-Ref: Time Functions-Footnote-6599712
-Node: Bitwise Functions599978
-Ref: table-bitwise-ops600572
-Ref: Bitwise Functions-Footnote-1606635
-Ref: Bitwise Functions-Footnote-2606808
-Node: Type Functions606999
-Node: I18N Functions609862
-Node: User-defined611513
-Node: Definition Syntax612325
-Ref: Definition Syntax-Footnote-1618019
-Node: Function Example618090
-Ref: Function Example-Footnote-1621012
-Node: Function Calling621034
-Node: Calling A Function621622
-Node: Variable Scope622580
-Node: Pass By Value/Reference625574
-Node: Function Caveats628218
-Ref: Function Caveats-Footnote-1630265
-Node: Return Statement630385
-Node: Dynamic Typing633364
-Node: Indirect Calls634294
-Ref: Indirect Calls-Footnote-1644546
-Node: Functions Summary644674
-Node: Library Functions647379
-Ref: Library Functions-Footnote-1650986
-Ref: Library Functions-Footnote-2651129
-Node: Library Names651300
-Ref: Library Names-Footnote-1654967
-Ref: Library Names-Footnote-2655190
-Node: General Functions655276
-Node: Strtonum Function656379
-Node: Assert Function659401
-Node: Round Function662727
-Node: Cliff Random Function664267
-Node: Ordinal Functions665283
-Ref: Ordinal Functions-Footnote-1668346
-Ref: Ordinal Functions-Footnote-2668598
-Node: Join Function668808
-Ref: Join Function-Footnote-1670578
-Node: Getlocaltime Function670778
-Node: Readfile Function674520
-Node: Shell Quoting676497
-Node: Data File Management677898
-Node: Filetrans Function678530
-Node: Rewind Function682626
-Node: File Checking684535
-Ref: File Checking-Footnote-1685869
-Node: Empty Files686070
-Node: Ignoring Assigns688049
-Node: Getopt Function689599
-Ref: Getopt Function-Footnote-1704810
-Node: Passwd Functions705010
-Ref: Passwd Functions-Footnote-1713849
-Node: Group Functions713937
-Ref: Group Functions-Footnote-1721835
-Node: Walking Arrays722042
-Node: Library Functions Summary725050
-Node: Library Exercises726456
-Node: Sample Programs726921
-Node: Running Examples727691
-Node: Clones728419
-Node: Cut Program729643
-Node: Egrep Program739572
-Node: Id Program748583
-Node: Split Program758530
-Ref: Split Program-Footnote-1768304
-Node: Tee Program768477
-Node: Uniq Program771267
-Node: Wc Program778831
-Node: Bytes vs. Characters779228
-Node: Using extensions780776
-Node: wc program781534
-Node: Miscellaneous Programs786399
-Node: Dupword Program787612
-Node: Alarm Program789642
-Node: Translate Program794497
-Ref: Translate Program-Footnote-1799062
-Node: Labels Program799332
-Ref: Labels Program-Footnote-1802683
-Node: Word Sorting802767
-Node: History Sorting806839
-Node: Extract Program809064
-Node: Simple Sed817118
-Node: Igawk Program820192
-Ref: Igawk Program-Footnote-1834523
-Ref: Igawk Program-Footnote-2834725
-Ref: Igawk Program-Footnote-3834847
-Node: Anagram Program834962
-Node: Signature Program838024
-Node: Programs Summary839271
-Node: Programs Exercises840485
-Ref: Programs Exercises-Footnote-1844615
-Node: Advanced Features844701
-Node: Nondecimal Data846691
-Node: Array Sorting848282
-Node: Controlling Array Traversal848982
-Ref: Controlling Array Traversal-Footnote-1857350
-Node: Array Sorting Functions857468
-Ref: Array Sorting Functions-Footnote-1862559
-Node: Two-way I/O862755
-Ref: Two-way I/O-Footnote-1870476
-Ref: Two-way I/O-Footnote-2870663
-Node: TCP/IP Networking870745
-Node: Profiling873863
-Node: Advanced Features Summary883177
-Node: Internationalization885021
-Node: I18N and L10N886501
-Node: Explaining gettext887188
-Ref: Explaining gettext-Footnote-1893080
-Ref: Explaining gettext-Footnote-2893265
-Node: Programmer i18n893430
-Ref: Programmer i18n-Footnote-1898379
-Node: Translator i18n898428
-Node: String Extraction899222
-Ref: String Extraction-Footnote-1900354
-Node: Printf Ordering900440
-Ref: Printf Ordering-Footnote-1903226
-Node: I18N Portability903290
-Ref: I18N Portability-Footnote-1905746
-Node: I18N Example905809
-Ref: I18N Example-Footnote-1909084
-Ref: I18N Example-Footnote-2909157
-Node: Gawk I18N909266
-Node: I18N Summary909915
-Node: Debugger911256
-Node: Debugging912256
-Node: Debugging Concepts912697
-Node: Debugging Terms914506
-Node: Awk Debugging917081
-Ref: Awk Debugging-Footnote-1918026
-Node: Sample Debugging Session918158
-Node: Debugger Invocation918692
-Node: Finding The Bug920078
-Node: List of Debugger Commands926552
-Node: Breakpoint Control927885
-Node: Debugger Execution Control931579
-Node: Viewing And Changing Data934941
-Node: Execution Stack938482
-Node: Debugger Info940119
-Node: Miscellaneous Debugger Commands944190
-Node: Readline Support949252
-Node: Limitations950148
-Node: Debugging Summary952702
-Node: Namespaces953981
-Node: Global Namespace955092
-Node: Qualified Names956490
-Node: Default Namespace957489
-Node: Changing The Namespace958230
-Node: Naming Rules959844
-Node: Internal Name Management961692
-Node: Namespace Example962734
-Node: Namespace And Features965296
-Node: Namespace Summary966731
-Node: Arbitrary Precision Arithmetic968208
-Node: Computer Arithmetic969695
-Ref: table-numeric-ranges973461
-Ref: table-floating-point-ranges973954
-Ref: Computer Arithmetic-Footnote-1974612
-Node: Math Definitions974669
-Ref: table-ieee-formats977985
-Ref: Math Definitions-Footnote-1978588
-Node: MPFR features978693
-Node: FP Math Caution980411
-Ref: FP Math Caution-Footnote-1981483
-Node: Inexactness of computations981852
-Node: Inexact representation982812
-Node: Comparing FP Values984172
-Node: Errors accumulate985413
-Node: Getting Accuracy986846
-Node: Try To Round989556
-Node: Setting precision990455
-Ref: table-predefined-precision-strings991152
-Node: Setting the rounding mode992982
-Ref: table-gawk-rounding-modes993356
-Ref: Setting the rounding mode-Footnote-1997287
-Node: Arbitrary Precision Integers997466
-Ref: Arbitrary Precision Integers-Footnote-11000641
-Node: Checking for MPFR1000790
-Node: POSIX Floating Point Problems1002264
-Ref: POSIX Floating Point Problems-Footnote-11006549
-Node: Floating point summary1006587
-Node: Dynamic Extensions1008777
-Node: Extension Intro1010330
-Node: Plugin License1011596
-Node: Extension Mechanism Outline1012393
-Ref: figure-load-extension1012832
-Ref: figure-register-new-function1014397
-Ref: figure-call-new-function1015489
-Node: Extension API Description1017551
-Node: Extension API Functions Introduction1019264
-Ref: table-api-std-headers1021100
-Node: General Data Types1025349
-Ref: General Data Types-Footnote-11033979
-Node: Memory Allocation Functions1034278
-Ref: Memory Allocation Functions-Footnote-11038779
-Node: Constructor Functions1038878
-Node: API Ownership of MPFR and GMP Values1042344
-Node: Registration Functions1043657
-Node: Extension Functions1044357
-Node: Exit Callback Functions1049679
-Node: Extension Version String1050929
-Node: Input Parsers1051592
-Node: Output Wrappers1064313
-Node: Two-way processors1068825
-Node: Printing Messages1071090
-Ref: Printing Messages-Footnote-11072261
-Node: Updating ERRNO1072414
-Node: Requesting Values1073153
-Ref: table-value-types-returned1073890
-Node: Accessing Parameters1074826
-Node: Symbol Table Access1076063
-Node: Symbol table by name1076575
-Ref: Symbol table by name-Footnote-11079599
-Node: Symbol table by cookie1079727
-Ref: Symbol table by cookie-Footnote-11083912
-Node: Cached values1083976
-Ref: Cached values-Footnote-11087512
-Node: Array Manipulation1087665
-Ref: Array Manipulation-Footnote-11088756
-Node: Array Data Types1088793
-Ref: Array Data Types-Footnote-11091451
-Node: Array Functions1091543
-Node: Flattening Arrays1096041
-Node: Creating Arrays1103017
-Node: Redirection API1107784
-Node: Extension API Variables1110617
-Node: Extension Versioning1111328
-Ref: gawk-api-version1111757
-Node: Extension GMP/MPFR Versioning1113488
-Node: Extension API Informational Variables1115116
-Node: Extension API Boilerplate1116189
-Node: Changes from API V11120163
-Node: Finding Extensions1121735
-Node: Extension Example1122294
-Node: Internal File Description1123092
-Node: Internal File Ops1127172
-Ref: Internal File Ops-Footnote-11138522
-Node: Using Internal File Ops1138662
-Ref: Using Internal File Ops-Footnote-11141045
-Node: Extension Samples1141319
-Node: Extension Sample File Functions1142848
-Node: Extension Sample Fnmatch1150497
-Node: Extension Sample Fork1151984
-Node: Extension Sample Inplace1153202
-Node: Extension Sample Ord1156828
-Node: Extension Sample Readdir1157664
-Ref: table-readdir-file-types1158553
-Node: Extension Sample Revout1159620
-Node: Extension Sample Rev2way1160209
-Node: Extension Sample Read write array1160949
-Node: Extension Sample Readfile1162891
-Node: Extension Sample Time1163986
-Node: Extension Sample API Tests1165738
-Node: gawkextlib1166230
-Node: Extension summary1169148
-Node: Extension Exercises1172850
-Node: Language History1174092
-Node: V7/SVR3.11175748
-Node: SVR41177900
-Node: POSIX1179334
-Node: BTL1180715
-Node: POSIX/GNU1181444
-Node: Feature History1187222
-Node: Common Extensions1203541
-Node: Ranges and Locales1204824
-Ref: Ranges and Locales-Footnote-11209440
-Ref: Ranges and Locales-Footnote-21209467
-Ref: Ranges and Locales-Footnote-31209702
-Node: Contributors1209925
-Node: History summary1215922
-Node: Installation1217302
-Node: Gawk Distribution1218246
-Node: Getting1218730
-Node: Extracting1219693
-Node: Distribution contents1221331
-Node: Unix Installation1227811
-Node: Quick Installation1228493
-Node: Shell Startup Files1230907
-Node: Additional Configuration Options1231996
-Node: Configuration Philosophy1234311
-Node: Non-Unix Installation1236680
-Node: PC Installation1237140
-Node: PC Binary Installation1237978
-Node: PC Compiling1238413
-Node: PC Using1239530
-Node: Cygwin1243083
-Node: MSYS1244307
-Node: VMS Installation1244909
-Node: VMS Compilation1245700
-Ref: VMS Compilation-Footnote-11246929
-Node: VMS Dynamic Extensions1246987
-Node: VMS Installation Details1248672
-Node: VMS Running1250925
-Node: VMS GNV1255204
-Node: VMS Old Gawk1255939
-Node: Bugs1256410
-Node: Bug address1257073
-Node: Usenet1260055
-Node: Maintainers1261059
-Node: Other Versions1262244
-Node: Installation summary1269332
-Node: Notes1270541
-Node: Compatibility Mode1271335
-Node: Additions1272117
-Node: Accessing The Source1273042
-Node: Adding Code1274479
-Node: New Ports1280698
-Node: Derived Files1285073
-Ref: Derived Files-Footnote-11290733
-Ref: Derived Files-Footnote-21290768
-Ref: Derived Files-Footnote-31291366
-Node: Future Extensions1291480
-Node: Implementation Limitations1292138
-Node: Extension Design1293348
-Node: Old Extension Problems1294492
-Ref: Old Extension Problems-Footnote-11296010
-Node: Extension New Mechanism Goals1296067
-Ref: Extension New Mechanism Goals-Footnote-11299431
-Node: Extension Other Design Decisions1299620
-Node: Extension Future Growth1301733
-Node: Notes summary1302339
-Node: Basic Concepts1303497
-Node: Basic High Level1304178
-Ref: figure-general-flow1304460
-Ref: figure-process-flow1305145
-Ref: Basic High Level-Footnote-11308446
-Node: Basic Data Typing1308631
-Node: Glossary1311959
-Node: Copying1343844
-Node: GNU Free Documentation License1381387
-Node: Index1406507
+Node: Foreword344553
+Node: Foreword448995
+Node: Preface50527
+Ref: Preface-Footnote-153386
+Ref: Preface-Footnote-253495
+Ref: Preface-Footnote-353729
+Node: History53871
+Node: Names56223
+Ref: Names-Footnote-157327
+Node: This Manual57474
+Ref: This Manual-Footnote-164113
+Node: Conventions64213
+Node: Manual History66582
+Ref: Manual History-Footnote-169579
+Ref: Manual History-Footnote-269620
+Node: How To Contribute69694
+Node: Acknowledgments70620
+Node: Getting Started75557
+Node: Running gawk77996
+Node: One-shot79186
+Node: Read Terminal80449
+Node: Long82442
+Node: Executable Scripts83955
+Ref: Executable Scripts-Footnote-186588
+Node: Comments86691
+Node: Quoting89175
+Node: DOS Quoting94701
+Node: Sample Data Files96757
+Node: Very Simple99352
+Node: Two Rules105454
+Node: More Complex107339
+Node: Statements/Lines109671
+Ref: Statements/Lines-Footnote-1114155
+Node: Other Features114420
+Node: When115356
+Ref: When-Footnote-1117110
+Node: Intro Summary117175
+Node: Invoking Gawk118059
+Node: Command Line119573
+Node: Options120371
+Ref: Options-Footnote-1138285
+Ref: Options-Footnote-2138516
+Node: Other Arguments138541
+Node: Naming Standard Input142552
+Node: Environment Variables143762
+Node: AWKPATH Variable144320
+Ref: AWKPATH Variable-Footnote-1147732
+Ref: AWKPATH Variable-Footnote-2147766
+Node: AWKLIBPATH Variable148137
+Ref: AWKLIBPATH Variable-Footnote-1149834
+Node: Other Environment Variables150209
+Node: Exit Status154030
+Node: Include Files154707
+Node: Loading Shared Libraries158397
+Node: Obsolete159825
+Node: Undocumented160517
+Node: Invoking Summary160814
+Node: Regexp163655
+Node: Regexp Usage165109
+Node: Escape Sequences167146
+Node: Regexp Operators173387
+Node: Regexp Operator Details173872
+Ref: Regexp Operator Details-Footnote-1180304
+Node: Interval Expressions180451
+Ref: Interval Expressions-Footnote-1181872
+Node: Bracket Expressions181970
+Ref: table-char-classes184446
+Node: Leftmost Longest187772
+Node: Computed Regexps189075
+Node: GNU Regexp Operators192502
+Node: Case-sensitivity196239
+Ref: Case-sensitivity-Footnote-1199105
+Ref: Case-sensitivity-Footnote-2199340
+Node: Regexp Summary199448
+Node: Reading Files200914
+Node: Records203183
+Node: awk split records204258
+Node: gawk split records209533
+Ref: gawk split records-Footnote-1214266
+Node: Fields214303
+Node: Nonconstant Fields217044
+Ref: Nonconstant Fields-Footnote-1219280
+Node: Changing Fields219484
+Node: Field Separators225515
+Node: Default Field Splitting228213
+Node: Regexp Field Splitting229331
+Node: Single Character Fields232684
+Node: Command Line Field Separator233744
+Node: Full Line Fields236962
+Ref: Full Line Fields-Footnote-1238484
+Ref: Full Line Fields-Footnote-2238530
+Node: Field Splitting Summary238631
+Node: Constant Size240705
+Node: Fixed width data241437
+Node: Skipping intervening244904
+Node: Allowing trailing data245702
+Node: Fields with fixed data246739
+Node: Splitting By Content248257
+Ref: Splitting By Content-Footnote-1252040
+Node: More CSV252203
+Node: Testing field creation253513
+Node: Multiple Line255138
+Node: Getline261415
+Node: Plain Getline263884
+Node: Getline/Variable266457
+Node: Getline/File267608
+Node: Getline/Variable/File268996
+Ref: Getline/Variable/File-Footnote-1270601
+Node: Getline/Pipe270689
+Node: Getline/Variable/Pipe273393
+Node: Getline/Coprocess274528
+Node: Getline/Variable/Coprocess275795
+Node: Getline Notes276537
+Node: Getline Summary279334
+Ref: table-getline-variants279758
+Node: Read Timeout280506
+Ref: Read Timeout-Footnote-1284412
+Node: Retrying Input284470
+Node: Command-line directories285669
+Node: Input Summary286575
+Node: Input Exercises289747
+Node: Printing290181
+Node: Print292015
+Node: Print Examples293472
+Node: Output Separators296252
+Node: OFMT298269
+Node: Printf299625
+Node: Basic Printf300410
+Node: Control Letters301984
+Node: Format Modifiers307146
+Node: Printf Examples313161
+Node: Redirection315647
+Node: Special FD322488
+Ref: Special FD-Footnote-1325656
+Node: Special Files325730
+Node: Other Inherited Files326347
+Node: Special Network327348
+Node: Special Caveats328208
+Node: Close Files And Pipes329157
+Ref: table-close-pipe-return-values336064
+Ref: Close Files And Pipes-Footnote-1336877
+Ref: Close Files And Pipes-Footnote-2337025
+Node: Nonfatal337177
+Node: Output Summary339515
+Node: Output Exercises340737
+Node: Expressions341416
+Node: Values342604
+Node: Constants343282
+Node: Scalar Constants343973
+Ref: Scalar Constants-Footnote-1346483
+Node: Nondecimal-numbers346733
+Node: Regexp Constants349734
+Node: Using Constant Regexps350260
+Node: Standard Regexp Constants350882
+Node: Strong Regexp Constants354070
+Node: Variables357082
+Node: Using Variables357739
+Node: Assignment Options359649
+Node: Conversion362120
+Node: Strings And Numbers362644
+Ref: Strings And Numbers-Footnote-1365707
+Node: Locale influences conversions365816
+Ref: table-locale-affects368574
+Node: All Operators369192
+Node: Arithmetic Ops369821
+Node: Concatenation372537
+Ref: Concatenation-Footnote-1375384
+Node: Assignment Ops375491
+Ref: table-assign-ops380482
+Node: Increment Ops381795
+Node: Truth Values and Conditions385255
+Node: Truth Values386329
+Node: Typing and Comparison387377
+Node: Variable Typing388197
+Ref: Variable Typing-Footnote-1394660
+Ref: Variable Typing-Footnote-2394732
+Node: Comparison Operators394809
+Ref: table-relational-ops395228
+Node: POSIX String Comparison398723
+Ref: POSIX String Comparison-Footnote-1400418
+Ref: POSIX String Comparison-Footnote-2400557
+Node: Boolean Ops400641
+Ref: Boolean Ops-Footnote-1405123
+Node: Conditional Exp405215
+Node: Function Calls406951
+Node: Precedence410828
+Node: Locales414487
+Node: Expressions Summary416119
+Node: Patterns and Actions418692
+Node: Pattern Overview419812
+Node: Regexp Patterns421489
+Node: Expression Patterns422031
+Node: Ranges425812
+Node: BEGIN/END428920
+Node: Using BEGIN/END429681
+Ref: Using BEGIN/END-Footnote-1432435
+Node: I/O And BEGIN/END432541
+Node: BEGINFILE/ENDFILE434854
+Node: Empty438085
+Node: Using Shell Variables438402
+Node: Action Overview440676
+Node: Statements443001
+Node: If Statement444849
+Node: While Statement446344
+Node: Do Statement448372
+Node: For Statement449520
+Node: Switch Statement452691
+Node: Break Statement455132
+Node: Continue Statement457224
+Node: Next Statement459051
+Node: Nextfile Statement461434
+Node: Exit Statement464072
+Node: Built-in Variables466475
+Node: User-modified467608
+Node: Auto-set475375
+Ref: Auto-set-Footnote-1492182
+Ref: Auto-set-Footnote-2492388
+Node: ARGC and ARGV492444
+Node: Pattern Action Summary496657
+Node: Arrays499087
+Node: Array Basics500416
+Node: Array Intro501260
+Ref: figure-array-elements503235
+Ref: Array Intro-Footnote-1505939
+Node: Reference to Elements506067
+Node: Assigning Elements508531
+Node: Array Example509022
+Node: Scanning an Array510781
+Node: Controlling Scanning513803
+Ref: Controlling Scanning-Footnote-1520259
+Node: Numeric Array Subscripts520575
+Node: Uninitialized Subscripts522759
+Node: Delete524378
+Ref: Delete-Footnote-1527130
+Node: Multidimensional527187
+Node: Multiscanning530282
+Node: Arrays of Arrays531873
+Node: Arrays Summary536641
+Node: Functions538734
+Node: Built-in539772
+Node: Calling Built-in540853
+Node: Numeric Functions542849
+Ref: Numeric Functions-Footnote-1546875
+Ref: Numeric Functions-Footnote-2547523
+Ref: Numeric Functions-Footnote-3547571
+Node: String Functions547843
+Ref: String Functions-Footnote-1571984
+Ref: String Functions-Footnote-2572112
+Ref: String Functions-Footnote-3572360
+Node: Gory Details572447
+Ref: table-sub-escapes574238
+Ref: table-sub-proposed575757
+Ref: table-posix-sub577120
+Ref: table-gensub-escapes578661
+Ref: Gory Details-Footnote-1579484
+Node: I/O Functions579638
+Ref: table-system-return-values586092
+Ref: I/O Functions-Footnote-1588172
+Ref: I/O Functions-Footnote-2588320
+Node: Time Functions588440
+Ref: Time Functions-Footnote-1599111
+Ref: Time Functions-Footnote-2599179
+Ref: Time Functions-Footnote-3599337
+Ref: Time Functions-Footnote-4599448
+Ref: Time Functions-Footnote-5599560
+Ref: Time Functions-Footnote-6599787
+Node: Bitwise Functions600053
+Ref: table-bitwise-ops600647
+Ref: Bitwise Functions-Footnote-1606710
+Ref: Bitwise Functions-Footnote-2606883
+Node: Type Functions607074
+Node: I18N Functions609937
+Node: User-defined611588
+Node: Definition Syntax612400
+Ref: Definition Syntax-Footnote-1618094
+Node: Function Example618165
+Ref: Function Example-Footnote-1621087
+Node: Function Calling621109
+Node: Calling A Function621697
+Node: Variable Scope622655
+Node: Pass By Value/Reference625649
+Node: Function Caveats628293
+Ref: Function Caveats-Footnote-1630340
+Node: Return Statement630460
+Node: Dynamic Typing633439
+Node: Indirect Calls634369
+Ref: Indirect Calls-Footnote-1644621
+Node: Functions Summary644749
+Node: Library Functions647454
+Ref: Library Functions-Footnote-1651061
+Ref: Library Functions-Footnote-2651204
+Node: Library Names651375
+Ref: Library Names-Footnote-1655042
+Ref: Library Names-Footnote-2655265
+Node: General Functions655351
+Node: Strtonum Function656454
+Node: Assert Function659476
+Node: Round Function662802
+Node: Cliff Random Function664342
+Node: Ordinal Functions665358
+Ref: Ordinal Functions-Footnote-1668421
+Ref: Ordinal Functions-Footnote-2668673
+Node: Join Function668883
+Ref: Join Function-Footnote-1670653
+Node: Getlocaltime Function670853
+Node: Readfile Function674595
+Node: Shell Quoting676572
+Node: Data File Management677973
+Node: Filetrans Function678605
+Node: Rewind Function682701
+Node: File Checking684610
+Ref: File Checking-Footnote-1685944
+Node: Empty Files686145
+Node: Ignoring Assigns688124
+Node: Getopt Function689674
+Ref: Getopt Function-Footnote-1704885
+Node: Passwd Functions705085
+Ref: Passwd Functions-Footnote-1713924
+Node: Group Functions714012
+Ref: Group Functions-Footnote-1721910
+Node: Walking Arrays722117
+Node: Library Functions Summary725125
+Node: Library Exercises726531
+Node: Sample Programs726996
+Node: Running Examples727766
+Node: Clones728494
+Node: Cut Program729718
+Node: Egrep Program739647
+Node: Id Program748658
+Node: Split Program758605
+Ref: Split Program-Footnote-1768379
+Node: Tee Program768552
+Node: Uniq Program771342
+Node: Wc Program778906
+Node: Bytes vs. Characters779303
+Node: Using extensions780851
+Node: wc program781609
+Node: Miscellaneous Programs786474
+Node: Dupword Program787687
+Node: Alarm Program789717
+Node: Translate Program794572
+Ref: Translate Program-Footnote-1799137
+Node: Labels Program799407
+Ref: Labels Program-Footnote-1802758
+Node: Word Sorting802842
+Node: History Sorting806914
+Node: Extract Program809139
+Node: Simple Sed817193
+Node: Igawk Program820267
+Ref: Igawk Program-Footnote-1834598
+Ref: Igawk Program-Footnote-2834800
+Ref: Igawk Program-Footnote-3834922
+Node: Anagram Program835037
+Node: Signature Program838099
+Node: Programs Summary839346
+Node: Programs Exercises840560
+Ref: Programs Exercises-Footnote-1844690
+Node: Advanced Features844776
+Node: Nondecimal Data846766
+Node: Array Sorting848357
+Node: Controlling Array Traversal849057
+Ref: Controlling Array Traversal-Footnote-1857425
+Node: Array Sorting Functions857543
+Ref: Array Sorting Functions-Footnote-1862634
+Node: Two-way I/O862830
+Ref: Two-way I/O-Footnote-1870551
+Ref: Two-way I/O-Footnote-2870738
+Node: TCP/IP Networking870820
+Node: Profiling873938
+Node: Advanced Features Summary883252
+Node: Internationalization885096
+Node: I18N and L10N886576
+Node: Explaining gettext887263
+Ref: Explaining gettext-Footnote-1893155
+Ref: Explaining gettext-Footnote-2893340
+Node: Programmer i18n893505
+Ref: Programmer i18n-Footnote-1898454
+Node: Translator i18n898503
+Node: String Extraction899297
+Ref: String Extraction-Footnote-1900429
+Node: Printf Ordering900515
+Ref: Printf Ordering-Footnote-1903301
+Node: I18N Portability903365
+Ref: I18N Portability-Footnote-1905821
+Node: I18N Example905884
+Ref: I18N Example-Footnote-1909159
+Ref: I18N Example-Footnote-2909232
+Node: Gawk I18N909341
+Node: I18N Summary909990
+Node: Debugger911331
+Node: Debugging912331
+Node: Debugging Concepts912772
+Node: Debugging Terms914581
+Node: Awk Debugging917156
+Ref: Awk Debugging-Footnote-1918101
+Node: Sample Debugging Session918233
+Node: Debugger Invocation918767
+Node: Finding The Bug920153
+Node: List of Debugger Commands926627
+Node: Breakpoint Control927960
+Node: Debugger Execution Control931654
+Node: Viewing And Changing Data935016
+Node: Execution Stack938557
+Node: Debugger Info940194
+Node: Miscellaneous Debugger Commands944265
+Node: Readline Support949327
+Node: Limitations950223
+Node: Debugging Summary952777
+Node: Namespaces954056
+Node: Global Namespace955167
+Node: Qualified Names956565
+Node: Default Namespace957564
+Node: Changing The Namespace958305
+Node: Naming Rules959919
+Node: Internal Name Management961767
+Node: Namespace Example962809
+Node: Namespace And Features965371
+Node: Namespace Summary966806
+Node: Arbitrary Precision Arithmetic968283
+Node: Computer Arithmetic969770
+Ref: table-numeric-ranges973536
+Ref: table-floating-point-ranges974029
+Ref: Computer Arithmetic-Footnote-1974687
+Node: Math Definitions974744
+Ref: table-ieee-formats977720
+Node: MPFR features978287
+Node: FP Math Caution980005
+Ref: FP Math Caution-Footnote-1981077
+Node: Inexactness of computations981446
+Node: Inexact representation982477
+Node: Comparing FP Values983837
+Node: Errors accumulate985078
+Node: Strange values986534
+Ref: Strange values-Footnote-1989096
+Node: Getting Accuracy989201
+Node: Try To Round991911
+Node: Setting precision992810
+Ref: table-predefined-precision-strings993507
+Node: Setting the rounding mode995337
+Ref: table-gawk-rounding-modes995711
+Ref: Setting the rounding mode-Footnote-1999642
+Node: Arbitrary Precision Integers999821
+Ref: Arbitrary Precision Integers-Footnote-11002996
+Node: Checking for MPFR1003145
+Node: POSIX Floating Point Problems1004619
+Ref: POSIX Floating Point Problems-Footnote-11008904
+Node: Floating point summary1008942
+Node: Dynamic Extensions1011132
+Node: Extension Intro1012685
+Node: Plugin License1013951
+Node: Extension Mechanism Outline1014748
+Ref: figure-load-extension1015187
+Ref: figure-register-new-function1016752
+Ref: figure-call-new-function1017844
+Node: Extension API Description1019906
+Node: Extension API Functions Introduction1021619
+Ref: table-api-std-headers1023455
+Node: General Data Types1027704
+Ref: General Data Types-Footnote-11036334
+Node: Memory Allocation Functions1036633
+Ref: Memory Allocation Functions-Footnote-11041134
+Node: Constructor Functions1041233
+Node: API Ownership of MPFR and GMP Values1044699
+Node: Registration Functions1046012
+Node: Extension Functions1046712
+Node: Exit Callback Functions1052034
+Node: Extension Version String1053284
+Node: Input Parsers1053947
+Node: Output Wrappers1066668
+Node: Two-way processors1071180
+Node: Printing Messages1073445
+Ref: Printing Messages-Footnote-11074616
+Node: Updating ERRNO1074769
+Node: Requesting Values1075508
+Ref: table-value-types-returned1076245
+Node: Accessing Parameters1077181
+Node: Symbol Table Access1078418
+Node: Symbol table by name1078930
+Ref: Symbol table by name-Footnote-11081954
+Node: Symbol table by cookie1082082
+Ref: Symbol table by cookie-Footnote-11086267
+Node: Cached values1086331
+Ref: Cached values-Footnote-11089867
+Node: Array Manipulation1090020
+Ref: Array Manipulation-Footnote-11091111
+Node: Array Data Types1091148
+Ref: Array Data Types-Footnote-11093806
+Node: Array Functions1093898
+Node: Flattening Arrays1098396
+Node: Creating Arrays1105372
+Node: Redirection API1110139
+Node: Extension API Variables1112972
+Node: Extension Versioning1113683
+Ref: gawk-api-version1114112
+Node: Extension GMP/MPFR Versioning1115843
+Node: Extension API Informational Variables1117471
+Node: Extension API Boilerplate1118544
+Node: Changes from API V11122518
+Node: Finding Extensions1124090
+Node: Extension Example1124649
+Node: Internal File Description1125447
+Node: Internal File Ops1129527
+Ref: Internal File Ops-Footnote-11140877
+Node: Using Internal File Ops1141017
+Ref: Using Internal File Ops-Footnote-11143400
+Node: Extension Samples1143674
+Node: Extension Sample File Functions1145203
+Node: Extension Sample Fnmatch1152852
+Node: Extension Sample Fork1154339
+Node: Extension Sample Inplace1155557
+Node: Extension Sample Ord1159183
+Node: Extension Sample Readdir1160019
+Ref: table-readdir-file-types1160908
+Node: Extension Sample Revout1161975
+Node: Extension Sample Rev2way1162564
+Node: Extension Sample Read write array1163304
+Node: Extension Sample Readfile1165246
+Node: Extension Sample Time1166341
+Node: Extension Sample API Tests1168093
+Node: gawkextlib1168585
+Node: Extension summary1171503
+Node: Extension Exercises1175205
+Node: Language History1176447
+Node: V7/SVR3.11178103
+Node: SVR41180255
+Node: POSIX1181689
+Node: BTL1183070
+Node: POSIX/GNU1183799
+Node: Feature History1189577
+Node: Common Extensions1205896
+Node: Ranges and Locales1207179
+Ref: Ranges and Locales-Footnote-11211795
+Ref: Ranges and Locales-Footnote-21211822
+Ref: Ranges and Locales-Footnote-31212057
+Node: Contributors1212280
+Node: History summary1218277
+Node: Installation1219657
+Node: Gawk Distribution1220601
+Node: Getting1221085
+Node: Extracting1222048
+Node: Distribution contents1223686
+Node: Unix Installation1230166
+Node: Quick Installation1230848
+Node: Shell Startup Files1233262
+Node: Additional Configuration Options1234351
+Node: Configuration Philosophy1236666
+Node: Non-Unix Installation1239035
+Node: PC Installation1239495
+Node: PC Binary Installation1240333
+Node: PC Compiling1240768
+Node: PC Using1241885
+Node: Cygwin1245438
+Node: MSYS1246662
+Node: VMS Installation1247264
+Node: VMS Compilation1248055
+Ref: VMS Compilation-Footnote-11249284
+Node: VMS Dynamic Extensions1249342
+Node: VMS Installation Details1251027
+Node: VMS Running1253280
+Node: VMS GNV1257559
+Node: VMS Old Gawk1258294
+Node: Bugs1258765
+Node: Bug address1259428
+Node: Usenet1262410
+Node: Maintainers1263414
+Node: Other Versions1264599
+Node: Installation summary1271687
+Node: Notes1272896
+Node: Compatibility Mode1273690
+Node: Additions1274472
+Node: Accessing The Source1275397
+Node: Adding Code1276834
+Node: New Ports1283053
+Node: Derived Files1287428
+Ref: Derived Files-Footnote-11293088
+Ref: Derived Files-Footnote-21293123
+Ref: Derived Files-Footnote-31293721
+Node: Future Extensions1293835
+Node: Implementation Limitations1294493
+Node: Extension Design1295703
+Node: Old Extension Problems1296847
+Ref: Old Extension Problems-Footnote-11298365
+Node: Extension New Mechanism Goals1298422
+Ref: Extension New Mechanism Goals-Footnote-11301786
+Node: Extension Other Design Decisions1301975
+Node: Extension Future Growth1304088
+Node: Notes summary1304694
+Node: Basic Concepts1305852
+Node: Basic High Level1306533
+Ref: figure-general-flow1306815
+Ref: figure-process-flow1307500
+Ref: Basic High Level-Footnote-11310801
+Node: Basic Data Typing1310986
+Node: Glossary1314314
+Node: Copying1346199
+Node: GNU Free Documentation License1383742
+Node: Index1408862

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index a7d7ff56..c69d591d 100644
--- a/doc/gawk.texi
+++ b/doc/gawk.texi
@@ -919,6 +919,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.
@@ -3135,11 +3136,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
@@ -8413,7 +8415,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})
@@ -10063,7 +10065,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
@@ -18298,7 +18300,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.
@@ -33586,21 +33588,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
@@ -33769,6 +33759,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
@@ -33890,6 +33881,236 @@ $ @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 infinity.
+
+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.
+
+@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 2a25c1d0..8b35bf32 100644
--- a/doc/gawktexi.in
+++ b/doc/gawktexi.in
@@ -914,6 +914,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.
@@ -3045,11 +3046,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
@@ -7966,7 +7968,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})
@@ -9616,7 +9618,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
@@ -17523,7 +17525,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.
@@ -32552,21 +32554,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
@@ -32735,6 +32725,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
@@ -32856,6 +32847,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 infinity.
+
+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 hanle 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/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 *