float App::fresnelReflectTerm(float etaPos, float etaNeg, float cos_theta_i)
{
float theta_i;
theta_i = acos(cos_theta_i);
...
This generates an "ambiguous call to overloaded function error" and says that there are four options:
float acos(float fValue)
double acos(double _X)
float acos(float _X)
long double acos(long double _X)
I suspect that the problem is that the first and third both take a float arg and return a float value. But can anyone give me a hint about how I might determine (I'm using Visual Studio) where those four functions came from, so that I can eliminate the duplication, for instance? Or perhaps just give me a hint on how to get around this problem.
You can press F12 on that function.
Update
Based on comments from the OP, the problem was due to a definition of acos being brought in from G3D::. Using std::acos as opposed to acos will remove the ambiguity.
You can enable the file listing compiler option in VS studio, so you will know which files are include during compiling, see this msdn article.
Related
I am writing a project in Visual Studio then I use GCC in order to compile it. Sometimes it causes some problems: This time I cannot use sqrtf function because VS accepts it however GCC does not. So I need to find some way (maybe mathematical approach to calculate square root) to find square root of some number in a way both GCC and VS will accept. To be more precise this is the line which causes a problem:
float x_f = circleRadius - sqrtf((float)((circleRadius * circleRadius) - (y * y)));
I need to find the square root of (circleRadius^2 - y^2)
std::sqrt solves this problem:
#include <cmath>
auto foo(int circleRadius, int y) {
float x_f = circleRadius - std::sqrt((float)(circleRadius * circleRadius - y * y));
}
compiles for both msvc and gcc according to https://godbolt.org/z/g9MJH6
You should prefer std::sqrt to sqrtf in C++. It works with more types, i.e., you could write your function more generically. It also does not use hungarian notation.
Edit: If you do not care if the calculation returns a float or a double, you could omit the cast and write the following:
auto x_f = circleRadius - std::sqrt(circleRadius * circleRadius - y * y);
If you care that a float is used, you can use std::sqrtf instead.
If you have to use a cast, you should generally prefer static_cast to C-style casts. Reasons for this are listed here.
Your situation may be if you use newer compiler at VC and older compiler at gcc.
Try to use sqrt or sqrtf WITH
#include <math.h>
Don't use
#include <cmath>
math.h should have sqrt, sqrtf definitions for both compilers.
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).
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 );
My company has a piece of software, sporting a rather large codebase. Recently I was assigned the task of checking wether the code would compile on an x86_64 target using gcc 4.1.2. I've gotten pretty far in the compilation with very minor modifications to the code but just this morning I got a somewhat confusing compile error.
The code is trying, and failing, to call powfrom <cmath> using int, unsigned int& as parameters. The compiler spits out an error because it can't find a suitable match to call. The overloads for pow in <cmath> are as follows:
double pow(double base, double exponent)
long double pow(long double base, long double exponent)
float pow(float base, float exponent)
double pow(double base, int exponent)
long double pow(long double base, int exponent)
I'm not quite shure as to why this builds on our 32-bit environments but that's beside the point right now.
My question is: how should I cast the parameters, which pow should I use? Thanks.
P.S. I can't change the datatype of the parameters as doing so would require too much work. My assignment is to get the code to compile, detailing any hacks I make so that later, we can go over those hacks and find proper ways do deal with them.
If you are making many calls to pow(int, unsigned int) why don't you just code it by yourself? If execution speed is not an issue, it's not much work.
Otherwise, I'd use a pow() overload whose input parameters are guaranteed to contain your expected values, such as pow(float, float) or pow(double, double). Anyway, I feel that making your own version could prevent problems with conversion between floating point and integer.
The result will always be integer, with these types of arguments.
Depending on the expected range of the arguments, especially the exponent, you should choose for the float or double or long double version.
So that would become
pow( (float) i, (int)ui );
You can find the allowed range of arguments by solving the equation pow(i,ui) < max_double.
while doing some homework in my very strange C++ book, which I've been told before to throw away, had a very peculiar code segment. I know homework stuff always throws in extra "mystery" to try to confuse you like indenting 2 lines after a single-statement for-loop. But this one I'm confused on because it seems to serve some real-purpose.
basically it is like this:
int counter=10;
...
if(pow(floor(sqrt(counter+0.0)),2) == counter)
...
I'm interested in this part especially:
sqrt(counter+0.0)
Is there some purpose to the +0.0? Is this the poormans way of doing a static cast to a double? Does this avoid some compiler warning on some compiler I do not use? The entire program printed the exact same thing and compiled without warnings on g++ whenever I left out the +0.0 part. Maybe I'm not using a weird enough compiler?
Edit:
Also, does gcc just break standard and not make an error for Ambiguous reference since sqrt can take 3 different types of parameters?
[earlz#EarlzBeta-~/projects/homework1] $ cat calc.cpp
#include <cmath>
int main(){
int counter=0;
sqrt(counter);
}
[earlz#EarlzBeta-~/projects/homework1] $ g++ calc.cpp
/usr/lib/libstdc++.so.47.0: warning: strcpy() is almost always misused, please use strlcpy()
/usr/lib/libstdc++.so.47.0: warning: strcat() is almost always misused, please use strlcat()
[earlz#EarlzBeta-~/projects/homework1] $
Also, here is the relevant part of my system libraries cmath I'm not too keen on templates, so I'm not sure what it's doing
using ::sqrt;
inline float
sqrt(float __x)
{ return __builtin_sqrtf(__x); }
inline long double
sqrt(long double __x)
{ return __builtin_sqrtl(__x); }
template<typename _Tp>
inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
double>::__type
sqrt(_Tp __x)
{ return __builtin_sqrt(__x);
Is this the poormans way of doing a static cast to a double?
Yes.
You can't call sqrt with an int as its parameter, because sqrt takes a float, double, or long double. You have to cast the int to one of those types, otherwise the call is ambiguous.
the reason for the expression counter + 0.0 is to explicitly make it a real number. if we donot add 0.0 the compiler will do implicit conversion
It's just another way to cast to a double. This is because sqrt doesn't accept ints. Because a double is higher it will merge the int into the 0.0. The same way can be done for converting from (int,double,float) to string.
double n = 0;
string m = ""+n;