diff options
-rw-r--r-- | arith.c | 2 | ||||
-rwxr-xr-x | configure | 32 | ||||
-rw-r--r-- | stream.c | 16 | ||||
-rw-r--r-- | txr.1 | 57 |
4 files changed, 99 insertions, 8 deletions
@@ -2282,9 +2282,11 @@ void arith_init(void) reg_varl(intern(lit("*flo-min*"), user_package), flo(DBL_MIN)); reg_varl(intern(lit("*flo-epsilon*"), user_package), flo(DBL_EPSILON)); reg_varl(intern(lit("flo-dig"), user_package), num_fast(DBL_DIG)); + reg_varl(intern(lit("flo-max-dig"), user_package), num_fast(FLO_MAX_DIG)); reg_varl(intern(lit("flo-max"), user_package), flo(DBL_MAX)); reg_varl(intern(lit("flo-min"), user_package), flo(DBL_MIN)); reg_varl(intern(lit("flo-epsilon"), user_package), flo(DBL_EPSILON)); + #ifndef M_PI #define M_PI 3.14159265358979323846 #endif @@ -112,6 +112,7 @@ lit_align= extra_debugging= debug_support=y gen_gc=y +have_dbl_decimal_dig= have_unistd= have_sys_time= have_syslog= @@ -1265,6 +1266,37 @@ printf '"%s"\n' "$inline" printf "#define INLINE $inline\n" >> $config_h # +# DBL_DECIMAL_DIG +# + +printf "Checking for DBL_DECIMAL_DIG ... " + +for try_sym in DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__ ; do + cat > conftest.c <<! +#include <float.h> + +#ifndef $try_sym +#error $try_sym not defined +#else +int main(void) +{ + return 0; +} +#endif +! + if conftest ; then + printf "yes (%s)\n" $try_sym + printf "#define FLO_MAX_DIG $try_sym\n" >> $config_h + have_dbl_decimal_dig=y + fi +done + +if ! [ $have_dbl_decimal_dig ] ; then + printf "no\n" + printf "#define FLO_MAX_DIG (DBL_DIG + 2)\n" >> $config_h +fi + +# # Valgrind # @@ -63,6 +63,8 @@ val stdin_s, stdout_s, stddebug_s, stderr_s, stdnull_s; +val print_flo_precision_s; + val from_start_k, from_current_k, from_end_k; val real_time_k, name_k, fd_k; val format_s; @@ -2183,7 +2185,7 @@ val formatv(val stream_in, val fmtstr, struct args *al) } state = vf_init, saved_state = vf_init; int width = 0, precision = 0, precision_p = 0, digits = 0, lt = 0, neg = 0; enum align align = al_right; - int sign = 0, zeropad = 0; + int sign = 0, zeropad = 0, dfl_precision = 0; cnum value; cnum arg_ix = 0; @@ -2453,8 +2455,12 @@ val formatv(val stream_in, val fmtstr, struct args *al) } goto output_num; case FLNUM: - if (!precision_p) - precision = DBL_DIG; + if (!precision_p) { + if (!dfl_precision) + dfl_precision = c_num(cdr(lookup_var(nil, + print_flo_precision_s))); + precision = dfl_precision; + } if (precision > 500) uw_throwf(error_s, lit("excessive precision in format: ~s\n"), @@ -3270,6 +3276,10 @@ void stream_init(void) reg_var(stdnull_s = intern(lit("*stdnull*"), user_package), make_null_stream()); + reg_var(print_flo_precision_s = intern(lit("*print-flo-precision*"), + user_package), + num_fast(DBL_DIG)); + #if HAVE_ISATTY if (isatty(fileno(stdin)) == 1) stream_set_prop(std_input, real_time_k, t); @@ -26385,6 +26385,15 @@ to a \*(TX floating-point number, and back to decimal, without a change in any o the digits. This holds regardless of the value of the number, provided that it does not exceed the floating-point range. +.coNP Variable @ flo-max-dig +.desc +This variable holds an integer representing the maximum number of +decimal digits required to capture the value of a floating-point number +such that the resulting decimal form will convert back to the same +floating-point number. See also the +.code *print-flo-precision* +variable. + .coNP Variables @ %pi% and @ %e% .desc These variables hold an approximation of the mathematical constants \(*p and e. @@ -30753,6 +30762,42 @@ the .code /dev/null device on Unix, but does not involve the operating system. +.coNP Special variable @ *print-flo-precision* +.desc +The +.code *print-flo-precision* +special variable holds the precision which applies when +floating-point values are converted to decimal text by the functions +.codn print , +.cond pprint , +.cond prinl , +.cond pprinl , +.code tostring +and +.codn tostringp . +It also applies when the +.code ~a +and +.code ~s +conversion specifiers of the +.code format +function are used for printing a floating-point value, and no precision +is specified. + +The default value of +.code *print-flo-precision* +is that of the +.code flo-dig +variable. + +Note: to print floating-point values in such a way that their values +can be precisely recovered from the printed representation, it is +recommended to override +.code *print-flo-precision* +to the value of the +.code flo-max-dig +variable. + .coNP Function @ format .synb .mets (format < stream-designator < format-string << format-arg *) @@ -30974,11 +31019,13 @@ When this specifier is used for floating-point values, the precision specifies the maximum number of total significant figures, which do not include any digits in the exponent, if one is printed. Numbers are printed in exponential notation if their magnitude is small, or else if their exponent exceeds their -precision. (If the precision is not specified, then it defaults to the -system-dependent number of digits in a floating point value, derived from the C -language -.code DBL_DIG -constant.) Floating point values which are integers are +precision. If the precision is not specified, then it is obtained from +the +.code *print-flo-precision* +special variable, whose default value is the same as that of the +.code flo-dig +variable. +Floating point values which are integers are printed without a trailing .code .0 (point zero). |