mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:arangodb/arangodb into devel
This commit is contained in:
commit
597ce40879
|
@ -1,5 +1,11 @@
|
|||
v2.5.0-alpha2 (2015-02-16)
|
||||
-------------------
|
||||
--------------------------
|
||||
|
||||
* fixed issue #1230: API: document/col-name/_key and cursor return different floats
|
||||
|
||||
|
||||
v2.5.0-beta1 (2015-02-23)
|
||||
-------------------------
|
||||
|
||||
* front-end: dashboard tries not to (re)load statistics if user has no access
|
||||
|
||||
|
|
|
@ -0,0 +1,451 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite for fpconv.cpp
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed 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.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2015, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "Basics/StringBuffer.h"
|
||||
#include "Basics/fpconv.h"
|
||||
#include "Basics/json.h"
|
||||
#include "Basics/string-buffer.h"
|
||||
|
||||
using namespace triagens::basics;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- setup / tear-down
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
struct CFpconvSetup {
|
||||
CFpconvSetup () {
|
||||
BOOST_TEST_MESSAGE("setup fpconv");
|
||||
}
|
||||
|
||||
~CFpconvSetup () {
|
||||
BOOST_TEST_MESSAGE("tear-down fpconv");
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- test suite
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief setup
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(CFpconvTest, CFpconvSetup)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test nan
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_nan) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = NAN;
|
||||
BOOST_CHECK_EQUAL(true, std::isnan(value));
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("NaN"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("NaN"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test infinity
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_inf) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = INFINITY;
|
||||
BOOST_CHECK_EQUAL(false, std::isfinite(value));
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("inf"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("inf"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test huge val
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_huge_val) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = HUGE_VAL;
|
||||
BOOST_CHECK_EQUAL(false, std::isfinite(value));
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("inf"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("inf"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test huge val
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_huge_val_neg) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = -HUGE_VAL;
|
||||
BOOST_CHECK_EQUAL(false, std::isfinite(value));
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("-inf"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("-inf"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test zero
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_zero) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = 0;
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("0"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("0"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test zero
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_zero_neg) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = -0;
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("0"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("0"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test high
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_value_high) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = 4.32e261;
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("4.32e+261"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("4.32e+261"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test low
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_value_low) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = -4.32e261;
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("-4.32e+261"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("-4.32e+261"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test small
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_value_small) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = 4.32e-261;
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("4.32e-261"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("4.32e-261"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test mchacki's value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_value_mchacki1) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = 1.374;
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("1.374"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("1.374"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test mchacki's value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_value_mchacki2) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = 56.94837631946843;
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("56.94837631946843"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("56.94837631946843"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test one third roundtrip
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_value_mchacki2_roundtrip) {
|
||||
double value;
|
||||
|
||||
value = 56.94837631946843;
|
||||
|
||||
TRI_string_buffer_t buffer;
|
||||
TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
auto json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, value);
|
||||
TRI_StringifyJson(&buffer, json);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("56.94837631946843"), std::string(buffer._buffer, buffer._current - buffer._buffer));
|
||||
|
||||
auto json2 = TRI_Json2String(TRI_UNKNOWN_MEM_ZONE, buffer._buffer, nullptr);
|
||||
BOOST_CHECK_EQUAL(TRI_JSON_NUMBER, json2->_type);
|
||||
BOOST_CHECK_EQUAL(value, json2->_value._number);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json2);
|
||||
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
TRI_DestroyStringBuffer(&buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test one third
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_one_third) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = 1.0 / 3.0;
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("0.3333333333333333"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("0.3333333333333333"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test one third roundtrip
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_one_third_roundtrip) {
|
||||
double value;
|
||||
|
||||
value = 1.0 / 3.0;
|
||||
|
||||
TRI_string_buffer_t buffer;
|
||||
TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
auto json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, value);
|
||||
TRI_StringifyJson(&buffer, json);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("0.3333333333333333"), std::string(buffer._buffer, buffer._current - buffer._buffer));
|
||||
|
||||
auto json2 = TRI_Json2String(TRI_UNKNOWN_MEM_ZONE, buffer._buffer, nullptr);
|
||||
BOOST_CHECK_EQUAL(TRI_JSON_NUMBER, json2->_type);
|
||||
BOOST_CHECK_EQUAL(value, json2->_value._number);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json2);
|
||||
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
TRI_DestroyStringBuffer(&buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test 0.4
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_04) {
|
||||
char out[24];
|
||||
double value;
|
||||
int length;
|
||||
|
||||
value = 0.1 + 0.3;
|
||||
length = fpconv_dtoa(value, out);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("0.4"), std::string(out, length));
|
||||
|
||||
StringBuffer buf(TRI_UNKNOWN_MEM_ZONE);
|
||||
buf.appendDecimal(value);
|
||||
BOOST_CHECK_EQUAL(std::string("0.4"), std::string(buf.c_str(), buf.length()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test 0.4
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_04_roundtrip) {
|
||||
double value;
|
||||
|
||||
value = 0.1 + 0.3;
|
||||
|
||||
TRI_string_buffer_t buffer;
|
||||
TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
auto json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, value);
|
||||
TRI_StringifyJson(&buffer, json);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("0.4"), std::string(buffer._buffer, buffer._current - buffer._buffer));
|
||||
|
||||
auto json2 = TRI_Json2String(TRI_UNKNOWN_MEM_ZONE, buffer._buffer, nullptr);
|
||||
BOOST_CHECK_EQUAL(TRI_JSON_NUMBER, json2->_type);
|
||||
BOOST_CHECK_EQUAL(value, json2->_value._number);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json2);
|
||||
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
TRI_DestroyStringBuffer(&buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test big roundtrip
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_value_high_roundtrip) {
|
||||
double value;
|
||||
|
||||
value = 4.32e261;
|
||||
|
||||
TRI_string_buffer_t buffer;
|
||||
TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
auto json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, value);
|
||||
TRI_StringifyJson(&buffer, json);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("4.32e+261"), std::string(buffer._buffer, buffer._current - buffer._buffer));
|
||||
|
||||
auto json2 = TRI_Json2String(TRI_UNKNOWN_MEM_ZONE, buffer._buffer, nullptr);
|
||||
BOOST_CHECK_EQUAL(TRI_JSON_NUMBER, json2->_type);
|
||||
BOOST_CHECK_EQUAL(value, json2->_value._number);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json2);
|
||||
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
TRI_DestroyStringBuffer(&buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test small roundtrip
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (tst_value_low_roundtrip) {
|
||||
double value;
|
||||
|
||||
value = -4.32e261;
|
||||
|
||||
TRI_string_buffer_t buffer;
|
||||
TRI_InitStringBuffer(&buffer, TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
auto json = TRI_CreateNumberJson(TRI_UNKNOWN_MEM_ZONE, value);
|
||||
TRI_StringifyJson(&buffer, json);
|
||||
|
||||
BOOST_CHECK_EQUAL(std::string("-4.32e+261"), std::string(buffer._buffer, buffer._current - buffer._buffer));
|
||||
|
||||
auto json2 = TRI_Json2String(TRI_UNKNOWN_MEM_ZONE, buffer._buffer, nullptr);
|
||||
BOOST_CHECK_EQUAL(TRI_JSON_NUMBER, json2->_type);
|
||||
BOOST_CHECK_EQUAL(value, json2->_value._number);
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json2);
|
||||
|
||||
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
|
||||
TRI_DestroyStringBuffer(&buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate tests
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END ()
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -704,12 +704,12 @@ BOOST_AUTO_TEST_CASE (tst_doubles) {
|
|||
value = n * n * n * n;
|
||||
TRI_ClearStringBuffer(&sb);
|
||||
TRI_AppendDoubleStringBuffer(&sb, value);
|
||||
BOOST_CHECK_EQUAL("3575783498001355000000", sb._buffer);
|
||||
|
||||
BOOST_CHECK_EQUAL("3575783498001355400000", sb._buffer);
|
||||
|
||||
value *= -1.0;
|
||||
TRI_ClearStringBuffer(&sb);
|
||||
TRI_AppendDoubleStringBuffer(&sb, value);
|
||||
BOOST_CHECK_EQUAL("-3575783498001355000000", sb._buffer);
|
||||
BOOST_CHECK_EQUAL("-3575783498001355400000", sb._buffer);
|
||||
|
||||
TRI_DestroyStringBuffer(&sb);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ add_executable(
|
|||
Basics/conversions-test.cpp
|
||||
Basics/csv-test.cpp
|
||||
Basics/files-test.cpp
|
||||
Basics/fpconv-test.cpp
|
||||
Basics/json-test.cpp
|
||||
Basics/json-utilities-test.cpp
|
||||
Basics/hashes-test.cpp
|
||||
|
|
|
@ -456,6 +456,58 @@ describe ArangoDB do
|
|||
doc.parsed_response['code'].should eq(400)
|
||||
doc.parsed_response['errorNum'].should eq(1501)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## floating points
|
||||
################################################################################
|
||||
|
||||
context "fetching floating-point values:" do
|
||||
before do
|
||||
@cn = "users"
|
||||
ArangoDB.drop_collection(@cn)
|
||||
@cid = ArangoDB.create_collection(@cn, false)
|
||||
|
||||
ArangoDB.post("/_api/document?collection=#{@cid}", :body => "{ \"_key\" : \"big\", \"value\" : 4e+262 }")
|
||||
ArangoDB.post("/_api/document?collection=#{@cid}", :body => "{ \"_key\" : \"neg\", \"value\" : -4e262 }")
|
||||
ArangoDB.post("/_api/document?collection=#{@cid}", :body => "{ \"_key\" : \"pos\", \"value\" : 4e262 }")
|
||||
ArangoDB.post("/_api/document?collection=#{@cid}", :body => "{ \"_key\" : \"small\", \"value\" : 4e-262 }")
|
||||
end
|
||||
|
||||
after do
|
||||
ArangoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "fetching via cursor" do
|
||||
cmd = api
|
||||
body = "{ \"query\" : \"FOR u IN #{@cn} SORT u._key RETURN u.value\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-float", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
doc.parsed_response['code'].should eq(201)
|
||||
doc.parsed_response['id'].should be_nil
|
||||
result = doc.parsed_response['result']
|
||||
result.length.should eq(4)
|
||||
result[0].should eq(4e262);
|
||||
result[1].should eq(-4e262);
|
||||
result[2].should eq(4e262);
|
||||
result[3].should eq(4e-262);
|
||||
|
||||
doc = ArangoDB.get("/_api/document/#{@cid}/big")
|
||||
doc.parsed_response['value'].should eq(4e262)
|
||||
|
||||
doc = ArangoDB.get("/_api/document/#{@cid}/neg")
|
||||
doc.parsed_response['value'].should eq(-4e262)
|
||||
|
||||
doc = ArangoDB.get("/_api/document/#{@cid}/pos")
|
||||
doc.parsed_response['value'].should eq(4e262)
|
||||
|
||||
doc = ArangoDB.get("/_api/document/#{@cid}/small")
|
||||
doc.parsed_response['value'].should eq(4e-262)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -338,6 +338,7 @@ UnitTests_basics_suite_SOURCES = \
|
|||
UnitTests/Basics/conversions-test.cpp \
|
||||
UnitTests/Basics/csv-test.cpp \
|
||||
UnitTests/Basics/files-test.cpp \
|
||||
UnitTests/Basics/fpconv-test.cpp \
|
||||
UnitTests/Basics/json-test.cpp \
|
||||
UnitTests/Basics/json-utilities-test.cpp \
|
||||
UnitTests/Basics/hashes-test.cpp \
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Aql/Functions.h"
|
||||
#include "Basics/fpconv.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
#include "Utils/Exception.h"
|
||||
|
||||
|
@ -115,38 +116,48 @@ AqlValue Functions::Length (triagens::arango::AqlTransaction* trx,
|
|||
if (json != nullptr) {
|
||||
switch (json->_type) {
|
||||
case TRI_JSON_UNUSED:
|
||||
case TRI_JSON_NULL:
|
||||
case TRI_JSON_NULL: {
|
||||
length = strlen("null");
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_JSON_BOOLEAN:
|
||||
case TRI_JSON_BOOLEAN: {
|
||||
length = (json->_value._boolean ? strlen("true") : strlen("false"));
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_JSON_NUMBER:
|
||||
try {
|
||||
std::string toString = std::to_string(json->_value._number);
|
||||
length = toString.size();
|
||||
case TRI_JSON_NUMBER: {
|
||||
if (std::isnan(json->_value._number) ||
|
||||
! std::isfinite(json->_value._number)) {
|
||||
// invalid value
|
||||
length = strlen("null");
|
||||
}
|
||||
catch (...) {
|
||||
else {
|
||||
// convert to a string representation of the number
|
||||
char buffer[24];
|
||||
length = static_cast<size_t>(fpconv_dtoa(json->_value._number, buffer));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_JSON_STRING:
|
||||
case TRI_JSON_STRING_REFERENCE:
|
||||
case TRI_JSON_STRING_REFERENCE: {
|
||||
// return number of characters (not bytes) in string
|
||||
length = TRI_CharLengthUtf8String(json->_value._string.data);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_JSON_OBJECT:
|
||||
case TRI_JSON_OBJECT: {
|
||||
// return number of attributes
|
||||
length = json->_value._objects._length / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
case TRI_JSON_ARRAY:
|
||||
case TRI_JSON_ARRAY: {
|
||||
// return list length
|
||||
length = TRI_LengthArrayJson(json);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -302,6 +302,8 @@
|
|||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks("grunt-sass");
|
||||
|
||||
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
|
||||
grunt.loadNpmTasks('grunt-text-replace');
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"grunt-contrib-uglify": "^0.7.0",
|
||||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-karma": "^0.10.1",
|
||||
"grunt-sass": "^0.18.0",
|
||||
"grunt-text-replace": "^0.4.0",
|
||||
"jasmine-core": "^2.2.0",
|
||||
"karma": "^0.12.31",
|
||||
|
|
|
@ -29,8 +29,9 @@
|
|||
|
||||
#include "conversions.h"
|
||||
|
||||
#include "Basics/tri-strings.h"
|
||||
#include "Basics/fpconv.h"
|
||||
#include "Basics/string-buffer.h"
|
||||
#include "Basics/tri-strings.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions for string to something
|
||||
|
@ -715,9 +716,10 @@ char* TRI_StringUInt64 (uint64_t attr) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief convert to string from double
|
||||
/// @brief convert to string from double (currently not used)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if 0
|
||||
char* TRI_StringDouble (double value) {
|
||||
TRI_string_buffer_t buffer;
|
||||
|
||||
|
@ -726,6 +728,7 @@ char* TRI_StringDouble (double value) {
|
|||
|
||||
return buffer._buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief convert to hex string from uint32, using the specified buffer.
|
||||
|
|
|
@ -243,10 +243,12 @@ char* TRI_StringInt64 (int64_t);
|
|||
char* TRI_StringUInt64 (uint64_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief convert to string from double
|
||||
/// @brief convert to string from double (currently not used)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if 0
|
||||
char* TRI_StringDouble (double);
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief convert to a hex string from uint32, using the specified buffer.
|
||||
|
|
|
@ -0,0 +1,332 @@
|
|||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fpconv.h"
|
||||
#include "powers.h"
|
||||
|
||||
#define fracmask 0x000FFFFFFFFFFFFFU
|
||||
#define expmask 0x7FF0000000000000U
|
||||
#define hiddenbit 0x0010000000000000U
|
||||
#define signmask 0x8000000000000000U
|
||||
#define expbias (1023 + 52)
|
||||
|
||||
#define absv(n) ((n) < 0 ? -(n) : (n))
|
||||
#define minv(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
static uint64_t tens[] = {
|
||||
10000000000000000000U, 1000000000000000000U, 100000000000000000U,
|
||||
10000000000000000U, 1000000000000000U, 100000000000000U,
|
||||
10000000000000U, 1000000000000U, 100000000000U,
|
||||
10000000000U, 1000000000U, 100000000U,
|
||||
10000000U, 1000000U, 100000U,
|
||||
10000U, 1000U, 100U,
|
||||
10U, 1U
|
||||
};
|
||||
|
||||
static inline uint64_t get_dbits(double d)
|
||||
{
|
||||
union {
|
||||
double dbl;
|
||||
uint64_t i;
|
||||
} dbl_bits = { d };
|
||||
|
||||
return dbl_bits.i;
|
||||
}
|
||||
|
||||
static Fp build_fp(double d)
|
||||
{
|
||||
uint64_t bits = get_dbits(d);
|
||||
|
||||
Fp fp;
|
||||
fp.frac = bits & fracmask;
|
||||
fp.exp = (bits & expmask) >> 52;
|
||||
|
||||
if(fp.exp) {
|
||||
fp.frac += hiddenbit;
|
||||
fp.exp -= expbias;
|
||||
|
||||
} else {
|
||||
fp.exp = -expbias + 1;
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
static void normalize(Fp* fp)
|
||||
{
|
||||
while ((fp->frac & hiddenbit) == 0) {
|
||||
fp->frac <<= 1;
|
||||
fp->exp--;
|
||||
}
|
||||
|
||||
int shift = 64 - 52 - 1;
|
||||
fp->frac <<= shift;
|
||||
fp->exp -= shift;
|
||||
}
|
||||
|
||||
static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
|
||||
{
|
||||
upper->frac = (fp->frac << 1) + 1;
|
||||
upper->exp = fp->exp - 1;
|
||||
|
||||
while ((upper->frac & (hiddenbit << 1)) == 0) {
|
||||
upper->frac <<= 1;
|
||||
upper->exp--;
|
||||
}
|
||||
|
||||
int u_shift = 64 - 52 - 2;
|
||||
|
||||
upper->frac <<= u_shift;
|
||||
upper->exp = upper->exp - u_shift;
|
||||
|
||||
|
||||
int l_shift = fp->frac == hiddenbit ? 2 : 1;
|
||||
|
||||
lower->frac = (fp->frac << l_shift) - 1;
|
||||
lower->exp = fp->exp - l_shift;
|
||||
|
||||
|
||||
lower->frac <<= lower->exp - upper->exp;
|
||||
lower->exp = upper->exp;
|
||||
}
|
||||
|
||||
static Fp multiply(Fp* a, Fp* b)
|
||||
{
|
||||
const uint64_t lomask = 0x00000000FFFFFFFF;
|
||||
|
||||
uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask);
|
||||
uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32);
|
||||
uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask);
|
||||
uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32);
|
||||
|
||||
uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32);
|
||||
/* round up */
|
||||
tmp += 1U << 31;
|
||||
|
||||
Fp fp = {
|
||||
ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
|
||||
a->exp + b->exp + 64
|
||||
};
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac)
|
||||
{
|
||||
while (rem < frac && delta - rem >= kappa &&
|
||||
(rem + kappa < frac || frac - rem > rem + kappa - frac)) {
|
||||
|
||||
digits[ndigits - 1]--;
|
||||
rem += kappa;
|
||||
}
|
||||
}
|
||||
|
||||
static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
|
||||
{
|
||||
uint64_t wfrac = upper->frac - fp->frac;
|
||||
uint64_t delta = upper->frac - lower->frac;
|
||||
|
||||
Fp one;
|
||||
one.frac = 1ULL << -upper->exp;
|
||||
one.exp = upper->exp;
|
||||
|
||||
uint64_t part1 = upper->frac >> -one.exp;
|
||||
uint64_t part2 = upper->frac & (one.frac - 1);
|
||||
|
||||
int idx = 0, kappa = 10;
|
||||
uint64_t* divp;
|
||||
/* 1000000000 */
|
||||
for(divp = tens + 10; kappa > 0; divp++) {
|
||||
|
||||
uint64_t div = *divp;
|
||||
unsigned digit = part1 / div;
|
||||
|
||||
if (digit || idx) {
|
||||
digits[idx++] = digit + '0';
|
||||
}
|
||||
|
||||
part1 -= digit * div;
|
||||
kappa--;
|
||||
|
||||
uint64_t tmp = (part1 <<-one.exp) + part2;
|
||||
if (tmp <= delta) {
|
||||
*K += kappa;
|
||||
round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac);
|
||||
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 10 */
|
||||
uint64_t* unit = tens + 18;
|
||||
|
||||
while(true) {
|
||||
part2 *= 10;
|
||||
delta *= 10;
|
||||
kappa--;
|
||||
|
||||
unsigned digit = part2 >> -one.exp;
|
||||
if (digit || idx) {
|
||||
digits[idx++] = digit + '0';
|
||||
}
|
||||
|
||||
part2 &= one.frac - 1;
|
||||
if (part2 < delta) {
|
||||
*K += kappa;
|
||||
round_digit(digits, idx, delta, part2, one.frac, wfrac * *unit);
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
unit--;
|
||||
}
|
||||
}
|
||||
|
||||
static int grisu2(double d, char* digits, int* K)
|
||||
{
|
||||
Fp w = build_fp(d);
|
||||
|
||||
Fp lower, upper;
|
||||
get_normalized_boundaries(&w, &lower, &upper);
|
||||
|
||||
normalize(&w);
|
||||
|
||||
int k;
|
||||
Fp cp = find_cachedpow10(upper.exp, &k);
|
||||
|
||||
w = multiply(&w, &cp);
|
||||
upper = multiply(&upper, &cp);
|
||||
lower = multiply(&lower, &cp);
|
||||
|
||||
lower.frac++;
|
||||
upper.frac--;
|
||||
|
||||
*K = -k;
|
||||
|
||||
return generate_digits(&w, &upper, &lower, digits, K);
|
||||
}
|
||||
|
||||
static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
|
||||
{
|
||||
int exp = absv(K + ndigits - 1);
|
||||
|
||||
/* write plain integer */
|
||||
if(K >= 0 && (exp < (ndigits + 7))) {
|
||||
memcpy(dest, digits, ndigits);
|
||||
memset(dest + ndigits, '0', K);
|
||||
|
||||
return ndigits + K;
|
||||
}
|
||||
|
||||
/* write decimal w/o scientific notation */
|
||||
if(K < 0 && (K > -7 || exp < 4)) {
|
||||
int offset = ndigits - absv(K);
|
||||
/* fp < 1.0 -> write leading zero */
|
||||
if(offset <= 0) {
|
||||
offset = -offset;
|
||||
dest[0] = '0';
|
||||
dest[1] = '.';
|
||||
memset(dest + 2, '0', offset);
|
||||
memcpy(dest + offset + 2, digits, ndigits);
|
||||
|
||||
return ndigits + 2 + offset;
|
||||
|
||||
/* fp > 1.0 */
|
||||
} else {
|
||||
memcpy(dest, digits, offset);
|
||||
dest[offset] = '.';
|
||||
memcpy(dest + offset + 1, digits + offset, ndigits - offset);
|
||||
|
||||
return ndigits + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* write decimal w/ scientific notation */
|
||||
ndigits = minv(ndigits, 18 - neg);
|
||||
|
||||
int idx = 0;
|
||||
dest[idx++] = digits[0];
|
||||
|
||||
if(ndigits > 1) {
|
||||
dest[idx++] = '.';
|
||||
memcpy(dest + idx, digits + 1, ndigits - 1);
|
||||
idx += ndigits - 1;
|
||||
}
|
||||
|
||||
dest[idx++] = 'e';
|
||||
|
||||
char sign = K + ndigits - 1 < 0 ? '-' : '+';
|
||||
dest[idx++] = sign;
|
||||
|
||||
int cent = 0;
|
||||
|
||||
if(exp > 99) {
|
||||
cent = exp / 100;
|
||||
dest[idx++] = cent + '0';
|
||||
exp -= cent * 100;
|
||||
}
|
||||
if(exp > 9) {
|
||||
int dec = exp / 10;
|
||||
dest[idx++] = dec + '0';
|
||||
exp -= dec * 10;
|
||||
|
||||
} else if(cent) {
|
||||
dest[idx++] = '0';
|
||||
}
|
||||
|
||||
dest[idx++] = exp % 10 + '0';
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int filter_special(double fp, char* dest)
|
||||
{
|
||||
if(fp == 0.0) {
|
||||
dest[0] = '0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t bits = get_dbits(fp);
|
||||
|
||||
bool nan = (bits & expmask) == expmask;
|
||||
|
||||
if(!nan) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(bits & fracmask) {
|
||||
dest[0] = 'N'; dest[1] = 'a'; dest[2] = 'N';
|
||||
|
||||
} else {
|
||||
dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
int fpconv_dtoa(double d, char dest[24])
|
||||
{
|
||||
char digits[18];
|
||||
|
||||
int str_len = 0;
|
||||
bool neg = false;
|
||||
|
||||
if(get_dbits(d) & signmask) {
|
||||
dest[0] = '-';
|
||||
str_len++;
|
||||
neg = true;
|
||||
}
|
||||
|
||||
int spec = filter_special(d, dest + str_len);
|
||||
|
||||
if(spec) {
|
||||
return str_len + spec;
|
||||
}
|
||||
|
||||
int K = 0;
|
||||
int ndigits = grisu2(d, digits, &K);
|
||||
|
||||
str_len += emit_digits(digits, ndigits, dest + str_len, K, neg);
|
||||
|
||||
return str_len;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef FPCONV_H
|
||||
#define FPCONV_H
|
||||
|
||||
/* Fast and accurate double to string conversion based on Florian Loitsch's
|
||||
* Grisu-algorithm[1].
|
||||
*
|
||||
* Input:
|
||||
* fp -> the double to convert, dest -> destination buffer.
|
||||
* The generated string will never be longer than 24 characters.
|
||||
* Make sure to pass a pointer to at least 24 bytes of memory.
|
||||
* The emitted string will not be null terminated.
|
||||
*
|
||||
* Output:
|
||||
* The number of written characters.
|
||||
*
|
||||
* Exemplary usage:
|
||||
*
|
||||
* void print(double d)
|
||||
* {
|
||||
* char buf[24 + 1] // plus null terminator
|
||||
* int str_len = fpconv_dtoa(d, buf);
|
||||
*
|
||||
* buf[str_len] = '\0';
|
||||
* printf("%s", buf);
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
int fpconv_dtoa(double fp, char dest[24]);
|
||||
|
||||
#endif
|
||||
|
||||
/* [1] http://florian.loitsch.com/publications/dtoa-pldi2010.pdf */
|
|
@ -0,0 +1,87 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#define npowers 87
|
||||
#define steppowers 8
|
||||
#define firstpower -348 /* 10 ^ -348 */
|
||||
|
||||
#define expmax -32
|
||||
#define expmin -60
|
||||
|
||||
|
||||
typedef struct Fp {
|
||||
uint64_t frac;
|
||||
int exp;
|
||||
} Fp;
|
||||
|
||||
static Fp powers_ten[] = {
|
||||
{ 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 },
|
||||
{ 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 },
|
||||
{ 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 },
|
||||
{ 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 },
|
||||
{ 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 },
|
||||
{ 15227053142812498563U, -954 }, { 11345038669416679861U, -927 },
|
||||
{ 16905424996341287883U, -901 }, { 12595523146049147757U, -874 },
|
||||
{ 9384396036005875287U, -847 }, { 13983839803942852151U, -821 },
|
||||
{ 10418772551374772303U, -794 }, { 15525180923007089351U, -768 },
|
||||
{ 11567161174868858868U, -741 }, { 17236413322193710309U, -715 },
|
||||
{ 12842128665889583758U, -688 }, { 9568131466127621947U, -661 },
|
||||
{ 14257626930069360058U, -635 }, { 10622759856335341974U, -608 },
|
||||
{ 15829145694278690180U, -582 }, { 11793632577567316726U, -555 },
|
||||
{ 17573882009934360870U, -529 }, { 13093562431584567480U, -502 },
|
||||
{ 9755464219737475723U, -475 }, { 14536774485912137811U, -449 },
|
||||
{ 10830740992659433045U, -422 }, { 16139061738043178685U, -396 },
|
||||
{ 12024538023802026127U, -369 }, { 17917957937422433684U, -343 },
|
||||
{ 13349918974505688015U, -316 }, { 9946464728195732843U, -289 },
|
||||
{ 14821387422376473014U, -263 }, { 11042794154864902060U, -236 },
|
||||
{ 16455045573212060422U, -210 }, { 12259964326927110867U, -183 },
|
||||
{ 18268770466636286478U, -157 }, { 13611294676837538539U, -130 },
|
||||
{ 10141204801825835212U, -103 }, { 15111572745182864684U, -77 },
|
||||
{ 11258999068426240000U, -50 }, { 16777216000000000000U, -24 },
|
||||
{ 12500000000000000000U, 3 }, { 9313225746154785156U, 30 },
|
||||
{ 13877787807814456755U, 56 }, { 10339757656912845936U, 83 },
|
||||
{ 15407439555097886824U, 109 }, { 11479437019748901445U, 136 },
|
||||
{ 17105694144590052135U, 162 }, { 12744735289059618216U, 189 },
|
||||
{ 9495567745759798747U, 216 }, { 14149498560666738074U, 242 },
|
||||
{ 10542197943230523224U, 269 }, { 15709099088952724970U, 295 },
|
||||
{ 11704190886730495818U, 322 }, { 17440603504673385349U, 348 },
|
||||
{ 12994262207056124023U, 375 }, { 9681479787123295682U, 402 },
|
||||
{ 14426529090290212157U, 428 }, { 10748601772107342003U, 455 },
|
||||
{ 16016664761464807395U, 481 }, { 11933345169920330789U, 508 },
|
||||
{ 17782069995880619868U, 534 }, { 13248674568444952270U, 561 },
|
||||
{ 9871031767461413346U, 588 }, { 14708983551653345445U, 614 },
|
||||
{ 10959046745042015199U, 641 }, { 16330252207878254650U, 667 },
|
||||
{ 12166986024289022870U, 694 }, { 18130221999122236476U, 720 },
|
||||
{ 13508068024458167312U, 747 }, { 10064294952495520794U, 774 },
|
||||
{ 14996968138956309548U, 800 }, { 11173611982879273257U, 827 },
|
||||
{ 16649979327439178909U, 853 }, { 12405201291620119593U, 880 },
|
||||
{ 9242595204427927429U, 907 }, { 13772540099066387757U, 933 },
|
||||
{ 10261342003245940623U, 960 }, { 15290591125556738113U, 986 },
|
||||
{ 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 },
|
||||
{ 12648080533535911531U, 1066 }
|
||||
};
|
||||
|
||||
static Fp find_cachedpow10(int exp, int* k)
|
||||
{
|
||||
const double one_log_ten = 0.30102999566398114;
|
||||
|
||||
int approx = -(exp + npowers) * one_log_ten;
|
||||
int idx = (approx - firstpower) / steppowers;
|
||||
|
||||
while(1) {
|
||||
int current = exp + powers_ten[idx].exp + 64;
|
||||
|
||||
if(current < expmin) {
|
||||
idx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(current > expmax) {
|
||||
idx--;
|
||||
continue;
|
||||
}
|
||||
|
||||
*k = (firstpower + idx * steppowers);
|
||||
|
||||
return powers_ten[idx];
|
||||
}
|
||||
}
|
|
@ -28,8 +28,8 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "string-buffer.h"
|
||||
#include <stdlib.h>
|
||||
#include "Basics/conversions.h"
|
||||
#include "Basics/fpconv.h"
|
||||
#include "Zip/zip.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -1282,10 +1282,7 @@ int TRI_AppendSizeHexStringBuffer (TRI_string_buffer_t * self, size_t attr) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_AppendDoubleStringBuffer (TRI_string_buffer_t * self, double attr) {
|
||||
// IEEE754 NaN values have an interesting property that we can exploit...
|
||||
// if the architecture does not use IEEE754 values then this shouldn't do
|
||||
// any harm either
|
||||
if (attr != attr) {
|
||||
if (std::isnan(attr)) {
|
||||
return TRI_AppendStringStringBuffer(self, "NaN");
|
||||
}
|
||||
|
||||
|
@ -1296,182 +1293,16 @@ int TRI_AppendDoubleStringBuffer (TRI_string_buffer_t * self, double attr) {
|
|||
return TRI_AppendStringStringBuffer(self, "-inf");
|
||||
}
|
||||
|
||||
int res = Reserve(self, 1);
|
||||
int res = Reserve(self, 24);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (attr < 0.0) {
|
||||
AppendChar(self, '-');
|
||||
attr = -attr;
|
||||
}
|
||||
else if (attr == 0.0) {
|
||||
AppendChar(self, '0');
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
int length = fpconv_dtoa(attr, self->_current);
|
||||
self->_current += static_cast<size_t>(length);
|
||||
|
||||
if (((double)((uint32_t) attr)) == attr) {
|
||||
return TRI_AppendUInt32StringBuffer(self, (uint32_t) attr);
|
||||
}
|
||||
else if (attr < (double) 429496U) {
|
||||
uint32_t smll;
|
||||
|
||||
smll = (uint32_t)(attr * 10000.0);
|
||||
|
||||
if (((double) smll) == attr * 10000.0) {
|
||||
uint32_t ep;
|
||||
|
||||
TRI_AppendUInt32StringBuffer(self, smll / 10000);
|
||||
|
||||
ep = smll % 10000;
|
||||
|
||||
if (ep != 0) {
|
||||
size_t pos;
|
||||
char a1;
|
||||
char a2;
|
||||
char a3;
|
||||
char a4;
|
||||
|
||||
pos = 0;
|
||||
|
||||
res = Reserve(self, 6);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
AppendChar(self, '.');
|
||||
|
||||
if ((ep / 1000L) % 10 != 0) pos = 1;
|
||||
a1 = (char) ((ep / 1000L) % 10 + '0');
|
||||
|
||||
if ((ep / 100L) % 10 != 0) pos = 2;
|
||||
a2 = (char) ((ep / 100L) % 10 + '0');
|
||||
|
||||
if ((ep / 10L) % 10 != 0) pos = 3;
|
||||
a3 = (char) ((ep / 10L) % 10 + '0');
|
||||
|
||||
if (ep % 10 != 0) pos = 4;
|
||||
a4 = (char) (ep % 10 + '0');
|
||||
|
||||
AppendChar(self, a1);
|
||||
if (pos > 1) { AppendChar(self, a2); }
|
||||
if (pos > 2) { AppendChar(self, a3); }
|
||||
if (pos > 3) { AppendChar(self, a4); }
|
||||
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// we do not habe a small integral number nor small decimal number with only a few decimal digits
|
||||
|
||||
// there at most 16 significant digits, first find out if we have an integer value
|
||||
if (10000000000000000.0 < attr) {
|
||||
size_t n;
|
||||
|
||||
n = 0;
|
||||
|
||||
while (10000000000000000.0 < attr) {
|
||||
attr /= 10.0;
|
||||
++n;
|
||||
}
|
||||
|
||||
res = TRI_AppendUInt64StringBuffer(self, (uint64_t) attr);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = Reserve(self, n);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
for (; 0 < n; --n) {
|
||||
AppendChar(self, '0');
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// very small, i. e. less than 1
|
||||
else if (attr < 1.0) {
|
||||
size_t n;
|
||||
|
||||
n = 0;
|
||||
|
||||
while (attr < 1.0) {
|
||||
attr *= 10.0;
|
||||
++n;
|
||||
|
||||
// should not happen, so it must be almost 0
|
||||
if (n > 400) {
|
||||
return TRI_AppendUInt32StringBuffer(self, 0);
|
||||
}
|
||||
}
|
||||
|
||||
res = Reserve(self, n + 2);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
AppendChar(self, '0');
|
||||
AppendChar(self, '.');
|
||||
|
||||
for (--n; 0 < n; --n) {
|
||||
AppendChar(self, '0');
|
||||
}
|
||||
|
||||
attr = 10000000000000000.0 * attr;
|
||||
|
||||
return TRI_AppendUInt64StringBuffer(self, (uint64_t) attr);
|
||||
}
|
||||
|
||||
|
||||
// somewhere in between
|
||||
else {
|
||||
uint64_t m;
|
||||
double d;
|
||||
size_t n;
|
||||
|
||||
m = (uint64_t) attr;
|
||||
d = attr - m;
|
||||
n = 0;
|
||||
|
||||
TRI_AppendUInt64StringBuffer(self, m);
|
||||
|
||||
while (d < 1.0) {
|
||||
d *= 10.0;
|
||||
++n;
|
||||
|
||||
// should not happen, so it must be almost 0
|
||||
if (n > 400) {
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
res = Reserve(self, n + 1);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
AppendChar(self, '.');
|
||||
|
||||
for (--n; 0 < n; --n) {
|
||||
AppendChar(self, '0');
|
||||
}
|
||||
|
||||
d = 10000000000000000.0 * d;
|
||||
|
||||
return TRI_AppendUInt64StringBuffer(self, (uint64_t) d);
|
||||
}
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -58,6 +58,7 @@ add_library(
|
|||
Basics/fasthash.cpp
|
||||
Basics/files.cpp
|
||||
Basics/FileUtils.cpp
|
||||
Basics/fpconv.cpp
|
||||
Basics/hashes.cpp
|
||||
Basics/init.cpp
|
||||
Basics/InitialiseBasics.cpp
|
||||
|
|
|
@ -25,6 +25,7 @@ lib_libarango_a_SOURCES = \
|
|||
lib/Basics/fasthash.cpp \
|
||||
lib/Basics/files.cpp \
|
||||
lib/Basics/FileUtils.cpp \
|
||||
lib/Basics/fpconv.cpp \
|
||||
lib/Basics/hashes.cpp \
|
||||
lib/Basics/init.cpp \
|
||||
lib/Basics/InitialiseBasics.cpp \
|
||||
|
|
Loading…
Reference in New Issue