semi-working mprb type based on mpr/mpfr + ufloat

This commit is contained in:
Fredrik Johansson 2012-08-07 14:37:10 +02:00
parent 48df1f1886
commit 9ee444f76c
33 changed files with 1513 additions and 225 deletions

View file

@ -102,5 +102,5 @@ build/%.lo: %.c
build/%.o: %.c
$(CC) -fPIC $(CFLAGS) $(INCS) -c $< -o $@
BUILD_DIRS = mpr mprb
BUILD_DIRS = ufloat mpr mprb

2
configure vendored
View file

@ -6,7 +6,7 @@
PREFIX="/usr/local"
MPIR_DIR="/usr/local"
MPFR_DIR="/usr/local"
FLINT_DIR="/home/fredrik/src/flint2/flint2"
FLINT_DIR="/home/fredrik/src/flint2"
SHARED=1
STATIC=1

3
mpr.h
View file

@ -62,7 +62,10 @@ void _mpr_printr(mp_ptr x, mp_size_t n);
int
_mpr_muld_n(mp_ptr z, mp_srcptr x, mp_srcptr y, mp_size_t n);
int _mpr_muld_using_mpfr(mp_ptr z, mp_size_t zn, mp_srcptr x, mp_size_t xn, mp_srcptr y, mp_size_t yn);
/* Addition ******************************************************************/
int _mpr_addd_n(mp_ptr z, mp_srcptr x, mp_srcptr y, mp_bitcnt_t shift, mp_size_t n);
int _mpr_addd_using_mpfr(mp_ptr z, mp_size_t zn, mp_srcptr x, mp_size_t xn, mp_srcptr y, mp_size_t yn, long shift);

31
mpr/addd_using_mpfr.c Normal file
View file

@ -0,0 +1,31 @@
#include "mpr.h"
/*
Computes z = x + y / 2^shift, rounding down (truncating) with correct rounding.
Returns adjustment (0 or 1) to be added to the exponent.
*/
int
_mpr_addd_using_mpfr(mp_ptr z, mp_size_t zn, mp_srcptr x, mp_size_t xn, mp_srcptr y, mp_size_t yn, long shift)
{
__mpfr_struct zs, xs, ys;
xs._mpfr_d = (mp_ptr) x;
xs._mpfr_exp = 0;
xs._mpfr_prec = xn * FLINT_BITS;
xs._mpfr_sign = 1;
ys._mpfr_d = (mp_ptr) y;
ys._mpfr_exp = -shift;
ys._mpfr_prec = yn * FLINT_BITS;
ys._mpfr_sign = 1;
zs._mpfr_d = (mp_ptr) z;
zs._mpfr_exp = 0;
zs._mpfr_prec = zn * FLINT_BITS;
zs._mpfr_sign = 1;
mpfr_add(&zs, &xs, &ys, MPFR_RNDD);
return zs._mpfr_exp != 0;
}

31
mpr/muld_using_mpfr.c Normal file
View file

@ -0,0 +1,31 @@
#include "mpr.h"
/*
Computes z = x * y, rounding down (truncating) with correct rounding.
Returns adjustment (0 or 1) to be subtracted from the exponent.
*/
int
_mpr_muld_using_mpfr(mp_ptr z, mp_size_t zn, mp_srcptr x, mp_size_t xn, mp_srcptr y, mp_size_t yn)
{
__mpfr_struct zs, xs, ys;
xs._mpfr_d = (mp_ptr) x;
xs._mpfr_exp = 0;
xs._mpfr_prec = xn * FLINT_BITS;
xs._mpfr_sign = 1;
ys._mpfr_d = (mp_ptr) y;
ys._mpfr_exp = 0;
ys._mpfr_prec = yn * FLINT_BITS;
ys._mpfr_sign = 1;
zs._mpfr_d = (mp_ptr) z;
zs._mpfr_exp = 0;
zs._mpfr_prec = zn * FLINT_BITS;
zs._mpfr_sign = 1;
mpfr_mul(&zs, &xs, &ys, MPFR_RNDD);
return zs._mpfr_exp != 0;
}

13
mprb.h
View file

@ -1,13 +1,20 @@
#include "mpr.h"
#include "ufloat.h"
typedef struct
{
mp_ptr d;
mp_limb_t rad;
long exp;
long size;
long alloc;
long sign;
long exp;
int sign;
}
mpr_struct;
typedef struct
{
mpr_struct mid;
ufloat_struct rad;
}
mprb_struct;

View file

