From owner-svn-src-head@freebsd.org Tue Aug 29 22:37:25 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 53DE6DE76BD; Tue, 29 Aug 2017 22:37:25 +0000 (UTC) (envelope-from rlibby@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 2FB5D73CC1; Tue, 29 Aug 2017 22:37:25 +0000 (UTC) (envelope-from rlibby@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v7TMbO4J070398; Tue, 29 Aug 2017 22:37:24 GMT (envelope-from rlibby@FreeBSD.org) Received: (from rlibby@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v7TMbOKV070397; Tue, 29 Aug 2017 22:37:24 GMT (envelope-from rlibby@FreeBSD.org) Message-Id: <201708292237.v7TMbOKV070397@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rlibby set sender to rlibby@FreeBSD.org using -f From: Ryan Libby Date: Tue, 29 Aug 2017 22:37:24 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r323004 - head/lib/msun/tests X-SVN-Group: head X-SVN-Commit-Author: rlibby X-SVN-Commit-Paths: head/lib/msun/tests X-SVN-Commit-Revision: 323004 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 29 Aug 2017 22:37:25 -0000 Author: rlibby Date: Tue Aug 29 22:37:24 2017 New Revision: 323004 URL: https://svnweb.freebsd.org/changeset/base/323004 Log: lib/msun: add more csqrt unit tests for precision and overflow Reviewed by: bde Approved by: markj (mentor) Sponsored by: Dell EMC Isilon Modified: head/lib/msun/tests/csqrt_test.c Modified: head/lib/msun/tests/csqrt_test.c ============================================================================== --- head/lib/msun/tests/csqrt_test.c Tue Aug 29 22:32:29 2017 (r323003) +++ head/lib/msun/tests/csqrt_test.c Tue Aug 29 22:37:24 2017 (r323004) @@ -214,28 +214,94 @@ test_nans(void) /* * Test whether csqrt(a + bi) works for inputs that are large enough to - * cause overflow in hypot(a, b) + a. In this case we are using - * csqrt(115 + 252*I) == 14 + 9*I - * scaled up to near MAX_EXP. + * cause overflow in hypot(a, b) + a. Each of the tests is scaled up to + * near MAX_EXP. */ static void test_overflow(int maxexp) { long double a, b; long double complex result; + int exp, i; - a = ldexpl(115 * 0x1p-8, maxexp); - b = ldexpl(252 * 0x1p-8, maxexp); - result = t_csqrt(CMPLXL(a, b)); - assert(creall(result) == ldexpl(14 * 0x1p-4, maxexp / 2)); - assert(cimagl(result) == ldexpl(9 * 0x1p-4, maxexp / 2)); + assert(maxexp > 0 && maxexp % 2 == 0); + + for (i = 0; i < 4; i++) { + exp = maxexp - 2 * i; + + /* csqrt(115 + 252*I) == 14 + 9*I */ + a = ldexpl(115 * 0x1p-8, exp); + b = ldexpl(252 * 0x1p-8, exp); + result = t_csqrt(CMPLXL(a, b)); + assert(creall(result) == ldexpl(14 * 0x1p-4, exp / 2)); + assert(cimagl(result) == ldexpl(9 * 0x1p-4, exp / 2)); + + /* csqrt(-11 + 60*I) = 5 + 6*I */ + a = ldexpl(-11 * 0x1p-6, exp); + b = ldexpl(60 * 0x1p-6, exp); + result = t_csqrt(CMPLXL(a, b)); + assert(creall(result) == ldexpl(5 * 0x1p-3, exp / 2)); + assert(cimagl(result) == ldexpl(6 * 0x1p-3, exp / 2)); + + /* csqrt(225 + 0*I) == 15 + 0*I */ + a = ldexpl(225 * 0x1p-8, exp); + b = 0; + result = t_csqrt(CMPLXL(a, b)); + assert(creall(result) == ldexpl(15 * 0x1p-4, exp / 2)); + assert(cimagl(result) == 0); + } } +/* + * Test that precision is maintained for some large squares. Set all or + * some bits in the lower mantdig/2 bits, square the number, and try to + * recover the sqrt. Note: + * (x + xI)**2 = 2xxI + */ +static void +test_precision(int maxexp, int mantdig) +{ + long double b, x; + long double complex result; + uint64_t mantbits, sq_mantbits; + int exp, i; + + assert(maxexp > 0 && maxexp % 2 == 0); + assert(mantdig <= 64); + mantdig = rounddown(mantdig, 2); + + for (exp = 0; exp <= maxexp; exp += 2) { + mantbits = ((uint64_t)1 << (mantdig / 2 )) - 1; + for (i = 0; + i < 100 && mantbits > ((uint64_t)1 << (mantdig / 2 - 1)); + i++, mantbits--) { + sq_mantbits = mantbits * mantbits; + /* + * sq_mantibts is a mantdig-bit number. Divide by + * 2**mantdig to normalize it to [0.5, 1), where, + * note, the binary power will be -1. Raise it by + * 2**exp for the test. exp is even. Lower it by + * one to reach a final binary power which is also + * even. The result should be exactly + * representable, given that mantdig is less than or + * equal to the available precision. + */ + b = ldexpl((long double)sq_mantbits, + exp - 1 - mantdig); + x = ldexpl(mantbits, (exp - 2 - mantdig) / 2); + assert(b == x * x * 2); + result = t_csqrt(CMPLXL(0, b)); + assert(creall(result) == x); + assert(cimagl(result) == x); + } + } +} + int main(void) { - printf("1..15\n"); + printf("1..18\n"); /* Test csqrt() */ t_csqrt = _csqrt; @@ -255,41 +321,56 @@ main(void) test_overflow(DBL_MAX_EXP); printf("ok 5 - csqrt\n"); + test_precision(DBL_MAX_EXP, DBL_MANT_DIG); + printf("ok 6 - csqrt\n"); + /* Now test csqrtf() */ t_csqrt = _csqrtf; test_finite(); - printf("ok 6 - csqrt\n"); + printf("ok 7 - csqrt\n"); test_zeros(); - printf("ok 7 - csqrt\n"); + printf("ok 8 - csqrt\n"); test_infinities(); - printf("ok 8 - csqrt\n"); + printf("ok 9 - csqrt\n"); test_nans(); - printf("ok 9 - csqrt\n"); + printf("ok 10 - csqrt\n"); test_overflow(FLT_MAX_EXP); - printf("ok 10 - csqrt\n"); + printf("ok 11 - csqrt\n"); + test_precision(FLT_MAX_EXP, FLT_MANT_DIG); + printf("ok 12 - csqrt\n"); + /* Now test csqrtl() */ t_csqrt = csqrtl; test_finite(); - printf("ok 11 - csqrt\n"); + printf("ok 13 - csqrt\n"); test_zeros(); - printf("ok 12 - csqrt\n"); + printf("ok 14 - csqrt\n"); test_infinities(); - printf("ok 13 - csqrt\n"); + printf("ok 15 - csqrt\n"); test_nans(); - printf("ok 14 - csqrt\n"); + printf("ok 16 - csqrt\n"); test_overflow(LDBL_MAX_EXP); - printf("ok 15 - csqrt\n"); + printf("ok 17 - csqrt\n"); + + test_precision(LDBL_MAX_EXP, +#ifndef __i386__ + LDBL_MANT_DIG +#else + DBL_MANT_DIG +#endif + ); + printf("ok 18 - csqrt\n"); return (0); }