<commit_before>
#define GLOG_NO_ABBREVIATED_SEVERITIES
#include "base/hexadecimal.hpp"
#include "base/not_null.hpp"

// Must come last to avoid conflicts when defining the CHECK macros.
#include "benchmark/benchmark.h"

using principia::base::not_null;
using principia::base::HexadecimalDecode;
using principia::base::HexadecimalEncode;

namespace principia {
namespace benchmarks {

static char const kPi1000HexadecimalDigits[] =
    "3243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E63"
    "8D01377BE5466CF34E90C6CC0AC29B7C97C50DD3F84D5B5B54709179216D5D98979FB1BD13"
    "10BA698DFB5AC2FFD72DBD01ADFB7B8E1AFED6A267E96BA7C9045F12C7F9924A19947B3916"
    "CF70801F2E2858EFC16636920D871574E69A458FEA3F4933D7E0D95748F728EB658718BCD5"
    "882154AEE7B54A41DC25A59B59C30D5392AF26013C5D1B023286085F0CA417918B8DB38EF8"
    "E79DCB0603A180E6C9E0E8BB01E8A3ED71577C1BD314B2778AF2FDA55605C60E65525F3AA5"
    "5AB945748986263E8144055CA396A2AAB10B6B4CC5C341141E8CEA15486AF7C72E993B3EE1"
    "411636FBC2A2BA9C55D741831F6CE5C3E169B87931EAFD6BA336C24CF5C7A3253812895867"
    "73B8F48986B4BB9AFC4BFE81B6628219361D809CCFB21A991487CAC605DEC8032EF845D5DE"
    "98575B1DC262302EB651B8823893E81D396ACC50F6D6FF383F442392E0B4482A484200469C"
    "8F04A9E1F9B5E21C66842F6E96C9A670C9C61ABD388F06A51A0D2D8542F68960FA728AB513"
    "3A36EEF0B6C137A3BE4BA3BF0507EFB2A98A1F1651D39AF017666CA593E82430E888CEE861"
    "9456F9FB47D84A5C33B8B5EBEE06F75D885C12073401A449F56C16AA64ED3AA62363F77061"
    "BFEDF72429B023D37D0D724D00A1248DB0FEAD";

static char const kPi500Bytes[] =
    "\x32\x43\xF6\xA8\x88\x5A\x30\x8D\x31\x31\x98\xA2\xE0\x37\x07\x34\x4A\x40"
    "\x93\x82\x22\x99\xF3\x1D\x00\x82\xEF\xA9\x8E\xC4\xE6\xC8\x94\x52\x82\x1E"
    "\x63\x8D\x01\x37\x7B\xE5\x46\x6C\xF3\x4E\x90\xC6\xCC\x0A\xC2\x9B\x7C\x97"
    "\xC5\x0D\xD3\xF8\x4D\x5B\x5B\x54\x70\x91\x79\x21\x6D\x5D\x98\x97\x9F\xB1"
    "\xBD\x13\x10\xBA\x69\x8D\xFB\x5A\xC2\xFF\xD7\x2D\xBD\x01\xAD\xFB\x7B\x8E"
    "\x1A\xFE\xD6\xA2\x67\xE9\x6B\xA7\xC9\x04\x5F\x12\xC7\xF9\x92\x4A\x19\x94"
    "\x7B\x39\x16\xCF\x70\x80\x1F\x2E\x28\x58\xEF\xC1\x66\x36\x92\x0D\x87\x15"
    "\x74\xE6\x9A\x45\x8F\xEA\x3F\x49\x33\xD7\xE0\xD9\x57\x48\xF7\x28\xEB\x65"
    "\x87\x18\xBC\xD5\x88\x21\x54\xAE\xE7\xB5\x4A\x41\xDC\x25\xA5\x9B\x59\xC3"
    "\x0D\x53\x92\xAF\x26\x01\x3C\x5D\x1B\x02\x32\x86\x08\x5F\x0C\xA4\x17\x91"
    "\x8B\x8D\xB3\x8E\xF8\xE7\x9D\xCB\x06\x03\xA1\x80\xE6\xC9\xE0\xE8\xBB\x01"
    "\xE8\xA3\xED\x71\x57\x7C\x1B\xD3\x14\xB2\x77\x8A\xF2\xFD\xA5\x56\x05\xC6"
    "\x0E\x65\x52\x5F\x3A\xA5\x5A\xB9\x45\x74\x89\x86\x26\x3E\x81\x44\x05\x5C"
    "\xA3\x96\xA2\xAA\xB1\x0B\x6B\x4C\xC5\xC3\x41\x14\x1E\x8C\xEA\x15\x48\x6A"
    "\xF7\xC7\x2E\x99\x3B\x3E\xE1\x41\x16\x36\xFB\xC2\xA2\xBA\x9C\x55\xD7\x41"
    "\x83\x1F\x6C\xE5\xC3\xE1\x69\xB8\x79\x31\xEA\xFD\x6B\xA3\x36\xC2\x4C\xF5"
    "\xC7\xA3\x25\x38\x12\x89\x58\x67\x73\xB8\xF4\x89\x86\xB4\xBB\x9A\xFC\x4B"
    "\xFE\x81\xB6\x62\x82\x19\x36\x1D\x80\x9C\xCF\xB2\x1A\x99\x14\x87\xCA\xC6"
    "\x05\xDE\xC8\x03\x2E\xF8\x45\xD5\xDE\x98\x57\x5B\x1D\xC2\x62\x30\x2E\xB6"
    "\x51\xB8\x82\x38\x93\xE8\x1D\x39\x6A\xCC\x50\xF6\xD6\xFF\x38\x3F\x44\x23"
    "\x92\xE0\xB4\x48\x2A\x48\x42\x00\x46\x9C\x8F\x04\xA9\xE1\xF9\xB5\xE2\x1C"
    "\x66\x84\x2F\x6E\x96\xC9\xA6\x70\xC9\xC6\x1A\xBD\x38\x8F\x06\xA5\x1A\x0D"
    "\x2D\x85\x42\xF6\x89\x60\xFA\x72\x8A\xB5\x13\x3A\x36\xEE\xF0\xB6\xC1\x37"
    "\xA3\xBE\x4B\xA3\xBF\x05\x07\xEF\xB2\xA9\x8A\x1F\x16\x51\xD3\x9A\xF0\x17"
    "\x66\x6C\xA5\x93\xE8\x24\x30\xE8\x88\xCE\xE8\x61\x94\x56\xF9\xFB\x47\xD8"
    "\x4A\x5C\x33\xB8\xB5\xEB\xEE\x06\xF7\x5D\x88\x5C\x12\x07\x34\x01\xA4\x49"
    "\xF5\x6C\x16\xAA\x64\xED\x3A\xA6\x23\x63\xF7\x70\x61\xBF\xED\xF7\x24\x29"
    "\xB0\x23\xD3\x7D\x0D\x72\x4D\x00\xA1\x24\x8D\xB0\xFE\xAD";

int const kCopiesOfPi = 10000;

void HexEncode(not_null<benchmark::State*> const state,
              not_null<bool*> const correct,
              std::vector<uint8_t> const& input_bytes,
              std::vector<uint8_t> const& expected_digits) {
  std::vector<uint8_t> digits(input_bytes.size() << 1);
  HexadecimalEncode(input_bytes.data(), input_bytes.size(),
                    digits.data(), digits.size());
  state->PauseTiming();
  *correct &= digits == expected_digits;
  state->ResumeTiming();
}

std::vector<uint8_t> Bytes() {
  std::string const pi_bytes(kPi500Bytes, 500);
  std::string bytes_str;
  bytes_str.reserve(500 * kCopiesOfPi);
  for (int i = 0; i < kCopiesOfPi; ++i) {
    bytes_str += pi_bytes;
  }
  return std::vector<uint8_t>(bytes_str.begin(), bytes_str.end());
}

std::vector<uint8_t> Digits() {
  std::string digits_str;
  digits_str.reserve(1000 * kCopiesOfPi);
  for (int i = 0; i < kCopiesOfPi; ++i) {
    digits_str += kPi1000HexadecimalDigits;
  }
  return std::vector<uint8_t>(digits_str.begin(), digits_str.end());
}

void BM_EncodePi(benchmark::State& state) {  // NOLINT(runtime/references)
  bool correct = true;
  state.PauseTiming();
  std::vector<uint8_t> const input_bytes = Bytes();
  std::vector<uint8_t> const expected_digits = Digits();
  state.ResumeTiming();
  while (state.KeepRunning()) {
    HexEncode(&state, &correct, input_bytes, expected_digits);
  }
  std::stringstream ss;
  ss << correct;
  state.SetLabel(ss.str());
}

BENCHMARK(BM_EncodePi);

void HexDecode(not_null<benchmark::State*> const state,
               not_null<bool*> const correct,
               std::vector<uint8_t> const& input_digits,
               std::vector<uint8_t> const& expected_bytes) {
  std::vector<uint8_t> bytes(input_digits.size() / 2);
  HexadecimalDecode(input_digits.data(), input_digits.size(),
                    bytes.data(), bytes.size());
  state->PauseTiming();
  *correct &= bytes == expected_bytes;
  state->ResumeTiming();
}

void BM_DecodePi(benchmark::State& state) {  // NOLINT(runtime/references)
  bool correct = true;
  state.PauseTiming();
  std::vector<uint8_t> input_digits = Digits();
  std::vector<uint8_t> expected_bytes = Bytes();
  state.ResumeTiming();
  while (state.KeepRunning()) {
    HexDecode(&state, &correct, input_digits, expected_bytes);
  }
  std::stringstream ss;
  ss << correct;
  state.SetLabel(ss.str());
}

BENCHMARK(BM_DecodePi);

}  // namespace benchmarks
}  // namespace principia
<commit_msg>Don't count allocation time<commit_after>
#define GLOG_NO_ABBREVIATED_SEVERITIES
#include "base/hexadecimal.hpp"
#include "base/not_null.hpp"

// Must come last to avoid conflicts when defining the CHECK macros.
#include "benchmark/benchmark.h"

using principia::base::not_null;
using principia::base::HexadecimalDecode;
using principia::base::HexadecimalEncode;

namespace principia {
namespace benchmarks {

static char const kPi1000HexadecimalDigits[] =
    "3243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E63"
    "8D01377BE5466CF34E90C6CC0AC29B7C97C50DD3F84D5B5B54709179216D5D98979FB1BD13"
    "10BA698DFB5AC2FFD72DBD01ADFB7B8E1AFED6A267E96BA7C9045F12C7F9924A19947B3916"
    "CF70801F2E2858EFC16636920D871574E69A458FEA3F4933D7E0D95748F728EB658718BCD5"
    "882154AEE7B54A41DC25A59B59C30D5392AF26013C5D1B023286085F0CA417918B8DB38EF8"
    "E79DCB0603A180E6C9E0E8BB01E8A3ED71577C1BD314B2778AF2FDA55605C60E65525F3AA5"
    "5AB945748986263E8144055CA396A2AAB10B6B4CC5C341141E8CEA15486AF7C72E993B3EE1"
    "411636FBC2A2BA9C55D741831F6CE5C3E169B87931EAFD6BA336C24CF5C7A3253812895867"
    "73B8F48986B4BB9AFC4BFE81B6628219361D809CCFB21A991487CAC605DEC8032EF845D5DE"
    "98575B1DC262302EB651B8823893E81D396ACC50F6D6FF383F442392E0B4482A484200469C"
    "8F04A9E1F9B5E21C66842F6E96C9A670C9C61ABD388F06A51A0D2D8542F68960FA728AB513"
    "3A36EEF0B6C137A3BE4BA3BF0507EFB2A98A1F1651D39AF017666CA593E82430E888CEE861"
    "9456F9FB47D84A5C33B8B5EBEE06F75D885C12073401A449F56C16AA64ED3AA62363F77061"
    "BFEDF72429B023D37D0D724D00A1248DB0FEAD";

static char const kPi500Bytes[] =
    "\x32\x43\xF6\xA8\x88\x5A\x30\x8D\x31\x31\x98\xA2\xE0\x37\x07\x34\x4A\x40"
    "\x93\x82\x22\x99\xF3\x1D\x00\x82\xEF\xA9\x8E\xC4\xE6\xC8\x94\x52\x82\x1E"
    "\x63\x8D\x01\x37\x7B\xE5\x46\x6C\xF3\x4E\x90\xC6\xCC\x0A\xC2\x9B\x7C\x97"
    "\xC5\x0D\xD3\xF8\x4D\x5B\x5B\x54\x70\x91\x79\x21\x6D\x5D\x98\x97\x9F\xB1"
    "\xBD\x13\x10\xBA\x69\x8D\xFB\x5A\xC2\xFF\xD7\x2D\xBD\x01\xAD\xFB\x7B\x8E"
    "\x1A\xFE\xD6\xA2\x67\xE9\x6B\xA7\xC9\x04\x5F\x12\xC7\xF9\x92\x4A\x19\x94"
    "\x7B\x39\x16\xCF\x70\x80\x1F\x2E\x28\x58\xEF\xC1\x66\x36\x92\x0D\x87\x15"
    "\x74\xE6\x9A\x45\x8F\xEA\x3F\x49\x33\xD7\xE0\xD9\x57\x48\xF7\x28\xEB\x65"
    "\x87\x18\xBC\xD5\x88\x21\x54\xAE\xE7\xB5\x4A\x41\xDC\x25\xA5\x9B\x59\xC3"
    "\x0D\x53\x92\xAF\x26\x01\x3C\x5D\x1B\x02\x32\x86\x08\x5F\x0C\xA4\x17\x91"
    "\x8B\x8D\xB3\x8E\xF8\xE7\x9D\xCB\x06\x03\xA1\x80\xE6\xC9\xE0\xE8\xBB\x01"
    "\xE8\xA3\xED\x71\x57\x7C\x1B\xD3\x14\xB2\x77\x8A\xF2\xFD\xA5\x56\x05\xC6"
    "\x0E\x65\x52\x5F\x3A\xA5\x5A\xB9\x45\x74\x89\x86\x26\x3E\x81\x44\x05\x5C"
    "\xA3\x96\xA2\xAA\xB1\x0B\x6B\x4C\xC5\xC3\x41\x14\x1E\x8C\xEA\x15\x48\x6A"
    "\xF7\xC7\x2E\x99\x3B\x3E\xE1\x41\x16\x36\xFB\xC2\xA2\xBA\x9C\x55\xD7\x41"
    "\x83\x1F\x6C\xE5\xC3\xE1\x69\xB8\x79\x31\xEA\xFD\x6B\xA3\x36\xC2\x4C\xF5"
    "\xC7\xA3\x25\x38\x12\x89\x58\x67\x73\xB8\xF4\x89\x86\xB4\xBB\x9A\xFC\x4B"
    "\xFE\x81\xB6\x62\x82\x19\x36\x1D\x80\x9C\xCF\xB2\x1A\x99\x14\x87\xCA\xC6"
    "\x05\xDE\xC8\x03\x2E\xF8\x45\xD5\xDE\x98\x57\x5B\x1D\xC2\x62\x30\x2E\xB6"
    "\x51\xB8\x82\x38\x93\xE8\x1D\x39\x6A\xCC\x50\xF6\xD6\xFF\x38\x3F\x44\x23"
    "\x92\xE0\xB4\x48\x2A\x48\x42\x00\x46\x9C\x8F\x04\xA9\xE1\xF9\xB5\xE2\x1C"
    "\x66\x84\x2F\x6E\x96\xC9\xA6\x70\xC9\xC6\x1A\xBD\x38\x8F\x06\xA5\x1A\x0D"
    "\x2D\x85\x42\xF6\x89\x60\xFA\x72\x8A\xB5\x13\x3A\x36\xEE\xF0\xB6\xC1\x37"
    "\xA3\xBE\x4B\xA3\xBF\x05\x07\xEF\xB2\xA9\x8A\x1F\x16\x51\xD3\x9A\xF0\x17"
    "\x66\x6C\xA5\x93\xE8\x24\x30\xE8\x88\xCE\xE8\x61\x94\x56\xF9\xFB\x47\xD8"
    "\x4A\x5C\x33\xB8\xB5\xEB\xEE\x06\xF7\x5D\x88\x5C\x12\x07\x34\x01\xA4\x49"
    "\xF5\x6C\x16\xAA\x64\xED\x3A\xA6\x23\x63\xF7\x70\x61\xBF\xED\xF7\x24\x29"
    "\xB0\x23\xD3\x7D\x0D\x72\x4D\x00\xA1\x24\x8D\xB0\xFE\xAD";

int const kCopiesOfPi = 10000;

void HexEncode(not_null<benchmark::State*> const state,
              not_null<bool*> const correct,
              std::vector<uint8_t> const& input_bytes,
              std::vector<uint8_t> const& expected_digits) {
  state->PauseTiming();
  std::vector<uint8_t> digits(input_bytes.size() << 1);
  state->ResumeTiming();
  HexadecimalEncode(input_bytes.data(), input_bytes.size(),
                    digits.data(), digits.size());
  state->PauseTiming();
  *correct &= digits == expected_digits;
  state->ResumeTiming();
}

std::vector<uint8_t> Bytes() {
  std::string const pi_bytes(kPi500Bytes, 500);
  std::string bytes_str;
  bytes_str.reserve(500 * kCopiesOfPi);
  for (int i = 0; i < kCopiesOfPi; ++i) {
    bytes_str += pi_bytes;
  }
  return std::vector<uint8_t>(bytes_str.begin(), bytes_str.end());
}

std::vector<uint8_t> Digits() {
  std::string digits_str;
  digits_str.reserve(1000 * kCopiesOfPi);
  for (int i = 0; i < kCopiesOfPi; ++i) {
    digits_str += kPi1000HexadecimalDigits;
  }
  return std::vector<uint8_t>(digits_str.begin(), digits_str.end());
}

void BM_EncodePi(benchmark::State& state) {  // NOLINT(runtime/references)
  bool correct = true;
  state.PauseTiming();
  std::vector<uint8_t> const input_bytes = Bytes();
  std::vector<uint8_t> const expected_digits = Digits();
  state.ResumeTiming();
  while (state.KeepRunning()) {
    HexEncode(&state, &correct, input_bytes, expected_digits);
  }
  std::stringstream ss;
  ss << correct;
  state.SetLabel(ss.str());
}

BENCHMARK(BM_EncodePi);

void HexDecode(not_null<benchmark::State*> const state,
               not_null<bool*> const correct,
               std::vector<uint8_t> const& input_digits,
               std::vector<uint8_t> const& expected_bytes) {
  state->PauseTiming();
  std::vector<uint8_t> bytes(input_digits.size() / 2);
  state->ResumeTiming();
  HexadecimalDecode(input_digits.data(), input_digits.size(),
                    bytes.data(), bytes.size());
  state->PauseTiming();
  *correct &= bytes == expected_bytes;
  state->ResumeTiming();
}

void BM_DecodePi(benchmark::State& state) {  // NOLINT(runtime/references)
  bool correct = true;
  state.PauseTiming();
  std::vector<uint8_t> input_digits = Digits();
  std::vector<uint8_t> expected_bytes = Bytes();
  state.ResumeTiming();
  while (state.KeepRunning()) {
    HexDecode(&state, &correct, input_digits, expected_bytes);
  }
  std::stringstream ss;
  ss << correct;
  state.SetLabel(ss.str());
}

BENCHMARK(BM_DecodePi);

}  // namespace benchmarks
}  // namespace principia
<|endoftext|>


<commit_before>#include <catch.hpp>
#include <rapidcheck-catch.h>

#include "util/Predictable.h"

using namespace rc;

// Always increasing type for testing generatinon ordering. Note that this is
// very much a hack but it will catch regressions where arguments are not
// generated in the correct order.
struct IncInt { int value; };

namespace rc {

template<>
class Arbitrary<IncInt> : public gen::Generator<IncInt>
{
public:
    IncInt generate() const override
    {
        return IncInt { value()++ };
    }

    static int &value()
    {
        static int value = 0;
        return value;
    }

    static void reset()
    { value() = 0; }
};

} // namespace rc

namespace {

void show(IncInt x, std::ostream &os) { os << x.value; }

} // namespace

TEST_CASE("gen::lambda") {
    prop("generates the return value of the given callable",
         [] (int x) {
             auto generator = gen::lambda([=] { return x; });
             for (int i = 0; i < gen::currentSize(); i++)
                 RC_ASSERT(*generator == x);
         });
}

TEST_CASE("gen::rescue") {
    prop("converts exceptions to generated values",
         [] (int x) {
             auto generator = gen::lambda([=] {
                 throw std::to_string(x);
                 return std::string("");
             });

             std::string str(
                 *gen::noShrink(
                     gen::rescue<std::string>(
                         generator,
                         [] (const std::string &ex) {
                             return ex;
                         })));

             RC_ASSERT(str == std::to_string(x));
         });
}

TEST_CASE("gen::anyInvocation") {
    prop("generates arguments in listing order",
         [] {
             Arbitrary<IncInt>::reset();
             auto tuple = *gen::noShrink(
                 gen::anyInvocation(
                     [] (IncInt a, IncInt b, IncInt c) {
                         return std::make_tuple(a.value, b.value, c.value);
                     }));

             RC_ASSERT(std::get<0>(tuple) < std::get<1>(tuple));
             RC_ASSERT(std::get<1>(tuple) < std::get<2>(tuple));
         });

    prop("uses the appropriate Arbitrary instance",
         [] {
             auto tuple = *gen::noShrink(
                 gen::anyInvocation(
                     [] (const Predictable &a,
                         Predictable &&b,
                         Predictable c)
             {
                 return std::make_tuple(a.value, b.value, c.value);
             }));
             RC_ASSERT(std::get<0>(tuple) == Predictable::predictableValue);
             RC_ASSERT(std::get<1>(tuple) == Predictable::predictableValue);
             RC_ASSERT(std::get<2>(tuple) == Predictable::predictableValue);
         });

    prop("uses the return value as the generated value",
         [] {
             int x = *gen::noShrink(
                 gen::anyInvocation([] (int a, int b) { return 12345; }));
             RC_ASSERT(x == 12345);
         });
}
<commit_msg>Use isArbitraryPredictable in InvokeTests instead of predictableValue<commit_after>#include <catch.hpp>
#include <rapidcheck-catch.h>

#include "util/Predictable.h"

using namespace rc;

// Always increasing type for testing generatinon ordering. Note that this is
// very much a hack but it will catch regressions where arguments are not
// generated in the correct order.
struct IncInt { int value; };

namespace rc {

template<>
class Arbitrary<IncInt> : public gen::Generator<IncInt>
{
public:
    IncInt generate() const override
    {
        return IncInt { value()++ };
    }

    static int &value()
    {
        static int value = 0;
        return value;
    }

    static void reset()
    { value() = 0; }
};

} // namespace rc

namespace {

void show(IncInt x, std::ostream &os) { os << x.value; }

} // namespace

TEST_CASE("gen::lambda") {
    prop("generates the return value of the given callable",
         [] (int x) {
             auto generator = gen::lambda([=] { return x; });
             for (int i = 0; i < gen::currentSize(); i++)
                 RC_ASSERT(*generator == x);
         });
}

TEST_CASE("gen::rescue") {
    prop("converts exceptions to generated values",
         [] (int x) {
             auto generator = gen::lambda([=] {
                 throw std::to_string(x);
                 return std::string("");
             });

             std::string str(
                 *gen::noShrink(
                     gen::rescue<std::string>(
                         generator,
                         [] (const std::string &ex) {
                             return ex;
                         })));

             RC_ASSERT(str == std::to_string(x));
         });
}

TEST_CASE("gen::anyInvocation") {
    prop("generates arguments in listing order",
         [] {
             Arbitrary<IncInt>::reset();
             auto tuple = *gen::noShrink(
                 gen::anyInvocation(
                     [] (IncInt a, IncInt b, IncInt c) {
                         return std::make_tuple(a.value, b.value, c.value);
                     }));

             RC_ASSERT(std::get<0>(tuple) < std::get<1>(tuple));
             RC_ASSERT(std::get<1>(tuple) < std::get<2>(tuple));
         });

    prop("uses the appropriate Arbitrary instance",
         [] {
             auto tuple = *gen::noShrink(
                 gen::anyInvocation(
                     [] (const Predictable &a,
                         Predictable &&b,
                         Predictable c)
             {
                 return std::make_tuple(a, b, c);
             }));
             RC_ASSERT(isArbitraryPredictable(std::get<0>(tuple)));
             RC_ASSERT(isArbitraryPredictable(std::get<1>(tuple)));
             RC_ASSERT(isArbitraryPredictable(std::get<2>(tuple)));
         });

    prop("uses the return value as the generated value",
         [] {
             int x = *gen::noShrink(
                 gen::anyInvocation([] (int a, int b) { return 12345; }));
             RC_ASSERT(x == 12345);
         });
}
<|endoftext|>


<commit_before>// ------------------------------------------------------------------------
// audioio-ewf.cpp: Ecasound wave format input/output
// Copyright (C) 1999-2002,2005,2008 Kai Vehmanen
//
// Attributes:
//     eca-style-version: 3 (see Ecasound Programmer's Guide)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
// ------------------------------------------------------------------------

#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <cmath>

#include <kvu_message_item.h>
#include <kvu_numtostr.h>
#include <kvu_dbc.h>

#include "eca-object-factory.h"
#include "samplebuffer.h"
#include "audioio-ewf.h"

#include "eca-error.h"
#include "eca-logger.h"

using std::cout;
using std::endl;
using SAMPLE_SPECS::sample_pos_t;

/**
 * FIXME notes  (last update 2008-03-09)
 *
 *  - Add (more) sanity checks for ewf fields.
 */

EWFFILE::EWFFILE (void)
{
}

EWFFILE::~EWFFILE(void)
{
}

EWFFILE* EWFFILE::clone(void) const
{
  EWFFILE* target = new EWFFILE();
  for(int n = 0; n < number_of_params(); n++) {
    target->set_parameter(n + 1, get_parameter(n + 1));
  }
  return target;
}

void EWFFILE::open(void) throw(AUDIO_IO::SETUP_ERROR &)
{
  if (io_mode() != AUDIO_IO::io_read)
    ECA_LOG_MSG(ECA_LOGGER::info,
		"WARNING: Writing to EWF files is a deprecated feature since 2.4.7 (2008), and it will be disabled in a future release.");

  ewf_rc.resource_file(label());
  ewf_rc.load();
  read_ewf_data();

  AUDIO_SEQUENCER_BASE::open();
}

void EWFFILE::close(void)
{
  if (io_mode() != AUDIO_IO::io_read)
    write_ewf_data();

  AUDIO_SEQUENCER_BASE::close();
}

void EWFFILE::init_default_child(void) throw(ECA_ERROR&)
{
  string::const_iterator e = std::find(label().begin(), label().end(), '.');
  if (e == label().end()) {
    throw(ECA_ERROR("AUDIOIO-EWF", "Invalid file name; unable to open file.",ECA_ERROR::retry));
  }

  string child_name (label().begin(), e);
  child_name += ".wav";
  set_child_object_string(child_name);

  DBC_CHECK(child_name == child_object_string());

  ewf_rc.resource("source", child_object_string());
}

void EWFFILE::read_ewf_data(void) throw(ECA_ERROR&)
{
  if (ewf_rc.has("source"))
    set_child_object_string(ewf_rc.resource("source"));
  else
    init_default_child();

  if (ewf_rc.has("offset")) {
    set_child_offset(ECA_AUDIO_TIME(ewf_rc.resource("offset")));
  }
  else
    set_child_offset(ECA_AUDIO_TIME());

  /* FIXME: doesn't work, if child has different srate and start-pos
   *        specified in samples, the result is incorrect! */

  if (ewf_rc.has("start-position")) {
    set_child_start_position(ECA_AUDIO_TIME(ewf_rc.resource("start-position")));
  }
  else
    set_child_start_position(ECA_AUDIO_TIME());

  if (ewf_rc.has("length")) {
    set_child_length(ECA_AUDIO_TIME(ewf_rc.resource("length")));
  }
  else
    set_child_length(ECA_AUDIO_TIME());

  toggle_looping(ewf_rc.boolean_resource("looping"));

  const std::vector<std::string> keys = ewf_rc.keywords();
  std::vector<std::string>::const_iterator p = keys.begin();
  while(p != keys.end()) {
    if (*p != "source" &&
	*p != "offset" &&
	*p != "start-position" &&
	*p != "length" &&
	*p != "looping")
      ECA_LOG_MSG(ECA_LOGGER::info,
		  "WARNING: Unknown keyword '"
		  + *p
		  + "' in EWF file '"
		  + label()
		  + "'.");
    ++p;
  }
}

void EWFFILE::write_ewf_data(void)
{
  ewf_rc.resource("source", child_object_string());
  if (child_offset().samples() > 0)
    ewf_rc.resource("offset", kvu_numtostr(child_offset().seconds(),6));
  if (child_start_position().samples() != 0)
    ewf_rc.resource("start-position", kvu_numtostr(child_start_position().seconds(), 6));
  if (child_looping() == true)
    ewf_rc.resource("looping","true");
  if (child_length().valid() == true)
    ewf_rc.resource("length", kvu_numtostr(child_length().seconds(),  6));

  ewf_rc.save();
}

std::string EWFFILE::parameter_names(void) const
{
  return AUDIO_IO::parameter_names();
}

void EWFFILE::set_parameter(int param, std::string value)
{
  AUDIO_IO::set_parameter(param, value);
}

std::string EWFFILE::get_parameter(int param) const
{
  return AUDIO_IO::get_parameter(param);
}
<commit_msg>Fixed a bug in detecting end-of-stream of EWF files. Bug reported by Julien Claassen.<commit_after>// ------------------------------------------------------------------------
// audioio-ewf.cpp: Ecasound wave format input/output
// Copyright (C) 1999-2002,2005,2008 Kai Vehmanen
//
// Attributes:
//     eca-style-version: 3 (see Ecasound Programmer's Guide)
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
// ------------------------------------------------------------------------

#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <cmath>

#include <kvu_message_item.h>
#include <kvu_numtostr.h>
#include <kvu_dbc.h>

#include "eca-object-factory.h"
#include "samplebuffer.h"
#include "audioio-ewf.h"

#include "eca-error.h"
#include "eca-logger.h"

using std::cout;
using std::endl;
using SAMPLE_SPECS::sample_pos_t;

/**
 * FIXME notes  (last update 2008-03-09)
 *
 *  - Add (more) sanity checks for ewf fields.
 */

EWFFILE::EWFFILE (void)
{
}

EWFFILE::~EWFFILE(void)
{
}

EWFFILE* EWFFILE::clone(void) const
{
  EWFFILE* target = new EWFFILE();
  for(int n = 0; n < number_of_params(); n++) {
    target->set_parameter(n + 1, get_parameter(n + 1));
  }
  return target;
}

void EWFFILE::open(void) throw(AUDIO_IO::SETUP_ERROR &)
{
  if (io_mode() != AUDIO_IO::io_read)
    ECA_LOG_MSG(ECA_LOGGER::info,
		"WARNING: Writing to EWF files is a deprecated feature since 2.4.7 (2008), and it will be disabled in a future release.");

  ewf_rc.resource_file(label());
  ewf_rc.load();
  read_ewf_data();

  AUDIO_SEQUENCER_BASE::open();
}

void EWFFILE::close(void)
{
  if (io_mode() != AUDIO_IO::io_read)
    write_ewf_data();

  AUDIO_SEQUENCER_BASE::close();
}

void EWFFILE::init_default_child(void) throw(ECA_ERROR&)
{
  string::const_iterator e = std::find(label().begin(), label().end(), '.');
  if (e == label().end()) {
    throw(ECA_ERROR("AUDIOIO-EWF", "Invalid file name; unable to open file.",ECA_ERROR::retry));
  }

  string child_name (label().begin(), e);
  child_name += ".wav";
  set_child_object_string(child_name);

  DBC_CHECK(child_name == child_object_string());

  ewf_rc.resource("source", child_object_string());
}

void EWFFILE::read_ewf_data(void) throw(ECA_ERROR&)
{
  if (ewf_rc.has("source"))
    set_child_object_string(ewf_rc.resource("source"));
  else
    init_default_child();

  if (ewf_rc.has("offset")) {
    set_child_offset(ECA_AUDIO_TIME(ewf_rc.resource("offset")));
  }
  else
    set_child_offset(ECA_AUDIO_TIME());

  /* FIXME: doesn't work, if child has different srate and start-pos
   *        specified in samples, the result is incorrect! */

  if (ewf_rc.has("start-position")) {
    set_child_start_position(ECA_AUDIO_TIME(ewf_rc.resource("start-position")));
  }
  else
    set_child_start_position(ECA_AUDIO_TIME());

  if (ewf_rc.has("length")) {
    set_child_length(ECA_AUDIO_TIME(ewf_rc.resource("length")));
  }

  toggle_looping(ewf_rc.boolean_resource("looping"));

  const std::vector<std::string> keys = ewf_rc.keywords();
  std::vector<std::string>::const_iterator p = keys.begin();
  while(p != keys.end()) {
    if (*p != "source" &&
	*p != "offset" &&
	*p != "start-position" &&
	*p != "length" &&
	*p != "looping")
      ECA_LOG_MSG(ECA_LOGGER::info,
		  "WARNING: Unknown keyword '"
		  + *p
		  + "' in EWF file '"
		  + label()
		  + "'.");
    ++p;
  }
}

void EWFFILE::write_ewf_data(void)
{
  ewf_rc.resource("source", child_object_string());
  if (child_offset().samples() > 0)
    ewf_rc.resource("offset", kvu_numtostr(child_offset().seconds(),6));
  if (child_start_position().samples() != 0)
    ewf_rc.resource("start-position", kvu_numtostr(child_start_position().seconds(), 6));
  if (child_looping() == true)
    ewf_rc.resource("looping","true");
  if (child_length().valid() == true)
    ewf_rc.resource("length", kvu_numtostr(child_length().seconds(),  6));

  ewf_rc.save();
}

std::string EWFFILE::parameter_names(void) const
{
  return AUDIO_IO::parameter_names();
}

void EWFFILE::set_parameter(int param, std::string value)
{
  AUDIO_IO::set_parameter(param, value);
}

std::string EWFFILE::get_parameter(int param) const
{
  return AUDIO_IO::get_parameter(param);
}
<|endoftext|>


<commit_before>#include <cmath>
#include <cstring>
#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <limits>
#include <random>
#include <vector>

#include <sys/resource.h>

#include "hashpack.h"
#include "hashmap.h"
#include "timers.hpp"

using namespace std;
using namespace rigtorp;

template <typename ht>
void populate(ht & h, vector<uint64_t> & keys) {
    for(size_t i = 0; i < keys.size(); ++i) {
        h.emplace(keys[i], i);
    }
}

template <typename ht>
size_t  query(ht & h, vector<uint64_t> & keys, size_t howmany) {
    size_t sum = 0;
    for(size_t i = 0; i < howmany; ++i) {
        auto it = h.find(keys[i]);
        if(it != h.end()) sum+= it->second;
    }
    return sum;
}

template <typename ht>
void query_avg_probed_keys(ht & h, vector<uint64_t> & keys, double * average, double * stderrprob) {
    double sum = 0;
    double sumsquare = 0;
    for(size_t i = 0; i < keys.size(); ++i) {
        double probed = h.probed_keys(keys[i]);
        sum += probed;
        sumsquare += probed * probed;
    }
    *average = sum  / keys.size();
    *stderrprob = sqrt(sumsquare /  keys.size() - *average * *average );
}

template <typename ht>
size_t query_max_probed_keys(ht & h, vector<uint64_t> & keys) {
    size_t mp = 0;
    for(size_t i = 0; i < keys.size(); ++i) {
        size_t tp = h.probed_keys(keys[i]);
        if(tp > mp) mp = tp;
    }
    return mp;
}
const uint64_t EMPTY = 0xFFFFFFFFFFFFFFFF;

struct BasicWorker {
    template <typename Pack>
    static inline void Go(std::vector<uint64_t> &keys, const float loadfactor,
                          const int repeat, size_t howmanyqueries) {
        double querycycles = 0;
        double probesperquery = 0;
        double probesperquerystderr = 0;
        double maxprobesperquery = 0;

        size_t howmany = keys.size();
        assert(howmanyqueries <= howmany);
        std::cout << "testing " << setw(20) << string(Pack::NAME) << " ";
        std::cout.flush();
        uint64_t sum = 0;
        vector<HashMap<uint64_t, uint32_t, Pack>> collection;
        uint64_t cycles_start, cycles_end;
        for (int r = 0; r < repeat; ++r) {
            HashMap<uint64_t, uint32_t, Pack> hm(16, EMPTY, loadfactor);
            cycles_start = RDTSC_START();
            populate(hm, keys);
            cycles_end = RDTSC_FINAL();
            collection.push_back(hm);
        }
        double max_avg_probes = 0;
        for (int r = 0; r < repeat; ++r) {
            HashMap<uint64_t, uint32_t, Pack> &hm = collection[r];
            cycles_start = RDTSC_START();
            sum += query(hm, keys, howmanyqueries);
            cycles_end = RDTSC_FINAL();
            querycycles += (cycles_end - cycles_start) * 1.0 / howmanyqueries;
            double pk, pkerr;
            query_avg_probed_keys(hm, keys, &pk, &pkerr);
            max_avg_probes = std::max<double>(pk, max_avg_probes);
            double mk = query_max_probed_keys(hm, keys);
            probesperquery += pk;
            probesperquerystderr += pkerr;
            maxprobesperquery += mk;
        }
        std::cout << "     " << setw(10) << querycycles / repeat
                  << " avg cycles ";
        std::cout << "     " << setw(10) << probesperquery / repeat
                  << " avg probes ";
        std::cout << "     " << setw(10) << probesperquerystderr / repeat
                  << " avg std. error ";
        std::cout << "     " << setw(10) << maxprobesperquery / repeat
                  << " avg max probes ";
        std::cout << "     " << setw(10) << max_avg_probes
                  << " max avg probes ";
        std::cout << " ignore me: " << sum;
        std::cout << std::endl;
    }
    static inline void Stop() {}
};

void demorandom(const uint64_t howmany, const float loadfactor,
                const float repeat, const size_t howmanyqueries) {
    srand(0);
    std::vector<uint64_t>  keys;
    for(uint64_t i = 1; i <= howmany; ++i) {
      uint64_t newkey = get64rand();
      while(newkey == EMPTY) newkey = get64rand();
      keys.push_back(newkey);
    }
    std::cout << "populating a hash table with " << howmany << " random 64-bit keys and then retrieving them. " << std::endl;
    std::cout << "load factor = " << loadfactor << std::endl;
    std::cout << "number of consecutive queries on same hash table = " << howmanyqueries << std::endl;

    std::cout << "We repeat with " << repeat << " different hash functions, using the same keys." << std::endl;

    ForEachT<Zobrist64Pack, MultiplyShift64Pack, WZobrist64Pack, ClLinear64Pack, ClQuadratic64Pack, ClCubic64Pack, ClQuartic64Pack,
             ThorupZhangCWCubic64Pack>::template Go<BasicWorker>(keys,
                                                                 loadfactor,
                                                                 repeat, howmanyqueries);

    std::cout << std::endl;

}

void demofixed(const uint64_t howmany, const float loadfactor, const float repeat, const size_t howmanyqueries) {
    srand(0);
    std::vector<uint64_t>  keys;
    for(uint64_t i = 1; i <= howmany; ++i) {
        keys.push_back(i + UINT64_C(0xFFFFFFFFF));
    }
    std::random_device rd;
    std::mt19937 g(rd());
    std::shuffle(keys.begin(), keys.end(),g);

    std::cout << "populating a hash table with " << howmany << " sequential and shuffled 64-bit keys and then retrieving them. " << std::endl;
    std::cout << "load factor = " << loadfactor << std::endl;
    std::cout << "number of consecutive queries on same hash table = " << howmanyqueries << std::endl;

    std::cout << "We repeat with " << repeat << " different hash functions, using the same keys." << std::endl;

    ForEachT<Cyclic64Pack, Zobrist64Pack, WZobrist64Pack, MultiplyShift64Pack, ClLinear64Pack, ClQuadratic64Pack, ClCubic64Pack, ClQuartic64Pack,
             ThorupZhangCWCubic64Pack>::template Go<BasicWorker>(keys,
                                                                 loadfactor,
                                                                 repeat,howmanyqueries);

    std::cout << std::endl;

}

int main() {
    const float loadfactor = 0.9;
    const float repeat = 1000;
    const size_t howmanyqueries = 10;

    demofixed(1000, loadfactor, repeat, howmanyqueries);
    demofixed(2000, loadfactor, repeat, howmanyqueries);
    demofixed(64000, loadfactor, repeat, howmanyqueries);
    demofixed(120000, loadfactor, repeat, howmanyqueries);

    std::cout << "=======" << std::endl;

    demorandom(1000, loadfactor, repeat, howmanyqueries);
    demorandom(2000, loadfactor, repeat, howmanyqueries);
    demorandom(64000, loadfactor, repeat, howmanyqueries);
    demorandom(120000, loadfactor, repeat, howmanyqueries);

}
<commit_msg>Uniformizing the tests<commit_after>#include <cmath>
#include <cstring>
#include <cstdio>
#include <cassert>
#include <cstdlib>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <limits>
#include <random>
#include <vector>

#include <sys/resource.h>

#include "hashpack.h"
#include "hashmap.h"
#include "timers.hpp"

using namespace std;
using namespace rigtorp;

template <typename ht>
void populate(ht & h, vector<uint64_t> & keys) {
    for(size_t i = 0; i < keys.size(); ++i) {
        h.emplace(keys[i], i);
    }
}

template <typename ht>
size_t  query(ht & h, vector<uint64_t> & keys, size_t howmany) {
    size_t sum = 0;
    for(size_t i = 0; i < howmany; ++i) {
        auto it = h.find(keys[i]);
        if(it != h.end()) sum+= it->second;
    }
    return sum;
}

template <typename ht>
void query_avg_probed_keys(ht & h, vector<uint64_t> & keys, double * average, double * stderrprob) {
    double sum = 0;
    double sumsquare = 0;
    for(size_t i = 0; i < keys.size(); ++i) {
        double probed = h.probed_keys(keys[i]);
        sum += probed;
        sumsquare += probed * probed;
    }
    *average = sum  / keys.size();
    *stderrprob = sqrt(sumsquare /  keys.size() - *average * *average );
}

template <typename ht>
size_t query_max_probed_keys(ht & h, vector<uint64_t> & keys) {
    size_t mp = 0;
    for(size_t i = 0; i < keys.size(); ++i) {
        size_t tp = h.probed_keys(keys[i]);
        if(tp > mp) mp = tp;
    }
    return mp;
}
const uint64_t EMPTY = 0xFFFFFFFFFFFFFFFF;

struct BasicWorker {
    template <typename Pack>
    static inline void Go(std::vector<uint64_t> &keys, const float loadfactor,
                          const int repeat, size_t howmanyqueries) {
        double querycycles = 0;
        double probesperquery = 0;
        double probesperquerystderr = 0;
        double maxprobesperquery = 0;

        size_t howmany = keys.size();
        assert(howmanyqueries <= howmany);
        std::cout << "testing " << setw(20) << string(Pack::NAME) << " ";
        std::cout.flush();
        uint64_t sum = 0;
        vector<HashMap<uint64_t, uint32_t, Pack>> collection;
        uint64_t cycles_start, cycles_end;
        for (int r = 0; r < repeat; ++r) {
            HashMap<uint64_t, uint32_t, Pack> hm(16, EMPTY, loadfactor);
            cycles_start = RDTSC_START();
            populate(hm, keys);
            cycles_end = RDTSC_FINAL();
            collection.push_back(hm);
        }
        double max_avg_probes = 0;
        for (int r = 0; r < repeat; ++r) {
            HashMap<uint64_t, uint32_t, Pack> &hm = collection[r];
            cycles_start = RDTSC_START();
            sum += query(hm, keys, howmanyqueries);
            cycles_end = RDTSC_FINAL();
            querycycles += (cycles_end - cycles_start) * 1.0 / howmanyqueries;
            double pk, pkerr;
            query_avg_probed_keys(hm, keys, &pk, &pkerr);
            max_avg_probes = std::max<double>(pk, max_avg_probes);
            double mk = query_max_probed_keys(hm, keys);
            probesperquery += pk;
            probesperquerystderr += pkerr;
            maxprobesperquery += mk;
        }
        std::cout << "     " << setw(10) << querycycles / repeat
                  << " avg cycles ";
        std::cout << "     " << setw(10) << probesperquery / repeat
                  << " avg probes ";
        std::cout << "     " << setw(10) << probesperquerystderr / repeat
                  << " avg std. error ";
        std::cout << "     " << setw(10) << maxprobesperquery / repeat
                  << " avg max probes ";
        std::cout << "     " << setw(10) << max_avg_probes
                  << " max avg probes ";
        std::cout << " ignore me: " << sum;
        std::cout << std::endl;
    }
    static inline void Stop() {}
};

void demorandom(const uint64_t howmany, const float loadfactor,
                const float repeat, const size_t howmanyqueries) {
    srand(0);
    std::vector<uint64_t>  keys;
    for(uint64_t i = 1; i <= howmany; ++i) {
      uint64_t newkey = get64rand();
      while(newkey == EMPTY) newkey = get64rand();
      keys.push_back(newkey);
    }
    std::cout << "populating a hash table with " << howmany << " random 64-bit keys and then retrieving them. " << std::endl;
    std::cout << "load factor = " << loadfactor << std::endl;
    std::cout << "number of consecutive queries on same hash table = " << howmanyqueries << std::endl;

    std::cout << "We repeat with " << repeat << " different hash functions, using the same keys." << std::endl;

    ForEachT<Cyclic64Pack, Zobrist64Pack, WZobrist64Pack, MultiplyShift64Pack, WZobrist64Pack, ClLinear64Pack, ClQuadratic64Pack, ClCubic64Pack, ClQuartic64Pack,
             ThorupZhangCWCubic64Pack>::template Go<BasicWorker>(keys,
                                                                 loadfactor,
                                                                 repeat, howmanyqueries);

    std::cout << std::endl;

}

void demofixed(const uint64_t howmany, const float loadfactor, const float repeat, const size_t howmanyqueries) {
    srand(0);
    std::vector<uint64_t>  keys;
    for(uint64_t i = 1; i <= howmany; ++i) {
        keys.push_back(i + UINT64_C(0xFFFFFFFFF));
    }
    std::random_device rd;
    std::mt19937 g(rd());
    std::shuffle(keys.begin(), keys.end(),g);

    std::cout << "populating a hash table with " << howmany << " sequential and shuffled 64-bit keys and then retrieving them. " << std::endl;
    std::cout << "load factor = " << loadfactor << std::endl;
    std::cout << "number of consecutive queries on same hash table = " << howmanyqueries << std::endl;

    std::cout << "We repeat with " << repeat << " different hash functions, using the same keys." << std::endl;

    ForEachT<Cyclic64Pack, Zobrist64Pack, WZobrist64Pack, MultiplyShift64Pack, ClLinear64Pack, ClQuadratic64Pack, ClCubic64Pack, ClQuartic64Pack,
             ThorupZhangCWCubic64Pack>::template Go<BasicWorker>(keys,
                                                                 loadfactor,
                                                                 repeat,howmanyqueries);

    std::cout << std::endl;

}

int main() {
    const float loadfactor = 0.9;
    const float repeat = 1000;
    const size_t howmanyqueries = 10;

    demofixed(1000, loadfactor, repeat, howmanyqueries);
    demofixed(2000, loadfactor, repeat, howmanyqueries);
    demofixed(64000, loadfactor, repeat, howmanyqueries);
    demofixed(120000, loadfactor, repeat, howmanyqueries);

    std::cout << "=======" << std::endl;

    demorandom(1000, loadfactor, repeat, howmanyqueries);
    demorandom(2000, loadfactor, repeat, howmanyqueries);
    demorandom(64000, loadfactor, repeat, howmanyqueries);
    demorandom(120000, loadfactor, repeat, howmanyqueries);

}
<|endoftext|>


<commit_before>//============================================================================
// vSMC/include/vsmc/rng/u01.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2015, Yan Zhou
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//============================================================================

#ifndef VSMC_RNG_U01_HPP
#define VSMC_RNG_U01_HPP

#include <vsmc/rng/internal/common.hpp>
#include <vsmc/rng/u01.h>

#define VSMC_RUNTIME_ASSERT_RNG_U01_U01_SEQUENCE(Method) \
    VSMC_RUNTIME_ASSERT(                                                     \
            (n >= 0 && n < N_ && (n == n_ || n == n_ + 1 || n_ == N_)),      \
            ("**U01Sequence"#Method"::operator[]** INVALID INDEX"))

#define VSMC_DEFINE_RNG_U01(FPType, Left, Right, left, right, UBits, FBits) \
template <> struct U01<Left, Right, uint##UBits##_t, FPType>                 \
{                                                                            \
    FPType operator() (uint##UBits##_t u) const                              \
    {return ::u01_##left##_##right##_##UBits##_##FBits(u);}                  \
                                                                             \
    static FPType uint2fp (uint##UBits##_t u)                                \
    {return ::u01_##left##_##right##_##UBits##_##FBits(u);}                  \
};

namespace vsmc {

/// \brief Parameter type for open interval
/// \ingroup U01
struct Open {};

/// \brief Parameter type for closed interval
/// \ingroup U01
struct Closed {};

template <typename, typename, typename, typename> struct U01;

/// \brief Converting 32-bits unsigned to single precision uniform \f$[0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Closed, Closed, closed, closed, 32, 24)

/// \brief Converting 32-bits unsigned to single precision uniform \f$[0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Closed, Open, closed, open, 32, 24)

/// \brief Converting 32-bits unsigned to single precision uniform \f$(0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Open, Closed, open, closed, 32, 24)

/// \brief Converting 32-bits unsigned to single precision uniform \f$(0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Open, Open, open, open, 32, 24)

/// \brief Converting 32-bits unsigned to double precision uniform \f$[0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Closed, Closed, closed, closed, 32, 53)

/// \brief Converting 32-bits unsigned to double precision uniform \f$[0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Closed, Open, closed, open, 32, 53)

/// \brief Converting 32-bits unsigned to double precision uniform \f$(0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Open, Closed, open, closed, 32, 53)

/// \brief Converting 32-bits unsigned to double precision uniform \f$(0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Open, Open, open, open, 32, 53)

/// \brief Converting 64-bits unsigned to single precision uniform \f$[0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Closed, Closed, closed, closed, 64, 24)

/// \brief Converting 64-bits unsigned to single precision uniform \f$[0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Closed, Open, closed, open, 64, 24)

/// \brief Converting 64-bits unsigned to single precision uniform \f$(0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Open, Closed, open, closed, 64, 24)

/// \brief Converting 64-bits unsigned to single precision uniform \f$(0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Open, Open, open, open, 64, 24)

/// \brief Converting 64-bits unsigned to double precision uniform \f$[0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Closed, Closed, closed, closed, 64, 53)

/// \brief Converting 64-bits unsigned to double precision uniform \f$[0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Closed, Open, closed, open, 64, 53)

/// \brief Converting 64-bits unsigned to double precision uniform \f$(0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Open, Closed, open, closed, 64, 53)

/// \brief Converting 64-bits unsigned to double precision uniform \f$(0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Open, Open, open, open, 64, 53)

/// \brief Generate a fixed length sequence of uniform \f$[0,1)\f$ random
/// variates by sorting.
///
/// \details
/// This is primarily used in resampling algorithms within the library but can
/// be used for other purposes. It deals with the usage case similar to the
/// following,
/// ~~~{.cpp}
/// const std::size_t N = 1000;
/// std::mt19937 rng;
/// std::uniform_real_distribution<double> runif(0, 1);
/// std::vector<double> u01(N);
/// for (std::size_t i = 0; i != N; ++i)
///     u01[i] = runif(rng);
/// std::sort(u01.begin(), u01.end());
/// for (std::size_t i = 0; i != N; ++i)
///     do_something_with_u01(u01[i]);
/// ~~~
/// In the above example, one want N uniform random variates, and having them
/// sorted. The sorted sequence is accessed sequentially. There are two
/// undesired effects. First the program has a runtime cost \f$O(N\log N)\f$.
/// Second, it has a memory cost \f$O(N)\f$. The presented class can be used in
/// place of the temporary vector in the following fashion.
/// ~~~{.cpp}
/// const std::size_t N = 1000;
/// std::mt19937 rng;
/// U01SequenceSorted<std::mt19937> u01(N, rng);
/// for (std::size_t i = 0; i != N; ++i)
///     do_something_with_u01(u01[i]);
/// ~~~
/// The above program will has a runtime cost \f$O(N)\f$ and a memory cost
/// \f$O(1)\f$. However, the overloaded `operator[]` has a few restrictions.
/// Most importantly, it is a forward one-pass operation. More specifically,
/// let `n` be the calling argument and `nlast` be the calling argument of the
/// last time it is called.
/// - `n` can only be either `0`, `nlast`, or `nlast + 1`
/// - `n` can be at most `N - 1`.
template <typename RngType>
class U01SequenceSorted
{
    public :

    U01SequenceSorted (std::size_t N, RngType &rng) :
        N_(N), n_(N), u_(0), lmax_(0), rng_(rng), runif_(0, 1) {}

    /// \brief Generate the n-th random variates
    ///
    double operator[] (std::size_t n)
    {
        using std::exp;
        using std::log;

        VSMC_RUNTIME_ASSERT_RNG_U01_U01_SEQUENCE(Sorted)

        if (n == n_)
            return u_;

        lmax_ += log(1 - runif_(rng_)) / (N_ - n);
        n_ = n;
        u_ = 1 - exp(lmax_);

        return u_;
    }

    double operator() (std::size_t n) {return operator[](n);}

    private :

    std::size_t N_;
    std::size_t n_;
    double u_;
    double lmax_;
    RngType &rng_;
    cxx11::uniform_real_distribution<double> runif_;
}; // U01SequenceSorted

/// \brief Generate a fixed length sequence of uniform \f$[0,1)\f$ random
/// variates by stratified sampling.
///
/// \details
/// This is similar to U01SequenceSorted except that, instead of generating the
/// sequence as if by sorting. It is done by generating
/// \f$u_i = U_i / N + (i - 1) / N\f$ where \f$U_i\f$ is uniform \f$[0,1)\f$
/// random variates.
template <typename RngType>
class U01SequenceStratified
{
    public :

    U01SequenceStratified (std::size_t N, RngType &rng) :
        N_(N), n_(N), u_(0), delta_(1.0 / N), rng_(rng), runif_(0, 1) {}

    double operator[] (std::size_t n)
    {
        VSMC_RUNTIME_ASSERT_RNG_U01_U01_SEQUENCE(Stratified)

        if (n == n_)
            return u_;

        n_ = n;
        u_ = runif_(rng_) * delta_ + n * delta_;

        return u_;
    }

    double operator() (std::size_t n) {return operator[](n);}

    private :

    std::size_t N_;
    std::size_t n_;
    double u_;
    double delta_;
    RngType &rng_;
    cxx11::uniform_real_distribution<double> runif_;
}; // class U01SequenceStratified

/// \brief Generate a fixed length sequence of uniform \f$[0,1)\f$ random
/// variates by systematic sampling.
///
/// \details
/// This is similar to U01SequenceSorted except that, instead of generating the
/// sequence as if by sorting. It is done by generating
/// \f$u_i = U / N + (i - 1) / N\f$ where \f$U\f$ is uniform \f$[0,1)\f$
/// random variates and it is generated only once for all \f$i\f$.
template <typename RngType>
class U01SequenceSystematic
{
    public :

    U01SequenceSystematic (std::size_t N, RngType &rng) :
        N_(N), n_(N), u_(0), u0_(0), delta_(1.0 / N)
    {
        cxx11::uniform_real_distribution<double> runif(0, 1);
        u0_ = runif(rng) * delta_;
    }

    double operator[] (std::size_t n)
    {
        VSMC_RUNTIME_ASSERT_RNG_U01_U01_SEQUENCE(Systematic)

        if (n == n_)
            return u_;

        n_ = n;
        u_ = u0_ + n * delta_;

        return u_;
    }

    double operator() (std::size_t n) {return operator[](n);}

    private :

    std::size_t N_;
    std::size_t n_;
    double u_;
    double u0_;
    double delta_;
}; // class U01SequenceSystematic

} // namespace vsmc

#endif // VSMC_RNG_U01_HPP
<commit_msg>remove comparison of unsigned to zero<commit_after>//============================================================================
// vSMC/include/vsmc/rng/u01.hpp
//----------------------------------------------------------------------------
//                         vSMC: Scalable Monte Carlo
//----------------------------------------------------------------------------
// Copyright (c) 2013-2015, Yan Zhou
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
//
//   Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//============================================================================

#ifndef VSMC_RNG_U01_HPP
#define VSMC_RNG_U01_HPP

#include <vsmc/rng/internal/common.hpp>
#include <vsmc/rng/u01.h>

#define VSMC_RUNTIME_ASSERT_RNG_U01_U01_SEQUENCE(Method) \
    VSMC_RUNTIME_ASSERT((n < N_ && (n == n_ || n == n_ + 1 || n_ == N_)),    \
            ("**U01Sequence"#Method"::operator[]** INVALID INDEX"))

#define VSMC_DEFINE_RNG_U01(FPType, Left, Right, left, right, UBits, FBits) \
template <> struct U01<Left, Right, uint##UBits##_t, FPType>                 \
{                                                                            \
    FPType operator() (uint##UBits##_t u) const                              \
    {return ::u01_##left##_##right##_##UBits##_##FBits(u);}                  \
                                                                             \
    static FPType uint2fp (uint##UBits##_t u)                                \
    {return ::u01_##left##_##right##_##UBits##_##FBits(u);}                  \
};

namespace vsmc {

/// \brief Parameter type for open interval
/// \ingroup U01
struct Open {};

/// \brief Parameter type for closed interval
/// \ingroup U01
struct Closed {};

template <typename, typename, typename, typename> struct U01;

/// \brief Converting 32-bits unsigned to single precision uniform \f$[0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Closed, Closed, closed, closed, 32, 24)

/// \brief Converting 32-bits unsigned to single precision uniform \f$[0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Closed, Open, closed, open, 32, 24)

/// \brief Converting 32-bits unsigned to single precision uniform \f$(0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Open, Closed, open, closed, 32, 24)

/// \brief Converting 32-bits unsigned to single precision uniform \f$(0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Open, Open, open, open, 32, 24)

/// \brief Converting 32-bits unsigned to double precision uniform \f$[0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Closed, Closed, closed, closed, 32, 53)

/// \brief Converting 32-bits unsigned to double precision uniform \f$[0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Closed, Open, closed, open, 32, 53)

/// \brief Converting 32-bits unsigned to double precision uniform \f$(0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Open, Closed, open, closed, 32, 53)

/// \brief Converting 32-bits unsigned to double precision uniform \f$(0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Open, Open, open, open, 32, 53)

/// \brief Converting 64-bits unsigned to single precision uniform \f$[0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Closed, Closed, closed, closed, 64, 24)

/// \brief Converting 64-bits unsigned to single precision uniform \f$[0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Closed, Open, closed, open, 64, 24)

/// \brief Converting 64-bits unsigned to single precision uniform \f$(0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Open, Closed, open, closed, 64, 24)

/// \brief Converting 64-bits unsigned to single precision uniform \f$(0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(float, Open, Open, open, open, 64, 24)

/// \brief Converting 64-bits unsigned to double precision uniform \f$[0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Closed, Closed, closed, closed, 64, 53)

/// \brief Converting 64-bits unsigned to double precision uniform \f$[0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Closed, Open, closed, open, 64, 53)

/// \brief Converting 64-bits unsigned to double precision uniform \f$(0,1]\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Open, Closed, open, closed, 64, 53)

/// \brief Converting 64-bits unsigned to double precision uniform \f$(0,1)\f$
/// \ingroup U01
VSMC_DEFINE_RNG_U01(double, Open, Open, open, open, 64, 53)

/// \brief Generate a fixed length sequence of uniform \f$[0,1)\f$ random
/// variates by sorting.
///
/// \details
/// This is primarily used in resampling algorithms within the library but can
/// be used for other purposes. It deals with the usage case similar to the
/// following,
/// ~~~{.cpp}
/// const std::size_t N = 1000;
/// std::mt19937 rng;
/// std::uniform_real_distribution<double> runif(0, 1);
/// std::vector<double> u01(N);
/// for (std::size_t i = 0; i != N; ++i)
///     u01[i] = runif(rng);
/// std::sort(u01.begin(), u01.end());
/// for (std::size_t i = 0; i != N; ++i)
///     do_something_with_u01(u01[i]);
/// ~~~
/// In the above example, one want N uniform random variates, and having them
/// sorted. The sorted sequence is accessed sequentially. There are two
/// undesired effects. First the program has a runtime cost \f$O(N\log N)\f$.
/// Second, it has a memory cost \f$O(N)\f$. The presented class can be used in
/// place of the temporary vector in the following fashion.
/// ~~~{.cpp}
/// const std::size_t N = 1000;
/// std::mt19937 rng;
/// U01SequenceSorted<std::mt19937> u01(N, rng);
/// for (std::size_t i = 0; i != N; ++i)
///     do_something_with_u01(u01[i]);
/// ~~~
/// The above program will has a runtime cost \f$O(N)\f$ and a memory cost
/// \f$O(1)\f$. However, the overloaded `operator[]` has a few restrictions.
/// Most importantly, it is a forward one-pass operation. More specifically,
/// let `n` be the calling argument and `nlast` be the calling argument of the
/// last time it is called.
/// - `n` can only be either `0`, `nlast`, or `nlast + 1`
/// - `n` can be at most `N - 1`.
template <typename RngType>
class U01SequenceSorted
{
    public :

    U01SequenceSorted (std::size_t N, RngType &rng) :
        N_(N), n_(N), u_(0), lmax_(0), rng_(rng), runif_(0, 1) {}

    /// \brief Generate the n-th random variates
    ///
    double operator[] (std::size_t n)
    {
        using std::exp;
        using std::log;

        VSMC_RUNTIME_ASSERT_RNG_U01_U01_SEQUENCE(Sorted)

        if (n == n_)
            return u_;

        lmax_ += log(1 - runif_(rng_)) / (N_ - n);
        n_ = n;
        u_ = 1 - exp(lmax_);

        return u_;
    }

    double operator() (std::size_t n) {return operator[](n);}

    private :

    std::size_t N_;
    std::size_t n_;
    double u_;
    double lmax_;
    RngType &rng_;
    cxx11::uniform_real_distribution<double> runif_;
}; // U01SequenceSorted

/// \brief Generate a fixed length sequence of uniform \f$[0,1)\f$ random
/// variates by stratified sampling.
///
/// \details
/// This is similar to U01SequenceSorted except that, instead of generating the
/// sequence as if by sorting. It is done by generating
/// \f$u_i = U_i / N + (i - 1) / N\f$ where \f$U_i\f$ is uniform \f$[0,1)\f$
/// random variates.
template <typename RngType>
class U01SequenceStratified
{
    public :

    U01SequenceStratified (std::size_t N, RngType &rng) :
        N_(N), n_(N), u_(0), delta_(1.0 / N), rng_(rng), runif_(0, 1) {}

    double operator[] (std::size_t n)
    {
        VSMC_RUNTIME_ASSERT_RNG_U01_U01_SEQUENCE(Stratified)

        if (n == n_)
            return u_;

        n_ = n;
        u_ = runif_(rng_) * delta_ + n * delta_;

        return u_;
    }

    double operator() (std::size_t n) {return operator[](n);}

    private :

    std::size_t N_;
    std::size_t n_;
    double u_;
    double delta_;
    RngType &rng_;
    cxx11::uniform_real_distribution<double> runif_;
}; // class U01SequenceStratified

/// \brief Generate a fixed length sequence of uniform \f$[0,1)\f$ random
/// variates by systematic sampling.
///
/// \details
/// This is similar to U01SequenceSorted except that, instead of generating the
/// sequence as if by sorting. It is done by generating
/// \f$u_i = U / N + (i - 1) / N\f$ where \f$U\f$ is uniform \f$[0,1)\f$
/// random variates and it is generated only once for all \f$i\f$.
template <typename RngType>
class U01SequenceSystematic
{
    public :

    U01SequenceSystematic (std::size_t N, RngType &rng) :
        N_(N), n_(N), u_(0), u0_(0), delta_(1.0 / N)
    {
        cxx11::uniform_real_distribution<double> runif(0, 1);
        u0_ = runif(rng) * delta_;
    }

    double operator[] (std::size_t n)
    {
        VSMC_RUNTIME_ASSERT_RNG_U01_U01_SEQUENCE(Systematic)

        if (n == n_)
            return u_;

        n_ = n;
        u_ = u0_ + n * delta_;

        return u_;
    }

    double operator() (std::size_t n) {return operator[](n);}

    private :

    std::size_t N_;
    std::size_t n_;
    double u_;
    double u0_;
    double delta_;
}; // class U01SequenceSystematic

} // namespace vsmc

#endif // VSMC_RNG_U01_HPP
<|endoftext|>


<commit_before>#pragma once

#include "cell_id.hpp"

#include "../std/queue.hpp"
#include "../std/vector.hpp"

// TODO: Move neccessary functions to geometry/covering_utils.hpp and delete this file.

template <typename BoundsT, typename CellIdT>
inline void SplitRectCell(CellIdT id,
                          CoordT minX, CoordT minY,
                          CoordT maxX, CoordT maxY,
                          vector<CellIdT> & result)
{
  for (size_t i = 0; i < 4; ++i)
  {
    CellIdT child = id.Child(i);
    CoordT minCellX, minCellY, maxCellX, maxCellY;
    CellIdConverter<BoundsT, CellIdT>::GetCellBounds(child, minCellX, minCellY, maxCellX, maxCellY);
    if (!((maxX < minCellX) || (minX > maxCellX) || (maxY < minCellY) || (minY > maxCellY)))
      result.push_back(child);
  }
}

template <typename BoundsT, typename CellIdT>
inline void CoverRect(CoordT minX, CoordT minY,
                      CoordT maxX, CoordT maxY,
                      size_t cells_count, int maxDepth,
                      vector<CellIdT> & cells)
{
  ASSERT_LESS(minX, maxX, ());
  ASSERT_LESS(minY, maxY, ());

  if (minX < BoundsT::minX) minX = BoundsT::minX;
  if (minY < BoundsT::minY) minY = BoundsT::minY;
  if (maxX > BoundsT::maxX) maxX = BoundsT::maxX;
  if (maxY > BoundsT::maxY) maxY = BoundsT::maxY;

  if (minX >= maxX || minY >= maxY)
    return;

  CellIdT commonCell =
      CellIdConverter<BoundsT, CellIdT>::Cover2PointsWithCell(minX, minY, maxX, maxY);

  vector<CellIdT> result;

  queue<CellIdT> cellQueue;
  cellQueue.push(commonCell);

  while (!cellQueue.empty() && cellQueue.size() + result.size() < cells_count)
  {
    CellIdT id = cellQueue.front();
    cellQueue.pop();

    if (id.Level() == maxDepth - 1)
    {
      result.push_back(id);
      break;
    }

    vector<CellIdT> children;
    SplitRectCell<BoundsT>(id, minX, minY, maxX, maxY, children);

    // Children shouldn't be empty, but if it is, ignore this cellid in release.
    ASSERT(!children.empty(), (id, minX, minY, maxX, maxY));
    if (children.empty())
    {
      result.push_back(id);
      continue;
    }

    if (cellQueue.size() + result.size() + children.size() <= cells_count)
    {
      for (size_t i = 0; i < children.size(); ++i)
        cellQueue.push(children[i]);
    }
    else
      result.push_back(id);
  }

  for (; !cellQueue.empty(); cellQueue.pop())
    result.push_back(cellQueue.front());

  for (size_t i = 0; i < result.size(); ++i)
  {
    CellIdT id = result[i];
    while (id.Level() < maxDepth - 1)
    {
      vector<CellIdT> children;
      SplitRectCell<BoundsT>(id, minX, minY, maxX, maxY, children);
      if (children.size() == 1)
        id = children[0];
      else
        break;
    }
    result[i] = id;
  }

  ASSERT_LESS_OR_EQUAL(result.size(), cells_count, (minX, minY, maxX, maxY));
  cells.insert(cells.end(), result.begin(), result.end());
}
<commit_msg>Fix max rect covering depth.<commit_after>#pragma once

#include "cell_id.hpp"

#include "../std/queue.hpp"
#include "../std/vector.hpp"

// TODO: Move neccessary functions to geometry/covering_utils.hpp and delete this file.

template <typename BoundsT, typename CellIdT>
inline void SplitRectCell(CellIdT id,
                          CoordT minX, CoordT minY,
                          CoordT maxX, CoordT maxY,
                          vector<CellIdT> & result)
{
  for (size_t i = 0; i < 4; ++i)
  {
    CellIdT child = id.Child(i);
    CoordT minCellX, minCellY, maxCellX, maxCellY;
    CellIdConverter<BoundsT, CellIdT>::GetCellBounds(child, minCellX, minCellY, maxCellX, maxCellY);
    if (!((maxX < minCellX) || (minX > maxCellX) || (maxY < minCellY) || (minY > maxCellY)))
      result.push_back(child);
  }
}

template <typename BoundsT, typename CellIdT>
inline void CoverRect(CoordT minX, CoordT minY,
                      CoordT maxX, CoordT maxY,
                      size_t cells_count, int maxDepth,
                      vector<CellIdT> & cells)
{
  ASSERT_LESS(minX, maxX, ());
  ASSERT_LESS(minY, maxY, ());

  if (minX < BoundsT::minX) minX = BoundsT::minX;
  if (minY < BoundsT::minY) minY = BoundsT::minY;
  if (maxX > BoundsT::maxX) maxX = BoundsT::maxX;
  if (maxY > BoundsT::maxY) maxY = BoundsT::maxY;

  if (minX >= maxX || minY >= maxY)
    return;

  CellIdT commonCell =
      CellIdConverter<BoundsT, CellIdT>::Cover2PointsWithCell(minX, minY, maxX, maxY);

  vector<CellIdT> result;

  queue<CellIdT> cellQueue;
  cellQueue.push(commonCell);

  maxDepth -= 1;

  while (!cellQueue.empty() && cellQueue.size() + result.size() < cells_count)
  {
    CellIdT id = cellQueue.front();
    cellQueue.pop();

    while (id.Level() > maxDepth)
      id = id.Parent();

    if (id.Level() == maxDepth)
    {
      result.push_back(id);
      break;
    }

    vector<CellIdT> children;
    SplitRectCell<BoundsT>(id, minX, minY, maxX, maxY, children);

    // Children shouldn't be empty, but if it is, ignore this cellid in release.
    ASSERT(!children.empty(), (id, minX, minY, maxX, maxY));
    if (children.empty())
    {
      result.push_back(id);
      continue;
    }

    if (cellQueue.size() + result.size() + children.size() <= cells_count)
    {
      for (size_t i = 0; i < children.size(); ++i)
        cellQueue.push(children[i]);
    }
    else
      result.push_back(id);
  }

  for (; !cellQueue.empty(); cellQueue.pop())
    result.push_back(cellQueue.front());

  for (size_t i = 0; i < result.size(); ++i)
  {
    CellIdT id = result[i];
    while (id.Level() < maxDepth)
    {
      vector<CellIdT> children;
      SplitRectCell<BoundsT>(id, minX, minY, maxX, maxY, children);
      if (children.size() == 1)
        id = children[0];
      else
        break;
    }
    result[i] = id;
  }

  ASSERT_LESS_OR_EQUAL(result.size(), cells_count, (minX, minY, maxX, maxY));
  cells.insert(cells.end(), result.begin(), result.end());
}
<|endoftext|>


<commit_before>#pragma once
#include <higanbana/graphics/GraphicsCore.hpp>
#include <higanbana/core/filesystem/filesystem.hpp>
#include <higanbana/core/platform/Window.hpp>
#include <higanbana/core/datastructures/proxy.hpp>
#include <higanbana/core/system/time.hpp>
#include <higanbana/graphics/helpers/pingpongTexture.hpp>
#include <higanbana/core/system/FreelistAllocator.hpp>
#include <higanbana/core/system/LBS.hpp>
#include "renderer/imgui.hpp"
#include "renderer/world_renderer.hpp"
#include "renderer/mesh_test.hpp"
#include "renderer/tsaa.hpp"
#include "renderer/tonemapper.hpp"
#include "renderer/blitter.hpp"
#include "renderer/cubes.hpp"
#include "renderer/meshes.hpp"
#include "renderer/textures.hpp"
#include "renderer/materials.hpp"
#include "renderer/generate_image.hpp"
#include "renderer/particles.hpp"
#include "renderer/viewport.hpp"
#include "world/visual_data_structures.hpp"

namespace app
{
struct RendererOptions
{
  bool submitExperimental = false;
  bool submitSingleThread = false;
  bool submitLBS = false;
  bool particles = false;
  bool particlesSimulate = true;
  bool allowMeshShaders = false;
  bool allowRaytracing = false;
  bool unbalancedCubes = false;
  bool renderImGui = true;
  void drawImGuiOptions()
  {
    ImGui::Checkbox("Submit with experimental mt", &submitExperimental);
    ImGui::Checkbox("Submit Singlethread", &submitSingleThread);
    ImGui::Checkbox("Submit using LBS", &submitLBS);
    ImGui::Checkbox("Particles", &particles);
    ImGui::Checkbox("Simulate", &particlesSimulate);
    ImGui::Checkbox("Allow Mesh Shaders", &allowMeshShaders);
    ImGui::Checkbox("Allow Raytracing", &allowRaytracing);
    ImGui::Checkbox("Unbalanced cube drawlists", &unbalancedCubes);
  }
};
struct ViewportOptions
{
  bool visible = false;
  int gpuToUse = 0;
  bool useMeshShaders = false;
  bool useRaytracing = false;
  bool syncResolutionToSwapchain = false;
  bool jitterEnabled = true;
  bool particlesDraw = true;
  bool tsaa = true;
  bool tsaaDebug = false;
  bool debugTextures = false;
  float resolutionScale = 1.f;
  bool writeStraightToBackbuffer = false;

  void drawImGuiOptions(higanbana::vector<higanbana::GpuInfo>& gpus)
  {
    if (gpus.size() > 1)
      ImGui::SliderInt("GPU Device index: ", &gpuToUse, 0, static_cast<int>(gpus.size())-1);
    ImGui::Checkbox("sync resolution to viewport size", &syncResolutionToSwapchain);
    if (!syncResolutionToSwapchain)
    {
      ImGui::DragFloat("resolution scale", &resolutionScale, 0.01f, 0.0001f, 4.f);
    }
    else
    {
      resolutionScale = 1.f;
    }
    ImGui::Checkbox("debug textures", &debugTextures);
    ImGui::Checkbox("jitter viewport", &jitterEnabled);
    ImGui::Checkbox("TSAA", &tsaa);
    if (tsaa)
    {
      ImGui::Checkbox("  enable taa debugoutput", &tsaaDebug);
    }
    ImGui::Checkbox("Draw particles", &particlesDraw);
    ImGui::Checkbox("Mesh Shaders", &useMeshShaders);
    ImGui::Checkbox("Raytracing", &useRaytracing);
  }
};

struct RenderViewportInfo {
  int viewportIndex; // gained when allocating a viewport from renderer
  int2 viewportSize;
  ViewportOptions options;
  ActiveCamera camera;
};

class Renderer
{
  higanbana::GraphicsSubsystem& graphics;
  higanbana::GpuGroup& dev;
  higanbana::GraphicsSurface surface;

  higanbana::SwapchainDescriptor scdesc;
  higanbana::Swapchain swapchain;

  // api logos
  higanbana::Texture m_logoDx12;
  higanbana::TextureSRV m_logoDx12Srv;
  higanbana::Texture m_logoVulkan;
  higanbana::TextureSRV m_logoVulkanSrv;

  // global layouts
  higanbana::ShaderArgumentsLayout m_camerasLayout;
  higanbana::Buffer cameras;
  higanbana::BufferSRV cameraSRV;
  higanbana::BufferUAV cameraUAV;
  higanbana::ShaderArguments cameraArgs;

  // meshes
  MeshSystem meshes;

  // materials
  TextureDB textures;
  MaterialDB materials;

  // renderers
  renderer::Cubes cubes;
  renderer::IMGui imgui;
  renderer::World worldRend;
  renderer::MeshTest worldMeshRend;
  // postprocess
  renderer::ShittyTSAA tsaa;
  renderer::Tonemapper tonemapper;
  renderer::Blitter blitter;
  renderer::GenerateImage genImage;
  renderer::Particles particleSimulation;

  // resources
  higanbana::vector<app::Viewport> viewports;
  higanbana::PingPongTexture proxyTex; // used for background color

  // could probably be replaced with blitter...
  higanbana::ShaderArgumentsLayout blitLayout;
  higanbana::GraphicsPipeline composite;
  higanbana::Renderpass compositeRP;

  // temp, probably shouldnt be here
  //CameraSettings m_previousCamera;

  // info
  std::optional<higanbana::SubmitTiming> m_previousInfo;
  int64_t m_acquireTimeTaken;
  void renderMeshes(higanbana::CommandGraphNode& node, higanbana::TextureRTV& backbuffer, higanbana::TextureRTV& motionVecs, higanbana::TextureDSV& depth, higanbana::ShaderArguments materials, int cameraIndex, int prevCamera, higanbana::vector<InstanceDraw>& instances);
  void renderMeshesWithMeshShaders(higanbana::CommandGraphNode& node, higanbana::TextureRTV& backbuffer, higanbana::TextureDSV& depth, higanbana::ShaderArguments materials, int cameraIndex, higanbana::vector<InstanceDraw>& instances);

  struct SceneArguments {
    higanbana::TextureRTV gbufferRTV;
    higanbana::TextureDSV depth;
    higanbana::TextureRTV motionVectors;
    higanbana::ShaderArguments materials;
    ViewportOptions options;
    int cameraIdx;
    int prevCameraIdx;
    float4x4 perspective;
    float3 cameraPos;
    int drawcalls;
    int drawsSplitInto;
  };
  void renderScene(higanbana::CommandNodeVector& tasks, higanbana::WTime& time, const RendererOptions& rendererOptions, const SceneArguments& args, higanbana::vector<InstanceDraw>& instances);
public:
  Renderer(higanbana::GraphicsSubsystem& graphics, higanbana::GpuGroup& dev);
  void initWindow(higanbana::Window& window, higanbana::GpuInfo info);
  void loadLogos(higanbana::FileSystem& fs);
  int2 windowSize();
  void ensureViewportCount(int size);
  void resizeExternal(higanbana::ResourceDescriptor& desc);
  //void render(higanbana::LBS& lbs, higanbana::WTime& time, RendererOptions options, ActiveCamera viewMat, higanbana::vector<InstanceDraw>& instances, int cubeCount, int cubeCommandLists, std::optional<higanbana::CpuImage>& heightmap);
  void renderViewports(higanbana::LBS& lbs, higanbana::WTime& time, const RendererOptions& options, higanbana::MemView<RenderViewportInfo> viewportsToRender, higanbana::vector<InstanceDraw>& instances, int cubeCount, int cubeCommandLists);
  std::optional<higanbana::SubmitTiming> timings();
  float acquireTimeTakenMs() {return float(m_acquireTimeTaken) / 1000000.f;}
  int loadMesh(MeshData& data, int buffer[5]);
  void unloadMesh(int index);
  int loadBuffer(BufferData& data);
  void unloadBuffer(int index);
  int loadTexture(TextureData& data);
  void unloadTexture(int index);
  int loadMaterial(MaterialData& data);
  void unloadMaterial(int index);
};
}<commit_msg>Implemented fun api toggle when we detect interopt with only 1 device.<commit_after>#pragma once
#include <higanbana/graphics/GraphicsCore.hpp>
#include <higanbana/core/filesystem/filesystem.hpp>
#include <higanbana/core/platform/Window.hpp>
#include <higanbana/core/datastructures/proxy.hpp>
#include <higanbana/core/system/time.hpp>
#include <higanbana/graphics/helpers/pingpongTexture.hpp>
#include <higanbana/core/system/FreelistAllocator.hpp>
#include <higanbana/core/system/LBS.hpp>
#include "renderer/imgui.hpp"
#include "renderer/world_renderer.hpp"
#include "renderer/mesh_test.hpp"
#include "renderer/tsaa.hpp"
#include "renderer/tonemapper.hpp"
#include "renderer/blitter.hpp"
#include "renderer/cubes.hpp"
#include "renderer/meshes.hpp"
#include "renderer/textures.hpp"
#include "renderer/materials.hpp"
#include "renderer/generate_image.hpp"
#include "renderer/particles.hpp"
#include "renderer/viewport.hpp"
#include "world/visual_data_structures.hpp"

namespace app
{
struct RendererOptions
{
  bool submitExperimental = false;
  bool submitSingleThread = false;
  bool submitLBS = false;
  bool particles = false;
  bool particlesSimulate = true;
  bool allowMeshShaders = false;
  bool allowRaytracing = false;
  bool unbalancedCubes = false;
  bool renderImGui = true;
  void drawImGuiOptions()
  {
    ImGui::Checkbox("Submit with experimental mt", &submitExperimental);
    ImGui::Checkbox("Submit Singlethread", &submitSingleThread);
    ImGui::Checkbox("Submit using LBS", &submitLBS);
    ImGui::Checkbox("Particles", &particles);
    ImGui::Checkbox("Simulate", &particlesSimulate);
    ImGui::Checkbox("Allow Mesh Shaders", &allowMeshShaders);
    ImGui::Checkbox("Allow Raytracing", &allowRaytracing);
    ImGui::Checkbox("Unbalanced cube drawlists", &unbalancedCubes);
  }
};
struct ViewportOptions
{
  bool visible = false;
  int gpuToUse = 0;
  bool useMeshShaders = false;
  bool useRaytracing = false;
  bool syncResolutionToSwapchain = false;
  bool jitterEnabled = true;
  bool particlesDraw = true;
  bool tsaa = true;
  bool tsaaDebug = false;
  bool debugTextures = false;
  float resolutionScale = 1.f;
  bool writeStraightToBackbuffer = false;

  void ToggleButton(const char* hidden_id, bool* v)
  {
    ImVec2 p = ImGui::GetCursorScreenPos();
    ImDrawList* draw_list = ImGui::GetWindowDrawList();

    float height = ImGui::GetFrameHeight();
    float width = height * 1.55f;
    float radius = height * 0.50f;

    ImU32 falseColor = IM_COL32(210, 50, 50, 255);
    ImU32 trueColor = IM_COL32(50, 210, 50, 255);
    ImU32 falseHovColor = IM_COL32(210, 50+20, 50+20, 255);
    ImU32 trueHovColor = IM_COL32(50+20, 210, 50+20, 255);

    if (ImGui::InvisibleButton(hidden_id, ImVec2(width, height)))
        *v = !*v;
    ImU32 col_bg;
    if (ImGui::IsItemHovered())
        col_bg = *v ? trueHovColor : falseHovColor;
    else
        col_bg = *v ? trueColor : falseColor;

    draw_list->AddRectFilled(p, ImVec2(p.x + width, p.y + height), col_bg, height * 0.5f);
    draw_list->AddCircleFilled(ImVec2(*v ? (p.x + width - radius) : (p.x + radius), p.y + radius), radius - 1.5f, IM_COL32(255, 255, 255, 255));
  }

  void drawImGuiOptions(higanbana::vector<higanbana::GpuInfo>& gpus)
  {
    bool isInteropDevice = false;
    if (gpus.size() == 2 && gpus[0].api != gpus[1].api)
      isInteropDevice = true;

    if (isInteropDevice) {
      bool current = gpus[gpuToUse].api == higanbana::GraphicsApi::DX12;
      bool before = current;
      ImGui::Text("Vulkan"); ImGui::SameLine();
      ToggleButton("##toggle", &current); ImGui::SameLine();
      ImGui::Text("DX12");
      if (current != before) {
        gpuToUse = gpuToUse == 1 ? 0 : 1;
      }
    } else if (gpus.size() > 1)
      ImGui::SliderInt("GPU Device index: ", &gpuToUse, 0, static_cast<int>(gpus.size())-1);
    ImGui::Checkbox("sync resolution to viewport size", &syncResolutionToSwapchain);
    if (!syncResolutionToSwapchain)
    {
      ImGui::DragFloat("resolution scale", &resolutionScale, 0.01f, 0.0001f, 4.f);
    }
    else
    {
      resolutionScale = 1.f;
    }
    ImGui::Checkbox("debug textures", &debugTextures);
    ImGui::Checkbox("jitter viewport", &jitterEnabled);
    ImGui::Checkbox("TSAA", &tsaa);
    if (tsaa)
    {
      ImGui::Checkbox("  enable taa debugoutput", &tsaaDebug);
    }
    ImGui::Checkbox("Draw particles", &particlesDraw);
    ImGui::Checkbox("Mesh Shaders", &useMeshShaders);
    ImGui::Checkbox("Raytracing", &useRaytracing);
  }
};

struct RenderViewportInfo {
  int viewportIndex; // gained when allocating a viewport from renderer
  int2 viewportSize;
  ViewportOptions options;
  ActiveCamera camera;
};

class Renderer
{
  higanbana::GraphicsSubsystem& graphics;
  higanbana::GpuGroup& dev;
  higanbana::GraphicsSurface surface;

  higanbana::SwapchainDescriptor scdesc;
  higanbana::Swapchain swapchain;

  // api logos
  higanbana::Texture m_logoDx12;
  higanbana::TextureSRV m_logoDx12Srv;
  higanbana::Texture m_logoVulkan;
  higanbana::TextureSRV m_logoVulkanSrv;

  // global layouts
  higanbana::ShaderArgumentsLayout m_camerasLayout;
  higanbana::Buffer cameras;
  higanbana::BufferSRV cameraSRV;
  higanbana::BufferUAV cameraUAV;
  higanbana::ShaderArguments cameraArgs;

  // meshes
  MeshSystem meshes;

  // materials
  TextureDB textures;
  MaterialDB materials;

  // renderers
  renderer::Cubes cubes;
  renderer::IMGui imgui;
  renderer::World worldRend;
  renderer::MeshTest worldMeshRend;
  // postprocess
  renderer::ShittyTSAA tsaa;
  renderer::Tonemapper tonemapper;
  renderer::Blitter blitter;
  renderer::GenerateImage genImage;
  renderer::Particles particleSimulation;

  // resources
  higanbana::vector<app::Viewport> viewports;
  higanbana::PingPongTexture proxyTex; // used for background color

  // could probably be replaced with blitter...
  higanbana::ShaderArgumentsLayout blitLayout;
  higanbana::GraphicsPipeline composite;
  higanbana::Renderpass compositeRP;

  // temp, probably shouldnt be here
  //CameraSettings m_previousCamera;

  // info
  std::optional<higanbana::SubmitTiming> m_previousInfo;
  int64_t m_acquireTimeTaken;
  void renderMeshes(higanbana::CommandGraphNode& node, higanbana::TextureRTV& backbuffer, higanbana::TextureRTV& motionVecs, higanbana::TextureDSV& depth, higanbana::ShaderArguments materials, int cameraIndex, int prevCamera, higanbana::vector<InstanceDraw>& instances);
  void renderMeshesWithMeshShaders(higanbana::CommandGraphNode& node, higanbana::TextureRTV& backbuffer, higanbana::TextureDSV& depth, higanbana::ShaderArguments materials, int cameraIndex, higanbana::vector<InstanceDraw>& instances);

  struct SceneArguments {
    higanbana::TextureRTV gbufferRTV;
    higanbana::TextureDSV depth;
    higanbana::TextureRTV motionVectors;
    higanbana::ShaderArguments materials;
    ViewportOptions options;
    int cameraIdx;
    int prevCameraIdx;
    float4x4 perspective;
    float3 cameraPos;
    int drawcalls;
    int drawsSplitInto;
  };
  void renderScene(higanbana::CommandNodeVector& tasks, higanbana::WTime& time, const RendererOptions& rendererOptions, const SceneArguments& args, higanbana::vector<InstanceDraw>& instances);
public:
  Renderer(higanbana::GraphicsSubsystem& graphics, higanbana::GpuGroup& dev);
  void initWindow(higanbana::Window& window, higanbana::GpuInfo info);
  void loadLogos(higanbana::FileSystem& fs);
  int2 windowSize();
  void ensureViewportCount(int size);
  void resizeExternal(higanbana::ResourceDescriptor& desc);
  //void render(higanbana::LBS& lbs, higanbana::WTime& time, RendererOptions options, ActiveCamera viewMat, higanbana::vector<InstanceDraw>& instances, int cubeCount, int cubeCommandLists, std::optional<higanbana::CpuImage>& heightmap);
  void renderViewports(higanbana::LBS& lbs, higanbana::WTime& time, const RendererOptions& options, higanbana::MemView<RenderViewportInfo> viewportsToRender, higanbana::vector<InstanceDraw>& instances, int cubeCount, int cubeCommandLists);
  std::optional<higanbana::SubmitTiming> timings();
  float acquireTimeTakenMs() {return float(m_acquireTimeTaken) / 1000000.f;}
  int loadMesh(MeshData& data, int buffer[5]);
  void unloadMesh(int index);
  int loadBuffer(BufferData& data);
  void unloadBuffer(int index);
  int loadTexture(TextureData& data);
  void unloadTexture(int index);
  int loadMaterial(MaterialData& data);
  void unloadMaterial(int index);
};
}<|endoftext|>