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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/AUTHORS +6 -0
  4. data/LICENSE +201 -0
  5. data/NOTICE +29 -0
  6. data/README.md +65 -0
  7. data/ext/libieeep1788_copy/README +3 -0
  8. data/ext/libieeep1788_copy/p1788/AUTHORS +16 -0
  9. data/ext/libieeep1788_copy/p1788/LICENSE +202 -0
  10. data/ext/libieeep1788_copy/p1788/NOTICE +14 -0
  11. data/ext/libieeep1788_copy/p1788/decoration/decoration.hpp +265 -0
  12. data/ext/libieeep1788_copy/p1788/exception/exception.hpp +302 -0
  13. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor.hpp +3443 -0
  14. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_bool_func_impl.hpp +608 -0
  15. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_cancel_func_impl.hpp +229 -0
  16. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_class_impl.hpp +526 -0
  17. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_elem_func_impl.hpp +4533 -0
  18. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_io_impl.hpp +1421 -0
  19. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_mul_rev_to_pair_func_impl.hpp +347 -0
  20. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_num_func_impl.hpp +655 -0
  21. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_rec_bool_func_impl.hpp +146 -0
  22. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_rec_overlap_impl.hpp +188 -0
  23. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_rev_func_impl.hpp +1674 -0
  24. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_set_op_impl.hpp +216 -0
  25. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_setup_func_impl.hpp +68 -0
  26. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_util_func_impl.hpp +135 -0
  27. data/ext/libieeep1788_copy/p1788/flavor/infsup/setbased/mpfr_bin_ieee754_flavor_validation_func_impl.hpp +93 -0
  28. data/ext/libieeep1788_copy/p1788/infsup/base_interval.hpp +1529 -0
  29. data/ext/libieeep1788_copy/p1788/infsup/base_interval_bool_func_impl.hpp +481 -0
  30. data/ext/libieeep1788_copy/p1788/infsup/base_interval_cancel_func_impl.hpp +126 -0
  31. data/ext/libieeep1788_copy/p1788/infsup/base_interval_elem_func_impl.hpp +1581 -0
  32. data/ext/libieeep1788_copy/p1788/infsup/base_interval_io_impl.hpp +59 -0
  33. data/ext/libieeep1788_copy/p1788/infsup/base_interval_mul_rev_to_pair_func_impl.hpp +88 -0
  34. data/ext/libieeep1788_copy/p1788/infsup/base_interval_num_func_impl.hpp +345 -0
  35. data/ext/libieeep1788_copy/p1788/infsup/base_interval_rec_bool_func_impl.hpp +92 -0
  36. data/ext/libieeep1788_copy/p1788/infsup/base_interval_rec_overlap_impl.hpp +72 -0
  37. data/ext/libieeep1788_copy/p1788/infsup/base_interval_rev_func_impl.hpp +656 -0
  38. data/ext/libieeep1788_copy/p1788/infsup/base_interval_set_op_impl.hpp +126 -0
  39. data/ext/libieeep1788_copy/p1788/infsup/decorated_interval.hpp +464 -0
  40. data/ext/libieeep1788_copy/p1788/infsup/forward_declaration.hpp +66 -0
  41. data/ext/libieeep1788_copy/p1788/infsup/interval.hpp +275 -0
  42. data/ext/libieeep1788_copy/p1788/io/io_manip.hpp +531 -0
  43. data/ext/libieeep1788_copy/p1788/overlapping/overlapping.hpp +241 -0
  44. data/ext/libieeep1788_copy/p1788/p1788.hpp +45 -0
  45. data/ext/libieeep1788_copy/p1788/reduction/reduction.hpp +341 -0
  46. data/ext/libieeep1788_copy/p1788/util/io.hpp +63 -0
  47. data/ext/libieeep1788_copy/p1788/util/mixed_type_traits.hpp +140 -0
  48. data/ext/libieeep1788_copy/p1788/util/mpfr_util.hpp +77 -0
  49. data/ext/libieeep1788_copy/p1788/util/mpfr_var.hpp +119 -0
  50. data/ext/libieeep1788_copy/p1788/util/mpfr_var_impl.hpp +382 -0
  51. data/ext/libieeep1788_copy/p1788/version.hpp +34 -0
  52. data/ext/p1788/extconf.rb +49 -0
  53. data/ext/p1788/p1788.cc +3764 -0
  54. data/lib/p1788/version.rb +4 -0
  55. data/lib/p1788.rb +25 -0
  56. data/p1788.gemspec +72 -0
  57. 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