@ -3,83 +3,39 @@
void
mprb_add(mprb_t z, const mprb_t x, const mprb_t y)
{
mp_limb_t xrad, yrad, t, u;
mp_srcptr xptr, yptr;
long size, xexp, yexp, shift, carry, exp;
mp_ptr zptr;
long zsize, xsize, ysize, xexp, yexp, shift;
if (x->sign != y->sign)
{
printf("mprb_add: different signs not supported\n");
if (x->mid.sign != y->mid.sign)
abort();
}
size = FLINT_MIN(x->size, y->size);
size = FLINT_MIN(size, z->alloc);
xrad = (size == x->size) ? x->rad : 2UL;
yrad = (size == y->size) ? y->rad : 2UL;
xptr = x->d + x->size - size;
yptr = y->d + y->size - size;
xptr = x->mid.d;
yptr = y->mid.d;
zptr = z->mid.d;
xexp = x->exp;
yexp = y->exp;
xsize = x->mid.size;
ysize = y->mid.size;
zsize = z->mid.size;
xexp = x->mid.exp;
yexp = y->mid.exp;
ufloat_add(&z->rad, &x->rad, &y->rad);
z->mid.sign = x->mid.sign;
if (xexp >= yexp)
{
shift = xexp - yexp;
carry = _mpr_addd_n(z->d, xptr, yptr, shift, size);
exp = xexp;
shift = _mpr_addd_using_mpfr(zptr, zsize, xptr, xsize, yptr, ysize, xexp - yexp);
z->mid.exp = x->mid.exp + shift;
}
else
{
shift = yexp - xexp;
carry = _mpr_addd_n(z->d, yptr, xptr, shift, size);
t = xrad;
xrad = yrad;
yrad = t;
exp = yexp;
shift = _mpr_addd_using_mpfr(zptr, zsize, yptr, ysize, xptr, xsize, yexp - xexp);
z->mid.exp = y->mid.exp + shift;
}
xrad = (xrad >> carry) + carry;
yrad = (yrad >> carry) + carry;
if (shift >= FLINT_BITS)
{
add_ssaaaa(u, t, 0, xrad, 0, 3);
}
else if (shift == 0)
{
add_ssaaaa(u, t, 0, xrad, 0, yrad);
add_ssaaaa(u, t, u, t, 0, carry);
}
else
{
add_ssaaaa(u, t, 0, xrad, 0, (yrad >> shift) + 3);
}
if (u == 0)
{
z->rad = t;
z->size = size;
z->sign = x->sign;
z->exp = exp + carry;
}
else
{
if (size == 1)
{
z->rad = 1UL << (FLINT_BITS - 1);
z->d[0] = 0;
z->size = 1;
z->sign = x->sign;
z->exp = exp + carry + 3;
}
else
{
z->rad = 3UL;
mpn_copyi(z->d, z->d + 1, size - 1);
z->size = size - 1;
z->sign = x->sign;
z->exp = exp + carry;
}
}
/* rounding error */
ufloat_add_2exp(&z->rad, &z->rad, z->mid.exp - z->mid.size * FLINT_BITS);
}

View file

@ -3,5 +3,5 @@
void
mprb_clear(mprb_t x)
{
free(x->d);
}
free(x->mid.d);
}

View file

@ -6,9 +6,10 @@ mprb_contains_mpfr(const mprb_t x, const mpfr_t f)
mpfr_t a, b;
int result;
/* 1 extra bit allows adding radius exactly */
mpfr_init2(a, FLINT_BITS * x->size + 1);
mpfr_init2(b, FLINT_BITS * x->size + 1);
/* XXX: this is no longer correct if the radius is larger */
mpfr_init2(a, FLINT_BITS * x->mid.size + 1000);
mpfr_init2(b, FLINT_BITS * x->mid.size + 1000);
mprb_get_interval_mpfr(a, b, x);

View file

@ -9,10 +9,10 @@ mprb_debug(const mprb_t x)
mpz_init(t);
e = mprb_get_mid_mpz_2exp(t, x);
printf("N: [exp=%ld] ", x->exp);
mpn_debug(x->d, x->size);
gmp_printf("Z: {mid=%Zx, exp=%ld, rad=%lu, size=%ld, alloc=%ld}\n",
t, e, x->rad, (long) x->size, (long) x->alloc);
printf("N: [exp=%ld] ", x->mid.exp);
mpn_debug(x->mid.d, x->mid.size);
gmp_printf("Z: {%Zd * 2^%ld +- %lu * 2^%ld, size=%ld, alloc=%ld}\n",
t, e, x->rad.man, x->rad.exp - UFLOAT_PREC, (long) x->mid.size, (long) x->mid.alloc);
mpz_clear(t);
}

View file

@ -11,20 +11,8 @@ mprb_get_interval_mpfr(mpfr_t a, mpfr_t b, const mprb_t x)
mprb_get_rad_mpfr(r, x);
#if 0
printf("GETTING INTRVLA\n");
mpfr_printf("a = %Rg [xsign = %ld]\n", a, x->sign);
mpfr_printf("b = %Rg\n", b);
mpfr_printf("r = %Rg\n", r);
#endif
mpfr_sub(a, a, r, MPFR_RNDD);
mpfr_add(b, b, r, MPFR_RNDU);
#if 0
mpfr_printf("a2 = %Rg\n", a);
mpfr_printf("b2 = %Rg\n", b);
#endif
mpfr_clear(r);
}

View file

@ -4,9 +4,8 @@
void
mprb_get_mid_mpfr(mpfr_t x, const mprb_t v, mpfr_rnd_t rnd)
{
if ((v->size == 1) && (v->d[0] == 0))
if ((v->mid.size == 1) && (v->mid.d[0] == 0))
mpfr_set_ui(x, 0, MPFR_RNDD);
else
_mpr_get_mpfr_signed(x, v->d, v->exp, v->size,
(v->sign == MPRB_SIGN_PLUS) ? 1 : -1, rnd);
_mpr_get_mpfr_signed(x, v->mid.d, v->mid.exp, v->mid.size, (v->mid.sign == MPRB_SIGN_PLUS) ? 1 : -1, rnd);
}

View file

@ -4,16 +4,16 @@
long
mprb_get_mid_mpz_2exp(mpz_t a, const mprb_t x)
{
if ((x->size == 1) && (x->d[0] == 0))
if ((x->mid.size == 1) && (x->mid.d[0] == 0))
{
mpz_set_ui(a, 0);
return 0;
}
else
{
mpz_realloc2(a, x->size * FLINT_BITS);
mpn_copyi(a->_mp_d, x->d, x->size);
a->_mp_size = (x->sign == MPRB_SIGN_PLUS) ? x->size : -(x->size);
return x->exp - x->size * FLINT_BITS;
mpz_realloc2(a, x->mid.size * FLINT_BITS);
mpn_copyi(a->_mp_d, x->mid.d, x->mid.size);
a->_mp_size = (x->mid.sign == MPRB_SIGN_PLUS) ? x->mid.size : -(x->mid.size);
return x->mid.exp - x->mid.size * FLINT_BITS;
}
}

View file

@ -3,5 +3,5 @@
void
mprb_get_rad_mpfr(mpfr_t r, const mprb_t x)
{
mpfr_set_ui_2exp(r, x->rad, x->exp - FLINT_BITS * x->size, MPFR_RNDU);
ufloat_get_mpfr(r, &x->rad);
}

View file

