Mex C++ unable to realize simple arithmetic operations with TypedArray std::complex<double>

40 次查看(过去 30 天)
I am trying to mex a C++ function to compute some elements in a matrix with complex value. I have no issue when I use double instead of std::complex<double>.
The complex version is the following:
#include "mex.hpp"
#include "mexAdapter.hpp"
#include <complex>
using namespace matlab::data;
using matlab::mex::ArgumentList;
class MexFunction : public matlab::mex::Function {
ArrayFactory factory;
public:
void operator()(ArgumentList outputs, ArgumentList inputs) {
const std::complex<double> I(0.0, 1.0); //define imaginary constant
const TypedArray<double> R = std::move(inputs[0]); // move inputs (1xN) into a TypedArray
TypedArray<std::complex<double>> U=factory.createArray<std::complex<double>>({1,R.getDimensions()[1]}); // create a complex array same size as R
for(size_t uind=0; uind<U.getDimensions()[1];uind++){U[0][uind] =I+U[0][uind];} // does not work
//for(size_t uind=0; uind<U.getDimensions()[1];uind++){U[0][uind] = I+I;} // Works
outputs[0] = std::move(U);
}
};
Compilation fails, the error message is much longer, I only paste here the beginnign for visibility:
mex test_complex.cpp
Building with 'MinGW64 Compiler (C++)'.
Error using mex
C:\Data\mex\test_complex.cpp: In member function 'virtual void MexFunction::operator()(matlab::mex::ArgumentList, matlab::mex::ArgumentList)':
C:\Data\mex\test_complex.cpp:17:75: error: no match for 'operator+' (operand types are 'const std::complex<double>' and
'matlab::data::ArrayElementTypedRef<std::complex<double>, false>')
for(size_t uind=0; uind<U.getDimensions()[1];uind++){U[0][uind] =I+U[0][uind];} // does not work
In file included from C:\Program Files\MATLAB\R2020b/extern/include/MatlabDataArray/matlab_data_array_defs.hpp:6:0,
from C:\Program Files\MATLAB\R2020b/extern/include/MatlabDataArray.hpp:7,
from C:\Program Files\MATLAB\R2020b/extern/include/mexAdapter.hpp:10,
from C:\Data\mex\test_complex.cpp:3:
C:/ProgramData/MATLAB/SupportPackages/R2020b/3P.instrset/mingw_w64.instrset/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/complex:445:5: note: candidate: template<class _Tp>
std::complex<_Tp> std::operator+(const std::complex<_Tp>&)
operator+(const complex<_Tp>& __x)
^~~~~~~~
C:/ProgramData/MATLAB/SupportPackages/R2020b/3P.instrset/mingw_w64.instrset/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/complex:445:5: note: template argument deduction/substitution
failed:
C:\Data\mex\test_complex.cpp:17:85: note: candidate expects 1 argument, 2 provided
for(size_t uind=0; uind<U.getDimensions()[1];uind++){U[0][uind] =I+U[0][uind];} // does not work
Using += , * , *= operators return similar errors.
What is strange is the the same function with double values does nto return any issue and works fine:
#include "mex.hpp"
#include "mexAdapter.hpp"
using namespace matlab::data;
using matlab::mex::ArgumentList;
class MexFunction : public matlab::mex::Function {
ArrayFactory factory;
public:
void operator()(ArgumentList outputs, ArgumentList inputs) {
const TypedArray<double> R = std::move(inputs[0]);
TypedArray<double> U=factory.createArray<double>({1,R.getDimensions()[1]});
for(size_t uind=0; uind<U.getDimensions()[1];uind++){U[0][uind] = U[0][uind]+1;}
outputs[0] = std::move(U);
}
};
>> mex test_real.cpp
Building with 'MinGW64 Compiler (C++)'.
MEX completed successfully.
>> test_real(1:10)
ans =
1 1 1 1 1 1 1 1 1 1
  1 个评论
