absolute Value of double - c

I am trying write a function named absD that returns the absolute value of its argument.
I do not want to use any predefined functions. Right now i am getting a parse error when i try to compile it.
I would image all i would have to do to get the absolute value of a double is change the sign bit? this is what i have
#include <stdio.h>
#include <stdlib.h>
#define PRECISION 3
double absD (double n)
{
asm(" fld %eax \n"
" movl $0x7FFFFFFFFFFFFFFF, %eax \n"
" pop %eax \n"
);
return n;
}
int main (int argc, char **argv)
{
double n = 0.0;
printf("Absolute value\n");
if (argc > 1)
n = atof(argv[1]);
printf("abs(%.*f) = %.*f\n", PRECISION, n, PRECISION, absD(n));
return 0;
}
I fixed the curly brace..
the error i am getting is
~ $ gc a02
gcc -Wall -g a02.c -o a02
/tmp/ccl2H7rf.s: Assembler messages:
/tmp/ccl2H7rf.s:228: Error: suffix or operands invalid for `fld'
/tmp/ccl2H7rf.s:229: Error: missing or invalid immediate expression `0x7FFFFFFFF
FFFFFFF'
~ $

Do you need to do it in assembly? Is this a homework requirement, or are you looking for very high performance?
This doesn't use any predefined functions:
double absD(double n)
{
if (n < 0.0)
n = -n;
return n;
}

I'm no expert, but it looks like you're using ( to open the assembly block and } to end it. You probably should use one or the other, not both inconsistently.

asm(" fld %eax \n"
" movl $0x7FFFFFFFFFFFFFFF, %eax \n"
" pop %eax \n"
};
notice the curley bracket before the semicolon.

Depending on how you want to treat -0.0, you can use C99 / POSIX (2004)'s signbit() function.
#include <math.h>
double absD (double x)
{
if ( signbit(x) ) {
#ifdef NAIVE
return 0.0 - x;
#else
return x &= 0x7FFFFFFFFFFFFFFF;
#endif
} else {
return x;
}
}
But frankly if you're using Standard C Library (libc) atof and printf, I don't see why not using fabs() is desirable. As you can also do normal bit-twiddling in C.
Of course if you're using assembly, why not usefchs op anyhow?

You have errors in your assembly code, which the assembler gives you perfectly reasonable error messages about.
you can't load a floating point value directly from %eax -- the operand needs to be an address to load from
you can't have constant literals that don't fit in 32 bits.

The sign of a floating bit number is just the high bit, so all you need to to is clear the most significant bit.
If you must do this in assembly, then it seems to me that you would be better of using integer rather than floating point instructions. You can't do bitwise operations on floating point registers.
Also, there isn't any need to load the entire 8 byte value into any register, you could just as easily operate only on the high byte (or int) if your processor doesn't have 8 byte integer registers.

/tmp/ccl2H7rf.s:228: Error: suffix or
operands invalid for `fld'
fld needs the operand to be in memory. Put it in memory, ie the stack, and supply the address.
/tmp/ccl2H7rf.s:229: Error: missing or
invalid immediate expression
`0x7FFFFFFFF FFFFFFF'
EAX does not hold more than 32 bits. If you meant for this to be a floating point number, put it on the floating point stack with a load instruction, ie fld.

Related

Convert a float literal to int representation in x86 assembly?

