<commit_before>/*******************************************************************************
 * src/benchmark.cpp
 *
 * Copyright (C) 2017 Florian Kurpicz <florian.kurpicz@tu-dortmund.de>
 * Copyright (C) 2018 Jonas Ellert <jonas.ellert@tu-dortmund.de>
 *
 * All rights reserved. Published under the BSD-2 license in the LICENSE file.
 ******************************************************************************/

#include <tclap/CmdLine.h>
#include <vector>

#include "benchmark/algorithm.hpp"
#include "util/alphabet_util.hpp"
#include "util/file_util.hpp"
#include "util/stxxl_helper.hpp"
#include "util/memory_types.hpp"

#ifdef MALLOC_COUNT
#include "benchmark/malloc_count.h"
#endif // MALLOC_COUNT

auto filter_parallel(bool only_parallel, bool is_parallel) {
  return (!only_parallel || is_parallel);
}

auto filter_sequential(bool sequential, bool is_parallel) {
  return (!sequential || !is_parallel);
}

auto filter_wavelet_type(bool is_tree, bool no_trees, bool no_matrices) {
  return (is_tree ? !no_trees : !no_matrices);
}

static TCLAP::SwitchArg list_all_algorithms("l", "list",
    "Print the name and description of all registered algorithms", false);
static TCLAP::MultiArg<std::string> file_path_arg("f", "file",
    "Path to the text file.", false, "string");
static TCLAP::ValueArg<std::string> filter_arg("n", "name",
    "Runs all algorithms that contain the <name> in their name", false, "",
    "string");
static TCLAP::ValueArg<int32_t> word_width_arg("b", "byte",
    "Bytes per char in the input text.", false, 1, "uint8_t");
static TCLAP::ValueArg<int32_t> nr_runs_arg("r", "runs",
    "Number of repetitions of the construction algorithm.",
    false, 5, "int32_t");
static TCLAP::SwitchArg run_only_parallel_arg("p", "parallel",
    "Run only parallel construction algorithms.", false);
static TCLAP::SwitchArg run_only_sequential_arg("s", "sequential",
    "Run only sequential construction algorithms.", false);
static TCLAP::SwitchArg no_trees_arg("m", "no_trees",
    "Skip all wavelet trees construction algorithms.", false);
static TCLAP::SwitchArg no_matrices_arg("t", "no_matrices",
    "Skip all wavelet matrices construction algorithms.", false);
static TCLAP::SwitchArg memory_arg("", "memory",
    "Compute peak memory during construction.", false);
static TCLAP::SwitchArg external_input_arg("i", "external_input",
    "Run only algorithms that stream the input instead of keeping it in RAM.", false);
static TCLAP::SwitchArg external_output_arg("o", "external_output",
    "Run only algorithms that stream the output instead of keeping it in RAM.", false);
static TCLAP::SwitchArg external_both_arg("e", "external",
    "Run only algorithms that use external memory", false);

template <memory_mode mem_mode>
int32_t run();

int32_t main(int32_t argc, char const* argv[]) {
  TCLAP::CmdLine cmd("Benchmark for wavelet tree (and matrix) construction",
    ' ', "0.2");
  cmd.add(list_all_algorithms);
  cmd.add(file_path_arg);
  cmd.add(filter_arg);
  cmd.add(word_width_arg);
  cmd.add(nr_runs_arg);
  cmd.add(run_only_parallel_arg);
  cmd.add(run_only_sequential_arg);
  cmd.add(no_trees_arg);
  cmd.add(no_matrices_arg);
  cmd.add(memory_arg);
  cmd.add(external_input_arg);
  cmd.add(external_output_arg);
  cmd.add(external_both_arg);
  cmd.parse( argc, argv );

  if(external_both_arg.getValue())
    return run<memory_mode::external>();
  else if(external_input_arg.getValue() && external_output_arg.getValue())
    return run<memory_mode::external>();
  else if(external_input_arg.getValue())
    return run<memory_mode::external_input>();
  else if(external_output_arg.getValue())
    return run<memory_mode::external_output>();
  else return run<memory_mode::internal>();
}

template <memory_mode mem_mode>
int32_t run() {

  if (list_all_algorithms.getValue()) {
    auto& algo_list_int =
      algorithm_list<memory_mode::internal>::get_algorithm_list();
    auto& algo_list_ext_in =
      algorithm_list<memory_mode::external_input>::get_algorithm_list();
    auto& algo_list_ext_out =
      algorithm_list<memory_mode::external_output>::get_algorithm_list();
    auto& algo_list_ext_both =
      algorithm_list<memory_mode::external>::get_algorithm_list();
    for (const auto& a : algo_list_int) a->print_info();
    for (const auto& a : algo_list_ext_in) a->print_info();
    for (const auto& a : algo_list_ext_out) a->print_info();
    for (const auto& a : algo_list_ext_both) a->print_info();
    return 0;
  }

  auto& algo_list = algorithm_list<mem_mode>::get_algorithm_list();

  const std::vector<std::string> file_paths = file_path_arg.getValue();
  std::string filter = filter_arg.getValue();
  const int32_t word_width = word_width_arg.getValue();
  const int32_t nr_runs = nr_runs_arg.getValue();
  const bool run_only_parallel = run_only_parallel_arg.getValue();
  const bool run_only_sequential = run_only_sequential_arg.getValue();
  const bool no_trees = no_trees_arg.getValue();
  const bool no_matrices = no_matrices_arg.getValue();
  const bool memory = memory_arg.getValue();

  constexpr bool ext_input =
    mem_mode == memory_mode::external ||
    mem_mode == memory_mode::external_input;
  constexpr bool ext_output =
    mem_mode == memory_mode::external ||
    mem_mode == memory_mode::external_output;

  for (const auto& path : file_paths) {
    std::cout << std::endl << "Text: " << path << std::endl;
    void * txt_prt = nullptr;

    uint64_t txt_bytes = 0;
    uint64_t all_bytes = 0;
    uint64_t text_size = 0;
    uint64_t max_char = 0;
    uint64_t levels = 0;
    std::string txt_path;

    std::vector<uint8_t> text_uint8;
    std::vector<uint16_t> text_uint16;
    std::vector<uint32_t> text_uint32;
    std::vector<uint64_t> text_uint64;
    uint8_t * text_uint8_data = nullptr;
    uint16_t * text_uint16_data = nullptr;
    uint32_t * text_uint32_data = nullptr;
    uint64_t * text_uint64_data = nullptr;

    stxxlvector<type_for_bytes<1>::type> * text_uint8_ext = nullptr;
    stxxlvector<type_for_bytes<2>::type> * text_uint16_ext = nullptr;
    stxxlvector<type_for_bytes<4>::type> * text_uint32_ext = nullptr;
    stxxlvector<type_for_bytes<8>::type> * text_uint64_ext = nullptr;

    malloc_count_reset_peak();
    uint64_t non_text_bytes = malloc_count_current();

    if(!ext_input) {
      // INTERNAL MEMORY INPUT
      if (word_width == 1) {
        text_uint8 = file_to_vector<1>(path);
        text_size = text_uint8.size();
        max_char = reduce_alphabet(text_uint8);
        text_uint8_data = text_uint8.data();
        txt_prt = &text_uint8_data;
      } else if (word_width == 2) {
        text_uint16 = file_to_vector<2>(path);
        text_size = text_uint16.size();
        max_char = reduce_alphabet(text_uint16);
        text_uint16_data = text_uint16.data();
        txt_prt = &text_uint16_data;
      } else if (word_width == 4) {
        text_uint32 = file_to_vector<4>(path);
        text_size = text_uint32.size();
        max_char = reduce_alphabet(text_uint32);
        text_uint32_data = text_uint32.data();
        txt_prt = &text_uint32_data;
      } else if (word_width == 8) {
        text_uint64 = file_to_vector<8>(path);
        text_size = text_uint64.size();
        max_char = reduce_alphabet(text_uint64);
        text_uint64_data = text_uint64.data();
        txt_prt = &text_uint64_data;
      } else {
        std::cerr << "You entered an invalid number of bytes per character "
                     "(parameter 'b')." << std::endl;
        return -1;
      }
    } else {
      // EXTERNAL MEMORY INPUT
      //~ stxxl::linuxaio_file stxxl_file(path, stxxl::file::open_mode::RDONLY);
      stxxl::syscall_file stxxl_file(path, stxxl::file::open_mode::RDONLY);
      if (word_width == 1) {
        const stxxlvector<type_for_bytes<1>::type> unreduced_vector(&stxxl_file);
        text_size = unreduced_vector.size();
        text_uint8_ext = new stxxlvector<type_for_bytes<1>::type>();
        max_char = reduce_alphabet<type_for_bytes<1>::type>(unreduced_vector, *text_uint8_ext);
        txt_prt = text_uint8_ext;
      } else if (word_width == 2) {
        const stxxlvector<type_for_bytes<2>::type> unreduced_vector(&stxxl_file);
        text_size = unreduced_vector.size();
        text_uint16_ext = new stxxlvector<type_for_bytes<2>::type>();
        max_char = reduce_alphabet<type_for_bytes<2>::type>(unreduced_vector, *text_uint16_ext);
        txt_prt = text_uint16_ext;
      } else if (word_width == 4) {
        const stxxlvector<type_for_bytes<4>::type> unreduced_vector(&stxxl_file);
        text_size = unreduced_vector.size();
        text_uint32_ext = new stxxlvector<type_for_bytes<4>::type>();
        max_char = reduce_alphabet<type_for_bytes<4>::type>(unreduced_vector, *text_uint32_ext);
        txt_prt = text_uint32_ext;
      } else if (word_width == 8) {
        const stxxlvector<type_for_bytes<8>::type> unreduced_vector(&stxxl_file);
        text_size = unreduced_vector.size();
        text_uint64_ext = new stxxlvector<type_for_bytes<8>::type>();
        max_char = reduce_alphabet<type_for_bytes<8>::type>(unreduced_vector, *text_uint64_ext);
        txt_prt = text_uint64_ext;
      } else {
        std::cerr << "You entered an invalid number of bytes per character "
                     "(parameter 'b')." << std::endl;
        return -1;
      }
    }
    levels = levels_for_max_char(max_char);

    #ifdef MALLOC_COUNT
      all_bytes = malloc_count_current();
      txt_bytes = all_bytes - non_text_bytes;
    #endif // MALLOC_COUNT

    std::cout << "Characters: " << text_size << std::endl;
    std::cout << "Levels:     " << levels << std::endl;

    #ifdef MALLOC_COUNT
      std::cout << "Memory peak text:  " << txt_bytes << ", MB: "
                << txt_bytes / (1024 * 1024) << std::endl;
      std::cout << "Memory peak total: " << all_bytes << ", MB: "
                << all_bytes / (1024 * 1024) << std::endl;
    #endif // MALLOC_COUNT

    for (const auto& a : algo_list) {
      if (filter == "" || (a->name().find(filter) != std::string::npos)) {
        if (a->word_width() == word_width) {
          if (filter_parallel(run_only_parallel, a->is_parallel())) {
            if (filter_sequential(run_only_sequential, a->is_parallel())) {
              if (filter_wavelet_type(a->is_tree(), no_trees, no_matrices)) {
                a->print_info();
                if (memory) {
                  #ifdef MALLOC_COUNT
                    malloc_count_reset_peak();
                    a->memory_peak(txt_prt, text_size, levels);
                    std::cout << malloc_count_peak() << ", MB: "
                              << malloc_count_peak() / (1024 * 1024) << std::endl;
                  #else
                    std::cout << "Memory measurement is NOT enabled."
                              << std::endl;
                  #endif // MALLOC_COUNT
                } else {
                  std::cout << a->median_time(
                    txt_prt, text_size, levels, nr_runs) << std::endl;
                }
              }
            }
          }
        }
      }
    }

    delete text_uint8_ext;
    delete text_uint16_ext;
    delete text_uint32_ext;
    delete text_uint64_ext;
  }
  return 0;
}

/******************************************************************************/
<commit_msg>Add missing #ifdef in benchmark.cpp<commit_after>/*******************************************************************************
 * src/benchmark.cpp
 *
 * Copyright (C) 2017 Florian Kurpicz <florian.kurpicz@tu-dortmund.de>
 * Copyright (C) 2018 Jonas Ellert <jonas.ellert@tu-dortmund.de>
 *
 * All rights reserved. Published under the BSD-2 license in the LICENSE file.
 ******************************************************************************/

