GCC Code Coverage Report


Directory: ./
File: Ops/ClassicalOps.cpp
Date: 2022-10-15 05:10:18
Exec Total Coverage
Lines: 153 311 49.2%
Functions: 26 41 63.4%
Branches: 149 612 24.3%
Decisions: 37 94 39.4%

Line Branch Decision Exec Source
1 // Copyright 2019-2022 Cambridge Quantum Computing
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "ClassicalOps.hpp"
16
17 #include <tkassert/Assert.hpp>
18
19 #include "OpType/OpType.hpp"
20 #include "Utils/Json.hpp"
21
22 namespace tket {
23
24 22 static uint32_t u32_from_boolvec(const std::vector<bool> &x) {
25 22 unsigned n = x.size();
26
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 22 times.
22 if (n > 32) {
27 throw std::domain_error("Vector of bool exceeds maximum size (32)");
28 }
29 22 uint32_t X = 0;
30
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 22 times.
2/2
✓ Decision 'true' taken 60 times.
✓ Decision 'false' taken 22 times.
82 for (unsigned i = 0; i < n; i++) {
31
2/2
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 31 times.
2/2
✓ Decision 'true' taken 22 times.
✓ Decision 'false' taken 38 times.
60 if (x[i]) X |= (1u << i);
32 }
33 22 return X;
34 }
35
36 static nlohmann::json classical_to_json(const Op_ptr &op, const OpType &type) {
37 nlohmann::json j_class;
38 switch (type) {
39
0/1
✗ Decision 'true' not taken.
case OpType::MultiBit: {
40 const auto &multibit = static_cast<const MultiBitOp &>(*op);
41 j_class["op"] = multibit.get_op();
42 j_class["n"] = multibit.get_n();
43 return j_class;
44 }
45
0/1
✗ Decision 'true' not taken.
case OpType::RangePredicate: {
46 const auto &rangop = static_cast<const RangePredicateOp &>(*op);
47 j_class["lower"] = rangop.lower();
48 j_class["upper"] = rangop.upper();
49 j_class["n_i"] = rangop.get_n_i();
50 return j_class;
51 }
52
0/1
✗ Decision 'true' not taken.
case OpType::ExplicitModifier: {
53 const auto &expmodop = static_cast<const ExplicitModifierOp &>(*op);
54 j_class["n_i"] = expmodop.get_n_i();
55 j_class["values"] = expmodop.get_values();
56 j_class["name"] = expmodop.get_name();
57 return j_class;
58 }
59
0/1
✗ Decision 'true' not taken.
case OpType::ExplicitPredicate: {
60 const auto &exppredop = static_cast<const ExplicitPredicateOp &>(*op);
61 j_class["n_i"] = exppredop.get_n_i();
62 j_class["values"] = exppredop.get_values();
63 j_class["name"] = exppredop.get_name();
64 return j_class;
65 }
66
0/1
✗ Decision 'true' not taken.
case OpType::ClassicalTransform: {
67 const auto &classtop = static_cast<const ClassicalTransformOp &>(*op);
68 j_class["n_io"] = classtop.get_n_io();
69 j_class["values"] = classtop.get_values();
70 j_class["name"] = classtop.get_name();
71 return j_class;
72 }
73
0/1
✗ Decision 'true' not taken.
case OpType::SetBits: {
74 const auto &setop = static_cast<const SetBitsOp &>(*op);
75 j_class["values"] = setop.get_values();
76 return j_class;
77 }
78
0/1
✗ Decision 'true' not taken.
case OpType::CopyBits: {
79 const auto &cop = static_cast<const CopyBitsOp &>(*op);
80 j_class["n_i"] = cop.get_n_i();
81 return j_class;
82 }
83
0/1
✗ Decision 'true' not taken.
default:
84 throw JsonError(
85 "Classical op with type " + optypeinfo().at(type).name +
86 " cannot be serialized.");
87 }
88 }
89
90 static std::shared_ptr<ClassicalEvalOp> classical_from_json(
91 const nlohmann::json &j_class, const OpType &type) {
92 switch (type) {
93
0/1
✗ Decision 'true' not taken.
case OpType::MultiBit:
94 return std::make_shared<MultiBitOp>(
95 classical_from_json(
96 j_class.at("op").at("classical"),
97 j_class.at("op").at("type").get<OpType>()),
98 j_class.at("n").get<unsigned>());
99
0/1
✗ Decision 'true' not taken.
case OpType::RangePredicate:
100 return std::make_shared<RangePredicateOp>(
101 j_class.at("n_i").get<unsigned>(),
102 j_class.at("lower").get<unsigned>(),
103 j_class.at("upper").get<unsigned>());
104
0/1
✗ Decision 'true' not taken.
case OpType::CopyBits:
105 return std::make_shared<CopyBitsOp>(j_class.at("n_i").get<unsigned>());
106
0/1
✗ Decision 'true' not taken.
case OpType::SetBits:
107 return std::make_shared<SetBitsOp>(
108 j_class.at("values").get<std::vector<bool>>());
109
0/1
✗ Decision 'true' not taken.
case OpType::ExplicitModifier:
110 return std::make_shared<ExplicitModifierOp>(
111 j_class.at("n_i").get<unsigned>(),
112 j_class.at("values").get<std::vector<bool>>(),
113 j_class.at("name").get<std::string>());
114
0/1
✗ Decision 'true' not taken.
case OpType::ExplicitPredicate:
115 return std::make_shared<ExplicitPredicateOp>(
116 j_class.at("n_i").get<unsigned>(),
117 j_class.at("values").get<std::vector<bool>>(),
118 j_class.at("name").get<std::string>());
119
0/1
✗ Decision 'true' not taken.
case OpType::ClassicalTransform:
120 return std::make_shared<ClassicalTransformOp>(
121 j_class.at("n_io").get<unsigned>(),
122 j_class.at("values").get<std::vector<uint32_t>>(),
123 j_class.at("name").get<std::string>());
124
0/1
✗ Decision 'true' not taken.
default:
125 throw JsonError(
126 "Classical op with name " + j_class.at("name").get<std::string>() +
127 " cannot be deserialized.");
128 }
129 }
130
131 1 static nlohmann::json wasm_to_json(const Op_ptr &op) {
132 1 nlohmann::json j_class;
133 1 const auto &wasm = static_cast<const WASMOp &>(*op);
134
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 j_class["n"] = wasm.get_n();
135
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 j_class["ni_vec"] = wasm.get_ni_vec();
136
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 j_class["no_vec"] = wasm.get_no_vec();
137
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 j_class["func_name"] = wasm.get_func_name();
138
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 j_class["wasm_uid"] = wasm.get_wasm_uid();
139 1 return j_class;
140 }
141
142 1 static std::shared_ptr<WASMOp> wasm_from_json(const nlohmann::json &j_class) {
143 return std::make_shared<WASMOp>(
144
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 j_class.at("n").get<unsigned>(),
145
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 j_class.at("ni_vec").get<std::vector<unsigned>>(),
146
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 j_class.at("no_vec").get<std::vector<unsigned>>(),
147
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 j_class.at("func_name").get<std::string>(),
148
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
3 j_class.at("wasm_uid").get<std::string>());
149 }
150
151 34 ClassicalOp::ClassicalOp(
152 OpType type, unsigned n_i, unsigned n_io, unsigned n_o,
153 34 const std::string &name)
154
1/2
✓ Branch 2 taken 34 times.
✗ Branch 3 not taken.
34 : Op(type), n_i_(n_i), n_io_(n_io), n_o_(n_o), name_(name), sig_() {
155
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 34 times.
2/2
✓ Decision 'true' taken 58 times.
✓ Decision 'false' taken 34 times.
92 for (unsigned i = 0; i < n_i; i++) {
156
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 sig_.push_back(EdgeType::Boolean);
157 }
158
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 34 times.
2/2
✓ Decision 'true' taken 44 times.
✓ Decision 'false' taken 34 times.
78 for (unsigned j = 0; j < n_io + n_o; j++) {
159
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 sig_.push_back(EdgeType::Classical);
160 }
161 34 }
162
163 18 ClassicalEvalOp::ClassicalEvalOp(
164 OpType type, unsigned n_i, unsigned n_io, unsigned n_o,
165 18 const std::string &name)
166 18 : ClassicalOp(type, n_i, n_io, n_o, name) {}
167
168 nlohmann::json ClassicalOp::serialize() const {
169 nlohmann::json j;
170 j["type"] = get_type();
171 j["classical"] = classical_to_json(shared_from_this(), get_type());
172 return j;
173 }
174
175 Op_ptr ClassicalOp::deserialize(const nlohmann::json &j) {
176 return classical_from_json(j.at("classical"), j.at("type").get<OpType>());
177 }
178
179 1 nlohmann::json WASMOp::serialize() const {
180 1 nlohmann::json j;
181
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 j["type"] = get_type();
182
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 j["wasm"] = wasm_to_json(shared_from_this());
183 1 return j;
184 }
185
186 1 Op_ptr WASMOp::deserialize(const nlohmann::json &j) {
187 1 return wasm_from_json(j.at("wasm"));
188 }
189
190 1 std::string ClassicalOp::get_name(bool) const { return name_; }
191
192 bool ClassicalOp::is_equal(const Op &op_other) const {
193 const ClassicalOp &other = dynamic_cast<const ClassicalOp &>(op_other);
194
195
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (n_i_ != other.get_n_i()) return false;
196
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (n_io_ != other.get_n_io()) return false;
197
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (n_o_ != other.get_n_o()) return false;
198 return true;
199 }
200
201 bool ClassicalEvalOp::is_equal(const Op &op_other) const {
202 const ClassicalEvalOp &other =
203 dynamic_cast<const ClassicalEvalOp &>(op_other);
204
205
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (n_i_ != other.get_n_i()) return false;
206
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (n_io_ != other.get_n_io()) return false;
207
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (n_o_ != other.get_n_o()) return false;
208 unsigned N = n_i_ + n_io_;
209 uint32_t xlim = 1u << N;
210 std::vector<bool> v(N);
211
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
for (uint32_t x = 0; x < xlim; x++) {
212
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
for (unsigned i = 0; i < N; i++) {
213 v[i] = (x >> i) & 1;
214 }
215
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (eval(v) != other.eval(v)) return false;
216 }
217 return true;
218 }
219
220 8 ClassicalTransformOp::ClassicalTransformOp(
221 8 unsigned n, const std::vector<uint32_t> &values, const std::string &name)
222 : ClassicalEvalOp(OpType::ClassicalTransform, 0, n, 0, name),
223
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 values_(values) {
224
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
8 if (n > 32) {
225 throw std::domain_error("Too many inputs/outputs (maximum is 32)");
226 }
227 8 }
228
229 12 std::vector<bool> ClassicalTransformOp::eval(const std::vector<bool> &x) const {
230
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 12 times.
12 if (x.size() != n_io_) {
231 throw std::domain_error("Incorrect input size");
232 }
233 12 uint32_t val = values_[u32_from_boolvec(x)];
234
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 std::vector<bool> y(n_io_);
235
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 12 times.
2/2
✓ Decision 'true' taken 32 times.
✓ Decision 'false' taken 12 times.
44 for (unsigned j = 0; j < n_io_; j++) {
236
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 y[j] = (val >> j) & 1;
237 }
238 12 return y;
239 }
240
241 16 WASMOp::WASMOp(
242 unsigned _n, std::vector<unsigned> _ni_vec, std::vector<unsigned> _no_vec,
243 16 const std::string &_func_name, const std::string &_wasm_uid)
244 : ClassicalOp(
245 OpType::WASM,
246 std::accumulate(
247 _ni_vec.begin(), _ni_vec.end(), decltype(_ni_vec)::value_type(0)),
248 0,
249 std::accumulate(
250 _no_vec.begin(), _no_vec.end(), decltype(_no_vec)::value_type(0)),
251 "WASM"),
252 16 n_(_n),
253 16 n_i32_(_ni_vec.size() + _no_vec.size()),
254
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ni_vec_(_ni_vec),
255
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 no_vec_(_no_vec),
256
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 func_name_(_func_name),
257
3/6
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 11 taken 16 times.
✗ Branch 12 not taken.
✓ Branch 17 taken 16 times.
✗ Branch 18 not taken.
32 wasm_uid_(_wasm_uid) {
258 unsigned sum_of_i32 =
259 16 std::accumulate(
260 ni_vec_.begin(), ni_vec_.end(), decltype(ni_vec_)::value_type(0)) +
261 16 std::accumulate(
262 16 no_vec_.begin(), no_vec_.end(), decltype(no_vec_)::value_type(0));
263
264 TKET_ASSERT(sum_of_i32 == n_);
265 16 }
266
267 6 bool WASMOp::is_equal(const Op &other) const {
268
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 6 times.
6 if (other.get_type() != OpType::WASM) {
269 return false;
270 }
271
272
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 const WASMOp &other_wasm = dynamic_cast<const WASMOp &>(other);
273
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 2 times.
6 if (other_wasm.get_n() != n_) return false;
274
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
1/2
✓ Decision 'true' taken 4 times.
✗ Decision 'false' not taken.
4 if (other_wasm.get_n_i32() != n_i32_) return false;
275
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
1/2
✓ Decision 'true' taken 4 times.
✗ Decision 'false' not taken.
4 if (other_wasm.get_ni_vec() != ni_vec_) return false;
276
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
1/2
✓ Decision 'true' taken 4 times.
✗ Decision 'false' not taken.
4 if (other_wasm.get_no_vec() != no_vec_) return false;
277
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3 times.
2/2
✓ Decision 'true' taken 3 times.
✓ Decision 'false' taken 1 times.
4 if (other_wasm.get_func_name() != func_name_) return false;
278
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1 times.
3 if (other_wasm.get_wasm_uid() != wasm_uid_) return false;
279 2 return true;
280 }
281
282 std::string SetBitsOp::get_name(bool) const {
283 std::stringstream name;
284 name << name_ << "(";
285
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
for (auto v : values_) {
286 name << v; // "0" or "1"
287 }
288 name << ")";
289 return name.str();
290 }
291
292 4 std::vector<bool> SetBitsOp::eval(const std::vector<bool> &x) const {
293
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 4 times.
4 if (!x.empty()) {
294 throw std::domain_error("Non-empty input");
295 }
296 4 return values_;
297 }
298
299 std::vector<bool> CopyBitsOp::eval(const std::vector<bool> &x) const {
300
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (x.size() != n_i_) {
301 throw std::domain_error("Incorrect input size");
302 }
303 return x;
304 }
305
306 std::string RangePredicateOp::get_name(bool) const {
307 std::stringstream name;
308 name << name_ << "([" << a << "," << b << "])";
309 return name.str();
310 }
311
312 8 std::vector<bool> RangePredicateOp::eval(const std::vector<bool> &x) const {
313
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 8 times.
8 if (x.size() != n_i_) {
314 throw std::domain_error("Incorrect input size");
315 }
316 8 uint32_t X = u32_from_boolvec(x);
317
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 std::vector<bool> y(1);
318
5/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 1 times.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
8 y[0] = (X >= a && X <= b);
319 8 return y;
320 }
321
322 bool RangePredicateOp::is_equal(const Op &op_other) const {
323 const RangePredicateOp &other =
324 dynamic_cast<const RangePredicateOp &>(op_other);
325
326
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (n_i_ != other.n_i_) return false;
327 return (a == other.a && b == other.b);
328 }
329
330 3 ExplicitPredicateOp::ExplicitPredicateOp(
331 3 unsigned n, const std::vector<bool> &values, const std::string &name)
332
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 : PredicateOp(OpType::ExplicitPredicate, n, name), values_(values) {
333
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 3 times.
3 if (n > 32) {
334 throw std::domain_error("Too many inputs");
335 }
336 3 }
337
338 2 std::vector<bool> ExplicitPredicateOp::eval(const std::vector<bool> &x) const {
339
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 2 times.
2 if (x.size() != n_i_) {
340 throw std::domain_error("Incorrect input size");
341 }
342
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 std::vector<bool> y(1);
343
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
2 y[0] = values_[u32_from_boolvec(x)];
344 2 return y;
345 }
346
347 2 ExplicitModifierOp::ExplicitModifierOp(
348 2 unsigned n, const std::vector<bool> &values, const std::string &name)
349
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 : ModifyingOp(OpType::ExplicitModifier, n, name), values_(values) {
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 2 times.
2 if (n > 31) {
351 throw std::domain_error("Too many inputs");
352 }
353 2 }
354
355 std::vector<bool> ExplicitModifierOp::eval(const std::vector<bool> &x) const {
356
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (x.size() != n_i_ + 1) {
357 throw std::domain_error("Incorrect input size");
358 }
359 std::vector<bool> y(1);
360 y[0] = values_[u32_from_boolvec(x)];
361 return y;
362 }
363
364 1 MultiBitOp::MultiBitOp(std::shared_ptr<const ClassicalEvalOp> op, unsigned n)
365 : ClassicalEvalOp(
366 2 OpType::MultiBit, n * op->get_n_i(), n * op->get_n_io(),
367 2 n * op->get_n_o(), op->get_name()),
368 1 op_(op),
369
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
5 n_(n) {
370
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 op_signature_t op_sig = op->get_signature();
371 1 const std::size_t op_sig_size = op_sig.size();
372 1 sig_.clear();
373
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 sig_.reserve(n_ * op_sig.size());
374
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1 times.
3 for (unsigned i = 0; i < n_; i++) {
375
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 std::copy_n(op_sig.begin(), op_sig_size, std::back_inserter(sig_));
376 }
377 1 }
378
379 std::string MultiBitOp::get_name(bool) const {
380 std::stringstream name;
381 name << name_ << " (*" << n_ << ")";
382 return name.str();
383 }
384
385 1 std::vector<bool> MultiBitOp::eval(const std::vector<bool> &x) const {
386
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 1 times.
1 if (x.size() != n_i_ + n_io_) {
387 throw std::domain_error("Incorrect input size");
388 }
389 1 unsigned n_op_inputs = op_->get_n_i() + op_->get_n_io();
390 1 unsigned n_op_outputs = op_->get_n_io() + op_->get_n_o();
391
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 std::vector<bool> y(n_io_ + n_o_);
392
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 1 times.
3 for (unsigned i = 0; i < n_; i++) {
393
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 std::vector<bool> x_i(n_op_inputs);
394
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
2/2
✓ Decision 'true' taken 4 times.
✓ Decision 'false' taken 2 times.
6 for (unsigned j = 0; j < n_op_inputs; j++) {
395
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 x_i[j] = x[n_op_inputs * i + j];
396 }
397
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 std::vector<bool> y_i = op_->eval(x_i);
398
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 2 times.
4 for (unsigned j = 0; j < n_op_outputs; j++) {
399
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 y[n_op_outputs * i + j] = y_i[j];
400 }
401 2 }
402 1 return y;
403 }
404
405 bool MultiBitOp::is_equal(const Op &op_other) const {
406 const MultiBitOp &other = dynamic_cast<const MultiBitOp &>(op_other);
407
408
0/2
✗ Decision 'true' not taken.
✗ Decision 'false' not taken.
if (n_ != other.n_) return false;
409 return (*op_ == *(other.op_));
410 }
411
412 7 std::shared_ptr<ClassicalTransformOp> ClassicalX() {
413
4/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
7 static const std::vector<uint32_t> values = {1, 0};
414 static const std::shared_ptr<ClassicalTransformOp> op =
415
4/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
7 std::make_shared<ClassicalTransformOp>(1, values, "ClassicalX");
416 7 return op;
417 }
418
419 1 std::shared_ptr<ClassicalTransformOp> ClassicalCX() {
420
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
1 static const std::vector<uint32_t> values = {0, 3, 2, 1};
421 static const std::shared_ptr<ClassicalTransformOp> op =
422
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1 std::make_shared<ClassicalTransformOp>(2, values, "ClassicalCX");
423 1 return op;
424 }
425
426 1 std::shared_ptr<ExplicitPredicateOp> NotOp() {
427
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
1 static const std::vector<bool> values = {1, 0};
428 static const std::shared_ptr<ExplicitPredicateOp> op =
429
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1 std::make_shared<ExplicitPredicateOp>(1, values, "NOT");
430 1 return op;
431 }
432
433 2 std::shared_ptr<ExplicitPredicateOp> AndOp() {
434
4/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
2 static const std::vector<bool> values = {0, 0, 0, 1};
435 static const std::shared_ptr<ExplicitPredicateOp> op =
436
4/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 std::make_shared<ExplicitPredicateOp>(2, values, "AND");
437 2 return op;
438 }
439
440 1 std::shared_ptr<ExplicitPredicateOp> OrOp() {
441
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
1 static const std::vector<bool> values = {0, 1, 1, 1};
442 static const std::shared_ptr<ExplicitPredicateOp> op =
443
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1 std::make_shared<ExplicitPredicateOp>(2, values, "OR");
444 1 return op;
445 }
446
447 std::shared_ptr<ExplicitPredicateOp> XorOp() {
448 static const std::vector<bool> values = {0, 1, 1, 0};
449 static const std::shared_ptr<ExplicitPredicateOp> op =
450 std::make_shared<ExplicitPredicateOp>(2, values, "XOR");
451 return op;
452 }
453
454 1 std::shared_ptr<ExplicitModifierOp> AndWithOp() {
455
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
1 static const std::vector<bool> values = {0, 0, 0, 1};
456 static const std::shared_ptr<ExplicitModifierOp> op =
457
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1 std::make_shared<ExplicitModifierOp>(1, values, "AND");
458 1 return op;
459 }
460
461 1 std::shared_ptr<ExplicitModifierOp> OrWithOp() {
462
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
1 static const std::vector<bool> values = {0, 1, 1, 1};
463 static const std::shared_ptr<ExplicitModifierOp> op =
464
3/8
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
1 std::make_shared<ExplicitModifierOp>(1, values, "OR");
465 1 return op;
466 }
467
468 std::shared_ptr<ExplicitModifierOp> XorWithOp() {
469 static const std::vector<bool> values = {0, 1, 1, 0};
470 static const std::shared_ptr<ExplicitModifierOp> op =
471 std::make_shared<ExplicitModifierOp>(1, values, "XOR");
472 return op;
473 }
474
475 } // namespace tket
476