aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--NEWS8
-rw-r--r--awk.h9
-rw-r--r--awklib/eg/test-programs/gen-float-table.awk59
-rw-r--r--awklib/eg/test-programs/gen-float-table.c60
-rw-r--r--awklib/eg/test-programs/gen-float-table.py42
-rw-r--r--builtin.c4
-rw-r--r--doc/ChangeLog27
-rw-r--r--doc/gawk.info1282
-rw-r--r--doc/gawk.texi273
-rw-r--r--doc/gawktexi.in273
-rw-r--r--doc/it/ChangeLog4
-rwxr-xr-x[-rw-r--r--]doc/it/gawktexi.in308
-rw-r--r--doc/wordlist2
-rw-r--r--eval.c96
-rw-r--r--interpret.h12
-rw-r--r--mpfr.c44
-rw-r--r--node.c5
18 files changed, 1803 insertions, 718 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 b606d14b..26c118e9 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -3,12 +3,39 @@
* gawkworkflow.texi: Add an additional web resource.
* gawktexi.in: More edits in sample programs chapter.
+2020-11-20 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Strange values): Correct the description of what
+ happens with infinity. Thanks to Antonio Columbo for pointing
+ out the problem.
+
2020-11-16 Arnold D. Robbins <arnold@skeeve.com>
* gawktexi.in (Nextfile Statement): Clarify what happens in
a BEGINFILE rule.
* gawktexi.in: Additional small fixes.
+2020-11-15 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Strange values): Add test programs inside
+ @ignore; extracted to example directory.
+
+2020-11-09 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in: Samll improvement in strange numbers section.
+
+2020-11-04 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Strange values): New section on NaN and infinity.
+ Update some other bits to point to it.
+ * wordlist: Updated with more words.
+
+2020-11-16 Arnold D. Robbins <arnold@skeeve.com>
+
+ * gawktexi.in (Nextfile Statement): Clarify what happens in
+ a BEGINFILE rule.
+>>>>>>> master
+
2020-10-31 Arnold D. Robbins <arnold@skeeve.com>
* texinfo.tex: Updated from GNULIB.
diff --git a/doc/gawk.info b/doc/gawk.info
index b1ba8672..b7f772a2 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()'
@@ -24161,18 +24162,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.
@@ -24231,11 +24224,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
@@ -24328,6 +24316,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
@@ -24392,7 +24381,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
..........................
@@ -24440,6 +24429,64 @@ representations yield an unexpected result:
-| 4

