Quantum++  v1.1
A modern C++11 quantum computing library
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 - 2019 Vlad Gheorghiu (vgheorgh@gmail.com)
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 {
63 template <typename Derived> // double
64 typename std::enable_if<std::is_same<typename Derived::Scalar, cplx>::value,
65  dyn_mat<cplx>>::type
66 loadMATLAB(const std::string& mat_file, const std::string& var_name) {
67  MATFile* pmat = matOpen(mat_file.c_str(), "r");
68 
69  // EXCEPTION CHECKS
70 
71  if (!pmat) {
72  throw std::runtime_error(
73  "qpp::loadMATLAB(): Can not open MATLAB file " + mat_file + "!");
74  }
75 
76  mxArray* pa = matGetVariable(pmat, var_name.c_str());
77  if (!pa)
78  throw std::runtime_error(
79  "qpp::loadMATLAB(): Can not load the variable " + var_name +
80  " from MATLAB file " + mat_file + "!");
81 
82  if (mxGetNumberOfDimensions(pa) != 2) // not a matrix
83  throw std::runtime_error("qpp::loadMATLAB(): Loaded variable " +
84  var_name + " is not 2-dimensional!");
85 
86  if (!mxIsDouble(pa))
87  throw std::runtime_error("qpp::loadMATLAB(): Loaded variable " +
88  var_name +
89  " is not in double-precision format!");
90  // END EXCEPTION CHECKS
91 
92  idx rows = mxGetM(pa);
93  idx cols = mxGetN(pa);
94 
95  dyn_mat<double> result_re(rows, cols);
96  dyn_mat<double> result_im(rows, cols);
97 
98  // real part and imaginary part pointers
99  double* pa_re = nullptr;
100  double* pa_im = nullptr;
101 
102  // Populate the real part of the created array.
103  pa_re = mxGetPr(pa);
104  std::memcpy(result_re.data(), pa_re,
105  sizeof(double) * mxGetNumberOfElements(pa));
106 
107  if (mxIsComplex(pa)) // populate the imaginary part if exists
108  {
109  pa_im = mxGetPi(pa);
110  std::memcpy(result_im.data(), pa_im,
111  sizeof(double) * mxGetNumberOfElements(pa));
112  } else // set to zero the imaginary part
113  {
114  std::memset(result_im.data(), 0,
115  sizeof(double) * mxGetNumberOfElements(pa));
116  }
117 
118  mxDestroyArray(pa);
119  matClose(pmat);
120 
121  return (result_re.cast<cplx>()) + 1_i * (result_im.cast<cplx>());
122 }
123 
145 template <typename Derived> // cplx
146 typename std::enable_if<!std::is_same<typename Derived::Scalar, cplx>::value,
148 loadMATLAB(const std::string& mat_file, const std::string& var_name) {
149  MATFile* pmat = matOpen(mat_file.c_str(), "r");
150 
151  // EXCEPTION CHECKS
152 
153  if (!pmat) {
154  throw std::runtime_error(
155  "qpp::loadMATLAB(): Can not open MATLAB file " + mat_file + "!");
156  }
157 
158  mxArray* pa = matGetVariable(pmat, var_name.c_str());
159  if (!pa)
160  throw std::runtime_error(
161  "qpp::loadMATLAB(): Can not load the variable " + var_name +
162  " from MATLAB file " + mat_file + "!");
163 
164  if (mxGetNumberOfDimensions(pa) != 2) // not a matrix
165  throw std::runtime_error("qpp::loadMATLAB(): Loaded variable " +
166  var_name + " is not 2-dimensional!");
167 
168  if (!mxIsDouble(pa))
169  throw std::runtime_error("qpp::loadMATLAB(): Loaded variable " +
170  var_name +
171  " is not in double-precision format!");
172  // END EXCEPTION CHECKS
173 
174  idx rows = mxGetM(pa);
175  idx cols = mxGetN(pa);
176 
177  dyn_mat<double> result(rows, cols);
178 
179  std::memcpy(result.data(), mxGetPr(pa),
180  sizeof(double) * mxGetNumberOfElements(pa));
181 
182  mxDestroyArray(pa);
183  matClose(pmat);
184 
185  // cast back to the original type
186  return result.cast<typename Derived::Scalar>();
187 }
188 
201 template <typename Derived>
202 // double
203 typename std::enable_if<
204  std::is_same<typename Derived::Scalar, cplx>::value>::type
205 saveMATLAB(const Eigen::MatrixBase<Derived>& A, const std::string& mat_file,
206  const std::string& var_name, const std::string& mode) {
207  const dyn_mat<cplx>& rA = A.derived();
208 
209  // EXCEPTION CHECKS
210 
211  // check zero-size
213  throw exception::ZeroSize("qpp::saveMATLAB()");
214 
215  // cast the input to a double (internal MATLAB format)
216  dyn_mat<double> tmp_re = rA.real();
217  dyn_mat<double> tmp_im = rA.imag();
218 
219  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
220  if (!pmat)
221  throw std::runtime_error(
222  "qpp::saveMATLAB(): Can not open/create MATLAB file " + mat_file +
223  "!");
224 
225  mxArray* pa = mxCreateDoubleMatrix(tmp_re.rows(), tmp_re.cols(), mxCOMPLEX);
226  if (!pa)
227  throw std::runtime_error(
228  "qpp::saveMATLAB(): mxCreateDoubleMatrix failed!");
229  // END EXCEPTION CHECKS
230 
231  // real part and imaginary part pointers
232  double* pa_re = nullptr;
233  double* pa_im = nullptr;
234 
235  /* Populate the real part of the created array. */
236  pa_re = mxGetPr(pa);
237  std::memcpy(pa_re, tmp_re.data(), sizeof(double) * tmp_re.size());
238 
239  /* Populate the imaginary part of the created array. */
240  pa_im = mxGetPi(pa);
241  std::memcpy(pa_im, tmp_im.data(), sizeof(double) * tmp_im.size());
242 
243  if (matPutVariable(pmat, var_name.c_str(), pa))
244  throw std::runtime_error(
245  "qpp::saveMATLAB(): Can not write the variable " + var_name +
246  " to MATLAB file " + mat_file + "!");
247 
248  mxDestroyArray(pa);
249  matClose(pmat);
250 }
251 
264 template <typename Derived>
265 // cplx
266 typename std::enable_if<
267  !std::is_same<typename Derived::Scalar, cplx>::value>::type
268 saveMATLAB(const Eigen::MatrixBase<Derived>& A, const std::string& mat_file,
269  const std::string& var_name, const std::string& mode) {
270  // cast to double, as MATLAB doesn't work with other types
271  const dyn_mat<double>& rA = A.template cast<double>();
272 
273  // EXCEPTION CHECKS
274 
275  // check zero-size
277  throw exception::ZeroSize("qpp::saveMATLAB()");
278 
279  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
280  if (!pmat)
281  throw std::runtime_error(
282  "qpp::saveMATLAB(): Can not open/create MATLAB file " + mat_file +
283  "!");
284 
285  mxArray* pa = mxCreateDoubleMatrix(rA.rows(), rA.cols(), mxREAL);
286  if (!pa)
287  throw std::runtime_error(
288  "qpp::saveMATLAB(): mxCreateDoubleMatrix failed!");
289  // END EXCEPTION CHECKS
290 
291  std::memcpy(mxGetPr(pa), rA.data(), sizeof(double) * rA.size());
292 
293  if (matPutVariable(pmat, var_name.c_str(), pa))
294  throw std::runtime_error(
295  "qpp::saveMATLAB(): Can not write the variable " + var_name +
296  " to MATLAB file " + mat_file + "!");
297 
298  mxDestroyArray(pa);
299  matClose(pmat);
300 }
301 
302 } /* namespace qpp */
303 #endif /* MATLAB_MATLAB_H_ */
bool check_nonzero_size(const T &x) noexcept
Definition: util.h:123
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > dyn_mat
Dynamic Eigen matrix over the field specified by Scalar.
Definition: types.h:81
Quantum++ main namespace.
Definition: codes.h:35
std::complex< double > cplx
Complex number in double precision.
Definition: types.h:49
std::enable_if< std::is_same< typename Derived::Scalar, cplx >::value, dyn_mat< cplx > >::type loadMATLAB(const std::string &mat_file, const std::string &var_name)
Loads a complex Eigen dynamic matrix from a MATLAB .mat file,.
Definition: matlab.h:66
std::size_t idx
Non-negative integer index.
Definition: types.h:39
std::enable_if< std::is_same< typename Derived::Scalar, cplx >::value >::type saveMATLAB(const Eigen::MatrixBase< Derived > &A, const std::string &mat_file, const std::string &var_name, const std::string &mode)
Saves a complex Eigen dynamic matrix to a MATLAB .mat file,.
Definition: matlab.h:205
Object has zero size exception.
Definition: exception.h:134