yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie HermaszewskaCorrect include dir for libslang (#5539)7b570feed

master
7.8 KiB299 linesraw
1// unit-test-path.cpp
2
3#include "../../source/core/slang-string-util.h"
4#include "unit-test/slang-unit-test.h"
5
6// #include <math.h>
7
8#include <sstream>
9
10using namespace Slang;
11
12static bool _areEqual(
13    const List<UnownedStringSlice>& lines,
14    const UnownedStringSlice* checkLines,
15    Int checkLinesCount)
16{
17    if (checkLinesCount != lines.getCount())
18    {
19        return false;
20    }
21
22    for (Int i = 0; i < checkLinesCount; ++i)
23    {
24        if (lines[i] != checkLines[i])
25        {
26            return false;
27        }
28    }
29    return true;
30}
31
32static bool _checkLines(
33    const UnownedStringSlice& input,
34    const UnownedStringSlice* checkLines,
35    Int checkLinesCount)
36{
37    List<UnownedStringSlice> lines;
38    StringUtil::calcLines(input, lines);
39    return _areEqual(lines, checkLines, checkLinesCount);
40}
41
42static bool _checkLineParser(const UnownedStringSlice& input)
43{
44    UnownedStringSlice remaining(input), line;
45    for (const auto parserLine : LineParser(input))
46    {
47        if (!StringUtil::extractLine(remaining, line) || line != parserLine)
48        {
49            return false;
50        }
51    }
52    return StringUtil::extractLine(remaining, line) == false;
53}
54
55static void _append(double v, StringBuilder& buf)
56{
57    std::ostringstream stream;
58    stream.imbue(std::locale::classic());
59    stream.setf(std::ios::fixed, std::ios::floatfield);
60    stream.precision(20);
61
62    stream << std::scientific << v;
63
64    buf << stream.str().c_str();
65}
66
67// Unit of least precision
68static int64_t _calcULPDistance(double a, double b)
69{
70    // Save work if the floats are equal.
71    // Also handles +0 == -0
72    if (a == b)
73    {
74        return 0;
75    }
76
77    const int64_t max = int64_t((~uint64_t(0)) >> 1);
78
79#if 0
80    // Max distance for NaN
81    if (isnan(a) || isnan(b))
82    {
83        return max;
84    }
85
86    // If one's infinite and they're not equal, max distance.
87    if (isinf(a) || isinf(b))
88    {
89        return max;
90    }
91#endif
92
93    int64_t ia, ib;
94    memcpy(&ia, &a, sizeof(a));
95    memcpy(&ib, &b, sizeof(b));
96
97    // Don't compare differently-signed floats.
98    if ((ia < 0) != (ib < 0))
99    {
100        return max;
101    }
102
103    // Return the absolute value of the distance in ULPs.
104    int64_t distance = ia - ib;
105    return distance < 0 ? -distance : distance;
106}
107
108static bool _areApproximatelyEqual(
109    double a,
110    double b,
111    double fixedEpsilon = 1e-10,
112    int ulpsEpsilon = 100)
113{
114    // Handle the near-zero case.
115    const double difference = abs(a - b);
116    if (difference <= fixedEpsilon)
117    {
118        return true;
119    }
120
121    return _calcULPDistance(a, b) <= ulpsEpsilon;
122}
123
124SLANG_UNIT_TEST(string)
125{
126    {
127        UnownedStringSlice checkLines[] = {UnownedStringSlice::fromLiteral("")};
128        SLANG_CHECK(_checkLines(
129            UnownedStringSlice::fromLiteral(""),
130            checkLines,
131            SLANG_COUNT_OF(checkLines)));
132    }
133    {
134        // Will emit no lines
135        SLANG_CHECK(_checkLines(UnownedStringSlice(nullptr, nullptr), nullptr, 0));
136    }
137    {
138        // Two lines - both empty
139        UnownedStringSlice checkLines[] = {UnownedStringSlice(), UnownedStringSlice()};
140        SLANG_CHECK(_checkLines(
141            UnownedStringSlice::fromLiteral("\n"),
142            checkLines,
143            SLANG_COUNT_OF(checkLines)));
144    }
145    {
146        UnownedStringSlice checkLines[] = {
147            UnownedStringSlice::fromLiteral("Hello"),
148            UnownedStringSlice::fromLiteral("World!")};
149        SLANG_CHECK(_checkLines(
150            UnownedStringSlice::fromLiteral("Hello\nWorld!"),
151            checkLines,
152            SLANG_COUNT_OF(checkLines)));
153    }
154    {
155        UnownedStringSlice checkLines[] = {
156            UnownedStringSlice::fromLiteral("Hello"),
157            UnownedStringSlice::fromLiteral("World!"),
158            UnownedStringSlice()};
159        SLANG_CHECK(_checkLines(
160            UnownedStringSlice::fromLiteral("Hello\n\rWorld!\n"),
161            checkLines,
162            SLANG_COUNT_OF(checkLines)));
163    }
164
165    {
166        SLANG_CHECK(_checkLineParser(UnownedStringSlice::fromLiteral("Hello\n\rWorld!\n")));
167        SLANG_CHECK(_checkLineParser(UnownedStringSlice::fromLiteral("\n")));
168        SLANG_CHECK(_checkLineParser(UnownedStringSlice::fromLiteral("")));
169    }
170    {
171        Int value;
172        SLANG_CHECK(
173            SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("-10"), value)) &&
174            value == -10);
175        SLANG_CHECK(
176            SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("0"), value)) && value == 0);
177        SLANG_CHECK(
178            SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("-0"), value)) && value == 0);
179
180        SLANG_CHECK(
181            SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("13824"), value)) &&
182            value == 13824);
183        SLANG_CHECK(
184            SLANG_SUCCEEDED(StringUtil::parseInt(UnownedStringSlice("-13824"), value)) &&
185            value == -13824);
186    }
187
188    {
189        UnownedStringSlice values[] = {
190            UnownedStringSlice("hello"),
191            UnownedStringSlice("world"),
192            UnownedStringSlice("!")};
193        ArrayView<UnownedStringSlice> valuesView(values, SLANG_COUNT_OF(values));
194
195        List<UnownedStringSlice> checkValues;
196        StringBuilder builder;
197
198        {
199            builder.clear();
200            StringUtil::join(values, 0, ',', builder);
201            SLANG_CHECK(builder == "");
202        }
203
204        {
205            builder.clear();
206            StringUtil::join(values, 1, ',', builder);
207            SLANG_CHECK(builder == "hello");
208
209            StringUtil::split(builder.getUnownedSlice(), ',', checkValues);
210            SLANG_CHECK(checkValues.getArrayView() == ArrayView<UnownedStringSlice>(values, 1));
211        }
212
213        {
214            builder.clear();
215            StringUtil::join(values, 2, ',', builder);
216            SLANG_CHECK(builder == "hello,world");
217
218            StringUtil::split(builder.getUnownedSlice(), ',', checkValues);
219            SLANG_CHECK(checkValues.getArrayView() == ArrayView<UnownedStringSlice>(values, 2));
220        }
221
222        {
223            builder.clear();
224            StringUtil::join(values, 3, UnownedStringSlice("ab"), builder);
225            SLANG_CHECK(builder == "helloabworldab!");
226
227            StringUtil::split(builder.getUnownedSlice(), UnownedStringSlice("ab"), checkValues);
228            SLANG_CHECK(checkValues.getArrayView() == ArrayView<UnownedStringSlice>(values, 3));
229        }
230    }
231    {
232
233        List<double> values;
234        values.add(0.0);
235        values.add(-0.0);
236
237        for (Index i = -300; i < 300; ++i)
238        {
239            double value = pow(10, i);
240
241            values.add(value);
242            values.add(-value);
243
244            values.addRange(value / 3);
245            values.addRange(-value / 3);
246        }
247
248        StringBuilder buf;
249
250        for (auto value : values)
251        {
252            buf.clear();
253            _append(value, buf);
254
255            UnownedStringSlice slice = buf.getUnownedSlice();
256
257            double parsedValue;
258            SlangResult res = StringUtil::parseDouble(slice, parsedValue);
259
260            auto ulpsParsed = _calcULPDistance(value, parsedValue);
261
262            SLANG_CHECK(SLANG_SUCCEEDED(res));
263
264            // Check that they are equal
265            SLANG_CHECK(_areApproximatelyEqual(value, parsedValue));
266        }
267    }
268    {
269        List<int64_t> values;
270        values.add(0);
271
272        for (Index i = 0; i < 63; ++i)
273        {
274            auto value = int64_t(1) << i;
275
276            values.add(value);
277            values.add(-value);
278        }
279
280        StringBuilder buf;
281
282        for (auto value : values)
283        {
284            buf.clear();
285            buf << value;
286
287
288            int64_t parsedValue;
289
290            UnownedStringSlice slice = buf.getUnownedSlice();
291            SlangResult res = StringUtil::parseInt64(slice, parsedValue);
292
293            SLANG_CHECK(SLANG_SUCCEEDED(res));
294
295            // Check that they are equal
296            SLANG_CHECK(value == parsedValue);
297        }
298    }
299}