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.texi273
-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, 1519 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 a1898169..af355722 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -4,6 +4,27 @@
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 cc359a69..bf4400fa 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 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
@@ -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 Statement464046
-Node: Built-in Variables466449
-Node: User-modified467582
-Node: Auto-set475349
-Ref: Auto-set-Footnote-1492156
-Ref: Auto-set-Footnote-2492362
-Node: ARGC and ARGV492418
-Node: Pattern Action Summary496631
-Node: Arrays499061
-Node: Array Basics500390
-Node: Array Intro501234
-Ref: figure-array-elements503209
-Ref: Array Intro-Footnote-1505913
-Node: Reference to Elements506041
-Node: Assigning Elements508505
-Node: Array Example508996
-Node: Scanning an Array510755
-Node: Controlling Scanning513777
-Ref: Controlling Scanning-Footnote-1520233
-Node: Numeric Array Subscripts520549
-Node: Uninitialized Subscripts522733
-Node: Delete524352
-Ref: Delete-Footnote-1527104
-Node: Multidimensional527161
-Node: Multiscanning530256
-Node: Arrays of Arrays531847
-Node: Arrays Summary536615
-Node: Functions538708
-Node: Built-in539746
-Node: Calling Built-in540827
-Node: Numeric Functions542823
-Ref: Numeric Functions-Footnote-1546851
-Ref: Numeric Functions-Footnote-2547499
-Ref: Numeric Functions-Footnote-3547547
-Node: String Functions547819
-Ref: String Functions-Footnote-1571960
-Ref: String Functions-Footnote-2572088
-Ref: String Functions-Footnote-3572336
-Node: Gory Details572423
-Ref: table-sub-escapes574214
-Ref: table-sub-proposed575733
-Ref: table-posix-sub577096
-Ref: table-gensub-escapes578637
-Ref: Gory Details-Footnote-1579460
-Node: I/O Functions579614
-Ref: table-system-return-values586068
-Ref: I/O Functions-Footnote-1588148
-Ref: I/O Functions-Footnote-2588296
-Node: Time Functions588416
-Ref: Time Functions-Footnote-1599087
-Ref: Time Functions-Footnote-2599155
-Ref: Time Functions-Footnote-3599313
-Ref: Time Functions-Footnote-4599424
-Ref: Time Functions-Footnote-5599536
-Ref: Time Functions-Footnote-6599763
-Node: Bitwise Functions600029
-Ref: table-bitwise-ops600623
-Ref: Bitwise Functions-Footnote-1606686
-Ref: Bitwise Functions-Footnote-2606859
-Node: Type Functions607050
-Node: I18N Functions609913
-Node: User-defined611564
-Node: Definition Syntax612376
-Ref: Definition Syntax-Footnote-1618070
-Node: Function Example618141
-Ref: Function Example-Footnote-1621063
-Node: Function Calling621085
-Node: Calling A Function621673
-Node: Variable Scope622631
-Node: Pass By Value/Reference625625
-Node: Function Caveats628269
-Ref: Function Caveats-Footnote-1630316
-Node: Return Statement630436
-Node: Dynamic Typing633415
-Node: Indirect Calls634345
-Ref: Indirect Calls-Footnote-1644597
-Node: Functions Summary644725
-Node: Library Functions647430
-Ref: Library Functions-Footnote-1651037
-Ref: Library Functions-Footnote-2651180
-Node: Library Names651351
-Ref: Library Names-Footnote-1655018
-Ref: Library Names-Footnote-2655241
-Node: General Functions655327
-Node: Strtonum Function656430
-Node: Assert Function659452
-Node: Round Function662778
-Node: Cliff Random Function664318
-Node: Ordinal Functions665334
-Ref: Ordinal Functions-Footnote-1668397
-Ref: Ordinal Functions-Footnote-2668649
-Node: Join Function668859
-Ref: Join Function-Footnote-1670629
-Node: Getlocaltime Function670829
-Node: Readfile Function674571
-Node: Shell Quoting676548
-Node: Data File Management677949
-Node: Filetrans Function678581
-Node: Rewind Function682677
-Node: File Checking684586
-Ref: File Checking-Footnote-1685920
-Node: Empty Files686121
-Node: Ignoring Assigns688100
-Node: Getopt Function689650
-Ref: Getopt Function-Footnote-1704861
-Node: Passwd Functions705061
-Ref: Passwd Functions-Footnote-1713900
-Node: Group Functions713988
-Ref: Group Functions-Footnote-1721886
-Node: Walking Arrays722093
-Node: Library Functions Summary725101
-Node: Library Exercises726507
-Node: Sample Programs726972
-Node: Running Examples727742
-Node: Clones728470
-Node: Cut Program729694
-Node: Egrep Program739623
-Node: Id Program748634
-Node: Split Program758581
-Ref: Split Program-Footnote-1768355
-Node: Tee Program768528
-Node: Uniq Program771318
-Node: Wc Program778882
-Node: Bytes vs. Characters779279
-Node: Using extensions780827
-Node: wc program781585
-Node: Miscellaneous Programs786450
-Node: Dupword Program787663
-Node: Alarm Program789693
-Node: Translate Program794548
-Ref: Translate Program-Footnote-1799113
-Node: Labels Program799383
-Ref: Labels Program-Footnote-1802734
-Node: Word Sorting802818
-Node: History Sorting806890
-Node: Extract Program809115
-Node: Simple Sed817169
-Node: Igawk Program820243
-Ref: Igawk Program-Footnote-1834574
-Ref: Igawk Program-Footnote-2834776
-Ref: Igawk Program-Footnote-3834898
-Node: Anagram Program835013
-Node: Signature Program838075
-Node: Programs Summary839322
-Node: Programs Exercises840536
-Ref: Programs Exercises-Footnote-1844666
-Node: Advanced Features844752
-Node: Nondecimal Data846742
-Node: Array Sorting848333
-Node: Controlling Array Traversal849033
-Ref: Controlling Array Traversal-Footnote-1857401
-Node: Array Sorting Functions857519
-Ref: Array Sorting Functions-Footnote-1862610
-Node: Two-way I/O862806
-Ref: Two-way I/O-Footnote-1870527
-Ref: Two-way I/O-Footnote-2870714
-Node: TCP/IP Networking870796
-Node: Profiling873914
-Node: Advanced Features Summary883228
-Node: Internationalization885072
-Node: I18N and L10N886552
-Node: Explaining gettext887239
-Ref: Explaining gettext-Footnote-1893131
-Ref: Explaining gettext-Footnote-2893316
-Node: Programmer i18n893481
-Ref: Programmer i18n-Footnote-1898430
-Node: Translator i18n898479
-Node: String Extraction899273
-Ref: String Extraction-Footnote-1900405
-Node: Printf Ordering900491
-Ref: Printf Ordering-Footnote-1903277
-Node: I18N Portability903341
-Ref: I18N Portability-Footnote-1905797
-Node: I18N Example905860
-Ref: I18N Example-Footnote-1909135
-Ref: I18N Example-Footnote-2909208
-Node: Gawk I18N909317
-Node: I18N Summary909966
-Node: Debugger911307
-Node: Debugging912307
-Node: Debugging Concepts912748
-Node: Debugging Terms914557
-Node: Awk Debugging917132
-Ref: Awk Debugging-Footnote-1918077
-Node: Sample Debugging Session918209
-Node: Debugger Invocation918743
-Node: Finding The Bug920129
-Node: List of Debugger Commands926603
-Node: Breakpoint Control927936
-Node: Debugger Execution Control931630
-Node: Viewing And Changing Data934992
-Node: Execution Stack938533
-Node: Debugger Info940170
-Node: Miscellaneous Debugger Commands944241
-Node: Readline Support949303
-Node: Limitations950199
-Node: Debugging Summary952753
-Node: Namespaces954032
-Node: Global Namespace955143
-Node: Qualified Names956541
-Node: Default Namespace957540
-Node: Changing The Namespace958281
-Node: Naming Rules959895
-Node: Internal Name Management961743
-Node: Namespace Example962785
-Node: Namespace And Features965347
-Node: Namespace Summary966782
-Node: Arbitrary Precision Arithmetic968259
-Node: Computer Arithmetic969746
-Ref: table-numeric-ranges973512
-Ref: table-floating-point-ranges974005
-Ref: Computer Arithmetic-Footnote-1974663
-Node: Math Definitions974720
-Ref: table-ieee-formats978036
-Ref: Math Definitions-Footnote-1978639
-Node: MPFR features978744
-Node: FP Math Caution980462
-Ref: FP Math Caution-Footnote-1981534
-Node: Inexactness of computations981903
-Node: Inexact representation982863
-Node: Comparing FP Values984223
-Node: Errors accumulate985464
-Node: Getting Accuracy986897
-Node: Try To Round989607
-Node: Setting precision990506
-Ref: table-predefined-precision-strings991203
-Node: Setting the rounding mode993033
-Ref: table-gawk-rounding-modes993407
-Ref: Setting the rounding mode-Footnote-1997338
-Node: Arbitrary Precision Integers997517
-Ref: Arbitrary Precision Integers-Footnote-11000692
-Node: Checking for MPFR1000841
-Node: POSIX Floating Point Problems1002315
-Ref: POSIX Floating Point Problems-Footnote-11006600
-Node: Floating point summary1006638
-Node: Dynamic Extensions1008828
-Node: Extension Intro1010381
-Node: Plugin License1011647
-Node: Extension Mechanism Outline1012444
-Ref: figure-load-extension1012883
-Ref: figure-register-new-function1014448
-Ref: figure-call-new-function1015540
-Node: Extension API Description1017602
-Node: Extension API Functions Introduction1019315
-Ref: table-api-std-headers1021151
-Node: General Data Types1025400
-Ref: General Data Types-Footnote-11034030
-Node: Memory Allocation Functions1034329
-Ref: Memory Allocation Functions-Footnote-11038830
-Node: Constructor Functions1038929
-Node: API Ownership of MPFR and GMP Values1042395
-Node: Registration Functions1043708
-Node: Extension Functions1044408
-Node: Exit Callback Functions1049730
-Node: Extension Version String1050980
-Node: Input Parsers1051643
-Node: Output Wrappers1064364
-Node: Two-way processors1068876
-Node: Printing Messages1071141
-Ref: Printing Messages-Footnote-11072312
-Node: Updating ERRNO1072465
-Node: Requesting Values1073204
-Ref: table-value-types-returned1073941
-Node: Accessing Parameters1074877
-Node: Symbol Table Access1076114
-Node: Symbol table by name1076626
-Ref: Symbol table by name-Footnote-11079650
-Node: Symbol table by cookie1079778
-Ref: Symbol table by cookie-Footnote-11083963
-Node: Cached values1084027
-Ref: Cached values-Footnote-11087563
-Node: Array Manipulation1087716
-Ref: Array Manipulation-Footnote-11088807
-Node: Array Data Types1088844
-Ref: Array Data Types-Footnote-11091502
-Node: Array Functions1091594
-Node: Flattening Arrays1096092
-Node: Creating Arrays1103068
-Node: Redirection API1107835
-Node: Extension API Variables1110668
-Node: Extension Versioning1111379
-Ref: gawk-api-version1111808
-Node: Extension GMP/MPFR Versioning1113539
-Node: Extension API Informational Variables1115167
-Node: Extension API Boilerplate1116240
-Node: Changes from API V11120214
-Node: Finding Extensions1121786
-Node: Extension Example1122345
-Node: Internal File Description1123143
-Node: Internal File Ops1127223
-Ref: Internal File Ops-Footnote-11138573
-Node: Using Internal File Ops1138713
-Ref: Using Internal File Ops-Footnote-11141096
-Node: Extension Samples1141370
-Node: Extension Sample File Functions1142899
-Node: Extension Sample Fnmatch1150548
-Node: Extension Sample Fork1152035
-Node: Extension Sample Inplace1153253
-Node: Extension Sample Ord1156879
-Node: Extension Sample Readdir1157715
-Ref: table-readdir-file-types1158604
-Node: Extension Sample Revout1159671
-Node: Extension Sample Rev2way1160260
-Node: Extension Sample Read write array1161000
-Node: Extension Sample Readfile1162942
-Node: Extension Sample Time1164037
-Node: Extension Sample API Tests1165789
-Node: gawkextlib1166281
-Node: Extension summary1169199
-Node: Extension Exercises1172901
-Node: Language History1174143
-Node: V7/SVR3.11175799
-Node: SVR41177951
-Node: POSIX1179385
-Node: BTL1180766
-Node: POSIX/GNU1181495
-Node: Feature History1187273
-Node: Common Extensions1203592
-Node: Ranges and Locales1204875
-Ref: Ranges and Locales-Footnote-11209491
-Ref: Ranges and Locales-Footnote-21209518
-Ref: Ranges and Locales-Footnote-31209753
-Node: Contributors1209976
-Node: History summary1215973
-Node: Installation1217353
-Node: Gawk Distribution1218297
-Node: Getting1218781
-Node: Extracting1219744
-Node: Distribution contents1221382
-Node: Unix Installation1227862
-Node: Quick Installation1228544
-Node: Shell Startup Files1230958
-Node: Additional Configuration Options1232047
-Node: Configuration Philosophy1234362
-Node: Non-Unix Installation1236731
-Node: PC Installation1237191
-Node: PC Binary Installation1238029
-Node: PC Compiling1238464
-Node: PC Using1239581
-Node: Cygwin1243134
-Node: MSYS1244358
-Node: VMS Installation1244960
-Node: VMS Compilation1245751
-Ref: VMS Compilation-Footnote-11246980
-Node: VMS Dynamic Extensions1247038
-Node: VMS Installation Details1248723
-Node: VMS Running1250976
-Node: VMS GNV1255255
-Node: VMS Old Gawk1255990
-Node: Bugs1256461
-Node: Bug address1257124
-Node: Usenet1260106
-Node: Maintainers1261110
-Node: Other Versions1262295
-Node: Installation summary1269383
-Node: Notes1270592
-Node: Compatibility Mode1271386
-Node: Additions1272168
-Node: Accessing The Source1273093
-Node: Adding Code1274530
-Node: New Ports1280749
-Node: Derived Files1285124
-Ref: Derived Files-Footnote-11290784
-Ref: Derived Files-Footnote-21290819
-Ref: Derived Files-Footnote-31291417
-Node: Future Extensions1291531
-Node: Implementation Limitations1292189
-Node: Extension Design1293399
-Node: Old Extension Problems1294543
-Ref: Old Extension Problems-Footnote-11296061
-Node: Extension New Mechanism Goals1296118
-Ref: Extension New Mechanism Goals-Footnote-11299482
-Node: Extension Other Design Decisions1299671
-Node: Extension Future Growth1301784
-Node: Notes summary1302390
-Node: Basic Concepts1303548
-Node: Basic High Level1304229
-Ref: figure-general-flow1304511
-Ref: figure-process-flow1305196
-Ref: Basic High Level-Footnote-11308497
-Node: Basic Data Typing1308682
-Node: Glossary1312010
-Node: Copying1343895
-Node: GNU Free Documentation License1381438
-Node: Index1406558
+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 Statement464123
+Node: Built-in Variables466526
+Node: User-modified467659
+Node: Auto-set475426
+Ref: Auto-set-Footnote-1492233
+Ref: Auto-set-Footnote-2492439
+Node: ARGC and ARGV492495
+Node: Pattern Action Summary496708
+Node: Arrays499138
+Node: Array Basics500467
+Node: Array Intro501311
+Ref: figure-array-elements503286
+Ref: Array Intro-Footnote-1505990
+Node: Reference to Elements506118
+Node: Assigning Elements508582
+Node: Array Example509073
+Node: Scanning an Array510832
+Node: Controlling Scanning513854
+Ref: Controlling Scanning-Footnote-1520310
+Node: Numeric Array Subscripts520626
+Node: Uninitialized Subscripts522810
+Node: Delete524429
+Ref: Delete-Footnote-1527181
+Node: Multidimensional527238
+Node: Multiscanning530333
+Node: Arrays of Arrays531924
+Node: Arrays Summary536692
+Node: Functions538785
+Node: Built-in539823
+Node: Calling Built-in540904
+Node: Numeric Functions542900
+Ref: Numeric Functions-Footnote-1546926
+Ref: Numeric Functions-Footnote-2547574
+Ref: Numeric Functions-Footnote-3547622
+Node: String Functions547894
+Ref: String Functions-Footnote-1572035
+Ref: String Functions-Footnote-2572163
+Ref: String Functions-Footnote-3572411
+Node: Gory Details572498
+Ref: table-sub-escapes574289
+Ref: table-sub-proposed575808
+Ref: table-posix-sub577171
+Ref: table-gensub-escapes578712
+Ref: Gory Details-Footnote-1579535
+Node: I/O Functions579689
+Ref: table-system-return-values586143
+Ref: I/O Functions-Footnote-1588223
+Ref: I/O Functions-Footnote-2588371
+Node: Time Functions588491
+Ref: Time Functions-Footnote-1599162
+Ref: Time Functions-Footnote-2599230
+Ref: Time Functions-Footnote-3599388
+Ref: Time Functions-Footnote-4599499
+Ref: Time Functions-Footnote-5599611
+Ref: Time Functions-Footnote-6599838
+Node: Bitwise Functions600104
+Ref: table-bitwise-ops600698
+Ref: Bitwise Functions-Footnote-1606761
+Ref: Bitwise Functions-Footnote-2606934
+Node: Type Functions607125
+Node: I18N Functions609988
+Node: User-defined611639
+Node: Definition Syntax612451
+Ref: Definition Syntax-Footnote-1618145
+Node: Function Example618216
+Ref: Function Example-Footnote-1621138
+Node: Function Calling621160
+Node: Calling A Function621748
+Node: Variable Scope622706
+Node: Pass By Value/Reference625700
+Node: Function Caveats628344
+Ref: Function Caveats-Footnote-1630391
+Node: Return Statement630511
+Node: Dynamic Typing633490
+Node: Indirect Calls634420
+Ref: Indirect Calls-Footnote-1644672
+Node: Functions Summary644800
+Node: Library Functions647505
+Ref: Library Functions-Footnote-1651112
+Ref: Library Functions-Footnote-2651255
+Node: Library Names651426
+Ref: Library Names-Footnote-1655093
+Ref: Library Names-Footnote-2655316
+Node: General Functions655402
+Node: Strtonum Function656505
+Node: Assert Function659527
+Node: Round Function662853
+Node: Cliff Random Function664393
+Node: Ordinal Functions665409
+Ref: Ordinal Functions-Footnote-1668472
+Ref: Ordinal Functions-Footnote-2668724
+Node: Join Function668934
+Ref: Join Function-Footnote-1670704
+Node: Getlocaltime Function670904
+Node: Readfile Function674646
+Node: Shell Quoting676623
+Node: Data File Management678024
+Node: Filetrans Function678656
+Node: Rewind Function682752
+Node: File Checking684661
+Ref: File Checking-Footnote-1685995
+Node: Empty Files686196
+Node: Ignoring Assigns688175
+Node: Getopt Function689725
+Ref: Getopt Function-Footnote-1704936
+Node: Passwd Functions705136
+Ref: Passwd Functions-Footnote-1713975
+Node: Group Functions714063
+Ref: Group Functions-Footnote-1721961
+Node: Walking Arrays722168
+Node: Library Functions Summary725176
+Node: Library Exercises726582
+Node: Sample Programs727047
+Node: Running Examples727817
+Node: Clones728545
+Node: Cut Program729769
+Node: Egrep Program739698
+Node: Id Program748709
+Node: Split Program758656
+Ref: Split Program-Footnote-1768430
+Node: Tee Program768603
+Node: Uniq Program771393
+Node: Wc Program778957
+Node: Bytes vs. Characters779354
+Node: Using extensions780902
+Node: wc program781660
+Node: Miscellaneous Programs786525
+Node: Dupword Program787738
+Node: Alarm Program789768
+Node: Translate Program794623
+Ref: Translate Program-Footnote-1799188
+Node: Labels Program799458
+Ref: Labels Program-Footnote-1802809
+Node: Word Sorting802893
+Node: History Sorting806965
+Node: Extract Program809190
+Node: Simple Sed817244
+Node: Igawk Program820318
+Ref: Igawk Program-Footnote-1834649
+Ref: Igawk Program-Footnote-2834851
+Ref: Igawk Program-Footnote-3834973
+Node: Anagram Program835088
+Node: Signature Program838150
+Node: Programs Summary839397
+Node: Programs Exercises840611
+Ref: Programs Exercises-Footnote-1844741
+Node: Advanced Features844827
+Node: Nondecimal Data846817
+Node: Array Sorting848408
+Node: Controlling Array Traversal849108
+Ref: Controlling Array Traversal-Footnote-1857476
+Node: Array Sorting Functions857594
+Ref: Array Sorting Functions-Footnote-1862685
+Node: Two-way I/O862881
+Ref: Two-way I/O-Footnote-1870602
+Ref: Two-way I/O-Footnote-2870789
+Node: TCP/IP Networking870871
+Node: Profiling873989
+Node: Advanced Features Summary883303
+Node: Internationalization885147
+Node: I18N and L10N886627
+Node: Explaining gettext887314
+Ref: Explaining gettext-Footnote-1893206
+Ref: Explaining gettext-Footnote-2893391
+Node: Programmer i18n893556
+Ref: Programmer i18n-Footnote-1898505
+Node: Translator i18n898554
+Node: String Extraction899348
+Ref: String Extraction-Footnote-1900480
+Node: Printf Ordering900566
+Ref: Printf Ordering-Footnote-1903352
+Node: I18N Portability903416
+Ref: I18N Portability-Footnote-1905872
+Node: I18N Example905935
+Ref: I18N Example-Footnote-1909210
+Ref: I18N Example-Footnote-2909283
+Node: Gawk I18N909392
+Node: I18N Summary910041
+Node: Debugger911382
+Node: Debugging912382
+Node: Debugging Concepts912823
+Node: Debugging Terms914632
+Node: Awk Debugging917207
+Ref: Awk Debugging-Footnote-1918152
+Node: Sample Debugging Session918284
+Node: Debugger Invocation918818
+Node: Finding The Bug920204
+Node: List of Debugger Commands926678
+Node: Breakpoint Control928011
+Node: Debugger Execution Control931705
+Node: Viewing And Changing Data935067
+Node: Execution Stack938608
+Node: Debugger Info940245
+Node: Miscellaneous Debugger Commands944316
+Node: Readline Support949378
+Node: Limitations950274
+Node: Debugging Summary952828
+Node: Namespaces954107
+Node: Global Namespace955218
+Node: Qualified Names956616
+Node: Default Namespace957615
+Node: Changing The Namespace958356
+Node: Naming Rules959970
+Node: Internal Name Management961818
+Node: Namespace Example962860
+Node: Namespace And Features965422
+Node: Namespace Summary966857
+Node: Arbitrary Precision Arithmetic968334
+Node: Computer Arithmetic969821
+Ref: table-numeric-ranges973587
+Ref: table-floating-point-ranges974080
+Ref: Computer Arithmetic-Footnote-1974738
+Node: Math Definitions974795
+Ref: table-ieee-formats977771
+Node: MPFR features978338
+Node: FP Math Caution980056
+Ref: FP Math Caution-Footnote-1981128
+Node: Inexactness of computations981497
+Node: Inexact representation982528
+Node: Comparing FP Values983888
+Node: Errors accumulate985129
+Node: Strange values986585
+Ref: Strange values-Footnote-1989148
+Node: Getting Accuracy989253
+Node: Try To Round991963
+Node: Setting precision992862
+Ref: table-predefined-precision-strings993559
+Node: Setting the rounding mode995389
+Ref: table-gawk-rounding-modes995763
+Ref: Setting the rounding mode-Footnote-1999694
+Node: Arbitrary Precision Integers999873
+Ref: Arbitrary Precision Integers-Footnote-11003048
+Node: Checking for MPFR1003197
+Node: POSIX Floating Point Problems1004671
+Ref: POSIX Floating Point Problems-Footnote-11008956
+Node: Floating point summary1008994
+Node: Dynamic Extensions1011184
+Node: Extension Intro1012737
+Node: Plugin License1014003
+Node: Extension Mechanism Outline1014800
+Ref: figure-load-extension1015239
+Ref: figure-register-new-function1016804
+Ref: figure-call-new-function1017896
+Node: Extension API Description1019958
+Node: Extension API Functions Introduction1021671
+Ref: table-api-std-headers1023507
+Node: General Data Types1027756
+Ref: General Data Types-Footnote-11036386
+Node: Memory Allocation Functions1036685
+Ref: Memory Allocation Functions-Footnote-11041186
+Node: Constructor Functions1041285
+Node: API Ownership of MPFR and GMP Values1044751
+Node: Registration Functions1046064
+Node: Extension Functions1046764
+Node: Exit Callback Functions1052086
+Node: Extension Version String1053336
+Node: Input Parsers1053999
+Node: Output Wrappers1066720
+Node: Two-way processors1071232
+Node: Printing Messages1073497
+Ref: Printing Messages-Footnote-11074668
+Node: Updating ERRNO1074821
+Node: Requesting Values1075560
+Ref: table-value-types-returned1076297
+Node: Accessing Parameters1077233
+Node: Symbol Table Access1078470
+Node: Symbol table by name1078982
+Ref: Symbol table by name-Footnote-11082006
+Node: Symbol table by cookie1082134
+Ref: Symbol table by cookie-Footnote-11086319
+Node: Cached values1086383
+Ref: Cached values-Footnote-11089919
+Node: Array Manipulation1090072
+Ref: Array Manipulation-Footnote-11091163
+Node: Array Data Types1091200
+Ref: Array Data Types-Footnote-11093858
+Node: Array Functions1093950
+Node: Flattening Arrays1098448
+Node: Creating Arrays1105424
+Node: Redirection API1110191
+Node: Extension API Variables1113024
+Node: Extension Versioning1113735
+Ref: gawk-api-version1114164
+Node: Extension GMP/MPFR Versioning1115895
+Node: Extension API Informational Variables1117523
+Node: Extension API Boilerplate1118596
+Node: Changes from API V11122570
+Node: Finding Extensions1124142
+Node: Extension Example1124701
+Node: Internal File Description1125499
+Node: Internal File Ops1129579
+Ref: Internal File Ops-Footnote-11140929
+Node: Using Internal File Ops1141069
+Ref: Using Internal File Ops-Footnote-11143452
+Node: Extension Samples1143726
+Node: Extension Sample File Functions1145255
+Node: Extension Sample Fnmatch1152904
+Node: Extension Sample Fork1154391
+Node: Extension Sample Inplace1155609
+Node: Extension Sample Ord1159235
+Node: Extension Sample Readdir1160071
+Ref: table-readdir-file-types1160960
+Node: Extension Sample Revout1162027
+Node: Extension Sample Rev2way1162616
+Node: Extension Sample Read write array1163356
+Node: Extension Sample Readfile1165298
+Node: Extension Sample Time1166393
+Node: Extension Sample API Tests1168145
+Node: gawkextlib1168637
+Node: Extension summary1171555
+Node: Extension Exercises1175257
+Node: Language History1176499
+Node: V7/SVR3.11178155
+Node: SVR41180307
+Node: POSIX1181741
+Node: BTL1183122
+Node: POSIX/GNU1183851
+Node: Feature History1189629
+Node: Common Extensions1205948
+Node: Ranges and Locales1207231
+Ref: Ranges and Locales-Footnote-11211847
+Ref: Ranges and Locales-Footnote-21211874
+Ref: Ranges and Locales-Footnote-31212109
+Node: Contributors1212332
+Node: History summary1218329
+Node: Installation1219709
+Node: Gawk Distribution1220653
+Node: Getting1221137
+Node: Extracting1222100
+Node: Distribution contents1223738
+Node: Unix Installation1230218
+Node: Quick Installation1230900
+Node: Shell Startup Files1233314
+Node: Additional Configuration Options1234403
+Node: Configuration Philosophy1236718
+Node: Non-Unix Installation1239087
+Node: PC Installation1239547
+Node: PC Binary Installation1240385
+Node: PC Compiling1240820
+Node: PC Using1241937
+Node: Cygwin1245490
+Node: MSYS1246714
+Node: VMS Installation1247316
+Node: VMS Compilation1248107
+Ref: VMS Compilation-Footnote-11249336
+Node: VMS Dynamic Extensions1249394
+Node: VMS Installation Details1251079
+Node: VMS Running1253332
+Node: VMS GNV1257611
+Node: VMS Old Gawk1258346
+Node: Bugs1258817
+Node: Bug address1259480
+Node: Usenet1262462
+Node: Maintainers1263466
+Node: Other Versions1264651
+Node: Installation summary1271739
+Node: Notes1272948
+Node: Compatibility Mode1273742
+Node: Additions1274524
+Node: Accessing The Source1275449
+Node: Adding Code1276886
+Node: New Ports1283105
+Node: Derived Files1287480
+Ref: Derived Files-Footnote-11293140
+Ref: Derived Files-Footnote-21293175
+Ref: Derived Files-Footnote-31293773
+Node: Future Extensions1293887
+Node: Implementation Limitations1294545
+Node: Extension Design1295755
+Node: Old Extension Problems1296899
+Ref: Old Extension Problems-Footnote-11298417
+Node: Extension New Mechanism Goals1298474
+Ref: Extension New Mechanism Goals-Footnote-11301838
+Node: Extension Other Design Decisions1302027
+Node: Extension Future Growth1304140
+Node: Notes summary1304746
+Node: Basic Concepts1305904
+Node: Basic High Level1306585
+Ref: figure-general-flow1306867
+Ref: figure-process-flow1307552
+Ref: Basic High Level-Footnote-11310853
+Node: Basic Data Typing1311038
+Node: Glossary1314366
+Node: Copying1346251
+Node: GNU Free Documentation License1383794
+Node: Index1408914

End Tag Table
diff --git a/doc/gawk.texi b/doc/gawk.texi
index 043d5ddf..7943365f 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
@@ -18299,7 +18301,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.
@@ -33587,21 +33589,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
@@ -33770,6 +33760,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
@@ -33891,6 +33882,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 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 7c1f7120..04e16468 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
@@ -17524,7 +17526,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.
@@ -32553,21 +32555,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
@@ -32736,6 +32726,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
@@ -32857,6 +32848,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 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/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 *