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

12 Ansichten (letzte 30 Tage)
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 Kommentar
Riccardo Scorretti
Riccardo Scorretti am 4 Mai 2021
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
};

Melden Sie sich an, um zu kommentieren.

Antworten (1)

Aghamarsh Varanasi
Aghamarsh Varanasi am 21 Apr. 2021
Bearbeitet: Aghamarsh Varanasi am 21 Apr. 2021
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

Kategorien

Mehr zu MATLAB Data API for C++ finden Sie in Help Center und File Exchange

Produkte


Version

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by