Narrowing conversion with template parameter (MSVC14) - c++11

Upon upgrading to MSVC 2015 (from MSVC 2013), I started getting warnings for the following code:
template< unsigned int i0, unsigned int i1, unsigned int i2, unsigned int i3 >
static __m128 Constant( )
{
static __m128i v = {
((i0&0x000000FF) >> 0 ), ((i0&0x0000FF00) >> 8), ((i0&0x00FF0000) >> 16), ((i0&0xFF000000) >> 24),
((i1&0x000000FF) >> 0 ), ((i1&0x0000FF00) >> 8), ((i1&0x00FF0000) >> 16), ((i1&0xFF000000) >> 24),
((i2&0x000000FF) >> 0 ), ((i2&0x0000FF00) >> 8), ((i2&0x00FF0000) >> 16), ((i2&0xFF000000) >> 24),
((i3&0x000000FF) >> 0 ), ((i3&0x0000FF00) >> 8), ((i3&0x00FF0000) >> 16), ((i3&0xFF000000) >> 24) };
return *(__m128*)&v;
}
Produces the following (with Constant<0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF>()):
note: see reference to function template instantiation '__m128 Constant<2147483647,2147483647,2147483647,2147483647>(void)' being compiled
warning C4838: conversion from 'unsigned int' to 'char' requires a narrowing conversion
The __m128i union is defined inside emmintrin.h, as a union of arrays with several different types, which represent an MMX register. To list initialize the structure, you must use the first type declared in the union, in this case, __int8. According to MSVC 2013 documentation (https://msdn.microsoft.com/en-us/library/29dh1w7z.aspx), __int8 maps to char, I would assume the same for MSVC 2015. So, it seems like the warning is valid, because even though the template parameters are non-types, not all of the fields would fit into char type after conversion.
My question is why does MSVC 2013 not give a warning for this (as it seems like a core c++11 issue)? Also, is there a 'nice' way to resolve the warning?

Factor out the shift-mask-cast:
template<unsigned n, unsigned value>
/*constexpr*/ int8_t get_byte() {
return static_cast<int8_t>(0xFF & (value >> (n*8)));
}
Then use it:
template<unsigned i0, unsigned i1, unsigned i2, unsigned i3>
static __m128 Constant( )
{
static __m128i v = {
get_byte<0,i0>(), get_byte<1,i0>(), get_byte<2,i0>(), get_byte<3,i0>(),
get_byte<0,i1>(), get_byte<1,i1>(), get_byte<2,i1>(), get_byte<3,i1>(),
get_byte<0,i2>(), get_byte<1,i2>(), get_byte<2,i2>(), get_byte<3,i2>(),
get_byte<0,i3>(), get_byte<1,i3>(), get_byte<2,i3>(), get_byte<3,i3>(),
};
return *(__m128*)&v;
}
note that get_byte returns a signed 8 bit integer.
Notice how the symmetry of the above is really obvious.

#Chuck Walbourn - "Note that C4838 is new for VS 2015 which is why it doesn't come up in VS 2013."

Related

Mixing Scalar Types in Eigen

#include <iostream>
#include <Eigen/Core>
namespace Eigen {
// float op double -> double
template <typename BinaryOp>
struct ScalarBinaryOpTraits<float, double, BinaryOp> {
enum { Defined = 1 };
typedef double ReturnType;
};
// double op float -> double
template <typename BinaryOp>
struct ScalarBinaryOpTraits<double, float, BinaryOp> {
enum { Defined = 1 };
typedef double ReturnType;
};
}
int main() {
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> m1(2, 2);
m1 << 1, 2, 3, 4;
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> m2(2, 2);
m2 << 1, 2, 3, 4;
std::cerr << m1 * m2 <<std::endl; // <- boom!!
}
I'd like to know why the above code does not compile. Here is the full error messages. Please note that if I define m1 and m2 to have fixed sizes, it works fine.
I'm using Eigen3.3.1. It's tested on a Mac running OSX-10.12 with Apple's clang-800.0.42.1.
This is because the general matrix-matrix product is highly optimized with aggressive manual vectorization, pipelining, multi-level caching, etc. This part does not support mixing float and double. You can bypass this heavily optimized implementation with m1.lazyProduct(m2) that corresponds to the implementations used fro small fixed-size matrices, but there is only disadvantages of doing so: the ALUs does not support mixing float and double, so float values have to be promoted to double anyway and you will loose vectorization. Better cast the float to double explicitly:
m1.cast<double>() * m2

How to find element in matrix using Opencv

I am novice in OpenCV. I want to use equality operator between a vector element and matrix to cross check where both values are equal or not. How do that?
Thanks in advance
Im not sure if I understand your question correctly, but if you just want to compare one element of the vector to one element of the matrix this could be done in the following way:
cv::Vec3b vec(1, 2, 3);
cv::Mat mat(2, 2, CV_8UC1);
if (vec[0] == mat.at<uchar>(2, 1)) {
...
}
This compares the first element of a uchar vector to the second-row, first-column element of a uchar matrix.
If you want to iterate over the matrix, do it the following way:
cv::Mat mat(2, 2, CV_8UC1);
uchar* ptr;
for (int row = 0; row < mat.rows; ++row) {
ptr = mat.ptr<uchar>(row);
for (int col = 0; cols < mat.cols; ++col) {
if(ptr[col] == ...)
}
}
EDIT: equivalent for float, just exchange uchar for float:
cv::Vec3f vec(1, 2, 3);
cv::Mat mat(2, 2, CV_32FC1);
if (vec[0] == mat.at<float>(2, 1)) {
...
}
And:
cv::Mat mat(2, 2, CV_32FC1);
float* ptr;
for (int row = 0; row < mat.rows; ++row) {
ptr = mat.ptr<float>(row);
for (int col = 0; cols < mat.cols; ++col) {
if(ptr[col] == ...)
}
}
If you have multiple channels ptr[col] returns not one value but an OpenCV vector of the matrix' data type and as many dimensions as you've got channels. You can also directly add another [] operator with the index of the channel you want to access:
if(ptr[col][channel] == ...)
How to find out the data type of your cv::Mat?
From the type and depth specifier of your matrix you can see what data type they store:
CV_8U - 8-bit unsigned integers ( 0..255 )
CV_8S - 8-bit signed integers ( -128..127 )
CV_16U - 16-bit unsigned integers ( 0..65535 )
CV_16S - 16-bit signed integers ( -32768..32767 )
CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )
These are the depth specifiers for matrices. You can find out the depth of your matrix by calling cv::Mat::depth(). They specify which data type one element has. The type specifiers you use when creating a matrix also contain the information how many channels the matrix shall have, just add Cx to the depth specifier, x being the amount of channels , e.g. CV_8UC3 would be a matrix with three channels and 8bit unsigned chars as data type (so a pretty normal 8bit image). This information can be obtained from an existing matrix by calling cv::Mat::type(). The amount of channels is returned by cv::Mat::channels().
For OpenCV Vectors those type specifiers are similar:
typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;

