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