C function call parameters get scrambled - c++

I am using Netbeans with gcc for this, and I find that the value of the function arguments are being corrupted between the calling function and the called function.
In myfuns.h:
float dotprod( float u1, float u2, float u3, float v1, float v2, float v3 );
In myfuns.c
float dotprod( float u1, float u2, float u3, float v1, float v2, float v3 )
{
float res= u1*v1+u2*v2+u3*v3 ;
return res;
}
In main.c
...
float dp=dotprod( rx, ry, rz, ddx, ddy, ddz );
...
If I print the values of u1,u2 etc in the dotprod() function, or examine them with the
debugger, the values are different to the values of rx,ry etc in main.c
If I convert the arguments from float to float*, the problem seems to go away. I also
tried adding a dummy integer argument before and after the 6 float arguments, the first one is OK but the last one also get corrupted. I have spent hours trying to spot the error.
Any suggestions ?

Are the types for all those variable in main() specified as float?
Is the prototype for dotprod() visible when you call it? In other words, does your main file have #include "myfuns.h"?
In particular, answering no for that second question means that the compiler will make certain assumptions about the arguments being passed that makes the value a different width, or interpret them in a different way.
For example, consider:
#include <stdio.h>
int main(int argc, char *argv[]) {
float x = 1.5, y = 2.5;
fn (x, y); // <-- compiler makes assumptions.
return 0;
}
void fn (float a, float b) { // <-- compiler should complain
printf ("%f %f\n", a, b); // about bad assumptions.
}
which outputs:
0.000000 1.937500
That's really not what you would expect. This was compiled with gcc and the slew of warnings that were spat out should have been reason enough to go back and check the code (a).
In this particular case, my int and float types are the same width (32 bits) but, because the compiler thinks the function accepts int, it will convert those floats to that type first. Unfortunately, when the function looks at those int values on the stack, it interprets them as float types, which are encoded quite differently.
It can be even worse if your expected and actual types are different widths, since you may find you try to use more data than what was put on the stack.
This particular code sample can be fixed simply by inserting:
void fn (float, float);
before main() (or swapping main() and fn() around) so that the prototype is not assumed. This results in no warnings from gcc and the correct output:
1.500000 2.500000
Basically, you have to ensure that the caller and callee agree on the parameters passed. That includes such things as calling convention, data types and parameter counts, among other things. A mismatch in any of these will cause you problems.
(a): Such as the following, on my system:
testprog.c: In function ‘main’:
testprog.c:5: warning: implicit declaration of function ‘fn’
testprog.c: At top level:
testprog.c:9: warning: conflicting types for ‘fn’
testprog.c:5: note: previous implicit declaration of ‘fn’ was here

Make sure you are passing the same type of data with the function parameter, i.e. the size and represent.
For a very simple test, try this in main:
float dp=dotprod( (float)rx, (float)ry, (float)rz, (float)ddx, (float)ddy, (float)ddz );

Related

Data type float

While declaring a variable of type float, is it necessary to write f towards the end of the value? For example, float amount = .01 and float amount = 0.01f, here what does the f mean and how does it make any difference?Also, what is the role of #include library file here.
It's not necessary: the compiler will make an appropriate numerical conversion for you.
0.01f is a literal of float type, whereas 0.01 is a double type.
Occasionally you need to descriminate explicitly especially when working with templates or overloaded functions:
void foo(const float&){
// Pay me a bonus
}
void foo(const double&){
// Reformat my disk
}
int main(){
foo(1.f);
}
Finally, if you're leading towards using a float over a double, then do read through this: Is using double faster than float?
It depends on how you define your variable. When specifying the type float in the definition, adding a trailing f is not necessary:
float amount = 0.1; /* This is fine, compiler knows the type of amount. */
Adding a superfluous literal here (float amount = 0.1f;) might even be considered bad practice, as you repeat the type information, resulting in more edits when the type is changed.
In the context of type deduction though, you have to give the f literal:
auto amount = 0.1f; /* Without the literal, compiler deduces double. */
There are more subtle contexts in which type deduction occurs, e.g.
std::vector<float> vecOfFloats;
/* ... */
std::accumulate(vecOfFloats.cbegin(), vecOfFloats.cend(), 0.1f);
Here, the third argument is used to deduce the type on which std::accumulate operates. If you just call it like std::accumulate(..., 0.1);, a double to float conversion takes place for every element in vecOfFloats.
.01 is a double literal. There is an implicit conversion to float in the initialisation
float amount = .01;
.01f is a float literal. There is no conversion in the initialisation
float amount = .01f;
That depends...
You can do for example:
1)
float f = 3.14f;
In this case the literal 3.14 is explicitly given as a float... so everything is ok
2)
float f = 3.14;
In this case 3.14 is actually a double, but the variable f is declared as a float...so when compiling, the number will be casted to a float with the loss precision consequences of that case...
You could since c++11
auto f = 3.14;
Or auto f{3,14};
In both cases the compiler takes exactly the type of the literal...(both are doubles)

