summaryrefslogtreecommitdiffstats
path: root/tools/slang-test/unit-test-string.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/slang-test/unit-test-string.cpp')
-rw-r--r--tools/slang-test/unit-test-string.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/tools/slang-test/unit-test-string.cpp b/tools/slang-test/unit-test-string.cpp
index e27411b3e..e8a33fbbe 100644
--- a/tools/slang-test/unit-test-string.cpp
+++ b/tools/slang-test/unit-test-string.cpp
@@ -4,6 +4,10 @@
#include "test-context.h"
+//#include <math.h>
+
+#include <sstream>
+
using namespace Slang;
static bool _areEqual(const List<UnownedStringSlice>& lines, const UnownedStringSlice* checkLines, Int checkLinesCount)
@@ -43,6 +47,71 @@ static bool _checkLineParser(const UnownedStringSlice& input)
return StringUtil::extractLine(remaining, line) == false;
}
+static void _append(double v, StringBuilder& buf)
+{
+ std::ostringstream stream;
+ stream.imbue(std::locale::classic());
+ stream.setf(std::ios::fixed, std::ios::floatfield);
+ stream.precision(20);
+
+ stream << std::scientific << v;
+
+ buf << stream.str().c_str();
+}
+
+// Unit of least precision
+static int64_t _calcULPDistance(double a, double b)
+{
+ // Save work if the floats are equal.
+ // Also handles +0 == -0
+ if (a == b)
+ {
+ return 0;
+ }
+
+ const int64_t max = int64_t((~uint64_t(0)) >> 1);
+
+#if 0
+ // Max distance for NaN
+ if (isnan(a) || isnan(b))
+ {
+ return max;
+ }
+
+ // If one's infinite and they're not equal, max distance.
+ if (isinf(a) || isinf(b))
+ {
+ return max;
+ }
+#endif
+
+ int64_t ia, ib;
+ memcpy(&ia, &a, sizeof(a));
+ memcpy(&ib, &b, sizeof(b));
+
+ // Don't compare differently-signed floats.
+ if ((ia < 0) != (ib < 0))
+ {
+ return max;
+ }
+
+ // Return the absolute value of the distance in ULPs.
+ int64_t distance = ia - ib;
+ return distance < 0 ? -distance : distance;
+}
+
+static bool _areApproximatelyEqual(double a, double b, double fixedEpsilon = 1e-10, int ulpsEpsilon = 100)
+{
+ // Handle the near-zero case.
+ const double difference = abs(a - b);
+ if (difference <= fixedEpsilon)
+ {
+ return true;
+ }
+
+ return _calcULPDistance(a, b) <= ulpsEpsilon;
+}
+
static void stringUnitTest()
{
{
@@ -122,6 +191,74 @@ static void stringUnitTest()
SLANG_CHECK(checkValues.getArrayView() == ArrayView<UnownedStringSlice>(values, 3));
}
}
+ {
+
+ List<double> values;
+ values.add(0.0);
+ values.add(-0.0);
+
+ for (Index i = -300; i < 300; ++i)
+ {
+ double value = pow(10, i);
+
+ values.add(value);
+ values.add(-value);
+
+ values.addRange(value / 3);
+ values.addRange(-value / 3);
+ }
+
+ StringBuilder buf;
+
+ for (auto value : values)
+ {
+ buf.Clear();
+ _append(value, buf);
+
+ UnownedStringSlice slice = buf.getUnownedSlice();
+
+ double parsedValue;
+ SlangResult res = StringUtil::parseDouble(slice, parsedValue);
+
+ auto ulpsParsed = _calcULPDistance(value, parsedValue);
+
+ SLANG_CHECK(SLANG_SUCCEEDED(res));
+
+ // Check that they are equal
+ SLANG_CHECK(_areApproximatelyEqual(value, parsedValue));
+ }
+ }
+ {
+ List<int64_t> values;
+ values.add(0);
+
+ for (Index i = 0; i < 63; ++i)
+ {
+ auto value = int64_t(1) << i;
+
+ values.add(value);
+ values.add(-value);
+ }
+
+ StringBuilder buf;
+
+ for (auto value : values)
+ {
+ buf.Clear();
+ buf << value;
+
+
+ int64_t parsedValue;
+
+ UnownedStringSlice slice = buf.getUnownedSlice();
+ SlangResult res = StringUtil::parseInt64(slice, parsedValue);
+
+ SLANG_CHECK(SLANG_SUCCEEDED(res));
+
+ // Check that they are equal
+ SLANG_CHECK(value == parsedValue);
+ }
+ }
}
SLANG_UNIT_TEST("String", stringUnitTest);