Module Name:    src
Committed By:   martin
Date:           Wed Oct  2 12:46:13 UTC 2024

Modified Files:
        src/distrib/sets/lists/debug [netbsd-10]: mi
        src/distrib/sets/lists/tests [netbsd-10]: mi
        src/lib/libm/src [netbsd-10]: s_remquo.c
        src/tests/lib/libm [netbsd-10]: Makefile
Added Files:
        src/tests/lib/libm [netbsd-10]: t_remquo.c

Log Message:
Pull up following revision(s) (requested by gdt in ticket #912):

        distrib/sets/lists/debug/mi: revision 1.449
        lib/libm/src/s_remquo.c: revision 1.3
        lib/libm/src/s_remquo.c: revision 1.4
        distrib/sets/lists/tests/mi: revision 1.1339
        tests/lib/libm/t_remquo.c: revision 1.1
        tests/lib/libm/t_remquo.c: revision 1.2
        tests/lib/libm/Makefile: revision 1.51

tests: Add test for remquo

This test currently fails, because remquo has bugs.  (A bugfix will be
committed soon.)  Test vectors derived from results from code by
Charles Karney in GeodesicLib/proj, and manually inspected.

t_remquo: Work around missing remquo(3) for vax
Part of PR port-vax/57881

libm/remquo: Fix bug where wrong quotient was returned

Fix taken from FreeBSD:
  https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=166463
  
https://cgit.freebsd.org/src/commit/lib/msun/src/s_remquo.c?id=1cbd288942b08217e99bf889e0967895d53af00c

FreeBSD commit message:
  Fix a bug in remquo{,f,l}, in which the quotient didn't always have the
  correct sign when the remainder was 0.
  Fix a separate bug in remquo alone, in which the remainder and
  quotient were both off by a bit in certain cases involving subnormal
  remainders.
  The bugs affected all platforms except amd64 and i386, on which the
  routines are implemented in assembly.

(On NetBSD, this bug manifests on amd64.)

libm/remquo: Fix bug where remquo returned wrong sign of quo
ISO C requires that quo be congruent to the quotient mod 2^k and have
a particular sign.  The current code can return 0 when it should be
negative.
Because the code chooses k=31 (for the requirement of congruence
modulo 2^k), the only value available (in ILP32 or LP64) that is
negative and congruent to 0 is 0x80000000.  In the specific case of
wanting "-0", return 0x80000000.
Resolves t_remquo test failure.


To generate a diff of this commit:
cvs rdiff -u -r1.394.2.9 -r1.394.2.10 src/distrib/sets/lists/debug/mi
cvs rdiff -u -r1.1238.2.11 -r1.1238.2.12 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.1 -r1.1.56.1 src/lib/libm/src/s_remquo.c
cvs rdiff -u -r1.48 -r1.48.2.1 src/tests/lib/libm/Makefile
cvs rdiff -u -r0 -r1.2.2.2 src/tests/lib/libm/t_remquo.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/debug/mi
diff -u src/distrib/sets/lists/debug/mi:1.394.2.9 src/distrib/sets/lists/debug/mi:1.394.2.10
--- src/distrib/sets/lists/debug/mi:1.394.2.9	Thu Sep  5 09:22:43 2024
+++ src/distrib/sets/lists/debug/mi	Wed Oct  2 12:46:13 2024
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.394.2.9 2024/09/05 09:22:43 martin Exp $
+# $NetBSD: mi,v 1.394.2.10 2024/10/02 12:46:13 martin Exp $
 ./etc/mtree/set.debug                           comp-sys-root
 ./usr/lib					comp-sys-usr		compatdir
 ./usr/lib/i18n/libBIG5_g.a			comp-c-debuglib		debuglib,compatfile
@@ -2319,6 +2319,7 @@
 ./usr/libdata/debug/usr/tests/lib/libm/t_modf.debug			tests-lib-debug		debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libm/t_pow.debug			tests-lib-debug		debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libm/t_precision.debug		tests-lib-debug		debug,atf,compattestfile
+./usr/libdata/debug/usr/tests/lib/libm/t_remquo.debug			tests-lib-debug		debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libm/t_round.debug			tests-lib-debug		debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libm/t_scalbn.debug			tests-lib-debug		debug,atf,compattestfile
 ./usr/libdata/debug/usr/tests/lib/libm/t_sin.debug			tests-lib-debug		debug,atf,compattestfile

Index: src/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.1238.2.11 src/distrib/sets/lists/tests/mi:1.1238.2.12
--- src/distrib/sets/lists/tests/mi:1.1238.2.11	Thu Sep  5 09:27:13 2024
+++ src/distrib/sets/lists/tests/mi	Wed Oct  2 12:46:13 2024
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1238.2.11 2024/09/05 09:27:13 martin Exp $
+# $NetBSD: mi,v 1.1238.2.12 2024/10/02 12:46:13 martin Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -3927,6 +3927,7 @@
 ./usr/tests/lib/libm/t_modf				tests-lib-tests		compattestfile,atf
 ./usr/tests/lib/libm/t_pow				tests-lib-tests		compattestfile,atf
 ./usr/tests/lib/libm/t_precision			tests-lib-tests		compattestfile,atf
+./usr/tests/lib/libm/t_remquo				tests-lib-tests		compattestfile,atf
 ./usr/tests/lib/libm/t_round				tests-lib-tests		compattestfile,atf
 ./usr/tests/lib/libm/t_scalbn				tests-lib-tests		compattestfile,atf
 ./usr/tests/lib/libm/t_sin				tests-lib-tests		compattestfile,atf

Index: src/lib/libm/src/s_remquo.c
diff -u src/lib/libm/src/s_remquo.c:1.1 src/lib/libm/src/s_remquo.c:1.1.56.1
--- src/lib/libm/src/s_remquo.c:1.1	Sun Feb  6 01:53:38 2011
+++ src/lib/libm/src/s_remquo.c	Wed Oct  2 12:46:13 2024
@@ -50,7 +50,7 @@ remquo(double x, double y, int *quo)
 		goto fixup;	/* |x|<|y| return x or x-y */
 	    }
 	    if(lx==ly) {
-		*quo = 1;
+		*quo = (sxy ? -1 : 1);
 		return Zero[(u_int32_t)sx>>31];	/* |x|=|y| return x*0*/
 	    }
 	}