C++ pow() - Mismatch type for float

I have made a simple code in C++
#include<math.h>
void main()
{
float a,x;
cout<<"Enter value of a"<<endl;
cin>>a;
x = pow(a,0.5);
cout<<x;
}
But it's giving me error:
When I press F12 and go to definition of pow(), these 6 overloads are found:
As we can see, it clearly has one overload for (double, double) and one for (float, float), so why does it give error when I declare a as float and works perfectly when I change its data-type to double?
The issue here is that the literal 0.5 is a double, so you are calling pow with a set of arguments that do not unambiguously match an overload, and for which type conversions cannot be applied to unambiguously match an existing overload. You should use the float literal 0.5f instead.
x = pow(a, 0.5f);
Also note that you need to #include <iostream> for cout, cin and endl, and you have to either refer to them by their full names (std::cout, std::cin, std::endl), or use using declarations
using std::cout;
using std::cin;
using std::endl;
Finally, void main() is not one of the valid signatures for the main function. It must return int, so
int main()
or
auto main()->int
You're calling it with a float and a double. There isn't an overload for that combination, and several that are close enough to be ambiguous.
0.5f would have type float, if you want to use the overload with two float parameters.
Your call doesn't exactly match any of the various definitions of pow, so the compiler is trying to see if it can automatically cast some of your arguments so it will exactly match, but here there are 6 possible definitions of pow that could match. You need to tell the compiler exactly which one you want.
What you tried to call is pow(float, double), because 0.5 is a double literal (not a float!).
If you do for example pow(a, 0.5f) then both arguments are float and it will compile. Of course you could also pick any of the other 5 overloads.
You need to explicitly call an overloaded function of pow()
x = pow(a, 0.5f);
or
double y = pow(static_cast<double>(a), 0.5);

Is 'float a = 3.0;' a correct statement?