@ -5,10 +5,13 @@ mprb_init(mprb_t x, long bits)
{
long limbs = _MPR_BITS_TO_LIMBS(bits);
x->d = calloc(limbs, sizeof(mp_limb_t));
x->exp = 0;
x->sign = MPRB_SIGN_PLUS;
x->alloc = limbs;
x->size = limbs;
x->rad = 0UL;
x->mid.d = calloc(limbs, sizeof(mp_limb_t));
x->mid.exp = 0;
x->mid.sign = MPRB_SIGN_PLUS;
x->mid.alloc = limbs;
x->mid.size = limbs;
/* XXX: ufloat_zero */
x->rad.man = 0UL;
x->rad.exp = 0L;
}

View file

@ -1,114 +1,55 @@
#include "mprb.h"
/* throw away to avoid overflow */
#define RAD_MUL_SHIFT 8
/* XXX: assumes nonzero! */
static __inline__ void
_mpr_get_ufloat(ufloat_t u, mp_srcptr d, long size, long exp)
{
/* since we truncate, we need to round up */
u->man = (d[size - 1] >> (FLINT_BITS - UFLOAT_PREC)) + 1UL;
u->exp = exp;
/* adjust for carry (very unlikely!) */
if (u->man >= (1UL << UFLOAT_PREC))
{
u->man = (u->man >> 1) + 1UL;
u->exp++;
}
}
void
mprb_mul(mprb_t z, const mprb_t x, const mprb_t y)
{
mp_limb_t xrad, yrad;
ufloat_t a, b;
mp_srcptr xptr, yptr;
long size;
mp_ptr zptr;
long zsize, xsize, ysize, exp, shift;
size = FLINT_MIN(x->size, y->size);
size = FLINT_MIN(size, z->alloc);
xrad = (size == x->size) ? x->rad : 2UL;
yrad = (size == y->size) ? y->rad : 2UL;
xptr = x->d + x->size - size;
yptr = y->d + y->size - size;
xptr = x->mid.d;
yptr = y->mid.d;
zptr = z->mid.d;
if (size == 1)
{
mp_limb_t u1, u0, a2, a1, a0, b1, b0;
xsize = x->mid.size;
ysize = y->mid.size;
zsize = z->mid.size;
umul_ppmm(a1, a0, xptr[0], yrad);
umul_ppmm(b1, b0, yptr[0], xrad);
add_sssaaaaaa(a2, a1, a0, 0, a1, a0, 0, b1, b0);
umul_ppmm(b1, b0, xrad, yrad);
add_sssaaaaaa(a2, a1, a0, a2, a1, a0, 0, b1, b0);
_mpr_get_ufloat(a, xptr, xsize, x->mid.exp);
_mpr_get_ufloat(b, yptr, ysize, y->mid.exp);
umul_ppmm(u1, u0, xptr[0], yptr[0]);
/* error propagation: x*rad(y) + y*rad(x) + rad(x)*rad(y) */
ufloat_mul(a, a, &y->rad);
ufloat_addmul(a, b, &x->rad);
ufloat_add_2exp(a, a, x->rad.exp + y->rad.exp);
if ((u1 >> (FLINT_BITS - 1)) == 0)
{
u1 = (u1 << 1) | (u0 >> (FLINT_BITS - 1));
u0 = (u0 << 1);
a2 = (a2 << 1) | (a1 >> (FLINT_BITS - 1));
a1 = (a1 << 1) | (a0 >> (FLINT_BITS - 1));
a0 = (a0 << 1);
z->exp = x->exp + y->exp - 1;
}
else
{
z->exp = x->exp + y->exp;
}
shift = _mpr_muld_using_mpfr(zptr, zsize, xptr, xsize, yptr, ysize);
/* round up */
add_ssaaaa(a2, a1, a2, a1, 0, (u0 != 0) + (a0 != 0));
/* add exponents */
exp = x->mid.exp + y->mid.exp - shift;
if (a2 == 0)
{
z->rad = a1;
z->d[0] = u1;
}
else
{
z->rad = -1UL;
z->d[0] = (1UL << (FLINT_BITS - 1));
z->exp += 2;
}
/* rounding error */
ufloat_add_2exp(a, a, exp - z->mid.size * FLINT_BITS);
z->size = 1;
z->sign = x->sign ^ y->sign;
}
else
{
mp_limb_t t0, t1, u0, u1, rad;
mp_limb_t xtop, ytop;
int shift, need_limb_shift;
/* upper bound for x*yrad + y*xrad */
xtop = (xptr[size-1] >> RAD_MUL_SHIFT) + 1UL;
ytop = (yptr[size-1] >> RAD_MUL_SHIFT) + 1UL;
umul_ppmm(t1, t0, xtop, y->rad);
umul_ppmm(u1, u0, ytop, x->rad);
add_ssaaaa(t1, t0, t1, t0, u1, u0);
/* scale back radius to the true magnitude */
t0 = (t0 >> (FLINT_BITS - RAD_MUL_SHIFT)) | (t1 << RAD_MUL_SHIFT);
t1 = (t1 >> (FLINT_BITS - RAD_MUL_SHIFT));
/* xrad * yrad < 1 ulp
+ 1 ulp error in the main multiplication
+ 1 ulp error from the shift above */
add_ssaaaa(t1, t0, t1, t0, 0, 3UL);
shift = _mpr_muld_n(z->d, xptr, yptr, size);
/* adjust radius */
t1 = (t1 << shift) | ((t0 >> (FLINT_BITS - 1)) & shift);
t0 = t0 << shift;
/* remove one limb */
if (t1 != 0)
{
need_limb_shift = 1;
/* +1 ulp error for the rounding of t1 */
/* +1 ulp error in the main product, which doubles
if we perform a shift */
rad = t1 + 2 + shift;
mpn_copyi(z->d, z->d + 1, size - 1);
}
else
{
need_limb_shift = 0;
rad = t0;
}
z->rad = rad;
z->exp = x->exp + y->exp - shift;
z->size = size - need_limb_shift;
z->sign = x->sign ^ y->sign;
}
z->rad = *a;
z->mid.exp = exp;
z->mid.sign = x->mid.sign ^ y->mid.sign;
}