+File: gawk.info, Node: Strange values, Prev: Errors accumulate, Up: Inexactness of computations
+
+16.4.1.4 Floating Point Values They Didn't Talk About In School
+...............................................................
+
+Both IEEE 754 floating-point hardware, and MPFR, support two kinds of
+values that you probably didn't learn about in school. The first is
+"infinity", a special value, that can be either negative or positive,
+and which is either smaller than any other value (negative infinity), or
+larger than any other value (positive infinity). When such values are
+generated, 'gawk' prints them as either '-inf' or '+inf', respectively.
+It accepts those strings as data input and converts them to the proper
+floating-point values internally.
+
+ Infinity values of the same sign compare as equal to each other.
+Otherwise, operations (addition, subtraction, etc.) involving another
+number and infinity produce mathematically reasonable results.
+
+ The second kind of value is "not a number", or NaN for short.(1)
+This is a special value that results from attempting a calculation that
+has no answer as a real number. In such a case, programs can either
+receive a floating-point exception, or get NaN back as the result. The
+IEEE 754 standard recommends that systems return NaN. Some examples:
+
+'sqrt(-1)'
+ This makes sense in the range of complex numbers, but not in the
+ range of real numbers, so the result is NaN.
+
+'log(-8)'
+ -8 is out of the domain of 'log()', so the result is NaN.
+
+ NaN values are strange. In particular, they cannot be compared with
+other floating point values; any such comparison, except for "is not
+equal to", returns false. NaN values are so much unequal to other
+values that even comparing two identical NaN values with '!=' returns
+true!
+
+ NaN values can also be signed, although it depends upon the
+implementation as to which sign you get for any operation that returns a
+NaN. For example, on some systems, 'sqrt(-1)' returns a negative NaN. On
+others, it returns a positive NaN.
+
+ When such values are generated, 'gawk' prints them as either '-nan'
+or '+nan', respectively. Here too, 'gawk' accepts those strings as data
+input and converts them to the proper floating-point values internally.
+
+ If you want to dive more deeply into this topic, you can find test
+programs in C, 'awk' and Python in the directory
+'awklib/eg/test-programs' in the 'gawk' distribution. These programs
+enable comparison among programming languages as to how they handle NaN
+and infinity values.
+
+ ---------- Footnotes ----------
+
+ (1) Thanks to Michael Brennan for this description, which we have
+paraphrased, and for the examples.
+
+
File: gawk.info, Node: Getting Accuracy, Next: Try To Round, Prev: Inexactness of computations, Up: FP Math Caution
16.4.2 Getting the Accuracy You Need
@@ -37942,602 +37989,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 Program739834
-Node: Id Program748845
-Node: Split Program758792
-Ref: Split Program-Footnote-1768682
-Node: Tee Program768855
-Node: Uniq Program771645
-Node: Wc Program779233
-Node: Bytes vs. Characters779630
-Node: Using extensions781178
-Node: wc program781932
-Node: Miscellaneous Programs786797
-Node: Dupword Program788010
-Node: Alarm Program790040
-Node: Translate Program794895
-Ref: Translate Program-Footnote-1799460
-Node: Labels Program799730
-Ref: Labels Program-Footnote-1803081
-Node: Word Sorting803165
-Node: History Sorting807237
-Node: Extract Program809462
-Node: Simple Sed817516
-Node: Igawk Program820590
-Ref: Igawk Program-Footnote-1834921
-Ref: Igawk Program-Footnote-2835123
-Ref: Igawk Program-Footnote-3835245
-Node: Anagram Program835360
-Node: Signature Program838422
-Node: Programs Summary839669
-Node: Programs Exercises840883
-Ref: Programs Exercises-Footnote-1845013
-Node: Advanced Features845099
-Node: Nondecimal Data847089
-Node: Array Sorting848680
-Node: Controlling Array Traversal849380
-Ref: Controlling Array Traversal-Footnote-1857748
-Node: Array Sorting Functions857866
-Ref: Array Sorting Functions-Footnote-1862957
-Node: Two-way I/O863153
-Ref: Two-way I/O-Footnote-1870874
-Ref: Two-way I/O-Footnote-2871061
-Node: TCP/IP Networking871143
-Node: Profiling874261
-Node: Advanced Features Summary883575
-Node: Internationalization885419
-Node: I18N and L10N886899
-Node: Explaining gettext887586
-Ref: Explaining gettext-Footnote-1893478
-Ref: Explaining gettext-Footnote-2893663
-Node: Programmer i18n893828
-Ref: Programmer i18n-Footnote-1898777
-Node: Translator i18n898826
-Node: String Extraction899620
-Ref: String Extraction-Footnote-1900752
-Node: Printf Ordering900838
-Ref: Printf Ordering-Footnote-1903624
-Node: I18N Portability903688
-Ref: I18N Portability-Footnote-1906144
-Node: I18N Example906207
-Ref: I18N Example-Footnote-1909482
-Ref: I18N Example-Footnote-2909555
-Node: Gawk I18N909664
-Node: I18N Summary910313
-Node: Debugger911654
-Node: Debugging912654
-Node: Debugging Concepts913095
-Node: Debugging Terms914904
-Node: Awk Debugging917479
-Ref: Awk Debugging-Footnote-1918424
-Node: Sample Debugging Session918556
-Node: Debugger Invocation919090
-Node: Finding The Bug920476
-Node: List of Debugger Commands926950
-Node: Breakpoint Control928283
-Node: Debugger Execution Control931977
-Node: Viewing And Changing Data935339
-Node: Execution Stack938880
-Node: Debugger Info940517
-Node: Miscellaneous Debugger Commands944588
-Node: Readline Support949650
-Node: Limitations950546
-Node: Debugging Summary953100
-Node: Namespaces954379
-Node: Global Namespace955490
-Node: Qualified Names956888
-Node: Default Namespace957887
-Node: Changing The Namespace958628
-Node: Naming Rules960242
-Node: Internal Name Management962090
-Node: Namespace Example963132
-Node: Namespace And Features965694
-Node: Namespace Summary967129
-Node: Arbitrary Precision Arithmetic968606
-Node: Computer Arithmetic970093
-Ref: table-numeric-ranges973859
-Ref: table-floating-point-ranges974352
-Ref: Computer Arithmetic-Footnote-1975010
-Node: Math Definitions975067
-Ref: table-ieee-formats978383
-Ref: Math Definitions-Footnote-1978986
-Node: MPFR features979091
-Node: FP Math Caution980809
-Ref: FP Math Caution-Footnote-1981881
-Node: Inexactness of computations982250
-Node: Inexact representation983210
-Node: Comparing FP Values984570
-Node: Errors accumulate985811
-Node: Getting Accuracy987244
-Node: Try To Round989954
-Node: Setting precision990853
-Ref: table-predefined-precision-strings991550
-Node: Setting the rounding mode993380
-Ref: table-gawk-rounding-modes993754
-Ref: Setting the rounding mode-Footnote-1997685
-Node: Arbitrary Precision Integers997864
-Ref: Arbitrary Precision Integers-Footnote-11001039
-Node: Checking for MPFR1001188
-Node: POSIX Floating Point Problems1002662
-Ref: POSIX Floating Point Problems-Footnote-11006947
-Node: Floating point summary1006985
-Node: Dynamic Extensions1009175
-Node: Extension Intro1010728
-Node: Plugin License1011994
-Node: Extension Mechanism Outline1012791
-Ref: figure-load-extension1013230
-Ref: figure-register-new-function1014795
-Ref: figure-call-new-function1015887
-Node: Extension API Description1017949
-Node: Extension API Functions Introduction1019662
-Ref: table-api-std-headers1021498
-Node: General Data Types1025747
-Ref: General Data Types-Footnote-11034377
-Node: Memory Allocation Functions1034676
-Ref: Memory Allocation Functions-Footnote-11039177
-Node: Constructor Functions1039276
-Node: API Ownership of MPFR and GMP Values1042742
-Node: Registration Functions1044055
-Node: Extension Functions1044755
-Node: Exit Callback Functions1050077
-Node: Extension Version String1051327
-Node: Input Parsers1051990
-Node: Output Wrappers1064711
-Node: Two-way processors1069223
-Node: Printing Messages1071488
-Ref: Printing Messages-Footnote-11072659
-Node: Updating ERRNO1072812
-Node: Requesting Values1073551
-Ref: table-value-types-returned1074288
-Node: Accessing Parameters1075224
-Node: Symbol Table Access1076461
-Node: Symbol table by name1076973
-Ref: Symbol table by name-Footnote-11079997
-Node: Symbol table by cookie1080125
-Ref: Symbol table by cookie-Footnote-11084310
-Node: Cached values1084374
-Ref: Cached values-Footnote-11087910
-Node: Array Manipulation1088063
-Ref: Array Manipulation-Footnote-11089154
-Node: Array Data Types1089191
-Ref: Array Data Types-Footnote-11091849
-Node: Array Functions1091941
-Node: Flattening Arrays1096439
-Node: Creating Arrays1103415
-Node: Redirection API1108182
-Node: Extension API Variables1111015
-Node: Extension Versioning1111726
-Ref: gawk-api-version1112155
-Node: Extension GMP/MPFR Versioning1113886
-Node: Extension API Informational Variables1115514
-Node: Extension API Boilerplate1116587
-Node: Changes from API V11120561
-Node: Finding Extensions1122133
-Node: Extension Example1122692
-Node: Internal File Description1123490
-Node: Internal File Ops1127570
-Ref: Internal File Ops-Footnote-11138920
-Node: Using Internal File Ops1139060
-Ref: Using Internal File Ops-Footnote-11141443
-Node: Extension Samples1141717
-Node: Extension Sample File Functions1143246
-Node: Extension Sample Fnmatch1150895
-Node: Extension Sample Fork1152382
-Node: Extension Sample Inplace1153600
-Node: Extension Sample Ord1157226
-Node: Extension Sample Readdir1158062
-Ref: table-readdir-file-types1158951
-Node: Extension Sample Revout1160018
-Node: Extension Sample Rev2way1160607
-Node: Extension Sample Read write array1161347
-Node: Extension Sample Readfile1163289
-Node: Extension Sample Time1164384
-Node: Extension Sample API Tests1166136
-Node: gawkextlib1166628
-Node: Extension summary1169546
-Node: Extension Exercises1173248
-Node: Language History1174490
-Node: V7/SVR3.11176146
-Node: SVR41178298
-Node: POSIX1179732
-Node: BTL1181113
-Node: POSIX/GNU1181842
-Node: Feature History1187620
-Node: Common Extensions1203939
-Node: Ranges and Locales1205222
-Ref: Ranges and Locales-Footnote-11209838
-Ref: Ranges and Locales-Footnote-21209865
-Ref: Ranges and Locales-Footnote-31210100
-Node: Contributors1210323
-Node: History summary1216320
-Node: Installation1217700
-Node: Gawk Distribution1218644
-Node: Getting1219128
-Node: Extracting1220091
-Node: Distribution contents1221729
-Node: Unix Installation1228209
-Node: Quick Installation1228891
-Node: Shell Startup Files1231305
-Node: Additional Configuration Options1232394
-Node: Configuration Philosophy1234709
-Node: Non-Unix Installation1237078
-Node: PC Installation1237538
-Node: PC Binary Installation1238376
-Node: PC Compiling1238811
-Node: PC Using1239928
-Node: Cygwin1243481
-Node: MSYS1244705
-Node: VMS Installation1245307
-Node: VMS Compilation1246098
-Ref: VMS Compilation-Footnote-11247327
-Node: VMS Dynamic Extensions1247385
-Node: VMS Installation Details1249070
-Node: VMS Running1251323
-Node: VMS GNV1255602
-Node: VMS Old Gawk1256337
-Node: Bugs1256808
-Node: Bug address1257471
-Node: Usenet1260453
-Node: Maintainers1261457
-Node: Other Versions1262642
-Node: Installation summary1269730
-Node: Notes1270939
-Node: Compatibility Mode1271733
-Node: Additions1272515
-Node: Accessing The Source1273440
-Node: Adding Code1274877
-Node: New Ports1281096
-Node: Derived Files1285471
-Ref: Derived Files-Footnote-11291131
-Ref: Derived Files-Footnote-21291166
-Ref: Derived Files-Footnote-31291764
-Node: Future Extensions1291878
-Node: Implementation Limitations1292536
-Node: Extension Design1293746
-Node: Old Extension Problems1294890
-Ref: Old Extension Problems-Footnote-11296408
-Node: Extension New Mechanism Goals1296465
-Ref: Extension New Mechanism Goals-Footnote-11299829
-Node: Extension Other Design Decisions1300018
-Node: Extension Future Growth1302131
-Node: Notes summary1302737
-Node: Basic Concepts1303895
-Node: Basic High Level1304576
-Ref: figure-general-flow1304858
-Ref: figure-process-flow1305543
-Ref: Basic High Level-Footnote-11308844
-Node: Basic Data Typing1309029
-Node: Glossary1312357
-Node: Copying1344242
-Node: GNU Free Documentation License1381785
-Node: Index1406905
+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 Program739909
+Node: Id Program748920
+Node: Split Program758867
+Ref: Split Program-Footnote-1768757
+Node: Tee Program768930
+Node: Uniq Program771720
+Node: Wc Program779308
+Node: Bytes vs. Characters779705
+Node: Using extensions781253
+Node: wc program782007
+Node: Miscellaneous Programs786872
+Node: Dupword Program788085
+Node: Alarm Program790115
+Node: Translate Program794970
+Ref: Translate Program-Footnote-1799535
+Node: Labels Program799805
+Ref: Labels Program-Footnote-1803156
+Node: Word Sorting803240
+Node: History Sorting807312
+Node: Extract Program809537
+Node: Simple Sed817591
+Node: Igawk Program820665
+Ref: Igawk Program-Footnote-1834996
+Ref: Igawk Program-Footnote-2835198
+Ref: Igawk Program-Footnote-3835320
+Node: Anagram Program835435
+Node: Signature Program838497
+Node: Programs Summary839744
+Node: Programs Exercises840958
+Ref: Programs Exercises-Footnote-1845088
+Node: Advanced Features845174
+Node: Nondecimal Data847164
+Node: Array Sorting848755
+Node: Controlling Array Traversal849455
+Ref: Controlling Array Traversal-Footnote-1857823
+Node: Array Sorting Functions857941
+Ref: Array Sorting Functions-Footnote-1863032
+Node: Two-way I/O863228
+Ref: Two-way I/O-Footnote-1870949
+Ref: Two-way I/O-Footnote-2871136
+Node: TCP/IP Networking871218
+Node: Profiling874336
+Node: Advanced Features Summary883650
+Node: Internationalization885494
+Node: I18N and L10N886974
+Node: Explaining gettext887661
+Ref: Explaining gettext-Footnote-1893553
+Ref: Explaining gettext-Footnote-2893738
+Node: Programmer i18n893903
+Ref: Programmer i18n-Footnote-1898852
+Node: Translator i18n898901
+Node: String Extraction899695
+Ref: String Extraction-Footnote-1900827
+Node: Printf Ordering900913
+Ref: Printf Ordering-Footnote-1903699
+Node: I18N Portability903763
+Ref: I18N Portability-Footnote-1906219
+Node: I18N Example906282
+Ref: I18N Example-Footnote-1909557
+Ref: I18N Example-Footnote-2909630
+Node: Gawk I18N909739
+Node: I18N Summary910388
+Node: Debugger911729
+Node: Debugging912729
+Node: Debugging Concepts913170
+Node: Debugging Terms914979
+Node: Awk Debugging917554
+Ref: Awk Debugging-Footnote-1918499
+Node: Sample Debugging Session918631
+Node: Debugger Invocation919165
+Node: Finding The Bug920551
+Node: List of Debugger Commands927025
+Node: Breakpoint Control928358
+Node: Debugger Execution Control932052
+Node: Viewing And Changing Data935414
+Node: Execution Stack938955
+Node: Debugger Info940592
+Node: Miscellaneous Debugger Commands944663
+Node: Readline Support949725
+Node: Limitations950621
+Node: Debugging Summary953175
+Node: Namespaces954454
+Node: Global Namespace955565
+Node: Qualified Names956963
+Node: Default Namespace957962
+Node: Changing The Namespace958703
+Node: Naming Rules960317
+Node: Internal Name Management962165
+Node: Namespace Example963207
+Node: Namespace And Features965769
+Node: Namespace Summary967204
+Node: Arbitrary Precision Arithmetic968681
+Node: Computer Arithmetic970168
+Ref: table-numeric-ranges973934
+Ref: table-floating-point-ranges974427
+Ref: Computer Arithmetic-Footnote-1975085
+Node: Math Definitions975142
+Ref: table-ieee-formats978118
+Node: MPFR features978685
+Node: FP Math Caution980403
+Ref: FP Math Caution-Footnote-1981475
+Node: Inexactness of computations981844
+Node: Inexact representation982875
+Node: Comparing FP Values984235
+Node: Errors accumulate985476
+Node: Strange values986932
+Ref: Strange values-Footnote-1989520
+Node: Getting Accuracy989625
+Node: Try To Round992335
+Node: Setting precision993234
+Ref: table-predefined-precision-strings993931
+Node: Setting the rounding mode995761
+Ref: table-gawk-rounding-modes996135
+Ref: Setting the rounding mode-Footnote-11000066
+Node: Arbitrary Precision Integers1000245
+Ref: Arbitrary Precision Integers-Footnote-11003420
+Node: Checking for MPFR1003569
+Node: POSIX Floating Point Problems1005043
+Ref: POSIX Floating Point Problems-Footnote-11009328
+Node: Floating point summary1009366
+Node: Dynamic Extensions1011556
+Node: Extension Intro1013109
+Node: Plugin License1014375
+Node: Extension Mechanism Outline1015172
+Ref: figure-load-extension1015611
+Ref: figure-register-new-function1017176
+Ref: figure-call-new-function1018268
+Node: Extension API Description1020330
+Node: Extension API Functions Introduction1022043
+Ref: table-api-std-headers1023879
+Node: General Data Types1028128
+Ref: General Data Types-Footnote-11036758
+Node: Memory Allocation Functions1037057
+Ref: Memory Allocation Functions-Footnote-11041558
+Node: Constructor Functions1041657
+Node: API Ownership of MPFR and GMP Values1045123
+Node: Registration Functions1046436
+Node: Extension Functions1047136
+Node: Exit Callback Functions1052458
+Node: Extension Version String1053708
+Node: Input Parsers1054371
+Node: Output Wrappers1067092
+Node: Two-way processors1071604
+Node: Printing Messages1073869
+Ref: Printing Messages-Footnote-11075040
+Node: Updating ERRNO1075193
+Node: Requesting Values1075932
+Ref: table-value-types-returned1076669
+Node: Accessing Parameters1077605
+Node: Symbol Table Access1078842
+Node: Symbol table by name1079354
+Ref: Symbol table by name-Footnote-11082378
+Node: Symbol table by cookie1082506
+Ref: Symbol table by cookie-Footnote-11086691
+Node: Cached values1086755
+Ref: Cached values-Footnote-11090291
+Node: Array Manipulation1090444
+Ref: Array Manipulation-Footnote-11091535
+Node: Array Data Types1091572
+Ref: Array Data Types-Footnote-11094230
+Node: Array Functions1094322
+Node: Flattening Arrays1098820
+Node: Creating Arrays1105796
+Node: Redirection API1110563
+Node: Extension API Variables1113396
+Node: Extension Versioning1114107
+Ref: gawk-api-version1114536
+Node: Extension GMP/MPFR Versioning1116267
+Node: Extension API Informational Variables1117895
+Node: Extension API Boilerplate1118968
+Node: Changes from API V11122942
+Node: Finding Extensions1124514
+Node: Extension Example1125073
+Node: Internal File Description1125871
+Node: Internal File Ops1129951
+Ref: Internal File Ops-Footnote-11141301
+Node: Using Internal File Ops1141441
+Ref: Using Internal File Ops-Footnote-11143824
+Node: Extension Samples1144098
+Node: Extension Sample File Functions1145627
+Node: Extension Sample Fnmatch1153276
+Node: Extension Sample Fork1154763
+Node: Extension Sample Inplace1155981
+Node: Extension Sample Ord1159607
+Node: Extension Sample Readdir1160443
+Ref: table-readdir-file-types1161332
+Node: Extension Sample Revout1162399
+Node: Extension Sample Rev2way1162988
+Node: Extension Sample Read write array1163728
+Node: Extension Sample Readfile1165670
+Node: Extension Sample Time1166765
+Node: Extension Sample API Tests1168517
+Node: gawkextlib1169009
+Node: Extension summary1171927
+Node: Extension Exercises1175629
+Node: Language History1176871
+Node: V7/SVR3.11178527
+Node: SVR41180679
+Node: POSIX1182113
+Node: BTL1183494
+Node: POSIX/GNU1184223
+Node: Feature History1190001
+Node: Common Extensions1206320
+Node: Ranges and Locales1207603
+Ref: Ranges and Locales-Footnote-11212219
+Ref: Ranges and Locales-Footnote-21212246
+Ref: Ranges and Locales-Footnote-31212481
+Node: Contributors1212704
+Node: History summary1218701
+Node: Installation1220081
+Node: Gawk Distribution1221025
+Node: Getting1221509
+Node: Extracting1222472
+Node: Distribution contents1224110
+Node: Unix Installation1230590
+Node: Quick Installation1231272
+Node: Shell Startup Files1233686
+Node: Additional Configuration Options1234775
+Node: Configuration Philosophy1237090
+Node: Non-Unix Installation1239459
+Node: PC Installation1239919
+Node: PC Binary Installation1240757
+Node: PC Compiling1241192
+Node: PC Using1242309
+Node: Cygwin1245862
+Node: MSYS1247086
+Node: VMS Installation1247688
+Node: VMS Compilation1248479
+Ref: VMS Compilation-Footnote-11249708
+Node: VMS Dynamic Extensions1249766
+Node: VMS Installation Details1251451
+Node: VMS Running1253704
+Node: VMS GNV1257983
+Node: VMS Old Gawk1258718
+Node: Bugs1259189
+Node: Bug address1259852
+Node: Usenet1262834
+Node: Maintainers1263838
+Node: Other Versions1265023
+Node: Installation summary1272111
+Node: Notes1273320
+Node: Compatibility Mode1274114
+Node: Additions1274896
+Node: Accessing The Source1275821
+Node: Adding Code1277258
+Node: New Ports1283477
+Node: Derived Files1287852
+Ref: Derived Files-Footnote-11293512
+Ref: Derived Files-Footnote-21293547
+Ref: Derived Files-Footnote-31294145
+Node: Future Extensions1294259
+Node: Implementation Limitations1294917
+Node: Extension Design1296127
+Node: Old Extension Problems1297271
+Ref: Old Extension Problems-Footnote-11298789
+Node: Extension New Mechanism Goals1298846
+Ref: Extension New Mechanism Goals-Footnote-11302210
+Node: Extension Other Design Decisions1302399
+Node: Extension Future Growth1304512
+Node: Notes summary1305118
+Node: Basic Concepts1306276
+Node: Basic High Level1306957
+Ref: figure-general-flow1307239
+Ref: figure-process-flow1307924
+Ref: Basic High Level-Footnote-11311225
+Node: Basic Data Typing1311410
+Node: Glossary1314738
+Node: Copying1346623
+Node: GNU Free Documentation License1384166
+Node: Index1409286

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