#include <tclap/CmdLine.h>
#include <vector>

#include "benchmark/algorithm.hpp"
#include "util/alphabet_util.hpp"
#include "util/file_util.hpp"
#include "util/stxxl_helper.hpp"
#include "util/memory_types.hpp"

#ifdef MALLOC_COUNT
#include "benchmark/malloc_count.h"
#endif // MALLOC_COUNT

auto filter_parallel(bool only_parallel, bool is_parallel) {
  return (!only_parallel || is_parallel);
}

auto filter_sequential(bool sequential, bool is_parallel) {
  return (!sequential || !is_parallel);
}

auto filter_wavelet_type(bool is_tree, bool no_trees, bool no_matrices) {
  return (is_tree ? !no_trees : !no_matrices);
}

static TCLAP::SwitchArg list_all_algorithms("l", "list",
    "Print the name and description of all registered algorithms", false);
static TCLAP::MultiArg<std::string> file_path_arg("f", "file",
    "Path to the text file.", false, "string");
static TCLAP::ValueArg<std::string> filter_arg("n", "name",
    "Runs all algorithms that contain the <name> in their name", false, "",
    "string");
static TCLAP::ValueArg<int32_t> word_width_arg("b", "byte",
    "Bytes per char in the input text.", false, 1, "uint8_t");
static TCLAP::ValueArg<int32_t> nr_runs_arg("r", "runs",
    "Number of repetitions of the construction algorithm.",
    false, 5, "int32_t");
static TCLAP::SwitchArg run_only_parallel_arg("p", "parallel",
    "Run only parallel construction algorithms.", false);
static TCLAP::SwitchArg run_only_sequential_arg("s", "sequential",
    "Run only sequential construction algorithms.", false);
static TCLAP::SwitchArg no_trees_arg("m", "no_trees",
    "Skip all wavelet trees construction algorithms.", false);
static TCLAP::SwitchArg no_matrices_arg("t", "no_matrices",
    "Skip all wavelet matrices construction algorithms.", false);
static TCLAP::SwitchArg memory_arg("", "memory",
    "Compute peak memory during construction.", false);
static TCLAP::SwitchArg external_input_arg("i", "external_input",
    "Run only algorithms that stream the input instead of keeping it in RAM.", false);
static TCLAP::SwitchArg external_output_arg("o", "external_output",
    "Run only algorithms that stream the output instead of keeping it in RAM.", false);
static TCLAP::SwitchArg external_both_arg("e", "external",
    "Run only algorithms that use external memory", false);

template <memory_mode mem_mode>
int32_t run();

int32_t main(int32_t argc, char const* argv[]) {
  TCLAP::CmdLine cmd("Benchmark for wavelet tree (and matrix) construction",
    ' ', "0.2");
  cmd.add(list_all_algorithms);
  cmd.add(file_path_arg);
  cmd.add(filter_arg);
  cmd.add(word_width_arg);
  cmd.add(nr_runs_arg);
  cmd.add(run_only_parallel_arg);
  cmd.add(run_only_sequential_arg);
  cmd.add(no_trees_arg);
  cmd.add(no_matrices_arg);
  cmd.add(memory_arg);
  cmd.add(external_input_arg);
  cmd.add(external_output_arg);
  cmd.add(external_both_arg);
  cmd.parse( argc, argv );

  if(external_both_arg.getValue())
    return run<memory_mode::external>();
  else if(external_input_arg.getValue() && external_output_arg.getValue())
    return run<memory_mode::external>();
  else if(external_input_arg.getValue())
    return run<memory_mode::external_input>();
  else if(external_output_arg.getValue())
    return run<memory_mode::external_output>();
  else return run<memory_mode::internal>();
}

template <memory_mode mem_mode>
int32_t run() {

  if (list_all_algorithms.getValue()) {
    auto& algo_list_int =
      algorithm_list<memory_mode::internal>::get_algorithm_list();
    auto& algo_list_ext_in =
      algorithm_list<memory_mode::external_input>::get_algorithm_list();
    auto& algo_list_ext_out =
      algorithm_list<memory_mode::external_output>::get_algorithm_list();
    auto& algo_list_ext_both =
      algorithm_list<memory_mode::external>::get_algorithm_list();
    for (const auto& a : algo_list_int) a->print_info();
    for (const auto& a : algo_list_ext_in) a->print_info();
    for (const auto& a : algo_list_ext_out) a->print_info();
    for (const auto& a : algo_list_ext_both) a->print_info();
    return 0;
  }

  auto& algo_list = algorithm_list<mem_mode>::get_algorithm_list();

  const std::vector<std::string> file_paths = file_path_arg.getValue();
  std::string filter = filter_arg.getValue();
  const int32_t word_width = word_width_arg.getValue();
  const int32_t nr_runs = nr_runs_arg.getValue();
  const bool run_only_parallel = run_only_parallel_arg.getValue();
  const bool run_only_sequential = run_only_sequential_arg.getValue();
  const bool no_trees = no_trees_arg.getValue();
  const bool no_matrices = no_matrices_arg.getValue();
  const bool memory = memory_arg.getValue();

  constexpr bool ext_input =
    mem_mode == memory_mode::external ||
    mem_mode == memory_mode::external_input;
  constexpr bool ext_output =
    mem_mode == memory_mode::external ||
    mem_mode == memory_mode::external_output;

  for (const auto& path : file_paths) {
    std::cout << std::endl << "Text: " << path << std::endl;

    void * txt_prt = nullptr;

    uint64_t txt_bytes = 0;
    uint64_t all_bytes = 0;
    uint64_t text_size = 0;
    uint64_t max_char = 0;
    uint64_t levels = 0;
    std::string txt_path;

    std::vector<uint8_t> text_uint8;
    std::vector<uint16_t> text_uint16;
    std::vector<uint32_t> text_uint32;
    std::vector<uint64_t> text_uint64;
    uint8_t * text_uint8_data = nullptr;
    uint16_t * text_uint16_data = nullptr;
    uint32_t * text_uint32_data = nullptr;
    uint64_t * text_uint64_data = nullptr;

    stxxlvector<type_for_bytes<1>::type> * text_uint8_ext = nullptr;
    stxxlvector<type_for_bytes<2>::type> * text_uint16_ext = nullptr;
    stxxlvector<type_for_bytes<4>::type> * text_uint32_ext = nullptr;
    stxxlvector<type_for_bytes<8>::type> * text_uint64_ext = nullptr;

    #ifdef MALLOC_COUNT
      malloc_count_reset_peak();
      uint64_t non_text_bytes = malloc_count_current();
    #endif // MALLOC_COUNT

    if(!ext_input) {
      // INTERNAL MEMORY INPUT
      if (word_width == 1) {
        text_uint8 = file_to_vector<1>(path);
        text_size = text_uint8.size();
        max_char = reduce_alphabet(text_uint8);
        text_uint8_data = text_uint8.data();
        txt_prt = &text_uint8_data;
      } else if (word_width == 2) {
        text_uint16 = file_to_vector<2>(path);
        text_size = text_uint16.size();
        max_char = reduce_alphabet(text_uint16);
        text_uint16_data = text_uint16.data();
        txt_prt = &text_uint16_data;
      } else if (word_width == 4) {
        text_uint32 = file_to_vector<4>(path);
        text_size = text_uint32.size();
        max_char = reduce_alphabet(text_uint32);
        text_uint32_data = text_uint32.data();
        txt_prt = &text_uint32_data;
      } else if (word_width == 8) {
        text_uint64 = file_to_vector<8>(path);
        text_size = text_uint64.size();
        max_char = reduce_alphabet(text_uint64);
        text_uint64_data = text_uint64.data();
        txt_prt = &text_uint64_data;
      } else {
        std::cerr << "You entered an invalid number of bytes per character "
                     "(parameter 'b')." << std::endl;
        return -1;
      }
    } else {
      // EXTERNAL MEMORY INPUT
      //~ stxxl::linuxaio_file stxxl_file(path, stxxl::file::open_mode::RDONLY);
      stxxl::syscall_file stxxl_file(path, stxxl::file::open_mode::RDONLY);
      if (word_width == 1) {
        const stxxlvector<type_for_bytes<1>::type> unreduced_vector(&stxxl_file);
        text_size = unreduced_vector.size();
        text_uint8_ext = new stxxlvector<type_for_bytes<1>::type>();
        max_char = reduce_alphabet<type_for_bytes<1>::type>(unreduced_vector, *text_uint8_ext);
        txt_prt = text_uint8_ext;
      } else if (word_width == 2) {
        const stxxlvector<type_for_bytes<2>::type> unreduced_vector(&stxxl_file);
        text_size = unreduced_vector.size();
        text_uint16_ext = new stxxlvector<type_for_bytes<2>::type>();
        max_char = reduce_alphabet<type_for_bytes<2>::type>(unreduced_vector, *text_uint16_ext);
        txt_prt = text_uint16_ext;
      } else if (word_width == 4) {
        const stxxlvector<type_for_bytes<4>::type> unreduced_vector(&stxxl_file);
        text_size = unreduced_vector.size();
        text_uint32_ext = new stxxlvector<type_for_bytes<4>::type>();
        max_char = reduce_alphabet<type_for_bytes<4>::type>(unreduced_vector, *text_uint32_ext);
        txt_prt = text_uint32_ext;
      } else if (word_width == 8) {
        const stxxlvector<type_for_bytes<8>::type> unreduced_vector(&stxxl_file);
        text_size = unreduced_vector.size();
        text_uint64_ext = new stxxlvector<type_for_bytes<8>::type>();
        max_char = reduce_alphabet<type_for_bytes<8>::type>(unreduced_vector, *text_uint64_ext);
        txt_prt = text_uint64_ext;
      } else {
        std::cerr << "You entered an invalid number of bytes per character "
                     "(parameter 'b')." << std::endl;
        return -1;
      }
    }
    levels = levels_for_max_char(max_char);

    #ifdef MALLOC_COUNT
      all_bytes = malloc_count_current();
      txt_bytes = all_bytes - non_text_bytes;
    #endif // MALLOC_COUNT

    std::cout << "Characters: " << text_size << std::endl;
    std::cout << "Levels:     " << levels << std::endl;

    #ifdef MALLOC_COUNT
      std::cout << "Memory peak text:  " << txt_bytes << ", MB: "
                << txt_bytes / (1024 * 1024) << std::endl;
      std::cout << "Memory peak total: " << all_bytes << ", MB: "
                << all_bytes / (1024 * 1024) << std::endl;
    #endif // MALLOC_COUNT

    for (const auto& a : algo_list) {
      if (filter == "" || (a->name().find(filter) != std::string::npos)) {
        if (a->word_width() == word_width) {
          if (filter_parallel(run_only_parallel, a->is_parallel())) {
            if (filter_sequential(run_only_sequential, a->is_parallel())) {
              if (filter_wavelet_type(a->is_tree(), no_trees, no_matrices)) {
                a->print_info();
                if (memory) {
                  #ifdef MALLOC_COUNT
                    malloc_count_reset_peak();
                    a->memory_peak(txt_prt, text_size, levels);
                    std::cout << malloc_count_peak() << ", MB: "
                              << malloc_count_peak() / (1024 * 1024) << std::endl;
                  #else
                    std::cout << "Memory measurement is NOT enabled."
                              << std::endl;
                  #endif // MALLOC_COUNT
                } else {
                  std::cout << a->median_time(
                    txt_prt, text_size, levels, nr_runs) << std::endl;
                }
              }
            }
          }
        }
      }
    }

    delete text_uint8_ext;
    delete text_uint16_ext;
    delete text_uint32_ext;
    delete text_uint64_ext;
  }
  return 0;
}

/******************************************************************************/
<|endoftext|>


<commit_before>#include <algorithm>
#include <map>
#include <string>
#include <limits>

#include "Prefetch.h"
#include "CodeGen_Internal.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "Bounds.h"
#include "Scope.h"
#include "Simplify.h"
#include "Substitute.h"
#include "Util.h"

namespace Halide {
namespace Internal {

using std::map;
using std::string;
using std::vector;
using std::stack;
using std::pair;

// Prefetch debug levels
int dbg_prefetch1 = 1;
int dbg_prefetch2 = 2;
int dbg_prefetch3 = 3;
int dbg_prefetch4 = 4;
int dbg_prefetch5 = 5;

#define MIN(x,y)        (((x)<(y)) ? (x) : (y))
#define MAX(x,y)        (((x)>(y)) ? (x) : (y))

class InjectPrefetch : public IRMutator {
public:
    InjectPrefetch(const map<string, Function> &e)
        : env(e) { }
private:
    const map<string, Function> &env;   // Environment
    Scope<Interval> scope;              // Interval scope
    Scope<int> rscope;                  // Realize scope
    unsigned long ptmp = 0;             // ID for all tmp vars in a prefetch op

private:
    using IRMutator::visit;

    // Strip down the tuple name, e.g. f.*.var into f
    string tuple_func(const string &name) {
        vector<string> v = split_string(name, ".");
        internal_assert(v.size() > 0);
        return v[0];
    }

    // Strip down the tuple name, e.g. f.*.var into var
    string tuple_var(const string &name) {
        vector<string> v = split_string(name, ".");
        internal_assert(v.size() > 0);
        return v[v.size()-1];
    }

    // Lookup a function in the environment
    Function get_func(const string &name) {
        map<string, Function>::const_iterator iter = env.find(name);
        internal_assert(iter != env.end()) << "function not in environment.\n";
        return iter->second;
    }

    // Determine the static type of a named buffer (if available)
    //
    // Note: If the type cannot be determined, the variable will
    //       be flagged as not having a static type (e.g. the type
    //       of input is only known at runtime, input.elem_size).
    //
    Type get_type(string varname, bool &has_static_type) {
        has_static_type = false;
        debug(dbg_prefetch4) << "    getType(" << varname << ")";
        Type t = UInt(8);       // default type
        map<string, Function>::const_iterator varit = env.find(varname);
        if (varit != env.end()) {
            Function varf = varit->second;
            debug(dbg_prefetch4) << " found: " << varit->first;
            if (varf.outputs()) {
                vector<Type> varts = varf.output_types();
                t = varts[0];
                has_static_type = true;
            }
        } else {
            debug(dbg_prefetch4) << " not found";
        }

        if (has_static_type) {
            debug(dbg_prefetch4) << ", type: " << t << "\n";
        } else {
            debug(dbg_prefetch4) << ", no static type\n";
        }

        return t;
    }

    // Generate the required prefetch code (lets and statements) for the
    // specified varname and box
    //
    void prefetch_box(const string &varname, Box &box,
                vector<pair<string, Expr>> &plets, vector<Stmt> &pstmts)
    {
        bool do_prefetch = true;
        int dims = box.size();
        bool has_static_type = true;
        Type t = get_type(varname, has_static_type);
        string elem_size_name = varname + ".elem_size";
        Expr elem_size_bytes;

        if (rscope.contains(varname)) {
            debug(dbg_prefetch2) << "  Found realize node for " << varname << "\n";
            debug(dbg_prefetch1) << "  Info: not prefetching realized " << varname << "\n";
            return;
        }
        if (has_static_type) {
            elem_size_bytes = t.bytes();
        } else {   // Use element size for inputs that don't have static types
            Expr elem_size_var = Variable::make(Int(32), elem_size_name);
            elem_size_bytes = elem_size_var;
        }

        std::ostringstream ss; ss << t;
        string type_name = ss.str();
        debug(dbg_prefetch1) << "  prefetch #" << ptmp << ": "
                             << varname << " ("
                             << (has_static_type ? type_name : elem_size_name)
                             << ", dims:" << dims << ")\n";

        for (int i = 0; i < dims; i++) {
            debug(dbg_prefetch3) << "    ---\n";
            debug(dbg_prefetch3) << "    box[" << i << "].min: " << box[i].min << "\n";
            debug(dbg_prefetch3) << "    box[" << i << "].max: " << box[i].max << "\n";
        }
        debug(dbg_prefetch3) << "    ---------\n";

        // TODO: Opt: check box if it should be prefetched?
        // TODO       - Only prefetch if varying by ivar_name?
        // TODO       - Don't prefetch if "small" all constant dimensions?
        // TODO         e.g. see: camera_pipe.cpp corrected matrix(4,3)

        string pstr = std::to_string(ptmp++);
        string varname_prefetch_buf = varname + "_prefetch_" + pstr + "_buf";
        Expr var_prefetch_buf = Variable::make(Int(32), varname_prefetch_buf);

        // Establish the variables for buffer strides, box min & max
        vector<Expr> stride_var(dims);
        vector<Expr> extent_var(dims);
        vector<Expr> min_var(dims);
        vector<Expr> max_var(dims);
        for (int i = 0; i < dims; i++) {
            string istr = std::to_string(i);
            // string extent_name = varname + ".extent." + istr;
            string stride_name = varname + ".stride." + istr;
            string extent_name = varname + ".extent." + istr;
            string min_name = varname + "_prefetch_" + pstr + "_min_" + istr;
            string max_name = varname + "_prefetch_" + pstr + "_max_" + istr;

            stride_var[i] = Variable::make(Int(32), stride_name);
            extent_var[i] = Variable::make(Int(32), extent_name);
            min_var[i] = Variable::make(Int(32), min_name);
            max_var[i] = Variable::make(Int(32), max_name);

            // Record let assignments
            // except for stride, already defined elsewhere
            plets.push_back(make_pair(min_name, box[i].min));
            plets.push_back(make_pair(max_name, box[i].max));
        }

        // This box should not be prefetched
        if (!do_prefetch) {
            debug(dbg_prefetch1) << "  Info: not prefetching " << varname << "\n";
            return;
        }

        // Create a buffer_t object for this prefetch.
        vector<Expr> args(dims*3 + 2);

        Expr first_elem = Load::make(t, varname, 0, Buffer(), Parameter());
        args[0] = Call::make(Handle(), Call::address_of, {first_elem}, Call::PureIntrinsic);
        args[1] = make_zero(t);
        for (int i = 0; i < dims; i++) {
            args[3*i+2] = min_var[i];
            args[3*i+3] = max_var[i] - min_var[i] + 1;
            args[3*i+4] = stride_var[i];
        }

        // Create the create_buffer_t call
        Expr prefetch_buf = Call::make(type_of<struct buffer_t *>(), Call::create_buffer_t,
                              args, Call::Intrinsic);
        plets.push_back(make_pair(varname_prefetch_buf, prefetch_buf));

        // Create the prefetch call
        Expr num_elem = stride_var[dims-1] * extent_var[dims-1];
        vector<Expr> args_prefetch(4);
        args_prefetch[0] = dims;
        args_prefetch[1] = elem_size_bytes;
        args_prefetch[2] = num_elem;
        args_prefetch[3] = var_prefetch_buf;
        Stmt stmt_prefetch = Evaluate::make(Call::make(Int(32), Call::prefetch_buffer_t,
                              args_prefetch, Call::Intrinsic));
        // TODO: Opt: Keep running sum of bytes prefetched on this sequence?
        // TODO: Opt: Keep running sum of number of prefetch instructions issued
        // TODO       on this sequence? (to not exceed MAX_PREFETCH)
        // TODO: Opt: Generate more control code for prefetch_buffer_t in Prefetch.cpp?
        // TODO       Passing box info through a buffer_t results in ~30 additional stores/loads

        pstmts.push_back(stmt_prefetch);
    }

    // Inject the generated prefetch code
    //
    // Note: plets/pstmts may be modified or partially emptied during injection
    //
    void inject_prefetch_stmts(const For *op, const Prefetch &p,
                vector<pair<string, Expr>> &plets, vector<Stmt> &pstmts, Stmt &body)
    {
        if (pstmts.size() > 0) {
            Stmt pbody = pstmts.back();    // Initialize prefetch body
            pstmts.pop_back();
            for (size_t i = pstmts.size(); i > 0; i--) {
                pbody = Block::make(pstmts[i-1], pbody);
            }
            for (size_t i = plets.size(); i > 0; i--) {
                pbody = LetStmt::make(plets[i-1].first, plets[i-1].second, pbody);
            }

            // No guard needed, address range checked in prefetch runtime
            body = Block::make({pbody, body});
            debug(dbg_prefetch4) << pbody << "\n";
        }
    }

    void visit(const Let *op) {
        Interval in = bounds_of_expr_in_scope(op->value, scope);
        scope.push(op->name, in);
        debug(dbg_prefetch5) << "Let scope.push(" << op->name << ")\n";
        IRMutator::visit(op);
        debug(dbg_prefetch5) << "Let scope.pop(" << op->name << ")\n";
        scope.pop(op->name);
    }

    void visit(const LetStmt *op) {
        Interval in = bounds_of_expr_in_scope(op->value, scope);
        scope.push(op->name, in);
        debug(dbg_prefetch5) << "LetStmt scope.push(" << op->name << ")\n";
        IRMutator::visit(op);
        debug(dbg_prefetch5) << "LetStmt scope.pop(" << op->name << ")\n";
        scope.pop(op->name);
    }

    void visit(const Realize *op) {
        rscope.push(op->name, 1);
        debug(dbg_prefetch5) << "Realize push(" << op->name << ")\n";
        IRMutator::visit(op);
    }

    void visit(const For *op) {
        Stmt body = op->body;

        string func_name = tuple_func(op->name);
        string ivar_name = tuple_var(op->name);
        vector<Prefetch> &prefetches = get_func(func_name).schedule().prefetches();

        // Add loop variable to interval scope for any inner loop prefetch
        Expr var = Variable::make(Int(32), op->name);
        Interval prein(var, var);
        scope.push(op->name, prein);
        debug(dbg_prefetch5) << "For scope.push(" << op->name << ", (" << var << "))\n";

        debug(dbg_prefetch4) << "For: " << op->name << " " << func_name << " " << ivar_name << "\n";
        if (prefetches.empty()) {
            debug(dbg_prefetch4) << " No prefetch directives in schedule\n";
        } else {
            debug(dbg_prefetch4) << " Found prefetch directive(s) in schedule\n";
        }

        body = mutate(body);

        for (const Prefetch &p : prefetches) {
            debug(dbg_prefetch4) << " Check prefetch ivar: " << p.var << " == " << ivar_name << "\n";
            if (p.var == ivar_name) {
                debug(dbg_prefetch4) << " Found directive matching " << ivar_name << "\n";
                debug(dbg_prefetch1) << " " << func_name
                                     << " prefetch(" << ivar_name << ", " << p.offset << ")\n";

                // Add loop variable + prefetch offset to interval scope for box computation
                Expr var = Variable::make(Int(32), op->name);
                Interval prein(var + p.offset, var + p.offset);
                scope.push(op->name, prein);
                debug(dbg_prefetch5) << " For scope.push(" << op->name << ", ("
                                     << var << " + " << p.offset << ", "
                                     << var << " + " << p.offset << "))\n";

                map<string, Box> boxes;
                boxes = boxes_required(body, scope);
                // TODO: Opt: prefetch the difference from previous iteration
                //            to the requested iteration (2 calls to boxes_required)

                vector<pair<string, Expr>> plets;  // Prefetch let assignments
                vector<Stmt> pstmts;               // Prefetch stmt sequence
                debug(dbg_prefetch3) << "  boxes required:\n";
                for (auto &b : boxes) {
                    const string &varname = b.first;
                    Box &box = b.second;
                    prefetch_box(varname, box, plets, pstmts);
                }

                inject_prefetch_stmts(op, p, plets, pstmts, body);

                debug(dbg_prefetch5) << " For scope.pop(" << op->name << ")\n";
                scope.pop(op->name);
            }
        }

        debug(dbg_prefetch5) << "For scope.pop(" << op->name << ")\n";
        scope.pop(op->name);

        stmt = For::make(op->name, op->min, op->extent, op->for_type, op->device_api, body);
        debug(dbg_prefetch4) << "EndFor: " << op->name << "\n";
    }

};

Stmt inject_prefetch(Stmt s, const std::map<std::string, Function> &env)
{
    size_t read;
    std::string lvl = get_env_variable("HL_DEBUG_PREFETCH", read);
    if (read) {
        int dbg_level = atoi(lvl.c_str());
        dbg_prefetch1 = MAX(dbg_prefetch1 - dbg_level, 0);
        dbg_prefetch2 = MAX(dbg_prefetch2 - dbg_level, 0);
        dbg_prefetch3 = MAX(dbg_prefetch3 - dbg_level, 0);
        dbg_prefetch4 = MAX(dbg_prefetch4 - dbg_level, 0);
        dbg_prefetch5 = MAX(dbg_prefetch5 - dbg_level, 0);
    }

    debug(dbg_prefetch1) << "prefetch:\n";
    return InjectPrefetch(env).mutate(s);
}

}
}
<commit_msg>Fix Travis build failure: Buffer() -> BufferPtr()<commit_after>#include <algorithm>
#include <map>
#include <string>
#include <limits>

