standards/56906: Several math(3) functions fail to set errno on a
domain error
Stefan Farfeleder
stefan at fafoe.narf.at
Mon Sep 15 16:00:43 PDT 2003
>Number: 56906
>Category: standards
>Synopsis: Several math(3) functions fail to set errno on a domain error
>Confidential: no
>Severity: serious
>Priority: low
>Responsible: freebsd-standards
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Mon Sep 15 16:00:34 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator: Stefan Farfeleder
>Release: FreeBSD 5.1-CURRENT i386
>Organization:
>Environment:
System: FreeBSD frog.fafoe.narf.at 5.1-CURRENT FreeBSD 5.1-CURRENT #8: Thu Sep 11 14:09:49 CEST 2003 freebsd at frog.fafoe.narf.at:/freebsd/frog/obj/freebsd/frog/src/sys/FROG i386
>Description:
ISO C90 says that errno must be set to EDOM if a domain error occurs.
The cases where a domain error definitely has to occur are:
acos(x) if |x| > 1,
asin(x) if |x| > 1,
log(x) if x < 0,
log10(x) if x < 0,
sqrt(x) if x < 0 and
pow(x, y) if x < 0 && y not an integer or if x == 0 && y <= 0.
FreeBSD's libm fails to set errno on each of these cases even though the
man pages of acos, asin and sqrt claim conformance to C89/90.
>How-To-Repeat:
This program should set errno to EDOM seven times but it currently only
prints zeroes.
%%
#include <errno.h>
#include <math.h>
#include <stdio.h>
#define TEST1(func, arg) { func, arg, #func }
#define TEST2(func, arg1, arg2) { func, arg1, arg2, #func }
struct {
double (*func)(double);
double arg;
char *name;
} test1[] = {
TEST1(acos, 2),
TEST1(asin, 2),
TEST1(log, -1),
TEST1(log10, -1),
TEST1(sqrt, -1),
};
struct {
double (*func)(double, double);
double arg1;
double arg2;
char *name;
} test2[] = {
TEST2(pow, -1, 0.5),
TEST2(pow, 0, -1),
};
int
main(void)
{
int i;
for (i = 0; i < sizeof(test1) / sizeof(*test1); i++) {
errno = 0;
test1[i].func(test1[i].arg);
printf("%s(%f): errno = %d\n", test1[i].name, test1[i].arg,
errno);
}
for (i = 0; i < sizeof(test2) / sizeof(*test2); i++) {
errno = 0;
test2[i].func(test2[i].arg1, test2[i].arg2);
printf("%s(%f, %f): errno = %d\n", test2[i].name,
test2[i].arg1, test2[i].arg2, errno);
}
return (0);
}
%%
>Fix:
Compiling msun with -D_POSIX_MODE fixes the setting of errno. I have no
idea if this breaks other parts of libm though; there don't seem to be
any regression tests for libm.
--- msun-Makefile.diff begins here ---
Index: src/lib/msun/Makefile
===================================================================
RCS file: /usr/home/ncvs/src/lib/msun/Makefile,v
retrieving revision 1.35
diff -u -r1.35 Makefile
--- src/lib/msun/Makefile 17 Aug 2003 08:28:46 -0000 1.35
+++ src/lib/msun/Makefile 15 Sep 2003 21:50:12 -0000
@@ -63,7 +63,7 @@
.PATH: ${.CURDIR}/man
.PATH: ${.CURDIR}/src
-CFLAGS+= -D_IEEE_LIBM
+CFLAGS+= -D_POSIX_MODE
LIB= m
SHLIBDIR?= /lib
--- msun-Makefile.diff ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-standards
mailing list