Quantum++  v1.0.0-beta1
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;
184  double* pa_im = nullptr;
185 
186  // Populate the real part of the created array.
187  pa_re = reinterpret_cast<double*>(mxGetPr(pa));
188  std::memcpy(result_re.data(), pa_re,
189  sizeof(double) * mxGetNumberOfElements(pa));
190 
191  if (mxIsComplex(pa)) // populate the imaginary part if exists
192  {
193  pa_im = reinterpret_cast<double*>(mxGetPi(pa));
194  std::memcpy(result_im.data(), pa_im,
195  sizeof(double) * mxGetNumberOfElements(pa));
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 */,
219  const std::string& /* var_name */,
220  const std::string& /* mode */)
221 {
222  throw Exception("qpp::saveMATLABmatrix()",
224 }
225 
238 template<>
239 // Eigen::MatrixXd specialization
240 inline void saveMATLABmatrix(const Eigen::MatrixBase <dmat>& A,
241  const std::string& mat_file,
242  const std::string& var_name,
243  const std::string& mode)
244 {
245  const dmat& rA = A.derived();
246 
247  // EXCEPTION CHECKS
248 
249  // check zero-size
251  throw Exception("qpp::saveMATLABmatrix()", Exception::Type::ZERO_SIZE);
252 
253  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
254  if (!pmat)
255  throw std::runtime_error(
256  "qpp::saveMATLABmatrix(): Can not open/create MATLAB file "
257  + mat_file + "!");
258 
259  mxArray* pa = mxCreateDoubleMatrix(rA.rows(), rA.cols(), mxREAL);
260  if (!pa)
261  throw std::runtime_error(
262  "qpp::saveMATLABmatrix(): mxCreateDoubleMatrix failed!");
263  // END EXCEPTION CHECKS
264 
265  std::memcpy(mxGetPr(pa), rA.data(), sizeof(double) * rA.size());
266 
267  if (matPutVariable(pmat, var_name.c_str(), pa))
268  throw std::runtime_error(
269  "qpp::saveMATLABmatrix(): Can not write the variable "
270  + var_name + " to MATLAB file " + mat_file + "!");
271 
272  mxDestroyArray(pa);
273  matClose(pmat);
274 }
275 
288 template<>
289 // Eigen::MatrixXcd specialization
290 inline void saveMATLABmatrix(const Eigen::MatrixBase <cmat>& A,
291  const std::string& mat_file,
292  const std::string& var_name,
293  const std::string& mode)
294 {
295  const cmat& rA = A.derived();
296 
297  // EXCEPTION CHECKS
298 
299  // check zero-size
301  throw Exception("qpp::saveMATLABmatrix()", Exception::Type::ZERO_SIZE);
302 
303  // cast the input to a double (internal MATLAB format)
304  dmat tmp_re = rA.real();
305  dmat tmp_im = rA.imag();
306 
307  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
308  if (!pmat)
309  throw std::runtime_error(
310  "qpp::saveMATLABmatrix(): Can not open/create MATLAB file "
311  + mat_file + "!");
312 
313  mxArray* pa = mxCreateDoubleMatrix(
314  tmp_re.rows(), tmp_re.cols(), mxCOMPLEX);
315  if (!pa)
316  throw std::runtime_error(
317  "qpp::saveMATLABmatrix(): mxCreateDoubleMatrix failed!");
318  // END EXCEPTION CHECKS
319 
320  // real part and imaginary part pointers
321  double* pa_re = nullptr;
322  double* pa_im = nullptr;
323 
324  /* Populate the real part of the created array. */
325  pa_re = reinterpret_cast<double*>(mxGetPr(pa));
326  std::memcpy(pa_re, tmp_re.data(), sizeof(double) * tmp_re.size());
327 
328  /* Populate the imaginary part of the created array. */
329  pa_im = reinterpret_cast<double*>(mxGetPi(pa));
330  std::memcpy(pa_im, tmp_im.data(), sizeof(double) * tmp_im.size());
331 
332  if (matPutVariable(pmat, var_name.c_str(), pa))
333  throw std::runtime_error(
334  "qpp::saveMATLABmatrix(): Can not write the variable "
335  + var_name + " to MATLAB file " + mat_file + "!");
336 
337  mxDestroyArray(pa);
338  matClose(pmat);
339 }
340 
341 } /* namespace qpp */
342 #endif /* MATLAB_MATLAB_H_ */
bool check_nonzero_size(const T &x) noexcept
Definition: util.h:112
Eigen::MatrixXd dmat
Real (double precision) dynamic Eigen matrix.
Definition: types.h:66
void saveMATLABmatrix(const Eigen::MatrixBase< Derived > &, const std::string &, const std::string &, const std::string &)
Saves an Eigen dynamic matrix to a MATLAB .mat file, generic version.
Definition: matlab.h:217
Quantum++ main namespace.
Definition: codes.h:30
std::complex< double > cplx
Complex number in double precision.
Definition: types.h:46
Generates custom exceptions, used when validating function parameters.
Definition: exception.h:39
Derived loadMATLABmatrix(const std::string &, const std::string &)
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:61
std::size_t idx
Non-negative integer index.
Definition: types.h:36