The following C code:
int main()
{
float f;
f = 3.0;
}
Is converted to the following assembly instructions:
main:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
flds .LC0
fstps -4(%ebp)
movl $0, %eax
leave
ret
.LC0:
.long 1077936128
What is the correct way to calculate the .long/int representation of the float literal?
e.g. 1077936128 generated from 3.0 for the example shown above
For this example gcc is used with the -m32 -S -O0 -fno-stack-protector -fno-asynchronous-unwind-tables flags using intel settings to generate the assembly output.
References:
Compiler Explorer Link with compilation flags and other settings
x86 FPU hardware uses IEEE754 binary32 / binary64 representations for float / double.
Determining the IEEE 754 representation of a floating point number is not trivial for humans. In handwritten assembly code, it's usually a good idea to use the .float or .double directives instead:
.float 3.0 # generates 3.0 as a 32 bit float
.double 3.0 # generates 3.0 as a 64 bit float
If you really want to compute this manually, refer to the explanations on Wikipedia. It might be interesting to do so as an exercise, but for actual programming it's tedious and mostly useless.
Compilers do the conversion (with rounding to the nearest representable FP value) internally, because FP values often don't come directly from a literal in the source; they can come from constant folding. e.g. 1.23 * 4.56 is evaluated at compile time, so the compiler already ends up with FP values in float or double binary representation. Printing them back to decimal for the assembler to parse and re-convert to binary would be slower and might require a lot of decimal places.
To compute the representation of a 32 bit float as a 32 bit integer, you can use an online IEEE754 converter, or a program like this:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(int argc, char *argv[])
{
union { uint32_t u32; float f32; } intfloat;
if (argc != 2) {
fprintf(stderr, "Usage: %s some-number\n", argv[0]);
return EXIT_FAILURE;
}
intfloat.f32 = atof(argv[1]);
printf("0x%08" PRIx32 "\n", intfloat.u32);
return EXIT_SUCCESS;
}

What is happening here in pow function?

