mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Szabolcs Nagy <nsz@port70.net>
To: musl@lists.openwall.com
Subject: Re: correctly rounded sqrt
Date: Wed, 14 Mar 2012 17:57:00 +0100	[thread overview]
Message-ID: <20120314165659.GG5728@port70.net> (raw)
In-Reply-To: <20120314165604.GF5728@port70.net>

[-- Attachment #1: Type: text/plain, Size: 111 bytes --]

* Szabolcs Nagy <nsz@port70.net> [2012-03-14 17:56:05 +0100]:
> ..and the code might be slow

forgot to attach

[-- Attachment #2: sqrt.c --]
[-- Type: text/x-csrc, Size: 5142 bytes --]

#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include <float.h>

#include <mpfr.h>
#include <gmp.h>

/*
int read(double *x, double *y) {
	char buf[256];

	if (!fgets(buf, sizeof buf, stdin))
		return 0;
	if (sscanf(buf, "%la %la", x, y) != 2)
		return 0;
	return 1;
}
*/

struct {
	double x,y;
} testdata[] = {
//	#include "sqrt.data"
0x1.fffffffffffffp+1023, 0x1.fffffffffffffp+511,
0x1.ffffffffffffbp+1023, 0x1.ffffffffffffdp+511,
0x1.ffffffffffff7p+1023, 0x1.ffffffffffffbp+511,
0x1.ffffffffffff3p+1023, 0x1.ffffffffffff9p+511,
0x1.fffffffffffefp+1023, 0x1.ffffffffffff7p+511,
0x1.fffffffffffebp+1023, 0x1.ffffffffffff5p+511,
0x1.fffffffffffe7p+1023, 0x1.ffffffffffff3p+511,
0x1.fffffffffffe3p+1023, 0x1.ffffffffffff1p+511,
0x1.fffffffffffdfp+1023, 0x1.fffffffffffefp+511,
0x1.fffffffffffdbp+1023, 0x1.fffffffffffedp+511,
0x1.fffffffffffd7p+1023, 0x1.fffffffffffebp+511,
0x1.0000000000003p-1022, 0x1.0000000000001p-511,
0x1.0000000000007p-1022, 0x1.0000000000003p-511,
0x1.000000000000bp-1022, 0x1.0000000000005p-511,
0x1.000000000000fp-1022, 0x1.0000000000007p-511,
0x1.0000000000013p-1022, 0x1.0000000000009p-511,
0x1.0000000000017p-1022, 0x1.000000000000bp-511,
0x1.000000000001bp-1022, 0x1.000000000000dp-511,
0x1.000000000001fp-1022, 0x1.000000000000fp-511,
0x1.0000000000023p-1022, 0x1.0000000000011p-511,
0x1.0000000000027p-1022, 0x1.0000000000013p-511,
0x1.000000000002bp-1022, 0x1.0000000000015p-511,
0x1.000000000002fp-1022, 0x1.0000000000017p-511,
0x1.0000000000033p-1022, 0x1.0000000000019p-511,
0x1.0000000000037p-1022, 0x1.000000000001bp-511,
0x1.7167bc36eaa3bp+6, 0x1.3384c7db650cdp+3,
0x1.7570994273ad7p+6, 0x1.353186e89b8ffp+3,
0x1.7dae969442fe6p+6, 0x1.389640fb18b75p+3,
0x1.7f8444fcf67e5p+6, 0x1.395659e94669fp+3,
0x1.8364650e63a54p+6, 0x1.3aea9efe1a3d7p+3,
0x1.85bedd274edd8p+6, 0x1.3bdf20c867057p+3,
0x1.8609cf496ab77p+6, 0x1.3bfd7e14b5eabp+3,
0x1.873849c70a375p+6, 0x1.3c77ed341d27fp+3,
0x1.8919c962cbaaep+6, 0x1.3d3a7113ee82fp+3,
0x1.8de4493e22dc6p+6, 0x1.3f27d448220c3p+3,
0x1.924829a17a288p+6, 0x1.40e9552eec28fp+3,
0x1.92702cd992f12p+6, 0x1.40f94a6fdfddfp+3,
0x1.92b763a8311fdp+6, 0x1.4115af614695fp+3,
0x1.947da013c7293p+6, 0x1.41ca91102940fp+3,
0x1.9536091c494d2p+6, 0x1.4213e334c77adp+3,
0x1.61b04c6p-1019, 0x1.a98b88f18b46dp-510,
0x1.93789f1p-1018, 0x1.4162ae43d5821p-509,
0x1.a1989b4p-1018, 0x1.46f6736eb44bbp-509,
0x1.f93bc9p-1018, 0x1.67a36ec403bafp-509,
0x1.2f675e3p-1017, 0x1.8a22ab6dcfee1p-509,
0x1.a158508p-1017, 0x1.ce418a96cf589p-509,
0x1.cd31f078p-1017, 0x1.e5ef1c65dccebp-509,
0x1.33b43b08p-1016, 0x1.18a9f607e1701p-508,
0x1.6e66a858p-1016, 0x1.324402a00b45fp-508,
0x1.8661cbf8p-1016, 0x1.3c212046bfdffp-508,
0x1.bbb221b4p-1016, 0x1.510681b939931p-508,
0x1.c4942f3cp-1016, 0x1.5461e59227ab5p-508,
0x1.dbb258c8p-1016, 0x1.5cf7b0f78d3afp-508,
0x1.57103ea4p-1015, 0x1.a31ab946d340bp-508,
0x1.9b294f88p-1015, 0x1.cad197e28e85bp-508,
0x1.0000000000001p+0, 0x1p+0,
0x1.fffffffffffffp-1, 0x1.fffffffffffffp-1,
};

void sq1(double *hi, double *lo, double u)
{
	static const double c = 1.0 + 0x1p27;
	double cu, u1, u2, r;

	cu = c*u;
	u1 = u - cu;
	u1 += cu;
	u2 = u - u1;
	*hi = u*u;
	r = u1*u1;
	r -= *hi;
	r += u1*u2;
	r += u2*u1;
	r += u2*u2;
	*lo = r;
}

void sq2(double *hi, double *lo, double u)
{
	double u1;
	double u2;
	double c;

	c = scalbn(1, ilogb(u)+27);
	u1 = u + c;
	u1 -= c;
	u2 = u - u1;
	*hi = u1*u1;
	*lo = u1*u2 + u1*u2 + u2*u2;
}

void sq3(double *hi, double *lo, double u)
{
	float u1;
	double u2;

	u1 = u;
	u2 = u - u1;
	*hi = (double)u1*u1;
	*lo = u1*u2 + u1*u2 + u2*u2;
}

double d_sqrt(double x)
{
	double y;
	double hi, lo, r, y1, r1;
	union {double x; uint64_t u;} u = {x};
	int e = u.u >> 52;
	int k;

	/* +-inf or nan */
	if ((e&0x7ff) == 0x7ff)
		return x + INFINITY;
	/* +-0 */
	if ((u.u & (uint64_t)-1>>1) == 0)
		return 0;
	/* x < 0 */
	if (e&0x800)
		return (x-x)/(x-x);
	if (!e) {
		/* subnormal */
		x *= 0x1p1022;
		k = -511;
	} else {
		/* normal */
		k = (e - 0x3ff)/2;
		e -= 2*k;
		u.u = (uint64_t)e<<52 | (u.u & (uint64_t)-1>>12);
		x = u.x;
	}
	y = sqrt(x);
	sq1(&hi, &lo, y);
	r = x - hi;
	r -= lo;
	if (r == 0)
		return scalbn(y, k);
	if (r < 0) {
		y1 = nextafter(y, 0);
		r = -r;
	} else
		y1 = nextafter(y, DBL_MAX);
	sq1(&hi, &lo, y1);
	r1 = x - hi;
	r1 -= lo;
	if (r1 < 0)
		r1 = -r1;
	y1 = scalbn(y1, k);
	y = scalbn(y, k);
	if (r1 < r)
		return y1;
	if (r1 > r)
		return y;
	printf("tie x %a y %a %a\n", scalbn(x, 2*k), y, y1);
	return y1;
}

static mpfr_t mx, my;

void mp_init()
{
	mpfr_init2(mx, 256);
	mpfr_init2(my, 256);
}

double mp_sqrt(double x) {
	mpfr_set_d(mx, x, GMP_RNDN);
	mpfr_sqrt(my, mx, GMP_RNDN);
	return mpfr_get_d(my, GMP_RNDN);
}

int main()
{
	int i;
	int c;
	double x, my, dy;

	c = 0;
/*
	mp_init();
	x = 1.0;
	for (i = 0; i < 1000000; i++) {
		my = mp_sqrt(x);
		dy = d_sqrt(x);

		if (my != dy) {
			printf("fail %a %a %a\n", x, my, dy);
			c++;
		}

		x = nextafter(x, 0);
	}
*/

	for (i = 0; i < sizeof testdata / sizeof *testdata; i++) {
		x = testdata[i].x;
		my = testdata[i].y;
		dy = d_sqrt(x);
		if (my != dy) {
			printf("fail %a %a %a\n", x, my, dy);
			c++;
		}
	}

	printf("%d\n", c);
	return 0;
}

  reply	other threads:[~2012-03-14 16:57 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-14 16:56 Szabolcs Nagy
2012-03-14 16:57 ` Szabolcs Nagy [this message]
2012-03-14 19:01 ` Szabolcs Nagy
2012-03-15  1:46   ` Szabolcs Nagy
2012-03-15  3:23     ` Szabolcs Nagy
2012-03-15  5:07       ` Rich Felker
2012-03-15  5:30         ` Szabolcs Nagy
2012-03-15  8:02           ` Szabolcs Nagy
2012-03-15 16:12             ` Rich Felker
2012-03-15 18:14               ` Pascal Cuoq
2012-03-15 18:22                 ` Szabolcs Nagy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120314165659.GG5728@port70.net \
    --to=nsz@port70.net \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).