Riccardo Scorretti
Thank you very much. In fact I have a similar problem, which I don't manage to fix by using casting. I'm trying to adapt the example arrayProduct.cpp so that it can works with complex values.
I tried the modification hereafter, but I got the following error message at run-time (the program compiles with no warning):
Error using arrayProductComplex
Can't convert the Array to this TypedArray
I guess it is a similar issue. Any hint to fix it? Thank you in advance
//
// arrayProduct.cpp - example in MATLAB External Interfaces
//
// (includes, comments, etc.)
class MexFunction : public matlab::mex::Function {
public:
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
checkArguments(outputs, inputs);
std::complex<double> multiplier = inputs[0][0]; // So far, so good
// Here I get a run-time error
matlab::data::TypedArray<std::complex<double>> in = std::move(inputs[1]);
arrayProduct(in, multiplier);
outputs[0] = std::move(in);
}
void arrayProduct(matlab::data::TypedArray<std::complex<double>>& inMatrix, std::complex<double> multiplier) {
for (auto& elem : inMatrix) {
elem *= multiplier;
}
}
// Here is the (modifid) method checkArguments
};

请先登录,再进行评论。

回答(1 个)

Aghamarsh Varanasi
Aghamarsh Varanasi 2021-4-21
编辑:Aghamarsh Varanasi 2021-4-21
Hi Matthieu Dupre,
The binary operator '+' in 'std::complex<T>' is only defined for adding types std::complex<T>' or 'scalar'. While using the 'operator[ ]' for 'matlab::data::TypedArray<T>', the return type is a 'ArrayElementTypedRef'. As the binary '+' operator is not defined for 'ArrayElementTypedRef' in 'std::complex<T>' you are recieving this error.
To overcome this issue,
  1. You can initialize the value of 'U[0][uind]' to a variable of type 'std::complex<double>'. Hence, your code would be,
#include "mex.hpp"
#include "mexAdapter.hpp"
#include <complex>
using namespace matlab::data;
using matlab::mex::ArgumentList;
class MexFunction : public matlab::mex::Function {
ArrayFactory factory;
public:
void operator()(ArgumentList outputs, ArgumentList inputs) {
const std::complex<double> I(0.0, 1.0); //define imaginary constant
const TypedArray<double> R = std::move(inputs[0]); // move inputs (1xN) into a TypedArray
TypedArray<std::complex<double>> U=factory.createArray<std::complex<double>>({1,R.getDimensions()[1]}); // create a complex array same size as R
// creating a temporary variable
std::complex<double> tmp;
for(size_t uind=0; uind<U.getDimensions()[1];uind++){
// initializing U[0][uind] to tmp
tmp = U[0][uind];
U[0][uind] = I + tmp;} // this does work !!
//for(size_t uind=0; uind<U.getDimensions()[1];uind++){U[0][uind] = I+I;} // Works
outputs[0] = std::move(U);
}
2. Or, you could type cast 'U[0][uind]' to 'std::complex<double'>. For Example,
#include "mex.hpp"
#include "mexAdapter.hpp"
#include <complex>
using namespace matlab::data;
using matlab::mex::ArgumentList;
class MexFunction : public matlab::mex::Function {
ArrayFactory factory;
public:
void operator()(ArgumentList outputs, ArgumentList inputs) {
const std::complex<double> I(0.0, 1.0); //define imaginary constant
const TypedArray<double> R = std::move(inputs[0]); // move inputs (1xN) into a TypedArray
TypedArray<std::complex<double>> U=factory.createArray<std::complex<double>>({1,R.getDimensions()[1]}); // create a complex array same size as R
for(size_t uind=0; uind<U.getDimensions()[1];uind++){
U[0][uind] = I + (std::complex<double>) U[0][uind];} // this does work !!
//for(size_t uind=0; uind<U.getDimensions()[1];uind++){U[0][uind] = I+I;} // Works
outputs[0] = std::move(U);
}
Hope this helps

类别

Help CenterFile Exchange 中查找有关 Write C++ Functions Callable from MATLAB (MEX Files) 的更多信息

产品


版本

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by