Fixed version of nextafter[f]/c for 80386 math lib v2.0
Glenn Geers
glenn at qed.physics.su.OZ.AU
Tue Dec 18 06:50:50 AEST 1990
Hi,
nextafter[f]() was overflowing the 80387 register set if called repeatedly.
A fixed version is attached to this posting.
Glenn
#!/bin/sh
# This is a shell archive (shar 3.47)
# made 12/17/1990 19:29 UTC by glenn at trantor
# Source directory /tmp
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1743 -rw-r--r-- nextafter.c
# 1735 -rw-r--r-- nextafterf.c
#
# ============= nextafter.c ==============
if test -f 'nextafter.c' -a X"$1" != X"-c"; then
echo 'x - skipping nextafter.c (File already exists)'
else
echo 'x - extracting nextafter.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'nextafter.c' &&
/*
** This file is part of the alternative 80386 math library and is
** covered by the GNU General Public license with my modification
** as noted in the README file that accompanied this file.
**
** Copyright 1990 G. Geers
**
** A mix of C and assembler - well I've got the functions so I might
** as well use them!
**
*/
X
#include "fpumath.h"
X
asm(".align 4");
asm(".Lulp:");
asm(".double 1.1102230246251565e-16");
X
asm(".align 4");
asm(".Lulpup:");
asm(".double 2.2204460492503131e-16");
X
double
nextafter(x, y)
double x, y;
{
X asm("subl $8, %esp");
X
X if (isnan(x) || isnan(y))
X return(quiet_nan(1.0));
X
X if (isinf(x))
X if (y > x)
X return(-max_normal());
X else
X if (y < x)
X return(max_normal());
X
X if (x == 0.0)
X if (y > 0.0)
X return(min_subnormal());
X else
X return(-min_subnormal());
X
X if (isnormal(x)) {
X if ((x == min_normal()) && y < x)
X return(max_subnormal());
X
X if ((x == max_normal()) && y > x)
X return(infinity());
X
X if ((x == -max_normal()) && y < x)
X return(-infinity());
X
X asm("movl 12(%ebp), %eax");
X asm("andl $0x7ff00000, %eax");
X asm("movl %eax, -12(%ebp)");
X asm("movl $0x0, -16(%ebp)");
X asm("fincstp");
X
X if (fabs(x) <= 2.0 && y < x)
X asm("fldl .Lulp");
X else
X asm("fldl .Lulpup");
X
X asm("fldl -16(%ebp)");
X asm("fmulp");
X
X if (y > x) {
X asm("fldl 8(%ebp)");
X asm("faddp");
X asm("leave");
X asm("ret");
X }
X if (y < x) {
X asm("fldl 8(%ebp)");
X asm("fsubp");
X asm("leave");
X asm("ret");
X }
X }
X else
X if (issubnormal(x)) {
X if ((x == max_subnormal()) && y > x)
X return(min_normal());
X
X if ((x == -max_subnormal()) && y < x)
X return(-min_normal());
X
X if (y > x)
X return(x + min_subnormal());
X
X if (y < x)
X return(x - min_subnormal());
X }
X
X return(x);
}
SHAR_EOF
chmod 0644 nextafter.c ||
echo 'restore of nextafter.c failed'
Wc_c="`wc -c < 'nextafter.c'`"
test 1743 -eq "$Wc_c" ||
echo 'nextafter.c: original size 1743, current size' "$Wc_c"
fi
# ============= nextafterf.c ==============
if test -f 'nextafterf.c' -a X"$1" != X"-c"; then
echo 'x - skipping nextafterf.c (File already exists)'
else
echo 'x - extracting nextafterf.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'nextafterf.c' &&
/*
** This file is part of the alternative 80386 math library and is
** covered by the GNU General Public license with my modification
** as noted in the README file that accompanied this file.
**
** Copyright 1990 G. Geers
**
** A mix of C and assembler - well I've got the functions so I might
** as well use them!
**
*/
X
#include "fpumath.h"
X
asm(".align 4");
asm(".Lulp:");
asm(".double 5.9604644775390625e-08");
X
asm(".align 4");
asm(".Lulpup:");
asm(".double 1.1920928955078125e-07");
X
float
nextafterf(float x, float y)
{
X asm("subl $8, %esp");
X
X if (isnanf(x) || isnanf(y))
X return(quiet_nanf(1.0));
X
X if (isinff(x))
X if (y > x)
X return(-max_normalf());
X else
X if (y < x)
X return(max_normalf());
X
X if (x == 0.0) {
X if (y > 0.0)
X return(min_subnormalf());
X else
X return(-min_subnormalf());
X }
X
X if (isnormalf(x)) {
X if ((x == min_normalf()) && y < x)
X return(max_subnormalf());
X
X if ((x == max_normalf()) && y > x)
X return(infinityf());
X
X if ((x == -max_normalf()) && y < x)
X return(-infinityf());
X
X asm("movl 8(%ebp), %eax");
X asm("andl $0x7f800000, %eax");
X asm("movl %eax, -8(%ebp)");
X asm("fincstp");
X
X if (fabsf(x) <= 2.0 && y < x)
X asm("fldl .Lulp");
X else
X asm("fldl .Lulpup");
X
X asm("flds -8(%ebp)");
X asm("fmulp");
X
X if (y > x) {
X asm("flds 8(%ebp)");
X asm("faddp");
X asm("leave");
X asm("ret");
X }
X if (y < x) {
X asm("flds 8(%ebp)");
X asm("fsubp");
X asm("leave");
X asm("ret");
X }
X }
X else
X if (issubnormalf(x)) {
X if ((x == max_subnormalf()) && y > x)
X return(min_normalf());
X
X if ((x == -max_subnormalf()) && y < x)
X return(-min_normalf());
X
X if (y > x)
X return(x + min_subnormalf());
X
X if (y < x)
X return(x - min_subnormalf());
X }
X
X return(x);
}
SHAR_EOF
chmod 0644 nextafterf.c ||
echo 'restore of nextafterf.c failed'
Wc_c="`wc -c < 'nextafterf.c'`"
test 1735 -eq "$Wc_c" ||
echo 'nextafterf.c: original size 1735, current size' "$Wc_c"
fi
exit 0
--
Glenn Geers | "So when it's over, we're back to people.
Department of Theoretical Physics | Just to prove that human touch can have
The University of Sydney | no equal."
Sydney NSW 2006 Australia | - Basia Trzetrzelewska, 'Prime Time TV'
More information about the Alt.sources
mailing list