gcc/libjava/java/lang/natDouble.cc

215 lines
4.0 KiB
C++
Raw Normal View History

// natDouble.cc - Implementation of java.lang.VMDouble native methods.
1999-04-07 16:42:40 +02:00
/* Copyright (C) 1998, 1999, 2000, 2001, 2003, 2005, 2006 Free Software Foundation
1999-04-07 16:42:40 +02:00
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
1999-11-19 20:13:42 +01:00
#include <config.h>
1999-04-07 16:42:40 +02:00
#include <stdlib.h>
#include <gcj/cni.h>
1999-04-07 16:42:40 +02:00
#include <java/lang/String.h>
#include <java/lang/Double.h>
#include <java/lang/VMDouble.h>
#include <java/lang/Character.h>
1999-04-07 16:42:40 +02:00
#include <java/lang/NumberFormatException.h>
#include <jvm.h>
#include <stdio.h>
#include <string.h>
#include "fdlibm.h"
1999-04-07 16:42:40 +02:00
union u
{
jlong l;
jdouble d;
};
jlong
java::lang::VMDouble::doubleToLongBits(jdouble value)
1999-04-07 16:42:40 +02:00
{
union u u;
u.d = value;
jlong e = u.l & 0x7ff0000000000000LL;
jlong f = u.l & 0x000fffffffffffffLL;
if (e == 0x7ff0000000000000LL && f != 0L)
u.l = 0x7ff8000000000000LL;
1999-04-07 16:42:40 +02:00
return u.l;
}
jlong
java::lang::VMDouble::doubleToRawLongBits(jdouble value)
{
union u u;
u.d = value;
return u.l;
}
1999-04-07 16:42:40 +02:00
jdouble
java::lang::VMDouble::longBitsToDouble(jlong bits)
1999-04-07 16:42:40 +02:00
{
union u u;
u.l = bits;
return u.d;
}
jstring
java::lang::VMDouble::toString(jdouble value, jboolean isFloat)
1999-04-07 16:42:40 +02:00
{
if (Double::isNaN (value))
1999-04-07 16:42:40 +02:00
return JvNewStringLatin1 ("NaN", sizeof ("NaN") - 1);
if (value == Double::POSITIVE_INFINITY)
1999-04-07 16:42:40 +02:00
return JvNewStringLatin1 ("Infinity", sizeof ("Infinity") - 1);
if (value == Double::NEGATIVE_INFINITY)
1999-04-07 16:42:40 +02:00
return JvNewStringLatin1 ("-Infinity", sizeof ("-Infinity") - 1);
char buffer[50], result[50];
int decpt, sign;
_dtoa (value, 0, 20, &decpt, &sign, NULL, buffer, (int)isFloat);
value = fabs (value);
char *s = buffer;
char *d = result;
if (sign)
*d++ = '-';
if (value >= 1e-3 && value < 1e7 || value == 0)
{
if (decpt <= 0)
*d++ = '0';
else
{
for (int i = 0; i < decpt; i++)
if (*s)
*d++ = *s++;
else
*d++ = '0';
}
*d++ = '.';
if (*s == 0)
{
*d++ = '0';
decpt++;
}
while (decpt++ < 0)
*d++ = '0';
while (*s)
*d++ = *s++;
*d = 0;
return JvNewStringLatin1 (result, strlen (result));
}
*d++ = *s++;
decpt--;
*d++ = '.';
if (*s == 0)
*d++ = '0';
while (*s)
*d++ = *s++;
*d++ = 'E';
if (decpt < 0)
{
*d++ = '-';
decpt = -decpt;
}
{
char exp[4];
char *e = exp + sizeof exp;
*--e = 0;
do
{
*--e = '0' + decpt % 10;
decpt /= 10;
}
while (decpt > 0);
while (*e)
*d++ = *e++;
}
*d = 0;
return JvNewStringLatin1 (result, strlen (result));
}
jdouble
java::lang::VMDouble::parseDouble(jstring str)
1999-04-07 16:42:40 +02:00
{
int length = str->length();
while (length > 0
&& Character::isWhitespace(str->charAt(length - 1)))
length--;
// The String could end with a f/F/d/D which is valid but we don't need.
bool saw_trailer = false;
if (length > 0)
{
jchar last = str->charAt(length-1);
if (last == 'f' || last == 'F' || last == 'd' || last == 'D')
{
length--;
saw_trailer = true;
}
}
jsize start = 0;
while (length > 0
&& Character::isWhitespace(str->charAt(start)))
start++, length--;
if (length > 0)
{
// Note that UTF can expand 3x.
char *data = (char *) __builtin_alloca (3 * length + 1);
jsize blength = _Jv_GetStringUTFRegion (str, start, length, data);
data[blength] = 0;
if (! saw_trailer)
{
if (! strcmp (data, "NaN") || ! strcmp (data, "+NaN")
|| ! strcmp (data, "-NaN"))
return Double::NaN;
else if (! strcmp (data, "Infinity") || ! strcmp (data, "+Infinity"))
return Double::POSITIVE_INFINITY;
else if (! strcmp (data, "-Infinity"))
return Double::NEGATIVE_INFINITY;
}
struct _Jv_reent reent;
memset (&reent, 0, sizeof reent);
char *endptr;
double val = _strtod_r (&reent, data, &endptr);
if (endptr == data + blength)
return val;
}
throw new NumberFormatException(str);
1999-04-07 16:42:40 +02:00
}