Quantum++  v0.8.6
C++11 quantum computing library
matlab.h
Go to the documentation of this file.
1 /*
2  * Quantum++
3  *
4  * Copyright (c) 2013 - 2016 Vlad Gheorghiu (vgheorgh@gmail.com)
5  *
6  * This file is part of Quantum++.
7  *
8  * Quantum++ is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * Quantum++ is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Quantum++. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
27 #ifndef MATLAB_MATLAB_H_
28 #define MATLAB_MATLAB_H_
29 
30 // MATLAB I/O interfacing
31 // add the path to $MATLAB_INSTALLATION_FOLDER/extern/include in include path
32 
33 #include "mat.h" // path to this file is defined in the Makefile
34 #include "mex.h" // path to this file is defined in the Makefile
35 
36 namespace qpp
37 {
38 
47 template<typename Derived>
48 Derived loadMATLABmatrix(const std::string& mat_file,
49  const std::string& var_name)
50 {
51  throw Exception("qpp::loadMATLABmatrix()",
53 }
54 
78 template<>
79 inline dmat loadMATLABmatrix(const std::string& mat_file,
80  const std::string& var_name)
81 {
82  MATFile* pmat = matOpen(mat_file.c_str(), "r");
83 
84  // EXCEPTION CHECKS
85 
86  if (!pmat)
87  {
88  throw std::runtime_error(
89  "qpp::loadMATLABmatrix(): Can not open MATLAB file "
90  + mat_file + "!");
91  }
92 
93  mxArray* pa = matGetVariable(pmat, var_name.c_str());
94  if (!pa)
95  throw std::runtime_error(
96  "qpp::loadMATLABmatrix(): Can not load the variable "
97  + var_name + " from MATLAB file " + mat_file + "!");
98 
99  if (mxGetNumberOfDimensions(pa) != 2) // not a matrix
100  throw std::runtime_error(
101  "qpp::loadMATLABmatrix(): Loaded variable " + var_name
102  + " is not 2-dimensional!");
103 
104  if (!mxIsDouble(pa))
105  throw std::runtime_error(
106  "qpp::loadMATLABmatrix(): Loaded variable " + var_name
107  + " is not in double-precision format!");
108  // END EXCEPTION CHECKS
109 
110  idx rows = mxGetM(pa);
111  idx cols = mxGetN(pa);
112 
113  dmat result(rows, cols);
114 
115  std::memcpy(result.data(), mxGetPr(pa),
116  sizeof(double) * mxGetNumberOfElements(pa));
117 
118  mxDestroyArray(pa);
119  matClose(pmat);
120 
121  return result;
122 }
123 
144 template<>
145 inline cmat loadMATLABmatrix(const std::string& mat_file,
146  const std::string& var_name)
147 {
148  MATFile* pmat = matOpen(mat_file.c_str(), "r");
149 
150  // EXCEPTION CHECKS
151 
152  if (!pmat)
153  {
154  throw std::runtime_error(
155  "qpp::loadMATLABmatrix(): Can not open MATLAB file "
156  + mat_file + "!");
157  }
158 
159  mxArray* pa = matGetVariable(pmat, var_name.c_str());
160  if (!pa)
161  throw std::runtime_error(
162  "qpp::loadMATLABmatrix(): Can not load the variable "
163  + var_name + " from MATLAB file " + mat_file + "!");
164 
165  if (mxGetNumberOfDimensions(pa) != 2) // not a matrix
166  throw std::runtime_error(
167  "qpp::loadMATLABmatrix(): Loaded variable " + var_name
168  + " is not 2-dimensional!");
169 
170  if (!mxIsDouble(pa))
171  throw std::runtime_error(
172  "qpp::loadMATLABmatrix(): Loaded variable " + var_name
173  + " is not in double-precision format!");
174  // END EXCEPTION CHECKS
175 
176  idx rows = mxGetM(pa);
177  idx cols = mxGetN(pa);
178 
179  dmat result_re(rows, cols);
180  dmat result_im(rows, cols);
181 
182  // real part and imaginary part pointers
183  double* pa_re = nullptr, * pa_im = nullptr;
184 
185  // Populate the real part of the created array.
186  pa_re = static_cast<double*>(mxGetPr(pa));
187  std::memcpy(result_re.data(), pa_re,
188  sizeof(double) * mxGetNumberOfElements(pa));
189 
190  if (mxIsComplex(pa)) // populate the imaginary part if exists
191  {
192  pa_im = static_cast<double*>(mxGetPi(pa));
193  std::memcpy(result_im.data(), pa_im,
194  sizeof(double) * mxGetNumberOfElements(pa));
195  }
196  else // set to zero the imaginary part
197  {
198  std::memset(result_im.data(), 0,
199  sizeof(double) * mxGetNumberOfElements(pa));
200  }
201 
202  mxDestroyArray(pa);
203  matClose(pmat);
204 
205  return (result_re.cast<cplx>()) + 1_i * (result_im.cast<cplx>());
206 }
207 
216 template<typename Derived>
217 void saveMATLABmatrix(const Eigen::MatrixBase <Derived>& A,
218  const std::string& mat_file, const std::string& var_name,
219  const std::string& mode)
220 {
221  throw Exception("qpp::saveMATLABmatrix()",
223 }
224 
237 template<>
238 // Eigen::MatrixXd specialization
239 inline void saveMATLABmatrix(const Eigen::MatrixBase <dmat>& A,
240  const std::string& mat_file,
241  const std::string& var_name,
242  const std::string& mode)
243 {
244  const dmat& rA = A;
245 
246  // EXCEPTION CHECKS
247 
248  // check zero-size
250  throw Exception("qpp::saveMATLABmatrix()", Exception::Type::ZERO_SIZE);
251 
252  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
253  if (!pmat)
254  throw std::runtime_error(
255  "qpp::saveMATLABmatrix(): Can not open/create MATLAB file "
256  + mat_file + "!");
257 
258  mxArray* pa = mxCreateDoubleMatrix(rA.rows(), rA.cols(), mxREAL);
259  if (!pa)
260  throw std::runtime_error(
261  "qpp::saveMATLABmatrix(): mxCreateDoubleMatrix failed!");
262  // END EXCEPTION CHECKS
263 
264  std::memcpy(mxGetPr(pa), rA.data(), sizeof(double) * rA.size());
265 
266  if (matPutVariable(pmat, var_name.c_str(), pa))
267  throw std::runtime_error(
268  "qpp::saveMATLABmatrix(): Can not write the variable "
269  + var_name + " to MATLAB file " + mat_file + "!");
270 
271  mxDestroyArray(pa);
272  matClose(pmat);
273 }
274 
287 template<>
288 // Eigen::MatrixXcd specialization
289 inline void saveMATLABmatrix(const Eigen::MatrixBase <cmat>& A,
290  const std::string& mat_file,
291  const std::string& var_name,
292  const std::string& mode)
293 {
294  const cmat& rA = A;
295 
296  // EXCEPTION CHECKS
297 
298  // check zero-size
300  throw Exception("qpp::saveMATLABmatrix()", Exception::Type::ZERO_SIZE);
301 
302  // cast the input to a double (internal MATLAB format)
303  dmat tmp_re = rA.real();
304  dmat tmp_im = rA.imag();
305 
306  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
307  if (!pmat)
308  throw std::runtime_error(
309  "qpp::saveMATLABmatrix(): Can not open/create MATLAB file "
310  + mat_file + "!");
311 
312  mxArray* pa = mxCreateDoubleMatrix(
313  tmp_re.rows(), tmp_re.cols(), mxCOMPLEX);
314  if (!pa)
315  throw std::runtime_error(
316  "qpp::saveMATLABmatrix(): mxCreateDoubleMatrix failed!");
317  // END EXCEPTION CHECKS
318 
319  double* pa_re, * pa_im;
320 
321  /* Populate the real part of the created array. */
322  pa_re = static_cast<double*>(mxGetPr(pa));
323  std::memcpy(pa_re, tmp_re.data(), sizeof(double) * tmp_re.size());
324 
325  /* Populate the imaginary part of the created array. */
326  pa_im = static_cast<double*>(mxGetPi(pa));
327  std::memcpy(pa_im, tmp_im.data(), sizeof(double) * tmp_im.size());
328 
329  if (matPutVariable(pmat, var_name.c_str(), pa))
330  throw std::runtime_error(
331  "qpp::saveMATLABmatrix(): Can not write the variable "
332  + var_name + " to MATLAB file " + mat_file + "!");
333 
334  mxDestroyArray(pa);
335  matClose(pmat);
336 }
337 
338 } /* namespace qpp */
339 #endif /* MATLAB_MATLAB_H_ */
Eigen::MatrixXd dmat
Real (double precision) dynamic Eigen matrix.
Definition: types.h:71
Quantum++ main namespace.
Definition: codes.h:30
std::complex< double > cplx
Complex number in double precision.
Definition: types.h:51
Generates custom exceptions, used when validating function parameters.
Definition: exception.h:39
bool _check_nonzero_size(const T &x) noexcept
Definition: util.h:113
Derived loadMATLABmatrix(const std::string &mat_file, const std::string &var_name)
Loads an Eigen dynamic matrix from a MATLAB .mat file, generic version.
Definition: matlab.h:48
Eigen::MatrixXcd cmat
Complex (double precision) dynamic Eigen matrix.
Definition: types.h:66
void saveMATLABmatrix(const Eigen::MatrixBase< Derived > &A, const std::string &mat_file, const std::string &var_name, const std::string &mode)
Saves an Eigen dynamic matrix to a MATLAB .mat file, generic version.
Definition: matlab.h:217
std::size_t idx
Non-negative integer index.
Definition: types.h:36