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 |