libqasm
library for handling cQASM files
cqasm-v1-types.cpp
Go to the documentation of this file.
1 
5 #include <cctype>
6 #include "cqasm-v1-types.hpp"
7 
8 namespace cqasm {
9 namespace v1 {
10 namespace types {
11 
35 Types from_spec(const std::string &spec) {
36  // Count the number of qubits, in case we find a unitary parameter.
37  size_t num_qubits = 0;
38  for (auto c : spec) {
39  if (c == 'Q') {
40  num_qubits += 1;
41  }
42  }
43 
44  // Now resolve the types.
45  Types types;
46  for (auto c : spec) {
47  bool assignable = std::tolower(c) != (int)c;
48  switch (std::tolower(c)) {
49  case 'q':
50  if (!assignable) {
51  throw std::invalid_argument("use uppercase Q for qubits");
52  }
53  types.add_raw(new types::Qubit(true));
54  break;
55  case 'a':
56  types.add_raw(new types::Axis(assignable));
57  break;
58  case 'b':
59  types.add_raw(new types::Bool(assignable));
60  break;
61  case 'i':
62  types.add_raw(new types::Int(assignable));
63  break;
64  case 'r':
65  types.add_raw(new types::Real(assignable));
66  break;
67  case 'c':
68  types.add_raw(new types::Complex(assignable));
69  break;
70  case 'u':
71  types.add_raw(new types::ComplexMatrix(
72  1ull << num_qubits, 1ull << num_qubits, assignable));
73  break;
74  case 'm':
75  types.add_raw(new types::RealMatrix(-1, -1, assignable));
76  break;
77  case 'n':
78  types.add_raw(new types::ComplexMatrix(-1, -1, assignable));
79  break;
80  case 's':
81  types.add_raw(new types::String(assignable));
82  break;
83  case 'j':
84  types.add_raw(new types::Json(assignable));
85  break;
86  default:
87  throw std::invalid_argument("unknown type code encountered");
88  }
89  }
90  return types;
91 }
92 
97 bool type_check(const Type &expected, const Type &actual) {
98 
99  // Check assignability constraint.
100  if (expected->assignable && !actual->assignable) {
101  return false;
102  }
103 
104  // Check the type itself.
105  if (actual->type() != expected->type()) {
106  return false;
107  }
108 
109  // Check matrix constraints if applicable.
110  if (auto expected_real_mat = expected->as_real_matrix()) {
111  auto actual_mat = actual->as_real_matrix();
112  if (expected_real_mat->num_cols >= 0) {
113  if (actual_mat->num_cols != expected_real_mat->num_cols) {
114  return false;
115  }
116  }
117  if (expected_real_mat->num_rows >= 0) {
118  if (actual_mat->num_rows != expected_real_mat->num_rows) {
119  return false;
120  }
121  }
122  } else if (auto expected_complex_mat = expected->as_complex_matrix()) {
123  auto actual_mat = actual->as_complex_matrix();
124  if (expected_complex_mat->num_cols >= 0) {
125  if (actual_mat->num_cols != expected_complex_mat->num_cols) {
126  return false;
127  }
128  }
129  if (expected_complex_mat->num_rows >= 0) {
130  if (actual_mat->num_rows != expected_complex_mat->num_rows) {
131  return false;
132  }
133  }
134  }
135 
136  // All constraints seem to match.
137  return true;
138 }
139 
140 static void mat_size(std::ostream &os, tree::signed_size_t nrows, tree::signed_size_t ncols) {
141  if (ncols == 0) {
142  os << "empty matrix";
143  } else if (nrows == 1) {
144  os << ncols << "-dimensional vector";
145  } else {
146  if (nrows < 0) {
147  os << "*";
148  } else {
149  os << nrows;
150  }
151  os << "-by-";
152  if (ncols < 0) {
153  os << "*";
154  } else {
155  os << ncols;
156  }
157  os << " matrix";
158  }
159 }
160 
164 std::ostream &operator<<(std::ostream &os, const Type &type) {
165  if (type.empty()) {
166  os << "!EMPTY";
167  } else if (type->as_bool()) {
168  os << "bool/bit";
169  } else if (type->as_axis()) {
170  os << "axis";
171  } else if (type->as_int()) {
172  os << "int";
173  } else if (type->as_real()) {
174  os << "real";
175  } else if (type->as_complex()) {
176  os << "complex";
177  } else if (auto real_mat = type->as_real_matrix()) {
178  os << "real ";
179  mat_size(os, real_mat->num_rows, real_mat->num_cols);
180  } else if (auto complex_mat = type->as_complex_matrix()) {
181  os << "complex ";
182  mat_size(os, complex_mat->num_rows, complex_mat->num_cols);
183  } else if (type->as_string()) {
184  os << "string";
185  } else if (type->as_json()) {
186  os << "json";
187  } else if (type->as_qubit()) {
188  os << "qubit";
189  } else {
190  // Fallback when no friendly repr is known.
191  os << *type;
192  return os;
193  }
194  if (type->assignable) {
195  os << " reference";
196  }
197  return os;
198 }
199 
203 std::ostream &operator<<(std::ostream &os, const Types &types) {
204  os << "(";
205  bool first = true;
206  for (const auto &type : types) {
207  if (first) {
208  first = false;
209  } else {
210  os << ", ";
211  }
212  os << type;
213  }
214  os << ")";
215  return os;
216 }
217 
218 } // namespace types
219 } // namespace v1
220 } // namespace cqasm
Type of an integer (signed 64-bit).
Type of a real number (IEEE double).
Types from_spec(const std::string &spec)
Constructs a set of types from a shorthand string representation.
Toplevel namespace with entry points for the new API.
Type of an arbitrary string.
Type of a boolean/bit.
Type of a complex matrix.
Type of one or more qubit references.
Namespace for the "new" cQASM 1.x API.
Type of an axis (x, y, or z).
tree::One< TypeBase > Type
A cQASM type.
Type of a complex number (2x IEEE double).
bool type_check(const Type &expected, const Type &actual)
Returns whether the actual type matches the constraints of the expected type.
tree::Any< TypeBase > Types
Zero or more cQASM types.
Type of a JSON string.
std::ostream & operator<<(std::ostream &os, const Type &type)
Stream << overload for a single type.
::tree::signed_size_t signed_size_t
Definition: cqasm-tree.hpp:17
Defines the types of values available within cQASM&#39;s type system, as well as some utility functions...