From 6d1274d1d0c9b2f0feb109876c7c250951035a3c Mon Sep 17 00:00:00 2001 From: "Arnold D. Robbins" Date: Sun, 15 Nov 2020 11:54:52 +0200 Subject: Add test programs embedded in the doc. --- awklib/eg/test-programs/gen-float-table.awk | 59 +++++++++ awklib/eg/test-programs/gen-float-table.c | 60 +++++++++ awklib/eg/test-programs/gen-float-table.py | 42 ++++++ doc/ChangeLog | 5 + doc/gawk.texi | 187 ++++++++++++++++++++++++++- doc/gawktexi.in | 193 +++++++++++++++++++++++++++- 6 files changed, 536 insertions(+), 10 deletions(-) create mode 100644 awklib/eg/test-programs/gen-float-table.awk create mode 100644 awklib/eg/test-programs/gen-float-table.c create mode 100644 awklib/eg/test-programs/gen-float-table.py 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 +#include +#include + +#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/doc/ChangeLog b/doc/ChangeLog index 224cddf5..bf89490e 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,8 @@ +2020-11-15 Arnold D. Robbins + + * gawktexi.in (Strange values): Add test programs inside + @ignore; extracted to example directory. + 2020-11-09 Arnold D. Robbins * gawktexi.in: Samll improvement in strange numbers section. diff --git a/doc/gawk.texi b/doc/gawk.texi index 30221b1c..7c855f0d 100644 --- a/doc/gawk.texi +++ b/doc/gawk.texi @@ -3136,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 @@ -33934,6 +33935,182 @@ When such values are generated, @command{gawk} prints them as either 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 +#include +#include + +#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 98e25de6..1822bc0b 100644 --- a/doc/gawktexi.in +++ b/doc/gawktexi.in @@ -3046,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 @@ -32900,6 +32901,188 @@ When such values are generated, @command{gawk} prints them as either 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 +#include +#include + +#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 -- cgit v1.2.1