Quantum++  v1.0-rc2
A modern C++11 quantum computing library
matlab.h
Go to the documentation of this file.
1 /*
2  * Quantum++
3  *
4  * Copyright (c) 2013 - 2017 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 {
59 template<typename Derived> // double
60 typename std::enable_if<std::is_same<typename Derived::Scalar, cplx>::value,
61  dyn_mat < cplx>>
62 
63 ::type
64 loadMATLAB(const std::string& mat_file, const std::string& var_name)
65 {
66  MATFile* pmat = matOpen(mat_file.c_str(), "r");
67 
68  // EXCEPTION CHECKS
69 
70  if (!pmat)
71  {
72  throw std::runtime_error(
73  "qpp::loadMATLAB(): Can not open MATLAB file "
74  + mat_file + "!");
75  }
76 
77  mxArray* pa = matGetVariable(pmat, var_name.c_str());
78  if (!pa)
79  throw std::runtime_error(
80  "qpp::loadMATLAB(): Can not load the variable "
81  + var_name + " from MATLAB file " + mat_file + "!");
82 
83  if (mxGetNumberOfDimensions(pa) != 2) // not a matrix
84  throw std::runtime_error(
85  "qpp::loadMATLAB(): Loaded variable " + var_name
86  + " is not 2-dimensional!");
87 
88  if (!mxIsDouble(pa))
89  throw std::runtime_error(
90  "qpp::loadMATLAB(): Loaded variable " + var_name
91  + " is not in double-precision format!");
92  // END EXCEPTION CHECKS
93 
94  idx rows = mxGetM(pa);
95  idx cols = mxGetN(pa);
96 
97  dyn_mat<double> result_re(rows, cols);
98  dyn_mat<double> result_im(rows, cols);
99 
100  // real part and imaginary part pointers
101  double* pa_re = nullptr;
102  double* pa_im = nullptr;
103 
104  // Populate the real part of the created array.
105  pa_re = mxGetPr(pa);
106  std::memcpy(result_re.data(), pa_re,
107  sizeof(double) * mxGetNumberOfElements(pa));
108 
109  if (mxIsComplex(pa)) // populate the imaginary part if exists
110  {
111  pa_im = mxGetPi(pa);
112  std::memcpy(result_im.data(), pa_im,
113  sizeof(double) * mxGetNumberOfElements(pa));
114  } else // set to zero the imaginary part
115  {
116  std::memset(result_im.data(), 0,
117  sizeof(double) * mxGetNumberOfElements(pa));
118  }
119 
120  mxDestroyArray(pa);
121  matClose(pmat);
122 
123  return (result_re.cast<cplx>()) + 1_i * (result_im.cast<cplx>());
124 }
125 
126 
148 template<typename Derived> // cplx
149 typename std::enable_if<!std::is_same<typename Derived::Scalar, cplx>::value,
151 
152 ::type
153 loadMATLAB(const std::string& mat_file, const std::string& var_name)
154 {
155  MATFile* pmat = matOpen(mat_file.c_str(), "r");
156 
157  // EXCEPTION CHECKS
158 
159  if (!pmat)
160  {
161  throw std::runtime_error(
162  "qpp::loadMATLAB(): Can not open MATLAB file "
163  + mat_file + "!");
164  }
165 
166  mxArray* pa = matGetVariable(pmat, var_name.c_str());
167  if (!pa)
168  throw std::runtime_error(
169  "qpp::loadMATLAB(): Can not load the variable "
170  + var_name + " from MATLAB file " + mat_file + "!");
171 
172  if (mxGetNumberOfDimensions(pa) != 2) // not a matrix
173  throw std::runtime_error(
174  "qpp::loadMATLAB(): Loaded variable " + var_name
175  + " is not 2-dimensional!");
176 
177  if (!mxIsDouble(pa))
178  throw std::runtime_error(
179  "qpp::loadMATLAB(): Loaded variable " + var_name
180  + " is not in double-precision format!");
181  // END EXCEPTION CHECKS
182 
183  idx rows = mxGetM(pa);
184  idx cols = mxGetN(pa);
185 
186  dyn_mat<double> result(rows, cols);
187 
188  std::memcpy(result.data(), mxGetPr(pa),
189  sizeof(double) * mxGetNumberOfElements(pa));
190 
191  mxDestroyArray(pa);
192  matClose(pmat);
193 
194  // cast back to the original type
195  return result.cast<typename Derived::Scalar>();
196 }
197 
210 template<typename Derived>
211 // double
212 typename
213 std::enable_if<std::is_same<typename Derived::Scalar, cplx>::value>::type
214 saveMATLAB(const Eigen::MatrixBase <Derived>& A,
215  const std::string& mat_file,
216  const std::string& var_name,
217  const std::string& mode)
218 {
219  const dyn_mat <cplx>& rA = A.derived();
220 
221  // EXCEPTION CHECKS
222 
223  // check zero-size
225  throw exception::ZeroSize("qpp::saveMATLAB()");
226 
227  // cast the input to a double (internal MATLAB format)
228  dyn_mat<double> tmp_re = rA.real();
229  dyn_mat<double> tmp_im = rA.imag();
230 
231  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
232  if (!pmat)
233  throw std::runtime_error(
234  "qpp::saveMATLAB(): Can not open/create MATLAB file "
235  + mat_file + "!");
236 
237  mxArray* pa = mxCreateDoubleMatrix(
238  tmp_re.rows(), tmp_re.cols(), mxCOMPLEX);
239  if (!pa)
240  throw std::runtime_error(
241  "qpp::saveMATLAB(): mxCreateDoubleMatrix failed!");
242  // END EXCEPTION CHECKS
243 
244  // real part and imaginary part pointers
245  double* pa_re = nullptr;
246  double* pa_im = nullptr;
247 
248  /* Populate the real part of the created array. */
249  pa_re = mxGetPr(pa);
250  std::memcpy(pa_re, tmp_re.data(), sizeof(double) * tmp_re.size());
251 
252  /* Populate the imaginary part of the created array. */
253  pa_im = mxGetPi(pa);
254  std::memcpy(pa_im, tmp_im.data(), sizeof(double) * tmp_im.size());
255 
256  if (matPutVariable(pmat, var_name.c_str(), pa))
257  throw std::runtime_error(
258  "qpp::saveMATLAB(): Can not write the variable "
259  + var_name + " to MATLAB file " + mat_file + "!");
260 
261  mxDestroyArray(pa);
262  matClose(pmat);
263 }
264 
277 template<typename Derived>
278 // cplx
279 typename
280 std::enable_if<!std::is_same<typename Derived::Scalar, cplx>::value>::type
281 saveMATLAB(const Eigen::MatrixBase <Derived>& A,
282  const std::string& mat_file,
283  const std::string& var_name,
284  const std::string& mode)
285 {
286  // cast to double, as MATLAB doesn't work with other types
287  const dyn_mat<double>& rA = A.template cast<double>();
288 
289  // EXCEPTION CHECKS
290 
291  // check zero-size
293  throw exception::ZeroSize("qpp::saveMATLAB()");
294 
295  MATFile* pmat = matOpen(mat_file.c_str(), mode.c_str());
296  if (!pmat)
297  throw std::runtime_error(
298  "qpp::saveMATLAB(): Can not open/create MATLAB file "
299  + mat_file + "!");
300 
301  mxArray* pa = mxCreateDoubleMatrix(rA.rows(), rA.cols(), mxREAL);
302  if (!pa)
303  throw std::runtime_error(
304  "qpp::saveMATLAB(): mxCreateDoubleMatrix failed!");
305  // END EXCEPTION CHECKS
306 
307  std::memcpy(mxGetPr(pa), rA.data(), sizeof(double) * rA.size());
308 
309  if (matPutVariable(pmat, var_name.c_str(), pa))
310  throw std::runtime_error(
311  "qpp::saveMATLAB(): Can not write the variable "
312  + var_name + " to MATLAB file " + mat_file + "!");
313 
314  mxDestroyArray(pa);
315  matClose(pmat);
316 }
317 
318 } /* namespace qpp */
319 #endif /* MATLAB_MATLAB_H_ */
bool check_nonzero_size(const T &x) noexcept
Definition: util.h:129
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > dyn_mat
Dynamic Eigen matrix over the field specified by Scalar.
Definition: types.h:77
Quantum++ main namespace.
Definition: codes.h:30
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:64
std::complex< double > cplx
Complex number in double precision.
Definition: types.h:45
std::size_t idx
Non-negative integer index.
Definition: types.h:35
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:214
Object has zero size exception.
Definition: exception.h:134