- marked as major
Arithmetic conversion leads to unexpected results for linspace/logspace
Hi,
I came across an unexpected result with the freshly introduced generator expressions. Consider the following piece of code:
#include <blaze/math/DynamicVector.h>
#include <iostream>
int main(void) {
size_t N = 10;
int start = -10;
int end = -1;
auto x = blaze::linspace(N, start, end);
blaze::DynamicVector<int> y = x;
std::cout << x << std::endl;
std::cout << y << std::endl;
return 0;
}
Compiling (tested with gcc 9.2.0 and clang 9.0.1) and executing yields:
$ ./a.out
( 18446744073709551606 )
( 18446744073709551607 )
( 18446744073709551608 )
( 18446744073709551609 )
( 18446744073709551610 )
( 18446744073709551611 )
( 18446744073709551612 )
( 18446744073709551613 )
( 18446744073709551614 )
( 18446744073709551615 )
( -10 )
( -9 )
( -8 )
( -7 )
( -6 )
( -5 )
( -4 )
( -3 )
( -2 )
( -1 )
The result indicates that although I am explicitly using a signed integer type the element type of the returned expression is in fact unsigned and therefore suffers from mod 2 arithmetic. Interestingly, constructing a new vector (y in the example above) recovers the result I was expecting in the first place.
I digged a little deeper into this issue and found that line 660 in \math\expressions\DVecGenExpr.h
causes the issue:
...
return generate<TF>( size, [ start=std::move(start), delta=std::move(end) ]( size_t index ) {
return evaluate( start + index*delta );
// ^
// |
// conversion to unsigned int according to "Usual arithmetic conversions" point 4 on
// https://en.cppreference.com/w/c/language/conversion
} );
...
The problem also persist for logspace
of course. A quick fix that made it work for my purposes was to introduce a index type IT as
using IT = If_t<IsInteger_v<BT> && std::is_signed_v<BT>, std::make_signed_t<size_t>, size_t>;
and then let the lambda passed to generate
take IT
instead of size_t
. That said I only considered ints
, and have not thought about any possible edge cases.
Thanks,
Tim
Comments (7)
-
reporter -
reporter - edited description
-
reporter -
Hi Tim!
Thanks a lot for pointing out this defect. You are correct, there are some edge cases that are not handled properly yet. I apologize for the inconveniences and will try to fix the issue as quickly as possible. Thanks again,
Best regards,
Klaus!
-
-
assigned issue to
-
assigned issue to
-
- changed status to open
-
- changed status to resolved
Commit ee64f71 fixes the
linspace()
andlogspace()
functions for dense vectors. The fix is immediately available via cloning the Blaze repository and will be officially released in Blaze 3.8. - Log in to comment