<commit_before>#include "command.h"
#include "ptr.h"
#include "progressbar.h"
#include "thread/exec.h"
#include "thread/queue.h"
#include "image/copy.h"
#include "image/loop.h"
#include "image/adapter/subset.h"
#include "image/buffer.h"
#include "image/buffer_preload.h"
#include "image/buffer_scratch.h"
#include "image/voxel.h"
#include "dwi/gradient.h"
#include "math/SH.h"
#include "dwi/directions/predefined.h"
#include "math/constrained_least_squares.h"

using namespace MR;
using namespace App;

void usage () {
  AUTHOR = "Ben Jeurissen (ben.jeurissen@gmail.com)";

  DESCRIPTION
    + "Multi-shell, multi-tissue CSD";

  REFERENCES = "Jeurissen, B.; Tournier, J.-D.; Dhollander, T.; Connelly, A.; Sijbers, J."
    "Multi-tissue constrained spherical deconvolution for improved analysis of multi-shell diffusion MRI data"
    "NeuroImage, in press, DOI: 10.1016/j.neuroimage.2014.07.061";

  ARGUMENTS
    + Argument ("dwi",
      "the input diffusion-weighted image.").type_image_in()
    + Argument ("response odf",
      "the input tissue response and the output ODF image.").allow_multiple();

  OPTIONS
    + Option ("mask",
        "only perform computation within the specified binary brain mask image.")
    + Argument ("image").type_image_in ()
    + Option ("lmax","")
    + Argument ("order").type_integer (0, 8, 30).allow_multiple();
}

typedef double value_type;
typedef Image::BufferPreload<value_type> InputBufferType;
typedef Image::Buffer<bool> MaskBufferType;
typedef Image::Buffer<value_type> OutputBufferType;
typedef Image::BufferScratch<value_type> BufferScratchType;

class Shared {
  public:
    Shared (std::vector<size_t>& lmax_, std::vector<Math::Matrix<value_type> >& response_, Math::Matrix<value_type>& grad_) :
      lmax(lmax_),
      response(response_),
      grad(grad_)
  {
    /* create forward convolution matrix */
    DWI::Shells shells (grad);
    size_t nbvals = shells.count();
    size_t nsamples = grad.rows();
    size_t ntissues = lmax.size();
    size_t nparams = 0;
    size_t maxlmax = 0;
    for(std::vector<size_t>::iterator it = lmax.begin(); it != lmax.end(); ++it) {
      nparams+=Math::SH::NforL(*it);
      if (*it > maxlmax)
        maxlmax = *it;
    }
    Math::Matrix<value_type> C (nsamples,nparams);

    std::vector<size_t> dwilist;
    for (size_t i = 0; i < nsamples; i++)
      dwilist.push_back(i);
    Math::Matrix<value_type> directions; DWI::gen_direction_matrix (directions, grad, dwilist);
    Math::Matrix<value_type> SHT; Math::SH::init_transform (SHT, directions, maxlmax);
    for (size_t i = 0; i < SHT.rows(); i++)
      for (size_t j = 0; j < SHT.columns(); j++)
        if (isnan(SHT(i,j)))
          SHT(i,j) = 0;

    Math::Matrix<value_type> delta(1,2);
    Math::Matrix<value_type> DSH__; Math::SH::init_transform (DSH__, delta, maxlmax);
    Math::Vector<value_type> DSH_ = DSH__.row(0);
    Math::Vector<value_type> DSH(maxlmax/2+1);
    size_t j = 0;
    for (size_t i = 0; i < DSH_.size(); i++)
      if (DSH_[i] != 0) {
        DSH[j] = DSH_[i];
        j++;
      }

    size_t pbegin = 0;
    for (size_t tissue_idx = 0; tissue_idx < ntissues; tissue_idx++) {
      size_t tissue_lmax = lmax[tissue_idx];
      size_t tissue_n = Math::SH::NforL(tissue_lmax);
      size_t tissue_nmzero = tissue_lmax/2+1;
      for (size_t shell_idx = 0; shell_idx < nbvals; shell_idx++) {
        Math::Vector<value_type> response_ = response[tissue_idx].row(shell_idx);
        Math::Vector<value_type> response__(response_);
        response__/=DSH.sub(0,tissue_nmzero);
        Math::Vector<value_type> fconv(tissue_n);
        int li = 0; int mi = 0;
        for (int l = 0; l <= int(tissue_lmax); l+=2) {
          for (int m = -l; m <= l; m++) {
            fconv[mi] = response__[li];
            mi++;
          }
          li++;
        }
        std::vector<size_t> vols = shells[shell_idx].get_volumes();
        for (size_t idx = 0; idx < vols.size(); idx++) {
          Math::Vector<value_type> SHT_(SHT.row(vols[idx]).sub(0,tissue_n));
          Math::Vector<value_type> SHT__(SHT_);
          SHT__*=fconv;
          C.row(vols[idx]).sub(pbegin,pbegin+tissue_n) = SHT__;
        }
      }
      pbegin+=tissue_n;
    }

    /* create constraint matrix */
    std::vector<size_t> m(lmax.size());
    std::vector<size_t> n(lmax.size());
    size_t M = 0;
    size_t N = 0;

    Math::Matrix<value_type> HR_dirs;
    DWI::Directions::electrostatic_repulsion_300(HR_dirs);
    Math::Matrix<value_type> SHT300; Math::SH::init_transform (SHT300, HR_dirs, maxlmax);

    for(size_t i = 0; i < lmax.size(); i++) {
      if (lmax[i] > 0)
        m[i] = HR_dirs.rows();
      else
        m[i] = 1;
      M+=m[i];
      n[i] = Math::SH::NforL(lmax[i]);
      N+=n[i];
    }

    Math::Matrix<value_type> A (M,N);
    size_t b_m = 0; size_t b_n = 0;
    for(size_t i = 0; i < lmax.size(); i++) {
      A.sub(b_m,b_m+m[i],b_n,b_n+n[i]) = SHT300.sub(0,m[i],0,n[i]);
      b_m+=m[i]; b_n+=n[i];
    }
    //A.save("A.txt",16);
    //C.save("C.txt",16);
    problem = Math::ICLS::Problem<value_type> (C, A);
  };

  public:
    std::vector<size_t> lmax;
    std::vector<Math::Matrix<value_type> > response;
    Math::Matrix<value_type>& grad;
    Math::ICLS::Problem<value_type> problem;
};

class Processor {
  public:
    Processor (
        Shared& shared,
        InputBufferType::voxel_type& dwi_in_vox,
        Ptr<MaskBufferType::voxel_type>& mask_in_vox,
        BufferScratchType::voxel_type& fodf_out_vox)
      :
        shared (shared),
        solver (shared.problem),
        dwi_in(dwi_in_vox),
        mask_in(mask_in_vox),
        fodf_out(fodf_out_vox),
        dwi(dwi_in.dim(3)),
        fodf(fodf_out.dim(3))
  { }

    void operator () (const Image::Iterator& pos) {
      if (!load_data(pos))
        return;
      try {
        solver (fodf, dwi);
      }
      catch (Exception& E) {
        INFO ("failed to converge for voxel " + str(pos));
        //dwi.save("d" + str(pos) + ".txt",16);
      }
      write_back (pos);
    }

  private:
    const Shared& shared;
    Math::ICLS::Solver<value_type> solver;
    InputBufferType::voxel_type dwi_in;
    Ptr<MaskBufferType::voxel_type> mask_in;
    BufferScratchType::voxel_type fodf_out;
    Math::Vector<value_type> dwi;
    Math::Vector<value_type> fodf;

    bool load_data (const Image::Iterator& pos) {
      if (mask_in) {
        Image::assign_pos(pos) (*mask_in);
        if (!mask_in->value())
          return false;
      }
      Image::assign_pos(pos) (dwi_in);

      for (auto l = Image::Loop(3) (dwi_in); l; ++l) {
        dwi[dwi_in[3]] = dwi_in.value();
        if (!std::isfinite (dwi[dwi_in[3]]))
          return false;
        if (dwi[dwi_in[3]] < 0.0)
          dwi[dwi_in[3]] = 0.0;
      }
      return true;
    }

    void write_back (const Image::Iterator& pos) {
      Image::assign_pos(pos) (fodf_out);
      for (auto l = Image::Loop(3) (fodf_out); l; ++l)
        fodf_out.value() = fodf[fodf_out[3]];
    }

};

void run () {
  std::cout << argument.size() << std::endl;
  std::cout << (argument.size()-1)/2 << std::endl;

  /* input DWI image */
  InputBufferType dwi_in_buffer (argument[0], Image::Stride::contiguous_along_axis(3));
  InputBufferType::voxel_type dwi_in_vox (dwi_in_buffer);

  /* input response functions */
  std::vector<size_t> lmax_response;
  std::vector<Math::Matrix<value_type> > response;
  for (size_t i = 0; i < (argument.size()-1)/2; i++) {
    Math::Matrix<value_type> r(argument[i*2+1]);
    response.push_back(r);
    lmax_response.push_back((r.columns()-1)*2);
  }

  /* input mask image */
  Ptr<MaskBufferType> mask_in_buffer;
  Ptr<MaskBufferType::voxel_type> mask_in_vox;
  Options opt = get_options ("mask");
  if (opt.size()) {
    mask_in_buffer = new MaskBufferType (opt[0][0]);
    Image::check_dimensions (*mask_in_buffer, dwi_in_buffer, 0, 3);
    mask_in_vox = new MaskBufferType::voxel_type (*mask_in_buffer);
  }

  /* gradient directions from header */
  auto grad = DWI::get_valid_DW_scheme<value_type> (dwi_in_buffer);

  /* for now,  lmaxes are taken from the response files, still take into account lmax option */
  /*int lmax_ = 8;
  opt = get_options ("lmax");
  if (opt.size())
    lmax_ = opt[0][0];
  std::vector<size_t> lmax;
  lmax.push_back(0);
  lmax.push_back(0);
  lmax.push_back(lmax_);*/
  std::vector<size_t> lmax = lmax_response;

  /* make sure responses abide to the lmaxes */
  size_t sumnparams = 0;
  std::vector<size_t> nparams;
  for(size_t i = 0; i < lmax.size(); i++) {
    nparams.push_back(Math::SH::NforL(lmax[i]));
    sumnparams+=Math::SH::NforL(lmax[i]);
    response[i].resize(response[i].rows(),lmax[i]/2+1);
  }

  /* precalculate everything */
  Shared shared (lmax,response,grad);

  /* create scratch buffer for output */
  Image::Header header (dwi_in_buffer);
  header.set_ndim (4);
  header.dim (3) = sumnparams;
  header.datatype() = DataType::Float32;
  BufferScratchType scratch_buffer (header);
  auto scratch_vox = scratch_buffer.voxel();

  /* do the actual work */
  Image::ThreadedLoop loop ("working...", dwi_in_vox, 1, 0, 3);
  Processor processor (shared, dwi_in_vox, mask_in_vox, scratch_vox);
  loop.run (processor);

  /* copy from scratch buffer to output files */
  std::vector<ssize_t> from (4, 0);
  std::vector<ssize_t> to = { scratch_vox.dim(0), scratch_vox.dim(1), scratch_vox.dim(2), 0 };

   for (size_t i = 0; i < (argument.size()-1)/2; ++i) {
    header.dim (3) = nparams[i];
    OutputBufferType out_buffer (argument[(i+1)*2], header);
    to[3] = nparams[i];
    Image::copy (Image::Adapter::Subset<decltype(scratch_vox)> (scratch_vox, from, to), out_buffer.voxel());
    from[3]+= nparams[i];
  }

}
<commit_msg>Cleaned up the msmt-csd command interface.<commit_after>#include "command.h"
#include "ptr.h"
#include "progressbar.h"
#include "thread/exec.h"
#include "thread/queue.h"
#include "image/copy.h"
#include "image/loop.h"
#include "image/adapter/subset.h"
#include "image/buffer.h"
#include "image/buffer_preload.h"
#include "image/buffer_scratch.h"
#include "image/voxel.h"
#include "dwi/gradient.h"
#include "math/SH.h"
#include "dwi/directions/predefined.h"
#include "math/constrained_least_squares.h"

using namespace MR;
using namespace App;

