A set of benchmarks to compare a new prototype MiniZinc implementation
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3/*
4 * Main authors:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7
8/* This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12#ifndef __MINIZINC_UTILS_H__
13#define __MINIZINC_UTILS_H__
14
15#include <minizinc/exception.hh>
16#include <minizinc/timer.hh>
17
18#include <cassert>
19#include <chrono>
20#include <ctime>
21#include <iomanip>
22#include <limits>
23#include <ratio>
24#include <sstream>
25#include <string>
26#include <vector>
27
28#ifdef MZN_HAS_LLROUND
29#include <cmath>
30namespace MiniZinc {
31inline long long int round_to_longlong(double v) { return ::llround(v); }
32} // namespace MiniZinc
33#else
34namespace MiniZinc {
35inline long long int round_to_longlong(double v) {
36 return static_cast<long long int>(v < 0 ? v - 0.5 : v + 0.5);
37}
38} // namespace MiniZinc
39#endif
40
41namespace MiniZinc {
42
43// #define __MZN_PRINTATONCE__
44#ifdef __MZN_PRINTATONCE__
45#define __MZN_PRINT_SRCLOC(e1, e2) \
46 std::cerr << '\n' \
47 << __FILE__ << ": " << __LINE__ << " (" << __func__ << "): not " << e1 << ": " \
48 << std::flush; \
49 std::cerr << e2 << std::endl
50#else
51#define __MZN_PRINT_SRCLOC(e1, e2)
52#endif
53#define MZN_ASSERT_HARD(c) \
54 do { \
55 if (!(c)) { \
56 __MZN_PRINT_SRCLOC(#c, ""); \
57 throw InternalError(#c); \
58 } \
59 } while (0)
60#define MZN_ASSERT_HARD_MSG(c, e) \
61 do { \
62 if (!(c)) { \
63 __MZN_PRINT_SRCLOC(#c, e); \
64 std::ostringstream oss; \
65 oss << "not " << #c << ": " << e; \
66 throw MiniZinc::InternalError(oss.str()); \
67 } \
68 } while (0)
69
70inline bool beginswith(std::string s, std::string t) { return s.compare(0, t.length(), t) == 0; }
71
72inline void checkIOStatus(bool fOk, std::string msg, bool fHard = 1) {
73 if (!fOk) {
74#ifdef _MSC_VER
75 char errBuf[1024];
76 strerror_s(errBuf, sizeof(errBuf), errno);
77#else
78 char* errBuf = strerror(errno);
79#endif
80 std::cerr << "\n " << msg << ": " << errBuf << "." << std::endl;
81 MZN_ASSERT_HARD_MSG(!fHard, msg << ": " << errBuf);
82 }
83}
84
85template <class T>
86inline bool assignStr(T*, const std::string) {
87 return false;
88}
89template <>
90inline bool assignStr(std::string* pS, const std::string s) {
91 *pS = s;
92 return true;
93}
94
95/// A simple per-cmdline option parser
96class CLOParser {
97 int& i; // current item
98 std::vector<std::string>& argv;
99
100public:
101 CLOParser(int& ii, std::vector<std::string>& av) : i(ii), argv(av) {}
102 template <class Value = int>
103 inline bool get(const char* names, // space-separated option list
104 Value* pResult = nullptr, // pointer to value storage
105 bool fValueOptional = false // if pResult, for non-string values
106 ) {
107 return getOption(names, pResult, fValueOptional);
108 }
109 template <class Value = int>
110 inline bool getOption(const char* names, // space-separated option list
111 Value* pResult = nullptr, // pointer to value storage
112 bool fValueOptional = false // if pResult, for non-string values
113 ) {
114 assert(0 == strchr(names, ','));
115 assert(0 == strchr(names, ';'));
116 if (i >= argv.size()) return false;
117 std::string arg(argv[i]);
118 /// Separate keywords
119 std::string keyword;
120 std::istringstream iss(names);
121 while (iss >> keyword) {
122 if (((2 < keyword.size() || 0 == pResult) && arg != keyword) || // exact cmp
123 (0 != arg.compare(0, keyword.size(), keyword))) // truncated cmp
124 continue;
125 /// Process it
126 bool combinedArg = false; // whether arg and value are combined in one string (like -Ggecode)
127 if (keyword.size() < arg.size()) {
128 if (0 == pResult) continue;
129 combinedArg = true;
130 arg.erase(0, keyword.size());
131 } else {
132 if (0 == pResult) return true;
133 i++;
134 if (i >= argv.size()) {
135 --i;
136 return fValueOptional;
137 }
138 arg = argv[i];
139 }
140 assert(pResult);
141 if (assignStr(pResult, arg)) return true;
142 std::istringstream iss(arg);
143 Value tmp;
144 if (!(iss >> tmp)) {
145 if (!combinedArg) --i;
146 if (fValueOptional) {
147 return true;
148 }
149 // Not print because another agent can handle this option
150 // cerr << "\nBad value for " << keyword << ": " << arg << endl;
151 return false;
152 }
153 *pResult = tmp;
154 return true;
155 }
156 return false;
157 }
158}; // class CLOParser
159
160/// This class prints a value if non-0 and adds comma if not 1st time
161class HadOne {
162 bool fHadOne = false;
163
164public:
165 template <class N>
166 std::string operator()(const N& val, const char* descr = 0) {
167 std::ostringstream oss;
168 if (val) {
169 if (fHadOne) oss << ", ";
170 fHadOne = true;
171 oss << val;
172 if (descr) oss << descr;
173 }
174 return oss.str();
175 }
176 void reset() { fHadOne = false; }
177 operator bool() const { return fHadOne; }
178 bool operator!() const { return !fHadOne; }
179};
180
181/// Split a string into words
182/// Add the words into the given vector
183inline void split(const std::string& str, std::vector<std::string>& words) {
184 std::istringstream iss(str);
185 std::string buf;
186 while (iss) {
187 iss >> buf;
188 words.push_back(buf);
189 }
190}
191
192/// Puts the strings' c_str()s into the 2nd argument.
193/// The latter is only valid as long as the former isn't changed.
194inline void vecString2vecPChar(const std::vector<std::string>& vS, std::vector<const char*>& vPC) {
195 vPC.resize(vS.size());
196 for (size_t i = 0; i < vS.size(); ++i) {
197 vPC[i] = vS[i].c_str();
198 }
199}
200
201} // namespace MiniZinc
202
203#endif // __MINIZINC_UTILS_H__