| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "Float.h" |
| #include <decaf/lang/Integer.h> |
| #include <decaf/lang/ArrayPointer.h> |
| #include <limits> |
| #include <string.h> |
| |
| using namespace std; |
| using namespace decaf; |
| using namespace decaf::lang; |
| using namespace decaf::lang::exceptions; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| const int Float::SIZE = 32; |
| const float Float::MAX_VALUE = 3.40282346638528860e+38f; |
| const float Float::MIN_VALUE = 1.40129846432481707e-45f; |
| const float Float::NaN = std::numeric_limits<float>::quiet_NaN(); |
| const float Float::POSITIVE_INFINITY = std::numeric_limits<float>::infinity(); |
| const float Float::NEGATIVE_INFINITY = -std::numeric_limits<float>::infinity(); |
| |
| const unsigned int Float::SINGLE_EXPONENT_MASK = 0x7F800000; |
| const unsigned int Float::SINGLE_MANTISSA_MASK = 0x007FFFFF; |
| const unsigned int Float::SINGLE_NAN_BITS = (SINGLE_EXPONENT_MASK | 0x00400000); |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Float::Float(float value) : value(value) { |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Float::Float(double value) : value((float) value) { |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Float::Float(const String& value) : value(0) { |
| this->value = Float::parseFloat(value); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Float::compareTo(const Float& f) const { |
| return Float::compare(this->value, f.value); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Float::compareTo(const float& f) const { |
| return Float::compare(this->value, f); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string Float::toString() const { |
| return Float::toString(this->value); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| bool Float::isInfinite() const { |
| return Float::isInfinite(this->value); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| bool Float::isNaN() const { |
| return Float::isNaN(this->value); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Float::compare(float f1, float f2) { |
| |
| int i1, i2 = 0; |
| long NaNbits = Float::floatToIntBits(Float::NaN); |
| |
| if ((i1 = Float::floatToIntBits(f1)) == NaNbits) { |
| if (Float::floatToIntBits(f2) == NaNbits) { |
| return 0; |
| } |
| return 1; |
| } |
| |
| if ((i2 = Float::floatToIntBits(f2)) == NaNbits) { |
| return -1; |
| } |
| |
| if (f1 == f2) { |
| if (i1 == i2) { |
| return 0; |
| } |
| |
| // check for -0 |
| return i1 > i2 ? 1 : -1; |
| } |
| |
| return f1 > f2 ? 1 : -1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Float::floatToIntBits(float value) { |
| |
| int intValue = 0; |
| memcpy(&intValue, &value, sizeof(float)); |
| |
| if ((intValue & SINGLE_EXPONENT_MASK) == SINGLE_EXPONENT_MASK) { |
| if (intValue & SINGLE_MANTISSA_MASK) { |
| return SINGLE_NAN_BITS; |
| } |
| } |
| |
| return intValue; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| int Float::floatToRawIntBits(float value) { |
| int intValue = 0; |
| memcpy(&intValue, &value, sizeof(float)); |
| return intValue; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| float Float::intBitsToFloat(int bits) { |
| float floatValue = 0; |
| memcpy(&floatValue, &bits, sizeof(int)); |
| return floatValue; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| bool Float::isInfinite(float value) { |
| return (value == POSITIVE_INFINITY) || (value == NEGATIVE_INFINITY); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| bool Float::isNaN(float value) { |
| return value != value; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| float Float::parseFloat(const String& value) { |
| |
| // TODO - This is not going to parse the formats we say we do. |
| float result = 0.0; |
| |
| ArrayPointer<char> buffer(value.length() + 1); |
| value.getChars(0, value.length(), buffer.get(), value.length() + 1, 0); |
| |
| istringstream stream(buffer.get()); |
| stream >> result; |
| |
| // Not everything got read, meaning there wasn't just a number here. |
| if (!stream.eof()) { |
| throw exceptions::NumberFormatException( |
| __FILE__, __LINE__, |
| "Failed to parse a valid float from input string: %s", value.c_str()); |
| } |
| |
| return result; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string Float::toHexString(float value) { |
| /* |
| * Reference: http://en.wikipedia.org/wiki/IEEE_754 |
| */ |
| if (value != value) { |
| return "NaN"; |
| } |
| if (value == POSITIVE_INFINITY) { |
| return "Infinity"; |
| } |
| if (value == NEGATIVE_INFINITY) { |
| return "-Infinity"; |
| } |
| |
| unsigned int bitValue = Float::floatToIntBits(value); |
| |
| bool negative = (bitValue & 0x80000000) != 0; |
| // mask exponent bits and shift down |
| unsigned int exponent = (bitValue & 0x7f800000) >> 23; |
| // mask significand bits and shift up |
| // significand is 23-bits, so we shift to treat it like 24-bits |
| unsigned int significand = (bitValue & 0x007FFFFF) << 1; |
| |
| if (exponent == 0 && significand == 0) { |
| return (negative ? "-0x0.0p0" : "0x0.0p0"); |
| } |
| |
| // Start with the correct sign and Hex indicator |
| std::string hexString(negative ? "-0x" : "0x"); |
| |
| if (exponent == 0) { |
| // denormal (subnormal) value |
| hexString.append("0."); |
| // significand is 23-bits, so there can be 6 hex digits |
| unsigned int fractionDigits = 6; |
| // remove trailing hex zeros, so Integer.toHexString() won't print |
| // them |
| while ((significand != 0) && ((significand & 0xF) == 0)) { |
| significand >>= 4; |
| fractionDigits--; |
| } |
| // this assumes Integer.toHexString() returns lowercase characters |
| std::string hexSignificand = Integer::toHexString(significand); |
| |
| // if there are digits left, then insert some '0' chars first |
| if (significand != 0 && fractionDigits > hexSignificand.length()) { |
| unsigned int digitDiff = fractionDigits - (int) hexSignificand.length(); |
| while (digitDiff-- != 0) { |
| hexString.append("0"); |
| } |
| } |
| hexString.append(hexSignificand); |
| hexString.append("p-126"); |
| } else { |
| // normal value |
| hexString.append("1."); |
| // significand is 23-bits, so there can be 6 hex digits |
| unsigned int fractionDigits = 6; |
| // remove trailing hex zeros, so Integer.toHexString() won't print |
| // them |
| while ((significand != 0) && ((significand & 0xF) == 0)) { |
| significand >>= 4; |
| fractionDigits--; |
| } |
| // this assumes Integer.toHexString() returns lowercase characters |
| std::string hexSignificand = Integer::toHexString(significand); |
| |
| // if there are digits left, then insert some '0' chars first |
| if (significand != 0 && fractionDigits > hexSignificand.length()) { |
| unsigned int digitDiff = fractionDigits - (int) hexSignificand.length(); |
| while (digitDiff-- != 0) { |
| hexString.append("0"); |
| } |
| } |
| hexString.append(hexSignificand); |
| hexString.append("p"); |
| // remove exponent's 'bias' and convert to a string |
| hexString.append(Integer::toString(exponent - 127)); |
| } |
| |
| return hexString; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| std::string Float::toString(float value) { |
| // TODO - This is not going to support the formats we say we do. |
| ostringstream stream; |
| stream << value; |
| return stream.str(); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Float Float::valueOf(float value) { |
| return Float(value); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| Float Float::valueOf(const String& value) { |
| return valueOf(parseFloat(value)); |
| } |