Question regarding libm

Jan-Benedict Glaw jbglaw at lug-owl.de
Fri Sep 30 09:07:05 UTC 2005


On Fri, 2005-09-30 08:32:51 +0200, Jan-Benedict Glaw <jbglaw at lug-owl.de> wrote:

> Will a patch adding a config option for this be accepted?

Hi all!

This is a first patch. It not only contains the initial config option,
but also some whitespace cleanups. (If you want me to submit is in two
different patches, that's no problem.)

First of all, here's my quick'n'dirty test program (I don't yet have
installed headers or a gcc that emits a correct -static linker command
line, so I do it all on my own):

---------------------- >8 =======================================
extern int _exit (int exit_value);
extern int printf (const char *format, ...);
extern double sin (double value_in);

extern void * fopen (const char *filename, const char *mode);
extern int fprintf (void *FP, char *format, ...);
extern void fclose (void *FP);
extern void fflush (void *FP);

static double sin_in[] = {
	0.1,
	0.2,
	0.5,
	1.0,
	1.3,
};
static double sin_out[] = {
	.09983341664682815230,
	.19866933079506121545,
	.47942553860420300027,
	.84147098480789650665,
	.96355818541719296470
};

int a;
int b = 1;

int
main (int argc, char *argv[])
{
	int c;
	int d = 3;
	float foo = 4.0;
	float bar = 17.3;
	float baz = foo * bar;
	double dfoo = 4.0;
	double dbar = 17.3;
	double dbaz = dfoo * dbar;
	double temp_double;
	int ret;
	int i;
	void *FP;

	for (c = b; c < d; c++) {
		1;
	}
#if 0
	for (;;)
		;
#endif
	FP = fopen ("main_vax.out", "w+");

	fprintf (FP, "Hello %s!\n", "World");
	fflush (FP);
	ret = fprintf (FP, "Hello float: %f * %f = %f!\n", foo, bar, baz);
	fflush (FP);
	fprintf (FP, "ret = %d\n", ret);
	fflush (FP);
	ret = fprintf (FP, "Hello double: %lf * %lf = %lf!\n", dfoo, dbar, dbaz);
	fflush (FP);
	fprintf (FP, "ret = %d\n", ret);
	fflush (FP);

	for (i = 0; i < argc; i++) {
		fprintf (FP, "argv[%d] = \"%s\"\n", i, argv[i]);
		fflush (FP);
	}

	for (i = 0; i < 5; i++) {
		fprintf (FP, "sin (%lf) = ", sin_in[i]); fflush (FP);
		temp_double = sin (sin_in[i]);
		fprintf (FP, "%lf, should be ", temp_double); fflush (FP);
		fprintf (FP, "%lf, d = ", sin_out[i]); fflush (FP);
		fprintf (FP, "%lf\n", sin_out[i] - sin (sin_in[i])); fflush (FP);
	}

	_exit (6);
}
============================== 8< -----------------------------------------

Compilation and linking looks like this:

---------------------- >8 =======================================
#!/bin/sh

VAX_DIR="`ls -d /home/jbglaw/vax-linux/scm/build-????????-??????-vax-linux-uclibc | sort | tail -n1`"

${VAX_DIR}/install/usr/bin/vax-linux-uclibc-gcc -c -o main_vax.o main.c
${VAX_DIR}/install/usr/bin/vax-linux-uclibc-ld                                  \
        -static -o main_vax                                                     \
        ${VAX_DIR}/src/uclibc/lib/crt1.o                                        \
        ${VAX_DIR}/src/uclibc/lib/crti.o                                        \
        ${VAX_DIR}/install/usr/lib/gcc/vax-linux-uclibc/4.1.0/crtbeginT.o       \
        main_vax.o                                                              \
        --start-group ${VAX_DIR}/src/uclibc/lib/libc.a                          \
        ${VAX_DIR}/src/uclibc/lib/libm.a                                        \
        ${VAX_DIR}/install/usr/lib/gcc/vax-linux-uclibc/4.1.0/libgcc.a          \
        --end-group ${VAX_DIR}/src/uclibc/lib/crtn.o

${VAX_DIR}/install/usr/bin/vax-linux-uclibc-objdump -S -d main_vax > main_vax.dump
============================== 8< -----------------------------------------

So my little test program does some fprintf()s and computes some sine
values, comparing it to given values (got those mannually out of 'bc -l')

With the following patch applied, I do get this result in the output
file:

---------------------- >8 =======================================
Hello World!
Hello float: 4.000000 * 17.299999 = 69.199997!
ret = 47
Hello double: 4.000000 * 17.300000 = 69.200000!
ret = 48
argv[0] = "./main_vax"
sin (0.100000) = 0.000000, should be 0.099833, d = 0.099833
sin (0.200000) = 0.000000, should be 0.198669, d = 0.198669
sin (0.500000) = 0.500000, should be 0.479426, d = -0.020574
sin (1.000000) = 0.841471, should be 0.841471, d = -0.000000
sin (1.300000) = 
============================== 8< -----------------------------------------

So for now, the sine values are waaaay off, and it still crashes. I'll
probably look into it at some time, but first I'll concentrate on
libc and try to build us some more up-to-date userland (first fixing
the compiler to ease the linking....).

Here's finally the patch:


diff -Nurp src-uclibc-fresh/extra/Configs/Config.in.arch src-uclibc-hacked/extra/Configs/Config.in.arch
--- src-uclibc-fresh/extra/Configs/Config.in.arch	2005-06-05 18:39:50.000000000 +0200
+++ src-uclibc-hacked/extra/Configs/Config.in.arch	2005-09-30 10:14:36.000000000 +0200
@@ -28,8 +28,8 @@ config ARCH_HAS_MMU
 	default y
 	depends !ARCH_HAS_NO_MMU
 	help
-	  If your target CPU does not have a memory management unit (MMU), 
-	  then answer N here.  Normally, Linux runs on systems with an MMU.  
+	  If your target CPU does not have a memory management unit (MMU),
+	  then answer N here.  Normally, Linux runs on systems with an MMU.
 	  If you are building a uClinux system, answer N.
 
 	  Most people will answer Y.
@@ -40,13 +40,24 @@ config UCLIBC_HAS_FLOATS
 	help
 	  This option allows you to entirely omit all floating point number
 	  support from uClibc.  This will cause floating point functions like
-	  strtod() to be omitted from uClibc.  Other floating point functions, 
-	  such as printf() and scanf() will still be included in the library, 
+	  strtod() to be omitted from uClibc.  Other floating point functions,
+	  such as printf() and scanf() will still be included in the library,
 	  but will not contain support for floating point numbers.
 
 	  Answering N to this option can reduce the size of uClibc.  Most people
 	  will answer Y.
 
+config TARGET_HAS_NEGATIVE_ZERO_FLOATS
+	bool "    Target CPU differs between +0 and -0"
+	default y
+	depends on UCLIBC_HAS_FLOATS
+	help
+	  If your target CPU can differ +0 and -0 (IEEE floating point
+	  support works that way), then you should enable this option.
+
+	  Most people will answer Y, because nearly all CPUs do use IEEE
+	  floating point support.
+
 config HAS_FPU
 	bool "Target CPU has a floating point unit (FPU)"
 	depends on UCLIBC_HAS_FLOATS
@@ -77,7 +88,7 @@ config DO_C99_MATH
 	  listed as part of the traditional POSIX/IEEE 1003.1b-1993 standard.
 	  Leaving this option set to N will save around 35k on an x86 system.
 
-	  If your applications require the newer C99 math library functions, 
+	  If your applications require the newer C99 math library functions,
 	  then answer Y.
 
 config KERNEL_SOURCE
