Arrayfire array from complex host data - c++

I'm having a problem initializing an arrayfire array from host data.
The following code will not link for me:
constexp int mNumEigenInfos = 100;
std::complex<float> mEigenVectors[mNumEigenInfos][6];
af::array mEigenVectorsArray = af::array((dim_t)6,(dim_t)(mNumEigenInfos),reinterpret_cast<float2*>(mEigenVectors));
Giving me an error of:
undefined reference to `af::array::array<float2>(long long, long long, float2 const*, af_source)'
Now if i change the reinterpret_cast from float2* to float*:
constexp int mNumEigenInfos = 100;
std::complex<float> mEigenVectors[mNumEigenInfos][6];
af::array mEigenVectorsArray = af::array((dim_t)6,(dim_t)(mNumEigenInfos),reinterpret_cast<float*>(mEigenVectors));
It links fine. From reading online, i thought i was supposed to treat complex data as a cuComplex (which casting to float2 or cuComplex gives the exact same error since they are the same thing).
I feel like i'm making a stupid mistake here but can't seem to figure it out.
How am i supposed to initialize an arrayfire array from std::complex host data?
Thank you for your Help

This is kind of similar to the question af::array::device doesn't work with complex arrays please have a look - the only difference is the direction in which complex data is passed.
The following should work fine as std::complex should be ABI compatible with af::cfloat.
af::array mEigenVectorsArray =
af::array((dim_t)6, (dim_t)(mNumEigenInfos),
reinterpret_cast<af::cfloat>(mEigenVectors));
ArrayFire API won't have a symbol for function with float2 type, however it will have the symbol for function with type af::cfloat. Even cuFloatComplext or float2 should also be ABI compatible with af::cfloat I think. So, reinterpret-cast to af::cfloat is what should be done.

Related

Difference between int cast and int& cast

Float a;
int i=(Int) a;
Int& j=(Int &) a;
Can't type with extensive details using my phone.
Can anyone tell thx
Update:
Not quite you Lot expected. Since Google was completely banned here in China. I can barely login using laptop. Always popping message like require third party JavaScript. typing Is hard. so that's it and to the one claims this a simple reference, incomplete i think. It's more complicated than that
Update:
Best just change title. Seems casting to different type could cause problems. So what's different between the two processes of different typecast.
Last update:
Experimented, why i and j are different. Don't vow down if you can't answer yourself
(int) will cast the float value to sizeof(int) byte integer value <= float value
(int &) will convert the float value to a one byte refrence

error: cannot convert 'float*' to 'qreal* {aka double*} in initialization

I'm trying to compile old Qt project and i encounter this error:
error: cannot convert 'float*' to 'qreal* {aka double*}' in
initialization
Here's the fragment of code:
void Camera::loadProjectionMatrix()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
qreal *dataMat = projectionMatrix_.data();
GLfloat matriceArray[16];
for (int i= 0; i < 16; ++i)
matriceArray[i] = dataMat[i];
glMultMatrixf(matriceArray);
}
What are my options to overcome this error?
The projection matrix will return float* to you as per documentation:
float * QMatrix4x4::​data()
Returns a pointer to the raw data of this matrix.
The best practice would be to eliminate the qreal usage in your codebase regardless this case. When the contributors went through the Qt 5 refactoring, the qreal ancient concept was dropped as much as possible and definitely should not be used much in new code where the API deals with float.
The recommendation is to use float these days in such cases. This is a bit historical, really. Back then, it made sense to define qreal to double where available, but float where not, e.g. ARM platforms. See the old documentation:
typedef qreal
Typedef for double on all platforms except for those using CPUs with ARM architectures. On ARM-based platforms, qreal is a typedef for float for performance reasons.
In Qt 5, the documentation is slightly different, although the main concept seems to have remained the same:
typedef qreal
Typedef for double unless Qt is configured with the -qreal float option.
I would fix your code the following way:
void Camera::loadProjectionMatrix()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float *dataMat = projectionMatrix_.data();
GLfloat matriceArray[16];
for (int i= 0; i < 16; ++i)
matriceArray[i] = dataMat[i];
glMultMatrixf(matriceArray);
}
Strictly speaking, you could also go an alternative way to solve the issue, namely by using this method rather than data():
float & QMatrix4x4::​operator()(int row, int column)
Returns a reference to the element at position (row, column) in this matrix so that the element can be assigned to.
In which case, you could even eliminate the dataMat variable and assign the items directly to your matriceArray in the iteration.
Going even further than that, you should consider using a Qt library for this common task, namely e.g. the opengl classes either in QtGui or Qt3D. It would make more sense to mess with low-level opengl API calls if you do something custom.
Apparently, projectionMatrix_.data() returns a float*, and you cannot assign a float* to a double* (which is what qreal* is in this case).
Use
float *dataMat = projectionMatrix_.data();
or
auto dataMat = projectionMatrix_.data();
instead. The latter sometimes has the advantage that it might still be correct code if the return type of the function changes for some reason, although that is nothing to expect from a mature library. Additionally, you cannot get the type wrong on accident.

ptxas "double is not supported" warning when using thrust::sort on a struct array

I'm trying to sort an array of structs on my GPU with thrust::sort. However, when I compile with nvcc, I get this warning:
ptxas /tmp/tmpxft_00005186_00000000-5_antsim.ptx, line 1520; warning : Double is not supported. Demoting to float
I've isolated the problem to my call to thrust::sort, here:
thrust::sort(thrustAnts, thrustAnts + NUM_ANTS, antSortByX());
thrustAnts is an array of Ant structs located on the GPU, while antSortByX is a functor as defined below:
typedef struct {
float posX;
float posY;
float direction;
float speed;
u_char life;
u_char carrying;
curandState rngState;
} Ant;
struct antSortByX {
__host__ __device__ bool operator()(Ant &antOne, Ant &antTwo) {
return antOne.posX < antTwo.posX;
}
};
It seems to me as though there aren't any doubles in this, though I'm suspicious the less-than operator in my functor evaluates those floats as doubles. I can solve this problem by compiling with -arch sm_13, but I'm curious as to why this is complaining at me in the first place.
The demotion happens because CUDA devices support double precision calculations at first with compute capability 1.3. NVCC knows the specifications and demotes every double to float for devices with CC < 1.3 just because the hardware cannot handle double precisions.
A good feature list could be found on wikipedia: CUDA
That you can’t see any doubles in this code doesn't mean that they are not there. Most commonly this error results from a missing f postfix on a floating point constant. The compiler performance an implicit cast from all floats to double when one double is part of the expression. A floating point constant without the f is a double value and the casting starts. However, for the less-operator a cast without constant expressions should not happen.
I can only speculate, but it seems to me that in your case a double precision value could be used within the thrust::sort implementation. Since you provide only a user function to a higher order function (functions that take functions as parameters).

Casting float2 to double2 and vice versa

So I have an openCL program where some of the variables are in float2 and some are in double2. And I would like to either upcast or downcast these variables but I am not sure how to do it. I tried to explicitly casting it like how I would normally do for float and double but it didn't work.
float2 a,b;
double2 c,d;
a = (float2)(c+d); //didnt work
a = float2(c+d); //didnt work
Maybe I am not understanding the type "float2" and "double2", could someone tell me how to cast them in order to work properly?
Thanks in advance.
The floatn and doublen type families represent vectors of values (in your case they have 2 members). A C-style conversion does not work on them.
There is a family of conversion functions that work for vectors that look like this:
convert_float2(vec2)
However, reading the documentation here it looks like conversion from/to double2 is not supported. That leaves you with the option of performing the conversions manually:
a.x = float(c.x + d.x);
a.y = float(c.y + d.y);

Int or Unsigned Int to float without getting a warning

Sometimes I have to convert from an unsigned integer value to a float. For example, my graphics engine takes in a SetScale(float x, float y, float z) with floats and I have an object that has a certain size as an unsigned int. I want to convert the unsigned int to a float to properly scale an entity (the example is very specific but I hope you get the point).
Now, what I usually do is:
unsigned int size = 5;
float scale = float(size);
My3DObject->SetScale(scale , scale , scale);
Is this good practice at all, under certain assumptions (see Notes)? Is there a better way than to litter the code with float()?
Notes: I cannot touch the graphics API. I have to use the SetScale() function which takes in floats. Moreover, I also cannot touch the size, it has to be an unsigned int. I am sure there are plenty of other examples with the same 'problem'. The above can be applied to any conversion that needs to be done and you as a programmer have little choice in the matter.
My preference would be to use static_cast:
float scale = static_cast<float>(size);
but what you are doing is functionally equivalent and fine.
There is an implicit conversion from unsigned int to float, so the cast is strictly unnecessary.
If your compiler issues a warning, then there isn't really anything wrong with using a cast to silence the warning. Just be aware that if size is very large it may not be representable exactly by a float.