Storm 1.13.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
constants.cpp
Go to the documentation of this file.
2
3#include <cmath>
4
14
15namespace storm {
16namespace utility {
17
18template<typename ValueType>
19ValueType one() {
20 return ValueType(1);
21}
22
23template<typename ValueType>
24ValueType zero() {
25 return ValueType(0);
26}
27
28template<typename ValueType>
29ValueType infinity() {
30 return std::numeric_limits<ValueType>::infinity();
31}
32
33template<typename ValueType>
34bool isOne(ValueType const& a) {
35 return a == one<ValueType>();
36}
37
38template<typename ValueType>
39bool isZero(ValueType const& a) {
40 return a == zero<ValueType>();
41}
42
43template<typename ValueType>
44bool isNan(ValueType const&) {
45 return false;
46}
47
48template<>
49bool isNan(double const& value) {
50 return std::isnan(value);
51}
52
53template<typename ValueType>
54bool isApproxEqual(ValueType const& a, ValueType const& b, ValueType const& precision, bool relative) {
55 ValueType const absDiff = abs<ValueType>(a - b);
56 if (relative) {
57 return absDiff <= precision * max(abs(a), abs(b));
58 } else {
59 return absDiff <= precision;
60 }
61}
62
63template<typename ValueType>
64bool isPositive(ValueType const& a) {
65 return a > zero<ValueType>();
66}
67
68template<typename ValueType>
69bool isNonNegative(ValueType const& a) {
70 return a >= zero<ValueType>();
71}
72
81template<typename ValueType>
82bool isBetween(ValueType const& a, ValueType const& b, ValueType const& c, bool strict) {
83 STORM_LOG_ASSERT(isConstant(a), "Checking whether something is between two values is only sensible on constants.");
84 STORM_LOG_ASSERT(isConstant(c), "Checking whether something is between two values is only sensible on constants.");
85 if (strict) {
86 return a < b && b < c;
87 } else {
88 return a <= b && b <= c;
89 }
90}
91
92template<typename ValueType>
93bool isAlmostZero(ValueType const& a) {
94 return a < convertNumber<ValueType>(1e-12) && a > -convertNumber<ValueType>(1e-12);
95}
96
97template<typename ValueType>
98bool isAlmostOne(ValueType const& a) {
99 return a < convertNumber<ValueType>(1.0 + 1e-12) && a > convertNumber<ValueType>(1.0 - 1e-12);
100}
101
102template<typename ValueType>
103bool isConstant(ValueType const&) {
104 return true;
105}
106
107template<typename ValueType>
108bool isInfinity(ValueType const& a) {
109 return a == infinity<ValueType>();
110}
111
112template<typename ValueType>
113bool isInteger(ValueType const& number) {
114 ValueType iPart;
115 ValueType result = std::modf(number, &iPart);
116 return result == zero<ValueType>();
117}
118
119template<>
120bool isInteger(int const&) {
121 return true;
122}
123
124template<>
125bool isInteger(uint32_t const&) {
126 return true;
127}
128
129template<>
131 return true;
132}
133
134template<typename TargetType, typename SourceType>
135TargetType convertNumber(SourceType const& number) {
136 return static_cast<TargetType>(number);
137}
138
139template<>
140uint_fast64_t convertNumber(double const& number) {
141 return std::llround(number);
142}
143
144template<>
145int_fast64_t convertNumber(double const& number) {
146 return std::llround(number);
147}
148
149template<>
150double convertNumber(uint_fast64_t const& number) {
151 return number;
152}
153
154template<>
155double convertNumber(double const& number) {
156 return number;
157}
158
159template<>
160double convertNumber(long long const& number) {
161 return static_cast<double>(number);
162}
163
164template<>
166 return static_cast<storm::storage::sparse::state_type>(number);
167}
168
169template<typename ValueType>
170ValueType simplify(ValueType value) {
171 // In the general case, we don't do anything here, but merely return the value. If something else is
172 // supposed to happen here, the templated function can be specialized for this particular type.
173 return value;
174}
175
176template<typename ValueType>
177std::pair<ValueType, ValueType> minmax(std::vector<ValueType> const& values) {
178 assert(!values.empty());
179 ValueType min = values.front();
180 ValueType max = values.front();
181 for (auto const& vt : values) {
182 if (vt < min) {
183 min = vt;
184 }
185 if (vt > max) {
186 max = vt;
187 }
188 }
189 return std::make_pair(min, max);
190}
191
192template<typename ValueType>
193ValueType minimum(std::vector<ValueType> const& values) {
194 assert(!values.empty());
195 ValueType min = values.front();
196 for (auto const& vt : values) {
197 if (vt < min) {
198 min = vt;
199 }
200 }
201 return min;
202}
203
204template<typename ValueType>
205ValueType maximum(std::vector<ValueType> const& values) {
206 assert(!values.empty());
207 ValueType max = values.front();
208 for (auto const& vt : values) {
209 if (vt > max) {
210 max = vt;
211 }
212 }
213 return max;
214}
215
216template<typename K, typename ValueType>
217std::pair<ValueType, ValueType> minmax(std::map<K, ValueType> const& values) {
218 assert(!values.empty());
219 ValueType min = values.begin()->second;
220 ValueType max = values.begin()->second;
221 for (auto const& vt : values) {
222 if (vt.second < min) {
223 min = vt.second;
224 }
225 if (vt.second > max) {
226 max = vt.second;
227 }
228 }
229 return std::make_pair(min, max);
230}
231
232template<typename K, typename ValueType>
233ValueType minimum(std::map<K, ValueType> const& values) {
234 return minmax(values).first;
235}
236
237template<typename K, typename ValueType>
238ValueType maximum(std::map<K, ValueType> const& values) {
239 return minmax(values).second;
240}
241
242template<typename ValueType>
243ValueType pow(ValueType const& value, int_fast64_t exponent) {
244 return std::pow(value, exponent);
245}
246
247template<typename ValueType>
248ValueType max(ValueType const& first, ValueType const& second) {
249 return std::max(first, second);
250}
251
252template<typename ValueType>
253ValueType min(ValueType const& first, ValueType const& second) {
254 return std::min(first, second);
255}
256
257template<typename ValueType>
258ValueType sqrt(ValueType const& number) {
259 return std::sqrt(number);
260}
261
262template<typename ValueType>
263ValueType abs(ValueType const& number) {
264 return std::fabs(number);
265}
266
267template<typename ValueType>
268ValueType floor(ValueType const& number) {
269 return std::floor(number);
270}
271
272template<typename ValueType>
273ValueType ceil(ValueType const& number) {
274 return std::ceil(number);
275}
276
277template<typename ValueType>
278ValueType round(ValueType const& number) {
279 // Rounding towards infinity
281}
282
283template<typename ValueType>
284ValueType log(ValueType const& number) {
285 return std::log(number);
286}
287
288template<typename ValueType>
289ValueType log10(ValueType const& number) {
290 return std::log10(number);
291}
292
293template<typename ValueType>
294ValueType cos(ValueType const& number) {
295 return std::cos(number);
296}
297
298template<typename ValueType>
299ValueType sin(ValueType const& number) {
300 return std::sin(number);
301}
302
303template<typename ValueType>
304uint64_t numDigits(ValueType const& number) {
305 auto numDigits = 0;
306 ValueType remaining = storm::utility::one<ValueType>() / number;
308 while (remaining >= storm::utility::one<ValueType>()) {
309 ++numDigits;
310 remaining = storm::utility::floor<ValueType>(remaining / ten);
311 }
312 return numDigits;
313}
314
315template<typename ValueType>
316uint64_t bitsize(ValueType const& number) {
317 if constexpr (std::is_same_v<ValueType, uint64_t>) {
318 return std::bit_width(number);
319 } else {
320 if (storm::utility::isZero(number)) {
321 return 0;
322 } else {
323 // GMPs sizeinbase returns 1 if number is zero.
324 // see https://gmplib.org/manual/Miscellaneous-Integer-Functions
325 return carl::bitsize(number);
326 }
327 }
328}
329
330template<typename ValueType>
331typename NumberTraits<ValueType>::IntegerType trunc(ValueType const& number) {
332 return static_cast<typename NumberTraits<ValueType>::IntegerType>(std::trunc(number));
333}
334
335template<typename IntegerType>
336IntegerType mod(IntegerType const& first, IntegerType const& second) {
337 return std::fmod(first, second);
338}
339
340template<typename IntegerType>
341std::pair<IntegerType, IntegerType> divide(IntegerType const& dividend, IntegerType const& divisor) {
342 return std::make_pair(dividend / divisor, mod(dividend, divisor));
343}
344
345template<typename ValueType>
346std::string to_string(ValueType const& value) {
347 std::stringstream ss;
348 ss.precision(std::numeric_limits<ValueType>::max_digits10 + 2);
349 ss << value;
350 return ss.str();
351}
352
353#if defined(STORM_HAVE_CLN)
354template<>
355storm::ClnRationalNumber infinity() {
356 // FIXME: this should be treated more properly.
357 return storm::ClnRationalNumber(100000000000);
358}
359
360template<>
361bool isOne(storm::ClnRationalNumber const& a) {
362 return carl::isOne(a);
363}
364
365template<>
366bool isZero(storm::ClnRationalNumber const& a) {
367 return carl::isZero(a);
368}
369
370template<>
371bool isInteger(storm::ClnRationalNumber const& number) {
372 return carl::isInteger(number);
373}
374
375template<>
376std::pair<storm::ClnRationalNumber, storm::ClnRationalNumber> minmax(std::vector<storm::ClnRationalNumber> const& values) {
377 assert(!values.empty());
378 storm::ClnRationalNumber min = values.front();
379 storm::ClnRationalNumber max = values.front();
380 for (auto const& vt : values) {
382 max = vt;
383 } else {
384 if (vt < min) {
385 min = vt;
386 }
387 if (vt > max) {
388 max = vt;
389 }
390 }
391 }
392 return std::make_pair(min, max);
393}
394
395template<>
396uint_fast64_t convertNumber(ClnRationalNumber const& number) {
397 return carl::toInt<carl::uint>(number);
398}
399
400template<>
401int_fast64_t convertNumber(ClnRationalNumber const& number) {
402 return carl::toInt<carl::sint>(number);
403}
404
405template<>
406ClnRationalNumber convertNumber(double const& number) {
407 return carl::rationalize<ClnRationalNumber>(number);
408}
409
410template<>
411ClnRationalNumber convertNumber(int const& number) {
412 return carl::rationalize<ClnRationalNumber>(number);
413}
414
415template<>
416ClnRationalNumber convertNumber(NumberTraits<ClnRationalNumber>::IntegerType const& number) {
417 return ClnRationalNumber(number);
418}
419
420template<>
421ClnRationalNumber convertNumber(uint_fast64_t const& number) {
422 STORM_LOG_ASSERT(static_cast<carl::uint>(number) == number, "Rationalizing failed, because the number is too large.");
423 return carl::rationalize<ClnRationalNumber>(static_cast<carl::uint>(number));
424}
425
426template<>
427typename NumberTraits<ClnRationalNumber>::IntegerType convertNumber(uint_fast64_t const& number) {
428 STORM_LOG_ASSERT(static_cast<unsigned long int>(number) == number, "Conversion failed, because the number is too large.");
429 return NumberTraits<ClnRationalNumber>::IntegerType(static_cast<unsigned long int>(number));
430}
431
432template<>
433typename NumberTraits<ClnRationalNumber>::IntegerType convertNumber(int_fast64_t const& number) {
434 STORM_LOG_ASSERT(static_cast<long int>(number) == number, "Conversion failed, because the number is too large.");
435 return NumberTraits<ClnRationalNumber>::IntegerType(static_cast<long int>(number));
436}
437
438template<>
439typename NumberTraits<ClnRationalNumber>::IntegerType convertNumber(double const& number) {
440 if (number < static_cast<double>(std::numeric_limits<uint64_t>::max())) {
441 return NumberTraits<ClnRationalNumber>::IntegerType(static_cast<uint64_t>(number));
442 } else {
443 return carl::round(carl::rationalize<ClnRationalNumber>(number));
444 }
445}
446
447template<>
448ClnRationalNumber convertNumber(int_fast64_t const& number) {
449 STORM_LOG_ASSERT(static_cast<carl::sint>(number) == number, "Rationalizing failed, because the number is too large.");
450 return carl::rationalize<ClnRationalNumber>(static_cast<carl::sint>(number));
451}
452
453template<>
454double convertNumber(ClnRationalNumber const& number) {
455 return carl::toDouble(number);
456}
457
458template<>
459ClnRationalNumber convertNumber(std::string const& number) {
460 ClnRationalNumber result;
461 if (carl::try_parse<ClnRationalNumber>(number, result)) {
462 return result;
463 }
464 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Unable to parse '" << number << "' as a rational number.");
465}
466
467template<>
468std::pair<ClnRationalNumber, ClnRationalNumber> asFraction(ClnRationalNumber const& number) {
469 return std::make_pair(carl::getNum(number), carl::getDenom(number));
470}
471
472template<>
473ClnRationalNumber sqrt(ClnRationalNumber const& number) {
474 return carl::sqrt(number);
475}
476
477template<>
478ClnRationalNumber abs(storm::ClnRationalNumber const& number) {
479 return carl::abs(number);
480}
481
482template<>
483ClnRationalNumber floor(storm::ClnRationalNumber const& number) {
484 return carl::floor(number);
485}
486
487template<>
488ClnRationalNumber ceil(storm::ClnRationalNumber const& number) {
489 return carl::ceil(number);
490}
491
492template<>
493ClnRationalNumber log(ClnRationalNumber const& number) {
494 return carl::log(number);
495}
496
497template<>
498ClnRationalNumber log10(ClnRationalNumber const& number) {
499 return carl::log10(number);
500}
501
502template<>
503ClnRationalNumber cos(ClnRationalNumber const& number) {
504 return carl::cos(number);
505}
506
507template<>
508ClnRationalNumber sin(ClnRationalNumber const& number) {
509 return carl::sin(number);
510}
511
512template<>
513typename NumberTraits<ClnRationalNumber>::IntegerType trunc(ClnRationalNumber const& number) {
514 return cln::truncate1(number);
515}
516
517template<>
518typename NumberTraits<ClnRationalNumber>::IntegerType mod(NumberTraits<ClnRationalNumber>::IntegerType const& first,
519 NumberTraits<ClnRationalNumber>::IntegerType const& second) {
520 return carl::mod(first, second);
521}
522
523template<>
524std::pair<typename NumberTraits<ClnRationalNumber>::IntegerType, typename NumberTraits<ClnRationalNumber>::IntegerType> divide(
525 typename NumberTraits<ClnRationalNumber>::IntegerType const& dividend, typename NumberTraits<ClnRationalNumber>::IntegerType const& divisor) {
526 std::pair<typename NumberTraits<ClnRationalNumber>::IntegerType, typename NumberTraits<ClnRationalNumber>::IntegerType> result;
527 carl::divide(dividend, divisor, result.first, result.second);
528 return result;
529}
530
531template<>
532typename NumberTraits<ClnRationalNumber>::IntegerType pow(typename NumberTraits<ClnRationalNumber>::IntegerType const& value, int_fast64_t exponent) {
533 STORM_LOG_THROW(exponent >= 0, storm::exceptions::InvalidArgumentException,
534 "Tried to compute the power 'x^y' as an integer, but the exponent 'y' is negative.");
535 return carl::pow(value, exponent);
536}
537
538template<>
539ClnRationalNumber pow(ClnRationalNumber const& value, int_fast64_t exponent) {
540 if (exponent >= 0) {
541 return carl::pow(value, exponent);
542 } else {
543 return storm::utility::one<ClnRationalNumber>() / carl::pow(value, -exponent);
544 }
545}
546
547template<>
548NumberTraits<ClnRationalNumber>::IntegerType numerator(ClnRationalNumber const& number) {
549 return carl::getNum(number);
550}
551
552template<>
553NumberTraits<ClnRationalNumber>::IntegerType denominator(ClnRationalNumber const& number) {
554 return carl::getDenom(number);
555}
556#endif
557
558#if defined(STORM_HAVE_GMP)
559template<>
560storm::GmpRationalNumber infinity() {
561 // FIXME: this should be treated more properly.
562 return storm::GmpRationalNumber(100000000000);
563}
564
565template<>
566bool isOne(storm::GmpRationalNumber const& a) {
567 return carl::isOne(a);
568}
569
570template<>
571bool isZero(storm::GmpRationalNumber const& a) {
572 return carl::isZero(a);
573}
574
575template<>
576bool isInteger(storm::GmpRationalNumber const& number) {
577 return carl::isInteger(number);
578}
579
580template<>
581std::pair<storm::GmpRationalNumber, storm::GmpRationalNumber> minmax(std::vector<storm::GmpRationalNumber> const& values) {
582 assert(!values.empty());
583 storm::GmpRationalNumber min = values.front();
584 storm::GmpRationalNumber max = values.front();
585 for (auto const& vt : values) {
587 max = vt;
588 } else {
589 if (vt < min) {
590 min = vt;
591 }
592 if (vt > max) {
593 max = vt;
594 }
595 }
596 }
597 return std::make_pair(min, max);
598}
599
600template<>
601std::pair<storm::GmpRationalNumber, storm::GmpRationalNumber> minmax(std::map<uint64_t, storm::GmpRationalNumber> const& values) {
602 assert(!values.empty());
603 storm::GmpRationalNumber min = values.begin()->second;
604 storm::GmpRationalNumber max = values.begin()->second;
605 for (auto const& vt : values) {
607 max = vt.second;
608 } else {
609 if (vt.second < min) {
610 min = vt.second;
611 }
612 if (vt.second > max) {
613 max = vt.second;
614 }
615 }
616 }
617 return std::make_pair(min, max);
618}
619
620template<>
621uint_fast64_t convertNumber(GmpRationalNumber const& number) {
622 return carl::toInt<carl::uint>(number);
623}
624
625template<>
626int_fast64_t convertNumber(GmpRationalNumber const& number) {
627 return carl::toInt<carl::sint>(number);
628}
629
630template<>
631GmpRationalNumber convertNumber(double const& number) {
632 return carl::rationalize<GmpRationalNumber>(number);
633}
634
635template<>
636GmpRationalNumber convertNumber(int const& number) {
637 return carl::rationalize<GmpRationalNumber>(number);
638}
639
640template<>
641GmpRationalNumber convertNumber(uint_fast64_t const& number) {
642 STORM_LOG_ASSERT(static_cast<carl::uint>(number) == number, "Rationalizing failed, because the number is too large.");
643 return carl::rationalize<GmpRationalNumber>(static_cast<carl::uint>(number));
644}
645
646template<>
647GmpRationalNumber convertNumber(NumberTraits<GmpRationalNumber>::IntegerType const& number) {
648 return GmpRationalNumber(number);
649}
650
651template<>
652typename NumberTraits<GmpRationalNumber>::IntegerType convertNumber(uint_fast64_t const& number) {
653 STORM_LOG_ASSERT(static_cast<unsigned long int>(number) == number, "Conversion failed, because the number is too large.");
654 return NumberTraits<GmpRationalNumber>::IntegerType(static_cast<unsigned long int>(number));
655}
656
657template<>
658typename NumberTraits<GmpRationalNumber>::IntegerType convertNumber(int_fast64_t const& number) {
659 STORM_LOG_ASSERT(static_cast<long int>(number) == number, "Conversion failed, because the number is too large.");
660 return NumberTraits<GmpRationalNumber>::IntegerType(static_cast<long int>(number));
661}
662
663template<>
664typename NumberTraits<GmpRationalNumber>::IntegerType convertNumber(double const& number) {
665 return NumberTraits<GmpRationalNumber>::IntegerType(number);
666}
667
668template<>
669GmpRationalNumber convertNumber(int_fast64_t const& number) {
670 STORM_LOG_ASSERT(static_cast<carl::sint>(number) == number, "Rationalizing failed, because the number is too large.");
671 return carl::rationalize<GmpRationalNumber>(static_cast<carl::sint>(number));
672}
673
674template<>
675double convertNumber(GmpRationalNumber const& number) {
676 return carl::toDouble(number);
677}
678
679template<>
680GmpRationalNumber convertNumber(std::string const& number) {
681 GmpRationalNumber result;
682 if (carl::try_parse<GmpRationalNumber>(number, result)) {
683 return result;
684 }
685 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Unable to parse '" << number << "' as a rational number.");
686}
687
688template<>
689std::pair<GmpRationalNumber, GmpRationalNumber> asFraction(GmpRationalNumber const& number) {
690 return std::make_pair(carl::getNum(number), carl::getDenom(number));
691}
692
693template<>
694GmpRationalNumber sqrt(GmpRationalNumber const& number) {
695 return carl::sqrt(number);
696}
697
698template<>
699GmpRationalNumber abs(storm::GmpRationalNumber const& number) {
700 return carl::abs(number);
701}
702
703template<>
704GmpRationalNumber floor(storm::GmpRationalNumber const& number) {
705 return carl::floor(number);
706}
707
708template<>
709GmpRationalNumber ceil(storm::GmpRationalNumber const& number) {
710 return carl::ceil(number);
711}
712
713template<>
714GmpRationalNumber log(GmpRationalNumber const& number) {
715 return carl::log(number);
716}
717
718template<>
719GmpRationalNumber log10(GmpRationalNumber const& number) {
720 STORM_LOG_WARN("Using log10 for GMP rational numbers is not exact, it converts to doubles internally! Avoid if possible.");
721 return carl::log10(number);
722}
723
724template<>
725GmpRationalNumber cos(GmpRationalNumber const& number) {
726 return carl::cos(number);
727}
728
729template<>
730GmpRationalNumber sin(GmpRationalNumber const& number) {
731 return carl::sin(number);
732}
733
734template<>
735typename NumberTraits<GmpRationalNumber>::IntegerType trunc(GmpRationalNumber const& number) {
736 return carl::getNum(number) / carl::getDenom(number);
737}
738
739template<>
740typename NumberTraits<GmpRationalNumber>::IntegerType mod(typename NumberTraits<GmpRationalNumber>::IntegerType const& first,
741 typename NumberTraits<GmpRationalNumber>::IntegerType const& second) {
742 return carl::mod(first, second);
743}
744
745template<>
746std::pair<typename NumberTraits<GmpRationalNumber>::IntegerType, typename NumberTraits<GmpRationalNumber>::IntegerType> divide(
747 typename NumberTraits<GmpRationalNumber>::IntegerType const& dividend, typename NumberTraits<GmpRationalNumber>::IntegerType const& divisor) {
748 std::pair<typename NumberTraits<GmpRationalNumber>::IntegerType, typename NumberTraits<GmpRationalNumber>::IntegerType> result;
749 carl::divide(dividend, divisor, result.first, result.second);
750 return result;
751}
752
753template<>
754typename NumberTraits<GmpRationalNumber>::IntegerType pow(typename NumberTraits<GmpRationalNumber>::IntegerType const& value, int_fast64_t exponent) {
755 STORM_LOG_THROW(exponent >= 0, storm::exceptions::InvalidArgumentException,
756 "Tried to compute the power 'x^y' as an integer, but the exponent 'y' is negative.");
757 return carl::pow(value, exponent);
758}
759
760template<>
761GmpRationalNumber pow(GmpRationalNumber const& value, int_fast64_t exponent) {
762 if (exponent >= 0) {
763 return carl::pow(value, exponent);
764 } else {
765 return storm::utility::one<GmpRationalNumber>() / carl::pow(value, -exponent);
766 }
767}
768
769template<>
770typename NumberTraits<GmpRationalNumber>::IntegerType numerator(GmpRationalNumber const& number) {
771 return carl::getNum(number);
772}
773
774template<>
775typename NumberTraits<GmpRationalNumber>::IntegerType denominator(GmpRationalNumber const& number) {
776 return carl::getDenom(number);
777}
778#endif
779
780#if defined(STORM_HAVE_GMP) && defined(STORM_HAVE_CLN)
781template<>
782storm::GmpRationalNumber convertNumber(storm::ClnRationalNumber const& number) {
783 return carl::parse<storm::GmpRationalNumber>(to_string(number));
784}
785
786template<>
787storm::ClnRationalNumber convertNumber(storm::GmpRationalNumber const& number) {
788 return carl::parse<storm::ClnRationalNumber>(to_string(number));
789}
790#endif
791
792template<>
794 // FIXME: this should be treated more properly.
796}
797
798template<>
800 return a.isOne();
801}
802
803template<>
804bool isOne(storm::Polynomial const& a) {
805 return a.isOne();
806}
807
808template<>
810 return a.isZero();
811}
812
813template<>
814bool isZero(storm::Polynomial const& a) {
815 return a.isZero();
816}
817
818template<>
820 return a.isConstant();
821}
822
823template<>
825 return a.isConstant();
826}
827
828template<>
829bool isApproxEqual(storm::RationalFunction const& a, storm::RationalFunction const& b, storm::RationalFunction const& precision, bool relative) {
830 STORM_LOG_ASSERT(isZero(precision), "Approx equal on rational functions is only defined for precision zero");
831 return a == b;
832}
833
834template<>
836 return a.isPointInterval();
837}
838
839template<>
841 return a.isPointInterval();
842}
843
844template<>
846 // FIXME: this should be treated more properly.
848}
849
850template<>
852 return storm::utility::isConstant(func) && storm::utility::isOne(func.denominator());
853}
854
855template<>
856RationalFunction convertNumber(double const& number) {
857 return RationalFunction(carl::rationalize<RationalFunctionCoefficient>(number));
858}
859
860template<>
861RationalFunction convertNumber(int_fast64_t const& number) {
862 STORM_LOG_ASSERT(static_cast<carl::sint>(number) == number, "Rationalizing failed, because the number is too large.");
863 return RationalFunction(carl::rationalize<RationalFunctionCoefficient>(static_cast<carl::sint>(number)));
864}
865
866#if defined(STORM_HAVE_CLN)
867template<>
868RationalFunction convertNumber(ClnRationalNumber const& number) {
870}
871
872template<>
873ClnRationalNumber convertNumber(RationalFunction const& number) {
874 storm::RationalFunctionCoefficient tmp = number.nominatorAsNumber() / number.denominatorAsNumber();
876}
877#endif
878
879#if defined(STORM_HAVE_GMP)
880template<>
881RationalFunction convertNumber(GmpRationalNumber const& number) {
883}
884
885template<>
886GmpRationalNumber convertNumber(RationalFunction const& number) {
887 return convertNumber<GmpRationalNumber>(number.nominatorAsNumber() / number.denominatorAsNumber());
888}
889#endif
890
891template<>
892carl::uint convertNumber(RationalFunction const& func) {
893 return carl::toInt<carl::uint>(convertNumber<RationalFunctionCoefficient>(func));
894}
895
896template<>
897carl::sint convertNumber(RationalFunction const& func) {
898 return carl::toInt<carl::sint>(convertNumber<RationalFunctionCoefficient>(func));
899}
900
901template<>
902double convertNumber(RationalFunction const& func) {
903 return carl::toDouble(convertNumber<RationalFunctionCoefficient>(func));
904}
905
906template<>
908 return number;
909}
910
911template<>
915
916template<>
920
921template<>
923
924template<>
926
927template<>
929 value.simplify();
930 return value;
931}
932
933template<>
935 value.simplify();
936 return value;
937}
938
939template<>
941 value.simplify();
942 return std::move(value);
943}
944
945template<>
949
950template<>
954
955template<>
959
960template<>
962 return a.isConstant() && isPositive(convertNumber<RationalFunctionCoefficient>(a));
963}
964
965template<>
967 STORM_LOG_ASSERT(a.isConstant(), "lower bound must be a constant");
968 STORM_LOG_ASSERT(c.isConstant(), "upper bound must be a constant");
971}
972
973template<>
974std::pair<storm::RationalFunction, storm::RationalFunction> minmax(std::vector<storm::RationalFunction> const&) {
975 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Minimum/maximum for rational functions is not defined.");
976}
977
978template<>
979storm::RationalFunction minimum(std::vector<storm::RationalFunction> const&) {
980 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Minimum for rational functions is not defined.");
981}
982
983template<>
984storm::RationalFunction maximum(std::vector<storm::RationalFunction> const&) {
985 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Maximum for rational functions is not defined.");
986}
987
988template<>
989std::pair<storm::RationalFunction, storm::RationalFunction> minmax(std::map<uint64_t, storm::RationalFunction> const&) {
990 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Maximum/maximum for rational functions is not defined.");
991}
992
993template<>
994storm::RationalFunction minimum(std::map<uint64_t, storm::RationalFunction> const&) {
995 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Minimum for rational functions is not defined.");
996}
997
998template<>
999storm::RationalFunction maximum(std::map<uint64_t, storm::RationalFunction> const&) {
1000 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Maximum for rational functions is not defined");
1001}
1002
1003template<>
1004RationalFunction pow(RationalFunction const& value, int_fast64_t exponent) {
1005 if (exponent >= 0) {
1006 return carl::pow(value, exponent);
1007 } else {
1008 return storm::utility::one<RationalFunction>() / carl::pow(value, -exponent);
1009 }
1010}
1011
1012template<>
1013std::string to_string(RationalFunction const& f) {
1014 std::stringstream ss;
1015 if (f.isConstant()) {
1016 if (f.denominator().isOne()) {
1017 ss << f.nominatorAsNumber();
1018 } else {
1019 ss << f.nominatorAsNumber() << "/" << f.denominatorAsNumber();
1020 }
1021 } else if (f.denominator().isOne()) {
1022 ss << f.nominatorAsPolynomial().coefficient() * f.nominatorAsPolynomial().polynomial();
1023 } else {
1024 ss << "(" << f.nominatorAsPolynomial() << ")/(" << f.denominatorAsPolynomial() << ")";
1025 }
1026 return ss.str();
1027}
1028
1029template<>
1030double convertNumber(std::string const& value) {
1032}
1033
1034template<>
1035storm::Interval convertNumber(double const& number) {
1036 return storm::Interval(number);
1037}
1038
1039template<>
1040storm::Interval convertNumber(uint64_t const& number) {
1041 return storm::Interval(convertNumber<double>(number));
1042}
1043
1044template<>
1048
1049template<>
1053
1054#if defined(STORM_HAVE_GMP)
1055template<>
1056storm::Interval convertNumber(storm::GmpRationalNumber const& n) {
1058}
1059
1060template<>
1061storm::GmpRationalNumber convertNumber(storm::Interval const& number) {
1062 STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert");
1063 return convertNumber<storm::GmpRationalNumber>(number.lower());
1064}
1065
1066template<>
1067storm::RationalInterval convertNumber(storm::GmpRationalNumber const& n) {
1069}
1070
1071template<>
1072storm::GmpRationalNumber convertNumber(storm::RationalInterval const& number) {
1073 STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert");
1074 return convertNumber<storm::GmpRationalNumber>(number.lower());
1075}
1076#endif
1077
1078#if defined(STORM_HAVE_CLN)
1079template<>
1080storm::Interval convertNumber(storm::ClnRationalNumber const& n) {
1082}
1083
1084template<>
1085storm::ClnRationalNumber convertNumber(storm::Interval const& number) {
1086 STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert");
1087 return convertNumber<storm::ClnRationalNumber>(number.lower());
1088}
1089
1090template<>
1091storm::RationalInterval convertNumber(storm::ClnRationalNumber const& n) {
1093}
1094
1095template<>
1096storm::ClnRationalNumber convertNumber(storm::RationalInterval const& number) {
1097 STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert");
1098 return convertNumber<storm::ClnRationalNumber>(number.lower());
1099}
1100#endif
1101
1102template<>
1103double convertNumber(storm::Interval const& number) {
1104 STORM_LOG_ASSERT(number.isPointInterval(), "Interval must be a point interval to convert");
1105 return number.lower();
1106}
1107
1108template<>
1110 STORM_LOG_ASSERT(number.isPointInterval(), "Rational interval must be a point interval to convert");
1111 return convertNumber<double>(number.lower());
1112}
1113
1114template<>
1119
1120template<>
1125
1126template<>
1128 return interval.abs();
1129}
1130
1131template<>
1132bool isApproxEqual(storm::Interval const& a, storm::Interval const& b, storm::Interval const& precision, bool relative) {
1133 STORM_LOG_ASSERT(precision.isPointInterval(), "Precision must be a point interval");
1134 return isApproxEqual<double>(a.lower(), b.lower(), precision.center(), relative) &&
1135 isApproxEqual<double>(a.upper(), b.upper(), precision.center(), relative);
1136}
1137
1138template<>
1139bool isApproxEqual(storm::RationalInterval const& a, storm::RationalInterval const& b, storm::RationalInterval const& precision, bool relative) {
1140 STORM_LOG_ASSERT(precision.isPointInterval(), "Precision must be a point interval");
1141 return isApproxEqual<storm::RationalNumber>(a.lower(), b.lower(), precision.center(), relative) &&
1142 isApproxEqual<storm::RationalNumber>(a.upper(), b.upper(), precision.center(), relative);
1143}
1144
1145template<>
1147 return interval.abs();
1148}
1149
1150// Explicit instantiations.
1151
1152// double
1153template double one();
1154template double zero();
1155template double infinity();
1156template bool isOne(double const& value);
1157template bool isZero(double const& value);
1158template bool isNonNegative(double const& value);
1159template bool isPositive(double const& value);
1160template bool isAlmostZero(double const& value);
1161template bool isAlmostOne(double const& value);
1162template bool isConstant(double const& value);
1163template bool isInfinity(double const& value);
1164template bool isInteger(double const& number);
1165template bool isBetween(double const& a, double const& b, double const& c, bool strict);
1166template bool isApproxEqual(double const& a, double const& b, double const& precision, bool relative);
1167template double simplify(double value);
1168template std::pair<double, double> minmax(std::vector<double> const&);
1169template double minimum(std::vector<double> const&);
1170template double maximum(std::vector<double> const&);
1171template std::pair<double, double> minmax(std::map<uint64_t, double> const&);
1172template double minimum(std::map<uint64_t, double> const&);
1173template double maximum(std::map<uint64_t, double> const&);
1174template double pow(double const& value, int_fast64_t exponent);
1175template double max(double const& first, double const& second);
1176template double min(double const& first, double const& second);
1177template double sqrt(double const& number);
1178template double abs(double const& number);
1179template double floor(double const& number);
1180template double ceil(double const& number);
1181template double round(double const& number);
1182template double log(double const& number);
1183template double log10(double const& number);
1184template double cos(double const& number);
1185template double sin(double const& number);
1186template typename NumberTraits<double>::IntegerType trunc(double const& number);
1187template double mod(double const& first, double const& second);
1188template std::string to_string(double const& value);
1189
1190// int
1191template int one();
1192template int zero();
1193template int infinity();
1194template bool isOne(int const& value);
1195template bool isZero(int const& value);
1196template bool isConstant(int const& value);
1197template bool isInfinity(int const& value);
1198template bool isNonNegative(int const& value);
1199template bool isPositive(int const& value);
1200template bool isApproxEqual(int const& a, int const& b, int const& precision, bool relative);
1201template bool isBetween(int const& a, int const& b, int const& c, bool strict);
1202
1203// uint32_t
1204template uint32_t one();
1205template uint32_t zero();
1206template uint32_t infinity();
1207template bool isOne(uint32_t const& value);
1208template bool isZero(uint32_t const& value);
1209template bool isConstant(uint32_t const& value);
1210template bool isNonNegative(uint32_t const& value);
1211template bool isPositive(uint32_t const& value);
1212template bool isInfinity(uint32_t const& value);
1213template bool isBetween(uint32_t const& a, uint32_t const& b, uint32_t const& c, bool strict);
1214
1215// storm::storage::sparse::state_type
1220 storm::storage::sparse::state_type const& precision, bool relative);
1221template bool isOne(storm::storage::sparse::state_type const& value);
1222template bool isZero(storm::storage::sparse::state_type const& value);
1228 bool strict);
1229template uint64_t bitsize(storm::storage::sparse::state_type const& number);
1230
1231// other instantiations
1232template unsigned long convertNumber(long const&);
1233template double convertNumber(long const&);
1234
1235#if defined(STORM_HAVE_CLN)
1236// Instantiations for (CLN) rational number.
1237template storm::ClnRationalNumber one();
1239template storm::ClnRationalNumber zero();
1241template bool isConstant(storm::ClnRationalNumber const& value);
1242template bool isPositive(storm::ClnRationalNumber const& value);
1243template bool isNonNegative(storm::ClnRationalNumber const& value);
1244template bool isInfinity(storm::ClnRationalNumber const& value);
1245template bool isNan(storm::ClnRationalNumber const& value);
1246template bool isAlmostZero(storm::ClnRationalNumber const& value);
1247template bool isAlmostOne(storm::ClnRationalNumber const& value);
1248template bool isApproxEqual(storm::ClnRationalNumber const& a, storm::ClnRationalNumber const& b, storm::ClnRationalNumber const& precision, bool relative);
1249template bool isBetween(storm::ClnRationalNumber const& a, storm::ClnRationalNumber const& b, storm::ClnRationalNumber const& c, bool strict);
1251template storm::ClnRationalNumber convertNumber(storm::ClnRationalNumber const& number);
1252template storm::ClnRationalNumber simplify(storm::ClnRationalNumber value);
1253template std::pair<storm::ClnRationalNumber, storm::ClnRationalNumber> minmax(std::map<uint64_t, storm::ClnRationalNumber> const&);
1254template storm::ClnRationalNumber minimum(std::map<uint64_t, storm::ClnRationalNumber> const&);
1255template storm::ClnRationalNumber maximum(std::map<uint64_t, storm::ClnRationalNumber> const&);
1256template storm::ClnRationalNumber minimum(std::vector<storm::ClnRationalNumber> const&);
1257template storm::ClnRationalNumber maximum(std::vector<storm::ClnRationalNumber> const&);
1258template storm::ClnRationalNumber max(storm::ClnRationalNumber const& first, storm::ClnRationalNumber const& second);
1259template storm::ClnRationalNumber min(storm::ClnRationalNumber const& first, storm::ClnRationalNumber const& second);
1260template storm::ClnRationalNumber round(storm::ClnRationalNumber const& number);
1261template std::string to_string(storm::ClnRationalNumber const& value);
1262template uint64_t numDigits(const storm::ClnRationalNumber& number);
1263template uint64_t bitsize(storm::ClnIntegerNumber const& number);
1264#endif
1265
1266#if defined(STORM_HAVE_GMP)
1267// Instantiations for (GMP) rational number.
1268template storm::GmpRationalNumber one();
1270template storm::GmpRationalNumber zero();
1272template bool isConstant(storm::GmpRationalNumber const& value);
1273template bool isPositive(storm::GmpRationalNumber const& value);
1274template bool isNonNegative(storm::GmpRationalNumber const& value);
1275template bool isInfinity(storm::GmpRationalNumber const& value);
1276template bool isNan(storm::GmpRationalNumber const& value);
1277template bool isAlmostZero(storm::GmpRationalNumber const& value);
1278template bool isAlmostOne(storm::GmpRationalNumber const& value);
1279template bool isBetween(storm::GmpRationalNumber const&, storm::GmpRationalNumber const&, storm::GmpRationalNumber const&, bool);
1280template bool isApproxEqual(storm::GmpRationalNumber const& a, storm::GmpRationalNumber const& b, storm::GmpRationalNumber const& precision, bool relative);
1282template storm::GmpRationalNumber convertNumber(storm::GmpRationalNumber const& number);
1283template storm::GmpRationalNumber simplify(storm::GmpRationalNumber value);
1284template storm::GmpRationalNumber minimum(std::map<uint64_t, storm::GmpRationalNumber> const&);
1285template storm::GmpRationalNumber maximum(std::map<uint64_t, storm::GmpRationalNumber> const&);
1286template storm::GmpRationalNumber minimum(std::vector<storm::GmpRationalNumber> const&);
1287template storm::GmpRationalNumber maximum(std::vector<storm::GmpRationalNumber> const&);
1288template storm::GmpRationalNumber max(storm::GmpRationalNumber const& first, storm::GmpRationalNumber const& second);
1289template storm::GmpRationalNumber min(storm::GmpRationalNumber const& first, storm::GmpRationalNumber const& second);
1290template storm::GmpRationalNumber round(storm::GmpRationalNumber const& number);
1291template std::string to_string(storm::GmpRationalNumber const& value);
1292template uint64_t numDigits(const storm::GmpRationalNumber& number);
1293template uint64_t bitsize(storm::GmpIntegerNumber const& number);
1294#endif
1295
1296// Instantiations for rational function.
1297template RationalFunction one();
1298template RationalFunction zero();
1299
1300template bool isNan(RationalFunction const&);
1301
1302// Instantiations for polynomials.
1303template Polynomial one();
1304template Polynomial zero();
1305
1306// Instantiations for intervals.
1307template Interval one();
1308template Interval zero();
1309template bool isOne(Interval const& value);
1310template bool isZero(Interval const& value);
1311template bool isInfinity(Interval const& value);
1312template bool isAlmostZero(Interval const& value);
1313template bool isNonNegative(Interval const& value);
1314template bool isPositive(Interval const& value);
1315template bool isBetween(Interval const&, Interval const&, Interval const& value, bool);
1316template Interval convertNumber(Interval const&);
1317
1318template std::string to_string(storm::Interval const& value);
1319
1320// Instantiations for rational intervals.
1321template RationalInterval one();
1322template RationalInterval zero();
1323template bool isOne(RationalInterval const& value);
1324template bool isZero(RationalInterval const& value);
1325template bool isInfinity(RationalInterval const& value);
1326template bool isAlmostZero(RationalInterval const& value);
1327template bool isNonNegative(RationalInterval const& value);
1328template bool isPositive(RationalInterval const& value);
1329template bool isBetween(RationalInterval const&, RationalInterval const&, RationalInterval const& value, bool);
1331
1332template std::string to_string(storm::RationalInterval const& value);
1333} // namespace utility
1334} // namespace storm
#define STORM_LOG_WARN(message)
Definition logging.h:25
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
ValueType max(ValueType const &first, ValueType const &second)
bool isPositive(ValueType const &a)
Definition constants.cpp:64
bool isOne(ValueType const &a)
Definition constants.cpp:34
NumberTraits< RationalType >::IntegerType denominator(RationalType const &number)
NumberTraits< RationalType >::IntegerType numerator(RationalType const &number)
bool isConstant(ValueType const &)
ValueType simplify(ValueType value)
bool isBetween(ValueType const &a, ValueType const &b, ValueType const &c, bool strict)
Compare whether a <= b <= c or a < b < c, based on the strictness parameter.
Definition constants.cpp:82
ValueType min(ValueType const &first, ValueType const &second)
ValueType sin(ValueType const &number)
bool isApproxEqual(ValueType const &a, ValueType const &b, ValueType const &precision, bool relative)
Definition constants.cpp:54
bool isAlmostZero(ValueType const &a)
Definition constants.cpp:93
bool isAlmostOne(ValueType const &a)
Definition constants.cpp:98
ValueType floor(ValueType const &number)
std::pair< ValueType, ValueType > asFraction(ValueType const &number)
bool isZero(ValueType const &a)
Definition constants.cpp:39
ValueType minimum(std::vector< ValueType > const &values)
ValueType ceil(ValueType const &number)
bool isInteger(ValueType const &number)
ValueType abs(ValueType const &number)
ValueType zero()
Definition constants.cpp:24
ValueType infinity()
Definition constants.cpp:29
bool isNan(ValueType const &)
Definition constants.cpp:44
std::string to_string(ValueType const &value)
std::pair< ValueType, ValueType > minmax(std::vector< ValueType > const &values)
bool isNonNegative(ValueType const &a)
Definition constants.cpp:69
NumberTraits< ValueType >::IntegerType trunc(ValueType const &number)
std::pair< IntegerType, IntegerType > divide(IntegerType const &dividend, IntegerType const &divisor)
(Integer-)Divides the dividend by the divisor and returns the result plus the remainder.
IntegerType mod(IntegerType const &first, IntegerType const &second)
ValueType pow(ValueType const &value, int_fast64_t exponent)
ValueType one()
Definition constants.cpp:19
ValueType log(ValueType const &number)
ValueType maximum(std::vector< ValueType > const &values)
ValueType cos(ValueType const &number)
ValueType sqrt(ValueType const &number)
uint64_t numDigits(ValueType const &number)
bool isInfinity(ValueType const &a)
uint64_t bitsize(ValueType const &number)
Returns the minimum number of bits to represent the given number.
ValueType log10(ValueType const &number)
ValueType round(ValueType const &number)
TargetType convertNumber(SourceType const &number)
carl::Interval< storm::RationalNumber > RationalInterval
carl::Interval< double > Interval
Interval type.
carl::FactorizedPolynomial< RawPolynomial > Polynomial
carl::RationalFunction< Polynomial, true > RationalFunction
typename detail::IntervalMetaProgrammingHelper< ValueType >::BaseType IntervalBaseType
Helper to access the type in which interval boundaries are stored.