@@ -113,6 +113,7 @@ remquo(double x, double y, int *quo)
 
     /* convert back to floating value and restore the sign */
 	if((hx|lx)==0) {			/* return sign(x)*0 */
+	    q &= 0x7fffffff;
 	    *quo = (sxy ? -q : q);
 	    return Zero[(u_int32_t)sx>>31];
 	}
@@ -128,9 +129,9 @@ remquo(double x, double y, int *quo)
 		lx = (lx>>n)|((u_int32_t)hx<<(32-n));
 		hx >>= n;
 	    } else if (n<=31) {
-		lx = (hx<<(32-n))|(lx>>n); hx = sx;
+		lx = (hx<<(32-n))|(lx>>n); hx = 0;
 	    } else {
-		lx = hx>>(n-32); hx = sx;
+		lx = hx>>(n-32); hx = 0;
 	    }
 	}
 fixup:
@@ -149,5 +150,12 @@ fixup:
 	SET_HIGH_WORD(x,hx^sx);
 	q &= 0x7fffffff;
 	*quo = (sxy ? -q : q);
+	/*
+	 * If q is 0 and we need to return negative, we have to choose
+	 * the largest negative number (in 32 bits) because it is the
+	 * only value that is negative and congruent to 0 mod 2^31.
+	 */
+	if (q == 0 && sxy)
+	  *quo = 0x80000000;
 	return x;
 }