#include "Prefetch.h"
#include "CodeGen_Internal.h"
#include "IRMutator.h"
#include "IROperator.h"
#include "Bounds.h"
#include "Scope.h"
#include "Simplify.h"
#include "Substitute.h"
#include "Util.h"

namespace Halide {
namespace Internal {

using std::map;
using std::string;
using std::vector;
using std::stack;
using std::pair;

// Prefetch debug levels
int dbg_prefetch1 = 1;
int dbg_prefetch2 = 2;
int dbg_prefetch3 = 3;
int dbg_prefetch4 = 4;
int dbg_prefetch5 = 5;

#define MIN(x,y)        (((x)<(y)) ? (x) : (y))
#define MAX(x,y)        (((x)>(y)) ? (x) : (y))

class InjectPrefetch : public IRMutator {
public:
    InjectPrefetch(const map<string, Function> &e)
        : env(e) { }
private:
    const map<string, Function> &env;   // Environment
    Scope<Interval> scope;              // Interval scope
    Scope<int> rscope;                  // Realize scope
    unsigned long ptmp = 0;             // ID for all tmp vars in a prefetch op

private:
    using IRMutator::visit;

    // Strip down the tuple name, e.g. f.*.var into f
    string tuple_func(const string &name) {
        vector<string> v = split_string(name, ".");
        internal_assert(v.size() > 0);
        return v[0];
    }

    // Strip down the tuple name, e.g. f.*.var into var
    string tuple_var(const string &name) {
        vector<string> v = split_string(name, ".");
        internal_assert(v.size() > 0);
        return v[v.size()-1];
    }

    // Lookup a function in the environment
    Function get_func(const string &name) {
        map<string, Function>::const_iterator iter = env.find(name);
        internal_assert(iter != env.end()) << "function not in environment.\n";
        return iter->second;
    }

    // Determine the static type of a named buffer (if available)
    //
    // Note: If the type cannot be determined, the variable will
    //       be flagged as not having a static type (e.g. the type
    //       of input is only known at runtime, input.elem_size).
    //
    Type get_type(string varname, bool &has_static_type) {
        has_static_type = false;
        debug(dbg_prefetch4) << "    getType(" << varname << ")";
        Type t = UInt(8);       // default type
        map<string, Function>::const_iterator varit = env.find(varname);
        if (varit != env.end()) {
            Function varf = varit->second;
            debug(dbg_prefetch4) << " found: " << varit->first;
            if (varf.outputs()) {
                vector<Type> varts = varf.output_types();
                t = varts[0];
                has_static_type = true;
            }
        } else {
            debug(dbg_prefetch4) << " not found";
        }

        if (has_static_type) {
            debug(dbg_prefetch4) << ", type: " << t << "\n";
        } else {
            debug(dbg_prefetch4) << ", no static type\n";
        }

        return t;
    }

    // Generate the required prefetch code (lets and statements) for the
    // specified varname and box
    //
    void prefetch_box(const string &varname, Box &box,
                vector<pair<string, Expr>> &plets, vector<Stmt> &pstmts)
    {
        bool do_prefetch = true;
        int dims = box.size();
        bool has_static_type = true;
        Type t = get_type(varname, has_static_type);
        string elem_size_name = varname + ".elem_size";
        Expr elem_size_bytes;

        if (rscope.contains(varname)) {
            debug(dbg_prefetch2) << "  Found realize node for " << varname << "\n";
            debug(dbg_prefetch1) << "  Info: not prefetching realized " << varname << "\n";
            return;
        }
        if (has_static_type) {
            elem_size_bytes = t.bytes();
        } else {   // Use element size for inputs that don't have static types
            Expr elem_size_var = Variable::make(Int(32), elem_size_name);
            elem_size_bytes = elem_size_var;
        }

        std::ostringstream ss; ss << t;
        string type_name = ss.str();
        debug(dbg_prefetch1) << "  prefetch #" << ptmp << ": "
                             << varname << " ("
                             << (has_static_type ? type_name : elem_size_name)
                             << ", dims:" << dims << ")\n";

        for (int i = 0; i < dims; i++) {
            debug(dbg_prefetch3) << "    ---\n";
            debug(dbg_prefetch3) << "    box[" << i << "].min: " << box[i].min << "\n";
            debug(dbg_prefetch3) << "    box[" << i << "].max: " << box[i].max << "\n";
        }
        debug(dbg_prefetch3) << "    ---------\n";

        // TODO: Opt: check box if it should be prefetched?
        // TODO       - Only prefetch if varying by ivar_name?
        // TODO       - Don't prefetch if "small" all constant dimensions?
        // TODO         e.g. see: camera_pipe.cpp corrected matrix(4,3)

        string pstr = std::to_string(ptmp++);
        string varname_prefetch_buf = varname + "_prefetch_" + pstr + "_buf";
        Expr var_prefetch_buf = Variable::make(Int(32), varname_prefetch_buf);

        // Establish the variables for buffer strides, box min & max
        vector<Expr> stride_var(dims);
        vector<Expr> extent_var(dims);
        vector<Expr> min_var(dims);
        vector<Expr> max_var(dims);
        for (int i = 0; i < dims; i++) {
            string istr = std::to_string(i);
            // string extent_name = varname + ".extent." + istr;
            string stride_name = varname + ".stride." + istr;
            string extent_name = varname + ".extent." + istr;
            string min_name = varname + "_prefetch_" + pstr + "_min_" + istr;
            string max_name = varname + "_prefetch_" + pstr + "_max_" + istr;

            stride_var[i] = Variable::make(Int(32), stride_name);
            extent_var[i] = Variable::make(Int(32), extent_name);
            min_var[i] = Variable::make(Int(32), min_name);
            max_var[i] = Variable::make(Int(32), max_name);

            // Record let assignments
            // except for stride, already defined elsewhere
            plets.push_back(make_pair(min_name, box[i].min));
            plets.push_back(make_pair(max_name, box[i].max));
        }

        // This box should not be prefetched
        if (!do_prefetch) {
            debug(dbg_prefetch1) << "  Info: not prefetching " << varname << "\n";
            return;
        }

        // Create a buffer_t object for this prefetch.
        vector<Expr> args(dims*3 + 2);

        Expr first_elem = Load::make(t, varname, 0, BufferPtr(), Parameter());
        args[0] = Call::make(Handle(), Call::address_of, {first_elem}, Call::PureIntrinsic);
        args[1] = make_zero(t);
        for (int i = 0; i < dims; i++) {
            args[3*i+2] = min_var[i];
            args[3*i+3] = max_var[i] - min_var[i] + 1;
            args[3*i+4] = stride_var[i];
        }

        // Create the create_buffer_t call
        Expr prefetch_buf = Call::make(type_of<struct buffer_t *>(), Call::create_buffer_t,
                              args, Call::Intrinsic);
        plets.push_back(make_pair(varname_prefetch_buf, prefetch_buf));

        // Create the prefetch call
        Expr num_elem = stride_var[dims-1] * extent_var[dims-1];
        vector<Expr> args_prefetch(4);
        args_prefetch[0] = dims;
        args_prefetch[1] = elem_size_bytes;
        args_prefetch[2] = num_elem;
        args_prefetch[3] = var_prefetch_buf;
        Stmt stmt_prefetch = Evaluate::make(Call::make(Int(32), Call::prefetch_buffer_t,
                              args_prefetch, Call::Intrinsic));
        // TODO: Opt: Keep running sum of bytes prefetched on this sequence?
        // TODO: Opt: Keep running sum of number of prefetch instructions issued
        // TODO       on this sequence? (to not exceed MAX_PREFETCH)
        // TODO: Opt: Generate more control code for prefetch_buffer_t in Prefetch.cpp?
        // TODO       Passing box info through a buffer_t results in ~30 additional stores/loads

        pstmts.push_back(stmt_prefetch);
    }

    // Inject the generated prefetch code
    //
    // Note: plets/pstmts may be modified or partially emptied during injection
    //
    void inject_prefetch_stmts(const For *op, const Prefetch &p,
                vector<pair<string, Expr>> &plets, vector<Stmt> &pstmts, Stmt &body)
    {
        if (pstmts.size() > 0) {
            Stmt pbody = pstmts.back();    // Initialize prefetch body
            pstmts.pop_back();
            for (size_t i = pstmts.size(); i > 0; i--) {
                pbody = Block::make(pstmts[i-1], pbody);
            }
            for (size_t i = plets.size(); i > 0; i--) {
                pbody = LetStmt::make(plets[i-1].first, plets[i-1].second, pbody);
            }

            // No guard needed, address range checked in prefetch runtime
            body = Block::make({pbody, body});
            debug(dbg_prefetch4) << pbody << "\n";
        }
    }

    void visit(const Let *op) {
        Interval in = bounds_of_expr_in_scope(op->value, scope);
        scope.push(op->name, in);
        debug(dbg_prefetch5) << "Let scope.push(" << op->name << ")\n";
        IRMutator::visit(op);
        debug(dbg_prefetch5) << "Let scope.pop(" << op->name << ")\n";
        scope.pop(op->name);
    }

    void visit(const LetStmt *op) {
        Interval in = bounds_of_expr_in_scope(op->value, scope);
        scope.push(op->name, in);
        debug(dbg_prefetch5) << "LetStmt scope.push(" << op->name << ")\n";
        IRMutator::visit(op);
        debug(dbg_prefetch5) << "LetStmt scope.pop(" << op->name << ")\n";
        scope.pop(op->name);
    }

    void visit(const Realize *op) {
        rscope.push(op->name, 1);
        debug(dbg_prefetch5) << "Realize push(" << op->name << ")\n";
        IRMutator::visit(op);
    }

    void visit(const For *op) {
        Stmt body = op->body;

        string func_name = tuple_func(op->name);
        string ivar_name = tuple_var(op->name);
        vector<Prefetch> &prefetches = get_func(func_name).schedule().prefetches();

        // Add loop variable to interval scope for any inner loop prefetch
        Expr var = Variable::make(Int(32), op->name);
        Interval prein(var, var);
        scope.push(op->name, prein);
        debug(dbg_prefetch5) << "For scope.push(" << op->name << ", (" << var << "))\n";

        debug(dbg_prefetch4) << "For: " << op->name << " " << func_name << " " << ivar_name << "\n";
        if (prefetches.empty()) {
            debug(dbg_prefetch4) << " No prefetch directives in schedule\n";
        } else {
            debug(dbg_prefetch4) << " Found prefetch directive(s) in schedule\n";
        }

        body = mutate(body);

        for (const Prefetch &p : prefetches) {
            debug(dbg_prefetch4) << " Check prefetch ivar: " << p.var << " == " << ivar_name << "\n";
            if (p.var == ivar_name) {
                debug(dbg_prefetch4) << " Found directive matching " << ivar_name << "\n";
                debug(dbg_prefetch1) << " " << func_name
                                     << " prefetch(" << ivar_name << ", " << p.offset << ")\n";

                // Add loop variable + prefetch offset to interval scope for box computation
                Expr var = Variable::make(Int(32), op->name);
                Interval prein(var + p.offset, var + p.offset);
                scope.push(op->name, prein);
                debug(dbg_prefetch5) << " For scope.push(" << op->name << ", ("
                                     << var << " + " << p.offset << ", "
                                     << var << " + " << p.offset << "))\n";

                map<string, Box> boxes;
                boxes = boxes_required(body, scope);
                // TODO: Opt: prefetch the difference from previous iteration
                //            to the requested iteration (2 calls to boxes_required)

                vector<pair<string, Expr>> plets;  // Prefetch let assignments
                vector<Stmt> pstmts;               // Prefetch stmt sequence
                debug(dbg_prefetch3) << "  boxes required:\n";
                for (auto &b : boxes) {
                    const string &varname = b.first;
                    Box &box = b.second;
                    prefetch_box(varname, box, plets, pstmts);
                }

                inject_prefetch_stmts(op, p, plets, pstmts, body);

                debug(dbg_prefetch5) << " For scope.pop(" << op->name << ")\n";
                scope.pop(op->name);
            }
        }

        debug(dbg_prefetch5) << "For scope.pop(" << op->name << ")\n";
        scope.pop(op->name);

        stmt = For::make(op->name, op->min, op->extent, op->for_type, op->device_api, body);
        debug(dbg_prefetch4) << "EndFor: " << op->name << "\n";
    }

};

Stmt inject_prefetch(Stmt s, const std::map<std::string, Function> &env)
{
    size_t read;
    std::string lvl = get_env_variable("HL_DEBUG_PREFETCH", read);
    if (read) {
        int dbg_level = atoi(lvl.c_str());
        dbg_prefetch1 = MAX(dbg_prefetch1 - dbg_level, 0);
        dbg_prefetch2 = MAX(dbg_prefetch2 - dbg_level, 0);
        dbg_prefetch3 = MAX(dbg_prefetch3 - dbg_level, 0);
        dbg_prefetch4 = MAX(dbg_prefetch4 - dbg_level, 0);
        dbg_prefetch5 = MAX(dbg_prefetch5 - dbg_level, 0);
    }

    debug(dbg_prefetch1) << "prefetch:\n";
    return InjectPrefetch(env).mutate(s);
}

}
}
<|endoftext|>


<commit_before>/*
 * Priority.cpp
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "log4cpp/Portability.hh"
#include "log4cpp/Priority.hh"

namespace log4cpp {

    const std::string& Priority::getPriorityName(int priority) throw() {
        static std::string names[10] = {
            "FATAL", "ALERT", "CRIT", "ERROR", "WARN",
            "NOTICE", "INFO", "DEBUG", "NOTSET", "UNKNOWN"
        };

        priority++;
        priority /= 100;
        return ((priority < 0) || (priority > 8)) ?
            names[8] :
            names[priority - 1];
    }
}
<commit_msg>getPriorityName(): use index 'priority' instead of 'priority - 1'.<commit_after>/*
 * Priority.cpp
 *
 * Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
 * Copyright 2000, Bastiaan Bakker. All rights reserved.
 *
 * See the COPYING file for the terms of usage and distribution.
 */

#include "log4cpp/Portability.hh"
#include "log4cpp/Priority.hh"

namespace log4cpp {

    const std::string& Priority::getPriorityName(int priority) throw() {
        static std::string names[10] = {
            "FATAL", "ALERT", "CRIT", "ERROR", "WARN",
            "NOTICE", "INFO", "DEBUG", "NOTSET", "UNKNOWN"
        };

        priority++;
        priority /= 100;
        return names[((priority < 0) || (priority > 8)) ? 8 : priority];
    }
}
<|endoftext|>


<commit_before>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#include <usModuleActivator.h>
#include <usModuleContext.h>

#include <mitkDicomRTMimeTypes.h>
#include <mitkRTDoseReaderService.h>
#include <mitkRTPlanReaderService.h>
#include <mitkRTStructureSetReaderService.h>

namespace mitk
{
  class DicomRTIOActivator : public us::ModuleActivator
  {
  public:
    DicomRTIOActivator()
    {
    }

    ~DicomRTIOActivator() = default;

    void Load(us::ModuleContext* context) override
    {
      us::ServiceProperties props;
      props[us::ServiceConstants::SERVICE_RANKING()] = 100;

      for (const auto& mimeType : DicomRTMimeTypes::Get())
        context->RegisterService(mimeType.get(), props);

      m_RTDoseReader.reset(new RTDoseReaderService);
      m_RTPlanReader.reset(new RTPlanReaderService);
      m_RTStructureSetReader.reset(new RTStructureSetReaderService);
    }

    void Unload(us::ModuleContext*) override
    {
    }

  private:
    std::unique_ptr<RTDoseReaderService> m_RTDoseReader;
    std::unique_ptr<RTPlanReaderService> m_RTPlanReader;
    std::unique_ptr<RTStructureSetReaderService> m_RTStructureSetReader;
  };
}

US_EXPORT_MODULE_ACTIVATOR(mitk::DicomRTIOActivator)
<commit_msg>Prefer std::make_unique() to std::unique_ptr::reset()<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#include <usModuleActivator.h>
#include <usModuleContext.h>

#include <mitkDicomRTMimeTypes.h>
#include <mitkRTDoseReaderService.h>
#include <mitkRTPlanReaderService.h>
#include <mitkRTStructureSetReaderService.h>

namespace mitk
{
  class DicomRTIOActivator : public us::ModuleActivator
  {
  public:
    DicomRTIOActivator()
    {
    }

    ~DicomRTIOActivator() = default;

    void Load(us::ModuleContext* context) override
    {
      us::ServiceProperties props;
      props[us::ServiceConstants::SERVICE_RANKING()] = 100;

      for (const auto& mimeType : DicomRTMimeTypes::Get())
        context->RegisterService(mimeType.get(), props);

      m_RTDoseReader = std::make_unique<RTDoseReaderService>();
      m_RTPlanReader = std::make_unique<RTPlanReaderService>();
      m_RTStructureSetReader = std::make_unique<RTStructureSetReaderService>();
    }

    void Unload(us::ModuleContext*) override
    {
    }

  private:
    std::unique_ptr<RTDoseReaderService> m_RTDoseReader;
    std::unique_ptr<RTPlanReaderService> m_RTPlanReader;
    std::unique_ptr<RTStructureSetReaderService> m_RTStructureSetReader;
  };
}

US_EXPORT_MODULE_ACTIVATOR(mitk::DicomRTIOActivator)
<|endoftext|>


<commit_before>/*
    Copyright (C) 2009  George Kiagiadakis <kiagiadakis.george@gmail.com>

    This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published
    by the Free Software Foundation; either version 2.1 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 Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "pad.h"
#include "caps.h"
#include "element.h"
#include <QtCore/QDebug>
#include <gst/gstpad.h>
#include <gst/gstutils.h>

namespace QGst {

//static
PadPtr Pad::create(PadDirection direction, const QGlib::String & name)
{
    GstPad *pad = gst_pad_new(name, static_cast<GstPadDirection>(direction));
    return PadPtr::wrap(pad, false);
}

PadDirection Pad::direction() const
{
    return static_cast<PadDirection>(gst_pad_get_direction(object<GstPad>()));
}

ElementPtr Pad::parentElement() const
{
    return ElementPtr::wrap(gst_pad_get_parent_element(object<GstPad>()), false);
}

PadPtr Pad::peer() const
{
    return PadPtr::wrap(gst_pad_get_peer(object<GstPad>()), false);
}

bool Pad::isLinked() const
{
    return gst_pad_is_linked(object<GstPad>());
}

bool Pad::canLink(const PadPtr & sink) const
{
    return gst_pad_can_link(object<GstPad>(), sink);
}

PadLinkReturn Pad::link(const PadPtr & sink)
{
    return static_cast<PadLinkReturn>(gst_pad_link(object<GstPad>(), sink));
}

bool Pad::unlink(const PadPtr & sink)
{
    return gst_pad_unlink(object<GstPad>(), sink);
}

CapsPtr Pad::caps() const
{
    return CapsPtr::wrap(gst_pad_get_caps_reffed(object<GstPad>()), false);
}

CapsPtr Pad::allowedCaps() const
{
    return CapsPtr::wrap(gst_pad_get_allowed_caps(object<GstPad>()), false);
}

CapsPtr Pad::negotiatedCaps() const
{
    return CapsPtr::wrap(gst_pad_get_negotiated_caps(object<GstPad>()), false);
}

bool Pad::setCaps(const CapsPtr & caps)
{
    return gst_pad_set_caps(object<GstPad>(), caps);
}

bool Pad::isActive() const
{
    return gst_pad_is_active(object<GstPad>());
}

bool Pad::isBlocked() const
{
    return gst_pad_is_blocked(object<GstPad>());
}

bool Pad::isBlocking() const
{
    return gst_pad_is_blocking(object<GstPad>());
}

bool Pad::setBlocked(bool blocked)
{
    return gst_pad_set_blocked(object<GstPad>(), blocked);
}

}
<commit_msg>Add missing gst_object_ref_sink() in Pad::create().<commit_after>/*
    Copyright (C) 2009  George Kiagiadakis <kiagiadakis.george@gmail.com>

    This library is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published
    by the Free Software Foundation; either version 2.1 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 Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "pad.h"
#include "caps.h"
#include "element.h"
#include <QtCore/QDebug>
#include <gst/gstpad.h>
#include <gst/gstutils.h>

namespace QGst {

//static
PadPtr Pad::create(PadDirection direction, const QGlib::String & name)
{
    GstPad *pad = gst_pad_new(name, static_cast<GstPadDirection>(direction));
    gst_object_ref_sink(pad);
    return PadPtr::wrap(pad, false);
}

PadDirection Pad::direction() const
{
    return static_cast<PadDirection>(gst_pad_get_direction(object<GstPad>()));
}

ElementPtr Pad::parentElement() const
{
    return ElementPtr::wrap(gst_pad_get_parent_element(object<GstPad>()), false);
}

PadPtr Pad::peer() const
{
    return PadPtr::wrap(gst_pad_get_peer(object<GstPad>()), false);
}

bool Pad::isLinked() const
{
    return gst_pad_is_linked(object<GstPad>());
}

bool Pad::canLink(const PadPtr & sink) const
{
    return gst_pad_can_link(object<GstPad>(), sink);
}

PadLinkReturn Pad::link(const PadPtr & sink)
{
    return static_cast<PadLinkReturn>(gst_pad_link(object<GstPad>(), sink));
}

bool Pad::unlink(const PadPtr & sink)
{
    return gst_pad_unlink(object<GstPad>(), sink);
}

CapsPtr Pad::caps() const
{
    return CapsPtr::wrap(gst_pad_get_caps_reffed(object<GstPad>()), false);
}

CapsPtr Pad::allowedCaps() const
{
    return CapsPtr::wrap(gst_pad_get_allowed_caps(object<GstPad>()), false);
}

CapsPtr Pad::negotiatedCaps() const
{
    return CapsPtr::wrap(gst_pad_get_negotiated_caps(object<GstPad>()), false);
}

bool Pad::setCaps(const CapsPtr & caps)
{
    return gst_pad_set_caps(object<GstPad>(), caps);
}

bool Pad::isActive() const
{
    return gst_pad_is_active(object<GstPad>());
}

bool Pad::isBlocked() const
{
    return gst_pad_is_blocked(object<GstPad>());
}

bool Pad::isBlocking() const
{
    return gst_pad_is_blocking(object<GstPad>());
}

bool Pad::setBlocked(bool blocked)
{
    return gst_pad_set_blocked(object<GstPad>(), blocked);
}

}
<|endoftext|>


<commit_before>#include "Renderer.hpp"

#include <QOpenGLShader>
#include <QMessageBox>
#include <typeinfo>
#include <QCoreApplication>
#include <QPainter>
#include <QThread>

#include <QAudioDeviceInfo>

static GLfloat vertices[] = {
    1, 1,0,  1,-1,0, -1,1,0,
    1,-1,0, -1,-1,0, -1,1,0
};
static GLfloat uvs[] = {
    1,0, 1,1, 0,0,
    1,1, 0,1, 0,0
};

const char * Renderer::defaultVertexShader =
        "#version 330 core\n"
        "\n"
        "in vec3 position;\n"
        "in vec2 texCoord;\n"
        "\n"
        "uniform int _time;\n"
        "\n"
        "out vec2  uv;\n"
        "out float time;\n"
        "\n"
        "void main(){\n"
        "   time = float(_time);\n"
        "   gl_Position = vec4(position, 1);\n"
        "   uv = texCoord;\n"
        "}";

const char * Renderer::defaultFragmentShader =
        "#version 330 core\n"
        "\n"
        "out vec4 color;\n"
        "\n"
        "uniform in vec2  uv;\n"
        "uniform in float time;\n"
        "\n"
        "void main(){\n"
        "     color = vec4(cos(uv.x * 5 - time / 1000) / 2 + .5, 0, sin(uv.x * 5 - time / 1000) / 2 + .5, 1);\n"
        "}";

const char * Renderer::mandelbrotFragmentShader =
        "#version 330 core\n"
        "\n"
        "in vec2  uv;\n"
        "in float time;\n"
        "\n"
        "vec2 center = vec2(0,0);\n"
        "float scale = 4;\n"
        "int iter = 10;\n"
        "\n"
        "void main() {\n"
        "    gl_FragColor = vec4(0,0,0,1);\n"
        "    vec2 z, c;\n"
        " \n"
        "    c.x = 1.3333 * (uv.x - 0.5) * scale - center.x;\n"
        "    c.y = (uv.y - 0.5) * scale - center.y;\n"
        " \n"
        "    int i;\n"
        "    z = c;\n"
        "    for(i=0; i < iter; ++i) {\n"
        "        float x = (z.x * z.x - z.y * z.y) + c.x;\n"
        "        float y = (z.y * z.x + z.x * z.y) + c.y;\n"
        " \n"
        "        if((x * x + y * y) > 4.0)\n"
        "            break;\n"
        "        z.x = x;\n"
        "        z.y = y;\n"
        "    }\n"
        "    if(i < iter)\n"
        "        gl_FragColor.r = float(i)/10.0;\n"
        "}\n";

const char * Renderer::juliaFragmentShader =
        "#version 330 core\n"
        "\n"
        "in vec2  uv;\n"
        "in float time;\n"
        "uniform in float[10] audioData;\n"
        "\n"
        "//uniform highp vec2 c = vec2(.1,.1);\n"
        "int iter = 100;\n"
        "out vec4 color;\n"
        "\n"
        "void main() {\n"
//        "   float audioVal = audioData[int(uv.x * 1764)];\n"
        "   float y = 1 - uv.y * 2;"
        "   if(y < max(0, audioVal) && y > min(0, audioVal)){\n"
        "       color = vec4(1.0);\n"
        "       return;\n"
        "   }\n"
        "    vec2 c = vec2(sin(time / 2000.0), cos(time / 1500.0));\n"
        "    color = vec4(0,audioData[int(uv.x * 1764)],0,1);\n"
        "    vec2 z;\n"
        " \n"
        "    z.x = 3.0 * (uv.x - 0.5);\n"
        "    z.y = 2.0 * (uv.y - 0.5);\n"
        " \n"
        "    int i;\n"
        "    for(i=0; i < iter; ++i) {\n"
        "        float x = (z.x * z.x - z.y * z.y) + c.x;\n"
        "        float y = (z.y * z.x + z.x * z.y) + c.y;\n"
        " \n"
        "        if((x * x + y * y) > 4.0)\n"
        "            break;\n"
        "        z.x = x;\n"
        "        z.y = y;\n"
        "    }\n"
        "    if(i < iter){\n"
        "        color.b = float(i) * 5.0 / float(iter);\n"
        "        color.g = (float(i) * 5.0 / float(iter) - .3) / .7;\n"
        "        color.r = (float(i) * 5.0 / float(iter) - .7) / .3;\n"
        "    }\n"
        "}\n";

Renderer::Renderer(QWindow *parent) : Renderer::Renderer("new", defaultFragmentShader, parent){ }

Renderer::Renderer(const QString &filename, const QString &instructions, QWindow *parent) :
    QWindow(parent),
    clearColor(Qt::black),
    context(0), device(0),
    time(0),
    pendingUpdate(false),
    vertexBuffer(0), uvBuffer(0), audioLeftTexture(0), audioRightTexture(0),
    vertexAttr(0), uvAttr(0), timeUniform(0),
    shaderProgram(0),
    fragmentSource(instructions)
{

    setTitle(filename);

    m_logger = new QOpenGLDebugLogger( this );

    connect(m_logger, SIGNAL(messageLogged(QOpenGLDebugMessage)),
             this, SLOT(onMessageLogged(QOpenGLDebugMessage)),
             Qt::DirectConnection );

    if ( m_logger->initialize() ) {
        m_logger->startLogging( QOpenGLDebugLogger::SynchronousLogging );
        m_logger->enableMessages();
    }

    time = new QTime();
    time->start();

    setSurfaceType(QWindow::OpenGLSurface);

    audio = new AudioInputProcessor(this);
    connect(audio, SIGNAL(processData(QByteArray)), this, SLOT(updateAudioData(QByteArray)));
    audio->start();

    QSurfaceFormat format;
    format.setMajorVersion(3);
    format.setMinorVersion(3);
    format.setSamples(4);
    format.setProfile(QSurfaceFormat::CoreProfile);
    setFormat(format);

    resize(800, 600);
    show();
}

Renderer::~Renderer(){
    glDeleteBuffers(1, &vertexBuffer);
    glDeleteBuffers(1, &uvBuffer);
    glDeleteTextures(1, &audioLeftTexture);
    glDeleteTextures(1, &audioRightTexture);
}

bool Renderer::init(){
    glDeleteBuffers(1, &vertexBuffer);
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glDeleteBuffers(1, &uvBuffer);
    glGenBuffers(1, &uvBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);

    glEnable(GL_TEXTURE_1D);

    glDeleteTextures(1, &audioLeftTexture);
    glGenTextures(1, &audioLeftTexture);
    glDeleteTextures(1, &audioRightTexture);
    glGenTextures(1, &audioRightTexture);

    glClearColor(0,0,.3,1);
    return initShaders(fragmentSource);
}

bool Renderer::initShaders(const QString &fragmentShader){
    QOpenGLShaderProgram *newShaderProgram = new QOpenGLShaderProgram(this);
    if(!newShaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, defaultVertexShader)){
        int infologLength;
        glGetShaderiv(newShaderProgram->programId(), GL_INFO_LOG_LENGTH, &infologLength);
        char *infoLog = new char[infologLength + 1];
        glGetShaderInfoLog(newShaderProgram->programId(), infologLength + 1, &infologLength, infoLog);

        qDebug() << infoLog;

        delete[] infoLog;

//        qDebug() << newShaderProgram->log();
        delete newShaderProgram;
        return false;
    }
    if(!newShaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShader)){
        qDebug() << newShaderProgram->log();
        delete newShaderProgram;
        return false;
    }
    if(!newShaderProgram->link()){
        qDebug() << newShaderProgram->log();
        delete newShaderProgram;
        return false;
    }
    shaderProgramMutex.lock();
        if(shaderProgram)
            delete shaderProgram;
        shaderProgram = newShaderProgram;
        vertexAttr   = shaderProgram->attributeLocation("position");
        uvAttr       = shaderProgram->attributeLocation("texCoord");
        timeUniform  = shaderProgram->uniformLocation("_time");
        audioLeftUniform = shaderProgram->uniformLocation("audioDataLeft");
        audioRightUniform = shaderProgram->uniformLocation("audioDataRight");
        shaderProgram->setUniformValue(audioLeftUniform, 0);
        shaderProgram->setUniformValue(audioRightUniform, 0);
        fragmentSource = fragmentShader;
    shaderProgramMutex.unlock();

//    qDebug() << "vertexAttr" << vertexAttr;
//    qDebug() << "uvAttr" << uvAttr;
//    qDebug() << "timeUniform" << timeUniform;
//    qDebug() << "audioUniform" << audioUniform;
    return true;
}

void Renderer::render(){
    if(!device)
        device = new QOpenGLPaintDevice();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    device->setSize(size());
    QPainter painter;
    //QPainter painter(device);
    render(&painter);
}

void Renderer::render(QPainter *){
    const qreal retinaScale = devicePixelRatio();
    glViewport(0, 0, width() * retinaScale, height() * retinaScale);

    glClear(GL_COLOR_BUFFER_BIT);

    shaderProgramMutex.lock();
    shaderProgram->bind();

    shaderProgram->setUniformValue(timeUniform, time->elapsed());

    glEnableVertexAttribArray(vertexAttr);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glVertexAttribPointer(vertexAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(uvAttr);
    glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
    glVertexAttribPointer(uvAttr, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices));

    glDisableVertexAttribArray(vertexAttr);
    glDisableVertexAttribArray(uvAttr);

    shaderProgram->release();
    shaderProgramMutex.unlock();
}

void Renderer::renderLater(){
    if(!pendingUpdate){
        QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
        pendingUpdate = true;
    }
}

void Renderer::renderNow(){
    pendingUpdate = false;

    if(!isExposed())
        return;

    bool needsInit = false;

    if(!context){
        context = new QOpenGLContext(this);
        context->setFormat(requestedFormat());
        context->create();

        needsInit = true;
    }

    context->makeCurrent(this);

    if(needsInit){
        initializeOpenGLFunctions();
        init();
    }
    if(!shaderProgram)
        initShaders(fragmentSource);

    if(shaderProgram)
        render();
    context->swapBuffers(this);

    renderLater();
}

bool Renderer::event(QEvent *event){
    switch(event->type()){
    case QEvent::UpdateRequest:
        QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
        renderNow();
        return true;
    case QEvent::Close:
        emit doneSignal(QtGlException());
        // No fall throu?
        return true;
    default:
        return QWindow::event(event);
    }
}

void Renderer::exposeEvent(QExposeEvent *){
    if(isExposed())
        renderNow();
}

bool Renderer::updateCode(const QString &filename, const QString &code){
    if(!initShaders(code))
        return false;
    setTitle(filename);
    return true;
}

void Renderer::updateAudioData(QByteArray data){
    if(!shaderProgram)
        return;
    GLenum type, internalType;
    char typeSize;
    switch(audio->format().sampleType() + audio->format().sampleSize()){
        case  8: case 10: type = GL_UNSIGNED_BYTE;  internalType = GL_R8UI;  typeSize = 1; break;
        case  9:          type = GL_BYTE;           internalType = GL_R8I;   typeSize = 1; break;
        case 16: case 18: type = GL_UNSIGNED_SHORT; internalType = GL_R16UI; typeSize = 2; break;
        case 17:          type = GL_SHORT;          internalType = GL_R16I;  typeSize = 2; break;
        case 32: case 34: type = GL_UNSIGNED_INT;   internalType = GL_R32UI; typeSize = 4; break;
        case 33:          type = GL_INT;            internalType = GL_R32I;  typeSize = 4; break;
        case 35:          type = GL_FLOAT;          internalType = GL_R32F;  typeSize = 4; break;
        default: return;
    }
    char *left, *right;
    int count = data.size();
    if(audio->format().channelCount() == 2){
        count /= 2;
        left  = new char[count];
        right = new char[count];
        for(int i = 0; i < count; i += typeSize){
            for(int j = 0; j < typeSize; ++j){
                left [i+j] = data[i*2+j         ];
                right[i+j] = data[i*2+j+typeSize];
            }
        }
    }else
        left = right = data.data();

    shaderProgramMutex.lock();
    shaderProgram->bind();

    glBindTexture(GL_TEXTURE_1D, audioLeftTexture);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage1D(GL_TEXTURE_1D, 0, GL_R32F, count / typeSize, 0, GL_RED, type, left);

    glBindTexture(GL_TEXTURE_1D, audioRightTexture);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage1D(GL_TEXTURE_1D, 0, GL_R32F, count / typeSize, 0, GL_RED, type, right);

    shaderProgram->release();
    shaderProgramMutex.unlock();
    if(left != data.data())
        delete[] left;
    if(right != data.data())
        delete[] right;
}

void Renderer::onMessageLogged(QOpenGLDebugMessage message){
    qDebug() << message;
}
<commit_msg>Slightly modified logger<commit_after>#include "Renderer.hpp"

#include <QOpenGLShader>
#include <QMessageBox>
#include <typeinfo>
#include <QCoreApplication>
#include <QPainter>
#include <QThread>

#include <QAudioDeviceInfo>

static GLfloat vertices[] = {
    1, 1,0,  1,-1,0, -1,1,0,
    1,-1,0, -1,-1,0, -1,1,0
};
static GLfloat uvs[] = {
    1,0, 1,1, 0,0,
    1,1, 0,1, 0,0
};

const char * Renderer::defaultVertexShader =
        "#version 330 core\n"
        "\n"
        "in vec3 position;\n"
        "in vec2 texCoord;\n"
        "\n"
        "uniform int _time;\n"
        "\n"
        "out vec2  uv;\n"
        "out float time;\n"
        "\n"
        "void main(){\n"
        "   time = float(_time);\n"
        "   gl_Position = vec4(position, 1);\n"
        "   uv = texCoord;\n"
        "}";

const char * Renderer::defaultFragmentShader =
        "#version 330 core\n"
        "\n"
        "out vec4 color;\n"
        "\n"
        "uniform in vec2  uv;\n"
        "uniform in float time;\n"
        "\n"
        "void main(){\n"
        "     color = vec4(cos(uv.x * 5 - time / 1000) / 2 + .5, 0, sin(uv.x * 5 - time / 1000) / 2 + .5, 1);\n"
        "}";

const char * Renderer::mandelbrotFragmentShader =
        "#version 330 core\n"
        "\n"
        "in vec2  uv;\n"
        "in float time;\n"
        "\n"
        "vec2 center = vec2(0,0);\n"
        "float scale = 4;\n"
        "int iter = 10;\n"
        "\n"
        "void main() {\n"
        "    gl_FragColor = vec4(0,0,0,1);\n"
        "    vec2 z, c;\n"
        " \n"
        "    c.x = 1.3333 * (uv.x - 0.5) * scale - center.x;\n"
        "    c.y = (uv.y - 0.5) * scale - center.y;\n"
        " \n"
        "    int i;\n"
        "    z = c;\n"
        "    for(i=0; i < iter; ++i) {\n"
        "        float x = (z.x * z.x - z.y * z.y) + c.x;\n"
        "        float y = (z.y * z.x + z.x * z.y) + c.y;\n"
        " \n"
        "        if((x * x + y * y) > 4.0)\n"
        "            break;\n"
        "        z.x = x;\n"
        "        z.y = y;\n"
        "    }\n"
        "    if(i < iter)\n"
        "        gl_FragColor.r = float(i)/10.0;\n"
        "}\n";

const char * Renderer::juliaFragmentShader =
        "#version 330 core\n"
        "\n"
        "in vec2  uv;\n"
        "in float time;\n"
        "uniform in float[10] audioData;\n"
        "\n"
        "//uniform highp vec2 c = vec2(.1,.1);\n"
        "int iter = 100;\n"
        "out vec4 color;\n"
        "\n"
        "void main() {\n"
//        "   float audioVal = audioData[int(uv.x * 1764)];\n"
        "   float y = 1 - uv.y * 2;"
        "   if(y < max(0, audioVal) && y > min(0, audioVal)){\n"
        "       color = vec4(1.0);\n"
        "       return;\n"
        "   }\n"
        "    vec2 c = vec2(sin(time / 2000.0), cos(time / 1500.0));\n"
        "    color = vec4(0,audioData[int(uv.x * 1764)],0,1);\n"
        "    vec2 z;\n"
        " \n"
        "    z.x = 3.0 * (uv.x - 0.5);\n"
        "    z.y = 2.0 * (uv.y - 0.5);\n"
        " \n"
        "    int i;\n"
        "    for(i=0; i < iter; ++i) {\n"
        "        float x = (z.x * z.x - z.y * z.y) + c.x;\n"
        "        float y = (z.y * z.x + z.x * z.y) + c.y;\n"
        " \n"
        "        if((x * x + y * y) > 4.0)\n"
        "            break;\n"
        "        z.x = x;\n"
        "        z.y = y;\n"
        "    }\n"
        "    if(i < iter){\n"
        "        color.b = float(i) * 5.0 / float(iter);\n"
        "        color.g = (float(i) * 5.0 / float(iter) - .3) / .7;\n"
        "        color.r = (float(i) * 5.0 / float(iter) - .7) / .3;\n"
        "    }\n"
        "}\n";

Renderer::Renderer(QWindow *parent) : Renderer::Renderer("new", defaultFragmentShader, parent){ }

Renderer::Renderer(const QString &filename, const QString &instructions, QWindow *parent) :
    QWindow(parent),
    clearColor(Qt::black),
    context(0), device(0),
    time(0),
    pendingUpdate(false),
    vertexBuffer(0), uvBuffer(0), audioLeftTexture(0), audioRightTexture(0),
    vertexAttr(0), uvAttr(0), timeUniform(0),
    shaderProgram(0),
    fragmentSource(instructions)
{

    setTitle(filename);

    m_logger = new QOpenGLDebugLogger( this );

    connect(m_logger, SIGNAL(messageLogged(QOpenGLDebugMessage)),
             this, SLOT(onMessageLogged(QOpenGLDebugMessage)),
             Qt::DirectConnection );

    time = new QTime();
    time->start();

    setSurfaceType(QWindow::OpenGLSurface);

    audio = new AudioInputProcessor(this);
    connect(audio, SIGNAL(processData(QByteArray)), this, SLOT(updateAudioData(QByteArray)));
    audio->start();

    QSurfaceFormat format;
    format.setMajorVersion(3);
    format.setMinorVersion(3);
    format.setSamples(4);
    format.setProfile(QSurfaceFormat::CoreProfile);
    setFormat(format);

    resize(800, 600);
    show();
}

Renderer::~Renderer(){
    glDeleteBuffers(1, &vertexBuffer);
    glDeleteBuffers(1, &uvBuffer);
    glDeleteTextures(1, &audioLeftTexture);
    glDeleteTextures(1, &audioRightTexture);
}

bool Renderer::init(){
    glDeleteBuffers(1, &vertexBuffer);
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glDeleteBuffers(1, &uvBuffer);
    glGenBuffers(1, &uvBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);

    glEnable(GL_TEXTURE_1D);

    glDeleteTextures(1, &audioLeftTexture);
    glGenTextures(1, &audioLeftTexture);
    glDeleteTextures(1, &audioRightTexture);
    glGenTextures(1, &audioRightTexture);

    glClearColor(0,0,.3,1);
    return initShaders(fragmentSource);
}

bool Renderer::initShaders(const QString &fragmentShader){
    QOpenGLShaderProgram *newShaderProgram = new QOpenGLShaderProgram(this);
    if(!newShaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, defaultVertexShader)){
        int infologLength;
        glGetShaderiv(newShaderProgram->programId(), GL_INFO_LOG_LENGTH, &infologLength);
        char *infoLog = new char[infologLength + 1];
        glGetShaderInfoLog(newShaderProgram->programId(), infologLength + 1, &infologLength, infoLog);

        qDebug() << infoLog;

        delete[] infoLog;

//        qDebug() << newShaderProgram->log();
        delete newShaderProgram;
        return false;
    }
    if(!newShaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShader)){
        qDebug() << newShaderProgram->log();
        delete newShaderProgram;
        return false;
    }
    if(!newShaderProgram->link()){
        qDebug() << newShaderProgram->log();
        delete newShaderProgram;
        return false;
    }
    shaderProgramMutex.lock();
        if(shaderProgram)
            delete shaderProgram;
        shaderProgram = newShaderProgram;
        vertexAttr   = shaderProgram->attributeLocation("position");
        uvAttr       = shaderProgram->attributeLocation("texCoord");
        timeUniform  = shaderProgram->uniformLocation("_time");
        audioLeftUniform = shaderProgram->uniformLocation("audioDataLeft");
        audioRightUniform = shaderProgram->uniformLocation("audioDataRight");
        shaderProgram->setUniformValue(audioLeftUniform, 0);
        shaderProgram->setUniformValue(audioRightUniform, 0);
        fragmentSource = fragmentShader;
    shaderProgramMutex.unlock();

//    qDebug() << "vertexAttr" << vertexAttr;
//    qDebug() << "uvAttr" << uvAttr;
//    qDebug() << "timeUniform" << timeUniform;
//    qDebug() << "audioUniform" << audioUniform;
    return true;
}

void Renderer::render(){
    if(!device)
        device = new QOpenGLPaintDevice();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    device->setSize(size());
    QPainter painter;
    //QPainter painter(device);
    render(&painter);
}

void Renderer::render(QPainter *){
    const qreal retinaScale = devicePixelRatio();
    glViewport(0, 0, width() * retinaScale, height() * retinaScale);

    glClear(GL_COLOR_BUFFER_BIT);

    shaderProgramMutex.lock();
    shaderProgram->bind();

    shaderProgram->setUniformValue(timeUniform, time->elapsed());

    glEnableVertexAttribArray(vertexAttr);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glVertexAttribPointer(vertexAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(uvAttr);
    glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
    glVertexAttribPointer(uvAttr, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices));

    glDisableVertexAttribArray(vertexAttr);
    glDisableVertexAttribArray(uvAttr);

    shaderProgram->release();
    shaderProgramMutex.unlock();
}

void Renderer::renderLater(){
    if(!pendingUpdate){
        QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
        pendingUpdate = true;
    }
}

void Renderer::renderNow(){
    pendingUpdate = false;

    if(!isExposed())
        return;

    bool needsInit = false;

    if(!context){
        context = new QOpenGLContext(this);
        context->setFormat(requestedFormat());
        context->create();

        needsInit = true;
    }

    context->makeCurrent(this);

    if(needsInit){
        initializeOpenGLFunctions();
        init();
    }

    if ( m_logger->initialize() ) {
        m_logger->startLogging( QOpenGLDebugLogger::SynchronousLogging );
        m_logger->enableMessages();
    }

    if(!shaderProgram)
        initShaders(fragmentSource);

    if(shaderProgram)
        render();
    context->swapBuffers(this);

    renderLater();
}

bool Renderer::event(QEvent *event){
    switch(event->type()){
    case QEvent::UpdateRequest:
        QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
        renderNow();
        return true;
    case QEvent::Close:
        emit doneSignal(QtGlException());
        // No fall throu?
        return true;
    default:
        return QWindow::event(event);
    }
}

void Renderer::exposeEvent(QExposeEvent *){
    if(isExposed())
        renderNow();
}

bool Renderer::updateCode(const QString &filename, const QString &code){
    if(!initShaders(code))
        return false;
    setTitle(filename);
    return true;
}

void Renderer::updateAudioData(QByteArray data){
    if(!shaderProgram)
        return;
    GLenum type, internalType;
    char typeSize;
    switch(audio->format().sampleType() + audio->format().sampleSize()){
        case  8: case 10: type = GL_UNSIGNED_BYTE;  internalType = GL_R8UI;  typeSize = 1; break;
        case  9:          type = GL_BYTE;           internalType = GL_R8I;   typeSize = 1; break;
        case 16: case 18: type = GL_UNSIGNED_SHORT; internalType = GL_R16UI; typeSize = 2; break;
        case 17:          type = GL_SHORT;          internalType = GL_R16I;  typeSize = 2; break;
        case 32: case 34: type = GL_UNSIGNED_INT;   internalType = GL_R32UI; typeSize = 4; break;
        case 33:          type = GL_INT;            internalType = GL_R32I;  typeSize = 4; break;
        case 35:          type = GL_FLOAT;          internalType = GL_R32F;  typeSize = 4; break;
        default: return;
    }
    char *left, *right;
    int count = data.size();
    if(audio->format().channelCount() == 2){
        count /= 2;
        left  = new char[count];
        right = new char[count];
        for(int i = 0; i < count; i += typeSize){
            for(int j = 0; j < typeSize; ++j){
                left [i+j] = data[i*2+j         ];
                right[i+j] = data[i*2+j+typeSize];
            }
        }
    }else
        left = right = data.data();

    shaderProgramMutex.lock();
    shaderProgram->bind();

    glBindTexture(GL_TEXTURE_1D, audioLeftTexture);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage1D(GL_TEXTURE_1D, 0, GL_R32F, count / typeSize, 0, GL_RED, type, left);

    glBindTexture(GL_TEXTURE_1D, audioRightTexture);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage1D(GL_TEXTURE_1D, 0, GL_R32F, count / typeSize, 0, GL_RED, type, right);

    shaderProgram->release();
    shaderProgramMutex.unlock();
    if(left != data.data())
        delete[] left;
    if(right != data.data())
        delete[] right;
}

void Renderer::onMessageLogged(QOpenGLDebugMessage message){
    qDebug() << message;
}
<|endoftext|>


<commit_before>#ifndef BLENDMODE_HPP_INCLUDED
#define BLENDMODE_HPP_INCLUDED

namespace gst
{
    // Supported blending techniques.
    enum class BlendMode {
        NONE,           // Blending disabled.
        ADDITIVE,       // Additive blending: out = src_frag + dst_frag.
        MULTIPLICATIVE, // Multiplicative blending: out = src_frag * dst_frag.
        INTERPOLATIVE   // Interpolative blending: out = (src_alpha * src_frag) + ((1 - src_alpha) * dst_frag).
    };
}

#endif
<commit_msg>fix redundant blend mode description<commit_after>#ifndef BLENDMODE_HPP_INCLUDED
#define BLENDMODE_HPP_INCLUDED

namespace gst
{
    // Supported blending techniques.
    enum class BlendMode {
        NONE,           // Blending disabled.
        ADDITIVE,       // out = src_frag + dst_frag.
        MULTIPLICATIVE, // out = src_frag * dst_frag.
        INTERPOLATIVE   // out = (src_alpha * src_frag) + ((1 - src_alpha) * dst_frag).
    };
}

#endif
<|endoftext|>


<commit_before>/**
 * blufs - a c++ luafilesystem library
 * --------------------------------------------------------
 * Copyright 2013-2015 Dmitry Ledentsov
 * [MIT License](http://opensource.org/licenses/MIT)
 *
 */

#include "blufs_lib.h"

#include <boost/filesystem.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/shared_ptr.hpp>

#include <lua.hpp>

#include <luabind/luabind.hpp>
#include <luabind/tag_function.hpp>
#include <luabind/operator.hpp>
#include <luabind/copy_policy.hpp>
#include <luabind/iterator_policy.hpp>
#include <boost/container/vector.hpp>
#include <string>
#include <stdexcept>
#include <iostream>

namespace blufs = boost::filesystem;

std::ostream& operator<<(std::ostream& s, blufs::path const& p) {
    return s << p.generic_string();
}

blufs::path const& itself(blufs::path const& self) { return self; }
blufs::path absolute_d(blufs::path const& self) { return blufs::absolute(self); }
blufs::path canonical_d(blufs::path const& self) { return blufs::canonical(self); }
void current_path_s(std::string const& p) { blufs::current_path(p); }

void register_blufs (lua_State* L) {
    using namespace luabind;
    using namespace blufs;

    open(L);

    module(L, "blufs")
    [
        class_<path, boost::shared_ptr<path>>("path")
            .def(constructor<std::string const&>())
            .def(constructor<>())
            .def(constructor<path const&>())
            .def(tostring(self))
            //.def(const_self + path())
            .def(const_self / path())
            //.def(const_self + std::string())
            .def(const_self / std::string())
            .property("generic_string", (std::string(path::*)()const) &path::generic_string)
            .property("root_path", &path::root_path)
            .property("root_name", &path::root_name)
            .property("root_directory", &path::root_directory)
            .property("relative_path", &path::relative_path)
            .property("parent_path", &path::parent_path)
            .property("filename", &path::filename)
            .property("stem", &path::stem)
            .property("extension", &path::extension)
            .property("empty", &path::empty)
            .property("exists", (bool(*)(path const&))exists)
            .property("absolute",absolute_d)
            .property("canonical", canonical_d)
            .def("parts", itself, copy(result) + return_stl_iterator)
            .def("absolute_to", (path(*)(path const&, path const&))absolute)
            .def("canonical_to", (path(*)(path const&, path const&))canonical)
            .def("clear", &path::clear)
            .def("make_preferred", &path::make_preferred)
            .def("remove_filename", &path::remove_filename)
            .def("replace_extension", &path::replace_extension)
            .def("compare", (int(path::*)(std::string const&)const) &path::compare)
            .def("compare", (int(path::*)(path const&)const) &path::compare)

            .enum_("file_type")
            [
                value("status_error", blufs::status_error),
                value("file_not_found", blufs::file_not_found),
                value("regular_file", blufs::regular_file),
                value("directory_file", blufs::directory_file),
                value("symlink_file", blufs::symlink_file),
                value("block_file", blufs::block_file),
                value("character_file", blufs::character_file),
                value("fifo_file", blufs::fifo_file),
                value("socket_file", blufs::socket_file),
                value("type_unknown", blufs::type_unknown)
            ]

            .enum_("perms")
            [
                value("no_perms", blufs::no_perms),
                value("owner_read", blufs::owner_read),
                value("owner_write", blufs::owner_write),
                value("owner_exe", blufs::owner_exe),
                value("owner_all", blufs::owner_all),
                value("group_read", blufs::group_read),
                value("group_write", blufs::group_write),
                value("group_exe", blufs::group_exe),
                value("group_all", blufs::group_all),
                value("others_read", blufs::others_read),
                value("others_write", blufs::others_write),
                value("others_exe", blufs::others_exe),
                value("others_all", blufs::others_all),
                value("all_all", blufs::all_all),
                value("set_uid_on_exe", blufs::set_uid_on_exe),
                value("set_gid_on_exe", blufs::set_gid_on_exe),
                value("sticky_bit", blufs::sticky_bit),
                value("perms_mask", blufs::perms_mask),
                value("perms_not_known", blufs::perms_not_known),
                value("add_perms", blufs::add_perms),
                value("remove_perms", blufs::remove_perms),
                value("symlink_perms", blufs::symlink_perms)
            ]
        ,

        class_<blufs::space_info>("space_info")
            .def_readwrite("capacity", &blufs::space_info::capacity)
            .def_readwrite("free", &blufs::space_info::free)
            .def_readwrite("available", &blufs::space_info::available)
        ,

        class_<blufs::copy_option>("copy_option")
            .enum_("values")
            [
                value("none", static_cast<int>(blufs::copy_option::none)),
                value("fail_if_exists", static_cast<int>(blufs::copy_option::fail_if_exists)),
                value("overwrite_if_exists", static_cast<int>(blufs::copy_option::overwrite_if_exists))
            ]
        ,

        class_<blufs::symlink_option>("symlink_option")
            .enum_("values")
            [
                value("none", static_cast<int>(blufs::symlink_option::none)),
                value("no_recurse", static_cast<int>(blufs::symlink_option::no_recurse)),
                value("recurse", static_cast<int>(blufs::symlink_option::recurse))
            ]
        ,

        def("current_path", (blufs::path(*)()) blufs::current_path),
        def("current_path", (void(*)(blufs::path const&)) blufs::current_path),
        def("current_path", current_path_s ),
        def("create_directories", (bool(*)(blufs::path const&)) blufs::create_directories),
        // def("create_directories", fs::create_directories_s),
        def("create_directory", (bool(*)(blufs::path const&)) blufs::create_directory),
        // def("create_directory", fs::create_directory_s),
        def("copy", (void(*)(blufs::path const&,blufs::path const&)) blufs::copy)
        // def("copy", fs::copy_s),
    ];
}
<commit_msg>equality operator<commit_after>/**
 * blufs - a c++ luafilesystem library
 * --------------------------------------------------------
 * Copyright 2013-2015 Dmitry Ledentsov
 * [MIT License](http://opensource.org/licenses/MIT)
 *
 */

