You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

731 lines
29 KiB

  1. #include "storm_wrapper.h"
  2. #include <cstring>
  3. #include <iostream>
  4. #include <sstream>
  5. #include <set>
  6. #include <map>
  7. #include <mutex>
  8. #include "storm/adapters/RationalFunctionAdapter.h"
  9. #include "storm/utility/constants.h"
  10. #include "storm/utility/KwekMehlhorn.h"
  11. #include "storm/exceptions/InvalidOperationException.h"
  12. #include "storm/exceptions/PrecisionExceededException.h"
  13. #include <sylvan_config.h>
  14. #include <sylvan.h>
  15. #include <sylvan_common.h>
  16. #include <sylvan_mtbdd.h>
  17. #if defined(STORM_HAVE_GMP) && !defined(STORM_USE_CLN_EA)
  18. #define RATIONAL_NUMBER_THREAD_SAFE
  19. #else
  20. #warning "Rational numbers do not appear to be thread-safe. Use in sylvan will be protected by mutexes, performance might degrade."
  21. #endif
  22. // A mutex that is used to lock all operations accessing rational numbers as they are not necessarily thread-safe.
  23. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  24. std::mutex rationalNumberMutex;
  25. #endif
  26. // A mutex that is used to lock all operations accessing rational functions as carl is not necessarily thread-safe.
  27. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  28. std::mutex rationalFunctionMutex;
  29. #endif
  30. /***************************************************
  31. Function-wrappers for storm::RationalNumber
  32. ****************************************************/
  33. void storm_rational_number_init(storm_rational_number_ptr* a) {
  34. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  35. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  36. #endif
  37. storm_rational_number_ptr srn_ptr = new storm::RationalNumber(*((storm::RationalNumber*)(*a)));
  38. *a = srn_ptr;
  39. }
  40. void storm_rational_number_destroy(storm_rational_number_ptr a) {
  41. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  42. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  43. #endif
  44. storm::RationalNumber* srn_ptr = (storm::RationalNumber*)a;
  45. delete srn_ptr;
  46. }
  47. int storm_rational_number_equals(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  48. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  49. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  50. #endif
  51. storm::RationalNumber const& srn_a = *(storm::RationalNumber*)a;
  52. storm::RationalNumber const& srn_b = *(storm::RationalNumber*)b;
  53. return (srn_a == srn_b) ? 1 : 0;
  54. }
  55. char* storm_rational_number_to_str(storm_rational_number_ptr val, char *buf, size_t buflen) {
  56. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  57. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  58. #endif
  59. std::stringstream ss;
  60. storm::RationalNumber const& srn_a = *(storm::RationalNumber*)val;
  61. ss << srn_a;
  62. std::string s = ss.str();
  63. if (s.size() + 1 < buflen) {
  64. std::memcpy(buf, s.c_str(), s.size() + 1);
  65. return buf;
  66. } else {
  67. char* result = (char*)malloc(s.size() + 1);
  68. std::memcpy(result, s.c_str(), s.size() + 1);
  69. return result;
  70. }
  71. }
  72. storm_rational_number_ptr storm_rational_number_clone(storm_rational_number_ptr a) {
  73. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  74. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  75. #endif
  76. storm::RationalNumber* result_srn = new storm::RationalNumber(*((storm::RationalNumber const*)a));
  77. return (storm_rational_number_ptr)result_srn;
  78. }
  79. storm_rational_number_ptr storm_rational_number_get_zero() {
  80. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  81. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  82. #endif
  83. storm::RationalNumber* result_srn = new storm::RationalNumber(storm::utility::zero<storm::RationalNumber>());
  84. return (storm_rational_number_ptr)result_srn;
  85. }
  86. storm_rational_number_ptr storm_rational_number_get_one() {
  87. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  88. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  89. #endif
  90. storm::RationalNumber* result_srn = new storm::RationalNumber(storm::utility::one<storm::RationalNumber>());
  91. return (storm_rational_number_ptr)result_srn;
  92. }
  93. storm_rational_number_ptr storm_rational_number_get_infinity() {
  94. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  95. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  96. #endif
  97. storm::RationalNumber* result_srn = new storm::RationalNumber(storm::utility::infinity<storm::RationalNumber>());
  98. return (storm_rational_number_ptr)result_srn;
  99. }
  100. int storm_rational_number_is_zero(storm_rational_number_ptr a) {
  101. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  102. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  103. #endif
  104. return storm::utility::isZero(*(storm::RationalNumber const*)a) ? 1 : 0;
  105. }
  106. uint64_t storm_rational_number_hash(storm_rational_number_ptr const a, uint64_t const seed) {
  107. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  108. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  109. #endif
  110. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  111. // Taken from boost::hash_combine that we do not call here for the lack of boost headers.
  112. return seed ^ (std::hash<storm::RationalNumber>()(srn_a) + 0x9e3779b9 + (seed<<6) + (seed>>2));
  113. }
  114. double storm_rational_number_get_value_double(storm_rational_number_ptr a) {
  115. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  116. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  117. #endif
  118. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  119. return storm::utility::convertNumber<double>(srn_a);
  120. }
  121. storm_rational_number_ptr storm_rational_number_from_double(double value) {
  122. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  123. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  124. #endif
  125. storm::RationalNumber* number = new storm::RationalNumber(storm::utility::convertNumber<storm::RationalNumber>(value));
  126. return number;
  127. }
  128. storm_rational_number_ptr storm_rational_number_plus(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  129. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  130. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  131. #endif
  132. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  133. storm::RationalNumber const& srn_b = *(storm::RationalNumber const*)b;
  134. storm::RationalNumber* result_srn = new storm::RationalNumber(srn_a + srn_b);
  135. return (storm_rational_number_ptr)result_srn;
  136. }
  137. storm_rational_number_ptr storm_rational_number_minus(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  138. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  139. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  140. #endif
  141. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  142. storm::RationalNumber const& srn_b = *(storm::RationalNumber const*)b;
  143. storm::RationalNumber* result_srn = new storm::RationalNumber(srn_a - srn_b);
  144. return (storm_rational_number_ptr)result_srn;
  145. }
  146. storm_rational_number_ptr storm_rational_number_times(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  147. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  148. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  149. #endif
  150. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  151. storm::RationalNumber const& srn_b = *(storm::RationalNumber const*)b;
  152. storm::RationalNumber* result_srn = new storm::RationalNumber(srn_a * srn_b);
  153. return (storm_rational_number_ptr)result_srn;
  154. }
  155. storm_rational_number_ptr storm_rational_number_divide(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  156. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  157. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  158. #endif
  159. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  160. storm::RationalNumber const& srn_b = *(storm::RationalNumber const*)b;
  161. storm::RationalNumber* result_srn = new storm::RationalNumber(srn_a / srn_b);
  162. return (storm_rational_number_ptr)result_srn;
  163. }
  164. storm_rational_number_ptr storm_rational_number_pow(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  165. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  166. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  167. #endif
  168. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  169. storm::RationalNumber const& srn_b = *(storm::RationalNumber const*)b;
  170. carl::sint exponentAsInteger = carl::toInt<carl::sint>(srn_b);
  171. storm::RationalNumber* result_srn = new storm::RationalNumber(storm::utility::pow(srn_a, exponentAsInteger));
  172. return (storm_rational_number_ptr)result_srn;
  173. }
  174. storm_rational_number_ptr storm_rational_number_mod(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  175. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  176. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  177. #endif
  178. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  179. storm::RationalNumber const& srn_b = *(storm::RationalNumber const*)b;
  180. if (carl::isInteger(srn_a) && carl::isInteger(srn_b)) {
  181. storm::RationalNumber* result_srn = new storm::RationalNumber(carl::mod(carl::getNum(srn_a), carl::getNum(srn_b)));
  182. return (storm_rational_number_ptr)result_srn;
  183. }
  184. throw storm::exceptions::InvalidOperationException() << "Modulo not supported for rational, non-integer numbers.";
  185. }
  186. storm_rational_number_ptr storm_rational_number_min(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  187. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  188. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  189. #endif
  190. return storm_rational_number_less_or_equal(a, b) ? storm_rational_number_clone(a) : storm_rational_number_clone(b);
  191. }
  192. storm_rational_number_ptr storm_rational_number_max(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  193. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  194. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  195. #endif
  196. return storm_rational_number_less(a, b) ? storm_rational_number_clone(b) : storm_rational_number_clone(a);
  197. }
  198. int storm_rational_number_less(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  199. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  200. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  201. #endif
  202. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  203. storm::RationalNumber const& srn_b = *(storm::RationalNumber const*)b;
  204. if (storm::utility::isInfinity<storm::RationalNumber>(srn_b)) {
  205. return storm::utility::isInfinity<storm::RationalNumber>(srn_a) ? 0 : 1;
  206. } else if (storm::utility::isInfinity<storm::RationalNumber>(srn_a)) {
  207. return 0;
  208. }
  209. return srn_a < srn_b ? 1 : 0;
  210. }
  211. int storm_rational_number_less_or_equal(storm_rational_number_ptr a, storm_rational_number_ptr b) {
  212. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  213. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  214. #endif
  215. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  216. storm::RationalNumber const& srn_b = *(storm::RationalNumber const*)b;
  217. if (storm::utility::isInfinity<storm::RationalNumber>(srn_b)) {
  218. return 1;
  219. } else if (storm::utility::isInfinity<storm::RationalNumber>(srn_a)) {
  220. return 0;
  221. }
  222. return srn_a <= srn_b ? 1 : 0;
  223. }
  224. storm_rational_number_ptr storm_rational_number_negate(storm_rational_number_ptr a) {
  225. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  226. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  227. #endif
  228. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  229. storm::RationalNumber* result_srn = new storm::RationalNumber(-srn_a);
  230. return (storm_rational_number_ptr)result_srn;
  231. }
  232. storm_rational_number_ptr storm_rational_number_floor(storm_rational_number_ptr a) {
  233. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  234. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  235. #endif
  236. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  237. storm::RationalNumber* result_srn = new storm::RationalNumber(carl::floor(srn_a));
  238. return (storm_rational_number_ptr)result_srn;
  239. }
  240. storm_rational_number_ptr storm_rational_number_ceil(storm_rational_number_ptr a) {
  241. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  242. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  243. #endif
  244. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  245. storm::RationalNumber* result_srn = new storm::RationalNumber(carl::ceil(srn_a));
  246. return (storm_rational_number_ptr)result_srn;
  247. }
  248. storm_rational_number_ptr storm_double_sharpen(double value, size_t precision) {
  249. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  250. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  251. #endif
  252. try {
  253. storm::RationalNumber tmp = storm::utility::kwek_mehlhorn::sharpen<storm::RationalNumber, double>(precision, value);
  254. storm::RationalNumber* result_srn = new storm::RationalNumber(tmp);
  255. return (storm_rational_number_ptr)result_srn;
  256. } catch (storm::exceptions::PrecisionExceededException const& e) {
  257. return (storm_rational_number_ptr)0;
  258. }
  259. }
  260. storm_rational_number_ptr storm_rational_number_sharpen(storm_rational_number_ptr a, size_t precision) {
  261. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  262. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  263. #endif
  264. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  265. storm::RationalNumber tmp = storm::utility::kwek_mehlhorn::sharpen<storm::RationalNumber, storm::RationalNumber>(precision, srn_a);
  266. storm::RationalNumber* result_srn = new storm::RationalNumber(tmp);
  267. return (storm_rational_number_ptr)result_srn;
  268. }
  269. int storm_rational_number_equal_modulo_precision(int relative, storm_rational_number_ptr a, storm_rational_number_ptr b, storm_rational_number_ptr precision) {
  270. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  271. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  272. #endif
  273. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  274. storm::RationalNumber const& srn_b = *(storm::RationalNumber const*)b;
  275. storm::RationalNumber const& srn_p = *(storm::RationalNumber const*)precision;
  276. if (relative) {
  277. if (storm::utility::isZero<storm::RationalNumber>(srn_a)) {
  278. return storm::utility::isZero<storm::RationalNumber>(srn_b);
  279. } else {
  280. return carl::abs(srn_a - srn_b)/srn_a < srn_p ? 1 : 0;
  281. }
  282. } else {
  283. return carl::abs(srn_a - srn_b) < srn_p ? 1 : 0;
  284. }
  285. }
  286. void print_storm_rational_number(storm_rational_number_ptr a) {
  287. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  288. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  289. #endif
  290. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  291. }
  292. void print_storm_rational_number_to_file(storm_rational_number_ptr a, FILE* out) {
  293. #ifndef RATIONAL_NUMBER_THREAD_SAFE
  294. std::lock_guard<std::mutex> lock(rationalNumberMutex);
  295. #endif
  296. std::stringstream ss;
  297. storm::RationalNumber const& srn_a = *(storm::RationalNumber const*)a;
  298. ss << srn_a;
  299. std::string s = ss.str();
  300. fprintf(out, "%s", s.c_str());
  301. }
  302. /***************************************************
  303. Function-wrappers for storm::RationalFunction
  304. ****************************************************/
  305. void storm_rational_function_init(storm_rational_function_ptr* a) {
  306. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  307. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  308. #endif
  309. storm_rational_function_ptr srf_ptr = new storm::RationalFunction(*((storm::RationalFunction*)(*a)));
  310. *a = srf_ptr;
  311. }
  312. void storm_rational_function_destroy(storm_rational_function_ptr a) {
  313. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  314. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  315. #endif
  316. storm::RationalFunction* srf = (storm::RationalFunction*)a;
  317. delete srf;
  318. }
  319. int storm_rational_function_equals(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  320. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  321. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  322. #endif
  323. storm::RationalFunction const& srf_a = *(storm::RationalFunction*)a;
  324. storm::RationalFunction const& srf_b = *(storm::RationalFunction*)b;
  325. return (srf_a == srf_b) ? 1 : 0;
  326. }
  327. char* storm_rational_function_to_str(storm_rational_function_ptr val, char* buf, size_t buflen) {
  328. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  329. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  330. #endif
  331. std::stringstream ss;
  332. storm::RationalFunction const& srf_a = *(storm::RationalFunction*)val;
  333. ss << srf_a;
  334. std::string s = ss.str();
  335. if (s.size() + 1 < buflen) {
  336. std::strcpy(buf, s.c_str());
  337. return buf;
  338. } else {
  339. char* result = (char*)malloc(s.size() + 1);
  340. std::strcpy(result, s.c_str());
  341. return result;
  342. }
  343. }
  344. storm_rational_function_ptr storm_rational_function_clone(storm_rational_function_ptr a) {
  345. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  346. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  347. #endif
  348. storm::RationalFunction* result_srf = new storm::RationalFunction(*((storm::RationalFunction const*)a));
  349. return (storm_rational_function_ptr)result_srf;
  350. }
  351. storm_rational_function_ptr storm_rational_function_get_zero() {
  352. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  353. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  354. #endif
  355. storm::RationalFunction* result_srf = new storm::RationalFunction(storm::utility::zero<storm::RationalFunction>());
  356. return (storm_rational_function_ptr)result_srf;
  357. }
  358. storm_rational_function_ptr storm_rational_function_get_one() {
  359. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  360. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  361. #endif
  362. storm::RationalFunction* result_srf = new storm::RationalFunction(storm::utility::one<storm::RationalFunction>());
  363. return (storm_rational_function_ptr)result_srf;
  364. }
  365. storm_rational_function_ptr storm_rational_function_get_infinity() {
  366. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  367. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  368. #endif
  369. storm::RationalFunction* result_srf = new storm::RationalFunction(storm::utility::infinity<storm::RationalFunction>());
  370. return (storm_rational_function_ptr)result_srf;
  371. }
  372. int storm_rational_function_is_zero(storm_rational_function_ptr a) {
  373. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  374. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  375. #endif
  376. return storm::utility::isZero(*(storm::RationalFunction const*)a) ? 1 : 0;
  377. }
  378. uint64_t storm_rational_function_hash(storm_rational_function_ptr const a, uint64_t const seed) {
  379. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  380. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  381. #endif
  382. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  383. // Taken from boost::hash_combine that we do not call here for the lack of boost headers.
  384. return seed ^ (std::hash<storm::RationalFunction>()(srf_a) + 0x9e3779b9 + (seed<<6) + (seed>>2));
  385. }
  386. double storm_rational_function_get_value_double(storm_rational_function_ptr a) {
  387. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  388. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  389. #endif
  390. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  391. if (srf_a.isConstant()) {
  392. return storm::utility::convertNumber<double>(srf_a);
  393. } else {
  394. throw storm::exceptions::InvalidOperationException() << "Cannot evaluate rational function as it's not constant.";
  395. }
  396. }
  397. storm_rational_function_ptr storm_rational_function_plus(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  398. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  399. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  400. #endif
  401. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  402. storm::RationalFunction const& srf_b = *(storm::RationalFunction const*)b;
  403. storm::RationalFunction* result_srf = new storm::RationalFunction(srf_a);
  404. *result_srf += srf_b;
  405. return (storm_rational_function_ptr)result_srf;
  406. }
  407. storm_rational_function_ptr storm_rational_function_minus(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  408. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  409. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  410. #endif
  411. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  412. storm::RationalFunction const& srf_b = *(storm::RationalFunction const*)b;
  413. storm::RationalFunction* result_srf = new storm::RationalFunction(srf_a);
  414. *result_srf -= srf_b;
  415. return (storm_rational_function_ptr)result_srf;
  416. }
  417. storm_rational_function_ptr storm_rational_function_times(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  418. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  419. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  420. #endif
  421. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  422. storm::RationalFunction const& srf_b = *(storm::RationalFunction const*)b;
  423. storm::RationalFunction* result_srf = new storm::RationalFunction(srf_a);
  424. *result_srf *= srf_b;
  425. return (storm_rational_function_ptr)result_srf;
  426. }
  427. storm_rational_function_ptr storm_rational_function_divide(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  428. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  429. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  430. #endif
  431. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  432. storm::RationalFunction const& srf_b = *(storm::RationalFunction const*)b;
  433. storm::RationalFunction* result_srf = new storm::RationalFunction(srf_a);
  434. *result_srf /= srf_b;
  435. return (storm_rational_function_ptr)result_srf;
  436. }
  437. storm_rational_function_ptr storm_rational_function_pow(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  438. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  439. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  440. #endif
  441. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  442. storm::RationalFunction const& srf_b = *(storm::RationalFunction const*)b;
  443. carl::uint exponentAsInteger = carl::toInt<carl::uint>(srf_b.nominatorAsNumber());
  444. storm::RationalFunction* result_srf = new storm::RationalFunction(carl::pow(srf_a, exponentAsInteger));
  445. return (storm_rational_function_ptr)result_srf;
  446. }
  447. storm_rational_function_ptr storm_rational_function_mod(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  448. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  449. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  450. #endif
  451. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  452. storm::RationalFunction const& srf_b = *(storm::RationalFunction const*)b;
  453. if (!storm::utility::isConstant(srf_a) || !storm::utility::isConstant(srf_b)) {
  454. throw storm::exceptions::InvalidOperationException() << "Operands of mod must not be non-constant rational functions.";
  455. }
  456. throw storm::exceptions::InvalidOperationException() << "Modulo not supported for rational functions.";
  457. }
  458. storm_rational_function_ptr storm_rational_function_min(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  459. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  460. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  461. #endif
  462. if (storm_rational_function_less_or_equal(a, b)) {
  463. return storm_rational_function_clone(a);
  464. } else {
  465. return storm_rational_function_clone(b);
  466. }
  467. }
  468. storm_rational_function_ptr storm_rational_function_max(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  469. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  470. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  471. #endif
  472. if (storm_rational_function_less(a, b)) {
  473. return storm_rational_function_clone(b);
  474. } else {
  475. return storm_rational_function_clone(a);
  476. }
  477. }
  478. int storm_rational_function_less(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  479. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  480. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  481. #endif
  482. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  483. storm::RationalFunction const& srf_b = *(storm::RationalFunction const*)b;
  484. if (!storm::utility::isConstant(srf_a) || !storm::utility::isConstant(srf_b)) {
  485. throw storm::exceptions::InvalidOperationException() << "Operands of less must not be non-constant rational functions.";
  486. }
  487. storm::RationalFunctionCoefficient srn_a = storm::utility::convertNumber<storm::RationalFunctionCoefficient>(srf_a);
  488. storm::RationalFunctionCoefficient srn_b = storm::utility::convertNumber<storm::RationalFunctionCoefficient>(srf_b);
  489. if (storm::utility::isInfinity<storm::RationalFunctionCoefficient>(srn_b)) {
  490. return storm::utility::isInfinity<storm::RationalFunctionCoefficient>(srn_a) ? 0 : 1;
  491. } else if (storm::utility::isInfinity<storm::RationalFunctionCoefficient>(srn_a)) {
  492. return 0;
  493. }
  494. return (srn_a < srn_b) ? 1 : 0;
  495. }
  496. int storm_rational_function_less_or_equal(storm_rational_function_ptr a, storm_rational_function_ptr b) {
  497. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  498. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  499. #endif
  500. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  501. storm::RationalFunction const& srf_b = *(storm::RationalFunction const*)b;
  502. if (!storm::utility::isConstant(srf_a) || !storm::utility::isConstant(srf_b)) {
  503. throw storm::exceptions::InvalidOperationException() << "Operands of less-or-equal must not be non-constant rational functions.";
  504. }
  505. storm::RationalFunctionCoefficient srn_a = storm::utility::convertNumber<storm::RationalFunctionCoefficient>(srf_a);
  506. storm::RationalFunctionCoefficient srn_b = storm::utility::convertNumber<storm::RationalFunctionCoefficient>(srf_b);
  507. if (storm::utility::isInfinity<storm::RationalFunctionCoefficient>(srn_b)) {
  508. return 1;
  509. } else if (storm::utility::isInfinity<storm::RationalFunctionCoefficient>(srn_a)) {
  510. return 0;
  511. }
  512. return (srn_a <= srn_b) ? 1 : 0;
  513. }
  514. storm_rational_function_ptr storm_rational_function_negate(storm_rational_function_ptr a) {
  515. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  516. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  517. #endif
  518. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  519. storm::RationalFunction* result_srf = new storm::RationalFunction(-srf_a);
  520. return (storm_rational_function_ptr)result_srf;
  521. }
  522. storm_rational_function_ptr storm_rational_function_floor(storm_rational_function_ptr a) {
  523. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  524. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  525. #endif
  526. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  527. if (!storm::utility::isConstant(srf_a)) {
  528. throw storm::exceptions::InvalidOperationException() << "Operand of floor must not be non-constant rational function.";
  529. }
  530. storm::RationalFunction* result_srf = new storm::RationalFunction(carl::floor(storm::utility::convertNumber<storm::RationalFunctionCoefficient>(srf_a)));
  531. return (storm_rational_function_ptr)result_srf;
  532. }
  533. storm_rational_function_ptr storm_rational_function_ceil(storm_rational_function_ptr a) {
  534. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  535. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  536. #endif
  537. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  538. if (!storm::utility::isConstant(srf_a)) {
  539. throw storm::exceptions::InvalidOperationException() << "Operand of ceil must not be non-constant rational function.";
  540. }
  541. storm::RationalFunction* result_srf = new storm::RationalFunction(carl::ceil(storm::utility::convertNumber<storm::RationalFunctionCoefficient>(srf_a)));
  542. return (storm_rational_function_ptr)result_srf;
  543. }
  544. int storm_rational_function_equal_modulo_precision(int relative, storm_rational_function_ptr a, storm_rational_function_ptr b, storm_rational_function_ptr precision) {
  545. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  546. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  547. #endif
  548. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  549. storm::RationalFunction const& srf_b = *(storm::RationalFunction const*)b;
  550. storm::RationalFunction const& srf_p = *(storm::RationalFunction const*)precision;
  551. if (!storm::utility::isConstant(srf_a) || !storm::utility::isConstant(srf_b) || !storm::utility::isConstant(srf_p)) {
  552. throw storm::exceptions::InvalidOperationException() << "Operands of equal-modulo-precision must not be non-constant rational functions.";
  553. }
  554. storm::RationalFunctionCoefficient srn_a = storm::utility::convertNumber<storm::RationalFunctionCoefficient>(srf_a);
  555. storm::RationalFunctionCoefficient srn_b = storm::utility::convertNumber<storm::RationalFunctionCoefficient>(srf_b);
  556. storm::RationalFunctionCoefficient srn_p = storm::utility::convertNumber<storm::RationalFunctionCoefficient>(srf_p);
  557. if (relative) {
  558. return carl::abs(srn_a - srn_b)/srn_a < srn_p ? 1 : 0;
  559. } else {
  560. return carl::abs(srn_a - srn_b) < srn_p ? 1 : 0;
  561. }
  562. }
  563. void print_storm_rational_function(storm_rational_function_ptr a) {
  564. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  565. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  566. #endif
  567. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  568. std::cout << srf_a << std::flush;
  569. }
  570. void print_storm_rational_function_to_file(storm_rational_function_ptr a, FILE* out) {
  571. #ifndef RATIONAL_FUNCTION_THREAD_SAFE
  572. std::lock_guard<std::mutex> lock(rationalFunctionMutex);
  573. #endif
  574. std::stringstream ss;
  575. storm::RationalFunction const& srf_a = *(storm::RationalFunction const*)a;
  576. ss << srf_a;
  577. std::string s = ss.str();
  578. fprintf(out, "%s", s.c_str());
  579. }