View file

@ -5,12 +5,14 @@ mprb_randtest(mprb_t x, flint_rand_t state, long emin, long emax)
{
long n;
n = n_randint(state, x->alloc) + 1;
n = n_randint(state, x->mid.alloc) + 1;
_mpr_randtest(x->d, state, n);
_mpr_randtest(x->mid.d, state, n);
x->rad = n_randtest(state);
x->size = n;
x->sign = n_randint(state, 2) ? MPRB_SIGN_PLUS : MPRB_SIGN_MINUS;
x->exp = emin + n_randint(state, emax - emin + 1);
x->mid.size = n;
x->mid.sign = n_randint(state, 2) ? MPRB_SIGN_PLUS : MPRB_SIGN_MINUS;
x->mid.exp = emin + n_randint(state, emax - emin + 1);
/* XXX: change ufloat_randtest to use emin / emax */
ufloat_randtest(&x->rad, state, emax);
}

View file

@ -6,11 +6,21 @@ mprb_set_mpfr(mprb_t x, const mpfr_t v)
{
long xprec, vprec, prec;
xprec = x->alloc;
xprec = x->mid.alloc;
vprec = _MPR_BITS_TO_LIMBS(v->_mpfr_prec);
x->exp = _mpr_set_mpfr(x->d, v, xprec);
x->rad = (xprec >= vprec) ? 0UL : 1UL;
x->sign = (v->_mpfr_sign == 1) ? MPRB_SIGN_PLUS : MPRB_SIGN_MINUS;
x->size = x->alloc;
x->mid.exp = _mpr_set_mpfr(x->mid.d, v, xprec);
x->mid.sign = (v->_mpfr_sign == 1) ? MPRB_SIGN_PLUS : MPRB_SIGN_MINUS;
x->mid.size = x->mid.alloc;
if (xprec >= vprec)
{
ufloat_zero(&x->rad);
}
else
{
/* max 1 ulp error */
/* XXX: ufloat_set_2exp */
ufloat_set_ui_2exp(&x->rad, 1UL, x->mid.exp - x->mid.size * FLINT_BITS);
}
}

View file

@ -26,11 +26,11 @@ int main()
mprb_init(y, 1 + n_randint(state, 300));
mprb_init(z, 1 + n_randint(state, 300));
do { mprb_randtest(x, state, -10, 10); } while (x->size == 0);
do { mprb_randtest(y, state, -10, 10); } while (y->size == 0);
do { mprb_randtest(z, state, -10, 10); } while (z->size == 0);
do { mprb_randtest(x, state, -10, 10); } while (x->mid.size == 0);
do { mprb_randtest(y, state, -10, 10); } while (y->mid.size == 0);
do { mprb_randtest(z, state, -10, 10); } while (z->mid.size == 0);
y->sign = x->sign;
y->mid.sign = x->mid.sign;
mpfr_init2(t, 1000);
mpfr_init2(u, 1000);
@ -76,4 +76,4 @@ int main()
flint_randclear(state);
_fmpz_cleanup();
return EXIT_SUCCESS;
}
}

View file

@ -26,9 +26,9 @@ int main()
mprb_init(y, 1 + n_randint(state, 300));
mprb_init(z, 1 + n_randint(state, 300));
do { mprb_randtest(x, state, -10, 10); } while (x->size == 0);
do { mprb_randtest(y, state, -10, 10); } while (y->size == 0);
do { mprb_randtest(z, state, -10, 10); } while (z->size == 0);
do { mprb_randtest(x, state, -10, 10); } while (x->mid.size == 0);
do { mprb_randtest(y, state, -10, 10); } while (y->mid.size == 0);
do { mprb_randtest(z, state, -10, 10); } while (z->mid.size == 0);
mpfr_init2(t, 1000);
mpfr_init2(u, 1000);
@ -74,4 +74,4 @@ int main()
flint_randclear(state);
_fmpz_cleanup();
return EXIT_SUCCESS;
}
}

418
ufloat.h Normal file
View file

