diff options
-rw-r--r-- | awk.h | 9 | ||||
-rw-r--r-- | awkgram.c | 334 | ||||
-rw-r--r-- | awkgram.y | 4 | ||||
-rw-r--r-- | eval.c | 7 | ||||
-rw-r--r-- | mpfr.c | 153 | ||||
-rw-r--r-- | test/Makefile.am | 24 | ||||
-rw-r--r-- | test/Makefile.in | 23 | ||||
-rw-r--r-- | test/mpfrexprange.awk | 7 | ||||
-rw-r--r-- | test/mpfrexprange.ok | 2 | ||||
-rw-r--r-- | test/mpfrieee.awk | 13 | ||||
-rw-r--r-- | test/mpfrieee.ok | 12 | ||||
-rw-r--r-- | test/mpfrnr.awk | 10 | ||||
-rw-r--r-- | test/mpfrnr.in | 3 | ||||
-rw-r--r-- | test/mpfrnr.ok | 1 | ||||
-rw-r--r-- | test/mpfrrnd.awk | 15 | ||||
-rw-r--r-- | test/mpfrrnd.ok | 10 |
16 files changed, 403 insertions, 224 deletions
@@ -623,7 +623,7 @@ typedef enum opcodeval { Op_indirect_func_call, Op_push, /* scalar variable */ - Op_push_arg, /* variable type (scalar or array) argument to built-in */ + Op_push_arg, /* variable type (scalar or array) argument to built-in */ Op_push_i, /* number, string */ Op_push_re, /* regex */ Op_push_array, @@ -1111,7 +1111,7 @@ extern mpfr_rnd_t RND_MODE; extern mpfr_t MNR; extern mpfr_t MFNR; extern mpz_t mpzval; -extern int do_subnormalize; /* IEEE 754 binary format emulation */ +extern int do_ieee_fmt; /* emulate IEEE 754 floating-point format */ #endif @@ -1215,7 +1215,7 @@ extern STACK_ITEM *stack_top; #define is_nonzero_num(n) (((n)->flags & MPFN) ? (! mpfr_zero_p((n)->mpg_numbr)) \ : ((n)->numbr != 0.0)) -#define SUBNORMALIZE(r, t) do_subnormalize ? mpfr_subnormalize(r, t, RND_MODE) : (void)0 +#define IEEE_FMT(r, t) do_ieee_fmt && format_ieee(r, t) #else #define get_number_ui(n) (unsigned long) (n)->numbr #define get_number_si(n) (long) (n)->numbr @@ -1423,8 +1423,6 @@ extern int strncasecmpmbs(const unsigned char *, extern void PUSH_CODE(INSTRUCTION *cp); extern INSTRUCTION *POP_CODE(void); extern void init_interpret(void); -extern int r_interpret(INSTRUCTION *); -extern int debug_interpret(INSTRUCTION *); extern int cmp_nodes(NODE *p1, NODE *p2); extern void set_IGNORECASE(void); extern void set_OFS(void); @@ -1526,6 +1524,7 @@ extern long getenv_long(const char *name); extern void set_PREC(void); extern void set_RNDMODE(void); #ifdef HAVE_MPFR +extern int format_ieee(mpfr_ptr, int); extern void mpg_update_var(NODE *); extern long mpg_set_var(NODE *); extern NODE *do_mpfr_and(int); @@ -2039,7 +2039,7 @@ yyreduce: { case 3: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 195 "awkgram.y" { rule = 0; @@ -2049,7 +2049,7 @@ yyreduce: case 5: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 201 "awkgram.y" { next_sourcefile(); @@ -2058,7 +2058,7 @@ yyreduce: case 6: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 205 "awkgram.y" { rule = 0; @@ -2072,7 +2072,7 @@ yyreduce: case 7: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 217 "awkgram.y" { (void) append_rule((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)])); @@ -2081,7 +2081,7 @@ yyreduce: case 8: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 221 "awkgram.y" { if (rule != Rule) { @@ -2097,7 +2097,7 @@ yyreduce: case 9: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 232 "awkgram.y" { in_function = NULL; @@ -2108,7 +2108,7 @@ yyreduce: case 10: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 238 "awkgram.y" { want_source = FALSE; @@ -2118,7 +2118,7 @@ yyreduce: case 11: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 246 "awkgram.y" { if (include_source((yyvsp[(1) - (1)])) < 0) @@ -2131,35 +2131,35 @@ yyreduce: case 12: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 254 "awkgram.y" { (yyval) = NULL; } break; case 13: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 256 "awkgram.y" { (yyval) = NULL; } break; case 14: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 261 "awkgram.y" { (yyval) = NULL; rule = Rule; } break; case 15: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 263 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); rule = Rule; } break; case 16: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 265 "awkgram.y" { INSTRUCTION *tp; @@ -2190,7 +2190,7 @@ yyreduce: case 17: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 291 "awkgram.y" { static int begin_seen = 0; @@ -2206,7 +2206,7 @@ yyreduce: case 18: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 302 "awkgram.y" { static int end_seen = 0; @@ -2222,7 +2222,7 @@ yyreduce: case 19: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 313 "awkgram.y" { (yyvsp[(1) - (1)])->in_rule = rule = BEGINFILE; @@ -2233,7 +2233,7 @@ yyreduce: case 20: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 319 "awkgram.y" { (yyvsp[(1) - (1)])->in_rule = rule = ENDFILE; @@ -2244,7 +2244,7 @@ yyreduce: case 21: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 328 "awkgram.y" { if ((yyvsp[(2) - (5)]) == NULL) @@ -2256,21 +2256,21 @@ yyreduce: case 22: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 338 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 23: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 340 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 24: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 342 "awkgram.y" { yyerror(_("`%s' is a built-in function, it cannot be redefined"), @@ -2281,14 +2281,14 @@ yyreduce: case 25: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 348 "awkgram.y" { (yyval) = (yyvsp[(2) - (2)]); } break; case 28: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 358 "awkgram.y" { (yyvsp[(1) - (6)])->source_file = source; @@ -2304,14 +2304,14 @@ yyreduce: case 29: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 376 "awkgram.y" { ++want_regexp; } break; case 30: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 378 "awkgram.y" { NODE *n, *exp; @@ -2345,21 +2345,21 @@ yyreduce: case 31: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 410 "awkgram.y" { bcfree((yyvsp[(1) - (1)])); } break; case 33: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 416 "awkgram.y" { (yyval) = NULL; } break; case 34: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 418 "awkgram.y" { if ((yyvsp[(2) - (2)]) == NULL) @@ -2377,28 +2377,28 @@ yyreduce: case 35: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 431 "awkgram.y" { (yyval) = NULL; } break; case 38: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 441 "awkgram.y" { (yyval) = NULL; } break; case 39: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 443 "awkgram.y" { (yyval) = (yyvsp[(2) - (3)]); } break; case 40: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 445 "awkgram.y" { if (do_pretty_print) @@ -2410,7 +2410,7 @@ yyreduce: case 41: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 452 "awkgram.y" { INSTRUCTION *dflt, *curr = NULL, *cexp, *cstmt; @@ -2505,7 +2505,7 @@ yyreduce: case 42: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 542 "awkgram.y" { /* @@ -2552,7 +2552,7 @@ yyreduce: case 43: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 584 "awkgram.y" { /* @@ -2599,7 +2599,7 @@ yyreduce: case 44: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 626 "awkgram.y" { INSTRUCTION *ip; @@ -2717,7 +2717,7 @@ regular_loop: case 45: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 739 "awkgram.y" { (yyval) = mk_for_loop((yyvsp[(1) - (12)]), (yyvsp[(3) - (12)]), (yyvsp[(6) - (12)]), (yyvsp[(9) - (12)]), (yyvsp[(12) - (12)])); @@ -2729,7 +2729,7 @@ regular_loop: case 46: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 746 "awkgram.y" { (yyval) = mk_for_loop((yyvsp[(1) - (11)]), (yyvsp[(3) - (11)]), (INSTRUCTION *) NULL, (yyvsp[(8) - (11)]), (yyvsp[(11) - (11)])); @@ -2741,7 +2741,7 @@ regular_loop: case 47: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 753 "awkgram.y" { if (do_pretty_print) @@ -2753,7 +2753,7 @@ regular_loop: case 48: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 763 "awkgram.y" { if (! break_allowed) @@ -2767,7 +2767,7 @@ regular_loop: case 49: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 772 "awkgram.y" { if (! continue_allowed) @@ -2781,7 +2781,7 @@ regular_loop: case 50: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 781 "awkgram.y" { /* if inside function (rule = 0), resolve context at run-time */ @@ -2795,7 +2795,7 @@ regular_loop: case 51: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 790 "awkgram.y" { if (do_traditional) @@ -2815,7 +2815,7 @@ regular_loop: case 52: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 805 "awkgram.y" { /* Initialize the two possible jump targets, the actual target @@ -2835,7 +2835,7 @@ regular_loop: case 53: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 820 "awkgram.y" { if (! in_function) @@ -2845,7 +2845,7 @@ regular_loop: case 54: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 823 "awkgram.y" { if ((yyvsp[(3) - (4)]) == NULL) { @@ -2871,14 +2871,14 @@ regular_loop: case 56: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 855 "awkgram.y" { in_print = TRUE; in_parens = 0; } break; case 57: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 856 "awkgram.y" { /* @@ -2977,14 +2977,14 @@ regular_loop: case 58: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 950 "awkgram.y" { sub_counter = 0; } break; case 59: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 951 "awkgram.y" { char *arr = (yyvsp[(2) - (4)])->lextok; @@ -3014,7 +3014,7 @@ regular_loop: case 60: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 980 "awkgram.y" { static short warned = FALSE; @@ -3038,35 +3038,35 @@ regular_loop: case 61: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 999 "awkgram.y" { (yyval) = optimize_assignment((yyvsp[(1) - (1)])); } break; case 62: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1004 "awkgram.y" { (yyval) = NULL; } break; case 63: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1006 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 64: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1011 "awkgram.y" { (yyval) = NULL; } break; case 65: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1013 "awkgram.y" { if ((yyvsp[(1) - (2)]) == NULL) @@ -3078,14 +3078,14 @@ regular_loop: case 66: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1020 "awkgram.y" { (yyval) = NULL; } break; case 67: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1025 "awkgram.y" { INSTRUCTION *casestmt = (yyvsp[(5) - (5)]); @@ -3102,7 +3102,7 @@ regular_loop: case 68: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1037 "awkgram.y" { INSTRUCTION *casestmt = (yyvsp[(4) - (4)]); @@ -3118,14 +3118,14 @@ regular_loop: case 69: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1051 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 70: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1053 "awkgram.y" { NODE *n = (yyvsp[(2) - (2)])->memory; @@ -3138,7 +3138,7 @@ regular_loop: case 71: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1061 "awkgram.y" { bcfree((yyvsp[(1) - (2)])); @@ -3148,14 +3148,14 @@ regular_loop: case 72: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1066 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 73: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1068 "awkgram.y" { (yyvsp[(1) - (1)])->opcode = Op_push_re; @@ -3165,21 +3165,21 @@ regular_loop: case 74: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1076 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 75: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1078 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 77: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1088 "awkgram.y" { (yyval) = (yyvsp[(2) - (3)]); @@ -3188,7 +3188,7 @@ regular_loop: case 78: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1095 "awkgram.y" { in_print = FALSE; @@ -3199,14 +3199,14 @@ regular_loop: case 79: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1100 "awkgram.y" { in_print = FALSE; in_parens = 0; } break; case 80: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1101 "awkgram.y" { if ((yyvsp[(1) - (3)])->redir_type == redirect_twoway @@ -3219,7 +3219,7 @@ regular_loop: case 81: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1112 "awkgram.y" { (yyval) = mk_condition((yyvsp[(3) - (6)]), (yyvsp[(1) - (6)]), (yyvsp[(6) - (6)]), NULL, NULL); @@ -3228,7 +3228,7 @@ regular_loop: case 82: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1117 "awkgram.y" { (yyval) = mk_condition((yyvsp[(3) - (9)]), (yyvsp[(1) - (9)]), (yyvsp[(6) - (9)]), (yyvsp[(7) - (9)]), (yyvsp[(9) - (9)])); @@ -3237,14 +3237,14 @@ regular_loop: case 87: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1134 "awkgram.y" { (yyval) = NULL; } break; case 88: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1136 "awkgram.y" { bcfree((yyvsp[(1) - (2)])); @@ -3254,21 +3254,21 @@ regular_loop: case 89: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1144 "awkgram.y" { (yyval) = NULL; } break; case 90: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1146 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]) ; } break; case 91: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1151 "awkgram.y" { (yyvsp[(1) - (1)])->param_count = 0; @@ -3278,7 +3278,7 @@ regular_loop: case 92: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1156 "awkgram.y" { (yyvsp[(3) - (3)])->param_count = (yyvsp[(1) - (3)])->lasti->param_count + 1; @@ -3289,63 +3289,63 @@ regular_loop: case 93: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1162 "awkgram.y" { (yyval) = NULL; } break; case 94: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1164 "awkgram.y" { (yyval) = (yyvsp[(1) - (2)]); } break; case 95: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1166 "awkgram.y" { (yyval) = (yyvsp[(1) - (3)]); } break; case 96: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1172 "awkgram.y" { (yyval) = NULL; } break; case 97: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1174 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 98: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1179 "awkgram.y" { (yyval) = NULL; } break; case 99: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1181 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 100: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1186 "awkgram.y" { (yyval) = mk_expression_list(NULL, (yyvsp[(1) - (1)])); } break; case 101: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1188 "awkgram.y" { (yyval) = mk_expression_list((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)])); @@ -3355,35 +3355,35 @@ regular_loop: case 102: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1193 "awkgram.y" { (yyval) = NULL; } break; case 103: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1195 "awkgram.y" { (yyval) = NULL; } break; case 104: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1197 "awkgram.y" { (yyval) = NULL; } break; case 105: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1199 "awkgram.y" { (yyval) = NULL; } break; case 106: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1205 "awkgram.y" { if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == Op_match_rec) @@ -3395,21 +3395,21 @@ regular_loop: case 107: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1212 "awkgram.y" { (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 108: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1214 "awkgram.y" { (yyval) = mk_boolean((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 109: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1216 "awkgram.y" { if ((yyvsp[(1) - (3)])->lasti->opcode == Op_match_rec) @@ -3430,7 +3430,7 @@ regular_loop: case 110: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1232 "awkgram.y" { if (do_lint_old) @@ -3445,7 +3445,7 @@ regular_loop: case 111: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1242 "awkgram.y" { if (do_lint && (yyvsp[(3) - (3)])->lasti->opcode == Op_match_rec) @@ -3457,35 +3457,35 @@ regular_loop: case 112: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1249 "awkgram.y" { (yyval) = mk_condition((yyvsp[(1) - (5)]), (yyvsp[(2) - (5)]), (yyvsp[(3) - (5)]), (yyvsp[(4) - (5)]), (yyvsp[(5) - (5)])); } break; case 113: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1251 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 114: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1256 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 115: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1258 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 116: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1260 "awkgram.y" { (yyvsp[(2) - (2)])->opcode = Op_assign_quotient; @@ -3495,49 +3495,49 @@ regular_loop: case 117: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1268 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 118: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1270 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 119: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1275 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 120: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1277 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 121: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1282 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 122: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1284 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 123: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1286 "awkgram.y" { int count = 2; @@ -3589,49 +3589,49 @@ regular_loop: case 125: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1338 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 126: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1340 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 127: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1342 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 128: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1344 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 129: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1346 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 130: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1348 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 131: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1350 "awkgram.y" { /* @@ -3659,7 +3659,7 @@ regular_loop: case 132: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1373 "awkgram.y" { (yyvsp[(2) - (2)])->opcode = Op_postincrement; @@ -3669,7 +3669,7 @@ regular_loop: case 133: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1378 "awkgram.y" { (yyvsp[(2) - (2)])->opcode = Op_postdecrement; @@ -3679,7 +3679,7 @@ regular_loop: case 134: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1383 "awkgram.y" { if (do_lint_old) { @@ -3704,7 +3704,7 @@ regular_loop: case 135: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1408 "awkgram.y" { (yyval) = mk_getline((yyvsp[(3) - (4)]), (yyvsp[(4) - (4)]), (yyvsp[(1) - (4)]), (yyvsp[(2) - (4)])->redir_type); @@ -3714,49 +3714,49 @@ regular_loop: case 136: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1414 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 137: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1416 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 138: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1418 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 139: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1420 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 140: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1422 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 141: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1424 "awkgram.y" { (yyval) = mk_binary((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)]), (yyvsp[(2) - (3)])); } break; case 142: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1429 "awkgram.y" { (yyval) = list_create((yyvsp[(1) - (1)])); @@ -3765,7 +3765,7 @@ regular_loop: case 143: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1433 "awkgram.y" { if ((yyvsp[(2) - (2)])->opcode == Op_match_rec) { @@ -3802,14 +3802,14 @@ regular_loop: case 144: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1465 "awkgram.y" { (yyval) = (yyvsp[(2) - (3)]); } break; case 145: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1467 "awkgram.y" { (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)])); @@ -3820,7 +3820,7 @@ regular_loop: case 146: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1473 "awkgram.y" { (yyval) = snode((yyvsp[(3) - (4)]), (yyvsp[(1) - (4)])); @@ -3831,7 +3831,7 @@ regular_loop: case 147: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1479 "awkgram.y" { static short warned1 = FALSE; @@ -3849,7 +3849,7 @@ regular_loop: case 150: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1494 "awkgram.y" { (yyvsp[(1) - (2)])->opcode = Op_preincrement; @@ -3859,7 +3859,7 @@ regular_loop: case 151: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1499 "awkgram.y" { (yyvsp[(1) - (2)])->opcode = Op_predecrement; @@ -3869,7 +3869,7 @@ regular_loop: case 152: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1504 "awkgram.y" { (yyval) = list_create((yyvsp[(1) - (1)])); @@ -3878,7 +3878,7 @@ regular_loop: case 153: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1508 "awkgram.y" { (yyval) = list_create((yyvsp[(1) - (1)])); @@ -3887,7 +3887,7 @@ regular_loop: case 154: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1512 "awkgram.y" { if ((yyvsp[(2) - (2)])->lasti->opcode == Op_push_i @@ -3909,7 +3909,7 @@ regular_loop: case 155: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1529 "awkgram.y" { /* @@ -3924,7 +3924,7 @@ regular_loop: case 156: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1542 "awkgram.y" { func_use((yyvsp[(1) - (1)])->lasti->func_name, FUNC_USE); @@ -3934,7 +3934,7 @@ regular_loop: case 157: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1547 "awkgram.y" { /* indirect function call */ @@ -3972,7 +3972,7 @@ regular_loop: case 158: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1583 "awkgram.y" { param_sanity((yyvsp[(3) - (4)])); @@ -3991,42 +3991,42 @@ regular_loop: case 159: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1600 "awkgram.y" { (yyval) = NULL; } break; case 160: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1602 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 161: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1607 "awkgram.y" { (yyval) = NULL; } break; case 162: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1609 "awkgram.y" { (yyval) = (yyvsp[(1) - (2)]); } break; case 163: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1614 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 164: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1616 "awkgram.y" { (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)])); @@ -4035,7 +4035,7 @@ regular_loop: case 165: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1623 "awkgram.y" { INSTRUCTION *ip = (yyvsp[(1) - (1)])->lasti; @@ -4054,7 +4054,7 @@ regular_loop: case 166: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1640 "awkgram.y" { INSTRUCTION *t = (yyvsp[(2) - (3)]); @@ -4073,14 +4073,14 @@ regular_loop: case 167: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1657 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); } break; case 168: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1659 "awkgram.y" { (yyval) = list_merge((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)])); @@ -4089,14 +4089,14 @@ regular_loop: case 169: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1666 "awkgram.y" { (yyval) = (yyvsp[(1) - (2)]); } break; case 170: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1671 "awkgram.y" { char *var_name = (yyvsp[(1) - (1)])->lextok; @@ -4109,7 +4109,7 @@ regular_loop: case 171: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1679 "awkgram.y" { char *arr = (yyvsp[(1) - (2)])->lextok; @@ -4121,7 +4121,7 @@ regular_loop: case 172: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1689 "awkgram.y" { INSTRUCTION *ip = (yyvsp[(1) - (1)])->nexti; @@ -4138,7 +4138,7 @@ regular_loop: case 173: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1701 "awkgram.y" { (yyval) = list_append((yyvsp[(2) - (3)]), (yyvsp[(1) - (3)])); @@ -4149,7 +4149,7 @@ regular_loop: case 174: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1710 "awkgram.y" { (yyvsp[(1) - (1)])->opcode = Op_postincrement; @@ -4158,7 +4158,7 @@ regular_loop: case 175: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1714 "awkgram.y" { (yyvsp[(1) - (1)])->opcode = Op_postdecrement; @@ -4167,49 +4167,49 @@ regular_loop: case 176: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1717 "awkgram.y" { (yyval) = NULL; } break; case 178: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1725 "awkgram.y" { yyerrok; } break; case 179: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1729 "awkgram.y" { yyerrok; } break; case 182: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1738 "awkgram.y" { yyerrok; } break; case 183: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1742 "awkgram.y" { (yyval) = (yyvsp[(1) - (1)]); yyerrok; } break; case 184: -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 1746 "awkgram.y" { yyerrok; } break; -/* Line 1806 of yacc.c */ +/* Line 1821 of yacc.c */ #line 4226 "awkgram.c" default: break; } @@ -4606,7 +4606,7 @@ negate_num(NODE *n) if (n->flags & MPFN) { int tval; tval = mpfr_setsign(n->mpg_numbr, n->mpg_numbr, TRUE, RND_MODE); - SUBNORMALIZE(n->mpg_numbr, tval); + IEEE_FMT(n->mpg_numbr, tval); } else #endif n->numbr = -n->numbr; @@ -6086,7 +6086,7 @@ retry: r = mpg_node(); tval = mpfr_strtofr(r->mpg_numbr, tokstart, NULL, base, RND_MODE); errno = 0; - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); yylval->memory = r; return lasttok = YNUMBER; } @@ -1909,7 +1909,7 @@ negate_num(NODE *n) if (n->flags & MPFN) { int tval; tval = mpfr_setsign(n->mpg_numbr, n->mpg_numbr, TRUE, RND_MODE); - SUBNORMALIZE(n->mpg_numbr, tval); + IEEE_FMT(n->mpg_numbr, tval); } else #endif n->numbr = -n->numbr; @@ -3389,7 +3389,7 @@ retry: r = mpg_node(); tval = mpfr_strtofr(r->mpg_numbr, tokstart, NULL, base, RND_MODE); errno = 0; - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); yylval->memory = r; return lasttok = YNUMBER; } @@ -1433,7 +1433,8 @@ free_arrayfor(NODE *r) } -/* unwind_stack --- pop items off the run-time stack; +/* + * unwind_stack --- pop items off the run-time stack; * 'n' is the # of items left in the stack. */ @@ -1623,7 +1624,8 @@ POP_CODE() } -/* Implementation of BEGINFILE and ENDFILE requires saving an execution +/* + * Implementation of BEGINFILE and ENDFILE requires saving an execution * state and the ability to return to that state. The state is * defined by the instruction triggering the BEGINFILE/ENDFILE rule, the * run-time stack, the rule and the source file. The source line is available in @@ -1745,7 +1747,6 @@ void init_interpret() { long newval; - int i = 0; if ((newval = getenv_long("GAWK_STACKSIZE")) > 0) STACK_SIZE = newval; @@ -27,11 +27,11 @@ #ifdef HAVE_MPFR -#if __GNU_MP_VERSION < 5 +#if !defined(__GNU_MP_VERSION) || __GNU_MP_VERSION < 5 typedef unsigned long int mp_bitcnt_t; #endif -#if MPFR_VERSION_MAJOR < 3 +#if !defined(MPFR_VERSION_MAJOR) || MPFR_VERSION_MAJOR < 3 typedef mp_exp_t mpfr_exp_t; #endif @@ -40,7 +40,7 @@ extern NODE **fmt_list; /* declared in eval.c */ mpz_t mpzval; /* GMP integer type; used as temporary in many places */ mpfr_t MNR; mpfr_t MFNR; -int do_subnormalize; /* emulate subnormal number arithmetic */ +int do_ieee_fmt; /* IEEE-754 floating-point emulation */ static mpfr_rnd_t get_rnd_mode(const char rmode); static NODE *get_bit_ops(NODE **p1, NODE **p2, const char *op); @@ -48,6 +48,8 @@ static NODE *mpg_force_number(NODE *n); static NODE *mpg_make_number(double); static NODE *mpg_format_val(const char *format, int index, NODE *s); static int mpg_interpret(INSTRUCTION **cp); +static mpfr_exp_t min_exp = MPFR_EMIN_DEFAULT; +static mpfr_exp_t max_exp = MPFR_EMAX_DEFAULT; /* init_mpfr --- set up MPFR related variables */ @@ -66,7 +68,7 @@ init_mpfr(const char *rmode) mpfr_set_d(MNR, 0.0, RND_MODE); mpfr_init(MFNR); mpfr_set_d(MFNR, 0.0, RND_MODE); - do_subnormalize = FALSE; + do_ieee_fmt = FALSE; register_exec_hook(mpg_interpret, 0); } @@ -103,7 +105,7 @@ mpg_make_number(double x) r = mpg_node(); tval = mpfr_set_d(r->mpg_numbr, x, RND_MODE); - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); return r; } @@ -150,7 +152,7 @@ mpg_force_number(NODE *n) errno = 0; tval = mpfr_strtofr(n->mpg_numbr, cp, & ptr, base, RND_MODE); - SUBNORMALIZE(n->mpg_numbr, tval); + IEEE_FMT(n->mpg_numbr, tval); /* trailing space is OK for NUMBER */ while (isspace((unsigned char) *ptr)) @@ -201,7 +203,7 @@ mpg_format_val(const char *format, int index, NODE *s) /* * mpg_update_var --- update NR or FNR. - * NR_node(mpfr_t) = MNR(mpfr_t) * LONG_MAX + NR(long) + * NR_node->var_value(mpfr_t) = MNR(mpfr_t) * LONG_MAX + NR(long) */ void @@ -309,18 +311,24 @@ set_PREC() if ((val->flags & (STRING|NUMBER)) == STRING) { int i, j; - /* emulate binary IEEE 754 arithmetic */ + /* emulate IEEE-754 binary format */ for (i = 0, j = sizeof(ieee_fmts)/sizeof(ieee_fmts[0]); i < j; i++) { - if (strcmp(ieee_fmts[i].name, val->stptr) == 0) + if (strcasecmp(ieee_fmts[i].name, val->stptr) == 0) break; } if (i < j) { prec = ieee_fmts[i].precision; - mpfr_set_emax(ieee_fmts[i].emax); - mpfr_set_emin(ieee_fmts[i].emin); - do_subnormalize = TRUE; + + /* + * We *DO NOT* change the MPFR exponent range using + * mpfr_set_{emin, emax} here. See format_ieee() for details. + */ + max_exp = ieee_fmts[i].emax; + min_exp = ieee_fmts[i].emin; + + do_ieee_fmt = TRUE; } } @@ -329,9 +337,10 @@ set_PREC() prec = get_number_si(val); if (prec < MPFR_PREC_MIN || prec > MPFR_PREC_MAX) { force_string(val); - warning(_("PREC value `%.*s' is invalid"), (int)val->stlen, val->stptr); + warning(_("PREC value `%.*s' is invalid"), (int) val->stlen, val->stptr); prec = 0; - } + } else + do_ieee_fmt = FALSE; } if (prec > 0) { @@ -359,7 +368,7 @@ get_rnd_mode(const char rmode) case 'D': case 'd': return MPFR_RNDD; /* round toward minus infinity */ -#ifdef MPFR_RNDA +#if defined(MPFR_VERSION_MAJOR) && MPFR_VERSION_MAJOR > 2 case 'A': case 'a': return MPFR_RNDA; /* round away from zero */ @@ -385,10 +394,56 @@ set_RNDMODE() mpfr_set_default_rounding_mode(rnd); RND_MODE = rnd; } else - warning(_("RNDMODE value `%.*s' is invalid"), (int)n->stlen, n->stptr); + warning(_("RNDMODE value `%.*s' is invalid"), (int) n->stlen, n->stptr); } } + +/* format_ieee --- make sure a number follows IEEE-754 floating-point standard */ + +int +format_ieee(mpfr_ptr x, int tval) +{ + /* + * The MPFR doc says that it's our responsibility to make sure all numbers + * including those previously created are in range after we've changed the + * exponent range. Most MPFR operations and functions requires + * the input arguments to have exponents within the current exponent range. + * Any argument outside the range results in a MPFR assertion failure + * like this: + * + * $] gawk -M 'BEGIN { x=1.0e-10000; print x+0; PREC="double"; print x+0}' + * 1e-10000 + * init2.c:52: MPFR assertion failed .... + * + * A "naive" approach would be to keep track of the ternary state and + * the rounding mode for each number, and make sure it is in the current + * exponent range (using mpfr_check_range) before using it in an + * operation or function. Instead, we adopt the following strategy. + * + * When gawk starts, the exponent range is the MPFR default + * [MPFR_EMIN_DEFAULT, MPFR_EMAX_DEFAULT]. Any number that gawk + * creates must have exponent in this range (excluding infinities, NANs and zeros). + * Each MPFR operation or function is performed with this default exponent + * range. + * + * When emulating IEEE-754 format, the exponents are *temporarily* changed, + * mpfr_check_range is called to make sure the number is in the new range, + * and mpfr_subnormalize is used to round following the rules of subnormal + * arithmetic. The exponent range is then *restored* to the original value + * [MPFR_EMIN_DEFAULT, MPFR_EMAX_DEFAULT]. + */ + + (void) mpfr_set_emin(min_exp); + (void) mpfr_set_emax(max_exp); + tval = mpfr_check_range(x, tval, RND_MODE); + tval = mpfr_subnormalize(x, tval, RND_MODE); + (void) mpfr_set_emin(MPFR_EMIN_DEFAULT); + (void) mpfr_set_emax(MPFR_EMAX_DEFAULT); + return tval; +} + + /* get_bit_ops --- get the numeric operands of a binary function */ static NODE * @@ -486,7 +541,7 @@ do_mpfr_atan2(int nargs) res = mpg_node(); /* See MPFR documentation for handling of special values like +inf as an argument */ tval = mpfr_atan2(res->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, RND_MODE); - SUBNORMALIZE(res->mpg_numbr, tval); + IEEE_FMT(res->mpg_numbr, tval); DEREF(t1); DEREF(t2); @@ -539,7 +594,7 @@ if (do_lint && (tmp->flags & (NUMCUR|NUMBER)) == 0) \ force_number(tmp); \ res = mpg_node(); \ tval = mpfr_##X(res->mpg_numbr, tmp->mpg_numbr, RND_MODE); \ -SUBNORMALIZE(res->mpg_numbr, tval); \ +IEEE_FMT(res->mpg_numbr, tval); \ DEREF(tmp); \ return res @@ -699,7 +754,7 @@ do_mpfr_strtonum(int nargs) tval = mpfr_set(r->mpg_numbr, tmp->mpg_numbr, RND_MODE); } - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); DEREF(tmp); return r; } @@ -754,7 +809,7 @@ do_mpfr_rand(int nargs ATTRIBUTE_UNUSED) } res = mpg_node(); tval = mpfr_urandomb(res->mpg_numbr, state); - SUBNORMALIZE(res->mpg_numbr, tval); + IEEE_FMT(res->mpg_numbr, tval); return res; } @@ -778,7 +833,7 @@ do_mpfr_srand(int nargs) res = mpg_node(); tval = mpfr_set_z(res->mpg_numbr, seed, RND_MODE); /* previous seed */ - SUBNORMALIZE(res->mpg_numbr, tval); + IEEE_FMT(res->mpg_numbr, tval); if (nargs == 0) mpz_set_ui(seed, (unsigned long) time((time_t *) 0)); @@ -823,7 +878,7 @@ plus: t1 = TOP_NUMBER(); r = mpg_node(); tval = mpfr_add(r->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, RND_MODE); - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); DEREF(t1); if (op == Op_plus) DEREF(t2); @@ -839,7 +894,7 @@ minus: t1 = TOP_NUMBER(); r = mpg_node(); tval = mpfr_sub(r->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, RND_MODE); - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); DEREF(t1); if (op == Op_minus) DEREF(t2); @@ -855,7 +910,7 @@ times: t1 = TOP_NUMBER(); r = mpg_node(); tval = mpfr_mul(r->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, RND_MODE); - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); DEREF(t1); if (op == Op_times) DEREF(t2); @@ -871,7 +926,7 @@ exp: t1 = TOP_NUMBER(); r = mpg_node(); tval = mpfr_pow(r->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, RND_MODE); - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); DEREF(t1); if (op == Op_exp) DEREF(t2); @@ -887,7 +942,7 @@ quotient: t1 = TOP_NUMBER(); r = mpg_node(); tval = mpfr_div(r->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, RND_MODE); - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); DEREF(t1); if (op == Op_quotient) DEREF(t2); @@ -903,7 +958,7 @@ mod: t1 = TOP_NUMBER(); r = mpg_node(); tval = mpfr_fmod(r->mpg_numbr, t1->mpg_numbr, t2->mpg_numbr, RND_MODE); - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); DEREF(t1); if (op == Op_mod) DEREF(t2); @@ -916,17 +971,26 @@ mod: lhs = TOP_ADDRESS(); t1 = *lhs; force_number(t1); - if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) { + +#if 0 + /* + * The optimizations for fixed precision do not always + * work the same way in arbitrary precision. With this optimization on, + * gawk -M 'BEGIN { PREC=53; i=2^53; PREC=113; ++i; print i}' + * prints 2^53 instead of 2^53+1. + */ + + if (t1->valref == 1 && t1->flags == (MALLOC|MPFN|NUMCUR|NUMBER)) { /* optimization */ tval = mpfr_add_d(t1->mpg_numbr, t1->mpg_numbr, x, RND_MODE); - SUBNORMALIZE(t1->mpg_numbr, tval); + IEEE_FMT(t1->mpg_numbr, tval); r = t1; - } else { - r = *lhs = mpg_node(); - tval = mpfr_add_d(r->mpg_numbr, t1->mpg_numbr, x, RND_MODE); - SUBNORMALIZE(r->mpg_numbr, tval); - unref(t1); } +#endif + r = *lhs = mpg_node(); + tval = mpfr_add_d(r->mpg_numbr, t1->mpg_numbr, x, RND_MODE); + IEEE_FMT(r->mpg_numbr, tval); + unref(t1); UPREF(r); REPLACE(r); break; @@ -939,17 +1003,11 @@ mod: force_number(t1); r = mpg_node(); tval = mpfr_set(r->mpg_numbr, t1->mpg_numbr, RND_MODE); /* r = t1 */ - SUBNORMALIZE(r->mpg_numbr, tval); - if (t1->valref == 1 && t1->flags == (MALLOC|NUMCUR|NUMBER)) { - /* optimization */ - tval = mpfr_add_d(t1->mpg_numbr, t1->mpg_numbr, x, RND_MODE); - SUBNORMALIZE(t1->mpg_numbr, tval); - } else { - t2 = *lhs = mpg_node(); - tval = mpfr_add_d(t2->mpg_numbr, t1->mpg_numbr, x, RND_MODE); - SUBNORMALIZE(t2->mpg_numbr, tval); - unref(t1); - } + IEEE_FMT(r->mpg_numbr, tval); + t2 = *lhs = mpg_node(); + tval = mpfr_add_d(t2->mpg_numbr, t1->mpg_numbr, x, RND_MODE); + IEEE_FMT(t2->mpg_numbr, tval); + unref(t1); REPLACE(r); break; @@ -958,7 +1016,7 @@ mod: r = mpg_node(); mpfr_set(r->mpg_numbr, t1->mpg_numbr, RND_MODE); /* r = t1 */ tval = mpfr_neg(r->mpg_numbr, r->mpg_numbr, RND_MODE); /* change sign */ - SUBNORMALIZE(r->mpg_numbr, tval); + IEEE_FMT(r->mpg_numbr, tval); DEREF(t1); REPLACE(r); break; @@ -999,7 +1057,8 @@ mod: default: cant_happen(); } - SUBNORMALIZE(r->mpg_numbr, tval); + + IEEE_FMT(r->mpg_numbr, tval); DEREF(t2); unref(*lhs); diff --git a/test/Makefile.am b/test/Makefile.am index f81bc8ec..bc174fb8 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -846,6 +846,8 @@ INET_TESTS = inetdayu inetdayt inetechu inetecht MACHINE_TESTS = double1 double2 fmtspcl intformat +MPFR_TESTS = mpfrnr mpfrrnd mpfrieee mpfrexprange + LOCALE_CHARSET_TESTS = \ asort asorti fmttest fnarydel fnparydl lc_num1 mbfw1 \ mbprintf1 mbprintf2 mbprintf3 rebt8b2 rtlenmb sort1 sprintfc @@ -906,6 +908,8 @@ inet: inetmesg $(INET_TESTS) machine-tests: $(MACHINE_TESTS) +mpfr-tests: $(MPFR_TESTS) + msg:: @echo '' @echo 'Any output from "cmp" is bad news, although some differences' @@ -1451,6 +1455,26 @@ rri1:: AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ +mpfrieee: + @echo $@ + @$(AWK) -M -vPREC=double -f $(srcdir)/$@.awk > _$@ 2>&1 + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + +mpfrexprange: + @echo $@ + @$(AWK) -M -vPREC=53 -f $(srcdir)/$@.awk > _$@ 2>&1 + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + +mpfrrnd: + @echo $@ + @$(AWK) -M -vPREC=53 -f $(srcdir)/$@.awk > _$@ 2>&1 + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + +mpfrnr: + @echo $@ + @$(AWK) -M -vPREC=113 -f $(srcdir)/$@.awk $(srcdir)/$@.in > _$@ + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + # Targets generated for other tests: include Maketests diff --git a/test/Makefile.in b/test/Makefile.in index 96f4a20f..7a88e836 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -1029,6 +1029,7 @@ GAWK_EXT_TESTS = \ EXTRA_TESTS = inftest regtest INET_TESTS = inetdayu inetdayt inetechu inetecht MACHINE_TESTS = double1 double2 fmtspcl intformat +MPFR_TESTS = mpfrnr mpfrrnd mpfrieee mpfrexprange LOCALE_CHARSET_TESTS = \ asort asorti fmttest fnarydel fnparydl lc_num1 mbfw1 \ mbprintf1 mbprintf2 mbprintf3 rebt8b2 rtlenmb sort1 sprintfc @@ -1260,6 +1261,8 @@ inet: inetmesg $(INET_TESTS) machine-tests: $(MACHINE_TESTS) +mpfr-tests: $(MPFR_TESTS) + msg:: @echo '' @echo 'Any output from "cmp" is bad news, although some differences' @@ -1802,6 +1805,26 @@ rri1:: @[ -z "$$GAWKLOCALE" ] && GAWKLOCALE=en_US.UTF-8; \ AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + +mpfrieee: + @echo $@ + @$(AWK) -M -vPREC=double -f $(srcdir)/$@.awk > _$@ 2>&1 + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + +mpfrexprange: + @echo $@ + @$(AWK) -M -vPREC=53 -f $(srcdir)/$@.awk > _$@ 2>&1 + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + +mpfrrnd: + @echo $@ + @$(AWK) -M -vPREC=53 -f $(srcdir)/$@.awk > _$@ 2>&1 + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + +mpfrnr: + @echo $@ + @$(AWK) -M -vPREC=113 -f $(srcdir)/$@.awk $(srcdir)/$@.in > _$@ + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ Gt-dummy: # file Maketests, generated from Makefile.am by the Gentests program addcomma: diff --git a/test/mpfrexprange.awk b/test/mpfrexprange.awk new file mode 100644 index 00000000..68e95a39 --- /dev/null +++ b/test/mpfrexprange.awk @@ -0,0 +1,7 @@ +# test change of allowed exponent range +BEGIN { + x=1.0e-10000 + print x+0 + PREC="double" + print x+0 +} diff --git a/test/mpfrexprange.ok b/test/mpfrexprange.ok new file mode 100644 index 00000000..4700ee22 --- /dev/null +++ b/test/mpfrexprange.ok @@ -0,0 +1,2 @@ +1e-10000 +0 diff --git a/test/mpfrieee.awk b/test/mpfrieee.awk new file mode 100644 index 00000000..dc6e120d --- /dev/null +++ b/test/mpfrieee.awk @@ -0,0 +1,13 @@ +# Test IEEE-754 binary double format +BEGIN { + x = 1.0e-320 + i = 0 + while (x > 0) { + printf("%.15e\n", x) + x /= 2 + + # terminate early when the test is going to fail. + if (++i > 50) + break + } +} diff --git a/test/mpfrieee.ok b/test/mpfrieee.ok new file mode 100644 index 00000000..e88f5c79 --- /dev/null +++ b/test/mpfrieee.ok @@ -0,0 +1,12 @@ +9.999888671826830e-321 +4.999944335913415e-321 +2.499972167956708e-321 +1.249986083978354e-321 +6.225227137599706e-322 +3.112613568799853e-322 +1.581010066691989e-322 +7.905050333459945e-323 +3.952525166729972e-323 +1.976262583364986e-323 +9.881312916824931e-324 +4.940656458412465e-324 diff --git a/test/mpfrnr.awk b/test/mpfrnr.awk new file mode 100644 index 00000000..1a3b753a --- /dev/null +++ b/test/mpfrnr.awk @@ -0,0 +1,10 @@ +# Test NR and FNR for file(s) with records > LONG_MAX +BEGIN { + NR = 0x7FFFFFFF +} +BEGINFILE { + FNR = 0x7fffffffffffffff +} +END { + print NR, NR-0x7FFFFFFF, FNR, FNR-0x7fffffffffffffff +} diff --git a/test/mpfrnr.in b/test/mpfrnr.in new file mode 100644 index 00000000..6ad36e52 --- /dev/null +++ b/test/mpfrnr.in @@ -0,0 +1,3 @@ +Line 1 +Line 2 +Line 3 diff --git a/test/mpfrnr.ok b/test/mpfrnr.ok new file mode 100644 index 00000000..e472f8bf --- /dev/null +++ b/test/mpfrnr.ok @@ -0,0 +1 @@ +2147483650 3 9223372036854775810 3 diff --git a/test/mpfrrnd.awk b/test/mpfrrnd.awk new file mode 100644 index 00000000..eafefb9f --- /dev/null +++ b/test/mpfrrnd.awk @@ -0,0 +1,15 @@ +BEGIN { + N = 22/7 + printf(" %.15f\n", N) + + printf("* %.10f\n", N) # default + RNDMODE="N"; printf("N %.10f\n", N) + RNDMODE="U"; printf("U %.10f\n", N) + RNDMODE="D"; printf("D %.10f\n", N) + RNDMODE="Z"; printf("Z %.10f\n", N) + N = -N + RNDMODE="N"; printf("N %.10f\n", N) + RNDMODE="U"; printf("U %.10f\n", N) + RNDMODE="D"; printf("D %.10f\n", N) + RNDMODE="Z"; printf("Z %.10f\n", N) +} diff --git a/test/mpfrrnd.ok b/test/mpfrrnd.ok new file mode 100644 index 00000000..fceb937b --- /dev/null +++ b/test/mpfrrnd.ok @@ -0,0 +1,10 @@ + 3.142857142857143 +* 3.1428571429 +N 3.1428571429 +U 3.1428571429 +D 3.1428571428 +Z 3.1428571428 +N -3.1428571429 +U -3.1428571428 +D -3.1428571429 +Z -3.1428571428 |