diff -Nurp src-uclibc-fresh/libc/stdio/_fpmaxtostr.c src-uclibc-hacked/libc/stdio/_fpmaxtostr.c
--- src-uclibc-fresh/libc/stdio/_fpmaxtostr.c	2005-07-30 22:29:22.000000000 +0200
+++ src-uclibc-hacked/libc/stdio/_fpmaxtostr.c	2005-09-30 10:20:42.000000000 +0200
@@ -17,7 +17,7 @@ typedef size_t (__fp_outfunc_t)(FILE *fp
 
 /* Copyright (C) 2000, 2001, 2003      Manuel Novoa III
  *
- * Function: 
+ * Function:
  *
  *     size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info,
  *                         __fp_outfunc_t fp_outfunc);
@@ -183,7 +183,7 @@ static const __fpmax_t exp16_table[] = {
 #if FPMAX_MAX_EXP >= 16384
 	0x1.0p16384L
 #endif
-#if FPMAX_MAX_EXP >= 32768 
+#if FPMAX_MAX_EXP >= 32768
 #error unsupported FPMAX_MAX_EXP.  please increase table
 #endif
 };
@@ -275,7 +275,7 @@ ssize_t _fpmaxtostr(FILE * fp, __fpmax_t
 	}
 
 	if (x == 0) {				/* Handle 0 now to avoid false positive. */
-#if 1
+#ifdef __TARGET_HAS_NEGATIVE_ZERO_FLOATS__
 		if (zeroisnegative(x)) { /* Handle 'signed' zero. */
 			*sign_str = '-';
 		}
@@ -323,14 +323,14 @@ ssize_t _fpmaxtostr(FILE * fp, __fpmax_t
 			base = 16;
 		} else {
 			lower_bnd = 1e8;
-			/* 		upper_bnd = 1e9; */
+			/*		upper_bnd = 1e9; */
 			power_table = exp10_table;
 			exp = DIGITS_PER_BLOCK - 1;
 			i = EXP10_TABLE_SIZE;
 			j = EXP10_TABLE_MAX;
-			/* 		dpb = DIGITS_PER_BLOCK; */
-			/* 		ndb = NUM_DIGIT_BLOCKS; */
-			/* 		base = 10; */
+			/*		dpb = DIGITS_PER_BLOCK; */
+			/*		ndb = NUM_DIGIT_BLOCKS; */
+			/*		base = 10; */
 		}
 
 
@@ -406,7 +406,7 @@ ssize_t _fpmaxtostr(FILE * fp, __fpmax_t
 	if (mode < 'a') {
 		*exp_buf -= ('a' - 'A'); /* e->E and p->P */
 		mode += ('a' - 'A');
-	} 
+	}
 
 	o_mode = mode;
 	if ((mode == 'g') && (preci > 0)){
@@ -446,7 +446,7 @@ ssize_t _fpmaxtostr(FILE * fp, __fpmax_t
 #ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__
 	if ((mode|0x20) == 'a') {
 		char *q;
-			
+
 		for (q = e ; *q ; --q) {
 			if (*q > '9') {
 				*q += (*exp_buf - ('p' - 'a') - '9' - 1);
@@ -694,12 +694,12 @@ ssize_t _fpmaxtostr(FILE * fp, __fpmax_t
 
 			cnt += num_groups * tslen; /* Adjust count now for sep chars. */
 
-/* 			printf("\n"); */
+/*			printf("\n"); */
 			do {
 				if (!blk) {		/* Initial group could be 0 digits long! */
 					blk = nblk2;
 				} else if (len >= blk) { /* Enough digits for a group. */
-/* 					printf("norm:  len=%d blk=%d  \"%.*s\"\n", len, blk, blk, gp); */
+/*					printf("norm:  len=%d blk=%d  \"%.*s\"\n", len, blk, blk, gp); */
 					if (fp_outfunc(fp, *ppc, blk, (intptr_t) gp) != blk) {
 						return -1;
 					}
@@ -709,9 +709,9 @@ ssize_t _fpmaxtostr(FILE * fp, __fpmax_t
 					}
 					len -= blk;
 				} else {		/* Transition to 0s. */
-/* 					printf("trans: len=%d blk=%d  \"%.*s\"\n", len, blk, len, gp); */
+/*					printf("trans: len=%d blk=%d  \"%.*s\"\n", len, blk, len, gp); */
 					if (len) {
-/* 						printf("len\n"); */
+/*						printf("len\n"); */
 						if (fp_outfunc(fp, *ppc, len, (intptr_t) gp) != len) {
 							return -1;
 						}
@@ -719,7 +719,7 @@ ssize_t _fpmaxtostr(FILE * fp, __fpmax_t
 					}
 
 					if (ppc[3] == FPO_ZERO_PAD) { /* Need to group 0s */
-/* 						printf("zeropad\n"); */
+/*						printf("zeropad\n"); */
 						cnt += ppc[1];
 						ppc += 3;
 						gp = (const char *) ppc[2];
@@ -742,7 +742,7 @@ ssize_t _fpmaxtostr(FILE * fp, __fpmax_t
 				}
 				blk = nblk2;
 
-/* 				printf("num_groups=%d   blk=%d\n", num_groups, blk); */
+/*				printf("num_groups=%d   blk=%d\n", num_groups, blk); */
 
 			} while (1);
 		} else



Finally, are you interested in getting the VAX bits into your tree?
Personally, I'd be interested in supplying it, maybe getting
write-access to the VAX specific bits at some time, too.

Thanks, JBG

-- 
Jan-Benedict Glaw       jbglaw at lug-owl.de    . +49-172-7608481             _ O _
"Eine Freie Meinung in  einem Freien Kopf    | Gegen Zensur | Gegen Krieg  _ _ O
 für einen Freien Staat voll Freier Bürger"  | im Internet! |   im Irak!   O O O
ret = do_actions((curr | FREE_SPEECH) & ~(NEW_COPYRIGHT_LAW | DRM | TCPA));
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://lists.busybox.net/pipermail/uclibc/attachments/20050930/86e5a0cf/attachment-0002.pgp 


More information about the uClibc mailing list