@ -0,0 +1,418 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#ifndef UFLOAT_H
#define UFLOAT_H
#include <stdio.h>
#include <mpir.h>
#include "flint.h"
#include "fmpz.h"
#include "ulong_extras.h"
#include "math.h"
static __inline__ mp_limb_t
n_rshift_ceil(mp_limb_t a, int k)
{
return (a >> k) + (((a >> k) << k) != a);
}
/*
A ufloat holds a nonzero bound for the magnitude of a number.
The mantissa has exactly UFLOAT_PREC bits, which must be at most
FLINT_BITS / 2.
*/
#define UFLOAT_PREC 15
#define UFLOAT_MAN_MIN (1UL << (UFLOAT_PREC - 1))
#define UFLOAT_MAN_MAX ((1UL << UFLOAT_PREC) - 1)
typedef struct
{
mp_limb_t man;
long exp;
}
ufloat_struct;
typedef ufloat_struct ufloat_t[1];
static __inline__ void
ufloat_print(const ufloat_t x)
{
double t = ldexp(x->man, x->exp - UFLOAT_PREC);
printf("ufloat{man=%lu, exp=%ld, %.20g}\n", x->man, x->exp, t);
}
static __inline__ void
ufloat_normalise(ufloat_t z)
{
int b = FLINT_BIT_COUNT(z->man);
if (b < UFLOAT_PREC)
{
z->man <<= (UFLOAT_PREC - b);
z->exp -= (UFLOAT_PREC - b);
}
else
{
int adjust;
z->man = n_rshift_ceil(z->man, (b - UFLOAT_PREC));
z->exp += (b - UFLOAT_PREC);
/* possible overflow to power of two */
adjust = z->man >> UFLOAT_PREC;
z->man = n_rshift_ceil(z->man, adjust);
z->exp += adjust;
}
}
static __inline__ int
ufloat_cmp_one(const ufloat_t u)
{
if (u->exp == 1L)
return u->man == (1UL << (UFLOAT_PREC - 1)) ? 0 : 1;
else
return u->exp < 1L ? -1 : 1;
}
static __inline__ void
ufloat_set(ufloat_t u, const ufloat_t v)
{
u->man = v->man;
u->exp = v->exp;
}
static __inline__ void
ufloat_zero(ufloat_t u)
{
u->man = 0UL;
u->exp = 0L;
}
/* TODO: add constant_p handling; overflow */
static __inline__ void
ufloat_set_ui_2exp(ufloat_t u, mp_limb_t a, long exp)
{
u->man = a;
u->exp = exp + UFLOAT_PREC;
ufloat_normalise(u);
}
/* TODO: overflow */
static __inline__ void
ufloat_set_ll_2exp(ufloat_t u, mp_limb_t hi, mp_limb_t lo, long exp)
{
if (hi == 0UL)
{
ufloat_set_ui_2exp(u, lo, exp);
}
else
{
unsigned int c;
count_leading_zeros(c, hi);
if (c != 0)
hi = (hi << c) | (lo >> (FLINT_BITS - c));
if (hi + 1UL != 0UL)
ufloat_set_ui_2exp(u, hi + 1UL, exp + FLINT_BITS - c);
else
ufloat_set_ui_2exp(u, 1UL, exp + 2 * FLINT_BITS - c);
}
}
static __inline__ void
ufloat_one(ufloat_t u)
{
u->man = (1UL << (UFLOAT_PREC - 1));
u->exp = 1L;
}
static __inline__ void
ufloat_add(ufloat_t z, const ufloat_t x, const ufloat_t y)
{
long shift;
int adjust;
shift = x->exp - y->exp;
if (shift >= 0)
{
z->exp = x->exp;
if (shift >= UFLOAT_PREC)
z->man = x->man + 1;
else
z->man = x->man + n_rshift_ceil(y->man, shift);
}
else
{
shift = -shift;
z->exp = y->exp;
if (shift >= UFLOAT_PREC)
z->man = y->man + 1;
else
z->man = y->man + n_rshift_ceil(x->man, shift);
}
/* adjust for carry */
adjust = z->man >> UFLOAT_PREC;
z->man = n_rshift_ceil(z->man, adjust);
z->exp += adjust;
}
/* bound |x-y| */
static __inline__ void
ufloat_sub(ufloat_t z, const ufloat_t x, const ufloat_t y)
{
long shift;
mp_limb_t a, b;
shift = x->exp - y->exp;
if (shift == 0)
{
if (x->man >= y->man)
z->man = x->man - y->man;
else
z->man = y->man - x->man;
z->exp = x->exp;
ufloat_normalise(z);
return;
}
if (shift > 0)
{
z->exp = x->exp;
a = x->man;
b = y->man;
}
else
{
shift = -shift;
z->exp = y->exp;
a = y->man;
b = x->man;
}
if (shift >= UFLOAT_PREC)
{
z->man = a;
}
else
{
z->man = (a << shift) - b;
z->exp -= shift;
}
ufloat_normalise(z);
}
static __inline__ void
ufloat_set_2exp(ufloat_t y, const ufloat_t x, long exp)
{
}
static __inline__ void
ufloat_add_2exp(ufloat_t y, const ufloat_t x, long exp)
{
long s, shift = x->exp - exp;
/* x is larger than 2^exp */
if (shift > 0)
{
s = FLINT_MAX(0L, UFLOAT_PREC - shift);
y->man = x->man + (1UL << s);
y->exp = x->exp;
}
/* 2^exp is larger than x */
else
{
s = FLINT_MIN(UFLOAT_PREC - 1L, 1L - shift);
y->man = (1UL << (UFLOAT_PREC - 1)) + (x->man >> s) + 1UL;
y->exp = exp + 1L;
}
/* unlikely */
if (y->man > UFLOAT_MAN_MAX)
{
y->man = n_rshift_ceil(y->man, 1);
y->exp++;
}
}
static __inline__ void
ufloat_mul(ufloat_t z, const ufloat_t x, const ufloat_t y)
{
mp_limb_t m;
int adjust, shift;
z->exp = x->exp + y->exp;
m = x->man * y->man;
/* product has one bit too little */
adjust = m >> (2 * UFLOAT_PREC - 1);
shift = UFLOAT_PREC - 1 + adjust;
z->exp += shift;
m = n_rshift_ceil(m, shift);
/* power of two */
adjust = m >> UFLOAT_PREC;
m >>= adjust;
z->exp += adjust;
z->man = m;
}
static __inline__ void
ufloat_addmul(ufloat_t z, const ufloat_t x, const ufloat_t y)
{
ufloat_t t;
ufloat_mul(t, x, y);
ufloat_add(z, z, t);
}
static __inline__ void
ufloat_div(ufloat_t z, const ufloat_t x, const ufloat_t y)
{
int adjust;
z->man = (x->man << UFLOAT_PREC) / y->man + 1;
z->exp = x->exp - y->exp;
/* quotient can be one bit too large */
adjust = z->man >> UFLOAT_PREC;
z->man = n_rshift_ceil(z->man, adjust);
z->exp += adjust;
/* power of two */
adjust = z->man >> UFLOAT_PREC;
z->man >>= adjust;
z->exp += adjust;
}
static __inline__ void
ufloat_randtest(ufloat_t u, flint_rand_t state, long erange)
{
u->man = n_randbits(state, UFLOAT_PREC);
u->man |= (1UL << (UFLOAT_PREC - 1));
u->exp = n_randint(state, erange) - (erange / 2) + 1;
}
static __inline__ void
ufloat_set_fmpz(ufloat_t u, const fmpz_t z)
{
u->man = fmpz_abs_ubound_ui_2exp(&u->exp, z, UFLOAT_PREC);
u->exp += UFLOAT_PREC;
}
static __inline__ void
ufloat_set_fmpz_lower(ufloat_t u, const fmpz_t z)
{
u->man = fmpz_abs_lbound_ui_2exp(&u->exp, z, UFLOAT_PREC);
u->exp += UFLOAT_PREC;
}
static __inline__ void
ufloat_get_fmpz(fmpz_t z, const ufloat_t u)
{
long exp = u->exp - UFLOAT_PREC;
_fmpz_demote(z);
*z = u->man;
if (exp >= 0)
{
if (exp < FLINT_BITS - UFLOAT_PREC - 2)
*z = (u->man << exp);
else
fmpz_mul_2exp(z, z, exp);
}
else
{
if (exp > -FLINT_BITS)
*z = n_rshift_ceil(u->man, -exp);
else
*z = 1;
}
}
static __inline__ int
ufloat_equal(const ufloat_t u, const ufloat_t v)
{
return u->man == v->man && u->exp == v->exp;
}
static __inline__ void
ufloat_get_mpfr(mpfr_t x, const ufloat_t u)
{
mpfr_set_ui_2exp(x, u->man, u->exp - UFLOAT_PREC, MPFR_RNDU);
}
static __inline__ void
ufloat_set_mpfr(ufloat_t u, const mpfr_t x)
{
if (mpfr_zero_p(x))
{
u->man = 0;
u->exp = 0;
}
else
{
mpz_t t;
long exp, bits;
mpz_init(t);
exp = mpfr_get_z_2exp(t, x);
mpz_abs(t, t);
bits = mpz_sizeinbase(t, 2);
if (bits > UFLOAT_PREC)
{
mpz_cdiv_q_2exp(t, t, bits - UFLOAT_PREC);
exp += bits - UFLOAT_PREC;
}
u->exp = exp + UFLOAT_PREC;
u->man = mpz_get_ui(t);
ufloat_normalise(u);
mpz_clear(t);
}
}
void ufloat_log(ufloat_t z, const ufloat_t x);
void ufloat_log1p(ufloat_t z, const ufloat_t x);
#endif

