I'm trying to use Eigen AlignedBox. Specifically, I'm trying to cast a box of double into an int one, by using AlignedBox::cast
AlignedBox<double, 2> aabbox2d = AlignedBox<double, 2>(Vector2d(0.52342, 2.12315), Vector2d(3.87346, 4.72525));
aabbox2d.cast<AlignedBox<int, 2>>();
auto minx = aabbox2d.min().x();
Anyway, when the execution gets to min() I get an assert:
Assertion failed: (((SizeAtCompileTime == Dynamic && (MaxSizeAtCompileTime==Dynamic || size<=MaxSizeAtCompileTime)) || SizeAtCompileTime == size) && size>=0), function resize, file /Users/max/Developer/Stage/Workspace/AutoTools3D/dep/libigl/external/eigen/Eigen/src/Core/PlainObjectBase.h, line 312.
Note that this is different from casting a matrix scalar to another one. An object is implied.
Supposedly I'm not doing the cast correctly. Does someone know the right way?
Thank you
Consulting the documentation for AlignedBox::cast shows that the template argument to cast is defined as template<typename NewScalarType> and the return value is *this with scalar type casted to NewScalarType. Thus the cast function does not modify the existing instance of the box, but returns a new one. To make your example work you need to store the returned instance like follows:
AlignedBox<double, 2> aabbox2d = AlignedBox<double, 2>(Vector2d(0.52342, 2.12315), Vector2d(3.87346, 4.72525));
AlignedBox<int, 2> casted = aabbox2d.cast<int>();
const int minx = casted.min().x();
You can play with this here: https://godbolt.org/z/ozE4rzebb
As a side note: as the documentation states, when working with Eigen one should refrain from using auto (probably not a problem in this case though)
Related
I have following C++ code snippet
inline std::vector<std::unique_ptr<xir::Tensor>> cloneTensorBuffer(
const std::vector<const xir::Tensor*>& tensors)
{
auto ret = std::vector<std::unique_ptr<xir::Tensor>>{};
auto type = xir::DataType::XINT;
ret.reserve(tensors.size());
for (const auto& tensor : tensors) {
ret.push_back(std::unique_ptr<xir::Tensor>(xir::Tensor::create(
tensor->get_name(), tensor->get_shape(), xir::DataType{type, 8u})));
}
return ret;
}
I am not clear about the expression:
std::unique_ptr<xir::Tensor>(xir::Tensor::create(
tensor->get_name(), tensor->get_shape(), xir::DataType{type, 8u}))
Is the expression casting the value returned by xir::Tensor::create() to std::unique_ptr<xir::Tensor? I am confused since the C++ casting syntax is (type)expression
Can someone explain please.
regards,
-sunil puranik
This code takes a vector of raw pointers to Tensor objects, and returns a new vector of unique pointers to a new set of Tensor objects. Doesn't look like any explicit casting is taking place.
std::unique_ptr<xir::Tensor>( // create unique pointer to new Tensor object
xir::Tensor::create(
tensor->get_name(), // created with name and shape of the
tensor->get_shape(), // tensor pointed at in the original vector
xir::DataType{type, 8u} // and with unsigned 8-bit XINT datatype
)
)
Regarding casting - please don't consider e.g. (int)foo to be C++-style casting - that's legacy C-style casting. Amongst other things it's hard to find by searching a codebase!
C++ has:
static_cast
dynamic_cast
reinterpret_cast
const_cast
implicit conversion
There's more detail on this at cplusplus.com.
You may have to forgive me as I'm new to C++ and may have made some fundamental errors with the code I have worked up so far.
static tuple<read_result, uint8_t*> m_scan_record(bool skip, uint32_t& size, FILE* file)
{
read_result result;
tuple<read_result, uint32_t*> rd_rec_size_result = m_read_generic_t<uint32_t>(file);
result = (read_result)get<0>(rd_rec_size_result);
if (result != read_success )
{
return tuple<read_result, uint8_t*>(result, nullptr);
}
size = (uint32_t) get<1>(rd_rec_size_result);
if ( skip )
{
fseek(file, size, SEEK_CUR);
}
// ...
}
template<typename T>
static tuple<read_result, T*> m_read_generic_t(FILE* file)
{
T ret = 0;
read_result result = m_read_from_file_to_buffer(&ret, sizeof(T), file);
if (result == read_success)
{
return tuple<read_result, T*>(result, &ret);
}
return tuple<read_result, T*>(result, nullptr);
}
When I compile this code I am getting this error:
cast from ‘std::__tuple_element_t<1, std::tuple<read_result, unsigned int*> >’ {aka ‘unsigned int*’} to ‘uint32_t’ {aka ‘unsigned int’} loses precision [-fpermissive]
My intentions and what I am expected to do/happen:
In the declaration of m_scan_record, the size argument is declared with a & which is intended to allow me to pass the value by reference, analogous to using the REF c# keyword
I make a call to generic (template) function m_read_generic_t which is called with the specified type <unit32_t> and therefore (according to its definition) will return a type of tuple<read_result, uint32_t*>
Once I have the tuple returned by m_read_generic_t, I want to take the unit32_t value pointed to by the second value of the tuple, and put that value into the size variable mentioned at point 1, above, which presumably will then be accessible to the calling function one step further up the stack.
From the above points you can hopefully see that my intention (and I appreciate that I may be far away in reality!) is that at this line:
size = (uint32_t) get<1>(rd_rec_size_result);
all I am doing is simply grabbing a 'pointed to' value and putting it into a variable of a matching type, much like the oft-cited textbook example:
uint32_t v = 123;
uint32_t* ptr_to_v = &v;
uint32_t x = ptr_to_v; // x == 123
Clearly this is not what is really going on with my code, though, because if it were, I presume that the cast would be un-needed. But if I remove it, like this:
size = get<1>(rd_rec_size_result);
then I get a compile-time error:
a value of type "std::__tuple_element_t<1UL, std::tuple<read_result, uint32_t *>>" cannot be assigned to an entity of type "uint32_t"
I believe therefore that I am doing something badly wrong - but I can't work out what. Is this to do with the way I am taking the pointer out of the tuple; or is there something else going on when it comes to the getting a uint32_t value from a uint32_t* ?
This is all in a C++ environment on Ubuntu 20.04, FWIW
Many thanks in advance for any/all suggestions; please go easy on me!
tuple<read_result, uint32_t*> rd_rec_size_result = ...
The 2nd member of this tuple, as explicitly declared here, is a pointer to a uint32_t. That's what uint32_t * means, in C++.
size = (uint32_t) get<1>(rd_rec_size_result);
This retrieves the uint32_t * and attempts to convert it to a uint32_t. C++ does not work this way. Although this conversion can be forced your compiler has every right to believe that whatever this code is trying to do it must be wrong.
Perhaps I was wondering initially, your intention was to dereference the pointer. This is the reason for your compilation error, in any case. If your intention was to, truly, dereference this pointer, then this would've been a simple matter of changing this to
size = *get<1>(rd_rec_size_result);
However, that's not going to be the end of your troubles. Even after this compilation error is fixed, this way, the shown code will still be badly, badly broken.
This is because m_read_generic_t returns a pointer to a local object, which will get destroyed when the function returns, and attempting to dereference this pointer, here, will make demons fly out of your nose.
The real fix here is to change m_read_generic_t to not return a pointer as the 2nd value in the tuple in the first place, thus eliminating the compilation error in the first place.
I am trying to assign a logical operator function to a variable but am unable to get it to work. I am using:
function<bool(double,double)> opFunct = less<bool>();
double highorlow = pOut.high;
if(pCheck){
opFunct = greater<bool>();
highorlow = pOut.low;
}
if(opFunct(highorlow,pStay.middle){
//never gets done
}
The problem with this code is no matter what the highorlow,pStay.middle doubles are, it returns false.
What am I missing?
Thanks
Short version:
less<bool> compares bools. Use less<double> to compare doubles (also in greater<>).
Long version:
This is an interesting question. Specifically, how come the following line compiles?
function<bool(double, double)> opFunct = less<bool>();
After all std::less<bool>:: operator() looks like bool(bool, bool), why does it match bool(double, double)?
Well that's because the check that std::function's constructor performs is simply whether less<bool>() can be invoked as bool(double, double), and yes it can! double is implicitly-convertible to bool, 0.0 becomes false and any other value true.
That obviously won't produce the expected result because e.g. opFunct(1.0, 2.0) will invoke less(true, true) which will return false.
The fix is to change bool to double
function<bool(double, double)> opFunct = less<double>();
And also here
opFunct = greater<double>();
But wait, std::function overhead aside1, depending on how the rest of your code looks like, the fragment shown can potentially be simplified to just:
if (pCheck ? pStay.middle < pOut.low : pOut.high < pStay.middle) {
// . . .
}
Or maybe even
if (pStay.middle < pOut.low || pOut.high < pStay.middle) {
// both checks at once . . .
}
1std::function comes at a cost of some 48-96 bytes of memory and an extra indirection or two. Compare the generated code for version with std::function vs. version without std::function.
I have a small problem. I am having a function using a function with 2 Mat pointer objects given, but im having trouble writing to outImg channels to update the img.
void convolve5(Mat *inputImg, Mat *outImg, int *kernel5) {
int channelvaluepixel = inputImg->at<Vect3b>(x,y)[channel];
// loads of changes happening here
outImg->at<Vect3b>(x,y)[0] = channelvaluepixel;
}
Since outImg is a pointer i cannot point to its adress to change it, so i tried this to change the value within the pointer:
*outImg->at<Vect3b>(x,y)[0] = channelvaluepixel;
But this would not work either since the compiler gives me an:
Error: invalid type argument of unary '*' (have 'unsigned char')
Can somebody help?
You are dereferencing whole expression outImg->at<Vect3b>(x,y)[0] instead of just (*outImg).at<Vect3b>(x,y)[0] = channelvaluepixel;
In Rascal, say I have the code:
value x = 2;
data Exp = con(int n);
Is there a way to call con(x), while x is a value (but actually an integer), without knowing on beforehand what the type of con's first argument is supposed to be (thus without explicitly casting it to an int)?
Why is it possible to call a function, say int something(int n) = n, with an integer defined as a value (e.g. value y = 2) passed into its first argument, while it gives me an error when I try to do the same with user-defined ADTs?
When you call a function in Rascal it actually is doing a pattern match on the arguments. So, if you define int something(int n) = n;, and then call something(x), it matches x with int n, sees that x is actually an int (so it can bind the value to n), and calls the function.
If you were to define value x = 2.5 instead and then call something(x) you would get an error since it cannot bind the value 2.5 to int n. You could overload something with a second definition that takes a real instead, like int something(real r) = toInt(r);, and it would then work. Two items to note here, though: something needs to return the same type in both cases, and you need to import util::Math to get access to toInt.
When you are using a constructor, like con(x), it doesn't do a pattern match for you automatically. The type that you give it has to match the type it expects. If you know that x will always be an int, it would be best to just declare it as such. Another option would be to create a function like Exp makeCon(int n) = con(n); which you could then use as you would like, i.e., Exp myExp = makeCon(x);. It would be best in this case to include a default version of the function, just in case you give it something unexpected, like default Exp makeCon(value x) { throw "Unexpected value <x>"; }, this way if you ever try to create a con with something that isn't an int you will get an error that you can handle, with the ability to create your own error message, add additional error handling versus just showing a message, see the value causing the problem, etc, versus just having the interpreter give an error (which may not give you all the info you want).