Manually Converting rgba8 to rgba5551

I need to convert rgba8 to rgba5551 manually. I found some helpful code from another post and want to modify it to convert from rgba8 to rgba5551. I don't really have experience with bitewise stuff and haven't had any luck messing with the code myself.
void* rgba8888_to_rgba4444( void* src, int src_bytes)
{
// compute the actual number of pixel elements in the buffer.
int num_pixels = src_bytes / 4;
unsigned long* psrc = (unsigned long*)src;
unsigned short* pdst = (unsigned short*)src;
// convert every pixel
for(int i = 0; i < num_pixels; i++){
// read a source pixel
unsigned px = psrc[i];
// unpack the source data as 8 bit values
unsigned r = (px << 8) & 0xf000;
unsigned g = (px >> 4) & 0x0f00;
unsigned b = (px >> 16) & 0x00f0;
unsigned a = (px >> 28) & 0x000f;
// and store
pdst[i] = r | g | b | a;
}
return pdst;
}
The value of RGBA5551 is that it has color info condensed into 16 bits - or two bytes, with only one bit for the alpha channel (on or off). RGBA8888, on the other hand, uses a byte for each channel. (If you don't need an alpha channel, I hear RGB565 is better - as humans are more sensitive to green). Now, with 5 bits, you get the numbers 0 through 31, so r, g, and b each need to be converted to some number between 0 and 31, and since they are originally a byte each (0-255), we multiply each by 31/255. Here is a function that takes RGBA bytes as input and outputs RGBA5551 as a short:
short int RGBA8888_to_RGBA5551(unsigned char r, unsigned char g, unsigned char b, unsigned char a){
unsigned char r5 = r*31/255; // All arithmetic is integer arithmetic, and so floating points are truncated. If you want to round to the nearest integer, adjust this code accordingly.
unsigned char g5 = g*31/255;
unsigned char b5 = b*31/255;
unsigned char a1 = (a > 0) ? 1 : 0; // 1 if a is positive, 0 else. You must decide what is sensible.
// Now that we have our 5 bit r, g, and b and our 1 bit a, we need to shift them into place before combining.
short int rShift = (short int)r5 << 11; // (short int)r5 looks like 00000000000vwxyz - 11 zeroes. I'm not sure if you need (short int), but I've wasted time tracking down bugs where I didn't typecast properly before shifting.
short int gShift = (short int)g5 << 6;
short int bShift = (short int)b5 << 1;
// Combine and return
return rShift | gShift | bShift | a1;
}
You can, of course condense this code.

Porting C++ project from VS 6.0 to VS 2010 brought to slower code

I ported one project from Visual C++ 6.0 to VS 2010 and found that a critical part of the code (scripting engine) now runs in about three times slower than in was before.
After some research I managed to extract code fragment which seems to cause the slowdown. I minimized it as much as possible, so it ill be easier to reproduce the problem.
The problem is reproduced when assigning a complex class (Variant) which contains another class (String), and the union of several other fields of simple types.
Playing with the example I discovered more "magic":
1. If I comment one of unused (!) class members, the speed increases, and the code finally runs faster than those complied with VS 6.2
2. The same is true if I remove the "union" wrapper"
3. The same is true event if change the value of the filed from 1 to 0
I have no idea what the hell is going on.
I have checked all code generation and optimization switches, but without any success.
The code sample is below:
On my Intel 2.53 GHz CPU this test, compiled under VS 6.2 runs 1.0 second.
Compiled under VS 2010 - 40 seconds
Compiled under VS 2010 with "magic" lines commented - 0.3 seconds.
The problem is reproduces with any optimization switch, but the "Whole program optimization" (/GL) should be disabled. Otherwise this too smart optimizer will know that out test actually does nothing, and the test will run 0 seconds.
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class String
{
public:
char *ptr;
int size;
String() : ptr(NULL), size( 0 ) {};
~String() {if ( ptr != NULL ) free( ptr );};
String& operator=( const String& str2 );
};
String& String::operator=( const String& string2 )
{
if ( string2.ptr != NULL )
{
// This part is never called in our test:
ptr = (char *)realloc( ptr, string2.size + 1 );
size = string2.size;
memcpy( ptr, string2.ptr, size + 1 );
}
else if ( ptr != NULL )
{
// This part is never called in our test:
free( ptr );
ptr = NULL;
size = 0;
}
return *this;
}
struct Date
{
unsigned short year;
unsigned char month;
unsigned char day;
unsigned char hour;
unsigned char minute;
unsigned char second;
unsigned char dayOfWeek;
};
class Variant
{
public:
int dataType;
String valStr; // If we comment this string, the speed is OK!
// if we drop the 'union' wrapper, the speed is OK!
union
{
__int64 valInteger;
// if we comment any of these fields, unused in out test, the speed is OK!
double valReal;
bool valBool;
Date valDate;
void *valObject;
};
Variant() : dataType( 0 ) {};
};
void TestSpeed()
{
__int64 index;
Variant tempVal, tempVal2;
tempVal.dataType = 3;
tempVal.valInteger = 1; // If we comment this string, the speed is OK!
for ( index = 0; index < 200000000; index++ )
{
tempVal2 = tempVal;
}
}
int main(int argc, char* argv[])
{
int ticks;
char str[64];
ticks = GetTickCount();
TestSpeed();
sprintf( str, "%.*f", 1, (double)( GetTickCount() - ticks ) / 1000 );
MessageBox( NULL, str, "", 0 );
return 0;
}
This was rather interesting. First I was unable to reproduce the slow down in release build, only in debug build. Then I turned off SSE2 optimizations and got the same ~40s run time.
The problem seems to be in the compiler generated copy assignment for Variant. Without SSE2 it actually does a floating point copy with fld/fstp instructions because the union contains a double. And with some specific values this apparently is a really expensive operation. The 64-bit integer value 1 maps to 4.940656458412e-324#DEN which is a denormalized number and I believe this causes problems. When you leave tempVal.valInteger uninitialized it may contain a value that works faster.
I did a small test to confirm this:
union {
uint64_t i;
volatile double d1;
};
i = 0xcccccccccccccccc; //with this value the test takes 0.07 seconds
//i = 1; //change to 1 and now the test takes 36 seconds
volatile double d2;
for(int i=0; i<200000000; ++i)
d2 = d1;
So what you could do is define your own copy assignment for Variant that just does a simple memcpy of the union.
Variant& operator=(const Variant& rhs)
{
dataType = rhs.dataType;
union UnionType
{
__int64 valInteger;
double valReal;
bool valBool;
Date valDate;
void *valObject;
};
memcpy(&valInteger, &rhs.valInteger, sizeof(UnionType));
valStr = rhs.valStr;
return *this;
}

How do I call a Win32 DLL void** parameter using Win32::API?

I have a Windows DLL that I want to call from Perl. The prototype for the exported function is:
int __stdcall func(const char*, int, int, int, double, double, void**);
The last parameter returns a pointer to an object that is allocated in the function.
The perl code –
my $dll_path = "../stage/test_dll.dll";
my $dll_func = new Win32::API($dll_path,
'func',
'PIIIDDP', 'I');
my $data = "test something here";
my $pResult = 0;
my $rc = $ dll_func ->Call($data, 0, 0, 9, 0.6, 0.3, $pResult);
An error message popped up saying that the memory can’t be written. Maybe I can’t use P to represent void**? I read through all the documentation and could not locate a single example that uses void** parameter. Help!
The variable associated with a P parameter must be a pre-allocated string variable, not an integer. Try something like:
my $pResult = "\0" x 8; # Just in case we're 64-bit
my $rc = $ dll_func ->Call($data, 0, 0, 9, 0.6, 0.3, $pResult);
$pResult will then contain the pointer to the object. You'll probably need to use unpack to extract it.
You don't say what you need to do with the object. If you need to pass it to other DLL functions as a void*, you'll probably need to unpack it as a long and use N instead of P in the parameter list.
Take a look at how swig would do it. Maybe you will find your answer there.
This answer might be off base, but the Inline::C module offers a pretty good interface into user libraries, and within Perl and C you can come up with all kinds of workarounds to passing data through a void** pointer.
use Inline C => DATA => LIBS => '-L../stage -ltest_dll';
my $data = "test something here";
my $rc = func_wrapper($data, 0, 0, 9, 0.6, 0.3);
my $p = get_pointer();
printf "func() set a pointer value of 0x%x\n", $p;
__END__
__C__
#include <stdio.h>
int func(const char *, int, int, int, double, double, void **);
void* pointer_value;
long get_pointer()
{
return (long) pointer_value;
}
/*
* Wraps func() in test_dll library.
*/
int func_wrapper(const char *s, int i1, int i2, int i3, double d1, double d2)
{
void *p = (void *) "some pointer";
int rval = func(s, i1, i2, i3, d1, d2, &p);
/* func() may have changed p as a side effect */
/* for demonstation, save it to a long value that can be retrieved with
the get_pointer() function. There are other ways to pass the pointer
data into Perl. */
pointer_value = p;
printf("The pointer value from func() is %p\n", p);
return rval;
}
If Inline::C looks interesting to you, the Inline::C-Cookbook page on CPAN is also indispensable.

Resources