42
ufloat/Makefile Normal file
View file

@ -0,0 +1,42 @@
SOURCES = $(wildcard *.c)
OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(SOURCES))
LIB_OBJS = $(patsubst %.c, $(BUILD_DIR)/%.lo, $(SOURCES))
TEST_SOURCES = $(wildcard test/*.c)
PROF_SOURCES = $(wildcard profile/*.c)
TUNE_SOURCES = $(wildcard tune/*.c)
TESTS = $(patsubst %.c, %, $(TEST_SOURCES))
PROFS = $(patsubst %.c, %, $(PROF_SOURCES))
TUNE = $(patsubst %.c, %, $(TUNE_SOURCES))
all: $(OBJS)
library: $(LIB_OBJS)
profile:
$(foreach prog, $(PROFS), $(CC) -O2 -std=c99 $(INCS) $(prog).c ../profiler.o -o $(BUILD_DIR)/$(prog) $(LIBS) -lflint;)
tune: $(TUNE_SOURCES)
$(foreach prog, $(TUNE), $(CC) -O2 -std=c99 $(INCS) $(prog).c -o $(BUILD_DIR)/$(prog) $(LIBS) -lflint;)
$(BUILD_DIR)/%.o: %.c
$(CC) $(CFLAGS) -c $(INCS) $< -o $@
$(BUILD_DIR)/%.lo: %.c
$(CC) -fPIC $(CFLAGS) $(INCS) -c $< -o $@
clean:
rm -rf $(BUILD_DIR)
check: library
$(foreach prog, $(TESTS), $(CC) $(CFLAGS) $(INCS) $(prog).c -o $(BUILD_DIR)/$(prog) $(LIBS) -lflint;)
$(foreach prog, $(TESTS), $(BUILD_DIR)/$(prog);)
.PHONY: profile clean check all

44
ufloat/log.c Normal file
View file

@ -0,0 +1,44 @@
/*=============================================================================
This file is part of FLINT.
FLINT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FLINT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FLINT; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
/* upper bound for log(2) */
#define LOG2 2977044472UL
#define LOG2_PREC 32
void
ufloat_log(ufloat_t z, const ufloat_t x)
{
if (ufloat_cmp_one(x) <= 0)
ufloat_zero(z);
else
{
mp_limb_t hi, lo;
umul_ppmm(hi, lo, x->exp, LOG2);
ufloat_set_ll_2exp(z, hi, lo, -LOG2_PREC);
}
}

44
ufloat/log1p.c Normal file
View file

@ -0,0 +1,44 @@
/*=============================================================================
This file is part of FLINT.
FLINT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FLINT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FLINT; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
void
ufloat_log1p(ufloat_t z, const ufloat_t x)
{
ufloat_t t;
if (x->exp >= -1L)
{
ufloat_one(t);
ufloat_add(t, t, x);
ufloat_log(z, t);
}
else
{
/* log(1+x) <= x, todo: improve accuracy */
ufloat_set(z, x);
}
}

87
ufloat/test/t-add.c Normal file
View file

