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