I have seen various answer here that depicts Strange behavior of pow function in C.
But I Have something different to ask here.
In the below code I have initialized int x = pow(10,2) and int y = pow(10,n) (int n = 2).
In first case it when I print the result it shows 100 and in the other case it comes out to be 99.
I know that pow returns double and it gets truncated on storing in int, but I want to ask why the output comes to be different.
CODE1
#include<stdio.h>
#include<math.h>
int main()
{
int n = 2;
int x;
int y;
x = pow(10,2); //Printing Gives Output 100
y = pow(10,n); //Printing Gives Output 99
printf("%d %d" , x , y);
}
Output : 100 99
Why is the output coming out to be different. ?
My gcc version is 4.9.2
Update :
Code 2
int main()
{
int n = 2;
int x;
int y;
x = pow(10,2); //Printing Gives Output 100
y = pow(10,n); //Printing Gives Output 99
double k = pow(10,2);
double l = pow(10,n);
printf("%d %d\n" , x , y);
printf("%f %f\n" , k , l);
}
Output : 100 99
100.000000 100.000000
Update 2 Assembly Instructions FOR CODE1
Generated Assembly Instructions GCC 4.9.2 using gcc -S -masm=intel :
.LC1:
.ascii "%d %d\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
push ebp
mov ebp, esp
and esp, -16
sub esp, 48
call ___main
mov DWORD PTR [esp+44], 2
mov DWORD PTR [esp+40], 100 //Concerned Line
fild DWORD PTR [esp+44]
fstp QWORD PTR [esp+8]
fld QWORD PTR LC0
fstp QWORD PTR [esp]
call _pow //Concerned Line
fnstcw WORD PTR [esp+30]
movzx eax, WORD PTR [esp+30]
mov ah, 12
mov WORD PTR [esp+28], ax
fldcw WORD PTR [esp+28]
fistp DWORD PTR [esp+36]
fldcw WORD PTR [esp+30]
mov eax, DWORD PTR [esp+36]
mov DWORD PTR [esp+8], eax
mov eax, DWORD PTR [esp+40]
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], OFFSET FLAT:LC1
call _printf
leave
ret
.section .rdata,"dr"
.align 8
LC0:
.long 0
.long 1076101120
.ident "GCC: (tdm-1) 4.9.2"
.def _pow; .scl 2; .type 32; .endef
.def _printf; .scl 2; .type 32; .endef
I know that pow returns double and it gets truncated on storing in int, but I want to ask why the output comes to be different.
You must first, if you haven't already, divest yourself of the idea that floating-point numbers are in any way sensible or predictable. double only approximates real numbers and almost anything you do with a double is likely to be an approximation to the actual result.
That said, as you have realized, pow(10, n) resulted in a value like 99.99999999999997, which is an approximation accurate to 15 significant figures. And then you told it to truncate to the largest integer less than that, so it threw away most of those.
(Aside: there is rarely a good reason to convert a double to an int. Usually you should either format it for display with something like sprintf("%.0f", x), which does rounding correctly, or use the floor function, which can handle floating-point numbers that may be out of the range of an int. If neither of those suit your purpose, like in currency or date calculations, possibly you should not be using floating point numbers at all.)
There are two weird things going on here. First, why is pow(10, n) inaccurate? 10, 2, and 100 are all precisely representable as double. The best answer I can offer is that the C standard library you are using has a bug. (The compiler and the standard library, which I assume are gcc and glibc, are developed on different release schedules and by different teams. If pow is returning inaccurate results, that is probably a bug in glibc, not gcc.)
In the comments on your question, amdn found a glibc bug to do with FP rounding that might be related and another Q&A that goes into more detail about why this happens and how it's not a violation of the C standard. chux's answer also addresses this. (C doesn't require implementation of IEEE 754, but even if it did, pow isn't required to use correct rounding.) I will still call this a glibc bug, because it's an undesirable property.
(It's also conceivable, though unlikely, that your processor's FPU is wrong.)
Second, why is pow(10, n) different from pow(10, 2)? This one is far easier. gcc optimizes away function calls for which the result can be calculated at compile time, so pow(10, 2) is almost certainly being optimized to 100.0. If you look at the generated assembly code, you will find only one call to pow.
The GCC manual, section 6.59 describes which standard library functions may be treated in this way (follow the link for the full list):
The remaining functions are provided for optimization purposes.
With the exception of built-ins that have library equivalents such as the standard C library functions discussed below, or that expand to library calls, GCC built-in functions are always expanded inline and thus do not have corresponding entry points and their address cannot be obtained. Attempting to use them in an expression other than a function call results in a compile-time error.
[...]
The ISO C90 functions abort, abs, acos, asin, atan2, atan, calloc, ceil, cosh, cos, exit, exp, fabs, floor, fmod, fprintf, fputs, frexp, fscanf, isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, isxdigit, tolower, toupper, labs, ldexp, log10, log, malloc, memchr, memcmp, memcpy, memset, modf, pow, printf, putchar, puts, scanf, sinh, sin, snprintf, sprintf, sqrt, sscanf, strcat, strchr, strcmp, strcpy, strcspn, strlen, strncat, strncmp, strncpy, strpbrk, strrchr, strspn, strstr, tanh, tan, vfprintf, vprintf and vsprintf are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin-function is specified for an individual function).
So it would seem you can disable this behavior with -fno-builtin-pow.
Why is the output coming out to be different. ? (in the updated appended code)
We do not know the values are that different.
When comparing the textual out of int/double, be sure to print the double with sufficient precision to see if it is 100.000000 or just near 100.000000 or in hex to remove all doubt.
printf("%d %d\n" , x , y);
// printf("%f %f\n" , k , l);
// Is it the FP number just less than 100?
printf("%.17e %.17e\n" , k , l); // maybe 9.99999999999999858e+01
printf("%a %a\n" , k , l); // maybe 0x1.8ffffffffffff0000p+6
Why is the output coming out to be different. ? (in the original code)
C does not specify the accuracy of most <math.h> functions. The following are all compliant results.
// Higher quality functions return 100.0
pow(10,2) --> 100.0
// Lower quality and/or faster one may return nearby results
pow(10,2) --> 100.0000000000000142...
pow(10,2) --> 99.9999999999999857...
Assigning a floating point (FP) number to an int simple drops the fraction regardless of how close the fraction is to 1.0
When converting FP to an integer, better to control the conversion and round to cope with minor computational differences.
// long int lround(double x);
long i = lround(pow(10.0,2.0));
You're not the first to find this. Here's a discussion form 2013:
pow() cast to integer, unexpected result
I'm speculating that the assembly code produced by the tcc guys is causing the second value to be rounded down after calculating a result that is REALLY close to 100.
Like mikijov said in that historic post, looks like the bug has been fixed.
As others have mentioned, Code 2 returns 99 due to floating point truncation. The reason why Code 1 returns a different and correct answer is because of a libc optimization.
When the power is a small positive integer, it is more efficient to perform the operation as repeated multiplication. The simpler path removes roundoff. Since this is inlined you don't see function calls being made.
You've fooled it into thinking that the inputs are real and so it gives an approximate answer, which happens to be slightly under 100, e.g. 99.999999 that is then truncated to 99.

