On Mon, Oct 17, 2022 at 08:21:01AM +0200, Aldy Hernandez wrote: > +// Set VALUE to its next real value, or INF if the operation overflows. > + > +inline void > +frange_nextafter (enum machine_mode mode, > + REAL_VALUE_TYPE &value, > + const REAL_VALUE_TYPE &inf) > +{ > + const real_format *fmt = REAL_MODE_FORMAT (mode); > + REAL_VALUE_TYPE tmp; > + bool overflow = real_nextafter (&tmp, fmt, &value, &inf); > + if (overflow) > + value = inf; > + else > + value = tmp;
Please change the above 5 lines to just real_nextafter (&tmp, fmt, &value, &inf); value = tmp; What real_nextafter returns isn't bool whether it overflowed, but a bool whether some exception should be raised for the nextafter, which can be either an overflow (in that case tmp will be already set to infinity of the right sign: if (REAL_EXP (r) > fmt->emax) { get_inf (r, x->sign); return true; } or underflow to zero: if (REAL_EXP (r) <= fmt->emin - fmt->p) { get_zero (r, x->sign); return true; } or when the result is subnormal: return r->cl == rvc_zero || REAL_EXP (r) < fmt->emin; But we shouldn't care about exceptions, we aren't emitting code, just estimating floating point range, and +-inf, or +-0, or subnormal are the right answers. Just for playing with this, I've tried: --- range-op-float.cc.jj 2022-11-02 10:06:02.620960861 +0100 +++ range-op-float.cc 2022-11-04 19:49:14.188075070 +0100 @@ -1815,6 +1815,20 @@ frange_float (const char *lb, const char return frange (type, min, max); } +inline void +frange_nextafter (enum machine_mode mode, + REAL_VALUE_TYPE &value, + const REAL_VALUE_TYPE &inf) +{ + const real_format *fmt = REAL_MODE_FORMAT (mode); + REAL_VALUE_TYPE tmp; + bool overflow = real_nextafter (&tmp, fmt, &value, &inf); + if (overflow) + value = inf; + else + value = tmp; +} + void range_op_float_tests () { @@ -1833,6 +1847,30 @@ range_op_float_tests () r1 = frange_float ("-1", "-0"); r1.update_nan (false); ASSERT_EQ (r, r1); + + if (MODE_COMPOSITE_P (TYPE_MODE (long_double_type_node))) + { + enum machine_mode mode = TYPE_MODE (long_double_type_node); + REAL_VALUE_TYPE result = dconst0; + { + REAL_VALUE_TYPE tmp; + real_convert (&tmp, DFmode, &result); + frange_nextafter (DFmode, tmp, dconstinf); + real_convert (&result, mode, &tmp); + } + for (int i = 0; i < 108; ++i) + { + char buf[1024], buf2[1024]; + REAL_VALUE_TYPE tmp, tmp2; + real_convert (&tmp, DFmode, &result); + frange_nextafter (DFmode, tmp, dconstinf); + real_convert (&tmp2, mode, &tmp); + real_to_hexadecimal (buf, &result, 1024, 0, 1); + real_to_hexadecimal (buf2, &tmp2, 1024, 0, 1); + fprintf (stderr, "%d %d %s %s\n", i, real_isdenormal (&result), buf, buf2); + real_arithmetic (&result, MULT_EXPR, &result, &dconst2); + } + } } } // namespace selftest in cross to powerpc64le-linux and I get: 0 0 0x0.8p-1073 0x0.8p-1072 1 0 0x0.8p-1072 0x0.cp-1072 2 0 0x0.8p-1071 0x0.ap-1071 3 0 0x0.8p-1070 0x0.9p-1070 4 0 0x0.8p-1069 0x0.88p-1069 5 0 0x0.8p-1068 0x0.84p-1068 6 0 0x0.8p-1067 0x0.82p-1067 7 0 0x0.8p-1066 0x0.81p-1066 8 0 0x0.8p-1065 0x0.808p-1065 9 0 0x0.8p-1064 0x0.804p-1064 10 0 0x0.8p-1063 0x0.802p-1063 11 0 0x0.8p-1062 0x0.801p-1062 12 0 0x0.8p-1061 0x0.8008p-1061 13 0 0x0.8p-1060 0x0.8004p-1060 14 0 0x0.8p-1059 0x0.8002p-1059 15 0 0x0.8p-1058 0x0.8001p-1058 16 0 0x0.8p-1057 0x0.80008p-1057 17 0 0x0.8p-1056 0x0.80004p-1056 18 0 0x0.8p-1055 0x0.80002p-1055 19 0 0x0.8p-1054 0x0.80001p-1054 20 0 0x0.8p-1053 0x0.800008p-1053 21 0 0x0.8p-1052 0x0.800004p-1052 22 0 0x0.8p-1051 0x0.800002p-1051 23 0 0x0.8p-1050 0x0.800001p-1050 24 0 0x0.8p-1049 0x0.8000008p-1049 25 0 0x0.8p-1048 0x0.8000004p-1048 26 0 0x0.8p-1047 0x0.8000002p-1047 27 0 0x0.8p-1046 0x0.8000001p-1046 28 0 0x0.8p-1045 0x0.80000008p-1045 29 0 0x0.8p-1044 0x0.80000004p-1044 30 0 0x0.8p-1043 0x0.80000002p-1043 31 0 0x0.8p-1042 0x0.80000001p-1042 32 0 0x0.8p-1041 0x0.800000008p-1041 33 0 0x0.8p-1040 0x0.800000004p-1040 34 0 0x0.8p-1039 0x0.800000002p-1039 35 0 0x0.8p-1038 0x0.800000001p-1038 36 0 0x0.8p-1037 0x0.8000000008p-1037 37 0 0x0.8p-1036 0x0.8000000004p-1036 38 0 0x0.8p-1035 0x0.8000000002p-1035 39 0 0x0.8p-1034 0x0.8000000001p-1034 40 0 0x0.8p-1033 0x0.80000000008p-1033 41 0 0x0.8p-1032 0x0.80000000004p-1032 42 0 0x0.8p-1031 0x0.80000000002p-1031 43 0 0x0.8p-1030 0x0.80000000001p-1030 44 0 0x0.8p-1029 0x0.800000000008p-1029 45 0 0x0.8p-1028 0x0.800000000004p-1028 46 0 0x0.8p-1027 0x0.800000000002p-1027 47 0 0x0.8p-1026 0x0.800000000001p-1026 48 0 0x0.8p-1025 0x0.8000000000008p-1025 49 0 0x0.8p-1024 0x0.8000000000004p-1024 50 0 0x0.8p-1023 0x0.8000000000002p-1023 51 0 0x0.8p-1022 0x0.8000000000001p-1022 52 0 0x0.8p-1021 0x0.80000000000008p-1021 53 0 0x0.8p-1020 0x0.80000000000008p-1020 54 0 0x0.8p-1019 0x0.80000000000008p-1019 55 0 0x0.8p-1018 0x0.80000000000008p-1018 56 0 0x0.8p-1017 0x0.80000000000008p-1017 57 0 0x0.8p-1016 0x0.80000000000008p-1016 58 0 0x0.8p-1015 0x0.80000000000008p-1015 59 0 0x0.8p-1014 0x0.80000000000008p-1014 60 0 0x0.8p-1013 0x0.80000000000008p-1013 61 0 0x0.8p-1012 0x0.80000000000008p-1012 62 0 0x0.8p-1011 0x0.80000000000008p-1011 63 0 0x0.8p-1010 0x0.80000000000008p-1010 64 0 0x0.8p-1009 0x0.80000000000008p-1009 65 0 0x0.8p-1008 0x0.80000000000008p-1008 66 0 0x0.8p-1007 0x0.80000000000008p-1007 67 0 0x0.8p-1006 0x0.80000000000008p-1006 68 0 0x0.8p-1005 0x0.80000000000008p-1005 69 0 0x0.8p-1004 0x0.80000000000008p-1004 70 0 0x0.8p-1003 0x0.80000000000008p-1003 71 0 0x0.8p-1002 0x0.80000000000008p-1002 72 0 0x0.8p-1001 0x0.80000000000008p-1001 73 0 0x0.8p-1000 0x0.80000000000008p-1000 74 0 0x0.8p-999 0x0.80000000000008p-999 75 0 0x0.8p-998 0x0.80000000000008p-998 76 0 0x0.8p-997 0x0.80000000000008p-997 77 0 0x0.8p-996 0x0.80000000000008p-996 78 0 0x0.8p-995 0x0.80000000000008p-995 79 0 0x0.8p-994 0x0.80000000000008p-994 80 0 0x0.8p-993 0x0.80000000000008p-993 81 0 0x0.8p-992 0x0.80000000000008p-992 82 0 0x0.8p-991 0x0.80000000000008p-991 83 0 0x0.8p-990 0x0.80000000000008p-990 84 0 0x0.8p-989 0x0.80000000000008p-989 85 0 0x0.8p-988 0x0.80000000000008p-988 86 0 0x0.8p-987 0x0.80000000000008p-987 87 0 0x0.8p-986 0x0.80000000000008p-986 88 0 0x0.8p-985 0x0.80000000000008p-985 89 0 0x0.8p-984 0x0.80000000000008p-984 90 0 0x0.8p-983 0x0.80000000000008p-983 91 0 0x0.8p-982 0x0.80000000000008p-982 92 0 0x0.8p-981 0x0.80000000000008p-981 93 0 0x0.8p-980 0x0.80000000000008p-980 94 0 0x0.8p-979 0x0.80000000000008p-979 95 0 0x0.8p-978 0x0.80000000000008p-978 96 0 0x0.8p-977 0x0.80000000000008p-977 97 0 0x0.8p-976 0x0.80000000000008p-976 98 0 0x0.8p-975 0x0.80000000000008p-975 99 0 0x0.8p-974 0x0.80000000000008p-974 100 0 0x0.8p-973 0x0.80000000000008p-973 101 0 0x0.8p-972 0x0.80000000000008p-972 102 0 0x0.8p-971 0x0.80000000000008p-971 103 0 0x0.8p-970 0x0.80000000000008p-970 104 0 0x0.8p-969 0x0.80000000000008p-969 105 0 0x0.8p-968 0x0.80000000000008p-968 106 0 0x0.8p-967 0x0.80000000000008p-967 107 0 0x0.8p-966 0x0.80000000000008p-966 One thing that is clear is that real_isdenormal is never true for these (but then a question is if flush_denormals_to_zero actually works). Jakub