Index: src/tests/lib/libm/Makefile
diff -u src/tests/lib/libm/Makefile:1.48 src/tests/lib/libm/Makefile:1.48.2.1
--- src/tests/lib/libm/Makefile:1.48	Sat Aug 27 08:31:58 2022
+++ src/tests/lib/libm/Makefile	Wed Oct  2 12:46:13 2024
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.48 2022/08/27 08:31:58 christos Exp $
+# $NetBSD: Makefile,v 1.48.2.1 2024/10/02 12:46:13 martin Exp $
 
 .include <bsd.own.mk>
 
@@ -37,6 +37,7 @@ TESTS_C+=	t_log
 TESTS_C+=	t_modf
 TESTS_C+=	t_pow
 TESTS_C+=	t_precision
+TESTS_C+=	t_remquo
 TESTS_C+=	t_round
 TESTS_C+=	t_scalbn
 TESTS_C+=	t_sin

Added files:

Index: src/tests/lib/libm/t_remquo.c
diff -u /dev/null src/tests/lib/libm/t_remquo.c:1.2.2.2
--- /dev/null	Wed Oct  2 12:46:13 2024
+++ src/tests/lib/libm/t_remquo.c	Wed Oct  2 12:46:13 2024
@@ -0,0 +1,126 @@
+/* $NetBSD: t_remquo.c,v 1.2.2.2 2024/10/02 12:46:13 martin Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen and Greg Troxel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <atf-c.h>
+#include <float.h>
+#include <math.h>
+
+/*
+ * remquo(3)
+ */
+ATF_TC(remquo_args);
+ATF_TC_HEAD(remquo_args, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Test some selected arguments");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+	ATF_TP_ADD_TC(tp, remquo_args);
+
+	return atf_no_error();
+}
+
+#ifdef __vax__
+
+ATF_TC_BODY(remquo_args, tc)
+{
+        atf_tc_expect_fail("PR 57881: vax libm is missing various symbols");
+        atf_tc_fail("missing remquo on vax");
+}
+
+#else /* !__vax__ */
+
+static const struct {
+	double		x;
+	double		y;
+	double		r;	/* expected */
+	int		quo;	/* expected */
+} args[] = {
+	{ -135.0,	-90.0,		45.0,	2 },
+	{ -45.0,	-90.0,		-45.0,	8 },
+	{ 45.0,		-90.0,		45.0,	-8 },
+	{ 135.0,	-90.0,		-45.0,	-2 },
+	{ -180.0,	90.0,		-0.0,	-2 },
+	{ -135.0,	90.0,		45.0,	-2 },
+	{ -90.0,	90.0,		-0.0,	-1 },
+	{ -45.0,	90.0,		-45.0,	-8 },
+	{ 0.0,		90.0,		0.0,	0 },
+	{ 45.0,		90.0,		45.0,	8 },
+	{ 90.0,		90.0,		0.0,	1 },
+	{ 135.0,	90.0,		-45.0,	2 },
+	{ 180.0,	90.0,		0.0,	2 },
+};
+
+ATF_TC_BODY(remquo_args, tc)
+{
+	const double eps = DBL_EPSILON;
+	size_t i;
+
+	for (i = 0; i < __arraycount(args); i++) {
+		double x = args[i].x;
+		double y = args[i].y;
+		double r;
+		double r_exp = args[i].r;
+		int quo;
+		int quo_exp = args[i].quo;
+
+		bool ok = true;
+
+		r = remquo(x, y, &quo);
+
+		ok &= (fabs(r - r_exp) <= eps);
+
+		/*
+		 * For now, consider 0 to have positive sign.
+		 */
+		if (quo_exp < 0 && quo >= 0)
+			ok = false;
+		if (quo_exp >= 0 && quo < 0)
+			ok = false;
+
+		/*
+		 * The specification requires that quo be congruent to
+		 * the integer remainder modulo 2^k for some k >=3.
+		 */
+		ok &= ((quo & 0x7) == (quo_exp & 0x7));
+
+		if (!ok) {
+			atf_tc_fail_nonfatal("remquo(%g, %g) "
+			    "r/quo expected %g/%d != %g/%d",
+			     x, y, r_exp, quo_exp, r, quo);
+		}
+	}
+}
+
+#endif /* !__vax__ */

Reply via email to