double-precision numbers in inline assembly (GCC, IA-32)

I'm just starting to learn assembly and I want to round a floating-point value using a specified rounding mode. I've tried to implement this using fstcw, fldcw, and frndint.
Right now I get a couple of errors:
~ $ gc a02p
gcc -Wall -g a02p.c -o a02p
a02p.c: In function `roundD':
a02p.c:33: error: parse error before '[' token
a02p.c:21: warning: unused variable `mode'
~ $
I'm not sure if I am even doing this right at all. I don't want to use any predefined functions. I want to use GCC inline assembly.
This is the code:
#include <stdio.h>
#include <stdlib.h>
#define PRECISION 3
#define RND_CTL_BIT_SHIFT 10
// floating point rounding modes: IA-32 Manual, Vol. 1, p. 4-20
typedef enum {
ROUND_NEAREST_EVEN = 0 << RND_CTL_BIT_SHIFT,
ROUND_MINUS_INF = 1 << RND_CTL_BIT_SHIFT,
ROUND_PLUS_INF = 2 << RND_CTL_BIT_SHIFT,
ROUND_TOWARD_ZERO = 3 << RND_CTL_BIT_SHIFT
} RoundingMode;
double roundD (double n, RoundingMode roundingMode)
{
short c;
short mode = (( c & 0xf3ff) | (roundingMode));
asm("fldcw %[nIn] \n"
"fstcw %%eax \n" // not sure why i would need to store the CW
"fldcw %[modeIn] \n"
"frndint \n"
"fistp %[nOut] \n"
: [nOut] "=m" (n)
: [nIn] "m" (n)
: [modeIn] "m" (mode)
);
return n;
}
int main (int argc, char **argv)
{
double n = 0.0;
if (argc > 1)
n = atof(argv[1]);
printf("roundD even %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_NEAREST_EVEN));
printf("roundD down %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_MINUS_INF));
printf("roundD up %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_PLUS_INF));
printf("roundD zero %.*f = %.*f\n",
PRECISION, n, PRECISION, roundD(n, ROUND_TOWARD_ZERO));
return 0;
}
Am I even remotely close to getting this right?
A better process is to write a simple function that rounds a floating point value. Next, instruct your compiler to print an assembly listing for the function. You may want to put the function in a separate file.
This process will show you the calling and exiting conventions used by the compiler. By placing the function in a separate file, you won't have to build other files. Also, it will give you the opportunity to replace the C language function with an assembly language function.
Although inline assembly is supported, I prefer to replace an entire function in assembly language and not use inline assembly (inline assembly isn't portable, so the source will have to be changed when porting to a different platform).
GCC's inline assembler syntax is arcane to say the least, and I do not claim to be an expert, but when I have used it I used this howto guide. In all examples all template markers are of the form %n where n is a number, rather then the %[ttt] form that you have used.
I also note that the line numbers reported in your error messages do not seem to correspond with the code you posted. So I wonder if they are in fact for this exact code?

floating point - absolute value - inline assembly - edited new code

I wrote a function named absD that i want to return the absolute value of its argument..
I am using GCC inline assembly with cygwin..
I dont see why its not working. i m loading into memory. then into st(0)
where i am using fabs - absolute value. Do i have to allocate memory?
I am trying to learn assembly with C here so please be nice. Please give me good help.
Thank you
heres the code and then the error:
#include <stdio.h>
#include <stdlib.h>
#define PRECISION 3
double absD (double n)
{
asm(
"fldl %[nIn]\n"
"fabs\n"
"fstpl %[nOut]\n"
: [nOut] "=m" (n)
: [nIn] "m" (n)
);
return n;
}
int main (int argc, char **argv)
{
double n = 0.0;
printf("Absolute value\n");
if (argc > 1)
n = atof(argv[1]);
printf("abs(%.*f) = %.*f\n", PRECISION, n, PRECISION, absD(n));
return 0;
}
here is the output:
~ $ gc a3
gcc -Wall -g a3.c -o a3
~ $ ./a3
Absolute value
abs(0.000) = 0.000
~ $
Not outputing its absolute value...
Thank you..
It is completely working..!! You are just forgetting to put values to argv. You can run the program with something like this:
./a3 -1.3
and it should return 1.3
you were done before posting it here...
fld (%eax) means "load a float from the value at address %eax". Obviously, the contents of %eax are a double, and not a pointer to a float, which is why you segfault.
Since the input is already on the stack (thus it has an address), there's no need to jump through hoops moving things around.
double absD(double input) {
double output;
asm(
"fldl %[input]\n"
"fabs\n"
"fstpl %[output]\n"
: [output] "=m" (output)
: [input] "m" (input)
);
return output;
}
Also, your printf format is wrong: %f means float, but you're giving it a double; you want to use %g.

Can I compute pow(10,x) at compile-time in c?

Is it possible to compute pow(10,x) at compile time?
I've got a processor without floating point support and slow integer division. I'm trying to perform as many calculations as possible at compile time. I can dramatically speed up one particular function if I pass both x and C/pow(10,x) as arguments (x and C are always constant integers, but they are different constants for each call). I'm wondering if I can make these function calls less error prone by introducing a macro which does the 1/pow(10,x) automatically, instead of forcing the programmer to calculate it?
Is there a pre-processor trick? Can I force the compiler optimize out the library call?
There are very few values possible before you overflow int (or even long). For clarities sake, make it a table!
edit: If you are using floats (looks like you are), then no it's not going to be possible to call the pow() function at compile time without actually writing code that runs in the make process and outputs the values to a file (such as a header file) which is then compiled.
GCC will do this at a sufficiently high optimization level (-O1 does it for me). For example:
#include <math.h>
int test() {
double x = pow(10, 4);
return (int)x;
}
Compiles at -O1 -m32 to:
.file "test.c"
.text
.globl test
.type test, #function
test:
pushl %ebp
movl %esp, %ebp
movl $10000, %eax
popl %ebp
ret
.size test, .-test
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",#progbits
This works without the cast as well - of course, you do get a floating-point load instruction in there, as the Linux ABI passes floating point return values in FPU registers.
You can do it with Boost.Preprocessor:
http://www.boost.org/doc/libs/1_39_0/libs/preprocessor/doc/index.html
Code:
#include <boost/preprocessor/repeat.hpp>
#define _TIMES_10(z, n, data) * 10
#define POW_10(n) (1 BOOST_PP_REPEAT(n, _TIMES_10, _))
int test[4] = {POW_10(0), POW_10(1), POW_10(2), POW_10(3)};
Actually, by exploiting the C preprocessor, you can get it to compute C pow(10, x) for any real C and integral x. Observe that, as #quinmars noted, C allows you to use scientific syntax to express numerical constants:
#define myexp 1.602E-19 // == 1.602 * pow(10, -19)
to be used for constants. With this in mind, and a bit of cleverness, we can construct a preprocessor macro that takes C and x and combine them into an exponentiation token:
#define EXP2(a, b) a ## b
#define EXP(a, b) EXP2(a ## e,b)
#define CONSTPOW(C,x) EXP(C, x)
This can now be used as a constant numerical value:
const int myint = CONSTPOW(3, 4); // == 30000
const double myfloat = CONSTPOW(M_PI, -2); // == 0.03141592653
You can use the scientific notation for floating point values which is part of the C language. It looks like that:
e = 1.602E-19 // == 1.602 * pow(10, -19)
The number before the E ( the E maybe capital or small 1.602e-19) is the fraction part where as the (signed) digit sequence after the E is the exponent part. By default the number is of the type double, but you can attach a floating point suffix (f, F, l or L) if you need a float or a long double.
I would not recommend to pack this semantic into a macro:
It will not work for variables, floating point values, etc.
The scientific notation is more readable.
Actually, you have M4 which is a pre-processor way more powerful than the GCC’s. A main difference between those two is GCC’s is not recursive whereas M4 is. It makes possible things like doing arithmetic at compile-time (and much more!). The below code sample is what you would like to do, isn’t it? I made it bulky in a one-file source; but I usually put M4's macro definitions in separate files and tune my Makefile rules. This way, your code is kept from ugly intrusive M4 definitions into the C source code I've done here.
$ cat foo.c
define(M4_POW_AUX, `ifelse($2, 1, $1, `eval($1 * M4_POW_AUX($1, decr($2)))')')dnl
define(M4_POW, `ifelse($2, 0, 1, `M4_POW_AUX($1, $2)')')dnl
#include <stdio.h>
int main(void)
{
printf("2^0 = %d\n", M4_POW(2, 0));
printf("2^1 = %d\n", M4_POW(2, 1));
printf("2^4 = %d\n", M4_POW(2, 4));
return 0;
}
The command line to compile this code sample uses the ability of GCC and M4 to read from the standard input.
$ cat foo.c | m4 - | gcc -x c -o m4_pow -
$ ./m4_pow
2^0 = 1
2^1 = 2
2^4 = 16
Hope this help!
If you just need to use the value at compile time, use the scientific notation like 1e2 for pow(10, 2)
If you want to populate the values at compile time and then use them later at runtime then simply use a lookup table because there are only 23 different powers of 10 that are exactly representable in double precision
double POW10[] = {1., 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
You can get larger powers of 10 at runtime from the above lookup table to quickly get the result without needing to multiply by 10 again and again, but the result is just a value close to a power of 10 like when you use 10eX with X > 22
double pow10(int x)
{
if (x > 22)
return POW10[22] * pow10(x - 22);
else if (x >= 0)
return POW10[x];
else
return 1/pow10(-x);
}
If negative exponents is not needed then the final branch can be removed.
You can also reduce the lookup table size further if memory is a constraint. For example by storing only even powers of 10 and multiply by 10 when the exponent is odd, the table size is now only a half.
Recent versions of GCC ( around 4.3 ) added the ability to use GMP and MPFR to do some compile-time optimizations by evaluating more complex functions that are constant. That approach leaves your code simple and portable, and trust the compiler to do the heavy lifting.
Of course, there are limits to what it can do. Here's a link to the description in the changelog, which includes a list of functions that are supported by this. 'pow' is one them.
Unfortunately, you can't use the preprocessor to precalculate library calls. If x is integral you could write your own function, but if it's a floating-point type I don't see any good way to do this.
bdonlan's replay is spot on but keep in mind that you can perform nearly any optimization you chose on the compile box provided you are willing to parse and analyze the code in your own custom preprocessor. It is a trivial task in most version of unix to override the implicit rules that call the compiler to call a custom step of your own before it hits the compiler.

Resources