p1788 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +8 -0
- data/AUTHORS +6 -0
- data/LICENSE +201 -0
- data/NOTICE +29 -0
- data/README.md +65 -0
- data/ext/libieeep1788_copy/README +3 -0
- data/ext/libieeep1788_copy/p1788/AUTHORS +16 -0
- data/ext/libieeep1788_copy/p1788/LICENSE +202 -0
- data/ext/libieeep1788_copy/p1788/NOTICE +14 -0
- data/ext/libieeep1788_copy/p1788/decoration/decoration.hpp +265 -0
- data/ext/libieeep1788_copy/p1788/exception/exception.hpp +302 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor.hpp +3443 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_bool_func_impl.hpp +608 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_cancel_func_impl.hpp +229 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_class_impl.hpp +526 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_elem_func_impl.hpp +4533 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_io_impl.hpp +1421 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_mul_rev_to_pair_func_impl.hpp +347 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_num_func_impl.hpp +655 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_rec_bool_func_impl.hpp +146 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_rec_overlap_impl.hpp +188 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_rev_func_impl.hpp +1674 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_set_op_impl.hpp +216 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_setup_func_impl.hpp +68 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_util_func_impl.hpp +135 -0
- data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_validation_func_impl.hpp +93 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval.hpp +1529 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_bool_func_impl.hpp +481 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_cancel_func_impl.hpp +126 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_elem_func_impl.hpp +1581 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_io_impl.hpp +59 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_mul_rev_to_pair_func_impl.hpp +88 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_num_func_impl.hpp +345 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_rec_bool_func_impl.hpp +92 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_rec_overlap_impl.hpp +72 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_rev_func_impl.hpp +656 -0
- data/ext/libieeep1788_copy/p1788/infsup/base_interval_set_op_impl.hpp +126 -0
- data/ext/libieeep1788_copy/p1788/infsup/decorated_interval.hpp +464 -0
- data/ext/libieeep1788_copy/p1788/infsup/forward_declaration.hpp +66 -0
- data/ext/libieeep1788_copy/p1788/infsup/interval.hpp +275 -0
- data/ext/libieeep1788_copy/p1788/io/io_manip.hpp +531 -0
- data/ext/libieeep1788_copy/p1788/overlapping/overlapping.hpp +241 -0
- data/ext/libieeep1788_copy/p1788/p1788.hpp +45 -0
- data/ext/libieeep1788_copy/p1788/reduction/reduction.hpp +341 -0
- data/ext/libieeep1788_copy/p1788/util/io.hpp +63 -0
- data/ext/libieeep1788_copy/p1788/util/mixed_type_traits.hpp +140 -0
- data/ext/libieeep1788_copy/p1788/util/mpfr_util.hpp +77 -0
- data/ext/libieeep1788_copy/p1788/util/mpfr_var.hpp +119 -0
- data/ext/libieeep1788_copy/p1788/util/mpfr_var_impl.hpp +382 -0
- data/ext/libieeep1788_copy/p1788/version.hpp +34 -0
- data/ext/p1788/extconf.rb +49 -0
- data/ext/p1788/p1788.cc +3764 -0
- data/lib/p1788/version.rb +4 -0
- data/lib/p1788.rb +25 -0
- data/p1788.gemspec +72 -0
- metadata +99 -0
@@ -0,0 +1,1421 @@
|
|
1
|
+
//
|
2
|
+
// libieeep1788
|
3
|
+
//
|
4
|
+
// An implementation of the preliminary IEEE P1788 standard for
|
5
|
+
// interval arithmetic
|
6
|
+
//
|
7
|
+
//
|
8
|
+
// Copyright 2013 - 2015
|
9
|
+
//
|
10
|
+
// Marco Nehmeier (nehmeier@informatik.uni-wuerzburg.de)
|
11
|
+
// Department of Computer Science,
|
12
|
+
// University of Wuerzburg, Germany
|
13
|
+
//
|
14
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
15
|
+
// you may not use this file except in compliance with the License.
|
16
|
+
// You may obtain a copy of the License at
|
17
|
+
//
|
18
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
19
|
+
//
|
20
|
+
// Unless required by applicable law or agreed to in writing, software
|
21
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
22
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
23
|
+
// See the License for the specific language governing permissions and
|
24
|
+
// limitations under the License.
|
25
|
+
|
26
|
+
#ifndef LIBIEEEP1788_P1788_FLAVOR_INFSUP_SETBASED_MPFR_BIN_IEEE754_FLAVOR_IO_IMPL_HPP
|
27
|
+
#define LIBIEEEP1788_P1788_FLAVOR_INFSUP_SETBASED_MPFR_BIN_IEEE754_FLAVOR_IO_IMPL_HPP
|
28
|
+
|
29
|
+
|
30
|
+
namespace p1788
|
31
|
+
{
|
32
|
+
|
33
|
+
namespace flavor
|
34
|
+
{
|
35
|
+
|
36
|
+
namespace infsup
|
37
|
+
{
|
38
|
+
|
39
|
+
namespace setbased
|
40
|
+
{
|
41
|
+
|
42
|
+
|
43
|
+
// writing a bare interval onto an output stream
|
44
|
+
// taking care of io manipulators
|
45
|
+
template<typename T>
|
46
|
+
template< typename CharT, typename Traits >
|
47
|
+
std::basic_ostream<CharT, Traits>&
|
48
|
+
mpfr_bin_ieee754_flavor<T>::operator_interval_to_text(std::basic_ostream<CharT, Traits>& os,
|
49
|
+
mpfr_bin_ieee754_flavor<T>::representation const& x)
|
50
|
+
{
|
51
|
+
if (!is_valid(x))
|
52
|
+
return os;
|
53
|
+
|
54
|
+
//-------------------------------------
|
55
|
+
// uncertain and not empty
|
56
|
+
//-------------------------------------
|
57
|
+
if ((os.iword(p1788::io::representation_manip_id) == p1788::io::uncertain_representation
|
58
|
+
|| os.iword(p1788::io::representation_manip_id) == p1788::io::uncertain_up_representation
|
59
|
+
|| os.iword(p1788::io::representation_manip_id) == p1788::io::uncertain_down_representation)
|
60
|
+
&& !is_empty(x))
|
61
|
+
{
|
62
|
+
std::string str;
|
63
|
+
int prec = os.iword(p1788::io::precision_manip_id);
|
64
|
+
p1788::io::text_representation_flags text_rep = static_cast<p1788::io::text_representation_flags>(os.iword(p1788::io::text_representation_manip_id));
|
65
|
+
p1788::io::uncertain_exponent_flags uc_exp = static_cast<p1788::io::uncertain_exponent_flags>(os.iword(p1788::io::uncertain_exponent_manip_id));
|
66
|
+
|
67
|
+
// Default precision is 6
|
68
|
+
if (prec == 0)
|
69
|
+
prec = 6;
|
70
|
+
|
71
|
+
// entire
|
72
|
+
if (is_entire(x))
|
73
|
+
{
|
74
|
+
mpfr_var::setup();
|
75
|
+
mpfr_var xu(mid(x), MPFR_RNDN);
|
76
|
+
|
77
|
+
// generate number string
|
78
|
+
str = xu.get_str(MPFR_RNDN,
|
79
|
+
uc_exp == p1788::io::show_uncertain_exponent ? p1788::io::scientific_representation : p1788::io::decimal_representation,
|
80
|
+
0,
|
81
|
+
prec,
|
82
|
+
text_rep);
|
83
|
+
|
84
|
+
// find exponent
|
85
|
+
int p = std::max(static_cast<int>(str.find('E')), static_cast<int>(str.find('e')));
|
86
|
+
|
87
|
+
// insert ??
|
88
|
+
if (p >= 0)
|
89
|
+
str.insert(p, "??");
|
90
|
+
else
|
91
|
+
str += "??";
|
92
|
+
}
|
93
|
+
else if (std::isinf(x.first)) // [-oo,x]
|
94
|
+
{
|
95
|
+
mpfr_var::setup();
|
96
|
+
mpfr_var xu(x.second, MPFR_RNDU);
|
97
|
+
|
98
|
+
// generate number string
|
99
|
+
str = xu.get_str(MPFR_RNDU,
|
100
|
+
uc_exp == p1788::io::show_uncertain_exponent ? p1788::io::scientific_representation : p1788::io::decimal_representation,
|
101
|
+
0,
|
102
|
+
prec,
|
103
|
+
static_cast<p1788::io::text_representation_flags>(os.iword(p1788::io::text_representation_manip_id)));
|
104
|
+
|
105
|
+
// find exponent
|
106
|
+
int p = std::max(static_cast<int>(str.find('E')), static_cast<int>(str.find('e')));
|
107
|
+
|
108
|
+
// add ??d
|
109
|
+
if (p >= 0)
|
110
|
+
str.insert(p, text_rep == p1788::io::upper_case_text_representation ? "??D" : "??d");
|
111
|
+
else
|
112
|
+
str += (text_rep == p1788::io::upper_case_text_representation ? "??D" : "??d");
|
113
|
+
}
|
114
|
+
else if (std::isinf(x.second)) // [x,+oo]
|
115
|
+
{
|
116
|
+
mpfr_var::setup();
|
117
|
+
mpfr_var xl(x.first, MPFR_RNDD);
|
118
|
+
|
119
|
+
// generate number string
|
120
|
+
str = xl.get_str(MPFR_RNDD,
|
121
|
+
uc_exp == p1788::io::show_uncertain_exponent ? p1788::io::scientific_representation : p1788::io::decimal_representation,
|
122
|
+
0,
|
123
|
+
prec,
|
124
|
+
text_rep);
|
125
|
+
|
126
|
+
// find exponent
|
127
|
+
int p = std::max(static_cast<int>(str.find('E')), static_cast<int>(str.find('e')));
|
128
|
+
|
129
|
+
// add ??d
|
130
|
+
if (p >= 0)
|
131
|
+
str.insert(p, text_rep == p1788::io::upper_case_text_representation ? "??U" : "??u");
|
132
|
+
else
|
133
|
+
str += (text_rep == p1788::io::upper_case_text_representation ? "??U" : "??u");
|
134
|
+
}
|
135
|
+
else // all other
|
136
|
+
{
|
137
|
+
mpfr_var::setup();
|
138
|
+
mpfr_var xl(x.first, MPFR_RNDD);
|
139
|
+
mpfr_var xu(x.second, MPFR_RNDU);
|
140
|
+
|
141
|
+
// lower bound representation
|
142
|
+
std::string tmp_l = xl.get_str(MPFR_RNDD,
|
143
|
+
uc_exp == p1788::io::show_uncertain_exponent ? p1788::io::scientific_representation : p1788::io::decimal_representation,
|
144
|
+
0,
|
145
|
+
prec,
|
146
|
+
text_rep);
|
147
|
+
|
148
|
+
// upper bound representation
|
149
|
+
std::string tmp_u = xu.get_str(MPFR_RNDU,
|
150
|
+
uc_exp == p1788::io::show_uncertain_exponent ? p1788::io::scientific_representation : p1788::io::decimal_representation,
|
151
|
+
0,
|
152
|
+
prec,
|
153
|
+
text_rep);
|
154
|
+
|
155
|
+
// find exponent part
|
156
|
+
int p_l = std::max(static_cast<int>(tmp_l.find('E')), static_cast<int>(tmp_l.find('e')));
|
157
|
+
int p_u = std::max(static_cast<int>(tmp_u.find('E')), static_cast<int>(tmp_u.find('e')));
|
158
|
+
|
159
|
+
std::string exp_str = "";
|
160
|
+
|
161
|
+
long long int ulps = 0;
|
162
|
+
|
163
|
+
// symmetric
|
164
|
+
if (os.iword(p1788::io::representation_manip_id) == p1788::io::uncertain_representation)
|
165
|
+
{
|
166
|
+
// midpoint string
|
167
|
+
mpfr_var m(mid(x), MPFR_RNDN);
|
168
|
+
std::string tmp_m = m.get_str(MPFR_RNDN,
|
169
|
+
uc_exp == p1788::io::show_uncertain_exponent ? p1788::io::scientific_representation : p1788::io::decimal_representation,
|
170
|
+
0,
|
171
|
+
prec,
|
172
|
+
text_rep);
|
173
|
+
|
174
|
+
// find exponent part
|
175
|
+
int p_m = std::max(static_cast<int>(tmp_m.find('E')), static_cast<int>(tmp_m.find('e')));
|
176
|
+
|
177
|
+
// split number and exponent part if necessary
|
178
|
+
str = p_m >= 0 ? tmp_m.substr(0, p_m) : tmp_m;
|
179
|
+
if (p_m >= 0)
|
180
|
+
{
|
181
|
+
exp_str = tmp_m.substr(p_m, tmp_m.size() - p_m);
|
182
|
+
tmp_m = str;
|
183
|
+
}
|
184
|
+
|
185
|
+
// remove seperator
|
186
|
+
tmp_m.erase(tmp_m.size() - prec - 1, 1);
|
187
|
+
|
188
|
+
// compute exponent difference
|
189
|
+
int exp_m = p_m >= 0 ? std::stoi(exp_str.substr(1, tmp_m.size() - 1)) : 0;
|
190
|
+
int ulp_l = 0;
|
191
|
+
int ulp_u = 0;
|
192
|
+
if (p_l >= 0)
|
193
|
+
{
|
194
|
+
int exp_l = std::stoi(tmp_l.substr(p_l + 1, tmp_l.size() - p_l - 1)) - exp_m;
|
195
|
+
// remove exponent and seperator
|
196
|
+
tmp_l.erase(p_l);
|
197
|
+
tmp_l.erase(tmp_l.size() - prec - 1, 1);
|
198
|
+
|
199
|
+
if (exp_l < 0)
|
200
|
+
{
|
201
|
+
// remove trailing digits and remind ulp if necessary
|
202
|
+
ulp_l = std::stoll(tmp_l.substr(tmp_l.size() + exp_l)) != 0 && x.first < 0.0 ? 1 : 0;
|
203
|
+
tmp_l.resize(tmp_l.size() + exp_l);
|
204
|
+
}
|
205
|
+
else if (exp_l > 0)
|
206
|
+
// add some digits
|
207
|
+
tmp_l.append(exp_l, '0');
|
208
|
+
|
209
|
+
}
|
210
|
+
else
|
211
|
+
{
|
212
|
+
// remove seperator
|
213
|
+
tmp_l.erase(tmp_l.size() - prec - 1, 1);
|
214
|
+
}
|
215
|
+
|
216
|
+
if (p_u >= 0)
|
217
|
+
{
|
218
|
+
int exp_u = exp_m - std::stoi(tmp_u.substr(p_u + 1, tmp_u.size() - p_u - 1));
|
219
|
+
// remove exponent and seperator
|
220
|
+
tmp_u.erase(p_u);
|
221
|
+
tmp_u.erase(tmp_u.size() - prec - 1, 1);
|
222
|
+
if (exp_u > 0)
|
223
|
+
{
|
224
|
+
// remove trailing digits and remind ulp if necessary
|
225
|
+
ulp_u = std::stoll(tmp_u.substr(tmp_u.size() - exp_u)) != 0 && x.second > 0.0 ? 1 : 0;
|
226
|
+
tmp_u.resize(tmp_u.size() - exp_u);
|
227
|
+
}
|
228
|
+
else if (exp_u < 0)
|
229
|
+
// add some digits
|
230
|
+
tmp_u.append(-exp_u, '0');
|
231
|
+
}
|
232
|
+
else
|
233
|
+
{
|
234
|
+
// remove seperator
|
235
|
+
tmp_u.erase(tmp_u.size() - prec - 1, 1);
|
236
|
+
}
|
237
|
+
|
238
|
+
// compute max ulps to lower and upper bound
|
239
|
+
long long int tmp = std::stoll(tmp_m);
|
240
|
+
|
241
|
+
ulps = std::max(-std::stoll(tmp_l) + tmp + ulp_l,
|
242
|
+
-tmp + std::stoll(tmp_u) + ulp_u);
|
243
|
+
}
|
244
|
+
else // downward or upward
|
245
|
+
{
|
246
|
+
if (os.iword(p1788::io::representation_manip_id) == p1788::io::uncertain_down_representation)
|
247
|
+
{
|
248
|
+
// split number and exponent part if necessary
|
249
|
+
str = p_u >= 0 ? tmp_u.substr(0, p_u) : tmp_u;
|
250
|
+
if (p_u >= 0)
|
251
|
+
exp_str = tmp_u.substr(p_u, tmp_u.size() - p_u);
|
252
|
+
}
|
253
|
+
else if (os.iword(p1788::io::representation_manip_id) == p1788::io::uncertain_up_representation)
|
254
|
+
{
|
255
|
+
// split number and exponent part if necessary
|
256
|
+
str = p_l >= 0 ? tmp_l.substr(0, p_l) : tmp_l;
|
257
|
+
if (p_l >= 0)
|
258
|
+
exp_str = tmp_l.substr(p_l, tmp_l.size() - p_l);
|
259
|
+
}
|
260
|
+
|
261
|
+
// compute exponent difference
|
262
|
+
int exp = 0;
|
263
|
+
if (p_l >= 0)
|
264
|
+
{
|
265
|
+
exp = std::stoi(tmp_l.substr(p_l + 1, tmp_l.size() - p_l - 1));
|
266
|
+
tmp_l.erase(p_l);
|
267
|
+
}
|
268
|
+
if (p_u >= 0)
|
269
|
+
{
|
270
|
+
exp -= std::stoi(tmp_u.substr(p_u + 1, tmp_u.size() - p_u - 1));
|
271
|
+
tmp_u.erase(p_u);
|
272
|
+
}
|
273
|
+
|
274
|
+
// remove seperator
|
275
|
+
tmp_l.erase(tmp_l.size() - prec - 1, 1);
|
276
|
+
tmp_u.erase(tmp_u.size() - prec - 1, 1);
|
277
|
+
|
278
|
+
// adjust string length to balance exponent difference
|
279
|
+
if (os.iword(p1788::io::representation_manip_id) == p1788::io::uncertain_down_representation)
|
280
|
+
{
|
281
|
+
if (exp < 0)
|
282
|
+
{
|
283
|
+
// remove trailing digits and adjust ulps if necessary
|
284
|
+
ulps += std::stoll(tmp_l.substr(tmp_l.size() + exp)) != 0 && x.first < 0.0 ? 1 : 0;
|
285
|
+
tmp_l.resize(tmp_l.size() + exp);
|
286
|
+
}
|
287
|
+
else if (exp > 0)
|
288
|
+
// add some digits
|
289
|
+
tmp_l.append(exp, '0');
|
290
|
+
}
|
291
|
+
else if (os.iword(p1788::io::representation_manip_id) == p1788::io::uncertain_up_representation)
|
292
|
+
{
|
293
|
+
if (exp > 0)
|
294
|
+
{
|
295
|
+
// remove trailing digits and adjust ulps if necessary
|
296
|
+
ulps += std::stoll(tmp_u.substr(tmp_u.size() - exp)) != 0 && x.second > 0.0 ? 1 : 0;
|
297
|
+
tmp_u.resize(tmp_u.size() - exp);
|
298
|
+
}
|
299
|
+
else if (exp < 0)
|
300
|
+
// add some digits
|
301
|
+
tmp_u.append(-exp, '0');
|
302
|
+
}
|
303
|
+
|
304
|
+
// compute ulps
|
305
|
+
ulps += -std::stoll(tmp_l) + std::stoll(tmp_u);
|
306
|
+
}
|
307
|
+
|
308
|
+
str += "?" + std::to_string(ulps);
|
309
|
+
|
310
|
+
// add downward or upward flag
|
311
|
+
switch(os.iword(p1788::io::representation_manip_id))
|
312
|
+
{
|
313
|
+
case p1788::io::uncertain_down_representation:
|
314
|
+
str += text_rep == p1788::io::upper_case_text_representation ? "D" : "d";
|
315
|
+
break;
|
316
|
+
case p1788::io::uncertain_up_representation:
|
317
|
+
str += text_rep == p1788::io::upper_case_text_representation ? "U" : "u";
|
318
|
+
break;
|
319
|
+
}
|
320
|
+
|
321
|
+
// add exponent
|
322
|
+
str += exp_str;
|
323
|
+
}
|
324
|
+
|
325
|
+
int w = os.iword(p1788::io::string_width_manip_id) - str.size();
|
326
|
+
|
327
|
+
// adjust width
|
328
|
+
if (w > 0)
|
329
|
+
str = std::string(w, ' ') + str;
|
330
|
+
|
331
|
+
return os << str;
|
332
|
+
}
|
333
|
+
|
334
|
+
//-------------------------------------
|
335
|
+
// inf sup representation or empty
|
336
|
+
//-------------------------------------
|
337
|
+
std::string part1 = os.iword(p1788::io::punctuation_manip_id) == p1788::io::show_no_punctuation ? "" : "[";
|
338
|
+
std::string part2;
|
339
|
+
std::string part3 = os.iword(p1788::io::punctuation_manip_id) == p1788::io::show_no_punctuation ? " " : ",";
|
340
|
+
std::string part4;
|
341
|
+
std::string part5 = os.iword(p1788::io::punctuation_manip_id) == p1788::io::show_no_punctuation ? "" : "]";
|
342
|
+
|
343
|
+
// empty or entire with no bounds
|
344
|
+
if ((is_empty(x) || is_entire(x))
|
345
|
+
&& os.iword(p1788::io::special_representation_manip_id) != p1788::io::bounds_special_representation)
|
346
|
+
{
|
347
|
+
switch (os.iword(p1788::io::special_representation_manip_id))
|
348
|
+
{
|
349
|
+
case p1788::io::no_bounds_special_representation:
|
350
|
+
if (os.iword(p1788::io::punctuation_manip_id) == p1788::io::show_punctuation)
|
351
|
+
{
|
352
|
+
part3 = is_empty(x) ? " " : ",";
|
353
|
+
break;
|
354
|
+
}
|
355
|
+
default:
|
356
|
+
switch (os.iword(p1788::io::text_representation_manip_id))
|
357
|
+
{
|
358
|
+
case p1788::io::upper_case_text_representation:
|
359
|
+
part3 = is_empty(x) ? "EMPTY" : "ENTIRE";
|
360
|
+
break;
|
361
|
+
default:
|
362
|
+
part3 = is_empty(x) ? "empty" : "entire";
|
363
|
+
break;
|
364
|
+
}
|
365
|
+
break;
|
366
|
+
}
|
367
|
+
|
368
|
+
// Adjust width
|
369
|
+
size_t w = os.iword(p1788::io::width_manip_id);
|
370
|
+
int w2 = w - ((part3.size() - 1) / 2);
|
371
|
+
int w4 =w - (part3.size() -1 - (part3.size() - 1) / 2);
|
372
|
+
|
373
|
+
part2 = w2 > 0 ? std::string(w2, ' ') : "";
|
374
|
+
part4 = w4 > 0 ? std::string(w4, ' ') : "";
|
375
|
+
}
|
376
|
+
else // print bounds
|
377
|
+
{
|
378
|
+
mpfr_var::setup();
|
379
|
+
|
380
|
+
p1788::io::number_representation_flags nr = static_cast<p1788::io::number_representation_flags>(os.iword(p1788::io::number_representation_manip_id));
|
381
|
+
size_t w = os.iword(p1788::io::width_manip_id);
|
382
|
+
size_t p = os.iword(p1788::io::precision_manip_id);
|
383
|
+
p1788::io::text_representation_flags tr = static_cast<p1788::io::text_representation_flags>(os.iword(p1788::io::text_representation_manip_id));
|
384
|
+
|
385
|
+
mpfr_var xl(inf(x), MPFR_RNDD);
|
386
|
+
part2 = xl.get_str(MPFR_RNDD, nr, w, p, tr);
|
387
|
+
|
388
|
+
mpfr_var xu(sup(x), MPFR_RNDU);
|
389
|
+
part4 = xu.get_str(MPFR_RNDU, nr, w, p, tr);
|
390
|
+
}
|
391
|
+
|
392
|
+
|
393
|
+
// Adjust width
|
394
|
+
int width = os.iword(p1788::io::string_width_manip_id)
|
395
|
+
- part1.size() - part2.size() - part3.size() - part4.size() - part5.size();
|
396
|
+
|
397
|
+
if (width < 0)
|
398
|
+
width = 0;
|
399
|
+
|
400
|
+
return os << part1 << std::string(width / 2, ' ')
|
401
|
+
<< part2
|
402
|
+
<< part3 << std::string(width - width / 2, ' ')
|
403
|
+
<< part4 << part5;
|
404
|
+
}
|
405
|
+
|
406
|
+
|
407
|
+
// writing a decorated interval onto an output stream
|
408
|
+
// taking care of io manipulators
|
409
|
+
template<typename T>
|
410
|
+
template< typename CharT, typename Traits >
|
411
|
+
std::basic_ostream<CharT, Traits>&
|
412
|
+
mpfr_bin_ieee754_flavor<T>::operator_interval_to_text(std::basic_ostream<CharT, Traits>& os,
|
413
|
+
mpfr_bin_ieee754_flavor<T>::representation_dec const& x)
|
414
|
+
{
|
415
|
+
if (!is_valid(x))
|
416
|
+
return os;
|
417
|
+
|
418
|
+
// Generate Nai
|
419
|
+
if (is_nai(x))
|
420
|
+
{
|
421
|
+
std::string part1 = os.iword(p1788::io::punctuation_manip_id) == p1788::io::show_no_punctuation ? "" : "[";
|
422
|
+
std::string part2 = os.iword(p1788::io::text_representation_manip_id) == p1788::io::upper_case_text_representation ? "NAI" : "nai";
|
423
|
+
std::string part3 = os.iword(p1788::io::punctuation_manip_id) == p1788::io::show_no_punctuation ? "" : "]";
|
424
|
+
|
425
|
+
// Adjust width
|
426
|
+
size_t w = os.iword(p1788::io::width_manip_id);
|
427
|
+
int w2 = w - ((part2.size() - 1) / 2);
|
428
|
+
int w3 =w - (part2.size() -1 - (part2.size() - 1) / 2);
|
429
|
+
|
430
|
+
part1 += w2 > 0 ? std::string(w2, ' ') : "";
|
431
|
+
part3 = (w3 > 0 ? std::string(w3, ' ') : "") + part3;
|
432
|
+
|
433
|
+
|
434
|
+
int width = os.iword(p1788::io::string_width_manip_id)
|
435
|
+
- part1.size() - part2.size() - part3.size();
|
436
|
+
|
437
|
+
if (width < 0)
|
438
|
+
width = 0;
|
439
|
+
|
440
|
+
return os << part1 << std::string(width / 2, ' ')
|
441
|
+
<< part2 << std::string(width - width / 2, ' ')
|
442
|
+
<< part3;
|
443
|
+
}
|
444
|
+
|
445
|
+
|
446
|
+
// no decorations for empty intervals
|
447
|
+
if (is_empty(x))
|
448
|
+
{
|
449
|
+
// bare interval
|
450
|
+
operator_interval_to_text(os, x.first);
|
451
|
+
return os;
|
452
|
+
}
|
453
|
+
|
454
|
+
// generate the decoration string
|
455
|
+
std::stringstream buf;
|
456
|
+
buf.copyfmt(os);
|
457
|
+
buf << ((os.iword(p1788::io::punctuation_manip_id) == p1788::io::show_no_punctuation) ? " " : "_") << x.second;
|
458
|
+
|
459
|
+
|
460
|
+
// RAII class to handle the string_width_manip
|
461
|
+
class string_width_helper
|
462
|
+
{
|
463
|
+
std::basic_ostream<CharT, Traits>& os_;
|
464
|
+
int size_;
|
465
|
+
public:
|
466
|
+
// adjust string size
|
467
|
+
string_width_helper(std::basic_ostream<CharT, Traits>& os, int dec_width)
|
468
|
+
: os_(os), size_(os.iword(p1788::io::string_width_manip_id))
|
469
|
+
{
|
470
|
+
os_.iword(p1788::io::string_width_manip_id) = size_ - dec_width;
|
471
|
+
}
|
472
|
+
|
473
|
+
// reset size
|
474
|
+
~string_width_helper()
|
475
|
+
{
|
476
|
+
os_.iword(p1788::io::string_width_manip_id) = size_;
|
477
|
+
}
|
478
|
+
} swh(os, buf.str().size());
|
479
|
+
|
480
|
+
// generate bare output
|
481
|
+
operator_interval_to_text(os, x.first);
|
482
|
+
|
483
|
+
// append decoration
|
484
|
+
return os << buf.str();
|
485
|
+
}
|
486
|
+
|
487
|
+
|
488
|
+
template<typename T>
|
489
|
+
template< typename CharT, typename Traits >
|
490
|
+
std::basic_istream<CharT, Traits>&
|
491
|
+
mpfr_bin_ieee754_flavor<T>::operator_text_to_interval(std::basic_istream<CharT, Traits>& is,
|
492
|
+
mpfr_bin_ieee754_flavor<T>::representation& x)
|
493
|
+
{
|
494
|
+
representation_dec x_dec;
|
495
|
+
|
496
|
+
operator_text_to_interval(is, x_dec);
|
497
|
+
|
498
|
+
if (is)
|
499
|
+
x = interval_part(x_dec);
|
500
|
+
|
501
|
+
return is;
|
502
|
+
}
|
503
|
+
|
504
|
+
template<typename T>
|
505
|
+
template< typename CharT, typename Traits >
|
506
|
+
std::basic_istream<CharT, Traits>&
|
507
|
+
mpfr_bin_ieee754_flavor<T>::operator_text_to_interval(std::basic_istream<CharT, Traits>& is,
|
508
|
+
mpfr_bin_ieee754_flavor<T>::representation_dec& x)
|
509
|
+
{
|
510
|
+
|
511
|
+
// RAII for mpz_t
|
512
|
+
struct mpz_var
|
513
|
+
{
|
514
|
+
mpz_var() : var_()
|
515
|
+
{
|
516
|
+
mpz_init(var_);
|
517
|
+
}
|
518
|
+
|
519
|
+
~mpz_var()
|
520
|
+
{
|
521
|
+
mpz_clear(var_);
|
522
|
+
}
|
523
|
+
|
524
|
+
mpz_t var_;
|
525
|
+
};
|
526
|
+
|
527
|
+
// RAII for mpq_t
|
528
|
+
struct mpq_var
|
529
|
+
{
|
530
|
+
mpq_var() : var_()
|
531
|
+
{
|
532
|
+
mpq_init(var_);
|
533
|
+
}
|
534
|
+
|
535
|
+
~mpq_var()
|
536
|
+
{
|
537
|
+
mpq_clear(var_);
|
538
|
+
}
|
539
|
+
|
540
|
+
mpq_t var_;
|
541
|
+
};
|
542
|
+
|
543
|
+
// remove whitespaces if necessary
|
544
|
+
if (is.flags() & std::ios_base::skipws)
|
545
|
+
{
|
546
|
+
p1788::util::remove_ws(is);
|
547
|
+
}
|
548
|
+
|
549
|
+
|
550
|
+
if (is)
|
551
|
+
{
|
552
|
+
//---------------------------------------------------------------------------------
|
553
|
+
// inf sup
|
554
|
+
//---------------------------------------------------------------------------------
|
555
|
+
|
556
|
+
if (is.peek() == '[') // check if first char is '[' than remove it and check if stream is ok
|
557
|
+
{
|
558
|
+
//is.get(); // remove '['
|
559
|
+
|
560
|
+
if (is)
|
561
|
+
{
|
562
|
+
std::string input;
|
563
|
+
//std::getline(is, input, ']');
|
564
|
+
|
565
|
+
// read string
|
566
|
+
for (auto c = is.peek(); is; c = is.peek())
|
567
|
+
{
|
568
|
+
input += is.get();
|
569
|
+
|
570
|
+
if (c == ']')
|
571
|
+
break;
|
572
|
+
}
|
573
|
+
|
574
|
+
if (is)
|
575
|
+
{
|
576
|
+
// regex to match valid literal
|
577
|
+
// Subgroups:
|
578
|
+
// [0] : whole string
|
579
|
+
//
|
580
|
+
// only one argument is specified:
|
581
|
+
// [1] : whole argument
|
582
|
+
// [2] : float representation: number
|
583
|
+
// [3] : float representation: exponent
|
584
|
+
// [4] : hex representation: number
|
585
|
+
// [5] : hex representation: exponent
|
586
|
+
// [6] : rational representation: nominator
|
587
|
+
// [7] : rational representation: denominator
|
588
|
+
// [8] : string if argument is "empty"
|
589
|
+
// [9] : string if argument is "entire"
|
590
|
+
// [10] : string if argument is "nai"
|
591
|
+
//
|
592
|
+
// two arguments are specified:
|
593
|
+
// [11] : whole first argument
|
594
|
+
// [12] : float representation: number
|
595
|
+
// [13] : float representation: exponent
|
596
|
+
// [14] : hex representation: number
|
597
|
+
// [15] : hex representation: exponent
|
598
|
+
// [16] : rational representation: nominator
|
599
|
+
// [17] : rational representation: denominator
|
600
|
+
// [18] : string if first argument is "-inf" or "-infinity"
|
601
|
+
// [19] : separator
|
602
|
+
// [20] : whole second argument
|
603
|
+
// [21] : float representation: number
|
604
|
+
// [22] : float representation: exponent
|
605
|
+
// [23] : hex representation: number
|
606
|
+
// [24] : hex representation: exponent
|
607
|
+
// [25] : rational representation: nominator
|
608
|
+
// [26] : rational representation: denominator
|
609
|
+
// [27] : string if second argument is "+inf" or "+infinity"
|
610
|
+
static std::regex inf_sup_regex(
|
611
|
+
//one argument or empty
|
612
|
+
"(?:\\[\\s*("
|
613
|
+
"|(?:([+-]?(?:(?:[0-9]*\\.[0-9]+)|(?:[0-9]+[\\.])|(?:[0-9]+)))(?:e([+-]?[0-9]+))?)" // float
|
614
|
+
"|(?:([+-]?0x(?:(?:[0-9a-f]*\\.[0-9a-f]+)|(?:[0-9a-f]+[\\.])|(?:[0-9a-f]+)))(?:p([+-]?[0-9]+)))" // hex
|
615
|
+
"|(?:([+-]?[0-9]+)\\s*/\\s*([0]*[1-9][0-9]*))" // rational
|
616
|
+
"|(?:(empty)|(entire)|(nai))" // empty, entire, nai strings
|
617
|
+
")?\\s*\\])"
|
618
|
+
// two arguments separated by a comma
|
619
|
+
"|(?:\\[\\s*("
|
620
|
+
"|(?:([+-]?(?:(?:[0-9]*\\.[0-9]+)|(?:[0-9]+[\\.])|(?:[0-9]+)))(?:e([+-]?[0-9]+))?)" // float
|
621
|
+
"|(?:([+-]?0x(?:(?:[0-9a-f]*\\.[0-9a-f]+)|(?:[0-9a-f]+[\\.])|(?:[0-9a-f]+)))(?:p([+-]?[0-9]+)))" // hex
|
622
|
+
"|(?:([+-]?[0-9]+)\\s*/\\s*([0]*[1-9][0-9]*))" // rational
|
623
|
+
"|(?:-(inf|infinity))" // inf string
|
624
|
+
")?\\s*(,)\\s*("
|
625
|
+
"|(?:([+-]?(?:(?:[0-9]*\\.[0-9]+)|(?:[0-9]+[\\.])|(?:[0-9]+)))(?:e([+-]?[0-9]+))?)" // float
|
626
|
+
"|(?:([+-]?0x(?:(?:[0-9a-f]*\\.[0-9a-f]+)|(?:[0-9a-f]+[\\.])|(?:[0-9a-f]+)))(?:p([+-]?[0-9]+)))" // hex
|
627
|
+
"|(?:([+-]?[0-9]+)\\s*/\\s*([0]*[1-9][0-9]*))" // rational
|
628
|
+
"|(?:[+]?(inf|infinity))" // inf string
|
629
|
+
")?\\s*\\])",
|
630
|
+
std::regex_constants::icase // ignore case
|
631
|
+
);
|
632
|
+
|
633
|
+
|
634
|
+
std::smatch match;
|
635
|
+
if (std::regex_match(input, match, inf_sup_regex))
|
636
|
+
{
|
637
|
+
|
638
|
+
// temporary storage of lower and upper bound
|
639
|
+
representation bare;
|
640
|
+
bare.first = 1.0;
|
641
|
+
bare.second = -1.0;
|
642
|
+
|
643
|
+
// for valid decorations
|
644
|
+
p1788::decoration::decoration dec = p1788::decoration::decoration::com;
|
645
|
+
|
646
|
+
mpfr_var::setup();
|
647
|
+
|
648
|
+
// only one argument or empty string
|
649
|
+
if (match[19].length() == 0)
|
650
|
+
{
|
651
|
+
// empty : string "empty" or only whitespaces
|
652
|
+
if (match[8].length() > 0 || match[1].length() == 0)
|
653
|
+
{
|
654
|
+
bare = empty();
|
655
|
+
dec = p1788::decoration::decoration::trv;
|
656
|
+
}
|
657
|
+
else if (match[9].length() > 0) // entire
|
658
|
+
{
|
659
|
+
bare = entire();
|
660
|
+
dec = p1788::decoration::decoration::dac;
|
661
|
+
}
|
662
|
+
else if (match[10].length() > 0) // nai
|
663
|
+
{
|
664
|
+
bare = empty();
|
665
|
+
dec = p1788::decoration::decoration::ill;
|
666
|
+
}
|
667
|
+
else if (match[2].length() > 0) // float
|
668
|
+
{
|
669
|
+
// number string
|
670
|
+
std::string n_str = match[2].str();
|
671
|
+
|
672
|
+
// compute precision and remove point
|
673
|
+
int p = n_str.find('.');
|
674
|
+
if (p >= 0)
|
675
|
+
{
|
676
|
+
n_str.erase(p,1);
|
677
|
+
p = -(n_str.size() - p);
|
678
|
+
}
|
679
|
+
else
|
680
|
+
{
|
681
|
+
p = 0;
|
682
|
+
}
|
683
|
+
|
684
|
+
// parse number as integer
|
685
|
+
mpz_var n;
|
686
|
+
int i = mpz_set_str(n.var_, n_str.c_str(), 10);
|
687
|
+
|
688
|
+
// everything ok
|
689
|
+
if (i == 0)
|
690
|
+
{
|
691
|
+
// exponent (and precision)
|
692
|
+
if (match[3].length() > 0)
|
693
|
+
{
|
694
|
+
p += std::stoi(match[3].str());
|
695
|
+
}
|
696
|
+
|
697
|
+
mpz_var e;
|
698
|
+
mpz_ui_pow_ui(e.var_, 10, std::abs(p));
|
699
|
+
|
700
|
+
mpq_var exp;
|
701
|
+
mpq_set_z(exp.var_, e.var_);
|
702
|
+
|
703
|
+
// invert if exponent (and precision) is negative
|
704
|
+
if (p < 0)
|
705
|
+
mpq_inv(exp.var_, exp.var_);
|
706
|
+
|
707
|
+
mpq_var q;
|
708
|
+
|
709
|
+
mpq_set_z(q.var_, n.var_);
|
710
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
711
|
+
|
712
|
+
mpfr_var l;
|
713
|
+
mpfr_var u;
|
714
|
+
|
715
|
+
l.subnormalize(mpfr_set_q(l(), q.var_, MPFR_RNDD), MPFR_RNDD);
|
716
|
+
u.subnormalize(mpfr_set_q(u(), q.var_, MPFR_RNDU), MPFR_RNDU);
|
717
|
+
|
718
|
+
if (mpfr_lessequal_p(l(),u()))
|
719
|
+
{
|
720
|
+
bare.first = l.template get<T>(MPFR_RNDD);
|
721
|
+
bare.second = u.template get<T>(MPFR_RNDU);
|
722
|
+
}
|
723
|
+
}
|
724
|
+
}
|
725
|
+
else if (match[4].length() > 0) // hex
|
726
|
+
{
|
727
|
+
// number string
|
728
|
+
std::string n_str = match[4].str();
|
729
|
+
|
730
|
+
// compute precision and remove point
|
731
|
+
int p = n_str.find('.');
|
732
|
+
if (p >= 0)
|
733
|
+
{
|
734
|
+
n_str.erase(p,1);
|
735
|
+
p = -(n_str.size() - p);
|
736
|
+
}
|
737
|
+
else
|
738
|
+
{
|
739
|
+
p = 0;
|
740
|
+
}
|
741
|
+
|
742
|
+
p *= 4;
|
743
|
+
|
744
|
+
// parse number as integer
|
745
|
+
mpz_var n;
|
746
|
+
int i = mpz_set_str(n.var_, n_str.c_str(), 0);
|
747
|
+
|
748
|
+
// everything ok
|
749
|
+
if (i == 0)
|
750
|
+
{
|
751
|
+
// exponent (and precision)
|
752
|
+
p += std::stoi(match[5].str());
|
753
|
+
|
754
|
+
|
755
|
+
mpz_var e;
|
756
|
+
mpz_ui_pow_ui(e.var_, 2, std::abs(p));
|
757
|
+
|
758
|
+
mpq_var exp;
|
759
|
+
mpq_set_z(exp.var_, e.var_);
|
760
|
+
|
761
|
+
// invert if exponent (and precision) is negative
|
762
|
+
if (p < 0)
|
763
|
+
mpq_inv(exp.var_, exp.var_);
|
764
|
+
|
765
|
+
mpq_var q;
|
766
|
+
|
767
|
+
mpq_set_z(q.var_, n.var_);
|
768
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
769
|
+
|
770
|
+
mpfr_var l;
|
771
|
+
mpfr_var u;
|
772
|
+
|
773
|
+
l.subnormalize(mpfr_set_q(l(), q.var_, MPFR_RNDD), MPFR_RNDD);
|
774
|
+
u.subnormalize(mpfr_set_q(u(), q.var_, MPFR_RNDU), MPFR_RNDU);
|
775
|
+
|
776
|
+
if (mpfr_lessequal_p(l(),u()))
|
777
|
+
{
|
778
|
+
bare.first = l.template get<T>(MPFR_RNDD);
|
779
|
+
bare.second = u.template get<T>(MPFR_RNDU);
|
780
|
+
}
|
781
|
+
}
|
782
|
+
}
|
783
|
+
else if (match[6].length() > 0) // rational
|
784
|
+
{
|
785
|
+
mpq_var q;
|
786
|
+
|
787
|
+
int i = mpq_set_str(q.var_, (match[6].str() + "/" + match[7].str()).c_str(), 10);
|
788
|
+
|
789
|
+
mpfr_var l;
|
790
|
+
mpfr_var u;
|
791
|
+
|
792
|
+
l.subnormalize(mpfr_set_q(l(), q.var_, MPFR_RNDD), MPFR_RNDD);
|
793
|
+
u.subnormalize(mpfr_set_q(u(), q.var_, MPFR_RNDU), MPFR_RNDU);
|
794
|
+
|
795
|
+
if (i == 0 && mpfr_lessequal_p(l(),u()))
|
796
|
+
{
|
797
|
+
bare.first = l.template get<T>(MPFR_RNDD);
|
798
|
+
bare.second = u.template get<T>(MPFR_RNDU);
|
799
|
+
}
|
800
|
+
else
|
801
|
+
{
|
802
|
+
bare.first = 1.0;
|
803
|
+
bare.second = -1.0;
|
804
|
+
}
|
805
|
+
}
|
806
|
+
}
|
807
|
+
|
808
|
+
else // two arguments
|
809
|
+
{
|
810
|
+
mpfr_var l;
|
811
|
+
mpfr_var u;
|
812
|
+
|
813
|
+
mpq_var ql;
|
814
|
+
mpq_var qu;
|
815
|
+
|
816
|
+
mpz_var zl;
|
817
|
+
mpz_var zu;
|
818
|
+
|
819
|
+
// lower bound
|
820
|
+
|
821
|
+
// -inf or empty
|
822
|
+
if (match[18].length() > 0 || match[11].length() == 0)
|
823
|
+
{
|
824
|
+
l.set(-std::numeric_limits<T>::infinity(), MPFR_RNDD);
|
825
|
+
dec = p1788::decoration::decoration::dac;
|
826
|
+
}
|
827
|
+
else if (match[12].length() > 0) // float
|
828
|
+
{
|
829
|
+
// number string
|
830
|
+
std::string n_str = match[12].str();
|
831
|
+
|
832
|
+
// compute precision and remove point
|
833
|
+
int p = n_str.find('.');
|
834
|
+
if (p >= 0)
|
835
|
+
{
|
836
|
+
n_str.erase(p,1);
|
837
|
+
p = -(n_str.size() - p);
|
838
|
+
}
|
839
|
+
else
|
840
|
+
{
|
841
|
+
p = 0;
|
842
|
+
}
|
843
|
+
|
844
|
+
// parse number as integer
|
845
|
+
int i = mpz_set_str(zl.var_, n_str.c_str(), 10);
|
846
|
+
|
847
|
+
// everything ok
|
848
|
+
if (i == 0)
|
849
|
+
{
|
850
|
+
// exponent (and precision)
|
851
|
+
if (match[13].length() > 0)
|
852
|
+
{
|
853
|
+
p += std::stoi(match[13].str());
|
854
|
+
}
|
855
|
+
|
856
|
+
mpz_var e;
|
857
|
+
mpz_ui_pow_ui(e.var_, 10, std::abs(p));
|
858
|
+
|
859
|
+
mpq_var exp;
|
860
|
+
mpq_set_z(exp.var_, e.var_);
|
861
|
+
|
862
|
+
// invert if exponent (and precision) is negative
|
863
|
+
if (p < 0)
|
864
|
+
mpq_inv(exp.var_, exp.var_);
|
865
|
+
|
866
|
+
mpq_set_z(ql.var_, zl.var_);
|
867
|
+
mpq_mul(ql.var_, ql.var_, exp.var_);
|
868
|
+
|
869
|
+
l.subnormalize(mpfr_set_q(l(), ql.var_, MPFR_RNDD), MPFR_RNDD);
|
870
|
+
}
|
871
|
+
else
|
872
|
+
l.set(std::numeric_limits<T>::infinity(), MPFR_RNDU);
|
873
|
+
}
|
874
|
+
else if (match[14].length() > 0) // hex
|
875
|
+
{
|
876
|
+
// number string
|
877
|
+
std::string n_str = match[14].str();
|
878
|
+
|
879
|
+
// compute precision and remove point
|
880
|
+
int p = n_str.find('.');
|
881
|
+
if (p >= 0)
|
882
|
+
{
|
883
|
+
n_str.erase(p,1);
|
884
|
+
p = -(n_str.size() - p);
|
885
|
+
}
|
886
|
+
else
|
887
|
+
{
|
888
|
+
p = 0;
|
889
|
+
}
|
890
|
+
|
891
|
+
p *= 4;
|
892
|
+
|
893
|
+
// parse number as integer
|
894
|
+
int i = mpz_set_str(zl.var_, n_str.c_str(), 0);
|
895
|
+
|
896
|
+
// everything ok
|
897
|
+
if (i == 0)
|
898
|
+
{
|
899
|
+
// exponent (and precision)
|
900
|
+
p += std::stoi(match[15].str());
|
901
|
+
|
902
|
+
mpz_var e;
|
903
|
+
mpz_ui_pow_ui(e.var_, 2, std::abs(p));
|
904
|
+
|
905
|
+
mpq_var exp;
|
906
|
+
mpq_set_z(exp.var_, e.var_);
|
907
|
+
|
908
|
+
// invert if exponent (and precision) is negative
|
909
|
+
if (p < 0)
|
910
|
+
mpq_inv(exp.var_, exp.var_);
|
911
|
+
|
912
|
+
mpq_set_z(ql.var_, zl.var_);
|
913
|
+
mpq_mul(ql.var_, ql.var_, exp.var_);
|
914
|
+
|
915
|
+
l.subnormalize(mpfr_set_q(l(), ql.var_, MPFR_RNDD), MPFR_RNDD);
|
916
|
+
}
|
917
|
+
else
|
918
|
+
l.set(std::numeric_limits<T>::infinity(), MPFR_RNDU);
|
919
|
+
}
|
920
|
+
else if (match[16].length() > 0) // rational
|
921
|
+
{
|
922
|
+
int i = mpq_set_str(ql.var_, (match[16].str() + "/" + match[17].str()).c_str(), 10);
|
923
|
+
|
924
|
+
if (i == 0)
|
925
|
+
l.subnormalize(mpfr_set_q(l(), ql.var_, MPFR_RNDD), MPFR_RNDD);
|
926
|
+
else
|
927
|
+
l.set(std::numeric_limits<T>::infinity(), MPFR_RNDU);
|
928
|
+
}
|
929
|
+
|
930
|
+
|
931
|
+
// upper bound
|
932
|
+
|
933
|
+
// +inf or empty
|
934
|
+
if (match[27].length() > 0 || match[20].length() == 0)
|
935
|
+
{
|
936
|
+
u.set(std::numeric_limits<T>::infinity(), MPFR_RNDU);
|
937
|
+
dec = p1788::decoration::decoration::dac;
|
938
|
+
}
|
939
|
+
else if (match[21].length() > 0) // float
|
940
|
+
{
|
941
|
+
// number string
|
942
|
+
std::string n_str = match[21].str();
|
943
|
+
|
944
|
+
// compute precision and remove point
|
945
|
+
int p = n_str.find('.');
|
946
|
+
if (p >= 0)
|
947
|
+
{
|
948
|
+
n_str.erase(p,1);
|
949
|
+
p = -(n_str.size() - p);
|
950
|
+
}
|
951
|
+
else
|
952
|
+
{
|
953
|
+
p = 0;
|
954
|
+
}
|
955
|
+
|
956
|
+
// parse number as integer
|
957
|
+
int i = mpz_set_str(zu.var_, n_str.c_str(), 10);
|
958
|
+
|
959
|
+
// everything ok
|
960
|
+
if (i == 0)
|
961
|
+
{
|
962
|
+
// exponent (and precision)
|
963
|
+
if (match[22].length() > 0)
|
964
|
+
{
|
965
|
+
p += std::stoi(match[22].str());
|
966
|
+
}
|
967
|
+
|
968
|
+
mpz_var e;
|
969
|
+
mpz_ui_pow_ui(e.var_, 10, std::abs(p));
|
970
|
+
|
971
|
+
mpq_var exp;
|
972
|
+
mpq_set_z(exp.var_, e.var_);
|
973
|
+
|
974
|
+
// invert if exponent (and precision) is negative
|
975
|
+
if (p < 0)
|
976
|
+
mpq_inv(exp.var_, exp.var_);
|
977
|
+
|
978
|
+
mpq_set_z(qu.var_, zu.var_);
|
979
|
+
mpq_mul(qu.var_, qu.var_, exp.var_);
|
980
|
+
|
981
|
+
u.subnormalize(mpfr_set_q(u(), qu.var_, MPFR_RNDU), MPFR_RNDU);
|
982
|
+
}
|
983
|
+
else
|
984
|
+
u.set(-std::numeric_limits<T>::infinity(), MPFR_RNDD);
|
985
|
+
}
|
986
|
+
else if (match[23].length() > 0) // hex
|
987
|
+
{
|
988
|
+
// number string
|
989
|
+
std::string n_str = match[23].str();
|
990
|
+
|
991
|
+
// compute precision and remove point
|
992
|
+
int p = n_str.find('.');
|
993
|
+
if (p >= 0)
|
994
|
+
{
|
995
|
+
n_str.erase(p,1);
|
996
|
+
p = -(n_str.size() - p);
|
997
|
+
}
|
998
|
+
else
|
999
|
+
{
|
1000
|
+
p = 0;
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
p *= 4;
|
1004
|
+
|
1005
|
+
// parse number as integer
|
1006
|
+
int i = mpz_set_str(zu.var_, n_str.c_str(), 0);
|
1007
|
+
|
1008
|
+
// everything ok
|
1009
|
+
if (i == 0)
|
1010
|
+
{
|
1011
|
+
// exponent (and precision)
|
1012
|
+
p += std::stoi(match[24].str());
|
1013
|
+
|
1014
|
+
mpz_var e;
|
1015
|
+
mpz_ui_pow_ui(e.var_, 2, std::abs(p));
|
1016
|
+
|
1017
|
+
mpq_var exp;
|
1018
|
+
mpq_set_z(exp.var_, e.var_);
|
1019
|
+
|
1020
|
+
// invert if exponent (and precision) is negative
|
1021
|
+
if (p < 0)
|
1022
|
+
mpq_inv(exp.var_, exp.var_);
|
1023
|
+
|
1024
|
+
mpq_set_z(qu.var_, zu.var_);
|
1025
|
+
mpq_mul(qu.var_, qu.var_, exp.var_);
|
1026
|
+
|
1027
|
+
u.subnormalize(mpfr_set_q(u(), qu.var_, MPFR_RNDU), MPFR_RNDU);
|
1028
|
+
}
|
1029
|
+
else
|
1030
|
+
u.set(-std::numeric_limits<T>::infinity(), MPFR_RNDD);
|
1031
|
+
}
|
1032
|
+
else if (match[25].length() > 0) // rational
|
1033
|
+
{
|
1034
|
+
int i = mpq_set_str(qu.var_, (match[25].str() + "/" + match[26].str()).c_str(), 10);
|
1035
|
+
|
1036
|
+
if (i == 0)
|
1037
|
+
u.subnormalize(mpfr_set_q(u(), qu.var_, MPFR_RNDU), MPFR_RNDU);
|
1038
|
+
else
|
1039
|
+
u.set(-std::numeric_limits<T>::infinity(), MPFR_RNDD);
|
1040
|
+
}
|
1041
|
+
|
1042
|
+
|
1043
|
+
if (mpfr_lessequal_p(l(),u())
|
1044
|
+
&& (
|
1045
|
+
(match[18].length() > 0 || match[11].length() == 0)
|
1046
|
+
|| (match[27].length() > 0 || match[20].length() == 0)
|
1047
|
+
|| (mpq_cmp(ql.var_, qu.var_) <= 0)
|
1048
|
+
)
|
1049
|
+
)
|
1050
|
+
{
|
1051
|
+
bare.first = l.template get<T>(MPFR_RNDD);
|
1052
|
+
bare.second = u.template get<T>(MPFR_RNDU);
|
1053
|
+
}
|
1054
|
+
}
|
1055
|
+
|
1056
|
+
// Check if bounds are valid
|
1057
|
+
if ((std::isnan(bare.first) && std::isnan(bare.second))
|
1058
|
+
|| (bare.first <= bare.second
|
1059
|
+
&& bare.first != std::numeric_limits<T>::infinity()
|
1060
|
+
&& bare.second != -std::numeric_limits<T>::infinity()))
|
1061
|
+
{
|
1062
|
+
|
1063
|
+
// check if it is necessary to read a decoration
|
1064
|
+
bool read_decoration = false;
|
1065
|
+
try
|
1066
|
+
{
|
1067
|
+
read_decoration = is && is.peek() == '_';
|
1068
|
+
}
|
1069
|
+
catch (std::ios_base::failure& e)
|
1070
|
+
{
|
1071
|
+
// rethrow exception if it is not an eof failure
|
1072
|
+
if (!is.eof())
|
1073
|
+
throw;
|
1074
|
+
}
|
1075
|
+
|
1076
|
+
// default decoration
|
1077
|
+
if (!read_decoration)
|
1078
|
+
{
|
1079
|
+
// if is.peek() == '_' reached eof than reset state
|
1080
|
+
if (is.eof())
|
1081
|
+
is.clear(std::ios_base::goodbit);
|
1082
|
+
|
1083
|
+
x = dec == p1788::decoration::decoration::ill ? nai() : new_dec(bare);
|
1084
|
+
|
1085
|
+
// everything was ok
|
1086
|
+
return is;
|
1087
|
+
}
|
1088
|
+
|
1089
|
+
// read decoration
|
1090
|
+
if (is && dec != p1788::decoration::decoration::ill)
|
1091
|
+
{
|
1092
|
+
is.get(); // remove underscore
|
1093
|
+
|
1094
|
+
p1788::decoration::decoration d;
|
1095
|
+
is >> d;
|
1096
|
+
|
1097
|
+
if (is && d <= dec && d != p1788::decoration::decoration::ill)
|
1098
|
+
{
|
1099
|
+
// create dec interval
|
1100
|
+
// and adjust decoration in case of an overflow
|
1101
|
+
x = set_dec(bare,
|
1102
|
+
std::isinf(bare.first) || std::isinf(bare.second) ?
|
1103
|
+
std::min(d, p1788::decoration::decoration::dac)
|
1104
|
+
: d);
|
1105
|
+
|
1106
|
+
// everything was ok
|
1107
|
+
return is;
|
1108
|
+
}
|
1109
|
+
}
|
1110
|
+
}
|
1111
|
+
}
|
1112
|
+
}
|
1113
|
+
}
|
1114
|
+
}
|
1115
|
+
else // uncertain
|
1116
|
+
{
|
1117
|
+
if (is && (is.peek() == '+' || is.peek() == '-' || is.peek() == '.' || std::isdigit(is.peek())))
|
1118
|
+
{
|
1119
|
+
// read string from stream
|
1120
|
+
std::string input;
|
1121
|
+
|
1122
|
+
|
1123
|
+
// read number
|
1124
|
+
for (auto c = is.peek(); is && (std::isdigit(c) || c == '.' || c == '?' || c == '+' || c == '-'); c = is.peek())
|
1125
|
+
{
|
1126
|
+
input += is.get();
|
1127
|
+
|
1128
|
+
if (c == '?')
|
1129
|
+
break;
|
1130
|
+
}
|
1131
|
+
|
1132
|
+
try
|
1133
|
+
{
|
1134
|
+
// read ulps
|
1135
|
+
if(is && is.peek() == '?')
|
1136
|
+
{
|
1137
|
+
input += is.get();
|
1138
|
+
}
|
1139
|
+
else
|
1140
|
+
{
|
1141
|
+
while (is && std::isdigit(is.peek()))
|
1142
|
+
input += is.get();
|
1143
|
+
}
|
1144
|
+
|
1145
|
+
// read direction
|
1146
|
+
if(is && (is.peek() == 'd' || is.peek() == 'D' || is.peek() == 'u' || is.peek() == 'U'))
|
1147
|
+
input += is.get();
|
1148
|
+
|
1149
|
+
|
1150
|
+
// read exponent
|
1151
|
+
if(is && (is.peek() == 'e' || is.peek() == 'E' ))
|
1152
|
+
{
|
1153
|
+
input += is.get();
|
1154
|
+
|
1155
|
+
|
1156
|
+
if(is.good() && (is.peek() == '-' || is.peek() == '+'))
|
1157
|
+
input += is.get();
|
1158
|
+
|
1159
|
+
while (is.good() && std::isdigit(is.peek()))
|
1160
|
+
input += is.get();
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
}
|
1164
|
+
catch (std::ios_base::failure& e)
|
1165
|
+
{
|
1166
|
+
// rethrow if failure was not eof
|
1167
|
+
if (!is.eof())
|
1168
|
+
throw;
|
1169
|
+
}
|
1170
|
+
|
1171
|
+
if (is || is.eof())
|
1172
|
+
{
|
1173
|
+
// regex to match valid literal
|
1174
|
+
// subgroups
|
1175
|
+
// [1] number
|
1176
|
+
// [2] infinite radius
|
1177
|
+
// [3] ulps radius
|
1178
|
+
// [4] direction upward
|
1179
|
+
// [5] direction downward
|
1180
|
+
// [6] exponent
|
1181
|
+
static std::regex uncertain_regex(
|
1182
|
+
"([+-]?(?:(?:[0-9]*\\.[0-9]+)|(?:[0-9]+[\\.])|(?:[0-9]+)))" // number
|
1183
|
+
"\\?" // ?
|
1184
|
+
"(?:(\\?)|([0-9]+))?" // radius
|
1185
|
+
"(?:(u|U)|(d|D))?" // direction
|
1186
|
+
"(?:[eE]([+-]?[0-9]+))?", // exponent
|
1187
|
+
std::regex_constants::icase // ignore case
|
1188
|
+
);
|
1189
|
+
|
1190
|
+
std::smatch match;
|
1191
|
+
if (std::regex_match(input, match, uncertain_regex))
|
1192
|
+
{
|
1193
|
+
// temporary storage of lower and upper bound
|
1194
|
+
representation bare;
|
1195
|
+
|
1196
|
+
// for valid decorations
|
1197
|
+
p1788::decoration::decoration dec = p1788::decoration::decoration::com;
|
1198
|
+
|
1199
|
+
mpfr_var::setup();
|
1200
|
+
|
1201
|
+
mpfr_var l;
|
1202
|
+
mpfr_var u;
|
1203
|
+
|
1204
|
+
// number string
|
1205
|
+
std::string m_str = match[1].str();
|
1206
|
+
|
1207
|
+
// compute precision and remove point
|
1208
|
+
int p = m_str.find('.');
|
1209
|
+
if (p >= 0)
|
1210
|
+
{
|
1211
|
+
m_str.erase(p,1);
|
1212
|
+
p = -(m_str.size() - p);
|
1213
|
+
}
|
1214
|
+
else
|
1215
|
+
{
|
1216
|
+
p = 0;
|
1217
|
+
}
|
1218
|
+
|
1219
|
+
// parse number as integer
|
1220
|
+
mpz_var m;
|
1221
|
+
int im = mpz_set_str(m.var_, m_str.c_str(), 10);
|
1222
|
+
|
1223
|
+
mpz_var ulps;
|
1224
|
+
int iu = 0;
|
1225
|
+
|
1226
|
+
// computing ulps
|
1227
|
+
if (match[3].length() > 0 )
|
1228
|
+
iu = mpz_set_str(ulps.var_, match[3].str().c_str(), 10);
|
1229
|
+
else
|
1230
|
+
{
|
1231
|
+
// 1/2 ulp => m * 10 and ulps=5
|
1232
|
+
mpz_set_si(ulps.var_, 5);
|
1233
|
+
p--;
|
1234
|
+
mpz_mul_si(m.var_, m.var_, 10);
|
1235
|
+
}
|
1236
|
+
|
1237
|
+
// everything ok
|
1238
|
+
if (im == 0 && iu == 0)
|
1239
|
+
{
|
1240
|
+
// exponent (and precision)
|
1241
|
+
if (match[6].length() > 0)
|
1242
|
+
{
|
1243
|
+
p += std::stoi(match[6].str());
|
1244
|
+
}
|
1245
|
+
|
1246
|
+
mpz_var e;
|
1247
|
+
mpz_ui_pow_ui(e.var_, 10, std::abs(p));
|
1248
|
+
|
1249
|
+
mpq_var exp;
|
1250
|
+
mpq_set_z(exp.var_, e.var_);
|
1251
|
+
|
1252
|
+
// invert if exponent (and precision) is negative
|
1253
|
+
if (p < 0)
|
1254
|
+
mpq_inv(exp.var_, exp.var_);
|
1255
|
+
|
1256
|
+
|
1257
|
+
// compute radius
|
1258
|
+
if (match[2].length() > 0) // "?" => infinity
|
1259
|
+
{
|
1260
|
+
// compute bounds
|
1261
|
+
if (match[4].length() > 0) // upward
|
1262
|
+
{
|
1263
|
+
mpq_var q;
|
1264
|
+
mpq_set_z(q.var_, m.var_);
|
1265
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
1266
|
+
|
1267
|
+
l.subnormalize(mpfr_set_q(l(), q.var_, MPFR_RNDD), MPFR_RNDD);
|
1268
|
+
u.set(std::numeric_limits<T>::infinity(), MPFR_RNDU);
|
1269
|
+
}
|
1270
|
+
else if (match[5].length() > 0) // downward
|
1271
|
+
{
|
1272
|
+
mpq_var q;
|
1273
|
+
mpq_set_z(q.var_, m.var_);
|
1274
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
1275
|
+
|
1276
|
+
l.set(-std::numeric_limits<T>::infinity(), MPFR_RNDD);
|
1277
|
+
u.subnormalize(mpfr_set_q(u(), q.var_, MPFR_RNDU), MPFR_RNDU);
|
1278
|
+
}
|
1279
|
+
else // symmetric
|
1280
|
+
{
|
1281
|
+
l.set(-std::numeric_limits<T>::infinity(), MPFR_RNDD);
|
1282
|
+
u.set(std::numeric_limits<T>::infinity(), MPFR_RNDU);
|
1283
|
+
}
|
1284
|
+
|
1285
|
+
dec = p1788::decoration::decoration::dac;
|
1286
|
+
}
|
1287
|
+
else
|
1288
|
+
{
|
1289
|
+
|
1290
|
+
// compute bounds
|
1291
|
+
if (match[4].length() > 0) // upward
|
1292
|
+
{
|
1293
|
+
mpq_var q;
|
1294
|
+
|
1295
|
+
mpq_set_z(q.var_, m.var_);
|
1296
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
1297
|
+
|
1298
|
+
l.subnormalize(mpfr_set_q(l(), q.var_, MPFR_RNDD), MPFR_RNDD);
|
1299
|
+
|
1300
|
+
mpz_add(m.var_, m.var_, ulps.var_);
|
1301
|
+
mpq_set_z(q.var_, m.var_);
|
1302
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
1303
|
+
|
1304
|
+
u.subnormalize(mpfr_set_q(u(), q.var_, MPFR_RNDU), MPFR_RNDU);
|
1305
|
+
}
|
1306
|
+
else if (match[5].length() > 0) // downward
|
1307
|
+
{
|
1308
|
+
mpq_var q;
|
1309
|
+
|
1310
|
+
mpq_set_z(q.var_, m.var_);
|
1311
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
1312
|
+
|
1313
|
+
u.subnormalize(mpfr_set_q(u(), q.var_, MPFR_RNDU), MPFR_RNDU);
|
1314
|
+
|
1315
|
+
mpz_sub(m.var_, m.var_, ulps.var_);
|
1316
|
+
mpq_set_z(q.var_, m.var_);
|
1317
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
1318
|
+
|
1319
|
+
l.subnormalize(mpfr_set_q(l(), q.var_, MPFR_RNDD), MPFR_RNDD);
|
1320
|
+
}
|
1321
|
+
else // symmetric
|
1322
|
+
{
|
1323
|
+
mpz_var tmp;
|
1324
|
+
mpq_var q;
|
1325
|
+
|
1326
|
+
mpz_sub(tmp.var_, m.var_, ulps.var_);
|
1327
|
+
mpq_set_z(q.var_, tmp.var_);
|
1328
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
1329
|
+
|
1330
|
+
l.subnormalize(mpfr_set_q(l(), q.var_, MPFR_RNDD), MPFR_RNDD);
|
1331
|
+
|
1332
|
+
mpz_add(tmp.var_, m.var_, ulps.var_);
|
1333
|
+
mpq_set_z(q.var_, tmp.var_);
|
1334
|
+
mpq_mul(q.var_, q.var_, exp.var_);
|
1335
|
+
|
1336
|
+
u.subnormalize(mpfr_set_q(u(), q.var_, MPFR_RNDU), MPFR_RNDU);
|
1337
|
+
}
|
1338
|
+
|
1339
|
+
}
|
1340
|
+
|
1341
|
+
bare.first = l.template get<T>(MPFR_RNDD);
|
1342
|
+
bare.second = u.template get<T>(MPFR_RNDU);
|
1343
|
+
|
1344
|
+
// Check if bounds are valid
|
1345
|
+
if (bare.first <= bare.second
|
1346
|
+
&& bare.first != std::numeric_limits<T>::infinity()
|
1347
|
+
&& bare.second != -std::numeric_limits<T>::infinity())
|
1348
|
+
{
|
1349
|
+
|
1350
|
+
// check if it is necessary to read a decoration
|
1351
|
+
bool read_decoration = false;
|
1352
|
+
try
|
1353
|
+
{
|
1354
|
+
read_decoration = is && is.peek() == '_';
|
1355
|
+
}
|
1356
|
+
catch (std::ios_base::failure& e)
|
1357
|
+
{
|
1358
|
+
// rethrow exception if it is not an eof failure
|
1359
|
+
if (!is.eof())
|
1360
|
+
throw;
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
// default decoration
|
1364
|
+
if (!read_decoration)
|
1365
|
+
{
|
1366
|
+
// if is.peek() == '_' reached eof than reset state
|
1367
|
+
if (is.eof())
|
1368
|
+
is.clear(std::ios_base::goodbit);
|
1369
|
+
|
1370
|
+
x = dec == p1788::decoration::decoration::ill ? nai() : new_dec(bare);
|
1371
|
+
|
1372
|
+
// everything was ok
|
1373
|
+
return is;
|
1374
|
+
}
|
1375
|
+
|
1376
|
+
// read decoration
|
1377
|
+
if (is && dec != p1788::decoration::decoration::ill)
|
1378
|
+
{
|
1379
|
+
is.get(); // remove underscore
|
1380
|
+
|
1381
|
+
p1788::decoration::decoration d;
|
1382
|
+
is >> d;
|
1383
|
+
|
1384
|
+
if (is && d <= dec && d != p1788::decoration::decoration::ill)
|
1385
|
+
{
|
1386
|
+
// create dec interval
|
1387
|
+
// and adjust decoration in case of an overflow
|
1388
|
+
x = set_dec(bare,
|
1389
|
+
std::isinf(bare.first) || std::isinf(bare.second) ?
|
1390
|
+
std::min(d, p1788::decoration::decoration::dac)
|
1391
|
+
: d);
|
1392
|
+
|
1393
|
+
// everything was ok
|
1394
|
+
return is;
|
1395
|
+
}
|
1396
|
+
}
|
1397
|
+
}
|
1398
|
+
}
|
1399
|
+
}
|
1400
|
+
}
|
1401
|
+
}
|
1402
|
+
}
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
// failed
|
1406
|
+
is.setstate(std::ios_base::failbit);
|
1407
|
+
|
1408
|
+
return is;
|
1409
|
+
}
|
1410
|
+
|
1411
|
+
|
1412
|
+
} // namespace setbased
|
1413
|
+
|
1414
|
+
} // namespace infsup
|
1415
|
+
|
1416
|
+
} // namespace flavor
|
1417
|
+
|
1418
|
+
} // namespace p1788
|
1419
|
+
|
1420
|
+
|
1421
|
+
#endif // LIBIEEEP1788_P1788_FLAVOR_INFSUP_SETBASED_MPFR_BIN_IEEE754_FLAVOR_IO_IMPL_HPP
|