mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Use dtoa_milo from str-util for double/float precision printing
Replace std::setprecision approach with dtoa_milo for proper double/float
precision in timeSamples printing.
Changes:
1. src/str-util.cc:
- Implement dtoa(double) wrapper using dtoa_milo for full precision
- Implement dtoa(float) using snprintf with %.9g format
- Include external/dtoa_milo.h at top of file
2. src/timesamples-pprint.cc:
- Replace std::setprecision with dtoa() calls from str-util.hh
- Remove <iomanip> and <limits> includes
- Add str-util.hh include
3. tests/unit/unit-strutil.cc:
- Add comprehensive dtoa_test() with 10 test cases:
* Full precision for pi (3.141592653589793)
* Full precision for e (2.718281828459045)
* Negative values
* Zero and negative zero
* Small and large numbers
* Float conversion
* Integer-like doubles (42.0, 1.0)
4. tests/unit/unit-strutil.h:
- Add dtoa_test() declaration
5. tests/unit/unit-main.cc:
- Register dtoa_test in test suite
Results:
- Double: 3.141592653589793 → 3.141592653589793 (exact match)
- Float: 3.14159f → 3.14159012 (full float precision)
- All dtoa unit tests pass
- timesamples-scalar-double-001.usda comparison test passes
Test command:
./build_asan/unit-test-tinyusdz dtoa_test
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "unicode-xid.hh"
|
||||
#include "common-macros.inc"
|
||||
#include "external/dtoa_milo.h"
|
||||
|
||||
#ifdef __SSE2__
|
||||
#include <emmintrin.h>
|
||||
@@ -1212,4 +1213,20 @@ bool GlobMatchPath(const std::string &pattern, const std::string &path) {
|
||||
return p == pattern.size();
|
||||
}
|
||||
|
||||
char *dtoa(float f, char *buf) {
|
||||
// For float, use simple sprintf for now
|
||||
// dtoa_milo is optimized for double and doesn't work well with float
|
||||
int n = snprintf(buf, 384, "%.9g", static_cast<double>(f));
|
||||
if (n < 0 || n >= 384) {
|
||||
buf[0] = '0';
|
||||
return &buf[1];
|
||||
}
|
||||
return &buf[n];
|
||||
}
|
||||
|
||||
char *dtoa(double d, char *buf) {
|
||||
// Use dtoa_milo for double precision
|
||||
return dtoa_milo(d, buf);
|
||||
}
|
||||
|
||||
} // namespace tinyusdz
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include "str-util.hh"
|
||||
|
||||
#ifdef TINYUSDZ_ENABLE_THREAD
|
||||
#include <thread>
|
||||
@@ -196,26 +195,26 @@ void print_type<char>(OutputAdapter& out, const uint8_t* data) {
|
||||
out.write(static_cast<int>(value));
|
||||
}
|
||||
|
||||
// Specialization for double - print with full precision
|
||||
// Specialization for double - print with full precision using dtoa
|
||||
template<>
|
||||
void print_type<double>(OutputAdapter& out, const uint8_t* data) {
|
||||
double value;
|
||||
std::memcpy(&value, data, sizeof(double));
|
||||
std::stringstream ss;
|
||||
ss << std::setprecision(std::numeric_limits<double>::max_digits10);
|
||||
ss << value;
|
||||
out.write(ss.str());
|
||||
char buf[384];
|
||||
char *end = dtoa(value, buf);
|
||||
*end = '\0';
|
||||
out.write(std::string(buf));
|
||||
}
|
||||
|
||||
// Specialization for float - print with full precision
|
||||
// Specialization for float - print with full precision using dtoa
|
||||
template<>
|
||||
void print_type<float>(OutputAdapter& out, const uint8_t* data) {
|
||||
float value;
|
||||
std::memcpy(&value, data, sizeof(float));
|
||||
std::stringstream ss;
|
||||
ss << std::setprecision(std::numeric_limits<float>::max_digits10);
|
||||
ss << value;
|
||||
out.write(ss.str());
|
||||
char buf[384];
|
||||
char *end = dtoa(value, buf);
|
||||
*end = '\0';
|
||||
out.write(std::string(buf));
|
||||
}
|
||||
|
||||
// Unified print function for vector types
|
||||
|
||||
@@ -49,6 +49,7 @@ TEST_LIST = {
|
||||
{ "strutil_test", strutil_test },
|
||||
{ "tinystring_test", tinystring_test },
|
||||
{ "parse_int_test", parse_int_test },
|
||||
{ "dtoa_test", dtoa_test },
|
||||
{ "timesamples_test", timesamples_test },
|
||||
{ "materialx_config_api_struct_test", materialx_config_api_struct_test },
|
||||
{ "materialx_config_api_parsing_test", materialx_config_api_parsing_test },
|
||||
|
||||
@@ -195,5 +195,135 @@ void parse_int_test(void) {
|
||||
tstring_view sv("+-123");
|
||||
TEST_CHECK(!parse_int(sv, &result));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void dtoa_test(void) {
|
||||
// Test double to ASCII conversion with full precision
|
||||
|
||||
{
|
||||
// Test pi with full double precision
|
||||
double pi = 3.141592653589793;
|
||||
char buf[384];
|
||||
char *end = dtoa(pi, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
// Should preserve full precision (at least 15 significant digits)
|
||||
TEST_CHECK(result.find("3.14159265358979") != std::string::npos);
|
||||
TEST_MSG("pi result: %s", result.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
// Test e with full double precision
|
||||
double e = 2.718281828459045;
|
||||
char buf[384];
|
||||
char *end = dtoa(e, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
// Should preserve full precision
|
||||
TEST_CHECK(result.find("2.71828182845904") != std::string::npos);
|
||||
TEST_MSG("e result: %s", result.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
// Test negative value
|
||||
double neg = -2.718281828459045;
|
||||
char buf[384];
|
||||
char *end = dtoa(neg, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
TEST_CHECK(result[0] == '-');
|
||||
TEST_CHECK(result.find("2.71828182845904") != std::string::npos);
|
||||
TEST_MSG("negative e result: %s", result.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
// Test zero
|
||||
double zero = 0.0;
|
||||
char buf[384];
|
||||
char *end = dtoa(zero, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
TEST_CHECK(result == "0.0");
|
||||
TEST_MSG("zero result: %s", result.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
// Test negative zero
|
||||
double neg_zero = -0.0;
|
||||
char buf[384];
|
||||
char *end = dtoa(neg_zero, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
// dtoa_milo should output "-0.0" for negative zero
|
||||
TEST_CHECK(result == "-0.0");
|
||||
TEST_MSG("negative zero result: %s", result.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
// Test small number
|
||||
double small = 0.000001234567890123456;
|
||||
char buf[384];
|
||||
char *end = dtoa(small, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
// Should use scientific notation for very small numbers
|
||||
TEST_MSG("small number result: %s", result.c_str());
|
||||
TEST_CHECK(result.length() > 0);
|
||||
}
|
||||
|
||||
{
|
||||
// Test large number
|
||||
double large = 1234567890123456.0;
|
||||
char buf[384];
|
||||
char *end = dtoa(large, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
TEST_MSG("large number result: %s", result.c_str());
|
||||
TEST_CHECK(result.length() > 0);
|
||||
}
|
||||
|
||||
{
|
||||
// Test float conversion
|
||||
float f = 3.14159f;
|
||||
char buf[384];
|
||||
char *end = dtoa(f, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
// Should output float with appropriate precision
|
||||
TEST_CHECK(result.find("3.14159") != std::string::npos);
|
||||
TEST_MSG("float result: %s", result.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
// Test one
|
||||
double one = 1.0;
|
||||
char buf[384];
|
||||
char *end = dtoa(one, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
TEST_CHECK(result == "1.0");
|
||||
TEST_MSG("one result: %s", result.c_str());
|
||||
}
|
||||
|
||||
{
|
||||
// Test integer-like double
|
||||
double int_like = 42.0;
|
||||
char buf[384];
|
||||
char *end = dtoa(int_like, buf);
|
||||
*end = '\0';
|
||||
std::string result(buf);
|
||||
|
||||
TEST_CHECK(result == "42.0");
|
||||
TEST_MSG("integer-like result: %s", result.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
void strutil_test(void);
|
||||
void tinystring_test(void);
|
||||
void parse_int_test(void);
|
||||
void dtoa_test(void);
|
||||
|
||||
Reference in New Issue
Block a user