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