XACC
matlab.h
Go to the documentation of this file.
1 /*
2  * This file is part of Quantum++.
3  *
4  * MIT License
5  *
6  * Copyright (c) 2013 - 2020 Vlad Gheorghiu.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
32 #ifndef MATLAB_MATLAB_H_
33 #define MATLAB_MATLAB_H_
34 
35 // MATLAB I/O interfacing
36 // add the path to $MATLAB_INSTALLATION_FOLDER/extern/include in include path
37 
38 #include "mat.h" // path to this file is defined in the Makefile
39 #include "mex.h" // path to this file is defined in the Makefile
40 
41 namespace qpp {
62 template <typename Derived> // double
63 typename std::enable_if<std::is_same<typename Derived::Scalar, cplx>::value,
64  dyn_mat<cplx>>::type
65 loadMATLAB(const std::string& mat_file, const std::string& var_name) {
66  MATFile* pmat = matOpen(mat_file.c_str(), "r");
67 
68  // EXCEPTION CHECKS
69 
70  if (!pmat) {
71  throw std::runtime_error(
72  "qpp::loadMATLAB(): Can not open MATLAB file " + mat_file + "!");
73  }
74 
75  mxArray* pa = matGetVariable(pmat, var_name.c_str());
76  if (!pa)
77  throw std::runtime_error(
78  "qpp::loadMATLAB(): Can not load the variable " + var_name +
79  " from MATLAB file " + mat_file + "!");
80 
81  if (mxGetNumberOfDimensions(pa) != 2) // not a matrix
82  throw std::runtime_error("qpp::loadMATLAB(): Loaded variable " +
83  var_name + " is not 2-dimensional!");
84 
85  if (!mxIsDouble(pa))
86  throw std::runtime_error("qpp::loadMATLAB(): Loaded variable " +
87  var_name +
88  " is not in double-precision format!");
89  // END EXCEPTION CHECKS
90 
91  idx rows = mxGetM(pa);
92  idx cols = mxGetN(pa);
93 
94  dyn_mat<double> result_re(rows, cols);
95  dyn_mat<double> result_im(rows, cols);
96 
97  // real part and imaginary part pointers
98  double* pa_re = nullptr;
99  double* pa_im = nullptr;
100 
101  // Populate the real part of the created array.
102  pa_re = mxGetPr(pa);
103  std::memcpy(result_re.data(), pa_re,
104  sizeof(double) * mxGetNumberOfElements(pa));
105 
106  if (mxIsComplex(pa)) // populate the imaginary part if exists
107  {
108  pa_im = mxGetPi(pa);
109  std::memcpy(result_im.data(), pa_im,
110  sizeof(double) * mxGetNumberOfElements(pa));
111  } else // set to zero the imaginary part
112  {
113  std::memset(result_im.data(), 0,
114  sizeof(double) * mxGetNumberOfElements(pa));
115  }
116 
117  mxDestroyArray(pa);
118  matClose(pmat);
119 
120  return (result_re.cast<cplx>()) + 1_i * (result_im.cast<cplx>());
121 }
122 
143 template <typename Derived> // cplx
144 typename std::enable_if<!std::is_same<typename Derived::Scalar, cplx>::value,
145  dyn_mat<typename Derived::Scalar>>::type
146 loadMATLAB(const std::string& mat_file, const std::string& var_name) {
147  MATFile* pmat = matOpen(mat_file.c_str(), "r");
148 
149  // EXCEPTION CHECKS
150 
151  if (!pmat) {
152  throw std::runtime_error(
153  "qpp::loadMATLAB(): Can not open MATLAB file " + mat_file + "!");
154  }
155 
156  mxArray* pa = matGetVariable(pmat, var_name.c_str());
157  if (!pa)
158  throw std::runtime_error(
159  "qpp::loadMATLAB(): Can not load the variable " + var_name +
160  " from MATLAB file " + mat_file + "!");
161 
162  if (mxGetNumberOfDimensions(pa) != 2) // not a matrix
163  throw std::runtime_error("qpp::loadMATLAB(): Loaded variable " +
164  var_name + " is not 2-dimensional!");
165 
166  if (!mxIsDouble(pa))
167  throw std::runtime_error("qpp::loadMATLAB(): Loaded variable " +
168  var_name +
169  " is not in double-precision format!");
170  // END EXCEPTION CHECKS
171 
172  idx rows = mxGetM(pa);
173  idx cols = mxGetN(pa);
174 
175  dyn_mat<double> result(rows, cols);
176 
177  std::memcpy(result.data(), mxGetPr(pa),
178  sizeof(double) * mxGetNumberOfElements(pa));
179 
180  mxDestroyArray(pa);
181  matClose(pmat);
182 
183  // cast back to the original type
184  return result.cast<typename Derived::Scalar>();
185 }
186 
199 template <typename Derived>
200 // double
201 typename std::enable_if<
202  std::is_same<typename Derived::Scalar, cplx>::value>::type
203 saveMATLAB(const Eigen::MatrixBase<Derived>& A, const std::string& mat_file,
204  const std::string& var_name, const std::string& mode) {
205  const dyn_mat<cplx>& rA = A.derived();
206 
207  // EXCEPTION CHECKS
208 
209  // check zero-size
210  if (!internal::check_nonzero_size(rA))
211  throw exception::ZeroSize("qpp::saveMATLAB()");
212 
213  // cast the input to a double (internal MATLAB format)
214  dyn_mat<double> tmp_re = rA.real();
215  dyn_mat<double> tmp_im = rA.imag();
216 
217  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
218  if (!pmat)
219  throw std::runtime_error(
220  "qpp::saveMATLAB(): Can not open/create MATLAB file " + mat_file +
221  "!");
222 
223  mxArray* pa = mxCreateDoubleMatrix(tmp_re.rows(), tmp_re.cols(), mxCOMPLEX);
224  if (!pa)
225  throw std::runtime_error(
226  "qpp::saveMATLAB(): mxCreateDoubleMatrix failed!");
227  // END EXCEPTION CHECKS
228 
229  // real part and imaginary part pointers
230  double* pa_re = nullptr;
231  double* pa_im = nullptr;
232 
233  /* Populate the real part of the created array. */
234  pa_re = mxGetPr(pa);
235  std::memcpy(pa_re, tmp_re.data(), sizeof(double) * tmp_re.size());
236 
237  /* Populate the imaginary part of the created array. */
238  pa_im = mxGetPi(pa);
239  std::memcpy(pa_im, tmp_im.data(), sizeof(double) * tmp_im.size());
240 
241  if (matPutVariable(pmat, var_name.c_str(), pa))
242  throw std::runtime_error(
243  "qpp::saveMATLAB(): Can not write the variable " + var_name +
244  " to MATLAB file " + mat_file + "!");
245 
246  mxDestroyArray(pa);
247  matClose(pmat);
248 }
249 
262 template <typename Derived>
263 // cplx
264 typename std::enable_if<
265  !std::is_same<typename Derived::Scalar, cplx>::value>::type
266 saveMATLAB(const Eigen::MatrixBase<Derived>& A, const std::string& mat_file,
267  const std::string& var_name, const std::string& mode) {
268  // cast to double, as MATLAB doesn't work with other types
269  const dyn_mat<double>& rA = A.template cast<double>();
270 
271  // EXCEPTION CHECKS
272 
273  // check zero-size
274  if (!internal::check_nonzero_size(rA))
275  throw exception::ZeroSize("qpp::saveMATLAB()");
276 
277  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
278  if (!pmat)
279  throw std::runtime_error(
280  "qpp::saveMATLAB(): Can not open/create MATLAB file " + mat_file +
281  "!");
282 
283  mxArray* pa = mxCreateDoubleMatrix(rA.rows(), rA.cols(), mxREAL);
284  if (!pa)
285  throw std::runtime_error(
286  "qpp::saveMATLAB(): mxCreateDoubleMatrix failed!");
287  // END EXCEPTION CHECKS
288 
289  std::memcpy(mxGetPr(pa), rA.data(), sizeof(double) * rA.size());
290 
291  if (matPutVariable(pmat, var_name.c_str(), pa))
292  throw std::runtime_error(
293  "qpp::saveMATLAB(): Can not write the variable " + var_name +
294  " to MATLAB file " + mat_file + "!");
295 
296  mxDestroyArray(pa);
297  matClose(pmat);
298 }
299 
300 } /* namespace qpp */
301 #endif /* MATLAB_MATLAB_H_ */
Quantum++ main namespace.
Definition: circuits.h:35