Garfield++ v1r0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
DoubleAc.cpp
Go to the documentation of this file.
1/*
2Copyright (c) 2001 Igor B. Smirnov
3
4The file can be used, copied, modified, and distributed
5according to the terms of GNU Lesser General Public License version 2.1
6as published by the Free Software Foundation,
7and provided that the above copyright notice, this permission notice,
8and notices about any modifications of the original text
9appear in all copies and in supporting documentation.
10The file is provided "as is" without express or implied warranty.
11*/
12#include <iomanip>
14#include "wcpplib/math/minmax.h"
16
17DoubleAc::DoubleAc(double f, double ffmin, double ffmax) {
18 mfunname("DoubleAc::DoubleAc(double f, double ffmin, double ffmax)");
19 check_econd12a(f, <, ffmin, "f - ffmin=" << f - ffmin << '\n', mcerr);
20 check_econd12a(f, >, ffmax, "f - ffmax=" << f - ffmax << '\n', mcerr);
21 di = ffmin;
22 d = f;
23 da = ffmax;
24}
25
26DoubleAc::DoubleAc(double f, double relative_prec) {
27 mfunname("DoubleAc::DoubleAc(double f, double relative_prec)");
28 check_econd11(relative_prec, < 0, mcerr);
29 check_econd11(relative_prec, >= 1, mcerr);
30 d = f;
31 if (f >= 0) {
32 da = f * (1.0 + relative_prec);
33 di = f / (1.0 + relative_prec);
34 } else {
35 di = f * (1.0 + relative_prec);
36 da = f / (1.0 + relative_prec);
37 }
38}
39
41 mfunnamep("DoubleAc& DoubleAc::operator*=(const DoubleAc& f)");
42#ifdef DEBUG_OPERATOR_MULT_PRINT
43 mcout.precision(17);
44 mcout << "d=" << d << '\n';
45 mcout << "di=" << di << '\n';
46 mcout << "da=" << da << '\n';
47 mcout << "f.d=" << f.d << '\n';
48 mcout << "f.di=" << f.di << '\n';
49 mcout << "f.da=" << f.da << '\n';
50#endif
51#ifndef VISUAL_STUDIO
52 if (std::isnan(di) == 1) di = -DBL_MAX;
53 if (std::isnan(da) == 1) da = DBL_MAX;
54 if (std::isnan(f.di) == 1) f.di = -DBL_MAX;
55 if (std::isnan(f.da) == 1) f.da = DBL_MAX;
56#else
57 if (_isnan(di) == 1) di = -DBL_MAX;
58 if (_isnan(da) == 1) da = DBL_MAX;
59 if (_isnan(f.di) == 1) f.di = -DBL_MAX;
60 if (_isnan(f.da) == 1) f.da = DBL_MAX;
61#endif
62#ifdef POSSIBLE_FAILURE_ISNAN
63 if (!(di < d) && !(di >= d)) di = -DBL_MAX;
64 if (!(da < d) && !(da >= d)) da = DBL_MAX;
65 if (!(f.di < f.d) && !(f.di >= f.d)) f.di = -DBL_MAX;
66 if (!(f.da < f.d) && !(f.da >= f.d)) f.da = DBL_MAX;
67#endif
68#ifdef DEBUG_OPERATOR_MULT
69 DoubleAc temp(*this); // for debug
70#endif
71 d *= f.d;
72 if (di >= 0) {
73 if (f.di >= 0) {
74 di *= f.di;
75 da *= f.da;
76#ifdef DEBUG_OPERATOR_MULT_PRINT
77 mcout << "case 1\n";
78#endif
79 } else if (f.da >= 0) // assumed that f.di < 0
80 {
81 di = f.di * da;
82 da *= f.da;
83#ifdef DEBUG_OPERATOR_MULT_PRINT
84 mcout << "case 2\n";
85#endif
86 } else // assumed that f.da < 0
87 {
88 double ti = da * f.di;
89 da = di * f.da;
90 di = ti;
91#ifdef DEBUG_OPERATOR_MULT_PRINT
92 mcout << "case 3\n";
93#endif
94 }
95 } else if (da >= 0) // assumed that di < 0
96 {
97 if (f.di >= 0) {
98 di *= f.da;
99 da *= f.da;
100#ifdef DEBUG_OPERATOR_MULT_PRINT
101 mcout << "case 4\n";
102#endif
103 } else if (f.da >= 0) {
104 double ti = find_min(di * f.da, da * f.di);
105 da = find_max(di * f.di, da * f.da);
106 di = ti;
107#ifdef DEBUG_OPERATOR_MULT_PRINT
108 mcout << "case 5\n";
109#endif
110 } else {
111 double ti = da * f.di;
112 da = di * f.di;
113 di = ti;
114#ifdef DEBUG_OPERATOR_MULT_PRINT
115 mcout << "case 6\n";
116#endif
117 }
118 } else // assumed that di < 0 and da < 0
119 {
120 if (f.di >= 0) {
121 di *= f.da;
122 da *= f.di;
123#ifdef DEBUG_OPERATOR_MULT_PRINT
124 mcout << "case 7\n";
125#endif
126 } else if (f.da >= 0) {
127 double ti = di * f.da;
128 da = di * f.di;
129 di = ti;
130#ifdef DEBUG_OPERATOR_MULT_PRINT
131 mcout << "case 8\n";
132#endif
133 } else {
134 double ti = da * f.da;
135 da = di * f.di;
136 di = ti;
137#ifdef DEBUG_OPERATOR_MULT_PRINT
138 mcout << "case 8\n";
139#endif
140 }
141 }
142//mcout<<"d="<<d<<'\n';
143//mcout<<"di="<<di<<'\n';
144//mcout<<"da="<<da<<'\n';
145#ifdef CHECK_CORRECTNESS_AT_MULT
146 if (d < di) {
147 if (d - di == 0.0) // strange but at Sc. Linux 4.0 with -O2 this happens
148 goto mend; // but this precation does not cure!
149 funnw.ehdr(mcerr);
150 mcerr << "d < di at the end of computations\n";
151 mcerr << "This number:\n";
152 print(mcerr, 6);
153 mcerr << "Argument:\n";
154 f.print(mcerr, 6);
155 if (d > di) mcerr << "if(d > di) is also positive\n";
156 if (d == di) mcerr << "if(d == di) is also positive\n";
157 Iprintn(mcerr, d - di);
158#ifdef DEBUG_OPERATOR_MULT
159 // for debug:
160 mcerr << "old value:\n";
161 temp.print(mcerr, 6);
162#endif
163 spexit(mcerr);
164 }
165 if (d > da) {
166 if (d == da) // strange but at Sc. Linux 4.0 with O2 this happens
167 goto mend;
168 funnw.ehdr(mcerr);
169 mcerr << "d > di at the end of computations\n";
170 mcerr << "This number:\n";
171 print(mcerr, 6);
172 mcerr << "Argument:\n";
173 f.print(mcerr, 6);
174 if (d < da) mcerr << "if(d < da) is also positive\n";
175 if (d == da) mcerr << "if(d == da) is also positive\n";
176 Iprintn(mcerr, d - da);
177#ifdef DEBUG_OPERATOR_MULT
178 // for debug:
179 mcerr << "old value:\n";
180 temp.print(mcerr, 6);
181#endif
182 spexit(mcerr);
183 }
184mend:
185#endif
186 return *this;
187}
188
190 mfunnamep("DoubleAc& DoubleAc::operator/=(const DoubleAc& f)");
191 check_econd11(f.d, == 0, mcerr);
192 check_econd11(f.d, == 0.0, mcerr);
193#ifndef VISUAL_STUDIO
194 if (std::isnan(di) == 1) di = -DBL_MAX;
195 if (std::isnan(da) == 1) da = DBL_MAX;
196 if (std::isnan(f.di) == 1) f.di = -DBL_MAX;
197 if (std::isnan(f.da) == 1) f.da = DBL_MAX;
198#else
199 if (_isnan(di) == 1) di = -DBL_MAX;
200 if (_isnan(da) == 1) da = DBL_MAX;
201 if (_isnan(f.di) == 1) f.di = -DBL_MAX;
202 if (_isnan(f.da) == 1) f.da = DBL_MAX;
203#endif
204#ifdef POSSIBLE_FAILURE_ISNAN
205 if (!(di < d) && !(di >= d)) di = -DBL_MAX;
206 if (!(da < d) && !(da >= d)) da = DBL_MAX;
207 if (!(f.di < f.d) && !(f.di >= f.d)) f.di = -DBL_MAX;
208 if (!(f.da < f.d) && !(f.da >= f.d)) f.da = DBL_MAX;
209#endif
210
211 d /= f.d;
212 if (f.di < 0 && f.da > 0) {
213 di = -DBL_MAX;
214 da = DBL_MAX;
215 } else if (di >= 0) {
216 if (f.di > 0) {
217 di /= f.da;
218 da /= f.di;
219 } else if (f.di == 0) {
220 di /= f.da;
221 da = DBL_MAX;
222 } else {
223 if (f.da == 0) {
224 da = di / f.di;
225 di = -DBL_MAX;
226 } else {
227 double ti = da / f.da;
228 //mcout<<"d="<<d<<" ti="<<ti<<'\n';
229 da = di / f.di;
230 di = ti;
231 }
232 }
233 } else if (da >= 0) {
234 if (f.di > 0) {
235 di /= f.di;
236 da /= f.di;
237 } else if (f.di == 0) {
238 di = -DBL_MAX;
239 da = DBL_MAX;
240 } else {
241 if (f.da == 0) {
242 da = DBL_MAX;
243 di = -DBL_MAX;
244 } else {
245 double ti = da / f.da;
246 da = di / f.da;
247 di = ti;
248 }
249 }
250 } else {
251 // assumed da < 0
252 if (f.di > 0) {
253 di /= f.di;
254 da /= f.da;
255 } else if (f.di == 0) {
256 di = -DBL_MAX;
257 //check_econd11(f.da , == 0 , mcerr); // otherwise f.d == 0 which
258 // was already rejected
259 if (f.da == 0) {
260 funnw.ehdr(mcerr);
261 mcerr << "f.da == 0\n";
262 mcerr << "This means that f.d == 0 which should been already "
263 << "rejected.\n";
264 mcerr << "If the program reaches this point, this means that\n"
265 << "f.d is not between f.di and f.da, which is prohibited\n";
266 mcerr << "f :\n";
267 f.print(mcerr, 6);
268 spexit(mcerr);
269 }
270 da /= f.da;
271 } else {
272 if (f.da == 0) {
273 di = da / f.di;
274 da = DBL_MAX;
275 } else {
276 double ti = da / f.di;
277 da = di / f.da;
278 di = ti;
279 }
280 }
281 }
282#ifdef CHECK_CORRECTNESS_AT_MULT
283 if (d < di) {
284 funnw.ehdr(mcerr);
285 mcerr << "d < di at the end of computations\n";
286 mcerr << "This number:\n";
287 print(mcerr, 6);
288 mcerr << "Argument:\n";
289 f.print(mcerr, 6);
290 // for debug:
291 //mcerr<<"old value:\n";
292 //temp.print(mcerr, 6);
293 spexit(mcerr);
294 }
295 if (d > da) {
296 funnw.ehdr(mcerr);
297 mcerr << "d > di at the end of computations\n";
298 mcerr << "This number:\n";
299 print(mcerr, 6);
300 mcerr << "Argument:\n";
301 f.print(mcerr, 6);
302 // for debug:
303 //mcerr<<"old value:\n";
304 //temp.print(mcerr, 6);
305 spexit(mcerr);
306 }
307#endif
308 //check_econd12(d , < , di , mcerr);
309 //check_econd12(d , > , da , mcerr);
310 return *this;
311}
312
314 if (f.get() < 0) {
315 mcerr << "error in DoubleAc sqrt(const DoubleAc& f): f.get() < 0, f.get()="
316 << f.get() << '\n';
317 spexit(mcerr);
318 }
319 return DoubleAc(std::sqrt(double(f.get())),
320 std::sqrt(double(find_max(f.get_left_limit(), 0.0))),
321 std::sqrt(double(f.get_right_limit())));
322}
323
325 if (f.left_limit() >= 0.0) {
326 return DoubleAc(f.get() * f.get(), f.left_limit() * f.left_limit(),
327 f.right_limit() * f.right_limit());
328 } else if (f.right_limit() >= 0.0) {
329 double t = find_max(-f.left_limit(), f.right_limit());
330 return DoubleAc(f.get() * f.get(), 0.0, t * t);
331 }
332 return DoubleAc(f.get() * f.get(), f.right_limit() * f.right_limit(),
333 f.left_limit() * f.left_limit());
334}
335
336DoubleAc pow(const DoubleAc& f, double p) {
337 if (p == 1) return f;
338 if (p == 0) return DoubleAc(1.0);
339 if (p > 0) {
340 double d = std::pow(f.get(), p);
341 double di = std::pow(f.left_limit(), p);
342 double da = std::pow(f.right_limit(), p);
343 if (f.left_limit() >= 0.0) {
344 return DoubleAc(d, di, da);
345 } else if (f.right_limit() >= 0.0) {
346 if (di < 0.0)
347 return DoubleAc(d, di, da);
348 else // the power is even
349 return DoubleAc(d, 0.0, find_max(di, da));
350 } else {
351 if (di < 0.0)
352 return DoubleAc(d, di, da);
353 else // the power is even
354 return DoubleAc(d, da, di);
355 }
356 } else {
357 double d = std::pow(f.get(), -p);
358 double di = std::pow(f.left_limit(), -p);
359 double da = std::pow(f.right_limit(), -p);
360 if (f.left_limit() >= 0.0) {
361 return 1.0 / DoubleAc(d, di, da);
362 } else if (f.right_limit() >= 0.0) {
363 if (di < 0.0)
364 return 1.0 / DoubleAc(d, di, da);
365 else // the power is even
366 return 1.0 / DoubleAc(d, 0.0, find_max(di, da));
367 } else {
368 if (di < 0.0)
369 return 1.0 / DoubleAc(d, di, da);
370 else // the power is even
371 return 1.0 / DoubleAc(d, da, di);
372 }
373 }
374}
375
377 double d = std::exp(f.get());
378 double di = std::exp(f.left_limit());
379 double da = std::exp(f.right_limit());
380 return DoubleAc(d, di, da);
381}
382
384 //mcout<<"DoubleAc sin is starting, f="; f.print(mcout, 3);
385 double d = std::sin(f.get());
386 double di = std::sin(f.left_limit());
387 double da = std::sin(f.right_limit());
388 //Iprintn(mcout, d);
389 //Iprintn(mcout, di);
390 //Iprintn(mcout, da);
391 long n = left_round(f.get() / M_PI + 0.5);
392 long ni = left_round(f.left_limit() / M_PI + 0.5);
393 long na = left_round(f.right_limit() / M_PI + 0.5);
394 //Iprintn(mcout, n);
395 //Iprintn(mcout, ni);
396 //Iprintn(mcout, na);
397 int seven = even_num(n);
398 //Iprintn(mcout, seven);
399 if (seven == 1) {
400 if (ni < n) {
401 di = -1.0;
402 da = find_max(di, da);
403 if (na > n) {
404 da = 1.0;
405 }
406 } else if (na > n) {
407 da = 1.0;
408 di = find_min(di, da);
409 }
410 } else {
411 double temp = di;
412 di = da;
413 da = temp;
414 if (ni < n) {
415 da = 1.0;
416 di = find_min(di, da);
417 if (na > n) {
418 di = -1.0;
419 }
420 } else if (na > n) {
421 di = -1.0;
422 da = find_max(di, da);
423 }
424 }
425 //Iprintn(mcout, d);
426 //Iprintn(mcout, di);
427 //Iprintn(mcout, da);
428 return DoubleAc(d, di, da);
429}
430
432 double d = std::cos(f.get());
433 double di = std::cos(f.left_limit());
434 double da = std::cos(f.right_limit());
435 long n = left_round(f.get() / M_PI - 1.0);
436 long ni = left_round(f.left_limit() / M_PI - 1.0);
437 long na = left_round(f.right_limit() / M_PI - 1.0);
438 int seven = even_num(n);
439 if (seven == 1) {
440 if (ni < n) {
441 di = -1.0;
442 da = find_max(di, da);
443 if (na > n) {
444 da = 1.0;
445 }
446 } else if (na > n) {
447 da = 1.0;
448 di = find_min(di, da);
449 }
450 } else {
451 double temp = di;
452 di = da;
453 da = temp;
454 if (ni < n) {
455 da = 1.0;
456 di = find_min(di, da);
457 if (na > n) {
458 di = -1.0;
459 }
460 } else if (na > n) {
461 di = -1.0;
462 da = find_max(di, da);
463 }
464 }
465 return DoubleAc(d, di, da);
466}
467
469 if (fabs(f.get()) > 1) {
470 mcerr << "ERROR in inline DoubleAc asin(const DoubleAc& f):\n"
471 << "fabs(f.get()) > 1: f.get()=" << f.get() << '\n';
472 spexit(mcerr);
473 }
474 double d = std::asin(f.get());
475 double di;
476 if (f.left_limit() < -1.0)
477 di = std::asin(-1.0);
478 else
479 di = std::asin(f.left_limit());
480 double da;
481 if (f.right_limit() > 1.0)
482 da = std::asin(1.0);
483 else
484 da = std::asin(f.right_limit());
485 return DoubleAc(d, di, da);
486}
487
489 if (fabs(f.get()) > 1) {
490 mcerr << "ERROR in inline DoubleAc acos(const DoubleAc& f):\n"
491 << "fabs(f.get()) > 1: f.get()=" << f.get() << '\n';
492 spexit(mcerr);
493 }
494 double d = std::acos(f.get());
495 double da;
496 if (f.left_limit() < -1.0)
497 da = std::acos(-1.0);
498 else
499 da = std::acos(f.left_limit());
500 double di;
501 if (f.right_limit() > 1.0)
502 di = std::acos(1.0);
503 else
504 di = std::acos(f.right_limit());
505 return DoubleAc(d, di, da);
506}
507
508void DoubleAc::print(std::ostream& file, int l) const {
509 if (l <= 0) return;
510 if (l == 1) {
511 file << d;
512 } else if (l == 2) {
513 file << d << " [ " << di << " , " << da << " ] ";
514 } else if (l == 3) {
515 file << d;
516 int t = file.precision(2);
517 file << " [" << std::setw(8) << d - di << "," << std::setw(8) << da - d
518 << "] ";
519 file.precision(t);
520 } else if (l == 4) {
521 file << d << " [ " << di << " , " << da << " ] \n";
522 } else if (l == 5) {
523 file << d;
524 int t = file.precision(2);
525 file << " [" << std::setw(8) << d - di << "," << std::setw(8) << da - d
526 << "] \n";
527 file.precision(t);
528 } else {
529 int t = file.precision(16);
530 file << "DoubleAc: d=" << std::setw(20) << d << " di=" << std::setw(20)
531 << di << " da=" << std::setw(20) << da << '\n';
532 file.precision(t);
533 }
534}
535
536DoubleAc pow(const DoubleAc& /*f*/, const DoubleAc& /*p*/) {
537 mcerr << "ERROR in inline DoubleAc pow(const DoubleAc& f, const DoubleAc& "
538 "p):\n";
539 mcerr << "not implemented yet\n";
540 spexit(mcerr);
541 return 0.0;
542}
543
544std::ostream& operator<<(std::ostream& file, const DoubleAc& f) {
545 f.print(file, 1);
546 return file;
547}
DoubleAc cos(const DoubleAc &f)
Definition: DoubleAc.cpp:431
DoubleAc asin(const DoubleAc &f)
Definition: DoubleAc.cpp:468
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:336
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:313
DoubleAc square(const DoubleAc &f)
Definition: DoubleAc.cpp:324
DoubleAc sin(const DoubleAc &f)
Definition: DoubleAc.cpp:383
std::ostream & operator<<(std::ostream &file, const DoubleAc &f)
Definition: DoubleAc.cpp:544
DoubleAc acos(const DoubleAc &f)
Definition: DoubleAc.cpp:488
DoubleAc exp(const DoubleAc &f)
Definition: DoubleAc.cpp:376
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:616
DoubleAc find_min(const DoubleAc &a, const DoubleAc &b)
Definition: DoubleAc.h:627
DoubleAc find_max(const DoubleAc &a, const DoubleAc &b)
Definition: DoubleAc.h:655
#define check_econd11(a, signb, stream)
Definition: FunNameStack.h:366
#define check_econd12a(a, sign, b, add, stream)
Definition: FunNameStack.h:411
#define mfunnamep(string)
Definition: FunNameStack.h:77
#define spexit(stream)
Definition: FunNameStack.h:536
#define mfunname(string)
Definition: FunNameStack.h:67
DoubleAc & operator/=(DoubleAc f)
Definition: DoubleAc.cpp:189
void print(std::ostream &file, int l=1) const
Definition: DoubleAc.cpp:508
DoubleAc & operator*=(DoubleAc f)
Definition: DoubleAc.cpp:40
double get_right_limit(void) const
Definition: DoubleAc.h:82
double left_limit(void) const
Definition: DoubleAc.h:79
double right_limit(void) const
Definition: DoubleAc.h:83
double get(void) const
Definition: DoubleAc.h:76
DoubleAc(void)
Definition: DoubleAc.h:49
double get_left_limit(void) const
Definition: DoubleAc.h:78
int even_num(long n)
Definition: minmax.h:105
long left_round(double f)
Definition: minmax.h:99
#define mcout
Definition: prstream.h:133
#define mcerr
Definition: prstream.h:135
#define Iprintn(file, name)
Definition: prstream.h:216