The following codes are used for calculate the sin
and cos
value if the angle is given. In order to calculate these functions as fast as possible, assembly code implementations are adopted.
#include <stdio.h>
float sinx( float degree ) {
float result, two_right_angles = 180.0f ;
__asm__ __volatile__ ( "fld %1;"
"fld %2;"
"fldpi;"
"fmul;"
"fdiv;"
"fsin;"
"fstp %0;"
: "=g" (result)
: "g"(two_right_angles), "g" (degree)
) ;
return result ;
}
float cosx( float degree ) {
float result, two_right_angles = 180.0f, radians ;
__asm__ __volatile__ ( "fld %1;"
"fld %2;"
"fldpi;"
"fmul;"
"fdiv;"
"fstp %0;"
: "=g" (radians)
: "g"(two_right_angles), "g" (degree)
) ;
__asm__ __volatile__ ( "fld %1;"
"fcos;"
"fstp %0;" : "=g" (result) : "g" (radians)
) ;
return result ;
}
float square_root( float val ) {
float result ;
__asm__ __volatile__ ( "fld %1;"
"fsqrt;"
"fstp %0;"
: "=g" (result)
: "g" (val)
) ;
return result ;
}
int main() {
float theta ;
printf( "Enter theta in degrees : " ) ;
scanf( "%f", &theta ) ;
printf( "sinx(%f) = %f\n", theta, sinx( theta ) );
printf( "cosx(%f) = %f\n", theta, cosx( theta ) );
printf( "square_root(%f) = %f\n", theta, square_root( theta ) ) ;
return 0 ;
}
The above codes comes from here, and I am trying to compile the above codes with gcc:
g++ -Wall -fexceptions -g -c /filename.cpp
However, it fails, and the following error messages are given:
Error: operand type mismatch for `fstp'|
Error: operand type mismatch for `fstp'|
I was wondering why the compilation would fail and how I can compile them successfully. Thanks!
The manual says about
g
constraint:Any register, memory or immediate integer operand is allowed, except for registers that are not general registers
. The compiler probably picked a register whichfstp
doesn't accept but fits the constraints.By the way, this is quite horrible inline asm.
Also note just because something is in asm, it will not necessarily be faster. The compiler is quite capable of optimizing things and it does a better job, too. You might be interested in the
-ffast-math
switch. Fromreturn sin(degree * M_PI / 180);
the compiler produces this small piece of code: