| 316 | |
| 317 | template <typename T> |
| 318 | T randDecimal( |
| 319 | const TypePtr& type, |
| 320 | FuzzerGenerator& rng, |
| 321 | bool isShortDecimal, |
| 322 | bool isLongDecimal) { |
| 323 | BOLT_CHECK( |
| 324 | isShortDecimal != isLongDecimal, |
| 325 | "Can only generate either a short decimal or a long decimal."); |
| 326 | |
| 327 | bool generateSpecialValues = rand<bool>(rng); |
| 328 | |
| 329 | if (generateSpecialValues) { |
| 330 | // Generate special values based on hardcoded rules. |
| 331 | uint8_t precision = isShortDecimal ? type->asShortDecimal().precision() |
| 332 | : type->asLongDecimal().precision(); |
| 333 | uint8_t scale = isShortDecimal ? type->asShortDecimal().scale() |
| 334 | : type->asLongDecimal().scale(); |
| 335 | |
| 336 | using DecimalValueGenerationRule = |
| 337 | std::function<std::string(int8_t, FuzzerGenerator&)>; |
| 338 | |
| 339 | std::vector<DecimalValueGenerationRule> fractionalDigitsGenerationRules = { |
| 340 | // All 9s. |
| 341 | [&](uint8_t length, FuzzerGenerator& /*rng*/) { |
| 342 | return std::string(length, '9'); |
| 343 | }, |
| 344 | // All 0s. |
| 345 | [&](uint8_t length, FuzzerGenerator& /*rng*/) { |
| 346 | return std::string(length, '0'); |
| 347 | }, |
| 348 | // The last digit is 5 to test rounding. |
| 349 | [&](uint8_t length, FuzzerGenerator& rng) { |
| 350 | if (length <= 1) { |
| 351 | return std::string(length, '0'); |
| 352 | } |
| 353 | std::string digitString; |
| 354 | digitString.resize(length); |
| 355 | std::uniform_int_distribution<int8_t> rand0To9(0, 9); |
| 356 | for (uint8_t i = 0; i < length - 1; ++i) { |
| 357 | digitString[i] = static_cast<char>('0' + rand0To9(rng)); |
| 358 | } |
| 359 | digitString[length - 1] = '5'; |
| 360 | BOLT_DCHECK_EQ( |
| 361 | digitString.size(), |
| 362 | length, |
| 363 | "Incorrect decimal string generation."); |
| 364 | return digitString; |
| 365 | }, |
| 366 | // .00...01 to simulate very small fractions. |
| 367 | [&](uint8_t length, FuzzerGenerator& /*rng*/) { |
| 368 | if (length <= 1) { |
| 369 | return std::string(length, '0'); |
| 370 | } |
| 371 | std::string digitString; |
| 372 | digitString.resize(length); |
| 373 | digitString.replace(0, length - 1, std::string(length - 1, '0')); |
| 374 | digitString[length - 1] = '1'; |
| 375 | BOLT_DCHECK_EQ( |