void usage () {
  AUTHOR = "Ben Jeurissen (ben.jeurissen@gmail.com)";

  DESCRIPTION
    + "Multi-shell, multi-tissue CSD";

  REFERENCES = "Jeurissen, B; Tournier, J-D; Dhollander, T; Connelly, A; Sijbers, J "
    "Multi-tissue constrained spherical deconvolution for improved analysis of multi-shell diffusion MRI data "
    "NeuroImage, in press, DOI: 10.1016/j.neuroimage.2014.07.061";

  ARGUMENTS
    + Argument ("dwi",
      "the input diffusion-weighted image.").type_image_in()
    + Argument ("response odf",
      "the input tissue response and the output ODF image.").allow_multiple();

  OPTIONS
    + Option ("mask",
        "only perform computation within the specified binary brain mask image.")
    + Argument ("image").type_image_in ()
    + Option ("lmax","")
    + Argument ("order").type_sequence_int()
    + Option ("directions",
                "specify the directions over which to apply the non-negativity constraint "
                "(by default, the built-in 300 direction set is used). These should be "
                "supplied as a text file containing the [ az el ] pairs for the directions.")
    + Argument ("file").type_file_in()
    + DWI::GradOption;
}

typedef double value_type;
typedef Image::BufferPreload<value_type> InputBufferType;
typedef Image::Buffer<bool> MaskBufferType;
typedef Image::Buffer<value_type> OutputBufferType;
typedef Image::BufferScratch<value_type> BufferScratchType;

class Shared {
  public:
    Shared (std::vector<int>& lmax_, std::vector<Math::Matrix<value_type> >& response_, Math::Matrix<value_type>& grad_) :
      lmax(lmax_),
      response(response_),
      grad(grad_)
  {
    /* create forward convolution matrix */
    DWI::Shells shells (grad);
    size_t nbvals = shells.count();
    size_t nsamples = grad.rows();
    size_t ntissues = lmax.size();
    size_t nparams = 0;
    int maxlmax = 0;
    for(size_t i = 0; i < lmax.size(); i++) {
      nparams+=Math::SH::NforL(lmax[i]);
      if (lmax[i] > maxlmax)
        maxlmax = lmax[i];
    }
    Math::Matrix<value_type> C (nsamples,nparams);

    std::vector<size_t> dwilist;
    for (size_t i = 0; i < nsamples; i++)
      dwilist.push_back(i);
    Math::Matrix<value_type> directions; DWI::gen_direction_matrix (directions, grad, dwilist);
    Math::Matrix<value_type> SHT; Math::SH::init_transform (SHT, directions, maxlmax);
    for (size_t i = 0; i < SHT.rows(); i++)
      for (size_t j = 0; j < SHT.columns(); j++)
        if (isnan(SHT(i,j)))
          SHT(i,j) = 0;

    Math::Matrix<value_type> delta(1,2);
    Math::Matrix<value_type> DSH__; Math::SH::init_transform (DSH__, delta, maxlmax);
    Math::Vector<value_type> DSH_ = DSH__.row(0);
    Math::Vector<value_type> DSH(maxlmax/2+1);
    size_t j = 0;
    for (size_t i = 0; i < DSH_.size(); i++)
      if (DSH_[i] != 0) {
        DSH[j] = DSH_[i];
        j++;
      }

    size_t pbegin = 0;
    for (size_t tissue_idx = 0; tissue_idx < ntissues; tissue_idx++) {
      size_t tissue_lmax = lmax[tissue_idx];
      size_t tissue_n = Math::SH::NforL(tissue_lmax);
      size_t tissue_nmzero = tissue_lmax/2+1;
      for (size_t shell_idx = 0; shell_idx < nbvals; shell_idx++) {
        Math::Vector<value_type> response_ = response[tissue_idx].row(shell_idx);
        Math::Vector<value_type> response__(response_);
        response__/=DSH.sub(0,tissue_nmzero);
        Math::Vector<value_type> fconv(tissue_n);
        int li = 0; int mi = 0;
        for (int l = 0; l <= int(tissue_lmax); l+=2) {
          for (int m = -l; m <= l; m++) {
            fconv[mi] = response__[li];
            mi++;
          }
          li++;
        }
        std::vector<size_t> vols = shells[shell_idx].get_volumes();
        for (size_t idx = 0; idx < vols.size(); idx++) {
          Math::Vector<value_type> SHT_(SHT.row(vols[idx]).sub(0,tissue_n));
          Math::Vector<value_type> SHT__(SHT_);
          SHT__*=fconv;
          C.row(vols[idx]).sub(pbegin,pbegin+tissue_n) = SHT__;
        }
      }
      pbegin+=tissue_n;
    }

    /* create constraint matrix */
    std::vector<size_t> m(lmax.size());
    std::vector<size_t> n(lmax.size());
    size_t M = 0;
    size_t N = 0;

    Math::Matrix<value_type> HR_dirs;
    DWI::Directions::electrostatic_repulsion_300(HR_dirs);
    Math::Matrix<value_type> SHT300; Math::SH::init_transform (SHT300, HR_dirs, maxlmax);

    for(size_t i = 0; i < lmax.size(); i++) {
      if (lmax[i] > 0)
        m[i] = HR_dirs.rows();
      else
        m[i] = 1;
      M+=m[i];
      n[i] = Math::SH::NforL(lmax[i]);
      N+=n[i];
    }

    Math::Matrix<value_type> A (M,N);
    size_t b_m = 0; size_t b_n = 0;
    for(size_t i = 0; i < lmax.size(); i++) {
      A.sub(b_m,b_m+m[i],b_n,b_n+n[i]) = SHT300.sub(0,m[i],0,n[i]);
      b_m+=m[i]; b_n+=n[i];
    }
    //A.save("A.txt",16);
    //C.save("C.txt",16);
    problem = Math::ICLS::Problem<value_type> (C, A);
  };

  public:
    std::vector<int> lmax;
    std::vector<Math::Matrix<value_type> > response;
    Math::Matrix<value_type>& grad;
    Math::ICLS::Problem<value_type> problem;
};

class Processor {
  public:
    Processor (
        Shared& shared,
        InputBufferType::voxel_type& dwi_in_vox,
        Ptr<MaskBufferType::voxel_type>& mask_in_vox,
        BufferScratchType::voxel_type& fodf_out_vox)
      :
        shared (shared),
        solver (shared.problem),
        dwi_in(dwi_in_vox),
        mask_in(mask_in_vox),
        fodf_out(fodf_out_vox),
        dwi(dwi_in.dim(3)),
        fodf(fodf_out.dim(3))
  { }

    void operator () (const Image::Iterator& pos) {
      if (!load_data(pos))
        return;
      try {
        solver (fodf, dwi);
      }
      catch (Exception& E) {
        INFO ("failed to converge for voxel " + str(pos));
        //dwi.save("d" + str(pos) + ".txt",16);
      }
      write_back (pos);
    }

  private:
    const Shared& shared;
    Math::ICLS::Solver<value_type> solver;
    InputBufferType::voxel_type dwi_in;
    Ptr<MaskBufferType::voxel_type> mask_in;
    BufferScratchType::voxel_type fodf_out;
    Math::Vector<value_type> dwi;
    Math::Vector<value_type> fodf;

    bool load_data (const Image::Iterator& pos) {
      if (mask_in) {
        Image::assign_pos(pos) (*mask_in);
        if (!mask_in->value())
          return false;
      }
      Image::assign_pos(pos) (dwi_in);

      for (auto l = Image::Loop(3) (dwi_in); l; ++l) {
        dwi[dwi_in[3]] = dwi_in.value();
        if (!std::isfinite (dwi[dwi_in[3]]))
          return false;
        if (dwi[dwi_in[3]] < 0.0)
          dwi[dwi_in[3]] = 0.0;
      }
      return true;
    }

    void write_back (const Image::Iterator& pos) {
      Image::assign_pos(pos) (fodf_out);
      for (auto l = Image::Loop(3) (fodf_out); l; ++l)
        fodf_out.value() = fodf[fodf_out[3]];
    }

};

void run () {
  /* input DWI image */
  InputBufferType dwi_in_buffer (argument[0], Image::Stride::contiguous_along_axis(3));
  InputBufferType::voxel_type dwi_in_vox (dwi_in_buffer);

  /* input response functions */
  std::vector<int> lmax;
  std::vector<Math::Matrix<value_type> > response;
  for (size_t i = 0; i < (argument.size()-1)/2; i++) {
    Math::Matrix<value_type> r(argument[i*2+1]);
    response.push_back(r);
    lmax.push_back((r.columns()-1)*2);
  }

  /* input mask image */
  Ptr<MaskBufferType> mask_in_buffer;
  Ptr<MaskBufferType::voxel_type> mask_in_vox;
  Options opt = get_options ("mask");
  if (opt.size()) {
    mask_in_buffer = new MaskBufferType (opt[0][0]);
    Image::check_dimensions (*mask_in_buffer, dwi_in_buffer, 0, 3);
    mask_in_vox = new MaskBufferType::voxel_type (*mask_in_buffer);
  }

  /* gradient directions from header */
  auto grad = DWI::get_valid_DW_scheme<value_type> (dwi_in_buffer);

  /* lmax */
  opt = get_options ("lmax");
  if (opt.size()) {
    std::vector<int> lmax_in = opt[0][0];
    if (lmax_in.size() == lmax.size()) {
      for (size_t i = 0; i<lmax_in.size(); i++) {
        lmax[i] = lmax_in[i];
      }
    } else {
      throw Exception ("number of lmaxes does not match number of response functions");
    }
  }

  /* make sure responses abide to the lmaxes */
  size_t sumnparams = 0;
  std::vector<size_t> nparams;
  for(size_t i = 0; i < lmax.size(); i++) {
    nparams.push_back(Math::SH::NforL(lmax[i]));
    sumnparams+=Math::SH::NforL(lmax[i]);
    response[i].resize(response[i].rows(),lmax[i]/2+1);
  }

  /* precalculate everything */
  Shared shared (lmax,response,grad);

  /* create scratch buffer for output */
  Image::Header header (dwi_in_buffer);
  header.set_ndim (4);
  header.dim (3) = sumnparams;
  header.datatype() = DataType::Float32;
  BufferScratchType scratch_buffer (header);
  auto scratch_vox = scratch_buffer.voxel();

  /* do the actual work */
  Image::ThreadedLoop loop ("working...", dwi_in_vox, 1, 0, 3);
  Processor processor (shared, dwi_in_vox, mask_in_vox, scratch_vox);
  loop.run (processor);

  /* copy from scratch buffer to output buffers */
  std::vector<ssize_t> from (4, 0);
  std::vector<ssize_t> to = { scratch_vox.dim(0), scratch_vox.dim(1), scratch_vox.dim(2), 0 };

   for (size_t i = 0; i < (argument.size()-1)/2; ++i) {
    header.dim (3) = nparams[i];
    OutputBufferType out_buffer (argument[(i+1)*2], header);
    to[3] = nparams[i];
    Image::copy (Image::Adapter::Subset<decltype(scratch_vox)> (scratch_vox, from, to), out_buffer.voxel());
    from[3]+= nparams[i];
  }

}
<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#include <Param.hpp>
#include <common/dispatch.hpp>
#include <common/half.hpp>
#include <err_cpu.hpp>
#include <kernel/random_engine_mersenne.hpp>
#include <kernel/random_engine_philox.hpp>
#include <kernel/random_engine_threefry.hpp>
#include <types.hpp>

#include <algorithm>
#include <cstring>

using std::array;
using std::memcpy;

namespace cpu {
namespace kernel {
// Utils
static const double PI_VAL =
    3.1415926535897932384626433832795028841971693993751058209749445923078164;

// Conversion to half adapted from Random123
#define USHORTMAX 0xffff
#define HALF_FACTOR ((1.0f) / (USHORTMAX + (1.0f)))
#define HALF_HALF_FACTOR ((0.5f) * HALF_FACTOR)

// Conversion to floats adapted from Random123
#define UINTMAX 0xffffffff
#define FLT_FACTOR ((1.0f) / (UINTMAX + (1.0f)))
#define HALF_FLT_FACTOR ((0.5f) * FLT_FACTOR)

#define UINTLMAX 0xffffffffffffffff
#define DBL_FACTOR ((1.0) / (UINTLMAX + (1.0)))
#define HALF_DBL_FACTOR ((0.5) * DBL_FACTOR)

template<typename T, typename To = T>
To transform(uint *val, int index) {
    T *oval = (T *)val;
    return oval[index];
}

template<>
char transform<char>(uint *val, int index) {
    char v = val[index >> 2] >> (8 << (index & 3));
    v      = (v & 0x1) ? 1 : 0;
    return v;
}

template<>
uchar transform<uchar>(uint *val, int index) {
    uchar v = val[index >> 2] >> (index << 3);
    return v;
}

template<>
ushort transform<ushort>(uint *val, int index) {
    ushort v = val[index >> 1] >> (16 << (index & 1));
    return v;
}

template<>
short transform<short>(uint *val, int index) {
    return transform<ushort>(val, index);
}

template<>
uint transform<uint>(uint *val, int index) {
    return val[index];
}

template<>
int transform<int>(uint *val, int index) {
    return transform<uint>(val, index);
}

template<>
uintl transform<uintl>(uint *val, int index) {
    uintl v = (((uintl)val[index << 1]) << 32) | ((uintl)val[(index << 1) + 1]);
    return v;
}

template<>
intl transform<intl>(uint *val, int index) {
    return transform<uintl>(val, index);
}

// Generates rationals in [0, 1)
template<>
float transform<float>(uint *val, int index) {
    return 1.f - (val[index] * FLT_FACTOR + HALF_FLT_FACTOR);
}

// Generates rationals in [0, 1)
template<>
float transform<common::half, float>(uint *val, int index) {
    ushort v = val[index >> 1] >> (16 << (index & 1));
    return 1.f - (v * HALF_FACTOR + HALF_HALF_FACTOR);
}

// Generates rationals in [0, 1)
template<>
double transform<double>(uint *val, int index) {
    uintl v = transform<uintl>(val, index);
    return 1.0 - (v * DBL_FACTOR + HALF_DBL_FACTOR);
}

#define MAX_RESET_CTR_VAL 64
#define WRITE_STRIDE 256

// This implementation aims to emulate the corresponding method in the CUDA
// backend, in order to produce the exact same numbers as CUDA.
// A stride of WRITE_STRIDE (256) is applied between each write
// (emulating the CUDA thread writing to 4 locations with a stride of
// blockDim.x, which is 256).
// ELEMS_PER_ITER correspond to elementsPerBlock in the CUDA backend, so each
// "iter" (iteration) here correspond to a CUDA thread block doing its work.
// This change was prompted by issue #2429
template<typename T>
void philoxUniform(T *out, size_t elements, const uintl seed, uintl counter) {
    uint hi  = seed >> 32;
    uint lo  = seed;
    uint hic = counter >> 32;
    uint loc = counter;

    constexpr size_t RESET_CTR = MAX_RESET_CTR_VAL / sizeof(T);
    constexpr size_t ELEMS_PER_ITER =
        WRITE_STRIDE * 4 * sizeof(uint) / sizeof(T);

    int num_iters = divup(elements, ELEMS_PER_ITER);
    size_t len    = num_iters * ELEMS_PER_ITER;

    constexpr size_t NUM_WRITES = 16 / sizeof(T);
    for (size_t iter = 0; iter < len; iter += ELEMS_PER_ITER) {
        for (size_t i = 0; i < WRITE_STRIDE; i += RESET_CTR) {
            for (size_t j = 0; j < RESET_CTR; ++j) {
                // first_write_idx is the first of the 4 locations that will
                // be written to
                uintptr_t first_write_idx = iter + i + j;
                if (first_write_idx >= elements) { break; }

                // Recalculate key and ctr to emulate how the CUDA backend
                // calculates these per thread
                uint key[2] = {lo, hi};
                uint ctr[4] = {loc + (uint)first_write_idx,
                               hic + (ctr[0] < loc), (ctr[1] < hic), 0};
                philox(key, ctr);

                // Use the same ctr array for each of the 4 locations,
                // but each of the location gets a different ctr value
                for (size_t buf_idx = 0; buf_idx < NUM_WRITES; ++buf_idx) {
                    size_t out_idx = iter + buf_idx * WRITE_STRIDE + i + j;
                    if (out_idx < elements) {
                        out[out_idx] =
                            transform<data_t<T>, compute_t<T>>(ctr, buf_idx);
                    }
                }
            }
        }
    }
}

#undef MAX_RESET_CTR_VAL
#undef WRITE_STRIDE

template<typename T>
void threefryUniform(T *out, size_t elements, const uintl seed, uintl counter) {
    uint hi     = seed >> 32;
    uint lo     = seed;
    uint hic    = counter >> 32;
    uint loc    = counter;
    uint key[2] = {lo, hi};
    uint ctr[2] = {loc, hic};
    uint val[2];

    int reset = (2 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        threefry(key, ctr, val);
        ++ctr[0];
        ctr[1] += (ctr[0] == 0);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) {
            out[i + j] = transform<data_t<T>, compute_t<T>>(val, j);
        }
    }
}

template<typename T>
void boxMullerTransform(data_t<T> *const out1, data_t<T> *const out2,
                        const compute_t<T> r1, const compute_t<T> r2) {
    /*
     * The log of a real value x where 0 < x < 1 is negative.
     */
    using Tc = compute_t<T>;
    Tc r     = sqrt((Tc)(-2.0) * log((Tc)(1.0) - r1));
    Tc theta = 2 * (Tc)PI_VAL * ((Tc)(1.0) - r2);
    *out1    = r * sin(theta);
    *out2    = r * cos(theta);
}

void boxMullerTransform(uint val[4], double *temp) {
    boxMullerTransform<double>(&temp[0], &temp[1], transform<double>(val, 0),
                               transform<double>(val, 1));
}

void boxMullerTransform(uint val[4], float *temp) {
    boxMullerTransform<float>(&temp[0], &temp[1], transform<float>(val, 0),
                              transform<float>(val, 1));
    boxMullerTransform<float>(&temp[2], &temp[3], transform<float>(val, 2),
                              transform<float>(val, 3));
}

void boxMullerTransform(uint val[4], common::half *temp) {
    using common::half;
    boxMullerTransform<half>(&temp[0], &temp[1], transform<half, float>(val, 0),
                             transform<half, float>(val, 1));
    boxMullerTransform<half>(&temp[2], &temp[3], transform<half, float>(val, 2),
                             transform<half, float>(val, 3));
    boxMullerTransform<half>(&temp[4], &temp[5], transform<half, float>(val, 4),
                             transform<half, float>(val, 5));
    boxMullerTransform<half>(&temp[6], &temp[7], transform<half, float>(val, 6),
                             transform<half, float>(val, 7));
}

template<typename T>
void philoxNormal(T *out, size_t elements, const uintl seed, uintl counter) {
    uint hi     = seed >> 32;
    uint lo     = seed;
    uint hic    = counter >> 32;
    uint loc    = counter;
    uint key[2] = {lo, hi};
    uint ctr[4] = {loc, hic, 0, 0};
    T temp[(4 * sizeof(uint)) / sizeof(T)];

    int reset = (4 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        philox(key, ctr);
        boxMullerTransform(ctr, temp);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) { out[i + j] = temp[j]; }
    }
}

template<typename T>
void threefryNormal(T *out, size_t elements, const uintl seed, uintl counter) {
    uint hi     = seed >> 32;
    uint lo     = seed;
    uint hic    = counter >> 32;
    uint loc    = counter;
    uint key[2] = {lo, hi};
    uint ctr[2] = {loc, hic};
    uint val[4];
    T temp[(4 * sizeof(uint)) / sizeof(T)];

    int reset = (4 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        threefry(key, ctr, val);
        ++ctr[0];
        ctr[1] += (ctr[0] == 0);
        threefry(key, ctr, val + 2);
        ++ctr[0];
        ctr[1] += (ctr[0] == 0);
        boxMullerTransform(val, temp);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) { out[i + j] = temp[j]; }
    }
}

template<typename T>
void uniformDistributionMT(T *out, size_t elements, uint *const state,
                           const uint *const pos, const uint *const sh1,
                           const uint *const sh2, uint mask,
                           const uint *const recursion_table,
                           const uint *const temper_table) {
    uint l_state[STATE_SIZE];
    uint o[4];
    uint lpos = pos[0];
    uint lsh1 = sh1[0];
    uint lsh2 = sh2[0];

    state_read(l_state, state);

    int reset = (4 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        mersenne(o, l_state, i, lpos, lsh1, lsh2, mask, recursion_table,
                 temper_table);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) {
            out[i + j] = transform<data_t<T>, compute_t<T>>(o, j);
        }
    }

    state_write(state, l_state);
}

template<typename T>
void normalDistributionMT(T *out, size_t elements, uint *const state,
                          const uint *const pos, const uint *const sh1,
                          const uint *const sh2, uint mask,
                          const uint *const recursion_table,
                          const uint *const temper_table) {
    T temp[(4 * sizeof(uint)) / sizeof(T)];
    uint l_state[STATE_SIZE];
    uint o[4];
    uint lpos = pos[0];
    uint lsh1 = sh1[0];
    uint lsh2 = sh2[0];

    state_read(l_state, state);

    int reset = (4 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        mersenne(o, l_state, i, lpos, lsh1, lsh2, mask, recursion_table,
                 temper_table);
        boxMullerTransform(o, temp);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) { out[i + j] = temp[j]; }
    }

    state_write(state, l_state);
}

template<typename T>
void uniformDistributionCBRNG(T *out, size_t elements,
                              af_random_engine_type type, const uintl seed,
                              uintl counter) {
    switch (type) {
        case AF_RANDOM_ENGINE_PHILOX_4X32_10:
            philoxUniform(out, elements, seed, counter);
            break;
        case AF_RANDOM_ENGINE_THREEFRY_2X32_16:
            threefryUniform(out, elements, seed, counter);
            break;
        default:
            AF_ERROR("Random Engine Type Not Supported", AF_ERR_NOT_SUPPORTED);
    }
}

