diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | awk.h | 9 | ||||
-rw-r--r-- | awklib/eg/test-programs/gen-float-table.awk | 59 | ||||
-rw-r--r-- | awklib/eg/test-programs/gen-float-table.c | 60 | ||||
-rw-r--r-- | awklib/eg/test-programs/gen-float-table.py | 42 | ||||
-rw-r--r-- | builtin.c | 4 | ||||
-rw-r--r-- | doc/ChangeLog | 21 | ||||
-rw-r--r-- | doc/gawk.info | 1282 | ||||
-rw-r--r-- | doc/gawk.texi | 267 | ||||
-rw-r--r-- | doc/gawktexi.in | 273 | ||||
-rw-r--r-- | doc/wordlist | 2 | ||||
-rw-r--r-- | eval.c | 96 | ||||
-rw-r--r-- | interpret.h | 12 | ||||
-rw-r--r-- | mpfr.c | 44 | ||||
-rw-r--r-- | node.c | 5 |
16 files changed, 1513 insertions, 684 deletions
@@ -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. @@ -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 --------------------------- @@ -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("") @@ -4293,11 +4293,11 @@ format_nan_inf(NODE *n, char format) return NULL; else if (is_mpg_float(n)) { if (mpfr_nan_p(n->mpg_numbr)) { - strcpy(buf, mpfr_sgn(n->mpg_numbr) < 0 ? "-nan" : "+nan"); + strcpy(buf, mpfr_signbit(n->mpg_numbr) ? "-nan" : "+nan"); goto fmt; } else if (mpfr_inf_p(n->mpg_numbr)) { - strcpy(buf, mpfr_sgn(n->mpg_numbr) < 0 ? "-inf" : "+inf"); + strcpy(buf, mpfr_signbit(n->mpg_numbr) ? "-inf" : "+inf"); goto fmt; } else diff --git a/doc/ChangeLog b/doc/ChangeLog index 6dad4af7..8d00228d 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -3,6 +3,27 @@ * gawktexi.in (Nextfile Statement): Clarify what happens in a BEGINFILE rule. +2020-11-15 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Strange values): Add test programs inside + @ignore; extracted to example directory. + +2020-11-09 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in: Samll improvement in strange numbers section. + +2020-11-04 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Strange values): New section on NaN and infinity. + Update some other bits to point to it. + * wordlist: Updated with more words. + +2020-11-16 Arnold D. Robbins <arnold@skeeve.com> + + * gawktexi.in (Nextfile Statement): Clarify what happens in + a BEGINFILE rule. +>>>>>>> master + 2020-10-31 Arnold D. Robbins <arnold@skeeve.com> * texinfo.tex: Updated from GNULIB. diff --git a/doc/gawk.info b/doc/gawk.info index 909cf29e..ebae71b7 100644 --- a/doc/gawk.info +++ b/doc/gawk.info @@ -546,6 +546,7 @@ in (a) below. A copy of the license is included in the section entitled * Inexact representation:: Numbers are not exactly represented. * Comparing FP Values:: How to compare floating point values. * Errors accumulate:: Errors get bigger as they go. +* Strange values:: A few words about infinities and NaNs. * Getting Accuracy:: Getting more accuracy takes some work. * Try To Round:: Add digits and round. * Setting precision:: How to set the precision. @@ -6926,8 +6927,8 @@ width. Here is a list of the format-control letters: On systems supporting IEEE 754 floating-point format, values representing negative infinity are formatted as '-inf' or '-infinity', and positive infinity as 'inf' or 'infinity'. The - special "not a number" value formats as '-nan' or 'nan' (*note Math - Definitions::). + special "not a number" value formats as '-nan' or 'nan' (*note + Strange values::). '%F' Like '%f', but the infinity and "not a number" values are spelled @@ -12819,7 +12820,7 @@ brackets ([ ]): 'log(X)' Return the natural logarithm of X, if X is positive; otherwise, - return 'NaN' ("not a number") on IEEE 754 systems. Additionally, + return NaN ("not a number") on IEEE 754 systems. Additionally, 'gawk' prints a warning message when 'x' is negative. 'rand()' @@ -24153,18 +24154,10 @@ material here: another number and infinity produce infinity. "NaN" - "Not a number."(1) A special value that results from attempting a - calculation that has no answer as a real number. In such a case, - programs can either receive a floating-point exception, or get - 'NaN' back as the result. The IEEE 754 standard recommends that - systems return 'NaN'. Some examples: - - 'sqrt(-1)' - This makes sense in the range of complex numbers, but not in - the range of real numbers, so the result is 'NaN'. - - 'log(-8)' - -8 is out of the domain of 'log()', so the result is 'NaN'. + "Not a number." A special value that results from attempting a + calculation that has no answer as a real number. *Note Strange + values::, for more information about infinity and not-a-number + values. "Normalized" How the significand (see later in this list) is usually stored. @@ -24223,11 +24216,6 @@ Table 16.3: Basic IEEE format values NOTE: The precision numbers include the implied leading one that gives them one extra bit of significand. - ---------- Footnotes ---------- - - (1) Thanks to Michael Brennan for this description, which we have -paraphrased, and for the examples. - File: gawk.info, Node: MPFR features, Next: FP Math Caution, Prev: Math Definitions, Up: Arbitrary Precision Arithmetic @@ -24320,6 +24308,7 @@ be sure of the number of significant decimal places in the final result. * Inexact representation:: Numbers are not exactly represented. * Comparing FP Values:: How to compare floating point values. * Errors accumulate:: Errors get bigger as they go. +* Strange values:: A few words about infinities and NaNs. File: gawk.info, Node: Inexact representation, Next: Comparing FP Values, Up: Inexactness of computations @@ -24384,7 +24373,7 @@ values with a delta, you should be sure to use 'difference < abs(delta)' in case someone passes in a negative delta value. -File: gawk.info, Node: Errors accumulate, Prev: Comparing FP Values, Up: Inexactness of computations +File: gawk.info, Node: Errors accumulate, Next: Strange values, Prev: Comparing FP Values, Up: Inexactness of computations 16.4.1.3 Errors Accumulate .......................... @@ -24432,6 +24421,64 @@ representations yield an unexpected result: -| 4 +File: gawk.info, Node: Strange values, Prev: Errors accumulate, Up: Inexactness of computations + +16.4.1.4 Floating Point Values They Didn't Talk About In School +............................................................... + +Both IEEE 754 floating-point hardware, and MPFR, support two kinds of +values that you probably didn't learn about in school. The first is +"infinity", a special value, that can be either negative or positive, +and which is either smaller than any other value (negative infinity), or +larger than any other value (positive infinity). When such values are +generated, 'gawk' prints them as either '-inf' or '+inf', respectively. +It accepts those strings as data input and converts them to the proper +floating-point values internally. + + Infinity values of the same sign compare as equal to each other. +Otherwise, operations (addition, subtraction, etc.) involving another +number and infinity produce infinity. + + The second kind of value is "not a number", or NaN for short.(1) +This is a special value that results from attempting a calculation that +has no answer as a real number. In such a case, programs can either +receive a floating-point exception, or get NaN back as the result. The +IEEE 754 standard recommends that systems return NaN. Some examples: + +'sqrt(-1)' + This makes sense in the range of complex numbers, but not in the + range of real numbers, so the result is NaN. + +'log(-8)' + -8 is out of the domain of 'log()', so the result is NaN. + + NaN values are strange. In particular, they cannot be compared with +other floating point values; any such comparison, except for "is not +equal to", returns false. NaN values are so much unequal to other +values that even comparing two identical NaN values with '!=' returns +true! + + NaN values can also be signed, although it depends upon the +implementation as to which sign you get for any operation that returns a +NaN. For example, on some systems, 'sqrt(-1)' returns a negative NaN. On +others, it returns a positive NaN. + + When such values are generated, 'gawk' prints them as either '-nan' +or '+nan', respectively. Here too, 'gawk' accepts those strings as data +input and converts them to the proper floating-point values internally. + + If you want to dive more deeply into this topic, you can find test +programs in C, 'awk' and Python in the directory +'awklib/eg/test-programs' in the 'gawk' distribution. These programs +enable comparison among programming languages as to how they hanle NaN +and infinity values. + + ---------- Footnotes ---------- + + (1) Thanks to Michael Brennan for this description, which we have +paraphrased, and for the examples. + + File: gawk.info, Node: Getting Accuracy, Next: Try To Round, Prev: Inexactness of computations, Up: FP Math Caution 16.4.2 Getting the Accuracy You Need @@ -37934,602 +37981,603 @@ Index Tag Table: Node: Top1200 -Node: Foreword344474 -Node: Foreword448916 -Node: Preface50448 -Ref: Preface-Footnote-153307 -Ref: Preface-Footnote-253416 -Ref: Preface-Footnote-353650 -Node: History53792 -Node: Names56144 -Ref: Names-Footnote-157248 -Node: This Manual57395 -Ref: This Manual-Footnote-164034 -Node: Conventions64134 -Node: Manual History66503 -Ref: Manual History-Footnote-169500 -Ref: Manual History-Footnote-269541 -Node: How To Contribute69615 -Node: Acknowledgments70541 -Node: Getting Started75478 -Node: Running gawk77917 -Node: One-shot79107 -Node: Read Terminal80370 -Node: Long82363 -Node: Executable Scripts83876 -Ref: Executable Scripts-Footnote-186509 -Node: Comments86612 -Node: Quoting89096 -Node: DOS Quoting94622 -Node: Sample Data Files96678 -Node: Very Simple99273 -Node: Two Rules105375 -Node: More Complex107260 -Node: Statements/Lines109592 -Ref: Statements/Lines-Footnote-1114076 -Node: Other Features114341 -Node: When115277 -Ref: When-Footnote-1117031 -Node: Intro Summary117096 -Node: Invoking Gawk117980 -Node: Command Line119494 -Node: Options120292 -Ref: Options-Footnote-1138206 -Ref: Options-Footnote-2138437 -Node: Other Arguments138462 -Node: Naming Standard Input142473 -Node: Environment Variables143683 -Node: AWKPATH Variable144241 -Ref: AWKPATH Variable-Footnote-1147653 -Ref: AWKPATH Variable-Footnote-2147687 -Node: AWKLIBPATH Variable148058 -Ref: AWKLIBPATH Variable-Footnote-1149755 -Node: Other Environment Variables150130 -Node: Exit Status153951 -Node: Include Files154628 -Node: Loading Shared Libraries158318 -Node: Obsolete159746 -Node: Undocumented160438 -Node: Invoking Summary160735 -Node: Regexp163576 -Node: Regexp Usage165030 -Node: Escape Sequences167067 -Node: Regexp Operators173308 -Node: Regexp Operator Details173793 -Ref: Regexp Operator Details-Footnote-1180225 -Node: Interval Expressions180372 -Ref: Interval Expressions-Footnote-1181793 -Node: Bracket Expressions181891 -Ref: table-char-classes184367 -Node: Leftmost Longest187693 -Node: Computed Regexps188996 -Node: GNU Regexp Operators192423 -Node: Case-sensitivity196160 -Ref: Case-sensitivity-Footnote-1199026 -Ref: Case-sensitivity-Footnote-2199261 -Node: Regexp Summary199369 -Node: Reading Files200835 -Node: Records203104 -Node: awk split records204179 -Node: gawk split records209454 -Ref: gawk split records-Footnote-1214187 -Node: Fields214224 -Node: Nonconstant Fields216965 -Ref: Nonconstant Fields-Footnote-1219201 -Node: Changing Fields219405 -Node: Field Separators225436 -Node: Default Field Splitting228134 -Node: Regexp Field Splitting229252 -Node: Single Character Fields232605 -Node: Command Line Field Separator233665 -Node: Full Line Fields236883 -Ref: Full Line Fields-Footnote-1238405 -Ref: Full Line Fields-Footnote-2238451 -Node: Field Splitting Summary238552 -Node: Constant Size240626 -Node: Fixed width data241358 -Node: Skipping intervening244825 -Node: Allowing trailing data245623 -Node: Fields with fixed data246660 -Node: Splitting By Content248178 -Ref: Splitting By Content-Footnote-1251961 -Node: More CSV252124 -Node: Testing field creation253434 -Node: Multiple Line255059 -Node: Getline261336 -Node: Plain Getline263805 -Node: Getline/Variable266378 -Node: Getline/File267529 -Node: Getline/Variable/File268917 -Ref: Getline/Variable/File-Footnote-1270522 -Node: Getline/Pipe270610 -Node: Getline/Variable/Pipe273314 -Node: Getline/Coprocess274449 -Node: Getline/Variable/Coprocess275716 -Node: Getline Notes276458 -Node: Getline Summary279255 -Ref: table-getline-variants279679 -Node: Read Timeout280427 -Ref: Read Timeout-Footnote-1284333 -Node: Retrying Input284391 -Node: Command-line directories285590 -Node: Input Summary286496 -Node: Input Exercises289668 -Node: Printing290102 -Node: Print291936 -Node: Print Examples293393 -Node: Output Separators296173 -Node: OFMT298190 -Node: Printf299546 -Node: Basic Printf300331 -Node: Control Letters301905 -Node: Format Modifiers307069 -Node: Printf Examples313084 -Node: Redirection315570 -Node: Special FD322411 -Ref: Special FD-Footnote-1325579 -Node: Special Files325653 -Node: Other Inherited Files326270 -Node: Special Network327271 -Node: Special Caveats328131 -Node: Close Files And Pipes329080 -Ref: table-close-pipe-return-values335987 -Ref: Close Files And Pipes-Footnote-1336800 -Ref: Close Files And Pipes-Footnote-2336948 -Node: Nonfatal337100 -Node: Output Summary339438 -Node: Output Exercises340660 -Node: Expressions341339 -Node: Values342527 -Node: Constants343205 -Node: Scalar Constants343896 -Ref: Scalar Constants-Footnote-1346406 -Node: Nondecimal-numbers346656 -Node: Regexp Constants349657 -Node: Using Constant Regexps350183 -Node: Standard Regexp Constants350805 -Node: Strong Regexp Constants353993 -Node: Variables357005 -Node: Using Variables357662 -Node: Assignment Options359572 -Node: Conversion362043 -Node: Strings And Numbers362567 -Ref: Strings And Numbers-Footnote-1365630 -Node: Locale influences conversions365739 -Ref: table-locale-affects368497 -Node: All Operators369115 -Node: Arithmetic Ops369744 -Node: Concatenation372460 -Ref: Concatenation-Footnote-1375307 -Node: Assignment Ops375414 -Ref: table-assign-ops380405 -Node: Increment Ops381718 -Node: Truth Values and Conditions385178 -Node: Truth Values386252 -Node: Typing and Comparison387300 -Node: Variable Typing388120 -Ref: Variable Typing-Footnote-1394583 -Ref: Variable Typing-Footnote-2394655 -Node: Comparison Operators394732 -Ref: table-relational-ops395151 -Node: POSIX String Comparison398646 -Ref: POSIX String Comparison-Footnote-1400341 -Ref: POSIX String Comparison-Footnote-2400480 -Node: Boolean Ops400564 -Ref: Boolean Ops-Footnote-1405046 -Node: Conditional Exp405138 -Node: Function Calls406874 -Node: Precedence410751 -Node: Locales414410 -Node: Expressions Summary416042 -Node: Patterns and Actions418615 -Node: Pattern Overview419735 -Node: Regexp Patterns421412 -Node: Expression Patterns421954 -Node: Ranges425735 -Node: BEGIN/END428843 -Node: Using BEGIN/END429604 -Ref: Using BEGIN/END-Footnote-1432358 -Node: I/O And BEGIN/END432464 -Node: BEGINFILE/ENDFILE434777 -Node: Empty438008 -Node: Using Shell Variables438325 -Node: Action Overview440599 -Node: Statements442924 -Node: If Statement444772 -Node: While Statement446267 -Node: Do Statement448295 -Node: For Statement449443 -Node: Switch Statement452614 -Node: Break Statement455055 -Node: Continue Statement457147 -Node: Next Statement458974 -Node: Nextfile Statement461357 -Node: Exit Statement463995 -Node: Built-in Variables466398 -Node: User-modified467531 -Node: Auto-set475298 -Ref: Auto-set-Footnote-1492105 -Ref: Auto-set-Footnote-2492311 -Node: ARGC and ARGV492367 -Node: Pattern Action Summary496580 -Node: Arrays499010 -Node: Array Basics500339 -Node: Array Intro501183 -Ref: figure-array-elements503158 -Ref: Array Intro-Footnote-1505862 -Node: Reference to Elements505990 -Node: Assigning Elements508454 -Node: Array Example508945 -Node: Scanning an Array510704 -Node: Controlling Scanning513726 -Ref: Controlling Scanning-Footnote-1520182 -Node: Numeric Array Subscripts520498 -Node: Uninitialized Subscripts522682 -Node: Delete524301 -Ref: Delete-Footnote-1527053 -Node: Multidimensional527110 -Node: Multiscanning530205 -Node: Arrays of Arrays531796 -Node: Arrays Summary536564 -Node: Functions538657 -Node: Built-in539695 -Node: Calling Built-in540776 -Node: Numeric Functions542772 -Ref: Numeric Functions-Footnote-1546800 -Ref: Numeric Functions-Footnote-2547448 -Ref: Numeric Functions-Footnote-3547496 -Node: String Functions547768 -Ref: String Functions-Footnote-1571909 -Ref: String Functions-Footnote-2572037 -Ref: String Functions-Footnote-3572285 -Node: Gory Details572372 -Ref: table-sub-escapes574163 -Ref: table-sub-proposed575682 -Ref: table-posix-sub577045 -Ref: table-gensub-escapes578586 -Ref: Gory Details-Footnote-1579409 -Node: I/O Functions579563 -Ref: table-system-return-values586017 -Ref: I/O Functions-Footnote-1588097 -Ref: I/O Functions-Footnote-2588245 -Node: Time Functions588365 -Ref: Time Functions-Footnote-1599036 -Ref: Time Functions-Footnote-2599104 -Ref: Time Functions-Footnote-3599262 -Ref: Time Functions-Footnote-4599373 -Ref: Time Functions-Footnote-5599485 -Ref: Time Functions-Footnote-6599712 -Node: Bitwise Functions599978 -Ref: table-bitwise-ops600572 -Ref: Bitwise Functions-Footnote-1606635 -Ref: Bitwise Functions-Footnote-2606808 -Node: Type Functions606999 -Node: I18N Functions609862 -Node: User-defined611513 -Node: Definition Syntax612325 -Ref: Definition Syntax-Footnote-1618019 -Node: Function Example618090 -Ref: Function Example-Footnote-1621012 -Node: Function Calling621034 -Node: Calling A Function621622 -Node: Variable Scope622580 -Node: Pass By Value/Reference625574 -Node: Function Caveats628218 -Ref: Function Caveats-Footnote-1630265 -Node: Return Statement630385 -Node: Dynamic Typing633364 -Node: Indirect Calls634294 -Ref: Indirect Calls-Footnote-1644546 -Node: Functions Summary644674 -Node: Library Functions647379 -Ref: Library Functions-Footnote-1650986 -Ref: Library Functions-Footnote-2651129 -Node: Library Names651300 -Ref: Library Names-Footnote-1654967 -Ref: Library Names-Footnote-2655190 -Node: General Functions655276 -Node: Strtonum Function656379 -Node: Assert Function659401 -Node: Round Function662727 -Node: Cliff Random Function664267 -Node: Ordinal Functions665283 -Ref: Ordinal Functions-Footnote-1668346 -Ref: Ordinal Functions-Footnote-2668598 -Node: Join Function668808 -Ref: Join Function-Footnote-1670578 -Node: Getlocaltime Function670778 -Node: Readfile Function674520 -Node: Shell Quoting676497 -Node: Data File Management677898 -Node: Filetrans Function678530 -Node: Rewind Function682626 -Node: File Checking684535 -Ref: File Checking-Footnote-1685869 -Node: Empty Files686070 -Node: Ignoring Assigns688049 -Node: Getopt Function689599 -Ref: Getopt Function-Footnote-1704810 -Node: Passwd Functions705010 -Ref: Passwd Functions-Footnote-1713849 -Node: Group Functions713937 -Ref: Group Functions-Footnote-1721835 -Node: Walking Arrays722042 -Node: Library Functions Summary725050 -Node: Library Exercises726456 -Node: Sample Programs726921 -Node: Running Examples727691 -Node: Clones728419 -Node: Cut Program729643 -Node: Egrep Program739572 -Node: Id Program748583 -Node: Split Program758530 -Ref: Split Program-Footnote-1768304 -Node: Tee Program768477 -Node: Uniq Program771267 -Node: Wc Program778831 -Node: Bytes vs. Characters779228 -Node: Using extensions780776 -Node: wc program781534 -Node: Miscellaneous Programs786399 -Node: Dupword Program787612 -Node: Alarm Program789642 -Node: Translate Program794497 -Ref: Translate Program-Footnote-1799062 -Node: Labels Program799332 -Ref: Labels Program-Footnote-1802683 -Node: Word Sorting802767 -Node: History Sorting806839 -Node: Extract Program809064 -Node: Simple Sed817118 -Node: Igawk Program820192 -Ref: Igawk Program-Footnote-1834523 -Ref: Igawk Program-Footnote-2834725 -Ref: Igawk Program-Footnote-3834847 -Node: Anagram Program834962 -Node: Signature Program838024 -Node: Programs Summary839271 -Node: Programs Exercises840485 -Ref: Programs Exercises-Footnote-1844615 -Node: Advanced Features844701 -Node: Nondecimal Data846691 -Node: Array Sorting848282 -Node: Controlling Array Traversal848982 -Ref: Controlling Array Traversal-Footnote-1857350 -Node: Array Sorting Functions857468 -Ref: Array Sorting Functions-Footnote-1862559 -Node: Two-way I/O862755 -Ref: Two-way I/O-Footnote-1870476 -Ref: Two-way I/O-Footnote-2870663 -Node: TCP/IP Networking870745 -Node: Profiling873863 -Node: Advanced Features Summary883177 -Node: Internationalization885021 -Node: I18N and L10N886501 -Node: Explaining gettext887188 -Ref: Explaining gettext-Footnote-1893080 -Ref: Explaining gettext-Footnote-2893265 -Node: Programmer i18n893430 -Ref: Programmer i18n-Footnote-1898379 -Node: Translator i18n898428 -Node: String Extraction899222 -Ref: String Extraction-Footnote-1900354 -Node: Printf Ordering900440 -Ref: Printf Ordering-Footnote-1903226 -Node: I18N Portability903290 -Ref: I18N Portability-Footnote-1905746 -Node: I18N Example905809 -Ref: I18N Example-Footnote-1909084 -Ref: I18N Example-Footnote-2909157 -Node: Gawk I18N909266 -Node: I18N Summary909915 -Node: Debugger911256 -Node: Debugging912256 -Node: Debugging Concepts912697 -Node: Debugging Terms914506 -Node: Awk Debugging917081 -Ref: Awk Debugging-Footnote-1918026 -Node: Sample Debugging Session918158 -Node: Debugger Invocation918692 -Node: Finding The Bug920078 -Node: List of Debugger Commands926552 -Node: Breakpoint Control927885 -Node: Debugger Execution Control931579 -Node: Viewing And Changing Data934941 -Node: Execution Stack938482 -Node: Debugger Info940119 -Node: Miscellaneous Debugger Commands944190 -Node: Readline Support949252 -Node: Limitations950148 -Node: Debugging Summary952702 -Node: Namespaces953981 -Node: Global Namespace955092 -Node: Qualified Names956490 -Node: Default Namespace957489 -Node: Changing The Namespace958230 -Node: Naming Rules959844 -Node: Internal Name Management961692 -Node: Namespace Example962734 -Node: Namespace And Features965296 -Node: Namespace Summary966731 -Node: Arbitrary Precision Arithmetic968208 -Node: Computer Arithmetic969695 -Ref: table-numeric-ranges973461 -Ref: table-floating-point-ranges973954 -Ref: Computer Arithmetic-Footnote-1974612 -Node: Math Definitions974669 -Ref: table-ieee-formats977985 -Ref: Math Definitions-Footnote-1978588 -Node: MPFR features978693 -Node: FP Math Caution980411 -Ref: FP Math Caution-Footnote-1981483 -Node: Inexactness of computations981852 -Node: Inexact representation982812 -Node: Comparing FP Values984172 -Node: Errors accumulate985413 -Node: Getting Accuracy986846 -Node: Try To Round989556 -Node: Setting precision990455 -Ref: table-predefined-precision-strings991152 -Node: Setting the rounding mode992982 -Ref: table-gawk-rounding-modes993356 -Ref: Setting the rounding mode-Footnote-1997287 -Node: Arbitrary Precision Integers997466 -Ref: Arbitrary Precision Integers-Footnote-11000641 -Node: Checking for MPFR1000790 -Node: POSIX Floating Point Problems1002264 -Ref: POSIX Floating Point Problems-Footnote-11006549 -Node: Floating point summary1006587 -Node: Dynamic Extensions1008777 -Node: Extension Intro1010330 -Node: Plugin License1011596 -Node: Extension Mechanism Outline1012393 -Ref: figure-load-extension1012832 -Ref: figure-register-new-function1014397 -Ref: figure-call-new-function1015489 -Node: Extension API Description1017551 -Node: Extension API Functions Introduction1019264 -Ref: table-api-std-headers1021100 -Node: General Data Types1025349 -Ref: General Data Types-Footnote-11033979 -Node: Memory Allocation Functions1034278 -Ref: Memory Allocation Functions-Footnote-11038779 -Node: Constructor Functions1038878 -Node: API Ownership of MPFR and GMP Values1042344 -Node: Registration Functions1043657 -Node: Extension Functions1044357 -Node: Exit Callback Functions1049679 -Node: Extension Version String1050929 -Node: Input Parsers1051592 -Node: Output Wrappers1064313 -Node: Two-way processors1068825 -Node: Printing Messages1071090 -Ref: Printing Messages-Footnote-11072261 -Node: Updating ERRNO1072414 -Node: Requesting Values1073153 -Ref: table-value-types-returned1073890 -Node: Accessing Parameters1074826 -Node: Symbol Table Access1076063 -Node: Symbol table by name1076575 -Ref: Symbol table by name-Footnote-11079599 -Node: Symbol table by cookie1079727 -Ref: Symbol table by cookie-Footnote-11083912 -Node: Cached values1083976 -Ref: Cached values-Footnote-11087512 -Node: Array Manipulation1087665 -Ref: Array Manipulation-Footnote-11088756 -Node: Array Data Types1088793 -Ref: Array Data Types-Footnote-11091451 -Node: Array Functions1091543 -Node: Flattening Arrays1096041 -Node: Creating Arrays1103017 -Node: Redirection API1107784 -Node: Extension API Variables1110617 -Node: Extension Versioning1111328 -Ref: gawk-api-version1111757 -Node: Extension GMP/MPFR Versioning1113488 -Node: Extension API Informational Variables1115116 -Node: Extension API Boilerplate1116189 -Node: Changes from API V11120163 -Node: Finding Extensions1121735 -Node: Extension Example1122294 -Node: Internal File Description1123092 -Node: Internal File Ops1127172 -Ref: Internal File Ops-Footnote-11138522 -Node: Using Internal File Ops1138662 -Ref: Using Internal File Ops-Footnote-11141045 -Node: Extension Samples1141319 -Node: Extension Sample File Functions1142848 -Node: Extension Sample Fnmatch1150497 -Node: Extension Sample Fork1151984 -Node: Extension Sample Inplace1153202 -Node: Extension Sample Ord1156828 -Node: Extension Sample Readdir1157664 -Ref: table-readdir-file-types1158553 -Node: Extension Sample Revout1159620 -Node: Extension Sample Rev2way1160209 -Node: Extension Sample Read write array1160949 -Node: Extension Sample Readfile1162891 -Node: Extension Sample Time1163986 -Node: Extension Sample API Tests1165738 -Node: gawkextlib1166230 -Node: Extension summary1169148 -Node: Extension Exercises1172850 -Node: Language History1174092 -Node: V7/SVR3.11175748 -Node: SVR41177900 -Node: POSIX1179334 -Node: BTL1180715 -Node: POSIX/GNU1181444 -Node: Feature History1187222 -Node: Common Extensions1203541 -Node: Ranges and Locales1204824 -Ref: Ranges and Locales-Footnote-11209440 -Ref: Ranges and Locales-Footnote-21209467 -Ref: Ranges and Locales-Footnote-31209702 -Node: Contributors1209925 -Node: History summary1215922 -Node: Installation1217302 -Node: Gawk Distribution1218246 -Node: Getting1218730 -Node: Extracting1219693 -Node: Distribution contents1221331 -Node: Unix Installation1227811 -Node: Quick Installation1228493 -Node: Shell Startup Files1230907 -Node: Additional Configuration Options1231996 -Node: Configuration Philosophy1234311 -Node: Non-Unix Installation1236680 -Node: PC Installation1237140 -Node: PC Binary Installation1237978 -Node: PC Compiling1238413 -Node: PC Using1239530 -Node: Cygwin1243083 -Node: MSYS1244307 -Node: VMS Installation1244909 -Node: VMS Compilation1245700 -Ref: VMS Compilation-Footnote-11246929 -Node: VMS Dynamic Extensions1246987 -Node: VMS Installation Details1248672 -Node: VMS Running1250925 -Node: VMS GNV1255204 -Node: VMS Old Gawk1255939 -Node: Bugs1256410 -Node: Bug address1257073 -Node: Usenet1260055 -Node: Maintainers1261059 -Node: Other Versions1262244 -Node: Installation summary1269332 -Node: Notes1270541 -Node: Compatibility Mode1271335 -Node: Additions1272117 -Node: Accessing The Source1273042 -Node: Adding Code1274479 -Node: New Ports1280698 -Node: Derived Files1285073 -Ref: Derived Files-Footnote-11290733 -Ref: Derived Files-Footnote-21290768 -Ref: Derived Files-Footnote-31291366 -Node: Future Extensions1291480 -Node: Implementation Limitations1292138 -Node: Extension Design1293348 -Node: Old Extension Problems1294492 -Ref: Old Extension Problems-Footnote-11296010 -Node: Extension New Mechanism Goals1296067 -Ref: Extension New Mechanism Goals-Footnote-11299431 -Node: Extension Other Design Decisions1299620 -Node: Extension Future Growth1301733 -Node: Notes summary1302339 -Node: Basic Concepts1303497 -Node: Basic High Level1304178 -Ref: figure-general-flow1304460 -Ref: figure-process-flow1305145 -Ref: Basic High Level-Footnote-11308446 -Node: Basic Data Typing1308631 -Node: Glossary1311959 -Node: Copying1343844 -Node: GNU Free Documentation License1381387 -Node: Index1406507 +Node: Foreword344553 +Node: Foreword448995 +Node: Preface50527 +Ref: Preface-Footnote-153386 +Ref: Preface-Footnote-253495 +Ref: Preface-Footnote-353729 +Node: History53871 +Node: Names56223 +Ref: Names-Footnote-157327 +Node: This Manual57474 +Ref: This Manual-Footnote-164113 +Node: Conventions64213 +Node: Manual History66582 +Ref: Manual History-Footnote-169579 +Ref: Manual History-Footnote-269620 +Node: How To Contribute69694 +Node: Acknowledgments70620 +Node: Getting Started75557 +Node: Running gawk77996 +Node: One-shot79186 +Node: Read Terminal80449 +Node: Long82442 +Node: Executable Scripts83955 +Ref: Executable Scripts-Footnote-186588 +Node: Comments86691 +Node: Quoting89175 +Node: DOS Quoting94701 +Node: Sample Data Files96757 +Node: Very Simple99352 +Node: Two Rules105454 +Node: More Complex107339 +Node: Statements/Lines109671 +Ref: Statements/Lines-Footnote-1114155 +Node: Other Features114420 +Node: When115356 +Ref: When-Footnote-1117110 +Node: Intro Summary117175 +Node: Invoking Gawk118059 +Node: Command Line119573 +Node: Options120371 +Ref: Options-Footnote-1138285 +Ref: Options-Footnote-2138516 +Node: Other Arguments138541 +Node: Naming Standard Input142552 +Node: Environment Variables143762 +Node: AWKPATH Variable144320 +Ref: AWKPATH Variable-Footnote-1147732 +Ref: AWKPATH Variable-Footnote-2147766 +Node: AWKLIBPATH Variable148137 +Ref: AWKLIBPATH Variable-Footnote-1149834 +Node: Other Environment Variables150209 +Node: Exit Status154030 +Node: Include Files154707 +Node: Loading Shared Libraries158397 +Node: Obsolete159825 +Node: Undocumented160517 +Node: Invoking Summary160814 +Node: Regexp163655 +Node: Regexp Usage165109 +Node: Escape Sequences167146 +Node: Regexp Operators173387 +Node: Regexp Operator Details173872 +Ref: Regexp Operator Details-Footnote-1180304 +Node: Interval Expressions180451 +Ref: Interval Expressions-Footnote-1181872 +Node: Bracket Expressions181970 +Ref: table-char-classes184446 +Node: Leftmost Longest187772 +Node: Computed Regexps189075 +Node: GNU Regexp Operators192502 +Node: Case-sensitivity196239 +Ref: Case-sensitivity-Footnote-1199105 +Ref: Case-sensitivity-Footnote-2199340 +Node: Regexp Summary199448 +Node: Reading Files200914 +Node: Records203183 +Node: awk split records204258 +Node: gawk split records209533 +Ref: gawk split records-Footnote-1214266 +Node: Fields214303 +Node: Nonconstant Fields217044 +Ref: Nonconstant Fields-Footnote-1219280 +Node: Changing Fields219484 +Node: Field Separators225515 +Node: Default Field Splitting228213 +Node: Regexp Field Splitting229331 +Node: Single Character Fields232684 +Node: Command Line Field Separator233744 +Node: Full Line Fields236962 +Ref: Full Line Fields-Footnote-1238484 +Ref: Full Line Fields-Footnote-2238530 +Node: Field Splitting Summary238631 +Node: Constant Size240705 +Node: Fixed width data241437 +Node: Skipping intervening244904 +Node: Allowing trailing data245702 +Node: Fields with fixed data246739 +Node: Splitting By Content248257 +Ref: Splitting By Content-Footnote-1252040 +Node: More CSV252203 +Node: Testing field creation253513 +Node: Multiple Line255138 +Node: Getline261415 +Node: Plain Getline263884 +Node: Getline/Variable266457 +Node: Getline/File267608 +Node: Getline/Variable/File268996 +Ref: Getline/Variable/File-Footnote-1270601 +Node: Getline/Pipe270689 +Node: Getline/Variable/Pipe273393 +Node: Getline/Coprocess274528 +Node: Getline/Variable/Coprocess275795 +Node: Getline Notes276537 +Node: Getline Summary279334 +Ref: table-getline-variants279758 +Node: Read Timeout280506 +Ref: Read Timeout-Footnote-1284412 +Node: Retrying Input284470 +Node: Command-line directories285669 +Node: Input Summary286575 +Node: Input Exercises289747 +Node: Printing290181 +Node: Print292015 +Node: Print Examples293472 +Node: Output Separators296252 +Node: OFMT298269 +Node: Printf299625 +Node: Basic Printf300410 +Node: Control Letters301984 +Node: Format Modifiers307146 +Node: Printf Examples313161 +Node: Redirection315647 +Node: Special FD322488 +Ref: Special FD-Footnote-1325656 +Node: Special Files325730 +Node: Other Inherited Files326347 +Node: Special Network327348 +Node: Special Caveats328208 +Node: Close Files And Pipes329157 +Ref: table-close-pipe-return-values336064 +Ref: Close Files And Pipes-Footnote-1336877 +Ref: Close Files And Pipes-Footnote-2337025 +Node: Nonfatal337177 +Node: Output Summary339515 +Node: Output Exercises340737 +Node: Expressions341416 +Node: Values342604 +Node: Constants343282 +Node: Scalar Constants343973 +Ref: Scalar Constants-Footnote-1346483 +Node: Nondecimal-numbers346733 +Node: Regexp Constants349734 +Node: Using Constant Regexps350260 +Node: Standard Regexp Constants350882 +Node: Strong Regexp Constants354070 +Node: Variables357082 +Node: Using Variables357739 +Node: Assignment Options359649 +Node: Conversion362120 +Node: Strings And Numbers362644 +Ref: Strings And Numbers-Footnote-1365707 +Node: Locale influences conversions365816 +Ref: table-locale-affects368574 +Node: All Operators369192 +Node: Arithmetic Ops369821 +Node: Concatenation372537 +Ref: Concatenation-Footnote-1375384 +Node: Assignment Ops375491 +Ref: table-assign-ops380482 +Node: Increment Ops381795 +Node: Truth Values and Conditions385255 +Node: Truth Values386329 +Node: Typing and Comparison387377 +Node: Variable Typing388197 +Ref: Variable Typing-Footnote-1394660 +Ref: Variable Typing-Footnote-2394732 +Node: Comparison Operators394809 +Ref: table-relational-ops395228 +Node: POSIX String Comparison398723 +Ref: POSIX String Comparison-Footnote-1400418 +Ref: POSIX String Comparison-Footnote-2400557 +Node: Boolean Ops400641 +Ref: Boolean Ops-Footnote-1405123 +Node: Conditional Exp405215 +Node: Function Calls406951 +Node: Precedence410828 +Node: Locales414487 +Node: Expressions Summary416119 +Node: Patterns and Actions418692 +Node: Pattern Overview419812 +Node: Regexp Patterns421489 +Node: Expression Patterns422031 +Node: Ranges425812 +Node: BEGIN/END428920 +Node: Using BEGIN/END429681 +Ref: Using BEGIN/END-Footnote-1432435 +Node: I/O And BEGIN/END432541 +Node: BEGINFILE/ENDFILE434854 +Node: Empty438085 +Node: Using Shell Variables438402 +Node: Action Overview440676 +Node: Statements443001 +Node: If Statement444849 +Node: While Statement446344 +Node: Do Statement448372 +Node: For Statement449520 +Node: Switch Statement452691 +Node: Break Statement455132 +Node: Continue Statement457224 +Node: Next Statement459051 +Node: Nextfile Statement461434 +Node: Exit Statement464072 +Node: Built-in Variables466475 +Node: User-modified467608 +Node: Auto-set475375 +Ref: Auto-set-Footnote-1492182 +Ref: Auto-set-Footnote-2492388 +Node: ARGC and ARGV492444 +Node: Pattern Action Summary496657 +Node: Arrays499087 +Node: Array Basics500416 +Node: Array Intro501260 +Ref: figure-array-elements503235 +Ref: Array Intro-Footnote-1505939 +Node: Reference to Elements506067 +Node: Assigning Elements508531 +Node: Array Example509022 +Node: Scanning an Array510781 +Node: Controlling Scanning513803 +Ref: Controlling Scanning-Footnote-1520259 +Node: Numeric Array Subscripts520575 +Node: Uninitialized Subscripts522759 +Node: Delete524378 +Ref: Delete-Footnote-1527130 +Node: Multidimensional527187 +Node: Multiscanning530282 +Node: Arrays of Arrays531873 +Node: Arrays Summary536641 +Node: Functions538734 +Node: Built-in539772 +Node: Calling Built-in540853 +Node: Numeric Functions542849 +Ref: Numeric Functions-Footnote-1546875 +Ref: Numeric Functions-Footnote-2547523 +Ref: Numeric Functions-Footnote-3547571 +Node: String Functions547843 +Ref: String Functions-Footnote-1571984 +Ref: String Functions-Footnote-2572112 +Ref: String Functions-Footnote-3572360 +Node: Gory Details572447 +Ref: table-sub-escapes574238 +Ref: table-sub-proposed575757 +Ref: table-posix-sub577120 +Ref: table-gensub-escapes578661 +Ref: Gory Details-Footnote-1579484 +Node: I/O Functions579638 +Ref: table-system-return-values586092 +Ref: I/O Functions-Footnote-1588172 +Ref: I/O Functions-Footnote-2588320 +Node: Time Functions588440 +Ref: Time Functions-Footnote-1599111 +Ref: Time Functions-Footnote-2599179 +Ref: Time Functions-Footnote-3599337 +Ref: Time Functions-Footnote-4599448 +Ref: Time Functions-Footnote-5599560 +Ref: Time Functions-Footnote-6599787 +Node: Bitwise Functions600053 +Ref: table-bitwise-ops600647 +Ref: Bitwise Functions-Footnote-1606710 +Ref: Bitwise Functions-Footnote-2606883 +Node: Type Functions607074 +Node: I18N Functions609937 +Node: User-defined611588 +Node: Definition Syntax612400 +Ref: Definition Syntax-Footnote-1618094 +Node: Function Example618165 +Ref: Function Example-Footnote-1621087 +Node: Function Calling621109 +Node: Calling A Function621697 +Node: Variable Scope622655 +Node: Pass By Value/Reference625649 +Node: Function Caveats628293 +Ref: Function Caveats-Footnote-1630340 +Node: Return Statement630460 +Node: Dynamic Typing633439 +Node: Indirect Calls634369 +Ref: Indirect Calls-Footnote-1644621 +Node: Functions Summary644749 +Node: Library Functions647454 +Ref: Library Functions-Footnote-1651061 +Ref: Library Functions-Footnote-2651204 +Node: Library Names651375 +Ref: Library Names-Footnote-1655042 +Ref: Library Names-Footnote-2655265 +Node: General Functions655351 +Node: Strtonum Function656454 +Node: Assert Function659476 +Node: Round Function662802 +Node: Cliff Random Function664342 +Node: Ordinal Functions665358 +Ref: Ordinal Functions-Footnote-1668421 +Ref: Ordinal Functions-Footnote-2668673 +Node: Join Function668883 +Ref: Join Function-Footnote-1670653 +Node: Getlocaltime Function670853 +Node: Readfile Function674595 +Node: Shell Quoting676572 +Node: Data File Management677973 +Node: Filetrans Function678605 +Node: Rewind Function682701 +Node: File Checking684610 +Ref: File Checking-Footnote-1685944 +Node: Empty Files686145 +Node: Ignoring Assigns688124 +Node: Getopt Function689674 +Ref: Getopt Function-Footnote-1704885 +Node: Passwd Functions705085 +Ref: Passwd Functions-Footnote-1713924 +Node: Group Functions714012 +Ref: Group Functions-Footnote-1721910 +Node: Walking Arrays722117 +Node: Library Functions Summary725125 +Node: Library Exercises726531 +Node: Sample Programs726996 +Node: Running Examples727766 +Node: Clones728494 +Node: Cut Program729718 +Node: Egrep Program739647 +Node: Id Program748658 +Node: Split Program758605 +Ref: Split Program-Footnote-1768379 +Node: Tee Program768552 +Node: Uniq Program771342 +Node: Wc Program778906 +Node: Bytes vs. Characters779303 +Node: Using extensions780851 +Node: wc program781609 +Node: Miscellaneous Programs786474 +Node: Dupword Program787687 +Node: Alarm Program789717 +Node: Translate Program794572 +Ref: Translate Program-Footnote-1799137 +Node: Labels Program799407 +Ref: Labels Program-Footnote-1802758 +Node: Word Sorting802842 +Node: History Sorting806914 +Node: Extract Program809139 +Node: Simple Sed817193 +Node: Igawk Program820267 +Ref: Igawk Program-Footnote-1834598 +Ref: Igawk Program-Footnote-2834800 +Ref: Igawk Program-Footnote-3834922 +Node: Anagram Program835037 +Node: Signature Program838099 +Node: Programs Summary839346 +Node: Programs Exercises840560 +Ref: Programs Exercises-Footnote-1844690 +Node: Advanced Features844776 +Node: Nondecimal Data846766 +Node: Array Sorting848357 +Node: Controlling Array Traversal849057 +Ref: Controlling Array Traversal-Footnote-1857425 +Node: Array Sorting Functions857543 +Ref: Array Sorting Functions-Footnote-1862634 +Node: Two-way I/O862830 +Ref: Two-way I/O-Footnote-1870551 +Ref: Two-way I/O-Footnote-2870738 +Node: TCP/IP Networking870820 +Node: Profiling873938 +Node: Advanced Features Summary883252 +Node: Internationalization885096 +Node: I18N and L10N886576 +Node: Explaining gettext887263 +Ref: Explaining gettext-Footnote-1893155 +Ref: Explaining gettext-Footnote-2893340 +Node: Programmer i18n893505 +Ref: Programmer i18n-Footnote-1898454 +Node: Translator i18n898503 +Node: String Extraction899297 +Ref: String Extraction-Footnote-1900429 +Node: Printf Ordering900515 +Ref: Printf Ordering-Footnote-1903301 +Node: I18N Portability903365 +Ref: I18N Portability-Footnote-1905821 +Node: I18N Example905884 +Ref: I18N Example-Footnote-1909159 +Ref: I18N Example-Footnote-2909232 +Node: Gawk I18N909341 +Node: I18N Summary909990 +Node: Debugger911331 +Node: Debugging912331 +Node: Debugging Concepts912772 +Node: Debugging Terms914581 +Node: Awk Debugging917156 +Ref: Awk Debugging-Footnote-1918101 +Node: Sample Debugging Session918233 +Node: Debugger Invocation918767 +Node: Finding The Bug920153 +Node: List of Debugger Commands926627 +Node: Breakpoint Control927960 +Node: Debugger Execution Control931654 +Node: Viewing And Changing Data935016 +Node: Execution Stack938557 +Node: Debugger Info940194 +Node: Miscellaneous Debugger Commands944265 +Node: Readline Support949327 +Node: Limitations950223 +Node: Debugging Summary952777 +Node: Namespaces954056 +Node: Global Namespace955167 +Node: Qualified Names956565 +Node: Default Namespace957564 +Node: Changing The Namespace958305 +Node: Naming Rules959919 +Node: Internal Name Management961767 +Node: Namespace Example962809 +Node: Namespace And Features965371 +Node: Namespace Summary966806 +Node: Arbitrary Precision Arithmetic968283 +Node: Computer Arithmetic969770 +Ref: table-numeric-ranges973536 +Ref: table-floating-point-ranges974029 +Ref: Computer Arithmetic-Footnote-1974687 +Node: Math Definitions974744 +Ref: table-ieee-formats977720 +Node: MPFR features978287 +Node: FP Math Caution980005 +Ref: FP Math Caution-Footnote-1981077 +Node: Inexactness of computations981446 +Node: Inexact representation982477 +Node: Comparing FP Values983837 +Node: Errors accumulate985078 +Node: Strange values986534 +Ref: Strange values-Footnote-1989096 +Node: Getting Accuracy989201 +Node: Try To Round991911 +Node: Setting precision992810 +Ref: table-predefined-precision-strings993507 +Node: Setting the rounding mode995337 +Ref: table-gawk-rounding-modes995711 +Ref: Setting the rounding mode-Footnote-1999642 +Node: Arbitrary Precision Integers999821 +Ref: Arbitrary Precision Integers-Footnote-11002996 +Node: Checking for MPFR1003145 +Node: POSIX Floating Point Problems1004619 +Ref: POSIX Floating Point Problems-Footnote-11008904 +Node: Floating point summary1008942 +Node: Dynamic Extensions1011132 +Node: Extension Intro1012685 +Node: Plugin License1013951 +Node: Extension Mechanism Outline1014748 +Ref: figure-load-extension1015187 +Ref: figure-register-new-function1016752 +Ref: figure-call-new-function1017844 +Node: Extension API Description1019906 +Node: Extension API Functions Introduction1021619 +Ref: table-api-std-headers1023455 +Node: General Data Types1027704 +Ref: General Data Types-Footnote-11036334 +Node: Memory Allocation Functions1036633 +Ref: Memory Allocation Functions-Footnote-11041134 +Node: Constructor Functions1041233 +Node: API Ownership of MPFR and GMP Values1044699 +Node: Registration Functions1046012 +Node: Extension Functions1046712 +Node: Exit Callback Functions1052034 +Node: Extension Version String1053284 +Node: Input Parsers1053947 +Node: Output Wrappers1066668 +Node: Two-way processors1071180 +Node: Printing Messages1073445 +Ref: Printing Messages-Footnote-11074616 +Node: Updating ERRNO1074769 +Node: Requesting Values1075508 +Ref: table-value-types-returned1076245 +Node: Accessing Parameters1077181 +Node: Symbol Table Access1078418 +Node: Symbol table by name1078930 +Ref: Symbol table by name-Footnote-11081954 +Node: Symbol table by cookie1082082 +Ref: Symbol table by cookie-Footnote-11086267 +Node: Cached values1086331 +Ref: Cached values-Footnote-11089867 +Node: Array Manipulation1090020 +Ref: Array Manipulation-Footnote-11091111 +Node: Array Data Types1091148 +Ref: Array Data Types-Footnote-11093806 +Node: Array Functions1093898 +Node: Flattening Arrays1098396 +Node: Creating Arrays1105372 +Node: Redirection API1110139 +Node: Extension API Variables1112972 +Node: Extension Versioning1113683 +Ref: gawk-api-version1114112 +Node: Extension GMP/MPFR Versioning1115843 +Node: Extension API Informational Variables1117471 +Node: Extension API Boilerplate1118544 +Node: Changes from API V11122518 +Node: Finding Extensions1124090 +Node: Extension Example1124649 +Node: Internal File Description1125447 +Node: Internal File Ops1129527 +Ref: Internal File Ops-Footnote-11140877 +Node: Using Internal File Ops1141017 +Ref: Using Internal File Ops-Footnote-11143400 +Node: Extension Samples1143674 +Node: Extension Sample File Functions1145203 +Node: Extension Sample Fnmatch1152852 +Node: Extension Sample Fork1154339 +Node: Extension Sample Inplace1155557 +Node: Extension Sample Ord1159183 +Node: Extension Sample Readdir1160019 +Ref: table-readdir-file-types1160908 +Node: Extension Sample Revout1161975 +Node: Extension Sample Rev2way1162564 +Node: Extension Sample Read write array1163304 +Node: Extension Sample Readfile1165246 +Node: Extension Sample Time1166341 +Node: Extension Sample API Tests1168093 +Node: gawkextlib1168585 +Node: Extension summary1171503 +Node: Extension Exercises1175205 +Node: Language History1176447 +Node: V7/SVR3.11178103 +Node: SVR41180255 +Node: POSIX1181689 +Node: BTL1183070 +Node: POSIX/GNU1183799 +Node: Feature History1189577 +Node: Common Extensions1205896 +Node: Ranges and Locales1207179 +Ref: Ranges and Locales-Footnote-11211795 +Ref: Ranges and Locales-Footnote-21211822 +Ref: Ranges and Locales-Footnote-31212057 +Node: Contributors1212280 +Node: History summary1218277 +Node: Installation1219657 +Node: Gawk Distribution1220601 +Node: Getting1221085 +Node: Extracting1222048 +Node: Distribution contents1223686 +Node: Unix Installation1230166 +Node: Quick Installation1230848 +Node: Shell Startup Files1233262 +Node: Additional Configuration Options1234351 +Node: Configuration Philosophy1236666 +Node: Non-Unix Installation1239035 +Node: PC Installation1239495 +Node: PC Binary Installation1240333 +Node: PC Compiling1240768 +Node: PC Using1241885 +Node: Cygwin1245438 +Node: MSYS1246662 +Node: VMS Installation1247264 +Node: VMS Compilation1248055 +Ref: VMS Compilation-Footnote-11249284 +Node: VMS Dynamic Extensions1249342 +Node: VMS Installation Details1251027 +Node: VMS Running1253280 +Node: VMS GNV1257559 +Node: VMS Old Gawk1258294 +Node: Bugs1258765 +Node: Bug address1259428 +Node: Usenet1262410 +Node: Maintainers1263414 +Node: Other Versions1264599 +Node: Installation summary1271687 +Node: Notes1272896 +Node: Compatibility Mode1273690 +Node: Additions1274472 +Node: Accessing The Source1275397 +Node: Adding Code1276834 +Node: New Ports1283053 +Node: Derived Files1287428 +Ref: Derived Files-Footnote-11293088 +Ref: Derived Files-Footnote-21293123 +Ref: Derived Files-Footnote-31293721 +Node: Future Extensions1293835 +Node: Implementation Limitations1294493 +Node: Extension Design1295703 +Node: Old Extension Problems1296847 +Ref: Old Extension Problems-Footnote-11298365 +Node: Extension New Mechanism Goals1298422 +Ref: Extension New Mechanism Goals-Footnote-11301786 +Node: Extension Other Design Decisions1301975 +Node: Extension Future Growth1304088 +Node: Notes summary1304694 +Node: Basic Concepts1305852 +Node: Basic High Level1306533 +Ref: figure-general-flow1306815 +Ref: figure-process-flow1307500 +Ref: Basic High Level-Footnote-11310801 +Node: Basic Data Typing1310986 +Node: Glossary1314314 +Node: Copying1346199 +Node: GNU Free Documentation License1383742 +Node: Index1408862 End Tag Table diff --git a/doc/gawk.texi b/doc/gawk.texi index a7d7ff56..c69d591d 100644 --- a/doc/gawk.texi +++ b/doc/gawk.texi @@ -919,6 +919,7 @@ particular records in a file and perform operations upon them. * Inexact representation:: Numbers are not exactly represented. * Comparing FP Values:: How to compare floating point values. * Errors accumulate:: Errors get bigger as they go. +* Strange values:: A few words about infinities and NaNs. * Getting Accuracy:: Getting more accuracy takes some work. * Try To Round:: Add digits and round. * Setting precision:: How to set the precision. @@ -3135,11 +3136,12 @@ column means that the person is a friend. An @samp{R} means that the person is a relative: @example -@c system if test ! -d eg ; then mkdir eg ; fi -@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi -@c system if test ! -d eg/data ; then mkdir eg/data ; fi -@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi -@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi +@c system if test ! -d eg ; then mkdir eg ; fi +@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi +@c system if test ! -d eg/data ; then mkdir eg/data ; fi +@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi +@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi +@c system if test ! -d eg/test-programs ; then mkdir eg/test-programs ; fi @c file eg/data/mail-list Amelia 555-5553 amelia.zodiacusque@@gmail.com F Anthony 555-3412 anthony.asserturo@@hotmail.com A @@ -8413,7 +8415,7 @@ FPAT = "([^,]*)|(\"[^\"]+\")" @c Per email from Ed Morton <mortoneccc@comcast.net> @c @c WONTFIX: 10/2020 -@c This is too much work. FPAT and CSV files are very flakey and +@c This is too much work. FPAT and CSV files are very flaky and @c fragile. Doing something like this is merely inviting trouble. As with @code{FS}, the @code{IGNORECASE} variable (@pxref{User-modified}) @@ -10063,7 +10065,7 @@ infinity are formatted as and positive infinity as @samp{inf} or @samp{infinity}. The special ``not a number'' value formats as @samp{-nan} or @samp{nan} -(@pxref{Math Definitions}). +(@pxref{Strange values}). @item @code{%F} Like @samp{%f}, but the infinity and ``not a number'' values are spelled @@ -18298,7 +18300,7 @@ compatibility mode (@pxref{Options}). @cindexawkfunc{log} @cindex logarithm Return the natural logarithm of @var{x}, if @var{x} is positive; -otherwise, return @code{NaN} (``not a number'') on IEEE 754 systems. +otherwise, return NaN (``not a number'') on IEEE 754 systems. Additionally, @command{gawk} prints a warning message when @code{x} is negative. @@ -33586,21 +33588,9 @@ A special value representing infinity. Operations involving another number and infinity produce infinity. @item NaN -``Not a number.''@footnote{Thanks to Michael Brennan for this description, -which we have paraphrased, and for the examples.} A special value that -results from attempting a calculation that has no answer as a real number. -In such a case, programs can either receive a floating-point exception, -or get @code{NaN} back as the result. The IEEE 754 standard recommends -that systems return @code{NaN}. Some examples: - -@table @code -@item sqrt(-1) -This makes sense in the range of complex numbers, but not in the -range of real numbers, so the result is @code{NaN}. - -@item log(-8) -@minus{}8 is out of the domain of @code{log()}, so the result is @code{NaN}. -@end table +``Not a number.'' A special value that results from attempting a +calculation that has no answer as a real number. @xref{Strange values}, +for more information about infinity and not-a-number values. @item Normalized How the significand (see later in this list) is usually stored. The @@ -33769,6 +33759,7 @@ decimal places in the final result. * Inexact representation:: Numbers are not exactly represented. * Comparing FP Values:: How to compare floating point values. * Errors accumulate:: Errors get bigger as they go. +* Strange values:: A few words about infinities and NaNs. @end menu @node Inexact representation @@ -33890,6 +33881,236 @@ $ @kbd{gawk 'BEGIN @{} @print{} 4 @end example +@node Strange values +@subsubsection Floating Point Values They Didn't Talk About In School + +Both IEEE 754 floating-point hardware, and MPFR, support two kinds of +values that you probably didn't learn about in school. The first is +@dfn{infinity}, a special value, that can be either negative or positive, +and which is either smaller than any other value (negative infinity), +or larger than any other value (positive infinity). When such values +are generated, @command{gawk} prints them as either @samp{-inf} or +@samp{+inf}, respectively. It accepts those strings as data input and +converts them to the proper floating-point values internally. + +Infinity values of the same sign compare as equal to each other. +Otherwise, operations (addition, subtraction, etc.) involving another +number and infinity produce infinity. + +The second kind of value is ``not a number'', or NaN for +short.@footnote{Thanks to Michael Brennan for this description, which we +have paraphrased, and for the examples.} This is a special value that results +from attempting a calculation that has no answer as a real number. +In such a case, programs can either receive a floating-point exception, +or get NaN back as the result. The IEEE 754 standard recommends +that systems return NaN. Some examples: + +@table @code +@item sqrt(-1) +@iftex +The @math{\sqrt{-1}} +@end iftex +@ifnottex +This +@end ifnottex +makes sense in the range of complex numbers, but not in the +range of real numbers, so the result is NaN. + +@item log(-8) +@minus{}8 is out of the domain of @code{log()}, so the result is NaN. +@end table + +NaN values are strange. In particular, they cannot be compared with other +floating point values; any such comparison, except for ``is not equal +to'', returns false. NaN values are so much unequal to other values that +even comparing two identical NaN values with @code{!=} returns true! + +NaN values can also be signed, although it depends upon the implementation +as to which sign you get for any operation that returns a NaN. For +example, on some systems, @code{sqrt(-1)} returns a negative NaN. On +others, it returns a positive NaN. + +When such values are generated, @command{gawk} prints them as either +@samp{-nan} or @samp{+nan}, respectively. Here too, @command{gawk} +accepts those strings as data input and converts them to the proper +floating-point values internally. + +@ignore +@c file eg/test-programs/gen-float-table.awk +function eq(left, right) +{ + return left == right +} + +function ne(left, right) +{ + return left != right +} + +function lt(left, right) +{ + return left < right +} + +function le(left, right) +{ + return left <= right +} + +function gt(left, right) +{ + return left > right +} + +function ge(left, right) +{ + return left >= right +} + +BEGIN { + nan = sqrt(-1) + inf = -log(0) + split("== != < <= > >=", names) + names[3] = names[3] " " + names[5] = names[5] " " + split("eq ne lt le gt ge", funcs) + + compare[1] = 2.0 + compare[2] = values[1] = -sqrt(-1.0) # nan + compare[3] = values[2] = sqrt(-1.0) # -nan + compare[4] = values[3] = -log(0.0) # inf + compare[5] = values[4] = log(0.0) # -inf + + for (i = 1; i in values; i++) { + for (j = 1; j in compare; j++) { + for (k = 1; k in names; k++) { + the_func = funcs[k] + printf("%g %s %g -> %s\n", + values[i], + names[k], + compare[j], + @the_func(values[i], compare[j]) ? + "true" : "false"); + } + printf("\n"); + } + } +} +@c endfile +@end ignore + +@ignore +@c file eg/test-programs/gen-float-table.c +#include <stdio.h> +#include <math.h> +#include <stdbool.h> + +#define def_func(name, op) \ + bool name(double left, double right) { \ + return left op right; \ + } + +def_func(eq, ==) +def_func(ne, !=) +def_func(lt, <) +def_func(le, <=) +def_func(gt, >) +def_func(ge, >=) + +struct { + const char *name; + bool (*func)(double left, double right); +} functions[] = { + { "==", eq }, + { "!=", ne }, + { "< ", lt }, + { "<=", le }, + { "> ", gt }, + { ">=", ge }, + { 0, 0 } +}; + +int main() +{ + double values[] = { + -sqrt(-1), // nan + sqrt(-1), // -nan + -log(0.0), // inf + log(0.0) // -inf + }; + double compare[] = { 2.0, + -sqrt(-1), // nan + sqrt(-1), // -nan + -log(0.0), // inf + log(0.0) // -inf + }; + + int i, j, k; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 5; j++) { + for (k = 0; functions[k].name != NULL; k++) { + printf("%g %s %g -> %s\n", values[i], + functions[k].name, + compare[j], + functions[k].func(values[i], compare[j]) ? "true" : "false"); + } + printf("\n"); + } + } + + return 0; +} +@c endfile +@end ignore + +@ignore +@c file eg/test-programs/gen-float-table.py +from math import * + +nan = float('NaN') +inf = float('Inf') + +def eq(left, right): + return left == right + +def ne(left, right): + return left != right + +def lt(left, right): + return left < right + +def le(left, right): + return left <= right + +def gt(left, right): + return left > right + +def ge(left, right): + return left >= right + +func_map = { + "==": eq, + "!=": ne, + "< ": lt, + "<=": le, + "> ": gt, + ">=": ge, +} + +compare = [2.0, nan, -nan, inf, -inf] +values = [nan, -nan, inf, -inf] + +for i in range(len(values)): + for j in range(len(compare)): + for op in func_map: + print("%g %s %g -> %s" % + (values[i], op, compare[j], func_map[op](values[i], compare[j]))) + + print("") +@c endfile +@end ignore + @node Getting Accuracy @subsection Getting the Accuracy You Need diff --git a/doc/gawktexi.in b/doc/gawktexi.in index 2a25c1d0..8b35bf32 100644 --- a/doc/gawktexi.in +++ b/doc/gawktexi.in @@ -914,6 +914,7 @@ particular records in a file and perform operations upon them. * Inexact representation:: Numbers are not exactly represented. * Comparing FP Values:: How to compare floating point values. * Errors accumulate:: Errors get bigger as they go. +* Strange values:: A few words about infinities and NaNs. * Getting Accuracy:: Getting more accuracy takes some work. * Try To Round:: Add digits and round. * Setting precision:: How to set the precision. @@ -3045,11 +3046,12 @@ column means that the person is a friend. An @samp{R} means that the person is a relative: @example -@c system if test ! -d eg ; then mkdir eg ; fi -@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi -@c system if test ! -d eg/data ; then mkdir eg/data ; fi -@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi -@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi +@c system if test ! -d eg ; then mkdir eg ; fi +@c system if test ! -d eg/lib ; then mkdir eg/lib ; fi +@c system if test ! -d eg/data ; then mkdir eg/data ; fi +@c system if test ! -d eg/prog ; then mkdir eg/prog ; fi +@c system if test ! -d eg/misc ; then mkdir eg/misc ; fi +@c system if test ! -d eg/test-programs ; then mkdir eg/test-programs ; fi @c file eg/data/mail-list Amelia 555-5553 amelia.zodiacusque@@gmail.com F Anthony 555-3412 anthony.asserturo@@hotmail.com A @@ -7966,7 +7968,7 @@ FPAT = "([^,]*)|(\"[^\"]+\")" @c Per email from Ed Morton <mortoneccc@comcast.net> @c @c WONTFIX: 10/2020 -@c This is too much work. FPAT and CSV files are very flakey and +@c This is too much work. FPAT and CSV files are very flaky and @c fragile. Doing something like this is merely inviting trouble. As with @code{FS}, the @code{IGNORECASE} variable (@pxref{User-modified}) @@ -9616,7 +9618,7 @@ infinity are formatted as and positive infinity as @samp{inf} or @samp{infinity}. The special ``not a number'' value formats as @samp{-nan} or @samp{nan} -(@pxref{Math Definitions}). +(@pxref{Strange values}). @item @code{%F} Like @samp{%f}, but the infinity and ``not a number'' values are spelled @@ -17523,7 +17525,7 @@ compatibility mode (@pxref{Options}). @cindexawkfunc{log} @cindex logarithm Return the natural logarithm of @var{x}, if @var{x} is positive; -otherwise, return @code{NaN} (``not a number'') on IEEE 754 systems. +otherwise, return NaN (``not a number'') on IEEE 754 systems. Additionally, @command{gawk} prints a warning message when @code{x} is negative. @@ -32552,21 +32554,9 @@ A special value representing infinity. Operations involving another number and infinity produce infinity. @item NaN -``Not a number.''@footnote{Thanks to Michael Brennan for this description, -which we have paraphrased, and for the examples.} A special value that -results from attempting a calculation that has no answer as a real number. -In such a case, programs can either receive a floating-point exception, -or get @code{NaN} back as the result. The IEEE 754 standard recommends -that systems return @code{NaN}. Some examples: - -@table @code -@item sqrt(-1) -This makes sense in the range of complex numbers, but not in the -range of real numbers, so the result is @code{NaN}. - -@item log(-8) -@minus{}8 is out of the domain of @code{log()}, so the result is @code{NaN}. -@end table +``Not a number.'' A special value that results from attempting a +calculation that has no answer as a real number. @xref{Strange values}, +for more information about infinity and not-a-number values. @item Normalized How the significand (see later in this list) is usually stored. The @@ -32735,6 +32725,7 @@ decimal places in the final result. * Inexact representation:: Numbers are not exactly represented. * Comparing FP Values:: How to compare floating point values. * Errors accumulate:: Errors get bigger as they go. +* Strange values:: A few words about infinities and NaNs. @end menu @node Inexact representation @@ -32856,6 +32847,242 @@ $ @kbd{gawk 'BEGIN @{} @print{} 4 @end example +@node Strange values +@subsubsection Floating Point Values They Didn't Talk About In School + +Both IEEE 754 floating-point hardware, and MPFR, support two kinds of +values that you probably didn't learn about in school. The first is +@dfn{infinity}, a special value, that can be either negative or positive, +and which is either smaller than any other value (negative infinity), +or larger than any other value (positive infinity). When such values +are generated, @command{gawk} prints them as either @samp{-inf} or +@samp{+inf}, respectively. It accepts those strings as data input and +converts them to the proper floating-point values internally. + +Infinity values of the same sign compare as equal to each other. +Otherwise, operations (addition, subtraction, etc.) involving another +number and infinity produce infinity. + +The second kind of value is ``not a number'', or NaN for +short.@footnote{Thanks to Michael Brennan for this description, which we +have paraphrased, and for the examples.} This is a special value that results +from attempting a calculation that has no answer as a real number. +In such a case, programs can either receive a floating-point exception, +or get NaN back as the result. The IEEE 754 standard recommends +that systems return NaN. Some examples: + +@table @code +@item sqrt(-1) +@iftex +The @math{\sqrt{-1}} +@end iftex +@ifnottex +This +@end ifnottex +makes sense in the range of complex numbers, but not in the +range of real numbers, so the result is NaN. + +@item log(-8) +@minus{}8 is out of the domain of @code{log()}, so the result is NaN. +@end table + +NaN values are strange. In particular, they cannot be compared with other +floating point values; any such comparison, except for ``is not equal +to'', returns false. NaN values are so much unequal to other values that +even comparing two identical NaN values with @code{!=} returns true! + +NaN values can also be signed, although it depends upon the implementation +as to which sign you get for any operation that returns a NaN. For +example, on some systems, @code{sqrt(-1)} returns a negative NaN. On +others, it returns a positive NaN. + +When such values are generated, @command{gawk} prints them as either +@samp{-nan} or @samp{+nan}, respectively. Here too, @command{gawk} +accepts those strings as data input and converts them to the proper +floating-point values internally. + +If you want to dive more deeply into this topic, you can find +test programs in C, @command{awk} and Python in the directory +@file{awklib/eg/test-programs} in the @command{gawk} distribution. +These programs enable comparison among programming languages as to how +they hanle NaN and infinity values. + +@ignore +@c file eg/test-programs/gen-float-table.awk +function eq(left, right) +{ + return left == right +} + +function ne(left, right) +{ + return left != right +} + +function lt(left, right) +{ + return left < right +} + +function le(left, right) +{ + return left <= right +} + +function gt(left, right) +{ + return left > right +} + +function ge(left, right) +{ + return left >= right +} + +BEGIN { + nan = sqrt(-1) + inf = -log(0) + split("== != < <= > >=", names) + names[3] = names[3] " " + names[5] = names[5] " " + split("eq ne lt le gt ge", funcs) + + compare[1] = 2.0 + compare[2] = values[1] = -sqrt(-1.0) # nan + compare[3] = values[2] = sqrt(-1.0) # -nan + compare[4] = values[3] = -log(0.0) # inf + compare[5] = values[4] = log(0.0) # -inf + + for (i = 1; i in values; i++) { + for (j = 1; j in compare; j++) { + for (k = 1; k in names; k++) { + the_func = funcs[k] + printf("%g %s %g -> %s\n", + values[i], + names[k], + compare[j], + @the_func(values[i], compare[j]) ? + "true" : "false"); + } + printf("\n"); + } + } +} +@c endfile +@end ignore + +@ignore +@c file eg/test-programs/gen-float-table.c +#include <stdio.h> +#include <math.h> +#include <stdbool.h> + +#define def_func(name, op) \ + bool name(double left, double right) { \ + return left op right; \ + } + +def_func(eq, ==) +def_func(ne, !=) +def_func(lt, <) +def_func(le, <=) +def_func(gt, >) +def_func(ge, >=) + +struct { + const char *name; + bool (*func)(double left, double right); +} functions[] = { + { "==", eq }, + { "!=", ne }, + { "< ", lt }, + { "<=", le }, + { "> ", gt }, + { ">=", ge }, + { 0, 0 } +}; + +int main() +{ + double values[] = { + -sqrt(-1), // nan + sqrt(-1), // -nan + -log(0.0), // inf + log(0.0) // -inf + }; + double compare[] = { 2.0, + -sqrt(-1), // nan + sqrt(-1), // -nan + -log(0.0), // inf + log(0.0) // -inf + }; + + int i, j, k; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 5; j++) { + for (k = 0; functions[k].name != NULL; k++) { + printf("%g %s %g -> %s\n", values[i], + functions[k].name, + compare[j], + functions[k].func(values[i], compare[j]) ? "true" : "false"); + } + printf("\n"); + } + } + + return 0; +} +@c endfile +@end ignore + +@ignore +@c file eg/test-programs/gen-float-table.py +from math import * + +nan = float('NaN') +inf = float('Inf') + +def eq(left, right): + return left == right + +def ne(left, right): + return left != right + +def lt(left, right): + return left < right + +def le(left, right): + return left <= right + +def gt(left, right): + return left > right + +def ge(left, right): + return left >= right + +func_map = { + "==": eq, + "!=": ne, + "< ": lt, + "<=": le, + "> ": gt, + ">=": ge, +} + +compare = [2.0, nan, -nan, inf, -inf] +values = [nan, -nan, inf, -inf] + +for i in range(len(values)): + for j in range(len(compare)): + for op in func_map: + print("%g %s %g -> %s" % + (values[i], op, compare[j], func_map[op](values[i], compare[j]))) + + print("") +@c endfile +@end ignore + @node Getting Accuracy @subsection Getting the Accuracy You Need diff --git a/doc/wordlist b/doc/wordlist index c93eda53..9ce31188 100644 --- a/doc/wordlist +++ b/doc/wordlist @@ -316,6 +316,7 @@ NR NT NUMCUR NaN +NaNs Nachum Neacsu Neacsu's @@ -483,6 +484,7 @@ VT Versioning Vinschen WIPO +WONTFIX Walamazoo Wallin Watchpoint @@ -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; @@ -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. @@ -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 * |