// -*- c++ -*- /* * Jakelib2 - General purpose C++ library * Copyright (C) 2001 Florian Wolff (florian@donuz.de) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: Double.jlc,v 1.4 2003/09/27 08:10:28 florian Exp $ */ #include "jakelib2.h" #include "jakelib2/lang/Double.h" #include "jakelib2/lang/Integer.h" #include "jakelib2/lang/Character.h" #include #include // FIXME: where does come from? do we need it? //+++AlFa 02-10-03 is ANSI header. // if we define our own DBL_MAX and DBL_MIN here, // FLT_MAX and FLT_MIN in float.cpp // and '#define Bad_float_h' in dtoa.c then we don't need it //---AlFa 02-10-03 //#include using namespace jakelib::lang; JAKELIB_IMPLEMENT_CLASS_1("jakelib.lang.Double", Double, Number, Comparable); #define DBL_MAX 1.7976931348623158e+308 /* max value */ #define DBL_MIN 2.2250738585072014e-308 /* min positive value */ const jdouble Double::MAX_VALUE = DBL_MAX; const jdouble Double::MIN_VALUE = DBL_MIN; const jdouble Double::ZERO = (jdouble) 0.0; const jdouble Double::NEGATIVE_INFINITY = ((jdouble) -1.0)/Double::ZERO;//LL(0xFFF0000000000000); const jdouble Double::POSITIVE_INFINITY = ((jdouble) 1.0)/Double::ZERO;//LL(0x7FF0000000000000); const jdouble Double::NaN = sqrt(-2.01); const unsigned int* Double::firstNanWord = (const unsigned int*) &NaN; const unsigned int* Double::secondNanWord = Double::firstNanWord + 1; const jint Double::DEFAULT_DIGITS = 6;//digits after decimal point /*****************************************************************************\ * Double | *****************************************************************************/ Double::Double(jdouble value) { this->value = value; } Double::Double(String* s) { value = parseDouble(s); } /*****************************************************************************\ * hashCode | *****************************************************************************/ jint Double::hashCode() { jlong v = (jlong) value; return (jint) (v ^ (v >> 32)); } /*****************************************************************************\ * equals | *****************************************************************************/ jboolean Double::equals(Object* obj) { if (obj == null || !obj->getClass()->isInstance(this)) return false; Double* object = (Double*) obj; return ( value == object->value ); } /*****************************************************************************\ * toString | *****************************************************************************/ String* Double::toString() { return toString(value); } String* Double::toString(jdouble value, jint ndigits) { if (value == 0) return new String("0"); char buf[30]; sprintf(buf, "%f", value); return new String(buf); // Commented out since it crashes Solaris: // const char zero = '0'; // const char dot = '.'; // const char minus = '-'; // //this is a workaround for use of default # of digits after decimal point; // //static function will not take default argument // //(i.e. ndigits is always 0, regardless of what is specified as default value in declaration) // if (!ndigits) // ndigits = Double::DEFAULT_DIGITS; // int decpt, sign; // char* rawstr = dtoa(value, 0, ndigits, &decpt, &sign, NULL); // jint rawlen = strlen(rawstr); // jint len = rawlen + ((decpt<0)?((jint) fabs(decpt) + 3):0) + ((decpt < rawlen)?2:6); // char* strno = new char[len]; // char* curpos = strno; // char* exp = null; // if (decpt == 9999) { // if (isNaN(value)) // return new String("NaN"); // else if (isPositiveInfinite(value)) // return new String("+Inf"); // else if (isNegativeInfinite(value)) // return new String("-Inf"); // } // if ((jint) fabs(decpt) > rawlen) { // exp = new char[32]; // memset(exp, 0, sizeof(exp)); // sprintf(exp, "e%s%.3d", decpt<0?"":"+", --decpt); // decpt = 1; // } // if (sign) // *curpos++ = minus; // if (decpt < 0) { // int pos = (jint) fabs(decpt); // *curpos++ = zero; // *curpos++ = dot; // memset(curpos, zero, pos); // curpos += pos; // memcpy(curpos, rawstr, strlen(rawstr) + 1); // } // else { // if (decpt == 0) // *curpos++ = zero; // memcpy(curpos, rawstr, decpt); // curpos += decpt; // *curpos++ = dot; // memcpy(curpos, rawstr+decpt, strlen(rawstr) - decpt + 1); // } // strno[(strchr(strno, dot)-strno+1) + ndigits] = '\0'; // if (exp) // strcat(strno, exp); // return new String(strno); } /*****************************************************************************\ * parseInt | *****************************************************************************/ jdouble Double::parseDouble(String* str) { if (str == null) throw new NumberFormatException(`"null"` .. JAKELIB_AT2("jakelib.lang.Double.parseDouble")); char* ptr; jdouble v = strtod(str->latin1(), &ptr); if (*ptr != '\0') throw new NumberFormatException(str .. JAKELIB_AT2("jakelib.lang.Double.parseDouble")); return v; } jdouble Double::parseDouble(const char* str) { if (str == null) throw new NumberFormatException(`"null"` .. JAKELIB_AT2("jakelib.lang.Double.parseDouble")); char* ptr; jdouble v = strtod(str, &ptr); if (*ptr != '\0') throw new NumberFormatException(`""` .. str .. JAKELIB_AT2("jakelib.lang.Double.parseDouble")); return v; } /*****************************************************************************\ * xxxValue | *****************************************************************************/ jbyte Double::byteValue() { return (jbyte) value; }; jfloat Double::floatValue() { return (jfloat) value; }; jint Double::intValue() { return (jint) value; }; jlong Double::longValue() { return (jlong) value; }; jdouble Double::doubleValue() { return (jdouble) value; }; jshort Double::shortValue() { return (jshort) value;} ; /*****************************************************************************\ * valueOf | *****************************************************************************/ Double* Double::valueOf(String* str) { return new Double(parseDouble(str)); } /*****************************************************************************\ * compareTo | *****************************************************************************/ int Double::compareTo(Double* obj) { jdouble otherValue = obj->value; return (value < otherValue ? -1 : (value > otherValue ? 1 : 0)); } int Double::compareTo(Object* obj) { return compareTo((Double*) obj); } /*****************************************************************************\ * isNaN | *****************************************************************************/ jboolean Double::isNaN(jdouble v) { //+++AlFa 02/05/2003 this is how it's done in Xalan (should be portable, except AIX). // however, it was tested on MSVC only const unsigned int* firstDword = (const unsigned int*) &v; const unsigned int* secondDword = firstDword + 1; return ((*firstDword == *Double::firstNanWord) && (*secondDword == *Double::secondNanWord)); } /*****************************************************************************\ * isInfinite | *****************************************************************************/ jboolean Double::isInfinite(jdouble v) { return ((v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY)); } /*****************************************************************************\ * isNegativeInfinite | *****************************************************************************/ jboolean Double::isNegativeInfinite(jdouble v) { return (v == NEGATIVE_INFINITY); } /*****************************************************************************\ * isPositiveInfinite | *****************************************************************************/ jboolean Double::isPositiveInfinite(jdouble v) { return (v == POSITIVE_INFINITY); } /*****************************************************************************\ * doubleToLongBits | *****************************************************************************/ jlong Double::doubleToLongBits(jdouble doubleValue) { jvalue val; jlong e, f; val.d = doubleValue; e = val.j & LL(0x7ff0000000000000); f = val.j & LL(0x000fffffffffffff); if ((e == LL(0x7ff0000000000000)) && (f != 0L)) val.j = LL(0x7ff8000000000000); return val.j; } /*****************************************************************************\ * doubleToRawLongBits | *****************************************************************************/ jlong Double::doubleToRawLongBits(jdouble doubleValue) { jvalue val; val.d = doubleValue; return val.j; } /*****************************************************************************\ * longBitsToDouble | *****************************************************************************/ jdouble Double::longBitsToDouble(jlong longValue) { jvalue val; val.j = longValue; return val.d; }