#include "blufs_lib.h"

#include <boost/filesystem.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/shared_ptr.hpp>

#include <lua.hpp>

#include <luabind/luabind.hpp>
#include <luabind/tag_function.hpp>
#include <luabind/operator.hpp>
#include <luabind/copy_policy.hpp>
#include <luabind/iterator_policy.hpp>
#include <boost/container/vector.hpp>
#include <string>
#include <stdexcept>
#include <iostream>

namespace blufs = boost::filesystem;

std::ostream& operator<<(std::ostream& s, blufs::path const& p) {
    return s << p.generic_string();
}

blufs::path const& itself(blufs::path const& self) { return self; }
blufs::path absolute_d(blufs::path const& self) { return blufs::absolute(self); }
blufs::path canonical_d(blufs::path const& self) { return blufs::canonical(self); }
void current_path_s(std::string const& p) { blufs::current_path(p); }

void register_blufs (lua_State* L) {
    using namespace luabind;
    using namespace blufs;

    open(L);

    module(L, "blufs")
    [
        class_<path, boost::shared_ptr<path>>("path")
            .def(constructor<std::string const&>())
            .def(constructor<>())
            .def(constructor<path const&>())
            .def(tostring(self))
            //.def(const_self + path())
            .def(const_self / path())
            //.def(const_self + std::string())
            .def(const_self / std::string())
            .def(const_self == std::string())
            .property("generic_string", (std::string(path::*)()const) &path::generic_string)
            .property("root_path", &path::root_path)
            .property("root_name", &path::root_name)
            .property("root_directory", &path::root_directory)
            .property("relative_path", &path::relative_path)
            .property("parent_path", &path::parent_path)
            .property("filename", &path::filename)
            .property("stem", &path::stem)
            .property("extension", &path::extension)
            .property("empty", &path::empty)
            .property("exists", (bool(*)(path const&))exists)
            .property("absolute",absolute_d)
            .property("canonical", canonical_d)
            .def("parts", itself, copy(result) + return_stl_iterator)
            .def("absolute_to", (path(*)(path const&, path const&))absolute)
            .def("canonical_to", (path(*)(path const&, path const&))canonical)
            .def("clear", &path::clear)
            .def("make_preferred", &path::make_preferred)
            .def("remove_filename", &path::remove_filename)
            .def("replace_extension", &path::replace_extension)
            .def("compare", (int(path::*)(std::string const&)const) &path::compare)
            .def("compare", (int(path::*)(path const&)const) &path::compare)

            .enum_("file_type")
            [
                value("status_error", blufs::status_error),
                value("file_not_found", blufs::file_not_found),
                value("regular_file", blufs::regular_file),
                value("directory_file", blufs::directory_file),
                value("symlink_file", blufs::symlink_file),
                value("block_file", blufs::block_file),
                value("character_file", blufs::character_file),
                value("fifo_file", blufs::fifo_file),
                value("socket_file", blufs::socket_file),
                value("type_unknown", blufs::type_unknown)
            ]

            .enum_("perms")
            [
                value("no_perms", blufs::no_perms),
                value("owner_read", blufs::owner_read),
                value("owner_write", blufs::owner_write),
                value("owner_exe", blufs::owner_exe),
                value("owner_all", blufs::owner_all),
                value("group_read", blufs::group_read),
                value("group_write", blufs::group_write),
                value("group_exe", blufs::group_exe),
                value("group_all", blufs::group_all),
                value("others_read", blufs::others_read),
                value("others_write", blufs::others_write),
                value("others_exe", blufs::others_exe),
                value("others_all", blufs::others_all),
                value("all_all", blufs::all_all),
                value("set_uid_on_exe", blufs::set_uid_on_exe),
                value("set_gid_on_exe", blufs::set_gid_on_exe),
                value("sticky_bit", blufs::sticky_bit),
                value("perms_mask", blufs::perms_mask),
                value("perms_not_known", blufs::perms_not_known),
                value("add_perms", blufs::add_perms),
                value("remove_perms", blufs::remove_perms),
                value("symlink_perms", blufs::symlink_perms)
            ]
        ,

        class_<blufs::space_info>("space_info")
            .def_readwrite("capacity", &blufs::space_info::capacity)
            .def_readwrite("free", &blufs::space_info::free)
            .def_readwrite("available", &blufs::space_info::available)
        ,

        class_<blufs::copy_option>("copy_option")
            .enum_("values")
            [
                value("none", static_cast<int>(blufs::copy_option::none)),
                value("fail_if_exists", static_cast<int>(blufs::copy_option::fail_if_exists)),
                value("overwrite_if_exists", static_cast<int>(blufs::copy_option::overwrite_if_exists))
            ]
        ,

        class_<blufs::symlink_option>("symlink_option")
            .enum_("values")
            [
                value("none", static_cast<int>(blufs::symlink_option::none)),
                value("no_recurse", static_cast<int>(blufs::symlink_option::no_recurse)),
                value("recurse", static_cast<int>(blufs::symlink_option::recurse))
            ]
        ,

        def("current_path", (blufs::path(*)()) blufs::current_path),
        def("current_path", (void(*)(blufs::path const&)) blufs::current_path),
        def("current_path", current_path_s ),
        def("create_directories", (bool(*)(blufs::path const&)) blufs::create_directories),
        // def("create_directories", fs::create_directories_s),
        def("create_directory", (bool(*)(blufs::path const&)) blufs::create_directory),
        // def("create_directory", fs::create_directory_s),
        def("copy", (void(*)(blufs::path const&,blufs::path const&)) blufs::copy)
        // def("copy", fs::copy_s),
    ];
}
<|endoftext|>