template<typename T>
void normalDistributionCBRNG(T *out, size_t elements,
                             af_random_engine_type type, const uintl seed,
                             uintl counter) {
    switch (type) {
        case AF_RANDOM_ENGINE_PHILOX_4X32_10:
            philoxNormal(out, elements, seed, counter);
            break;
        case AF_RANDOM_ENGINE_THREEFRY_2X32_16:
            threefryNormal(out, elements, seed, counter);
            break;
        default:
            AF_ERROR("Random Engine Type Not Supported", AF_ERR_NOT_SUPPORTED);
    }
}

}  // namespace kernel
}  // namespace cpu
<commit_msg>Fix random number generator for f16 and short on the CPU backend (#2587)<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#pragma once

#include <Param.hpp>
#include <common/dispatch.hpp>
#include <common/half.hpp>
#include <err_cpu.hpp>
#include <kernel/random_engine_mersenne.hpp>
#include <kernel/random_engine_philox.hpp>
#include <kernel/random_engine_threefry.hpp>
#include <types.hpp>

#include <algorithm>
#include <cstring>

using std::array;
using std::memcpy;

namespace cpu {
namespace kernel {
// Utils
static const double PI_VAL =
    3.1415926535897932384626433832795028841971693993751058209749445923078164;

// Conversion to half adapted from Random123
#define USHORTMAX 0xffff
#define HALF_FACTOR ((1.0f) / (USHORTMAX + (1.0f)))
#define HALF_HALF_FACTOR ((0.5f) * HALF_FACTOR)

// Conversion to floats adapted from Random123
#define UINTMAX 0xffffffff
#define FLT_FACTOR ((1.0f) / (UINTMAX + (1.0f)))
#define HALF_FLT_FACTOR ((0.5f) * FLT_FACTOR)

#define UINTLMAX 0xffffffffffffffff
#define DBL_FACTOR ((1.0) / (UINTLMAX + (1.0)))
#define HALF_DBL_FACTOR ((0.5) * DBL_FACTOR)

template<typename T>
T transform(uint *val, int index) {
    T *oval = (T *)val;
    return oval[index];
}

template<>
char transform<char>(uint *val, int index) {
    char v = val[index >> 2] >> (8 << (index & 3));
    v      = (v & 0x1) ? 1 : 0;
    return v;
}

template<>
uchar transform<uchar>(uint *val, int index) {
    uchar v = val[index >> 2] >> (index << 3);
    return v;
}

template<>
ushort transform<ushort>(uint *val, int index) {
    ushort v = val[index >> 1U] >> (16U * (index & 1U)) & 0x0000ffff;
    return v;
}

template<>
short transform<short>(uint *val, int index) {
    return transform<ushort>(val, index);
}

template<>
uint transform<uint>(uint *val, int index) {
    return val[index];
}

template<>
int transform<int>(uint *val, int index) {
    return transform<uint>(val, index);
}

template<>
uintl transform<uintl>(uint *val, int index) {
    uintl v = (((uintl)val[index << 1]) << 32) | ((uintl)val[(index << 1) + 1]);
    return v;
}

template<>
intl transform<intl>(uint *val, int index) {
    return transform<uintl>(val, index);
}

// Generates rationals in [0, 1)
template<>
float transform<float>(uint *val, int index) {
    return 1.f - (val[index] * FLT_FACTOR + HALF_FLT_FACTOR);
}

// Generates rationals in [0, 1)
template<>
common::half transform<common::half>(uint *val, int index) {
    float v = val[index >> 1U] >> (16U * (index & 1U)) & 0x0000ffff;
    return static_cast<common::half>(1.f - (v * HALF_FACTOR + HALF_HALF_FACTOR));
}

// Generates rationals in [0, 1)
template<>
double transform<double>(uint *val, int index) {
    uintl v = transform<uintl>(val, index);
    return 1.0 - (v * DBL_FACTOR + HALF_DBL_FACTOR);
}

#define MAX_RESET_CTR_VAL 64
#define WRITE_STRIDE 256

// This implementation aims to emulate the corresponding method in the CUDA
// backend, in order to produce the exact same numbers as CUDA.
// A stride of WRITE_STRIDE (256) is applied between each write
// (emulating the CUDA thread writing to 4 locations with a stride of
// blockDim.x, which is 256).
// ELEMS_PER_ITER correspond to elementsPerBlock in the CUDA backend, so each
// "iter" (iteration) here correspond to a CUDA thread block doing its work.
// This change was prompted by issue #2429
template<typename T>
void philoxUniform(T *out, size_t elements, const uintl seed, uintl counter) {
    uint hi  = seed >> 32;
    uint lo  = seed;
    uint hic = counter >> 32;
    uint loc = counter;

    constexpr size_t RESET_CTR = MAX_RESET_CTR_VAL / sizeof(T);
    constexpr size_t ELEMS_PER_ITER =
        WRITE_STRIDE * 4 * sizeof(uint) / sizeof(T);

    int num_iters = divup(elements, ELEMS_PER_ITER);
    size_t len    = num_iters * ELEMS_PER_ITER;

    constexpr size_t NUM_WRITES = 16 / sizeof(T);
    for (size_t iter = 0; iter < len; iter += ELEMS_PER_ITER) {
        for (size_t i = 0; i < WRITE_STRIDE; i += RESET_CTR) {
            for (size_t j = 0; j < RESET_CTR; ++j) {
                // first_write_idx is the first of the 4 locations that will
                // be written to
                uintptr_t first_write_idx = iter + i + j;
                if (first_write_idx >= elements) { break; }

                // Recalculate key and ctr to emulate how the CUDA backend
                // calculates these per thread
                uint key[2] = {lo, hi};
                uint ctr[4] = {loc + (uint)first_write_idx,
                               hic + (ctr[0] < loc), (ctr[1] < hic), 0};
                philox(key, ctr);

                // Use the same ctr array for each of the 4 locations,
                // but each of the location gets a different ctr value
                for (size_t buf_idx = 0; buf_idx < NUM_WRITES; ++buf_idx) {
                    size_t out_idx = iter + buf_idx * WRITE_STRIDE + i + j;
                    if (out_idx < elements) {
                        out[out_idx] =
                            transform<T>(ctr, buf_idx);
                    }
                }
            }
        }
    }
}

#undef MAX_RESET_CTR_VAL
#undef WRITE_STRIDE

template<typename T>
void threefryUniform(T *out, size_t elements, const uintl seed, uintl counter) {
    uint hi     = seed >> 32;
    uint lo     = seed;
    uint hic    = counter >> 32;
    uint loc    = counter;
    uint key[2] = {lo, hi};
    uint ctr[2] = {loc, hic};
    uint val[2];

    int reset = (2 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        threefry(key, ctr, val);
        ++ctr[0];
        ctr[1] += (ctr[0] == 0);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) {
            out[i + j] = transform<T>(val, j);
        }
    }
}

template<typename T>
void boxMullerTransform(data_t<T> *const out1, data_t<T> *const out2,
                        const compute_t<T> r1, const compute_t<T> r2) {
    /*
     * The log of a real value x where 0 < x < 1 is negative.
     */
    using Tc = compute_t<T>;
    Tc r     = sqrt((Tc)(-2.0) * log((Tc)(1.0) - r1));
    Tc theta = 2 * (Tc)PI_VAL * ((Tc)(1.0) - r2);
    *out1    = r * sin(theta);
    *out2    = r * cos(theta);
}

void boxMullerTransform(uint val[4], double *temp) {
    boxMullerTransform<double>(&temp[0], &temp[1], transform<double>(val, 0),
                               transform<double>(val, 1));
}

void boxMullerTransform(uint val[4], float *temp) {
    boxMullerTransform<float>(&temp[0], &temp[1], transform<float>(val, 0),
                              transform<float>(val, 1));
    boxMullerTransform<float>(&temp[2], &temp[3], transform<float>(val, 2),
                              transform<float>(val, 3));
}

void boxMullerTransform(uint val[4], common::half *temp) {
    using common::half;
    boxMullerTransform<half>(&temp[0], &temp[1], transform<half>(val, 0),
                             transform<half>(val, 1));
    boxMullerTransform<half>(&temp[2], &temp[3], transform<half>(val, 2),
                             transform<half>(val, 3));
    boxMullerTransform<half>(&temp[4], &temp[5], transform<half>(val, 4),
                             transform<half>(val, 5));
    boxMullerTransform<half>(&temp[6], &temp[7], transform<half>(val, 6),
                             transform<half>(val, 7));
}

template<typename T>
void philoxNormal(T *out, size_t elements, const uintl seed, uintl counter) {
    uint hi     = seed >> 32;
    uint lo     = seed;
    uint hic    = counter >> 32;
    uint loc    = counter;
    uint key[2] = {lo, hi};
    uint ctr[4] = {loc, hic, 0, 0};
    T temp[(4 * sizeof(uint)) / sizeof(T)];

    int reset = (4 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        philox(key, ctr);
        boxMullerTransform(ctr, temp);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) { out[i + j] = temp[j]; }
    }
}

template<typename T>
void threefryNormal(T *out, size_t elements, const uintl seed, uintl counter) {
    uint hi     = seed >> 32;
    uint lo     = seed;
    uint hic    = counter >> 32;
    uint loc    = counter;
    uint key[2] = {lo, hi};
    uint ctr[2] = {loc, hic};
    uint val[4];
    T temp[(4 * sizeof(uint)) / sizeof(T)];

    int reset = (4 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        threefry(key, ctr, val);
        ++ctr[0];
        ctr[1] += (ctr[0] == 0);
        threefry(key, ctr, val + 2);
        ++ctr[0];
        ctr[1] += (ctr[0] == 0);
        boxMullerTransform(val, temp);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) { out[i + j] = temp[j]; }
    }
}

template<typename T>
void uniformDistributionMT(T *out, size_t elements, uint *const state,
                           const uint *const pos, const uint *const sh1,
                           const uint *const sh2, uint mask,
                           const uint *const recursion_table,
                           const uint *const temper_table) {
    uint l_state[STATE_SIZE];
    uint o[4];
    uint lpos = pos[0];
    uint lsh1 = sh1[0];
    uint lsh2 = sh2[0];

    state_read(l_state, state);

    int reset = (4 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        mersenne(o, l_state, i, lpos, lsh1, lsh2, mask, recursion_table,
                 temper_table);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) {
            out[i + j] = transform<T>(o, j);
        }
    }

    state_write(state, l_state);
}

template<typename T>
void normalDistributionMT(T *out, size_t elements, uint *const state,
                          const uint *const pos, const uint *const sh1,
                          const uint *const sh2, uint mask,
                          const uint *const recursion_table,
                          const uint *const temper_table) {
    T temp[(4 * sizeof(uint)) / sizeof(T)];
    uint l_state[STATE_SIZE];
    uint o[4];
    uint lpos = pos[0];
    uint lsh1 = sh1[0];
    uint lsh2 = sh2[0];

    state_read(l_state, state);

    int reset = (4 * sizeof(uint)) / sizeof(T);
    for (int i = 0; i < (int)elements; i += reset) {
        mersenne(o, l_state, i, lpos, lsh1, lsh2, mask, recursion_table,
                 temper_table);
        boxMullerTransform(o, temp);
        int lim = (reset < (int)(elements - i)) ? reset : (int)(elements - i);
        for (int j = 0; j < lim; ++j) { out[i + j] = temp[j]; }
    }

    state_write(state, l_state);
}

template<typename T>
void uniformDistributionCBRNG(T *out, size_t elements,
                              af_random_engine_type type, const uintl seed,
                              uintl counter) {
    switch (type) {
        case AF_RANDOM_ENGINE_PHILOX_4X32_10:
            philoxUniform(out, elements, seed, counter);
            break;
        case AF_RANDOM_ENGINE_THREEFRY_2X32_16:
            threefryUniform(out, elements, seed, counter);
            break;
        default:
            AF_ERROR("Random Engine Type Not Supported", AF_ERR_NOT_SUPPORTED);
    }
}

template<typename T>
void normalDistributionCBRNG(T *out, size_t elements,
                             af_random_engine_type type, const uintl seed,
                             uintl counter) {
    switch (type) {
        case AF_RANDOM_ENGINE_PHILOX_4X32_10:
            philoxNormal(out, elements, seed, counter);
            break;
        case AF_RANDOM_ENGINE_THREEFRY_2X32_16:
            threefryNormal(out, elements, seed, counter);
            break;
        default:
            AF_ERROR("Random Engine Type Not Supported", AF_ERR_NOT_SUPPORTED);
    }
}

}  // namespace kernel
}  // namespace cpu
<|endoftext|>


<commit_before>#include "../include/LRU.hpp"
#include "../include/ALRU.hpp"

#include <iostream>
#include <exception>

int main(int argc, char **argv) {

    if (argc < 2) {
        std::cerr << "Not enough parameters!\nUSAGE: " << argv[0] << " request_file" << std::endl;
        return -1;
    }

    const std::string fname(argv[1]);

    try {
        // std::cout << "INIT LRU" << std::endl;
        // LRU lru_test;

        // std::cout << "RUNNING LRU" << std::endl;
        // uint32_t total_faults = lru_test(fname);

        // std::cout << "LRU COMPLETE, " << total_faults << " TOTAL PAGE FAULTS." << std::endl;
    } catch (std::exception &e) {
        std::cerr << "Something broke! " << e.what() << std::endl;
    }

    try {
        std::cout << "INIT ALRU" << std::endl;
        ALRU alru_test;

        std::cout << "RUNNING ALRU" << std::endl;
        uint32_t total_faults = alru_test(fname);

        std::cout << "ALRU COMPLETE, " << total_faults << " TOTAL PAGE FAULTS." << std::endl;
    } catch (std::exception &e) {
        std::cerr << "Something broke! " << e.what() << std::endl;
    }

    return 0;
}
<commit_msg>uncommented necessary code<commit_after>#include "../include/LRU.hpp"
#include "../include/ALRU.hpp"

#include <iostream>
#include <exception>