If I have the following declaration:
float a = 3.0 ;
is that an error? I read in a book that 3.0 is a double value and that I have to specify it as float a = 3.0f. Is it so?
It is not an error to declare float a = 3.0 : if you do, the compiler will convert the double literal 3.0 to a float for you.
However, you should use the float literals notation in specific scenarios.
For performance reasons:
Specifically, consider:
float foo(float x) { return x * 0.42; }
Here the compiler will emit a conversion (that you will pay at runtime) for each returned value. To avoid it you should declare:
float foo(float x) { return x * 0.42f; } // OK, no conversion required
To avoid bugs when comparing results:
e.g. the following comparison fails :
float x = 4.2;
if (x == 4.2)
std::cout << "oops"; // Not executed!
We can fix it with the float literal notation :
if (x == 4.2f)
std::cout << "ok !"; // Executed!
(Note: of course, this is not how you should compare float or double numbers for equality in general)
To call the correct overloaded function (for the same reason):
Example:
void foo(float f) { std::cout << "\nfloat"; }
void foo(double d) { std::cout << "\ndouble"; }
int main()
{
foo(42.0); // calls double overload
foo(42.0f); // calls float overload
return 0;
}
As noted by Cyber, in a type deduction context, it is necessary to help the compiler deduce a float :
In case of auto :
auto d = 3; // int
auto e = 3.0; // double
auto f = 3.0f; // float
And similarly, in case of template type deduction :
void foo(float f) { std::cout << "\nfloat"; }
void foo(double d) { std::cout << "\ndouble"; }
template<typename T>
void bar(T t)
{
foo(t);
}
int main()
{
bar(42.0); // Deduce double
bar(42.0f); // Deduce float
return 0;
}
Live demo
The compiler will turn any of the following literals into floats, because you declared the variable as a float.
float a = 3; // converted to float
float b = 3.0; // converted to float
float c = 3.0f; // float
It would matter is if you used auto (or other type deducting methods), for example:
auto d = 3; // int
auto e = 3.0; // double
auto f = 3.0f; // float
Floating point literals without a suffix are of type double, this is covered in the draft C++ standard section 2.14.4 Floating literals:
[...]The type of a floating literal is double unless explicitly specified by a suffix.[...]
so is it an error to assign 3.0 a double literal to a float?:
float a = 3.0
No, it is not, it will be converted, which is covered in section 4.8 Floating point conversions:
A prvalue of floating point type can be converted to a prvalue of
another floating point type. If the source value can be exactly
represented in the destination type, the result of the conversion is
that exact representation. If the source value is between two adjacent
destination values, the result of the conversion is an
implementation-defined choice of either of those values. Otherwise,
the behavior is undefined.
We can read more details on the implications of this in GotW #67: double or nothing which says:
This means that a double constant can be implicitly (i.e., silently)
converted to a float constant, even if doing so loses precision (i.e.,
data). This was allowed to remain for C compatibility and usability
reasons, but it's worth keeping in mind when you do floating-point
work.
A quality compiler will warn you if you try to do something that's
undefined behavior, namely put a double quantity into a float that's
less than the minimum, or greater than the maximum, value that a float
is able to represent. A really good compiler will provide an optional
warning if you try to do something that may be defined but could lose
information, namely put a double quantity into a float that is between
the minimum and maximum values representable by a float, but which
can't be represented exactly as a float.
So there are caveats for the general case that you should be aware of.
From a practical perspective, in this case the results will most likely be the same even though technically there is a conversion, we can see this by trying out the following code on godbolt:
#include <iostream>
float func1()
{
return 3.0; // a double literal
}
float func2()
{
return 3.0f ; // a float literal
}
int main()
{
std::cout << func1() << ":" << func2() << std::endl ;
return 0;
}
and we see that the results for func1 and func2 are identical, using both clang and gcc:
func1():
movss xmm0, DWORD PTR .LC0[rip]
ret
func2():
movss xmm0, DWORD PTR .LC0[rip]
ret
As Pascal points out in this comment you won't always be able to count on this. Using 0.1 and 0.1f respectively causes the assembly generated to differ since the conversion must now be done explicitly. The following code:
float func1(float x )
{
return x*0.1; // a double literal
}
float func2(float x)
{
return x*0.1f ; // a float literal
}
results in the following assembly:
func1(float):
cvtss2sd %xmm0, %xmm0 # x, D.31147
mulsd .LC0(%rip), %xmm0 #, D.31147
cvtsd2ss %xmm0, %xmm0 # D.31147, D.31148
ret
func2(float):
mulss .LC2(%rip), %xmm0 #, D.31155
ret
Regardless whether you can determine if the conversion will have a performance impact or not, using the correct type better documents your intention. Using an explicit conversions for example static_cast also helps to clarify the conversion was intended as opposed to accidental, which may signify a bug or potential bug.
Note
As supercat points out, multiplication by e.g. 0.1 and 0.1f is not equivalent. I am just going to quote the comment because it was excellent and a summary probably would not do it justice:
For example, if f was equal to 100000224 (which is exactly
representable as a float), multiplying it by one tenth should yield a
result which rounds down to 10000022, but multiplying by 0.1f will
instead yield a result which erroneously rounds up to 10000023. If the
intention is to divide by ten, multiplication by double constant 0.1
will likely be faster than division by 10f, and more precise than
multiplication by 0.1f.
My original point was to demonstrate a false example given in another question but this finely demonstrates subtle issues can exist in toy examples.
It's not an error in the sense that the compiler will reject it, but it is an error in the sense that it may not be what you want.
As your book correctly states, 3.0 is a value of type double. There is an implicit conversion from double to float, so float a = 3.0; is a valid definition of a variable.
However, at least conceptually, this performs a needless conversion. Depending on the compiler, the conversion may be performed at compile time, or it may be saved for run time. A valid reason for saving it for run time is that floating-point conversions are difficult and may have unexpected side effects if the value cannot be represented exactly, and it's not always easy to verify whether the value can be represented exactly.
3.0f avoids that problem: although technically, the compiler is still allowed to calculate the constant at run time (it always is), here, there is absolutely no reason why any compiler might possibly do that.
While not an error, per se, it is a little sloppy. You know you want a float, so initialize it with a float.Another programmer may come along and not be sure which part of the declaration is correct, the type or the initializer. Why not have them both be correct?
float Answer = 42.0f;
When you define a variable, it is initialized with the provided initializer. This may require converting the value of the initializer to the type of the variable that's being initialized. That's what's happening when you say float a = 3.0;: The value of the initializer is converted to float, and the result of the conversion becomes the initial value of a.
That's generally fine, but it doesn't hurt to write 3.0f to show that you're aware of what you're doing, and especially if you want to write auto a = 3.0f.
If you try out the following:
std::cout << sizeof(3.2f) <<":" << sizeof(3.2) << std::endl;
you will get output as:
4:8
that shows, size of 3.2f is taken as 4 bytes on 32-bit machine wheres 3.2 is interpreted as double value taking 8 bytes on 32-bit machine.
This should provide the answer that you are looking for.
The compiler deduces the best-fitting type from literals, or at leas what it thinks is best-fitting. That is rather lose efficiency over precision, i.e. use a double instead of float.
If in doubt, use brace-intializers to make it explicit:
auto d = double{3}; // make a double
auto f = float{3}; // make a float
auto i = int{3}; // make a int
The story gets more interesting if you initialize from another variable where type-conversion rules apply: While it is legal to constuct a double form a literal, it cant be contructed from an int without possible narrowing:
auto xxx = double{i} // warning ! narrowing conversion of 'i' from 'int' to 'double'

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).

