Repository: apache/arrow
File: cpp/src/arrow/testing/random.cc (C++)

Code before:
  template <typename V>
  typename std::enable_if<std::is_floating_point<V>::value>::type GenerateTypedData(
      V* data, size_t n) {
    if (nan_probability_ == 0.0) {
      GenerateTypedDataNoNan(data, n);
      return;
    }
    pcg32_fast rng(seed_++);
    DistributionType dist(min_, max_);
    ::arrow::random::bernoulli_distribution nan_dist(nan_probability_);
    const ValueType nan_value = std::numeric_limits<ValueType>::quiet_NaN();

    // A static cast is required due to the int16 -> int8 handling.
    std::generate(data, data + n, [&] {
      return nan_dist(rng) ? nan_value : static_cast<ValueType>(dist(rng));
    });
  }

  void GenerateTypedDataNoNan(ValueType* data, size_t n) {
    pcg32_fast rng(seed_++);
    DistributionType dist(min_, max_);

    // A static cast is required due to the int16 -> int8 handling.
    std::generate(data, data + n, [&] { return static_cast<ValueType>(dist(rng)); });
  }

  void GenerateBitmap(uint8_t* buffer, size_t n, int64_t* null_count) {
    int64_t count = 0;
    pcg32_fast rng(seed_++);
    ::arrow::random::bernoulli_distribution dist(1.0 - probability_);

    for (size_t i = 0; i < n; i++) {
      if (dist(rng)) {
        bit_util::SetBit(buffer, i);
      } else {
        count++;
      }
    }

    if (null_count != nullptr) *null_count = count;
  }

  ValueType min_;
  ValueType max_;
  SeedType seed_;
  double probability_;
  double nan_probability_;
};

void GenerateFullDayMillisNoNan(uint8_t* buffer, size_t n) {
  int64_t* data = reinterpret_cast<int64_t*>(buffer);

Review comment (suggestion):
This doesn't fix `GenerateTypedData` when `nan_probability_` is non-zero (it will use `std::numeric_limits<uint16_t>::quiet_NaN()` which is 0 and translates to `Float16(0.0)`).

Code after:

  auto operator()(pcg32_fast* rng) const {
    return [dist = DistributionType(min_, max_), rng]() mutable {
      return Float16(dist(*rng)).bits();
    };
  }

 private:
  float min_;
  float max_;
};

template <typename ValueType, typename DistributionType>
struct GenerateOptions {
  static constexpr bool kIsHalfFloat = std::is_same_v<ValueType, Float16>;
  using PhysicalType = std::conditional_t<kIsHalfFloat, HalfFloatType::c_type, ValueType>;
  using FactoryType = GeneratorFactory<ValueType, DistributionType>;

  GenerateOptions(SeedType seed, ValueType min, ValueType max, double probability,
                  double nan_probability = 0.0)
      : generator_factory_(FactoryType(min, max)),
        seed_(seed),
        probability_(probability),
        nan_probability_(nan_probability) {}

  void GenerateData(uint8_t* buffer, size_t n) {
    GenerateTypedData(reinterpret_cast<PhysicalType*>(buffer), n);
  }

  template <typename V>
  typename std::enable_if<!std::is_floating_point_v<V> && !kIsHalfFloat>::type
  GenerateTypedData(V* data, size_t n) {
    GenerateTypedDataNoNan(data, n);
  }

  template <typename V>
  typename std::enable_if<std::is_floating_point_v<V> || kIsHalfFloat>::type
  GenerateTypedData(V* data, size_t n) {
    if (nan_probability_ == 0.0) {
      GenerateTypedDataNoNan(data, n);
      return;
    }
    pcg32_fast rng(seed_++);
    auto gen = generator_factory_(&rng);
    ::arrow::random::bernoulli_distribution nan_dist(nan_probability_);
    const PhysicalType nan_value = get_nan();

    std::generate(data, data + n, [&] { return nan_dist(rng) ? nan_value : gen(); });
  }

  void GenerateTypedDataNoNan(PhysicalType* data, size_t n) {