Mercurial > hg > octave-nkf
comparison liboctave/util/oct-inttypes.cc @ 18017:0cd39f7f2409 stable
additional improvements for int64 ops implemented with long double (bug #40607)
* oct-inttypes.h, oct-inttypes.cc: Ensure that conversions between
64-bit integer and long double are performed when long double rounding
rules are in effect.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 26 Nov 2013 02:04:10 -0500 |
parents | 79653c5b6147 |
children | 8e056300994b c644ed73c6ce |
comparison
equal
deleted
inserted
replaced
18016:683f9c39da06 | 18017:0cd39f7f2409 |
---|---|
54 | 54 |
55 #ifdef OCTAVE_INT_USE_LONG_DOUBLE | 55 #ifdef OCTAVE_INT_USE_LONG_DOUBLE |
56 | 56 |
57 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED | 57 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED |
58 | 58 |
59 template <class xop> | 59 #define DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES(T) \ |
60 bool | 60 template <class xop> \ |
61 octave_int_cmp_op::external_mop (long double x, long double y) | 61 bool \ |
62 { | 62 octave_int_cmp_op::external_mop (double x, T y) \ |
63 DECL_LONG_DOUBLE_ROUNDING | 63 { \ |
64 | 64 DECL_LONG_DOUBLE_ROUNDING \ |
65 BEGIN_LONG_DOUBLE_ROUNDING (); | 65 \ |
66 | 66 BEGIN_LONG_DOUBLE_ROUNDING (); \ |
67 bool retval = xop::op (x, y); | 67 \ |
68 | 68 bool retval = xop::op (static_cast<long double> (x), \ |
69 END_LONG_DOUBLE_ROUNDING (); | 69 static_cast<long double> (y)); \ |
70 | 70 \ |
71 return retval; | 71 END_LONG_DOUBLE_ROUNDING (); \ |
72 } | 72 \ |
73 | 73 return retval; \ |
74 #define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(OP) \ | 74 } \ |
75 \ | |
76 template <class xop> \ | |
77 bool \ | |
78 octave_int_cmp_op::external_mop (T x, double y) \ | |
79 { \ | |
80 DECL_LONG_DOUBLE_ROUNDING \ | |
81 \ | |
82 BEGIN_LONG_DOUBLE_ROUNDING (); \ | |
83 \ | |
84 bool retval = xop::op (static_cast<long double> (x), \ | |
85 static_cast<long double> (y)); \ | |
86 \ | |
87 END_LONG_DOUBLE_ROUNDING (); \ | |
88 \ | |
89 return retval; \ | |
90 } | |
91 | |
92 DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES (int64_t) | |
93 DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES (uint64_t) | |
94 | |
95 #define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(OP, T) \ | |
75 template OCTAVE_API bool \ | 96 template OCTAVE_API bool \ |
76 octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (long double, \ | 97 octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (double, T); \ |
77 long double) | 98 template OCTAVE_API bool \ |
78 | 99 octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (T, double) |
79 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(lt); | 100 |
80 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(le); | 101 #define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS(T) \ |
81 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(gt); | 102 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (lt, T); \ |
82 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(ge); | 103 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (le, T); \ |
83 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(eq); | 104 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (gt, T); \ |
84 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(ne); | 105 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (ge, T); \ |
106 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (eq, T); \ | |
107 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (ne, T) | |
108 | |
109 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS (int64_t); | |
110 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS (uint64_t); | |
85 | 111 |
86 uint64_t | 112 uint64_t |
87 octave_external_uint64_uint64_mul (uint64_t x, uint64_t y) | 113 octave_external_uint64_uint64_mul (uint64_t x, uint64_t y) |
88 { | 114 { |
89 DECL_LONG_DOUBLE_ROUNDING | 115 DECL_LONG_DOUBLE_ROUNDING |
114 // Note that if we return long double it is apparently possible for | 140 // Note that if we return long double it is apparently possible for |
115 // truncation to happen at the point of storing the result in retval, | 141 // truncation to happen at the point of storing the result in retval, |
116 // which can happen after we end long double rounding. Attempt to avoid | 142 // which can happen after we end long double rounding. Attempt to avoid |
117 // that problem by storing the full precision temporary value in the | 143 // that problem by storing the full precision temporary value in the |
118 // integer value before we end the long double rounding mode. | 144 // integer value before we end the long double rounding mode. |
119 | 145 // Similarly, the conversion from the 64-bit integer type to long double |
120 #define OCTAVE_LONG_DOUBLE_OP(RT, OP, NAME) \ | 146 // must also occur in long double rounding mode. |
121 RT \ | 147 |
122 RT ## _external_long_double_ ## NAME (long double x, long double y) \ | 148 #define OCTAVE_LONG_DOUBLE_OP(T, OP, NAME) \ |
149 T \ | |
150 external_double_ ## T ## _ ## NAME (double x, T y) \ | |
123 { \ | 151 { \ |
124 DECL_LONG_DOUBLE_ROUNDING \ | 152 DECL_LONG_DOUBLE_ROUNDING \ |
125 \ | 153 \ |
126 BEGIN_LONG_DOUBLE_ROUNDING (); \ | 154 BEGIN_LONG_DOUBLE_ROUNDING (); \ |
127 \ | 155 \ |
128 RT retval = RT (x OP y); \ | 156 T retval = T (x OP static_cast<long double> (y.value ())); \ |
157 \ | |
158 END_LONG_DOUBLE_ROUNDING (); \ | |
159 \ | |
160 return retval; \ | |
161 } \ | |
162 \ | |
163 T \ | |
164 external_ ## T ## _double_ ## NAME (T x, double y) \ | |
165 { \ | |
166 DECL_LONG_DOUBLE_ROUNDING \ | |
167 \ | |
168 BEGIN_LONG_DOUBLE_ROUNDING (); \ | |
169 \ | |
170 T retval = T (static_cast<long double> (x.value ()) OP y); \ | |
129 \ | 171 \ |
130 END_LONG_DOUBLE_ROUNDING (); \ | 172 END_LONG_DOUBLE_ROUNDING (); \ |
131 \ | 173 \ |
132 return retval; \ | 174 return retval; \ |
133 } | 175 } |
134 | 176 |
135 #define OCTAVE_LONG_DOUBLE_OPS(RT) \ | 177 #define OCTAVE_LONG_DOUBLE_OPS(T) \ |
136 OCTAVE_LONG_DOUBLE_OP (RT, +, add); \ | 178 OCTAVE_LONG_DOUBLE_OP (T, +, add); \ |
137 OCTAVE_LONG_DOUBLE_OP (RT, -, sub); \ | 179 OCTAVE_LONG_DOUBLE_OP (T, -, sub); \ |
138 OCTAVE_LONG_DOUBLE_OP (RT, *, mul); \ | 180 OCTAVE_LONG_DOUBLE_OP (T, *, mul); \ |
139 OCTAVE_LONG_DOUBLE_OP (RT, /, div) | 181 OCTAVE_LONG_DOUBLE_OP (T, /, div) |
140 | 182 |
141 OCTAVE_LONG_DOUBLE_OPS(octave_int64); | 183 OCTAVE_LONG_DOUBLE_OPS(octave_int64); |
142 OCTAVE_LONG_DOUBLE_OPS(octave_uint64); | 184 OCTAVE_LONG_DOUBLE_OPS(octave_uint64); |
143 | 185 |
144 #endif | 186 #endif |