Is const double cast at compile time?

It makes sense to define mathematical constants as double values but what happens when one requires float values instead of doubles? Does the compiler automatically interpret the doubles as floats at compile-time (so they are actually treated as they were const floats) or is this conversion made at runtime?
If by "defining", you mean using #define, here's what happens:
Say you have:
#define CONST1 1.5
#define CONST2 1.12312455431461363145134614 // Assume some number too
// precise for float
Now if you have:
float x = CONST1;
float y = CONST2;
you don't get any warning for x because the compiler automatically makes CONST1 a float. For y, you get a warning because CONST2 doesn't fit in a float, but the compiler casts it to float anyway.
If by "defining", you mean using const variables, here's what happens:
Say you have
const double CONST1=1.5;
const double CONST2=1.12312455431461363145134614; // Assume some number too
// precise for float
Now if you have:
float x = CONST1;
float y = CONST2;
there is no way for the compiler to know the values of CONST1 and CONST2(*) and therefore cannot interpret the values as float at compile them. You will be given two warnings about possible loss of data and the conversion will be done at runtime.
(*) Actually there is a way. Since the values are const, the optimizer may decide not to take a variable for them, but replace the values throughout the code. This could get complicated though, as you may pass the address to these variables around, so the optimizer may decide not to do that. That is, don't count on it.
Note that, this whole thing is true for any basic type conversions. If you have
#define CONST3 1
then you think CONST3 is int, but if you put it in a float, it would become float at compile-time, or if you put it in a char, it would become char at compiler-time.