int main(int argc, char **argv) {

    if (argc < 2) {
        std::cerr << "Not enough parameters!\nUSAGE: " << argv[0] << " request_file" << std::endl;
        return -1;
    }

    const std::string fname(argv[1]);

    try {
        std::cout << "INIT LRU" << std::endl;
        LRU lru_test;

        std::cout << "RUNNING LRU" << std::endl;
        uint32_t total_faults = lru_test(fname);

        std::cout << "LRU COMPLETE, " << total_faults << " TOTAL PAGE FAULTS." << std::endl;
    } catch (std::exception &e) {
        std::cerr << "Something broke! " << e.what() << std::endl;
    }

    try {
        std::cout << "INIT ALRU" << std::endl;
        ALRU alru_test;

        std::cout << "RUNNING ALRU" << std::endl;
        uint32_t total_faults = alru_test(fname);

        std::cout << "ALRU COMPLETE, " << total_faults << " TOTAL PAGE FAULTS." << std::endl;
    } catch (std::exception &e) {
        std::cerr << "Something broke! " << e.what() << std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "search_query.hpp"
#include "category_info.hpp"
#include "feature_offset_match.hpp"
#include "lang_keywords_scorer.hpp"
#include "latlon_match.hpp"
#include "result.hpp"
#include "search_common.hpp"

#include "../storage/country_info.hpp"

#include "../indexer/feature_covering.hpp"
#include "../indexer/features_vector.hpp"
#include "../indexer/index.hpp"
#include "../indexer/scales.hpp"
#include "../indexer/search_delimiters.hpp"
#include "../indexer/search_string_utils.hpp"

#include "../coding/multilang_utf8_string.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"
#include "../base/stl_add.hpp"

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

namespace search
{

Query::Query(Index const * pIndex,
             CategoriesMapT const * pCategories,
             StringsToSuggestVectorT const * pStringsToSuggest,
             storage::CountryInfoGetter const * pInfoGetter,
             int preferredLanguage)
  : m_pIndex(pIndex),
    m_pCategories(pCategories),
    m_pStringsToSuggest(pStringsToSuggest),
    m_pInfoGetter(pInfoGetter),
    m_preferredLanguage(preferredLanguage),
    m_viewport(m2::RectD::GetEmptyRect()), m_viewportExtended(m2::RectD::GetEmptyRect()),
    m_bOffsetsCacheIsValid(false)
{
}

Query::~Query()
{
}

void Query::SetViewport(m2::RectD const & viewport)
{
  // TODO: Clear m_viewportExtended when mwm index is added or removed!

  if (m_viewport != viewport || !m_bOffsetsCacheIsValid)
  {
    m_viewport = viewport;
    m_viewportExtended = m_viewport;
    m_viewportExtended.Scale(3);

    UpdateViewportOffsets();
  }
}

void Query::SetPreferredLanguage(int lang)
{
  m_preferredLanguage = lang;
}

void Query::ClearCache()
{
  m_offsetsInViewport.clear();
  m_bOffsetsCacheIsValid = false;
}

void Query::UpdateViewportOffsets()
{
  m_offsetsInViewport.clear();

  vector<MwmInfo> mwmInfo;
  m_pIndex->GetMwmInfo(mwmInfo);
  m_offsetsInViewport.resize(mwmInfo.size());

  int const viewScale = scales::GetScaleLevel(m_viewport);
  covering::CoveringGetter cov(m_viewport, 0);

  for (MwmSet::MwmId mwmId = 0; mwmId < mwmInfo.size(); ++mwmId)
  {
    // Search only mwms that intersect with viewport (world always does).
    if (m_viewportExtended.IsIntersect(mwmInfo[mwmId].m_limitRect))
    {
      Index::MwmLock mwmLock(*m_pIndex, mwmId);
      if (MwmValue * pMwm = mwmLock.GetValue())
      {
        feature::DataHeader const & header = pMwm->GetHeader();
        if (header.GetType() == feature::DataHeader::worldcoasts)
          continue;

        pair<int, int> const scaleR = header.GetScaleRange();
        int const scale = min(max(viewScale + 7, scaleR.first), scaleR.second);

        covering::IntervalsT const & interval = cov.Get(header.GetLastScale());

        ScaleIndex<ModelReaderPtr> index(pMwm->m_cont.GetReader(INDEX_FILE_TAG),
                                         pMwm->m_factory);

        for (size_t i = 0; i < interval.size(); ++i)
        {
          index.ForEachInIntervalAndScale(MakeInsertFunctor(m_offsetsInViewport[mwmId]),
                                          interval[i].first, interval[i].second,
                                          scale);
        }
      }
    }
  }

  m_bOffsetsCacheIsValid = true;

  size_t offsetsCached = 0;
  for (MwmSet::MwmId mwmId = 0; mwmId < mwmInfo.size(); ++mwmId)
    offsetsCached += m_offsetsInViewport[mwmId].size();
  LOG(LDEBUG, ("For search in viewport cached ",
              "mwms:", mwmInfo.size(),
              "offsets:", offsetsCached));
}

void Query::Search(string const & query,
                   function<void (Result const &)> const & f,
                   unsigned int resultsNeeded)
{
  // Initialize.
  {
    m_rawQuery = query;
    m_uniQuery = NormalizeAndSimplifyString(m_rawQuery);
    m_tokens.clear();
    m_prefix.clear();

    search::Delimiters delims;
    SplitUniString(m_uniQuery, MakeBackInsertFunctor(m_tokens), delims);

    if (!m_tokens.empty() && !delims(strings::LastUniChar(m_rawQuery)))
    {
      m_prefix.swap(m_tokens.back());
      m_tokens.pop_back();
    }
    if (m_tokens.size() > 31)
      m_tokens.resize(31);

    vector<vector<int8_t> > langPriorities(3);
    langPriorities[0].push_back(m_preferredLanguage);
    langPriorities[1].push_back(StringUtf8Multilang::GetLangIndex("int_name"));
    langPriorities[1].push_back(StringUtf8Multilang::GetLangIndex("en"));
    langPriorities[2].push_back(StringUtf8Multilang::GetLangIndex("default"));
    m_pKeywordsScorer.reset(new LangKeywordsScorer(langPriorities,
                                                   m_tokens.data(), m_tokens.size(), &m_prefix));

    m_results = my::limited_priority_queue<impl::IntermediateResult>(resultsNeeded);
  }

  // Match (lat, lon).
  {
    double lat, lon, latPrec, lonPrec;
    if (search::MatchLatLon(m_rawQuery, lat, lon, latPrec, lonPrec))
    {
      string const region = m_pInfoGetter->GetRegionName(m2::PointD(MercatorBounds::LonToX(lon),
                                                                    MercatorBounds::LatToY(lat)));
      double const precision = 5.0 * max(0.0001, min(latPrec, lonPrec));  // Min 55 meters

      AddResult(impl::IntermediateResult(m_viewport, region, lat, lon, precision));
    }
  }

  SuggestStrings();

  SearchFeatures();

  FlushResults(f);
}

void Query::AddResult(impl::IntermediateResult const & result)
{
  m_results.push(result);
}

void Query::FlushResults(function<void (Result const &)> const & f)
{
  vector<impl::IntermediateResult> v(m_results.begin(), m_results.end());
  sort_heap(v.begin(), v.end());
  for (vector<impl::IntermediateResult>::const_iterator it = v.begin(); it != v.end(); ++it)
    f(it->GenerateFinalResult());
}

void Query::AddFeatureResult(FeatureType const & f, string const & fName)
{
  uint32_t penalty;
  string name;
  GetBestMatchName(f, penalty, name);
  AddResult(impl::IntermediateResult(m_viewport, f, name, GetRegionName(f, fName)));
}

namespace impl
{

class BestNameFinder
{
  uint32_t & m_penalty;
  string & m_name;
  LangKeywordsScorer & m_keywordsScorer;
public:
  BestNameFinder(uint32_t & penalty, string & name, LangKeywordsScorer & keywordsScorer)
    : m_penalty(penalty), m_name(name), m_keywordsScorer(keywordsScorer)
  {
    m_penalty = uint32_t(-1);
  }

  bool operator()(signed char lang, string const & name) const
  {
    uint32_t penalty = m_keywordsScorer.Score(lang, name);
    if (penalty < m_penalty)
    {
      m_penalty = penalty;
      m_name = name;
    }
    return true;
  }
};

}  // namespace search::impl

void Query::GetBestMatchName(FeatureType const & f, uint32_t & penalty, string & name)
{
  impl::BestNameFinder bestNameFinder(penalty, name, *m_pKeywordsScorer);
  f.ForEachNameRef(bestNameFinder);
}

string Query::GetRegionName(FeatureType const & f, string const & fName)
{
  if (!fName.empty())
  {
    return m_pInfoGetter->GetRegionName(fName);
  }
  else
  {
    if (f.GetFeatureType() == feature::GEOM_POINT)
      return m_pInfoGetter->GetRegionName(f.GetCenter());
  }

  return string();
}

namespace impl
{

struct FeatureLoader
{
  uint32_t m_count;
  FeaturesVector & m_featuresVector;
  Query & m_query;
  string m_fName;

  FeatureLoader(FeaturesVector & featuresVector, Query & query, string const & fName)
    : m_count(0), m_featuresVector(featuresVector), m_query(query), m_fName(fName)
  {
  }

  void operator() (uint32_t offset)
  {
    ++m_count;
    FeatureType feature;
    m_featuresVector.Get(offset, feature);
    m_query.AddFeatureResult(feature, m_fName);
  }
};

}  // namespace search::impl

void Query::SearchFeatures()
{
  if (!m_pIndex)
    return;

  vector<vector<strings::UniString> > tokens(m_tokens.size());

  // Add normal tokens.
  for (size_t i = 0; i < m_tokens.size(); ++i)
    tokens[i].push_back(m_tokens[i]);

  // Add names of categories.
  if (m_pCategories)
  {
    for (size_t i = 0; i < m_tokens.size(); ++i)
    {
      pair<CategoriesMapT::const_iterator, CategoriesMapT::const_iterator> range
          = m_pCategories->equal_range(m_tokens[i]);
      for (CategoriesMapT::const_iterator it = range.first; it != range.second; ++it)
        tokens[i].push_back(FeatureTypeToString(it->second));
    }
  }

  vector<MwmInfo> mwmInfo;
  m_pIndex->GetMwmInfo(mwmInfo);

  unordered_set<int8_t> langs;
  langs.insert(StringUtf8Multilang::GetLangIndex("en"));
  SearchFeatures(tokens, mwmInfo, langs, true);
}

void Query::SearchFeatures(vector<vector<strings::UniString> > const & tokens,
                           vector<MwmInfo> const & mwmInfo,
                           unordered_set<int8_t> const & langs,
                           bool onlyInViewport)
{
  for (MwmSet::MwmId mwmId = 0; mwmId < mwmInfo.size(); ++mwmId)
  {
    // Search only mwms that intersect with viewport (world always does).
    if (!onlyInViewport ||
        m_viewportExtended.IsIntersect(mwmInfo[mwmId].m_limitRect))
    {
      Index::MwmLock mwmLock(*m_pIndex, mwmId);
      if (MwmValue * pMwm = mwmLock.GetValue())
      {
        if (pMwm->m_cont.IsReaderExist(SEARCH_INDEX_FILE_TAG))
        {
          scoped_ptr<TrieIterator> pTrieRoot(::trie::reader::ReadTrie(
                                               pMwm->m_cont.GetReader(SEARCH_INDEX_FILE_TAG),
                                               ::search::trie::ValueReader(),
                                               ::search::trie::EdgeValueReader()));
          if (pTrieRoot)
          {
            for (size_t i = 0; i < pTrieRoot->m_edge.size(); ++i)
            {
              TrieIterator::Edge::EdgeStrT const & edge = pTrieRoot->m_edge[i].m_str;
              ASSERT_GREATER_OR_EQUAL(edge.size(), 1, ());
              // TODO: edge.size() > 1 !!
              if (edge.size() == 1 && edge[0] < 128 && langs.count(static_cast<int8_t>(edge[0])))
              {
                scoped_ptr<TrieIterator> pLangRoot(pTrieRoot->GoToEdge(i));

                feature::DataHeader const & h = pMwm->GetHeader();
                FeaturesVector featuresVector(pMwm->m_cont, h);
                impl::FeatureLoader f(
                      featuresVector,
                      *this,
                      (h.GetType() == feature::DataHeader::world) ? "" : mwmLock.GetCountryName());

                MatchFeaturesInTrie(tokens, m_prefix, *pLangRoot,
                                    &m_offsetsInViewport[mwmId], f, m_results.max_size() * 10);

                LOG(LDEBUG, ("Lang:",
                             StringUtf8Multilang::GetLangByCode(static_cast<int8_t>(edge[0])),
                             "Matched: ",
                             f.m_count));
              }
            }
          }
        }
      }
    }
  }
}

void Query::SuggestStrings()
{
  if (m_pStringsToSuggest)
  {
    typedef StringsToSuggestVectorT::const_iterator ItT;

    if (m_tokens.size() == 0 && !m_prefix.empty())
    {
      // Match prefix.
      for (ItT it = m_pStringsToSuggest->begin(); it != m_pStringsToSuggest->end(); ++it)
        if (it->second <= m_prefix.size() &&
            StartsWith(it->first.begin(), it->first.end(), m_prefix.begin(), m_prefix.end()))
          AddResult(impl::IntermediateResult(strings::ToUtf8(it->first), it->second));
    }
    else if (m_tokens.size() == 1)
    {
      // Match token + prefix.
      strings::UniString tokenAndPrefix = m_tokens[0];
      if (!m_prefix.empty())
      {
        tokenAndPrefix.push_back(' ');
        tokenAndPrefix.append(m_prefix.begin(), m_prefix.end());
      }
      for (ItT it = m_pStringsToSuggest->begin(); it != m_pStringsToSuggest->end(); ++it)
      {
        strings::UniString const & s = it->first;
        if (it->second <= tokenAndPrefix.size() &&
            StartsWith(s.begin(), s.end(), tokenAndPrefix.begin(), tokenAndPrefix.end()))
          AddResult(impl::IntermediateResult(strings::ToUtf8(it->first), it->second));
      }
    }
  }
}

}  // namespace search
<commit_msg>[search] Search names in int_name and default languages.<commit_after>#include "search_query.hpp"
#include "category_info.hpp"
#include "feature_offset_match.hpp"
#include "lang_keywords_scorer.hpp"
#include "latlon_match.hpp"
#include "result.hpp"
#include "search_common.hpp"

#include "../storage/country_info.hpp"

#include "../indexer/feature_covering.hpp"
#include "../indexer/features_vector.hpp"
#include "../indexer/index.hpp"
#include "../indexer/scales.hpp"
#include "../indexer/search_delimiters.hpp"
#include "../indexer/search_string_utils.hpp"

#include "../coding/multilang_utf8_string.hpp"

#include "../base/logging.hpp"
#include "../base/string_utils.hpp"
#include "../base/stl_add.hpp"

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

namespace search
{

Query::Query(Index const * pIndex,
             CategoriesMapT const * pCategories,
             StringsToSuggestVectorT const * pStringsToSuggest,
             storage::CountryInfoGetter const * pInfoGetter,
             int preferredLanguage)
  : m_pIndex(pIndex),
    m_pCategories(pCategories),
    m_pStringsToSuggest(pStringsToSuggest),
    m_pInfoGetter(pInfoGetter),
    m_preferredLanguage(preferredLanguage),
    m_viewport(m2::RectD::GetEmptyRect()), m_viewportExtended(m2::RectD::GetEmptyRect()),
    m_bOffsetsCacheIsValid(false)
{
}

Query::~Query()
{
}

void Query::SetViewport(m2::RectD const & viewport)
{
  // TODO: Clear m_viewportExtended when mwm index is added or removed!

  if (m_viewport != viewport || !m_bOffsetsCacheIsValid)
  {
    m_viewport = viewport;
    m_viewportExtended = m_viewport;
    m_viewportExtended.Scale(3);

    UpdateViewportOffsets();
  }
}

void Query::SetPreferredLanguage(int lang)
{
  m_preferredLanguage = lang;
}

void Query::ClearCache()
{
  m_offsetsInViewport.clear();
  m_bOffsetsCacheIsValid = false;
}

void Query::UpdateViewportOffsets()
{
  m_offsetsInViewport.clear();

  vector<MwmInfo> mwmInfo;
  m_pIndex->GetMwmInfo(mwmInfo);
  m_offsetsInViewport.resize(mwmInfo.size());

  int const viewScale = scales::GetScaleLevel(m_viewport);
  covering::CoveringGetter cov(m_viewport, 0);

  for (MwmSet::MwmId mwmId = 0; mwmId < mwmInfo.size(); ++mwmId)
  {
    // Search only mwms that intersect with viewport (world always does).
    if (m_viewportExtended.IsIntersect(mwmInfo[mwmId].m_limitRect))
    {
      Index::MwmLock mwmLock(*m_pIndex, mwmId);
      if (MwmValue * pMwm = mwmLock.GetValue())
      {
        feature::DataHeader const & header = pMwm->GetHeader();
        if (header.GetType() == feature::DataHeader::worldcoasts)
          continue;

        pair<int, int> const scaleR = header.GetScaleRange();
        int const scale = min(max(viewScale + 7, scaleR.first), scaleR.second);

        covering::IntervalsT const & interval = cov.Get(header.GetLastScale());

        ScaleIndex<ModelReaderPtr> index(pMwm->m_cont.GetReader(INDEX_FILE_TAG),
                                         pMwm->m_factory);

        for (size_t i = 0; i < interval.size(); ++i)
        {
          index.ForEachInIntervalAndScale(MakeInsertFunctor(m_offsetsInViewport[mwmId]),
                                          interval[i].first, interval[i].second,
                                          scale);
        }
      }
    }
  }

  m_bOffsetsCacheIsValid = true;

  size_t offsetsCached = 0;
  for (MwmSet::MwmId mwmId = 0; mwmId < mwmInfo.size(); ++mwmId)
    offsetsCached += m_offsetsInViewport[mwmId].size();
  LOG(LDEBUG, ("For search in viewport cached ",
              "mwms:", mwmInfo.size(),
              "offsets:", offsetsCached));
}

void Query::Search(string const & query,
                   function<void (Result const &)> const & f,
                   unsigned int resultsNeeded)
{
  // Initialize.
  {
    m_rawQuery = query;
    m_uniQuery = NormalizeAndSimplifyString(m_rawQuery);
    m_tokens.clear();
    m_prefix.clear();

    search::Delimiters delims;
    SplitUniString(m_uniQuery, MakeBackInsertFunctor(m_tokens), delims);

    if (!m_tokens.empty() && !delims(strings::LastUniChar(m_rawQuery)))
    {
      m_prefix.swap(m_tokens.back());
      m_tokens.pop_back();
    }
    if (m_tokens.size() > 31)
      m_tokens.resize(31);

    vector<vector<int8_t> > langPriorities(3);
    langPriorities[0].push_back(m_preferredLanguage);
    langPriorities[1].push_back(StringUtf8Multilang::GetLangIndex("int_name"));
    langPriorities[1].push_back(StringUtf8Multilang::GetLangIndex("en"));
    langPriorities[2].push_back(StringUtf8Multilang::GetLangIndex("default"));
    m_pKeywordsScorer.reset(new LangKeywordsScorer(langPriorities,
                                                   m_tokens.data(), m_tokens.size(), &m_prefix));

    m_results = my::limited_priority_queue<impl::IntermediateResult>(resultsNeeded);
  }

  // Match (lat, lon).
  {
    double lat, lon, latPrec, lonPrec;
    if (search::MatchLatLon(m_rawQuery, lat, lon, latPrec, lonPrec))
    {
      string const region = m_pInfoGetter->GetRegionName(m2::PointD(MercatorBounds::LonToX(lon),
                                                                    MercatorBounds::LatToY(lat)));
      double const precision = 5.0 * max(0.0001, min(latPrec, lonPrec));  // Min 55 meters

      AddResult(impl::IntermediateResult(m_viewport, region, lat, lon, precision));
    }
  }

  SuggestStrings();

  SearchFeatures();

  FlushResults(f);
}

void Query::AddResult(impl::IntermediateResult const & result)
{
  m_results.push(result);
}

void Query::FlushResults(function<void (Result const &)> const & f)
{
  vector<impl::IntermediateResult> v(m_results.begin(), m_results.end());
  sort_heap(v.begin(), v.end());
  for (vector<impl::IntermediateResult>::const_iterator it = v.begin(); it != v.end(); ++it)
    f(it->GenerateFinalResult());
}

void Query::AddFeatureResult(FeatureType const & f, string const & fName)
{
  uint32_t penalty;
  string name;
  GetBestMatchName(f, penalty, name);
  AddResult(impl::IntermediateResult(m_viewport, f, name, GetRegionName(f, fName)));
}

namespace impl
{

class BestNameFinder
{
  uint32_t & m_penalty;
  string & m_name;
  LangKeywordsScorer & m_keywordsScorer;
public:
  BestNameFinder(uint32_t & penalty, string & name, LangKeywordsScorer & keywordsScorer)
    : m_penalty(penalty), m_name(name), m_keywordsScorer(keywordsScorer)
  {
    m_penalty = uint32_t(-1);
  }

  bool operator()(signed char lang, string const & name) const
  {
    uint32_t penalty = m_keywordsScorer.Score(lang, name);
    if (penalty < m_penalty)
    {
      m_penalty = penalty;
      m_name = name;
    }
    return true;
  }
};

}  // namespace search::impl

void Query::GetBestMatchName(FeatureType const & f, uint32_t & penalty, string & name)
{
  impl::BestNameFinder bestNameFinder(penalty, name, *m_pKeywordsScorer);
  f.ForEachNameRef(bestNameFinder);
}

string Query::GetRegionName(FeatureType const & f, string const & fName)
{
  if (!fName.empty())
  {
    return m_pInfoGetter->GetRegionName(fName);
  }
  else
  {
    if (f.GetFeatureType() == feature::GEOM_POINT)
      return m_pInfoGetter->GetRegionName(f.GetCenter());
  }

  return string();
}

namespace impl
{

struct FeatureLoader
{
  uint32_t m_count;
  FeaturesVector & m_featuresVector;
  Query & m_query;
  string m_fName;

  FeatureLoader(FeaturesVector & featuresVector, Query & query, string const & fName)
    : m_count(0), m_featuresVector(featuresVector), m_query(query), m_fName(fName)
  {
  }

  void operator() (uint32_t offset)
  {
    ++m_count;
    FeatureType feature;
    m_featuresVector.Get(offset, feature);
    m_query.AddFeatureResult(feature, m_fName);
  }
};

}  // namespace search::impl

void Query::SearchFeatures()
{
  if (!m_pIndex)
    return;

  vector<vector<strings::UniString> > tokens(m_tokens.size());

  // Add normal tokens.
  for (size_t i = 0; i < m_tokens.size(); ++i)
    tokens[i].push_back(m_tokens[i]);

  // Add names of categories.
  if (m_pCategories)
  {
    for (size_t i = 0; i < m_tokens.size(); ++i)
    {
      pair<CategoriesMapT::const_iterator, CategoriesMapT::const_iterator> range
          = m_pCategories->equal_range(m_tokens[i]);
      for (CategoriesMapT::const_iterator it = range.first; it != range.second; ++it)
        tokens[i].push_back(FeatureTypeToString(it->second));
    }
  }

  vector<MwmInfo> mwmInfo;
  m_pIndex->GetMwmInfo(mwmInfo);

  unordered_set<int8_t> langs;
  langs.insert(StringUtf8Multilang::GetLangIndex("int_name"));
  langs.insert(StringUtf8Multilang::GetLangIndex("en"));
  langs.insert(StringUtf8Multilang::GetLangIndex("default"));
  SearchFeatures(tokens, mwmInfo, langs, true);
}

void Query::SearchFeatures(vector<vector<strings::UniString> > const & tokens,
                           vector<MwmInfo> const & mwmInfo,
                           unordered_set<int8_t> const & langs,
                           bool onlyInViewport)
{
  for (MwmSet::MwmId mwmId = 0; mwmId < mwmInfo.size(); ++mwmId)
  {
    // Search only mwms that intersect with viewport (world always does).
    if (!onlyInViewport ||
        m_viewportExtended.IsIntersect(mwmInfo[mwmId].m_limitRect))
    {
      Index::MwmLock mwmLock(*m_pIndex, mwmId);
      if (MwmValue * pMwm = mwmLock.GetValue())
      {
        if (pMwm->m_cont.IsReaderExist(SEARCH_INDEX_FILE_TAG))
        {
          scoped_ptr<TrieIterator> pTrieRoot(::trie::reader::ReadTrie(
                                               pMwm->m_cont.GetReader(SEARCH_INDEX_FILE_TAG),
                                               ::search::trie::ValueReader(),
                                               ::search::trie::EdgeValueReader()));
          if (pTrieRoot)
          {
            for (size_t i = 0; i < pTrieRoot->m_edge.size(); ++i)
            {
              TrieIterator::Edge::EdgeStrT const & edge = pTrieRoot->m_edge[i].m_str;
              ASSERT_GREATER_OR_EQUAL(edge.size(), 1, ());
              // TODO: edge.size() > 1 !!
              if (edge.size() == 1 && edge[0] < 128 && langs.count(static_cast<int8_t>(edge[0])))
              {
                scoped_ptr<TrieIterator> pLangRoot(pTrieRoot->GoToEdge(i));

                feature::DataHeader const & h = pMwm->GetHeader();
                FeaturesVector featuresVector(pMwm->m_cont, h);
                impl::FeatureLoader f(
                      featuresVector,
                      *this,
                      (h.GetType() == feature::DataHeader::world) ? "" : mwmLock.GetCountryName());

                MatchFeaturesInTrie(tokens, m_prefix, *pLangRoot,
                                    &m_offsetsInViewport[mwmId], f, m_results.max_size() * 10);

                LOG(LDEBUG, ("Lang:",
                             StringUtf8Multilang::GetLangByCode(static_cast<int8_t>(edge[0])),
                             "Matched: ",
                             f.m_count));
              }
            }
          }
        }
      }
    }
  }
}

void Query::SuggestStrings()
{
  if (m_pStringsToSuggest)
  {
    typedef StringsToSuggestVectorT::const_iterator ItT;

    if (m_tokens.size() == 0 && !m_prefix.empty())
    {
      // Match prefix.
      for (ItT it = m_pStringsToSuggest->begin(); it != m_pStringsToSuggest->end(); ++it)
        if (it->second <= m_prefix.size() &&
            StartsWith(it->first.begin(), it->first.end(), m_prefix.begin(), m_prefix.end()))
          AddResult(impl::IntermediateResult(strings::ToUtf8(it->first), it->second));
    }
    else if (m_tokens.size() == 1)
    {
      // Match token + prefix.
      strings::UniString tokenAndPrefix = m_tokens[0];
      if (!m_prefix.empty())
      {
        tokenAndPrefix.push_back(' ');
        tokenAndPrefix.append(m_prefix.begin(), m_prefix.end());
      }
      for (ItT it = m_pStringsToSuggest->begin(); it != m_pStringsToSuggest->end(); ++it)
      {
        strings::UniString const & s = it->first;
        if (it->second <= tokenAndPrefix.size() &&
            StartsWith(s.begin(), s.end(), tokenAndPrefix.begin(), tokenAndPrefix.end()))
          AddResult(impl::IntermediateResult(strings::ToUtf8(it->first), it->second));
      }
    }
  }
}

}  // namespace search
<|endoftext|>


<commit_before><commit_msg>am 41bf75c6: am 287cd2d1: am bac309ca: Merge "RRO: idmap: fix sorting of overlays.list"<commit_after><|endoftext|>


<commit_before><commit_msg>TopCoder SRM647. Div2-1000.<commit_after><|endoftext|>


<commit_before><commit_msg>fix test cases for renamed/refactored SimpleRunnable stuff<commit_after><|endoftext|>


<commit_before><commit_msg>removed useless vector calcs<commit_after><|endoftext|>


<commit_before>
#pragma once

#include "numerics/pid.hpp"

#include <numeric>

#include "numerics/finite_difference.hpp"
#include "numerics/ulp_distance.hpp"

namespace principia {
namespace numerics {
namespace internal_pid {

using quantities::Product;
using quantities::Variation;

template<typename Value, int horizon, int finite_difference_order>
PID<Value, horizon, finite_difference_order>::PID(double const kp,
                                                       Inverse<Time> const& ki,
                                                       Time const& kd)
    : kp_(kp), ki_(ki), kd_(kd) {}

template<typename Value, int horizon, int finite_difference_order>
void PID<Value, horizon, finite_difference_order>::Clear() {
  errors_.clear();
}

template<typename Value, int horizon, int finite_difference_order>
Value PID<Value, horizon, finite_difference_order>::ComputeValue(
    Value const& process_variable,
    Value const& set_point,
    Time const& Δt) {
  // The PID is not prepared to receive inputs that are not equally spaced.
  // Clear it if that happens, but be very tolerant because KSP uses single-
  // precision float.
  if (previous_Δt_.has_value() && (Δt < previous_Δt_.value() * (1 - 1e-3) ||
                                   Δt > previous_Δt_.value() * (1 + 1e-3))) {
    Clear();
  }
  previous_Δt_ = Δt;

  errors_.push_back(process_variable - set_point);
  int size = errors_.size();
  if (size <= horizon) {
    // If we don't have enough error history, just return our input.
    return process_variable;
  }
  errors_.pop_front();
  --size;

  // The last error.
  Value proportional = errors_.back();

  // Compute the integral of the errors.  This is the dumbest possible algorithm
  // because we do not care too much about the accuracy.
  Product<Value, Time> const integral =
      std::accumulate(errors_.cbegin(), errors_.cend(), Value{}) * Δt;

  // Compute the derivative of the errors.
  std::array<Value, finite_difference_order> errors{};
  auto it = errors_.cend() - finite_difference_order;
  for (int i = 0; i < finite_difference_order; ++i, ++it) {
    errors[i] = *it;
  }
  Variation<Value> const derivative =
      FiniteDifference(errors, Δt, finite_difference_order - 1);

  return set_point + (kp_ * proportional + ki_ * integral + kd_ * derivative);
}

}  // namespace internal_pid
}  // namespace numerics
}  // namespace principia
<commit_msg>A trace.<commit_after>
#pragma once

#include "numerics/pid.hpp"

#include <numeric>

#include "numerics/finite_difference.hpp"

namespace principia {
namespace numerics {
namespace internal_pid {

using quantities::Product;
using quantities::Variation;

template<typename Value, int horizon, int finite_difference_order>
PID<Value, horizon, finite_difference_order>::PID(double const kp,
                                                  Inverse<Time> const& ki,
                                                  Time const& kd)
    : kp_(kp), ki_(ki), kd_(kd) {}

template<typename Value, int horizon, int finite_difference_order>
void PID<Value, horizon, finite_difference_order>::Clear() {
  errors_.clear();
}

template<typename Value, int horizon, int finite_difference_order>
Value PID<Value, horizon, finite_difference_order>::ComputeValue(
    Value const& process_variable,
    Value const& set_point,
    Time const& Δt) {
  // The PID is not prepared to receive inputs that are not equally spaced.
  // Clear it if that happens, but be very tolerant because KSP uses single-
  // precision float.
  if (previous_Δt_.has_value() && (Δt < previous_Δt_.value() * (1 - 1e-3) ||
                                   Δt > previous_Δt_.value() * (1 + 1e-3))) {
    LOG(WARNING) << "Resetting PID, " << Δt << " != " << previous_Δt_.value();
    Clear();
  }
  previous_Δt_ = Δt;

  errors_.push_back(process_variable - set_point);
  int size = errors_.size();
  if (size <= horizon) {
    // If we don't have enough error history, just return our input.
    return process_variable;
  }
  errors_.pop_front();
  --size;

  // The last error.
  Value proportional = errors_.back();

  // Compute the integral of the errors.  This is the dumbest possible algorithm
  // because we do not care too much about the accuracy.
  Product<Value, Time> const integral =
      std::accumulate(errors_.cbegin(), errors_.cend(), Value{}) * Δt;

  // Compute the derivative of the errors.
  std::array<Value, finite_difference_order> errors{};
  auto it = errors_.cend() - finite_difference_order;
  for (int i = 0; i < finite_difference_order; ++i, ++it) {
    errors[i] = *it;
  }
  Variation<Value> const derivative =
      FiniteDifference(errors, Δt, finite_difference_order - 1);

  return set_point + (kp_ * proportional + ki_ * integral + kd_ * derivative);
}

}  // namespace internal_pid
}  // namespace numerics
}  // namespace principia
<|endoftext|>


<commit_before>/*
 * GUI_Service.cpp
 *
 * Copyright (C) 2019 by MegaMol Team
 * Alle Rechte vorbehalten.
 */

#include "GUI_Service.hpp"

namespace megamol {
namespace frontend {

#define check_gui_not_nullptr (static_cast<bool>((this->m_gui != nullptr) && (this->m_gui->Get() != nullptr)))

GUI_Service::~GUI_Service() {

    // nothing to do here so far ...
}

bool GUI_Service::init(void* configPtr) {

    if (configPtr == nullptr) return false;
    return init(*static_cast<Config*>(configPtr));
}

bool GUI_Service::init(const Config& config) {

    // init resource state
    this->m_resource_state.time = 0.0;
    this->m_resource_state.framebuffer_size = glm::vec2(1.0f, 1.0f);
    this->m_resource_state.window_size = glm::vec2(1.0f, 1.0f);
    this->m_resource_state.opengl_context_ptr = nullptr;

    this->m_requestedResourcesNames = {
        {"MegaMolGraph"},                          // resource index 0
        {"WindowEvents"},                          // resource index 1
        {"KeyboardEvents"},                        // resource index 2
        {"MouseEvents"},                           // resource index 3
        {"IOpenGL_Context"},                       // resource index 4
        {"FramebufferEvents"},                     // resource index 5
        {"GLFrontbufferToPNG_ScreenshotTrigger"}   // resource index 6
    };

    // init gui
    if (config.imgui_api == GUI_Service::ImGuiAPI::OPEN_GL) {
        if (this->m_gui == nullptr) {
            this->m_gui = std::make_shared<megamol::gui::GUIWrapper>();

            if (check_gui_not_nullptr) {
                if (this->m_gui->Get()->CreateContext_GL(config.core_instance)) {
                    this->m_providedResourceReferences = { {"GUIResource", this->m_gui} };
                    megamol::core::utility::log::Log::DefaultLog.WriteInfo("GUI_Service: initialized successfully.");
                    return true;
                }
            }
        }
    }

    return false;
}

void GUI_Service::close() {

    // nothing to do here so far ...
}

void GUI_Service::updateProvidedResources() {

    // nothing to do here.
}

void GUI_Service::digestChangedRequestedResources() {

    if (!check_gui_not_nullptr) return;
    auto gui = this->m_gui->Get();

    // Trigger shutdown
    this->setShutdown(gui->ConsumeTriggeredShutdown());

    // Check for updates in requested resources --------------------------------

    /// MegaMolGraph = resource index 0
    auto graph_resource_ptr = &this->m_requestedResourceReferences[0].getResource<megamol::core::MegaMolGraph>();

    // Synchronise changes between core graph and gui graph
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    this->m_resource_state.megamol_graph = const_cast<megamol::core::MegaMolGraph*>(graph_resource_ptr);

    /// WindowEvents = resource index 1
    auto window_events = &this->m_requestedResourceReferences[1].getResource<megamol::module_resources::WindowEvents>();
    this->m_resource_state.time = window_events->time;
    for (auto& size_event : window_events->size_events) {
        m_resource_state.window_size.x = static_cast<float>(std::get<0>(size_event));
        m_resource_state.window_size.y = static_cast<float>(std::get<1>(size_event));
    }
    /* So far unused
    for (auto& event : window_events->dropped_path_events) {
        for (auto& file_path : event) {
            if (megamol::core::utility::graphics::ScreenShotComments::EndsWithCaseInsensitive(file_path, ".lua")) {
                m_queuedProjectFiles.push_back(file_path);
            }
        }
    }
    for (auto& file : m_queuedProjectFiles) {
        /// Propagate dropped project file to gui if requested (e.g. if configurator is hovered)
    }
    m_queuedProjectFiles.clear();
    */

    /// KeyboardEvents = resource index 2
    auto keyboard_events = &this->m_requestedResourceReferences[2].getResource<megamol::module_resources::KeyboardEvents>();

    std::vector<std::tuple<megamol::module_resources::Key, megamol::module_resources::KeyAction, megamol::module_resources::Modifiers>> pass_key_events;
    for (auto it = keyboard_events->key_events.begin(); it != keyboard_events->key_events.end(); it++) {
        auto key = std::get<0>((*it));
        auto action = std::get<1>((*it));
        auto modifiers = std::get<2>((*it));
        if (!gui->OnKey(key, action, modifiers)) {
            pass_key_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::KeyboardEvents*>(keyboard_events)->key_events = pass_key_events;

    std::vector<unsigned int> pass_codepoint_events;
    for (auto it = keyboard_events->codepoint_events.begin(); it != keyboard_events->codepoint_events.end(); it++) {
        if (!gui->OnChar((*it))) {
            pass_codepoint_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::KeyboardEvents*>(keyboard_events)->codepoint_events = pass_codepoint_events;

    /// MouseEvents = resource index 3
    auto mouse_events = &this->m_requestedResourceReferences[3].getResource<megamol::module_resources::MouseEvents>();

    std::vector<std::tuple<double, double>>  pass_mouse_pos_events;
    for (auto it = mouse_events->position_events.begin(); it != mouse_events->position_events.end(); it++) {
        auto x_pos = std::get<0>((*it));
        auto y_pos = std::get<1>((*it));
        if (!gui->OnMouseMove(x_pos, y_pos)) {
            pass_mouse_pos_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::MouseEvents*>(mouse_events)->position_events = pass_mouse_pos_events;

    std::vector<std::tuple<double, double>> pass_mouse_scroll_events;
    for (auto it = mouse_events->scroll_events.begin(); it != mouse_events->scroll_events.end(); it++) {
        auto x_scroll = std::get<0>((*it));
        auto y_scroll = std::get<1>((*it));
        if (!gui->OnMouseScroll(x_scroll, y_scroll)) {
            pass_mouse_scroll_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::MouseEvents*>(mouse_events)->scroll_events = pass_mouse_scroll_events;

    std::vector<std::tuple<megamol::module_resources::MouseButton, megamol::module_resources::MouseButtonAction, megamol::module_resources::Modifiers>>  pass_mouse_btn_events;
    for (auto it = mouse_events->buttons_events.begin(); it != mouse_events->buttons_events.end(); it++) {
        auto button = std::get<0>((*it));
        auto action = std::get<1>((*it));
        auto modifiers = std::get<2>((*it));
        if (!gui->OnMouseButton(button, action, modifiers)) {
            pass_mouse_btn_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::MouseEvents*>(mouse_events)->buttons_events = pass_mouse_btn_events;

    /// IOpenGL_Context = resource index 4
    this->m_resource_state.opengl_context_ptr = &this->m_requestedResourceReferences[4].getResource<megamol::module_resources::IOpenGL_Context>();

    /// FramebufferEvents = resource index 5
    auto framebuffer_events = &this->m_requestedResourceReferences[5].getResource<megamol::module_resources::FramebufferEvents>();
    for (auto& size_event : framebuffer_events->size_events) {
        m_resource_state.framebuffer_size.x = static_cast<float>(size_event.width);
        m_resource_state.framebuffer_size.y = static_cast<float>(size_event.height);
    }

    /// Trigger Screenshot = resource index 6
    if (gui->ConsumeTriggeredScreenshot()) {
        auto& screenshot_to_file_trigger = this->m_requestedResourceReferences[6].getResource< std::function<bool(std::string const&)> >();
        screenshot_to_file_trigger(gui->GetScreenshotFileName());
    }
}

void GUI_Service::resetProvidedResources() {

    // nothing to do here.
}

void GUI_Service::preGraphRender() {

    if (!check_gui_not_nullptr) return;
    auto gui = this->m_gui->Get();

    if (this->m_resource_state.opengl_context_ptr) {
        this->m_resource_state.opengl_context_ptr->activate();

        if (this->m_resource_state.megamol_graph != nullptr) {
            // Requires enabled OpenGL context
            gui->SynchronizeGraphs(this->m_resource_state.megamol_graph);
        }

        gui->PreDraw(this->m_resource_state.framebuffer_size, this->m_resource_state.window_size, this->m_resource_state.time);
        this->m_resource_state.opengl_context_ptr->close();
    }
}

void GUI_Service::postGraphRender() {

    if (!check_gui_not_nullptr) return;
    auto gui = this->m_gui->Get();

    if (this->m_resource_state.opengl_context_ptr) {
        this->m_resource_state.opengl_context_ptr->activate();
        gui->PostDraw();
        this->m_resource_state.opengl_context_ptr->close();
    }
}

std::vector<ModuleResource>& GUI_Service::getProvidedResources() {

    // unused - returning empty list
	return this->m_providedResourceReferences;
}

const std::vector<std::string> GUI_Service::getRequestedResourceNames() const {

    return this->m_requestedResourcesNames;
}

void GUI_Service::setRequestedResources(std::vector<ModuleResource> resources) {

    this->m_requestedResourceReferences = resources;
}

} // namespace frontend
} // namespace megamol
<commit_msg>minor renaming<commit_after>/*
 * GUI_Service.cpp
 *
 * Copyright (C) 2019 by MegaMol Team
 * Alle Rechte vorbehalten.
 */

#include "GUI_Service.hpp"

namespace megamol {
namespace frontend {

#define check_gui_not_nullptr (static_cast<bool>((this->m_gui != nullptr) && (this->m_gui->Get() != nullptr)))

GUI_Service::~GUI_Service() {

    // nothing to do here so far ...
}

bool GUI_Service::init(void* configPtr) {

    if (configPtr == nullptr) return false;
    return init(*static_cast<Config*>(configPtr));
}

bool GUI_Service::init(const Config& config) {

    // init resource state
    this->m_resource_state.time = 0.0;
    this->m_resource_state.framebuffer_size = glm::vec2(1.0f, 1.0f);
    this->m_resource_state.window_size = glm::vec2(1.0f, 1.0f);
    this->m_resource_state.opengl_context_ptr = nullptr;

    this->m_requestedResourcesNames = {
        {"MegaMolGraph"},                          // resource index 0
        {"WindowEvents"},                          // resource index 1
        {"KeyboardEvents"},                        // resource index 2
        {"MouseEvents"},                           // resource index 3
        {"IOpenGL_Context"},                       // resource index 4
        {"FramebufferEvents"},                     // resource index 5
        {"GLFrontbufferToPNG_ScreenshotTrigger"}   // resource index 6
    };

    // init gui
    if (config.imgui_api == GUI_Service::ImGuiAPI::OPEN_GL) {
        if (this->m_gui == nullptr) {
            this->m_gui = std::make_shared<megamol::gui::GUIWrapper>();

            if (check_gui_not_nullptr) {
                if (this->m_gui->Get()->CreateContext_GL(config.core_instance)) {
                    this->m_providedResourceReferences = { {"GUIResource", this->m_gui} };
                    megamol::core::utility::log::Log::DefaultLog.WriteInfo("GUI_Service: initialized successfully.");
                    return true;
                }
            }
        }
    }

    return false;
}

void GUI_Service::close() {

    // nothing to do here so far ...
}

void GUI_Service::updateProvidedResources() {

    // nothing to do here.
}

void GUI_Service::digestChangedRequestedResources() {

    if (!check_gui_not_nullptr) return;
    auto gui = this->m_gui->Get();

    // Trigger shutdown
    this->setShutdown(gui->ConsumeTriggeredShutdown());

    // Check for updates in requested resources --------------------------------

    /// MegaMolGraph = resource index 0
    auto graph_resource_ptr = &this->m_requestedResourceReferences[0].getResource<megamol::core::MegaMolGraph>();

    // Synchronise changes between core graph and gui graph
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    this->m_resource_state.megamol_graph = const_cast<megamol::core::MegaMolGraph*>(graph_resource_ptr);

    /// WindowEvents = resource index 1
    auto window_events = &this->m_requestedResourceReferences[1].getResource<megamol::module_resources::WindowEvents>();
    this->m_resource_state.time = window_events->time;
    for (auto& size_event : window_events->size_events) {
        m_resource_state.window_size.x = static_cast<float>(std::get<0>(size_event));
        m_resource_state.window_size.y = static_cast<float>(std::get<1>(size_event));
    }
    /* So far unused
    for (auto& event : window_events->dropped_path_events) {
        for (auto& file_path : event) {
            if (megamol::core::utility::graphics::ScreenShotComments::EndsWithCaseInsensitive(file_path, ".lua")) {
                m_queuedProjectFiles.push_back(file_path);
            }
        }
    }
    for (auto& file : m_queuedProjectFiles) {
        /// Propagate dropped project file to gui if requested (e.g. if configurator is hovered)
    }
    m_queuedProjectFiles.clear();
    */

    /// KeyboardEvents = resource index 2
    auto keyboard_events = &this->m_requestedResourceReferences[2].getResource<megamol::module_resources::KeyboardEvents>();

    std::vector<std::tuple<megamol::module_resources::Key, megamol::module_resources::KeyAction, megamol::module_resources::Modifiers>> pass_key_events;
    for (auto it = keyboard_events->key_events.begin(); it != keyboard_events->key_events.end(); it++) {
        auto key = std::get<0>((*it));
        auto action = std::get<1>((*it));
        auto modifiers = std::get<2>((*it));
        if (!gui->OnKey(key, action, modifiers)) {
            pass_key_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::KeyboardEvents*>(keyboard_events)->key_events = pass_key_events;

    std::vector<unsigned int> pass_codepoint_events;
    for (auto it = keyboard_events->codepoint_events.begin(); it != keyboard_events->codepoint_events.end(); it++) {
        if (!gui->OnChar((*it))) {
            pass_codepoint_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::KeyboardEvents*>(keyboard_events)->codepoint_events = pass_codepoint_events;

    /// MouseEvents = resource index 3
    auto mouse_events = &this->m_requestedResourceReferences[3].getResource<megamol::module_resources::MouseEvents>();

    std::vector<std::tuple<double, double>>  pass_mouse_pos_events;
    for (auto it = mouse_events->position_events.begin(); it != mouse_events->position_events.end(); it++) {
        auto x_pos = std::get<0>((*it));
        auto y_pos = std::get<1>((*it));
        if (!gui->OnMouseMove(x_pos, y_pos)) {
            pass_mouse_pos_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::MouseEvents*>(mouse_events)->position_events = pass_mouse_pos_events;

    std::vector<std::tuple<double, double>> pass_mouse_scroll_events;
    for (auto it = mouse_events->scroll_events.begin(); it != mouse_events->scroll_events.end(); it++) {
        auto x_scroll = std::get<0>((*it));
        auto y_scroll = std::get<1>((*it));
        if (!gui->OnMouseScroll(x_scroll, y_scroll)) {
            pass_mouse_scroll_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::MouseEvents*>(mouse_events)->scroll_events = pass_mouse_scroll_events;

    std::vector<std::tuple<megamol::module_resources::MouseButton, megamol::module_resources::MouseButtonAction, megamol::module_resources::Modifiers>>  pass_mouse_btn_events;
    for (auto it = mouse_events->buttons_events.begin(); it != mouse_events->buttons_events.end(); it++) {
        auto button = std::get<0>((*it));
        auto action = std::get<1>((*it));
        auto modifiers = std::get<2>((*it));
        if (!gui->OnMouseButton(button, action, modifiers)) {
            pass_mouse_btn_events.emplace_back((*it));
        }
    }
    /// WARNING: Changing a constant type will lead to an undefined behavior!
    const_cast<megamol::module_resources::MouseEvents*>(mouse_events)->buttons_events = pass_mouse_btn_events;

    /// IOpenGL_Context = resource index 4
    this->m_resource_state.opengl_context_ptr = &this->m_requestedResourceReferences[4].getResource<megamol::module_resources::IOpenGL_Context>();

    /// FramebufferEvents = resource index 5
    auto framebuffer_events = &this->m_requestedResourceReferences[5].getResource<megamol::module_resources::FramebufferEvents>();
    for (auto& size_event : framebuffer_events->size_events) {
        m_resource_state.framebuffer_size.x = static_cast<float>(size_event.width);
        m_resource_state.framebuffer_size.y = static_cast<float>(size_event.height);
    }

    /// Trigger Screenshot = resource index 6
    if (gui->ConsumeTriggeredScreenshot()) {
        auto& screenshot_to_file_trigger = this->m_requestedResourceReferences[6].getResource< std::function<bool(std::string const&)> >();
        screenshot_to_file_trigger(gui->ConsumeScreenshotFileName());
    }
}

void GUI_Service::resetProvidedResources() {

    // nothing to do here.
}

void GUI_Service::preGraphRender() {

    if (!check_gui_not_nullptr) return;
    auto gui = this->m_gui->Get();

    if (this->m_resource_state.opengl_context_ptr) {
        this->m_resource_state.opengl_context_ptr->activate();

        if (this->m_resource_state.megamol_graph != nullptr) {
            // Requires enabled OpenGL context
            gui->SynchronizeGraphs(this->m_resource_state.megamol_graph);
        }

        gui->PreDraw(this->m_resource_state.framebuffer_size, this->m_resource_state.window_size, this->m_resource_state.time);
        this->m_resource_state.opengl_context_ptr->close();
    }
}

void GUI_Service::postGraphRender() {

    if (!check_gui_not_nullptr) return;
    auto gui = this->m_gui->Get();

    if (this->m_resource_state.opengl_context_ptr) {
        this->m_resource_state.opengl_context_ptr->activate();
        gui->PostDraw();
        this->m_resource_state.opengl_context_ptr->close();
    }
}

std::vector<ModuleResource>& GUI_Service::getProvidedResources() {

    // unused - returning empty list
	return this->m_providedResourceReferences;
}

const std::vector<std::string> GUI_Service::getRequestedResourceNames() const {

    return this->m_requestedResourcesNames;
}

void GUI_Service::setRequestedResources(std::vector<ModuleResource> resources) {

    this->m_requestedResourceReferences = resources;
}

} // namespace frontend
} // namespace megamol
<|endoftext|>