Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Sep 2003 00:53:29 +0200 (CEST)
From:      Stefan Farfeleder <stefan@fafoe.narf.at>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        stefan@fafoe.narf.at
Subject:   standards/56906: Several math(3) functions fail to set errno on a domain error
Message-ID:  <20030915225329.95B30498@frog.fafoe.narf.at>
Resent-Message-ID: <200309152300.h8FN0fd0042682@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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@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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030915225329.95B30498>