@ -0,0 +1,87 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
int main()
{
long iter;
flint_rand_t state;
printf("add....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000000; iter++)
{
fmpz_t x, y, xy, z;
ufloat_t u, v, w;
fmpz_init(x);
fmpz_init(y);
fmpz_init(xy);
fmpz_init(z);
fmpz_randtest_not_zero(x, state, 1 + n_randint(state, 500));
fmpz_randtest_not_zero(y, state, 1 + n_randint(state, 500));
ufloat_set_fmpz(u, x);
ufloat_set_fmpz(v, y);
ufloat_add(w, u, v);
fmpz_add(xy, x, y);
ufloat_get_fmpz(z, w);
if (fmpz_cmpabs(z, xy) < 0)
{
printf("fail!\n");
printf("x = "); fmpz_print(x); printf("\n\n");
printf("y = "); fmpz_print(y); printf("\n\n");
printf("xy = "); fmpz_print(xy); printf("\n\n");
printf("z = "); fmpz_print(z); printf("\n\n");
abort();
}
if (FLINT_BIT_COUNT(w->man) != UFLOAT_PREC)
{
printf("wrong number of bits!\n");
abort();
}
fmpz_clear(x);
fmpz_clear(y);
fmpz_clear(xy);
fmpz_clear(z);
}
flint_randclear(state);
_fmpz_cleanup();
printf("PASS\n");
return EXIT_SUCCESS;
}

88
ufloat/test/t-add_2exp.c Normal file
View file

@ -0,0 +1,88 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
int main()
{
long iter;
flint_rand_t state;
printf("add_2exp....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000000; iter++)
{
fmpz_t x, y, xy, z;
ufloat_t u, w;
long exp;
fmpz_init(x);
fmpz_init(y);
fmpz_init(xy);
fmpz_init(z);
fmpz_randtest_not_zero(x, state, 1 + n_randint(state, 500));
exp = n_randint(state, 500);
fmpz_set_ui(y, 1UL);
fmpz_mul_2exp(y, y, exp);
ufloat_set_fmpz(u, x);
ufloat_add_2exp(w, u, exp);
fmpz_add(xy, x, y);
ufloat_get_fmpz(z, w);
if (fmpz_cmpabs(z, xy) < 0)
{
printf("fail!\n");
printf("x = "); fmpz_print(x); printf("\n\n");
printf("y = "); fmpz_print(y); printf("\n\n");
printf("xy = "); fmpz_print(xy); printf("\n\n");
printf("z = "); fmpz_print(z); printf("\n\n");
abort();
}
if (FLINT_BIT_COUNT(w->man) != UFLOAT_PREC)
{
printf("wrong number of bits!\n");
abort();
}
fmpz_clear(x);
fmpz_clear(y);
fmpz_clear(xy);
fmpz_clear(z);
}
flint_randclear(state);
_fmpz_cleanup();
printf("PASS\n");
return EXIT_SUCCESS;
}

89
ufloat/test/t-addmul.c Normal file
View file

@ -0,0 +1,89 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
int main()
{
long iter;
flint_rand_t state;
printf("addmul....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000000; iter++)
{
fmpz_t x, y, s, z;
ufloat_t u, v, w;
fmpz_init(x);
fmpz_init(y);
fmpz_init(s);
fmpz_init(z);
fmpz_randtest_not_zero(x, state, 1 + n_randint(state, 500));
fmpz_randtest_not_zero(y, state, 1 + n_randint(state, 500));
fmpz_randtest_not_zero(s, state, 1 + n_randint(state, 500));
ufloat_set_fmpz(u, x);
ufloat_set_fmpz(v, y);
ufloat_set_fmpz(w, s);
ufloat_addmul(w, u, v);
fmpz_addmul(s, x, y);
ufloat_get_fmpz(z, w);
if (fmpz_cmpabs(z, s) < 0)
{
printf("fail!\n");
printf("x = "); fmpz_print(x); printf("\n\n");
printf("y = "); fmpz_print(y); printf("\n\n");
printf("s = "); fmpz_print(s); printf("\n\n");
printf("z = "); fmpz_print(z); printf("\n\n");
abort();
}
if (FLINT_BIT_COUNT(w->man) != UFLOAT_PREC)
{
printf("wrong number of bits!\n");
abort();
}
fmpz_clear(x);
fmpz_clear(y);
fmpz_clear(s);
fmpz_clear(z);
}
flint_randclear(state);
_fmpz_cleanup();
printf("PASS\n");
return EXIT_SUCCESS;
}

87
ufloat/test/t-div.c Normal file
View file

@ -0,0 +1,87 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
int main()
{
long iter;
flint_rand_t state;
printf("div....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000000; iter++)
{
fmpz_t x, y, xy, z;
ufloat_t u, v, w;
fmpz_init(x);
fmpz_init(y);
fmpz_init(xy);
fmpz_init(z);
fmpz_randtest_not_zero(x, state, 1 + n_randint(state, 500));
fmpz_randtest_not_zero(y, state, 1 + n_randint(state, 500));
ufloat_set_fmpz(u, x);
ufloat_set_fmpz_lower(v, y);
ufloat_div(w, u, v);
fmpz_cdiv_q(xy, x, y);
ufloat_get_fmpz(z, w);
if (fmpz_cmpabs(z, xy) < 0)
{
printf("fail!\n");
printf("x = "); fmpz_print(x); printf("\n\n");
printf("y = "); fmpz_print(y); printf("\n\n");
printf("xy = "); fmpz_print(xy); printf("\n\n");
printf("z = "); fmpz_print(z); printf("\n\n");
abort();
}
if (FLINT_BIT_COUNT(w->man) != UFLOAT_PREC)
{
printf("wrong number of bits!\n");
abort();
}
fmpz_clear(x);
fmpz_clear(y);
fmpz_clear(xy);
fmpz_clear(z);
}
flint_randclear(state);
_fmpz_cleanup();
printf("PASS\n");
return EXIT_SUCCESS;
}

85
ufloat/test/t-log.c Normal file
View file

@ -0,0 +1,85 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include <mpfr.h>
#include "ufloat.h"
int main()
{
long iter;
flint_rand_t state;
printf("log....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000000; iter++)
{
mpfr_t x, y, z;
ufloat_t u, v;
if (n_randint(state, 2))
ufloat_randtest(u, state, 10);
else
ufloat_randtest(u, state, 1L << 30);
mpfr_init2(x, FLINT_BITS);
mpfr_init2(y, FLINT_BITS);
mpfr_init2(z, FLINT_BITS);
ufloat_log(v, u);
ufloat_get_mpfr(x, u);
ufloat_get_mpfr(y, v);
mpfr_log(z, x, MPFR_RNDU);
if ((FLINT_BIT_COUNT(v->man) != UFLOAT_PREC) && (v->man != 0))
{
printf("wrong number of bits!\n");
abort();
}
if (mpfr_cmp(z, y) > 0)
{
printf("fail!\n");
printf("x = "); mpfr_printf("%.20Rg", x); printf("\n\n");
printf("y = "); mpfr_printf("%.20Rg", y); printf("\n\n");
printf("z = "); mpfr_printf("%.20Rg", z); printf("\n\n");
abort();
}
mpfr_clear(x);
mpfr_clear(y);
mpfr_clear(z);
}
flint_randclear(state);
mpfr_free_cache();
printf("PASS\n");
return EXIT_SUCCESS;
}

87
ufloat/test/t-mul.c Normal file
View file

@ -0,0 +1,87 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
int main()
{
long iter;
flint_rand_t state;
printf("mul....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000000; iter++)
{
fmpz_t x, y, xy, z;
ufloat_t u, v, w;
fmpz_init(x);
fmpz_init(y);
fmpz_init(xy);
fmpz_init(z);
fmpz_randtest_not_zero(x, state, 1 + n_randint(state, 500));
fmpz_randtest_not_zero(y, state, 1 + n_randint(state, 500));
ufloat_set_fmpz(u, x);
ufloat_set_fmpz(v, y);
ufloat_mul(w, u, v);
fmpz_mul(xy, x, y);
ufloat_get_fmpz(z, w);
if (fmpz_cmpabs(z, xy) < 0)
{
printf("fail!\n");
printf("x = "); fmpz_print(x); printf("\n\n");
printf("y = "); fmpz_print(y); printf("\n\n");
printf("xy = "); fmpz_print(xy); printf("\n\n");
printf("z = "); fmpz_print(z); printf("\n\n");
abort();
}
if (FLINT_BIT_COUNT(w->man) != UFLOAT_PREC)
{
printf("wrong number of bits!\n");
abort();
}
fmpz_clear(x);
fmpz_clear(y);
fmpz_clear(xy);
fmpz_clear(z);
}
flint_randclear(state);
_fmpz_cleanup();
printf("PASS\n");
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,80 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
int main()
{
long iter;
flint_rand_t state;
printf("set_ll_2exp....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 100000; iter++)
{
ufloat_t u;
mp_limb_t hi, lo;
fmpz_t a, b;
long exp;
hi = n_randtest(state);
lo = n_randtest(state);
exp = n_randint(state, 200);
ufloat_set_ll_2exp(u, hi, lo, exp);
fmpz_init(a);
fmpz_init(b);
fmpz_set_ui(a, hi);
fmpz_mul_2exp(a, a, FLINT_BITS);
fmpz_add_ui(a, a, lo);
fmpz_mul_2exp(a, a, exp);
ufloat_get_fmpz(b, u);
if (fmpz_cmp(a, b) > 0 || fmpz_bits(b) > fmpz_bits(a) + 1)
{
printf("fail!\n");
printf("hi = %lu\n", hi);
printf("lo = %lu\n", lo);
printf("exp = %ld\n", exp);
printf("u = "); ufloat_print(u); printf("\n\n");
abort();
}
fmpz_clear(a);
fmpz_clear(b);
}
flint_randclear(state);
_fmpz_cleanup();
printf("PASS\n");
return EXIT_SUCCESS;
}

67
ufloat/test/t-set_mpfr.c Normal file
View file

@ -0,0 +1,67 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
int main()
{
long iter;
flint_rand_t state;
printf("set_mpfr....");
fflush(stdout);
flint_randinit(state);
/* Exact roundtrip */
for (iter = 0; iter < 100000; iter++)
{
ufloat_t u, v;
mpfr_t x;
mpfr_init2(x, UFLOAT_PREC);
ufloat_randtest(u, state, 10);
ufloat_get_mpfr(x, u);
ufloat_set_mpfr(v, x);
if (!ufloat_equal(u, v))
{
printf("fail!\n");
printf("u = "); ufloat_print(u); printf("\n\n");
printf("v = "); ufloat_print(v); printf("\n\n");
abort();
}
mpfr_clear(x);
}
flint_randclear(state);
_fmpz_cleanup();
printf("PASS\n");
return EXIT_SUCCESS;
}

98
ufloat/test/t-sub.c Normal file
View file

@ -0,0 +1,98 @@
/*=============================================================================
This file is part of ARB.
ARB is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
ARB is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ARB; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
=============================================================================*/
/******************************************************************************
Copyright (C) 2012 Fredrik Johansson
******************************************************************************/
#include "ufloat.h"
int main()
{
long iter;
flint_rand_t state;
printf("sub....");
fflush(stdout);
flint_randinit(state);
for (iter = 0; iter < 1000000; iter++)
{
fmpz_t x, y, xy, z;
ufloat_t u, v, w;
fmpz_init(x);
fmpz_init(y);
fmpz_init(xy);
fmpz_init(z);
fmpz_randtest_not_zero(x, state, 1 + n_randint(state, 500));
fmpz_randtest_not_zero(y, state, 1 + n_randint(state, 500));
fmpz_abs(x, x);
fmpz_abs(y, y);
if (fmpz_cmp(x, y) >= 0)
{
ufloat_set_fmpz(u, x);
ufloat_set_fmpz_lower(v, y);
}
else
{
ufloat_set_fmpz_lower(u, x);
ufloat_set_fmpz(v, y);
}
ufloat_sub(w, u, v);
fmpz_sub(xy, x, y);
ufloat_get_fmpz(z, w);
if (fmpz_cmpabs(z, xy) < 0)
{
printf("fail!\n");
printf("x = "); fmpz_print(x); printf("\n\n");
printf("y = "); fmpz_print(y); printf("\n\n");
printf("xy = "); fmpz_print(xy); printf("\n\n");
printf("z = "); fmpz_print(z); printf("\n\n");
abort();
}
if (!(FLINT_BIT_COUNT(w->man) == UFLOAT_PREC ||
w->man == 0))
{
printf("wrong number of bits!\n");
abort();
}
fmpz_clear(x);
fmpz_clear(y);
fmpz_clear(xy);
fmpz_clear(z);
}
flint_randclear(state);
_fmpz_cleanup();
printf("PASS\n");
return EXIT_SUCCESS;
}