<commit_before>
#include <vector>
#include <algorithm>
#include <cassert>
# include "mpi.h"

#include "types.hpp"
#include "fftwmpi.hpp"
#include "particle.hpp"
#include "interp.hpp"
#include "core.hpp"

int pic_fft(int argc, char* argv[]) {

  // Temp test params
  const int nt  = 20;
  const int ppc = 1;
  const FLOAT dt = 0.1;

  // Global problem setup
  const FLOAT Lz = 2*M_PI;
  const FLOAT Ly = 2*M_PI;
  const FLOAT Lx = 2*M_PI;

  const ptrdiff_t N0 = 128;
  const ptrdiff_t N1 = 128;
  const ptrdiff_t N2 = 128;

  const FLOAT dz = Lz/N0;
  const FLOAT dy = Ly/N1;
  const FLOAT dx = Lx/N2;
  const FLOAT V  = dz*dy*dx;
  const FLOAT Vi = 1.0/dz*dy*dx;

  // Build solver and get local params
  FFTWPoisson3DMPI solver(N0, Lz, N1, Ly, N2, Lx);
  const int nz = solver.get_nz();
  const int nx = solver.get_nx();
  const int ny = solver.get_ny();
  const int z0 = solver.get_z0();
  // Local domain length
  const FLOAT Lxl = nx*dx;
  const FLOAT Lyl = ny*dy;
  const FLOAT Lzl = nz*dz;
  const FLOAT Lz0 = z0*dz;

  // Field arrays
  std::vector<FLOAT> phi(nx*ny*nz, 0);
  std::vector<FLOAT> Ex(nx*ny*nz, 0);
  std::vector<FLOAT> Ey(nx*ny*nz, 0);
  std::vector<FLOAT> Ez(nx*ny*nz, 0);

  // Get MPI params
  int rank, size;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  const int right = (rank+1)%size;
  const int left  = rank>0 ? rank-1 : size-1;
  assert((left>=0) && (right<size));

  // Communication buffers
  std::vector<FLOAT> send_parts_right;
  std::vector<FLOAT> recv_parts_right;
  std::vector<FLOAT> send_parts_left;
  std::vector<FLOAT> recv_parts_left;

  // Construct particles
  ParticleList particles(ppc*ppc*ppc*nx*ny*nz);
  {
    const FLOAT pdx = dx/(ppc+1);
    const FLOAT pdy = dy/(ppc+1);
    const FLOAT pdz = dz/(ppc+1);
    FLOAT xl, yl, zl;
    for(int iz=0; iz<nz; ++iz)
      for(int iy=0; iy<ny; ++iy)
        for(int ix=0; ix<nx; ++ix) {
          xl = ix*dx;
          yl = iy*dy;
          zl = iz*dz;
          for(int pz=0; pz<ppc; ++pz)
            for(int py=0; py<ppc; ++py)
              for(int px=0; px<ppc; ++px) {
                particles.xp_.push_back(xl+px*pdx);
                particles.yp_.push_back(yl+py*pdy);
                particles.zp_.push_back(zl+pz*pdz);

                // TODO: Init particle velocities
                particles.vx_.push_back(1.0);
                particles.vy_.push_back(1.0);
                particles.vz_.push_back(1.0);

                particles.q_.push_back(1.0);
              }

        }

  }

  // Get global initial number of particles
  int init_n_parts;
  {
    int n_parts;
    n_parts = particles.size();
    MPI_Reduce(&n_parts, &init_n_parts, 1, MPI_INT, MPI_SUM, 0,
               MPI_COMM_WORLD);
  }

  int ind;
  std::vector<FLOAT> Exp, Eyp, Ezp;
  // Diagnostic vectors
  std::vector<int> vn_send_r(nt,0), vn_send_l(nt,0);
  std::vector<int> vn_recv_r(nt,0), vn_recv_l(nt,0);

  // Main time stepping loop
  for(int it=0; it<nt; ++it) {

    // Weight particles to mesh
    weight_cic_par(nz, ny, nx, &phi[0], particles.size(),
                   &particles.zp_[0], dz,
                   &particles.yp_[0], dy,
                   &particles.xp_[0], dx,
                   &particles.q_[0]);

    // Solve for phi
    for(int i=0; i<phi.size(); ++i)
      phi.at(i) *= Vi;

    solver.solve(&phi[0]);

    // Calc Exyz at grid points
    for(int iz=1; iz<nz-1; ++iz)
      for(int iy=1; iy<ny-1; ++iy)
        for(int ix=1; ix<nx-1; ++ix) {
          ind = iz*ny*nx+iy*nx+ix;
          Ex.at(ind) = (phi.at(ind+1)-phi.at(ind-1))/(2*dx);
          Ey.at(ind) = (phi.at(ind+nx)-phi.at(ind-nx))/(2*dy);
          Ez.at(ind) = (phi.at(ind+nx*ny)-phi.at(ind-nx*ny))/(2*dz);
        }

    // Weight Exyz to particles
    Exp.resize(particles.size());
    Eyp.resize(particles.size());
    Ezp.resize(particles.size());

    interp_cic_par(nz, ny, nx, &Ex[0],
                   particles.size(),
                   &particles.zp_[0], dz,
                   &particles.yp_[0], dy,
                   &particles.xp_[0], dx,
                   &Exp[0]);
    interp_cic_par(nz, ny, nx, &Ey[0],
                   particles.size(),
                   &particles.zp_[0], dz,
                   &particles.yp_[0], dy,
                   &particles.xp_[0], dx,
                   &Eyp[0]);
    interp_cic_par(nz, ny, nx, &Ez[0],
                   particles.size(),
                   &particles.zp_[0], dz,
                   &particles.yp_[0], dy,
                   &particles.xp_[0], dx,
                   &Ezp[0]);

    // Accel and move
    accel_par(particles.size(), dt, &particles.q_[0],
              &Ezp[0], &particles.vz_[0],
              &Eyp[0], &particles.vy_[0],
              &Exp[0], &particles.vx_[0]);

    move_par(particles.size(), dt,
             &particles.zp_[0], &particles.vz_[0],
             &particles.yp_[0], &particles.vy_[0],
             &particles.xp_[0], &particles.vx_[0]);

    // Find particles to send
    std::vector<int> to_send_right, to_send_left;
    for(int ipart=0; ipart<particles.size(); ++ipart)
      if(particles.zp_.at(ipart)>=Lzl)
        to_send_right.push_back(ipart);
      else if(particles.zp_.at(ipart)<0)
        to_send_left.push_back(ipart);

    // Communicate particles
    send_parts_right.resize(std::max<int>(1, to_send_right.size()*partFields));
    send_parts_left.resize(std::max<int>(1, to_send_left.size()*partFields));
    int ipart;
    for(int i=0; i<to_send_right.size(); ++i) {
      ipart = to_send_right.at(i);
      send_parts_right.at(i*partFields+0) = particles.xp_.at(ipart);
      send_parts_right.at(i*partFields+1) = particles.yp_.at(ipart);
      if(rank==size-1)
        // Periodic wrap around
        send_parts_right.at(i*partFields+2) = particles.zp_.at(ipart)-Lzl;
      else
        send_parts_right.at(i*partFields+2) = particles.zp_.at(ipart)+Lz0;
      send_parts_right.at(i*partFields+3) = particles.vx_.at(ipart);
      send_parts_right.at(i*partFields+4) = particles.vy_.at(ipart);
      send_parts_right.at(i*partFields+5) = particles.vz_.at(ipart);
      send_parts_right.at(i*partFields+6) = particles.q_.at(ipart);
    }
    for(int i=0; i<to_send_left.size(); ++i) {
      ipart = to_send_left.at(i);
      send_parts_left.at(i*partFields+0) = particles.xp_.at(ipart);
      send_parts_left.at(i*partFields+1) = particles.yp_.at(ipart);
      if(rank==0)
        send_parts_left.at(i*partFields+2) = Lz-particles.zp_.at(ipart);
      else
        send_parts_left.at(i*partFields+2) = particles.zp_.at(ipart)-Lz0;
      send_parts_left.at(i*partFields+3) = particles.vx_.at(ipart);
      send_parts_left.at(i*partFields+4) = particles.vy_.at(ipart);
      send_parts_left.at(i*partFields+5) = particles.vz_.at(ipart);
      send_parts_left.at(i*partFields+6) = particles.q_.at(ipart);
    }

    int n_send_r, n_send_l;
    int n_recv_r, n_recv_l;
    MPI_Request send_size[2], send_parts[2];

    n_send_r = to_send_right.size();
    n_send_l = to_send_left.size();
    MPI_Isend(&n_send_r, 1, MPI_INT, right, 0, MPI_COMM_WORLD, &send_size[0]);
    MPI_Isend(&n_send_l, 1, MPI_INT, left, 0, MPI_COMM_WORLD, &send_size[1]);

    MPI_Isend(&send_parts_right[0], n_send_r*partFields, MPI_DOUBLE, right,
              1, MPI_COMM_WORLD, &send_parts[0]);
    MPI_Isend(&send_parts_left[0], n_send_l*partFields, MPI_DOUBLE, left,
              1, MPI_COMM_WORLD, &send_parts[1]);

    MPI_Recv(&n_recv_r, 1, MPI_INT, right, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    MPI_Recv(&n_recv_l, 1, MPI_INT, left,  0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

    recv_parts_right.resize(std::max<int>(1, n_recv_r*partFields));
    recv_parts_left.resize(std::max<int>(1, n_recv_l*partFields));
    MPI_Recv(&recv_parts_right[0], n_recv_r*partFields, MPI_DOUBLE, right,
             1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    MPI_Recv(&recv_parts_left[0], n_recv_l*partFields, MPI_DOUBLE, left,
             1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

    MPI_Waitall(2, send_size,  MPI_STATUS_IGNORE);
    MPI_Waitall(2, send_parts, MPI_STATUS_IGNORE);

    // Update data structures
    particles.RemoveParticles(to_send_right);
    particles.RemoveParticles(to_send_left);
    for(int ipart=0; ipart<particles.size(); ++ipart)
      assert(particles.zp_.at(ipart)>=0 && particles.zp_.at(ipart)<Lzl);

    for(int ipart=0; ipart<n_recv_r; ++ipart) {
      particles.xp_.push_back(recv_parts_right.at(ipart*partFields+0));
      particles.yp_.push_back(recv_parts_right.at(ipart*partFields+1));
      particles.zp_.push_back(recv_parts_right.at(ipart*partFields+2)-Lz0);
      particles.vx_.push_back(recv_parts_right.at(ipart*partFields+3));
      particles.vy_.push_back(recv_parts_right.at(ipart*partFields+4));
      particles.vz_.push_back(recv_parts_right.at(ipart*partFields+5));
      particles.q_.push_back(recv_parts_right.at(ipart*partFields+6));
    }
    for(int ipart=0; ipart<n_recv_l; ++ipart) {
      particles.xp_.push_back(recv_parts_left.at(ipart*partFields+0));
      particles.yp_.push_back(recv_parts_left.at(ipart*partFields+1));
      particles.zp_.push_back(recv_parts_left.at(ipart*partFields+2)-Lz0);
      particles.vx_.push_back(recv_parts_left.at(ipart*partFields+3));
      particles.vy_.push_back(recv_parts_left.at(ipart*partFields+4));
      particles.vz_.push_back(recv_parts_left.at(ipart*partFields+5));
      particles.q_.push_back(recv_parts_left.at(ipart*partFields+6));
    }

    for(int ipart=0; ipart<particles.size(); ++ipart) {
      // Normalize particle positions
      if(particles.xp_.at(ipart)<0)
        particles.xp_.at(ipart) += Lxl;
      if(particles.yp_.at(ipart)<0)
        particles.yp_.at(ipart) += Lyl;
      if(particles.xp_.at(ipart)>=Lxl)
        particles.xp_.at(ipart) -= Lxl;
      if(particles.yp_.at(ipart)>=Lyl)
        particles.yp_.at(ipart) -= Lyl;

      assert(particles.xp_.at(ipart)>=0 && particles.xp_.at(ipart)<Lxl);
      assert(particles.yp_.at(ipart)>=0 && particles.yp_.at(ipart)<Lyl);
      assert(particles.zp_.at(ipart)>=0 && particles.zp_.at(ipart)<Lzl);

    }

    // Diagnostics
    {
      // Check total particle counts
      int part_sum, n_parts;
      n_parts = particles.size();
      MPI_Reduce(&n_parts, &part_sum, 1, MPI_INT, MPI_SUM, 0,
                 MPI_COMM_WORLD);
      if(rank==0)
        assert(part_sum==init_n_parts);

      // Save comm counts
      vn_send_r.at(it) = n_send_r;
      vn_send_l.at(it) = n_send_l;
      vn_recv_r.at(it) = n_recv_r;
      vn_recv_l.at(it) = n_recv_l;

    }

  }

}

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

  MPI_Init(&argc, &argv);
  fftw_mpi_init();

  pic_fft(argc, argv);

  MPI_Finalize();

}

<commit_msg>Basic timings.<commit_after>
#include <vector>
#include <algorithm>
#include <cassert>
# include "mpi.h"

#include "types.hpp"
#include "fftwmpi.hpp"
#include "particle.hpp"
#include "interp.hpp"
#include "core.hpp"

int pic_fft(int argc, char* argv[]) {

  // Temp test params
  const int nt  = 20;
  const int ppc = 1;
  const FLOAT dt = 0.1;

  // Global problem setup
  const FLOAT Lz = 2*M_PI;
  const FLOAT Ly = 2*M_PI;
  const FLOAT Lx = 2*M_PI;

  const ptrdiff_t N0 = 128;
  const ptrdiff_t N1 = 128;
  const ptrdiff_t N2 = 128;

  const FLOAT dz = Lz/N0;
  const FLOAT dy = Ly/N1;
  const FLOAT dx = Lx/N2;
  const FLOAT V  = dz*dy*dx;
  const FLOAT Vi = 1.0/dz*dy*dx;

  // Build solver and get local params
  FFTWPoisson3DMPI solver(N0, Lz, N1, Ly, N2, Lx);
  const int nz = solver.get_nz();
  const int nx = solver.get_nx();
  const int ny = solver.get_ny();
  const int z0 = solver.get_z0();
  // Local domain length
  const FLOAT Lxl = nx*dx;
  const FLOAT Lyl = ny*dy;
  const FLOAT Lzl = nz*dz;
  const FLOAT Lz0 = z0*dz;

  // Field arrays
  std::vector<FLOAT> phi(nx*ny*nz, 0);
  std::vector<FLOAT> Ex(nx*ny*nz, 0);
  std::vector<FLOAT> Ey(nx*ny*nz, 0);
  std::vector<FLOAT> Ez(nx*ny*nz, 0);

  // Get MPI params
  int rank, size;
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  const int right = (rank+1)%size;
  const int left  = rank>0 ? rank-1 : size-1;
  assert((left>=0) && (right<size));

  // Communication buffers
  std::vector<FLOAT> send_parts_right;
  std::vector<FLOAT> recv_parts_right;
  std::vector<FLOAT> send_parts_left;
  std::vector<FLOAT> recv_parts_left;

  // Construct particles
  ParticleList particles(ppc*ppc*ppc*nx*ny*nz);
  {
    const FLOAT pdx = dx/(ppc+1);
    const FLOAT pdy = dy/(ppc+1);
    const FLOAT pdz = dz/(ppc+1);
    FLOAT xl, yl, zl;
    for(int iz=0; iz<nz; ++iz)
      for(int iy=0; iy<ny; ++iy)
        for(int ix=0; ix<nx; ++ix) {
          xl = ix*dx;
          yl = iy*dy;
          zl = iz*dz;
          for(int pz=0; pz<ppc; ++pz)
            for(int py=0; py<ppc; ++py)
              for(int px=0; px<ppc; ++px) {
                particles.xp_.push_back(xl+px*pdx);
                particles.yp_.push_back(yl+py*pdy);
                particles.zp_.push_back(zl+pz*pdz);

                // TODO: Init particle velocities
                particles.vx_.push_back(1.0);
                particles.vy_.push_back(1.0);
                particles.vz_.push_back(1.0);

                particles.q_.push_back(1.0);
              }

        }

  }

  // Get global initial number of particles
  int init_n_parts;
  {
    int n_parts;
    n_parts = particles.size();
    MPI_Reduce(&n_parts, &init_n_parts, 1, MPI_INT, MPI_SUM, 0,
               MPI_COMM_WORLD);
  }

  int ind;
  std::vector<FLOAT> Exp, Eyp, Ezp;
  // Diagnostic vectors
  std::vector<int> vn_send_r(nt,0), vn_send_l(nt,0);
  std::vector<int> vn_recv_r(nt,0), vn_recv_l(nt,0);
  std::vector<FLOAT> t_field_solve(nt,0), t_weight(nt,0), t_interp(nt,0);
  std::vector<FLOAT> t_calc_E(nt,0), t_comm(nt,0), t_loop(nt,0);
  std::vector<FLOAT> t_accel(nt,0), t_move(nt,0);
  FLOAT t_start, t_end;
  FLOAT t_loop_start, t_loop_end;

  // Main time stepping loop
  MPI_Barrier(MPI_COMM_WORLD);
  for(int it=0; it<nt; ++it) {

    t_loop_start = MPI_Wtime();

    // Weight particles to mesh
    t_start = MPI_Wtime();
    weight_cic_par(nz, ny, nx, &phi[0], particles.size(),
                   &particles.zp_[0], dz,
                   &particles.yp_[0], dy,
                   &particles.xp_[0], dx,
                   &particles.q_[0]);
    t_end = MPI_Wtime();
    t_weight.at(it) = t_end-t_start;

    // Solve for phi
    t_start = MPI_Wtime();
    for(int i=0; i<phi.size(); ++i)
      phi.at(i) *= Vi;

    solver.solve(&phi[0]);
    t_end = MPI_Wtime();
    t_field_solve.at(it) = t_end-t_start;

    // Calc Exyz at grid points
    t_start = MPI_Wtime();
    for(int iz=1; iz<nz-1; ++iz)
      for(int iy=1; iy<ny-1; ++iy)
        for(int ix=1; ix<nx-1; ++ix) {
          ind = iz*ny*nx+iy*nx+ix;
          Ex.at(ind) = (phi.at(ind+1)-phi.at(ind-1))/(2*dx);
          Ey.at(ind) = (phi.at(ind+nx)-phi.at(ind-nx))/(2*dy);
          Ez.at(ind) = (phi.at(ind+nx*ny)-phi.at(ind-nx*ny))/(2*dz);
        }
    t_end = MPI_Wtime();
    t_calc_E.at(it) = t_end-t_start;

    // Weight Exyz to particles
    t_start = MPI_Wtime();
    Exp.resize(particles.size());
    Eyp.resize(particles.size());
    Ezp.resize(particles.size());

    interp_cic_par(nz, ny, nx, &Ex[0],
                   particles.size(),
                   &particles.zp_[0], dz,
                   &particles.yp_[0], dy,
                   &particles.xp_[0], dx,
                   &Exp[0]);
    interp_cic_par(nz, ny, nx, &Ey[0],
                   particles.size(),
                   &particles.zp_[0], dz,
                   &particles.yp_[0], dy,
                   &particles.xp_[0], dx,
                   &Eyp[0]);
    interp_cic_par(nz, ny, nx, &Ez[0],
                   particles.size(),
                   &particles.zp_[0], dz,
                   &particles.yp_[0], dy,
                   &particles.xp_[0], dx,
                   &Ezp[0]);
    t_end = MPI_Wtime();
    t_interp.at(it) = t_end-t_start;

    // Accel and move
    t_start = MPI_Wtime();
    accel_par(particles.size(), dt, &particles.q_[0],
              &Ezp[0], &particles.vz_[0],
              &Eyp[0], &particles.vy_[0],
              &Exp[0], &particles.vx_[0]);
    t_end = MPI_Wtime();
    t_accel.at(it) = t_end-t_start;

    t_start = MPI_Wtime();
    move_par(particles.size(), dt,
             &particles.zp_[0], &particles.vz_[0],
             &particles.yp_[0], &particles.vy_[0],
             &particles.xp_[0], &particles.vx_[0]);
    t_end = MPI_Wtime();
    t_move.at(it) = t_end-t_start;

    // Find particles to send
    t_start = MPI_Wtime();
    std::vector<int> to_send_right, to_send_left;
    for(int ipart=0; ipart<particles.size(); ++ipart)
      if(particles.zp_.at(ipart)>=Lzl)
        to_send_right.push_back(ipart);
      else if(particles.zp_.at(ipart)<0)
        to_send_left.push_back(ipart);

    // Communicate particles
    send_parts_right.resize(std::max<int>(1, to_send_right.size()*partFields));
    send_parts_left.resize(std::max<int>(1, to_send_left.size()*partFields));
    int ipart;
    for(int i=0; i<to_send_right.size(); ++i) {
      ipart = to_send_right.at(i);
      send_parts_right.at(i*partFields+0) = particles.xp_.at(ipart);
      send_parts_right.at(i*partFields+1) = particles.yp_.at(ipart);
      if(rank==size-1)
        // Periodic wrap around
        send_parts_right.at(i*partFields+2) = particles.zp_.at(ipart)-Lzl;
      else
        send_parts_right.at(i*partFields+2) = particles.zp_.at(ipart)+Lz0;
      send_parts_right.at(i*partFields+3) = particles.vx_.at(ipart);
      send_parts_right.at(i*partFields+4) = particles.vy_.at(ipart);
      send_parts_right.at(i*partFields+5) = particles.vz_.at(ipart);
      send_parts_right.at(i*partFields+6) = particles.q_.at(ipart);
    }
    for(int i=0; i<to_send_left.size(); ++i) {
      ipart = to_send_left.at(i);
      send_parts_left.at(i*partFields+0) = particles.xp_.at(ipart);
      send_parts_left.at(i*partFields+1) = particles.yp_.at(ipart);
      if(rank==0)
        send_parts_left.at(i*partFields+2) = Lz-particles.zp_.at(ipart);
      else
        send_parts_left.at(i*partFields+2) = particles.zp_.at(ipart)-Lz0;
      send_parts_left.at(i*partFields+3) = particles.vx_.at(ipart);
      send_parts_left.at(i*partFields+4) = particles.vy_.at(ipart);
      send_parts_left.at(i*partFields+5) = particles.vz_.at(ipart);
      send_parts_left.at(i*partFields+6) = particles.q_.at(ipart);
    }

    int n_send_r, n_send_l;
    int n_recv_r, n_recv_l;
    MPI_Request send_size[2], send_parts[2];

    n_send_r = to_send_right.size();
    n_send_l = to_send_left.size();
    MPI_Isend(&n_send_r, 1, MPI_INT, right, 0, MPI_COMM_WORLD, &send_size[0]);
    MPI_Isend(&n_send_l, 1, MPI_INT, left, 0, MPI_COMM_WORLD, &send_size[1]);

    MPI_Isend(&send_parts_right[0], n_send_r*partFields, MPI_DOUBLE, right,
              1, MPI_COMM_WORLD, &send_parts[0]);
    MPI_Isend(&send_parts_left[0], n_send_l*partFields, MPI_DOUBLE, left,
              1, MPI_COMM_WORLD, &send_parts[1]);

    MPI_Recv(&n_recv_r, 1, MPI_INT, right, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    MPI_Recv(&n_recv_l, 1, MPI_INT, left,  0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

    recv_parts_right.resize(std::max<int>(1, n_recv_r*partFields));
    recv_parts_left.resize(std::max<int>(1, n_recv_l*partFields));
    MPI_Recv(&recv_parts_right[0], n_recv_r*partFields, MPI_DOUBLE, right,
             1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    MPI_Recv(&recv_parts_left[0], n_recv_l*partFields, MPI_DOUBLE, left,
             1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

    MPI_Waitall(2, send_size,  MPI_STATUS_IGNORE);
    MPI_Waitall(2, send_parts, MPI_STATUS_IGNORE);

    // Update data structures
    particles.RemoveParticles(to_send_right);
    particles.RemoveParticles(to_send_left);
    for(int ipart=0; ipart<particles.size(); ++ipart)
      assert(particles.zp_.at(ipart)>=0 && particles.zp_.at(ipart)<Lzl);

    for(int ipart=0; ipart<n_recv_r; ++ipart) {
      particles.xp_.push_back(recv_parts_right.at(ipart*partFields+0));
      particles.yp_.push_back(recv_parts_right.at(ipart*partFields+1));
      particles.zp_.push_back(recv_parts_right.at(ipart*partFields+2)-Lz0);
      particles.vx_.push_back(recv_parts_right.at(ipart*partFields+3));
      particles.vy_.push_back(recv_parts_right.at(ipart*partFields+4));
      particles.vz_.push_back(recv_parts_right.at(ipart*partFields+5));
      particles.q_.push_back(recv_parts_right.at(ipart*partFields+6));
    }
    for(int ipart=0; ipart<n_recv_l; ++ipart) {
      particles.xp_.push_back(recv_parts_left.at(ipart*partFields+0));
      particles.yp_.push_back(recv_parts_left.at(ipart*partFields+1));
      particles.zp_.push_back(recv_parts_left.at(ipart*partFields+2)-Lz0);
      particles.vx_.push_back(recv_parts_left.at(ipart*partFields+3));
      particles.vy_.push_back(recv_parts_left.at(ipart*partFields+4));
      particles.vz_.push_back(recv_parts_left.at(ipart*partFields+5));
      particles.q_.push_back(recv_parts_left.at(ipart*partFields+6));
    }

    for(int ipart=0; ipart<particles.size(); ++ipart) {
      // Normalize particle positions
      if(particles.xp_.at(ipart)<0)
        particles.xp_.at(ipart) += Lxl;
      if(particles.yp_.at(ipart)<0)
        particles.yp_.at(ipart) += Lyl;
      if(particles.xp_.at(ipart)>=Lxl)
        particles.xp_.at(ipart) -= Lxl;
      if(particles.yp_.at(ipart)>=Lyl)
        particles.yp_.at(ipart) -= Lyl;

      assert(particles.xp_.at(ipart)>=0 && particles.xp_.at(ipart)<Lxl);
      assert(particles.yp_.at(ipart)>=0 && particles.yp_.at(ipart)<Lyl);
      assert(particles.zp_.at(ipart)>=0 && particles.zp_.at(ipart)<Lzl);

    }

    t_end = MPI_Wtime();
    t_comm.at(it) = t_end-t_start;

    // Diagnostics
    {
      // Check total particle counts
      int part_sum, n_parts;
      n_parts = particles.size();
      MPI_Reduce(&n_parts, &part_sum, 1, MPI_INT, MPI_SUM, 0,
                 MPI_COMM_WORLD);
      if(rank==0)
        assert(part_sum==init_n_parts);

      // Save comm counts
      vn_send_r.at(it) = n_send_r;
      vn_send_l.at(it) = n_send_l;
      vn_recv_r.at(it) = n_recv_r;
      vn_recv_l.at(it) = n_recv_l;

    }

    t_loop_end = MPI_Wtime();
    t_loop.at(it) = t_loop_end-t_loop_start;

    if(rank==0)
      std::cout << it+1 << ' ' << t_loop.at(it) << std::endl;;

  }

}

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

  MPI_Init(&argc, &argv);
  fftw_mpi_init();

  pic_fft(argc, argv);

  MPI_Finalize();

}

<|endoftext|>


<commit_before>#include "sieve.h"

namespace
{
bool is_prime(int n)
{
    if (n % 2 == 0) {
        return false;
    }
    for (int probe = 2, end = static_cast<int>(std::sqrt(n)); probe <= end; ++probe) {
        if (n % probe == 0) {
            return false;
        }
    }
    return true;
}
}

namespace sieve
{

std::vector<int> primes(int n)
{
    std::vector<int> result;
    if (n >= 2) {
        result.push_back(2);
    }
    for (int candidate = 3; candidate < n; ++candidate) {
        if (is_prime(candidate)) {
            result.push_back(candidate);
        }
    }
    return result;
}

}
<commit_msg>std::sqrt comes from <cmath><commit_after>#include "sieve.h"
#include <cmath>

namespace
{
bool is_prime(int n)
{
    if (n % 2 == 0) {
        return false;
    }
    for (int probe = 2, end = static_cast<int>(std::sqrt(n)); probe <= end; ++probe) {
        if (n % probe == 0) {
            return false;
        }
    }
    return true;
}
}

namespace sieve
{

std::vector<int> primes(int n)
{
    std::vector<int> result;
    if (n >= 2) {
        result.push_back(2);
    }
    for (int candidate = 3; candidate < n; ++candidate) {
        if (is_prime(candidate)) {
            result.push_back(candidate);
        }
    }
    return result;
}

}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LineMarker.cxx
 ** Defines the look of a line marker in the margin .
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "XPM.h"
#include "LineMarker.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

void LineMarker::RefreshColourPalette(Palette &pal, bool want) {
	pal.WantFind(fore, want);
	pal.WantFind(back, want);
	if (pxpm) {
		pxpm->RefreshColourPalette(pal, want);
	}
}

void LineMarker::SetXPM(const char *textForm) {
	delete pxpm;
	pxpm = new XPM(textForm);
	markType = SC_MARK_PIXMAP;
}

void LineMarker::SetXPM(const char *const *linesForm) {
	delete pxpm;
	pxpm = new XPM(linesForm);
	markType = SC_MARK_PIXMAP;
}

static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
	PRectangle rc;
	rc.left = centreX - armSize;
	rc.top = centreY - armSize;
	rc.right = centreX + armSize + 1;
	rc.bottom = centreY + armSize + 1;
	surface->RectangleDraw(rc, back, fore);
}

static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
	PRectangle rcCircle;
	rcCircle.left = centreX - armSize;
	rcCircle.top = centreY - armSize;
	rcCircle.right = centreX + armSize + 1;
	rcCircle.bottom = centreY + armSize + 1;
	surface->Ellipse(rcCircle, back, fore);
}

static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
	PRectangle rcV(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
	surface->FillRectangle(rcV, fore);
	PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
	surface->FillRectangle(rcH, fore);
}

static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
	PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
	surface->FillRectangle(rcH, fore);
}

void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter) {
	if ((markType == SC_MARK_PIXMAP) && (pxpm)) {
		pxpm->Draw(surface, rcWhole);
		return;
	}
	// Restrict most shapes a bit
	PRectangle rc = rcWhole;
	rc.top++;
	rc.bottom--;
	int minDim = Platform::Minimum(rc.Width(), rc.Height());
	minDim--;	// Ensure does not go beyond edge
	int centreX = (rc.right + rc.left) / 2;
	int centreY = (rc.bottom + rc.top) / 2;
	int dimOn2 = minDim / 2;
	int dimOn4 = minDim / 4;
	int blobSize = dimOn2-1;
	int armSize = dimOn2-2;
	if (rc.Width() > (rc.Height() * 2)) {
		// Wide column is line number so move to left to try to avoid overlapping number
		centreX = rc.left + dimOn2 + 1;
	}
	if (markType == SC_MARK_ROUNDRECT) {
		PRectangle rcRounded = rc;
		rcRounded.left = rc.left + 1;
		rcRounded.right = rc.right - 1;
		surface->RoundedRectangle(rcRounded, fore.allocated, back.allocated);
	} else if (markType == SC_MARK_CIRCLE) {
		PRectangle rcCircle;
		rcCircle.left = centreX - dimOn2;
		rcCircle.top = centreY - dimOn2;
		rcCircle.right = centreX + dimOn2;
		rcCircle.bottom = centreY + dimOn2;
		surface->Ellipse(rcCircle, fore.allocated, back.allocated);
	} else if (markType == SC_MARK_ARROW) {
		Point pts[] = {
    		Point(centreX - dimOn4, centreY - dimOn2),
    		Point(centreX - dimOn4, centreY + dimOn2),
    		Point(centreX + dimOn2 - dimOn4, centreY),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore.allocated, back.allocated);

	} else if (markType == SC_MARK_ARROWDOWN) {
		Point pts[] = {
    		Point(centreX - dimOn2, centreY - dimOn4),
    		Point(centreX + dimOn2, centreY - dimOn4),
    		Point(centreX, centreY + dimOn2 - dimOn4),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore.allocated, back.allocated);

	} else if (markType == SC_MARK_PLUS) {
		Point pts[] = {
    		Point(centreX - armSize, centreY - 1),
    		Point(centreX - 1, centreY - 1),
    		Point(centreX - 1, centreY - armSize),
    		Point(centreX + 1, centreY - armSize),
    		Point(centreX + 1, centreY - 1),
    		Point(centreX + armSize, centreY -1),
    		Point(centreX + armSize, centreY +1),
    		Point(centreX + 1, centreY + 1),
    		Point(centreX + 1, centreY + armSize),
    		Point(centreX - 1, centreY + armSize),
    		Point(centreX - 1, centreY + 1),
    		Point(centreX - armSize, centreY + 1),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore.allocated, back.allocated);

	} else if (markType == SC_MARK_MINUS) {
		Point pts[] = {
    		Point(centreX - armSize, centreY - 1),
    		Point(centreX + armSize, centreY -1),
    		Point(centreX + armSize, centreY +1),
    		Point(centreX - armSize, centreY + 1),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore.allocated, back.allocated);

	} else if (markType == SC_MARK_SMALLRECT) {
		PRectangle rcSmall;
		rcSmall.left = rc.left + 1;
		rcSmall.top = rc.top + 2;
		rcSmall.right = rc.right - 1;
		rcSmall.bottom = rc.bottom - 2;
		surface->RectangleDraw(rcSmall, fore.allocated, back.allocated);

	} else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND ||
		markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) {
		// An invisible marker so don't draw anything

	} else if (markType == SC_MARK_VLINE) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rcWhole.bottom + 1);

	} else if (markType == SC_MARK_LCORNER) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rc.top + dimOn2);
		surface->LineTo(rc.right - 2, rc.top + dimOn2);

	} else if (markType == SC_MARK_TCORNER) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rcWhole.bottom + 1);
		surface->MoveTo(centreX, rc.top + dimOn2);
		surface->LineTo(rc.right - 2, rc.top + dimOn2);

	} else if (markType == SC_MARK_LCORNERCURVE) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rc.top + dimOn2-3);
		surface->LineTo(centreX+3, rc.top + dimOn2);
		surface->LineTo(rc.right - 1, rc.top + dimOn2);

	} else if (markType == SC_MARK_TCORNERCURVE) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rcWhole.bottom + 1);

		surface->MoveTo(centreX, rc.top + dimOn2-3);
		surface->LineTo(centreX+3, rc.top + dimOn2);
		surface->LineTo(rc.right - 1, rc.top + dimOn2);

	} else if (markType == SC_MARK_BOXPLUS) {
		surface->PenColour(back.allocated);
		DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		DrawPlus(surface, centreX, centreY, blobSize, back.allocated);

	} else if (markType == SC_MARK_BOXPLUSCONNECTED) {
		surface->PenColour(back.allocated);
		DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		DrawPlus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom + 1);

		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize + 1);

	} else if (markType == SC_MARK_BOXMINUS) {
		surface->PenColour(back.allocated);
		DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		DrawMinus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom + 1);

	} else if (markType == SC_MARK_BOXMINUSCONNECTED) {
		surface->PenColour(back.allocated);
		DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		DrawMinus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom + 1);

		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize + 1);

	} else if (markType == SC_MARK_CIRCLEPLUS) {
		DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		surface->PenColour(back.allocated);
		DrawPlus(surface, centreX, centreY, blobSize, back.allocated);

	} else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) {
		DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		surface->PenColour(back.allocated);
		DrawPlus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom + 1);

		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize + 1);

	} else if (markType == SC_MARK_CIRCLEMINUS) {
		DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		surface->PenColour(back.allocated);
		DrawMinus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom + 1);

	} else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) {
		DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		surface->PenColour(back.allocated);
		DrawMinus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom + 1);

		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize + 1);

	} else if (markType >= SC_MARK_CHARACTER) {
		char character[1];
		character[0] = static_cast<char>(markType - SC_MARK_CHARACTER);
		int width = surface->WidthText(fontForCharacter, character, 1);
		rc.left += (rc.Width() - width) / 2;
		rc.right = rc.left + width;
		surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2,
			character, 1, fore.allocated, back.allocated);

	} else if (markType == SC_MARK_DOTDOTDOT) {
		int right = centreX - 6;
		for (int b=0; b<3; b++) {
			PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2);
			surface->FillRectangle(rcBlob, fore.allocated);
			right += 5;
		}
	} else if (markType == SC_MARK_ARROWS) {
		surface->PenColour(fore.allocated);
		int right = centreX - 2;
		for (int b=0; b<3; b++) {
			surface->MoveTo(right - 4, centreY - 4);
			surface->LineTo(right, centreY);
			surface->LineTo(right - 5, centreY + 5);
			right += 4;
		}
	} else if (markType == SC_MARK_SHORTARROW) {
		Point pts[] = {
			Point(centreX, centreY + dimOn2),
			Point(centreX + dimOn2, centreY),
			Point(centreX, centreY - dimOn2),
			Point(centreX, centreY - dimOn4),
			Point(centreX - dimOn4, centreY - dimOn4),
			Point(centreX - dimOn4, centreY + dimOn4),
			Point(centreX, centreY + dimOn4),
			Point(centreX, centreY + dimOn2),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
				fore.allocated, back.allocated);
	} else if (markType == SC_MARK_LEFTRECT) {
		PRectangle rcLeft = rcWhole;
		rcLeft.right = rcLeft.left + 4;
		surface->FillRectangle(rcLeft, back.allocated);
	} else { // SC_MARK_FULLRECT
		surface->FillRectangle(rcWhole, back.allocated);
	}
}
<commit_msg>Undo previous change to folding markers as can be fixed Cairo drawing can be fixed in PlatGTK.cxx.<commit_after>// Scintilla source code edit control
/** @file LineMarker.cxx
 ** Defines the look of a line marker in the margin .
 **/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <string.h>

#include "Platform.h"

#include "Scintilla.h"
#include "XPM.h"
#include "LineMarker.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

void LineMarker::RefreshColourPalette(Palette &pal, bool want) {
	pal.WantFind(fore, want);
	pal.WantFind(back, want);
	if (pxpm) {
		pxpm->RefreshColourPalette(pal, want);
	}
}

void LineMarker::SetXPM(const char *textForm) {
	delete pxpm;
	pxpm = new XPM(textForm);
	markType = SC_MARK_PIXMAP;
}

void LineMarker::SetXPM(const char *const *linesForm) {
	delete pxpm;
	pxpm = new XPM(linesForm);
	markType = SC_MARK_PIXMAP;
}

static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
	PRectangle rc;
	rc.left = centreX - armSize;
	rc.top = centreY - armSize;
	rc.right = centreX + armSize + 1;
	rc.bottom = centreY + armSize + 1;
	surface->RectangleDraw(rc, back, fore);
}

static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) {
	PRectangle rcCircle;
	rcCircle.left = centreX - armSize;
	rcCircle.top = centreY - armSize;
	rcCircle.right = centreX + armSize + 1;
	rcCircle.bottom = centreY + armSize + 1;
	surface->Ellipse(rcCircle, back, fore);
}

static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
	PRectangle rcV(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
	surface->FillRectangle(rcV, fore);
	PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
	surface->FillRectangle(rcH, fore);
}

static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) {
	PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1);
	surface->FillRectangle(rcH, fore);
}

void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter) {
	if ((markType == SC_MARK_PIXMAP) && (pxpm)) {
		pxpm->Draw(surface, rcWhole);
		return;
	}
	// Restrict most shapes a bit
	PRectangle rc = rcWhole;
	rc.top++;
	rc.bottom--;
	int minDim = Platform::Minimum(rc.Width(), rc.Height());
	minDim--;	// Ensure does not go beyond edge
	int centreX = (rc.right + rc.left) / 2;
	int centreY = (rc.bottom + rc.top) / 2;
	int dimOn2 = minDim / 2;
	int dimOn4 = minDim / 4;
	int blobSize = dimOn2-1;
	int armSize = dimOn2-2;
	if (rc.Width() > (rc.Height() * 2)) {
		// Wide column is line number so move to left to try to avoid overlapping number
		centreX = rc.left + dimOn2 + 1;
	}
	if (markType == SC_MARK_ROUNDRECT) {
		PRectangle rcRounded = rc;
		rcRounded.left = rc.left + 1;
		rcRounded.right = rc.right - 1;
		surface->RoundedRectangle(rcRounded, fore.allocated, back.allocated);
	} else if (markType == SC_MARK_CIRCLE) {
		PRectangle rcCircle;
		rcCircle.left = centreX - dimOn2;
		rcCircle.top = centreY - dimOn2;
		rcCircle.right = centreX + dimOn2;
		rcCircle.bottom = centreY + dimOn2;
		surface->Ellipse(rcCircle, fore.allocated, back.allocated);
	} else if (markType == SC_MARK_ARROW) {
		Point pts[] = {
    		Point(centreX - dimOn4, centreY - dimOn2),
    		Point(centreX - dimOn4, centreY + dimOn2),
    		Point(centreX + dimOn2 - dimOn4, centreY),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore.allocated, back.allocated);

	} else if (markType == SC_MARK_ARROWDOWN) {
		Point pts[] = {
    		Point(centreX - dimOn2, centreY - dimOn4),
    		Point(centreX + dimOn2, centreY - dimOn4),
    		Point(centreX, centreY + dimOn2 - dimOn4),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore.allocated, back.allocated);

	} else if (markType == SC_MARK_PLUS) {
		Point pts[] = {
    		Point(centreX - armSize, centreY - 1),
    		Point(centreX - 1, centreY - 1),
    		Point(centreX - 1, centreY - armSize),
    		Point(centreX + 1, centreY - armSize),
    		Point(centreX + 1, centreY - 1),
    		Point(centreX + armSize, centreY -1),
    		Point(centreX + armSize, centreY +1),
    		Point(centreX + 1, centreY + 1),
    		Point(centreX + 1, centreY + armSize),
    		Point(centreX - 1, centreY + armSize),
    		Point(centreX - 1, centreY + 1),
    		Point(centreX - armSize, centreY + 1),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore.allocated, back.allocated);

	} else if (markType == SC_MARK_MINUS) {
		Point pts[] = {
    		Point(centreX - armSize, centreY - 1),
    		Point(centreX + armSize, centreY -1),
    		Point(centreX + armSize, centreY +1),
    		Point(centreX - armSize, centreY + 1),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                 		fore.allocated, back.allocated);

	} else if (markType == SC_MARK_SMALLRECT) {
		PRectangle rcSmall;
		rcSmall.left = rc.left + 1;
		rcSmall.top = rc.top + 2;
		rcSmall.right = rc.right - 1;
		rcSmall.bottom = rc.bottom - 2;
		surface->RectangleDraw(rcSmall, fore.allocated, back.allocated);

	} else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND ||
		markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) {
		// An invisible marker so don't draw anything

	} else if (markType == SC_MARK_VLINE) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rcWhole.bottom);

	} else if (markType == SC_MARK_LCORNER) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rc.top + dimOn2);
		surface->LineTo(rc.right - 2, rc.top + dimOn2);

	} else if (markType == SC_MARK_TCORNER) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rcWhole.bottom);
		surface->MoveTo(centreX, rc.top + dimOn2);
		surface->LineTo(rc.right - 2, rc.top + dimOn2);

	} else if (markType == SC_MARK_LCORNERCURVE) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rc.top + dimOn2-3);
		surface->LineTo(centreX+3, rc.top + dimOn2);
		surface->LineTo(rc.right - 1, rc.top + dimOn2);

	} else if (markType == SC_MARK_TCORNERCURVE) {
		surface->PenColour(back.allocated);
		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, rcWhole.bottom);

		surface->MoveTo(centreX, rc.top + dimOn2-3);
		surface->LineTo(centreX+3, rc.top + dimOn2);
		surface->LineTo(rc.right - 1, rc.top + dimOn2);

	} else if (markType == SC_MARK_BOXPLUS) {
		surface->PenColour(back.allocated);
		DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		DrawPlus(surface, centreX, centreY, blobSize, back.allocated);

	} else if (markType == SC_MARK_BOXPLUSCONNECTED) {
		surface->PenColour(back.allocated);
		DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		DrawPlus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize);

	} else if (markType == SC_MARK_BOXMINUS) {
		surface->PenColour(back.allocated);
		DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		DrawMinus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

	} else if (markType == SC_MARK_BOXMINUSCONNECTED) {
		surface->PenColour(back.allocated);
		DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		DrawMinus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize);

	} else if (markType == SC_MARK_CIRCLEPLUS) {
		DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		surface->PenColour(back.allocated);
		DrawPlus(surface, centreX, centreY, blobSize, back.allocated);

	} else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) {
		DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		surface->PenColour(back.allocated);
		DrawPlus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize);

	} else if (markType == SC_MARK_CIRCLEMINUS) {
		DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		surface->PenColour(back.allocated);
		DrawMinus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

	} else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) {
		DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated);
		surface->PenColour(back.allocated);
		DrawMinus(surface, centreX, centreY, blobSize, back.allocated);

		surface->MoveTo(centreX, centreY + blobSize);
		surface->LineTo(centreX, rcWhole.bottom);

		surface->MoveTo(centreX, rcWhole.top);
		surface->LineTo(centreX, centreY - blobSize);

	} else if (markType >= SC_MARK_CHARACTER) {
		char character[1];
		character[0] = static_cast<char>(markType - SC_MARK_CHARACTER);
		int width = surface->WidthText(fontForCharacter, character, 1);
		rc.left += (rc.Width() - width) / 2;
		rc.right = rc.left + width;
		surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2,
			character, 1, fore.allocated, back.allocated);

	} else if (markType == SC_MARK_DOTDOTDOT) {
		int right = centreX - 6;
		for (int b=0; b<3; b++) {
			PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2);
			surface->FillRectangle(rcBlob, fore.allocated);
			right += 5;
		}
	} else if (markType == SC_MARK_ARROWS) {
		surface->PenColour(fore.allocated);
		int right = centreX - 2;
		for (int b=0; b<3; b++) {
			surface->MoveTo(right - 4, centreY - 4);
			surface->LineTo(right, centreY);
			surface->LineTo(right - 5, centreY + 5);
			right += 4;
		}
	} else if (markType == SC_MARK_SHORTARROW) {
		Point pts[] = {
			Point(centreX, centreY + dimOn2),
			Point(centreX + dimOn2, centreY),
			Point(centreX, centreY - dimOn2),
			Point(centreX, centreY - dimOn4),
			Point(centreX - dimOn4, centreY - dimOn4),
			Point(centreX - dimOn4, centreY + dimOn4),
			Point(centreX, centreY + dimOn4),
			Point(centreX, centreY + dimOn2),
		};
		surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
				fore.allocated, back.allocated);
	} else if (markType == SC_MARK_LEFTRECT) {
		PRectangle rcLeft = rcWhole;
		rcLeft.right = rcLeft.left + 4;
		surface->FillRectangle(rcLeft, back.allocated);
	} else { // SC_MARK_FULLRECT
		surface->FillRectangle(rcWhole, back.allocated);
	}
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <fstream>
#include <ctime>
#include <set>

#ifdef WIN32
#  define WIN32_LEAN_AND_MEAN
#  include <Windows.h>
#else
#  include <sys/stat.h>
#endif

#include "LogManager.hpp"
#include "SampConfigReader.hpp"
#include "crashhandler.hpp"
#include "amx/amx2.h"

#include <fmt/format.h>
#include <fmt/time.h>

using samplog::LogLevel;

LogManager::LogManager() :
	m_ThreadRunning(true),
	m_DateTimeFormat("{:%x %X}")
{
	crashhandler::Install();

	std::string cfg_time_format;
	if (SampConfigReader::Get()->GetVar("logtimeformat", cfg_time_format))
	{
		//delete brackets
		size_t pos = 0;
		while ((pos = cfg_time_format.find_first_of("[]()")) != std::string::npos)
			cfg_time_format.erase(pos, 1);

		m_DateTimeFormat = "{:" + cfg_time_format + "}";
		// quickly test out the format string
		// will assert if invalid and on Windows
		fmt::format(m_DateTimeFormat, fmt::localtime(std::time(nullptr)));
	}

	CreateFolder("logs");

	m_WarningLog.open("logs/warnings.log");
	m_ErrorLog.open("logs/errors.log");

	m_Thread = new std::thread(std::bind(&LogManager::Process, this));
}

LogManager::~LogManager()
{
	{
		std::lock_guard<std::mutex> lg(m_QueueMtx);
		m_ThreadRunning = false;
	}
	m_QueueNotifier.notify_one();
	m_Thread->join();
	delete m_Thread;
}

void LogManager::QueueLogMessage(Message_t &&msg)
{
	{
		std::lock_guard<std::mutex> lg(m_QueueMtx);
		m_LogMsgQueue.push(std::move(msg));
	}
	m_QueueNotifier.notify_one();
}

void LogManager::Process()
{
	std::unique_lock<std::mutex> lk(m_QueueMtx);
	std::set<size_t> HashedModules;
	std::hash<std::string> StringHash;

	do
	{
		m_QueueNotifier.wait(lk);
		while (!m_LogMsgQueue.empty())
		{
			Message_t msg = std::move(m_LogMsgQueue.front());
			m_LogMsgQueue.pop();

			//manually unlock mutex
			//the whole write-to-file code below has no need to be locked with the
			//message queue mutex; while writing to the log file, new messages can
			//now be queued
			lk.unlock();

			std::string timestamp;
			std::time_t now_c = std::chrono::system_clock::to_time_t(msg->timestamp);
			timestamp = fmt::format(m_DateTimeFormat, fmt::localtime(now_c));

			const char *loglevel_str = "<unknown>";
			switch (msg->loglevel)
			{
			case LogLevel::DEBUG:
				loglevel_str = "DEBUG";
				break;
			case LogLevel::INFO:
				loglevel_str = "INFO";
				break;
			case LogLevel::WARNING:
				loglevel_str = "WARNING";
				break;
			case LogLevel::ERROR:
				loglevel_str = "ERROR";
				break;
			}

			const string &modulename = msg->log_module;
			size_t module_hash = StringHash(modulename);
			if (HashedModules.find(module_hash) == HashedModules.end())
			{
				//create possibly non-existing folders before opening log file
				size_t pos = 0;
				while ((pos = modulename.find('/', pos)) != std::string::npos)
				{
					CreateFolder("logs/" + modulename.substr(0, pos++));
				}

				HashedModules.insert(module_hash);
			}

			// build log string
			fmt::MemoryWriter log_string;

			log_string << msg->text;
			if (!msg->call_info.empty())
			{
				log_string << " (";
				bool first = true;
				for (auto const &ci : msg->call_info)
				{
					if (!first)
						log_string << " -> ";
					log_string << ci.file << ":" << ci.line;
					first = false;
				}
				log_string << ")";
			}

			//default logging
			std::ofstream logfile("logs/" + modulename + ".log",
				std::ofstream::out | std::ofstream::app);
			logfile <<
				"[" << timestamp << "] " <<
				"[" << loglevel_str << "] " <<
				log_string.str() << '\n' << std::flush;

			//per-log-level logging
			std::ofstream *loglevel_file = nullptr;
			if (msg->loglevel & LogLevel::WARNING)
				loglevel_file = &m_WarningLog;
			else if (msg->loglevel & LogLevel::ERROR)
				loglevel_file = &m_ErrorLog;

			if (loglevel_file != nullptr)
			{
				(*loglevel_file) <<
					"[" << timestamp << "] " <<
					"[" << modulename << "] " <<
					log_string.str() << '\n' << std::flush;
			}

			//lock the log message queue again (because while-condition and cv.wait)
			lk.lock();
		}
	} while (m_ThreadRunning);
}

void LogManager::CreateFolder(std::string foldername)
{
#ifdef WIN32
	std::replace(foldername.begin(), foldername.end(), '/', '\\');
	CreateDirectoryA(foldername.c_str(), NULL);
#else
	std::replace(foldername.begin(), foldername.end(), '\\', '/');
	mkdir(foldername.c_str(), ACCESSPERMS);
#endif
}
<commit_msg>handle new log levels<commit_after>#include <algorithm>
#include <fstream>
#include <ctime>
#include <set>

#ifdef WIN32
#  define WIN32_LEAN_AND_MEAN
#  include <Windows.h>
#else
#  include <sys/stat.h>
#endif

#include "LogManager.hpp"
#include "SampConfigReader.hpp"
#include "crashhandler.hpp"
#include "amx/amx2.h"

#include <fmt/format.h>
#include <fmt/time.h>

using samplog::LogLevel;

LogManager::LogManager() :
	m_ThreadRunning(true),
	m_DateTimeFormat("{:%x %X}")
{
	crashhandler::Install();

	std::string cfg_time_format;
	if (SampConfigReader::Get()->GetVar("logtimeformat", cfg_time_format))
	{
		//delete brackets
		size_t pos = 0;
		while ((pos = cfg_time_format.find_first_of("[]()")) != std::string::npos)
			cfg_time_format.erase(pos, 1);

		m_DateTimeFormat = "{:" + cfg_time_format + "}";
		// quickly test out the format string
		// will assert if invalid and on Windows
		fmt::format(m_DateTimeFormat, fmt::localtime(std::time(nullptr)));
	}

	CreateFolder("logs");

	m_WarningLog.open("logs/warnings.log");
	m_ErrorLog.open("logs/errors.log");

	m_Thread = new std::thread(std::bind(&LogManager::Process, this));
}

LogManager::~LogManager()
{
	{
		std::lock_guard<std::mutex> lg(m_QueueMtx);
		m_ThreadRunning = false;
	}
	m_QueueNotifier.notify_one();
	m_Thread->join();
	delete m_Thread;
}

void LogManager::QueueLogMessage(Message_t &&msg)
{
	{
		std::lock_guard<std::mutex> lg(m_QueueMtx);
		m_LogMsgQueue.push(std::move(msg));
	}
	m_QueueNotifier.notify_one();
}

void LogManager::Process()
{
	std::unique_lock<std::mutex> lk(m_QueueMtx);
	std::set<size_t> HashedModules;
	std::hash<std::string> StringHash;

	do
	{
		m_QueueNotifier.wait(lk);
		while (!m_LogMsgQueue.empty())
		{
			Message_t msg = std::move(m_LogMsgQueue.front());
			m_LogMsgQueue.pop();

			//manually unlock mutex
			//the whole write-to-file code below has no need to be locked with the
			//message queue mutex; while writing to the log file, new messages can
			//now be queued
			lk.unlock();

			std::string timestamp;
			std::time_t now_c = std::chrono::system_clock::to_time_t(msg->timestamp);
			timestamp = fmt::format(m_DateTimeFormat, fmt::localtime(now_c));

			const char *loglevel_str = "<unknown>";
			switch (msg->loglevel)
			{
			case LogLevel::DEBUG:
				loglevel_str = "DEBUG";
				break;
			case LogLevel::INFO:
				loglevel_str = "INFO";
				break;
			case LogLevel::WARNING:
				loglevel_str = "WARNING";
				break;
			case LogLevel::ERROR:
				loglevel_str = "ERROR";
				break;
			case LogLevel::FATAL:
				loglevel_str = "FATAL";
				break;
			case LogLevel::VERBOSE:
				loglevel_str = "VERBOSE";
				break;
			}

			const string &modulename = msg->log_module;
			size_t module_hash = StringHash(modulename);
			if (HashedModules.find(module_hash) == HashedModules.end())
			{
				//create possibly non-existing folders before opening log file
				size_t pos = 0;
				while ((pos = modulename.find('/', pos)) != std::string::npos)
				{
					CreateFolder("logs/" + modulename.substr(0, pos++));
				}

				HashedModules.insert(module_hash);
			}

			// build log string
			fmt::MemoryWriter log_string;

			log_string << msg->text;
			if (!msg->call_info.empty())
			{
				log_string << " (";
				bool first = true;
				for (auto const &ci : msg->call_info)
				{
					if (!first)
						log_string << " -> ";
					log_string << ci.file << ":" << ci.line;
					first = false;
				}
				log_string << ")";
			}

			//default logging
			std::ofstream logfile("logs/" + modulename + ".log",
				std::ofstream::out | std::ofstream::app);
			logfile <<
				"[" << timestamp << "] " <<
				"[" << loglevel_str << "] " <<
				log_string.str() << '\n' << std::flush;

			//per-log-level logging
			std::ofstream *loglevel_file = nullptr;
			if (msg->loglevel & LogLevel::WARNING)
				loglevel_file = &m_WarningLog;
			else if (msg->loglevel & LogLevel::ERROR)
				loglevel_file = &m_ErrorLog;

			if (loglevel_file != nullptr)
			{
				(*loglevel_file) <<
					"[" << timestamp << "] " <<
					"[" << modulename << "] " <<
					log_string.str() << '\n' << std::flush;
			}

			//lock the log message queue again (because while-condition and cv.wait)
			lk.lock();
		}
	} while (m_ThreadRunning);
}

void LogManager::CreateFolder(std::string foldername)
{
#ifdef WIN32
	std::replace(foldername.begin(), foldername.end(), '/', '\\');
	CreateDirectoryA(foldername.c_str(), NULL);
#else
	std::replace(foldername.begin(), foldername.end(), '\\', '/');
	mkdir(foldername.c_str(), ACCESSPERMS);
#endif
}
<|endoftext|>


<commit_before>/*
 * MainWindow.cpp
 *
 *  Created on: 17.05.2009
 *      Author: matthias
 */

#include <QtCore/QDebug>
#include "MainWindow.h"
//#include "dbus/Notifications.h"
#include "ofono.h"

#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeComponent>
#include <QGraphicsObject>
#include <QtDeclarative/QDeclarativeContext>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
	ui.setupUi(this);

    QML_REGISTER_TYPE(OfonoLib, 1,0, Ofono, Ofono);

    QDeclarativeEngine *engine = new QDeclarativeEngine();
    QDeclarativeContext *context = engine->rootContext();
    context->setContextProperty("OfonoContext", new Ofono());
    QDeclarativeComponent component(engine, QUrl::fromLocalFile(":qml/mobos-gui.qml"));
    // to print out errors in the qml file
    if(component.isError()) {
        QListIterator<QDeclarativeError> itr (component.errors());
        while(itr.hasNext()) {
            QDeclarativeError current = itr.next();
            qDebug() << current;
        }
    }
    QGraphicsObject *object = qobject_cast<QGraphicsObject *>(component.create());

    // load qml into the view
    QGraphicsScene* scene = new QGraphicsScene(0, 0, 240, 320);
    scene->addItem(object);
    ui.graphicsView->setScene(scene);
    ui.graphicsView->show();
}

/**
 * http://www.galago-project.org/specs/notification/0.9/x408.html#command-notify
 */

MainWindow::~MainWindow() {
	// TODO Auto-generated destructor stub
}
<commit_msg>Qt 4.7 Version Changes<commit_after>/*
 * MainWindow.cpp
 *
 *  Created on: 17.05.2009
 *      Author: matthias
 */

#include <QtCore/QDebug>
#include "MainWindow.h"
//#include "dbus/Notifications.h"
#include "ofono.h"

#include <QtDeclarative/QDeclarativeEngine>
#include <QtDeclarative/QDeclarativeComponent>
#include <QGraphicsObject>
#include <QtDeclarative/QDeclarativeContext>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
	ui.setupUi(this);

    qmlRegisterType<Ofono>("OfonoLib", 1, 0, "Ofono");

    QDeclarativeEngine *engine = new QDeclarativeEngine();
    QDeclarativeContext *context = engine->rootContext();
    context->setContextProperty("OfonoContext", new Ofono());
    QDeclarativeComponent component(engine, QUrl::fromLocalFile(":qml/mobos-gui.qml"));
    // to print out errors in the qml file
    if(component.isError()) {
        QListIterator<QDeclarativeError> itr (component.errors());
        while(itr.hasNext()) {
            QDeclarativeError current = itr.next();
            qDebug() << current;
        }
    }
    QGraphicsObject *object = qobject_cast<QGraphicsObject *>(component.create());

    // load qml into the view
    QGraphicsScene* scene = new QGraphicsScene(0, 0, 240, 320);
    scene->addItem(object);
    ui.graphicsView->setScene(scene);
    ui.graphicsView->show();
}

/**
 * http://www.galago-project.org/specs/notification/0.9/x408.html#command-notify
 */

MainWindow::~MainWindow() {
	// TODO Auto-generated destructor stub
}
<|endoftext|>


<commit_before>/*
 * This file is part of the Yildiz-Engine project, licenced under the MIT License  (MIT)
 *
 * Copyright (c) 2019 Grégory Van den Borre
 *
 * More infos available: https://engine.yildiz-games.be
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  SOFTWARE.
 */

#ifndef YZ_SCENEMANAGER_H
#define YZ_SCENEMANAGER_H

#define SCENEMANAGER yz::SceneManager

#include <Ogre.h>
#include "CollisionTools.h"
#include "PointLight.hpp"
#include "SpotLight.hpp"
#include "DirectionalLight.hpp"
#include "Camera.hpp"
#include "DynamicLine.hpp"
#include "Node.hpp"
#include "Lensflare.hpp"
#include "ParticleSystem.hpp"
#include "BillboardSet.hpp"
#include "ElectricArc.hpp"
#include "Entity.hpp"
#include "Query.hpp"
#include "GroundQuery.hpp"
#include "RayProvider.hpp"

namespace yz {

/**
 * Wrap an Ogre::SceneManager to provide construction and management for graphic objects.
 *@author Grégory Van den Borre
 */
class SceneManager {

public:
    SceneManager(Ogre::SceneManager* sm);

    inline void preloadMesh(const std::string& mesh) {
        LOG_FUNCTION
        this->sceneManager->createEntity("preload_" + mesh, mesh, "General");
    }

    inline void setShadowTextureSize(const int size) {
        LOG_FUNCTION
        this->sceneManager->setShadowTextureSize(size);
    }

    inline void setShadowFarDistance(const int distance) {
        LOG_FUNCTION
        this->sceneManager->setShadowFarDistance(distance);
    }

    inline void setShadowType(const int shadowType) {
        LOG_FUNCTION
        Ogre::ShadowTechnique shadow;
        switch (shadowType) {
        case 0:
            shadow = Ogre::SHADOWTYPE_NONE;
            break;
        case 1:
            shadow = Ogre::SHADOWTYPE_TEXTURE_ADDITIVE;
            break;
        case 2:
            shadow = Ogre::SHADOWTYPE_TEXTURE_MODULATIVE;
            break;
        case 3:
            shadow = Ogre::SHADOWTYPE_STENCIL_ADDITIVE;
            break;
        case 4:
            shadow = Ogre::SHADOWTYPE_STENCIL_MODULATIVE;
            break;
        default:
            shadow = Ogre::SHADOWTYPE_NONE;
            break;
        }
        this->sceneManager->setShadowTechnique(shadow);
    }

    inline void setDebugMode() {
        LOG_FUNCTION
        this->debug = true;
        Ogre::Node::ChildNodeMap children = i_pSceneNode->getChildren();
        for (int i = 0; i < children.size(); i++) {
            static_cast<Ogre::SceneNode*>(children.at(i))->showBoundingBox(true);
	    }
    }

    yz::Camera* createCamera(const std::string& name);

    yz::Query* createQuery(yz::RayProvider* provider);

    yz::GroundQuery* createGroundQuery(yz::RayProvider* provider, yz::Node* e);

    //FIXME use java sky object and retrieve name from native.
    inline void setSkyBox(const std::string& file) {
        LOG_FUNCTION
        this->sceneManager->setSkyBox(true, file);
    }

    inline yz::Node* getRootNode() {
        LOG_FUNCTION
        return this->rootNode;
    }

    yz::PointLight* createPointLight(
        const std::string& name,
        const Ogre::Real x,
        const Ogre::Real y,
        const Ogre::Real z);

    yz::SpotLight* createSpotLight(
        const std::string& name,
        const Ogre::Real x,
        const Ogre::Real y,
        const Ogre::Real z,
        const Ogre::Real dirX,
        const Ogre::Real dirY,
        const Ogre::Real dirZ);

    yz::DirectionalLight* createDirectionalLight(
        const std::string& name,
        const Ogre::Real x,
        const Ogre::Real y,
        const Ogre::Real z,
        const Ogre::Real dirX,
        const Ogre::Real dirY,
        const Ogre::Real dirZ);

    Ogre::Vector3 getPoint(
        const Ogre::Vector3&,
        yz::Camera* cam,
        const Ogre::Real x,
        const Ogre::Real y);

    inline yz::Entity* createEntity(const std::string& mesh) {
        LOG_FUNCTION
        yz::Entity* e = new yz::Entity(this->sceneManager->createEntity(mesh));
        e->setQueryFlags(Ogre::SceneManager::ENTITY_TYPE_MASK);
        return e;
    }

    Ogre::Entity* createUnpickableEntity(const std::string& mesh);

    inline yz::ParticleSystem* createParticleSystem() {
        LOG_FUNCTION
        return new yz::ParticleSystem(this->sceneManager->createParticleSystem());
    }

    inline yz::BillboardSet* createBillboardSet(yz::Material* material) {
        LOG_FUNCTION
        yz::BillboardSet* set = new yz::BillboardSet(this->sceneManager->createBillboardSet());
        set->setMaterial(material);
        return set;
    }

    inline yz::Node* createNode(const std::string& name) {
        LOG_FUNCTION
        yz::Node* node = new yz::Node(this->sceneManager->getRootSceneNode()->createChildSceneNode(name));
        if (this->debug) {
            node->showBoundingBox(true);
        }
        return node;
    }

    /**
     * Create a yz::Node and associate it with an ID.
     */
    inline yz::Node* createNode(yz::Id* id, const std::string& name) {
        LOG_FUNCTION
        yz::Node* node = new yz::Node(this->sceneManager->getRootSceneNode()->createChildSceneNode(name), id);
        if (this->debug) {
            node->showBoundingBox(true);
        }
        return node;
    }

    yz::LensFlare* createLensFlare(
        const std::string& name,
        yz::Material* light,
        yz::Material* streak,
        yz::Material* halo,
        yz::Material* burst,
        const Ogre::Real x,
        const Ogre::Real y,
        const Ogre::Real z);

    inline void setAmbientLight(
    		const Ogre::Real red,
    		const Ogre::Real green,
    		const Ogre::Real blue,
    		const Ogre::Real alpha) {
        LOG_FUNCTION
        this->sceneManager->setAmbientLight(Ogre::ColourValue(red, green, blue, alpha));
    }

    inline yz::Entity* createCube(const std::string& name) {
        LOG_FUNCTION
        return this->createEntity(this->sceneManager->createEntity(name, Ogre::SceneManager::PT_CUBE));
    }

    inline yz::Entity* createCube() {
        LOG_FUNCTION
        return this->createEntity(this->sceneManager->createEntity(Ogre::SceneManager::PT_CUBE));
    }

    inline yz::Entity* createPlane(const std::string& name) {
        LOG_FUNCTION
        return new yz::Entity(this->sceneManager->createEntity(name, Ogre::SceneManager::PT_PLANE));
    }

    inline yz::Entity* createPlane() {
        LOG_FUNCTION
        return new yz::Entity(this->sceneManager->createEntity(Ogre::SceneManager::PT_PLANE));
    }

    inline yz::Entity* createSphere(const std::string& name) {
        LOG_FUNCTION
        return this->createEntity(this->sceneManager->createEntity(name, Ogre::SceneManager::PT_SPHERE));
    }

    yz::Entity* createSphere(
        const std::string& name,
        const int ring,
        const int segment,
        const float radius = 100.0f);

    inline yz::Entity* createSphere() {
        LOG_FUNCTION
        return this->createEntity(this->sceneManager->createEntity(Ogre::SceneManager::PT_SPHERE));

    }

    inline Ogre::SceneManager* getSceneManager() {
        LOG_FUNCTION
        return this->sceneManager;
    }

    inline yz::ElectricArc* createElectricArc(
          const std::string& name,
          const Ogre::Real x,
          const Ogre::Real y,
          const Ogre::Real z,
          const Ogre::Real eX,
          const Ogre::Real eY,
          const Ogre::Real eZ,
          const Ogre::Real width) {
        LOG_FUNCTION
        Node* start = this->createNode(name + "01");
        start->setPosition(x, y, z);
        Node* end = this->createNode(name + "02");
        end->setPosition(eX, eY, eZ);
        Node* base = this->createNode(name + "03");
        return new yz::ElectricArc(start, end, base, name, width);
    }

private:
    Ogre::SceneManager* sceneManager;
    bool debug;
    yz::Node* rootNode;

    yz::Entity* createEntity(Ogre::Entity* e) {
        e->setMaterialName("_internal_red_");
        e->setQueryFlags(Ogre::SceneManager::ENTITY_TYPE_MASK);
        return new yz::Entity(e);
    }
};
}
#endif

<commit_msg>Update SceneManager.hpp<commit_after>/*
 * This file is part of the Yildiz-Engine project, licenced under the MIT License  (MIT)
 *
 * Copyright (c) 2019 Grégory Van den Borre
 *
 * More infos available: https://engine.yildiz-games.be
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without
 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT  HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  SOFTWARE.
 */

#ifndef YZ_SCENEMANAGER_H
#define YZ_SCENEMANAGER_H

#define SCENEMANAGER yz::SceneManager

#include <Ogre.h>
#include "CollisionTools.h"
#include "PointLight.hpp"
#include "SpotLight.hpp"
#include "DirectionalLight.hpp"
#include "Camera.hpp"
#include "DynamicLine.hpp"
#include "Node.hpp"
#include "Lensflare.hpp"
#include "ParticleSystem.hpp"
#include "BillboardSet.hpp"
#include "ElectricArc.hpp"
#include "Entity.hpp"
#include "Query.hpp"
#include "GroundQuery.hpp"
#include "RayProvider.hpp"

namespace yz {

/**
 * Wrap an Ogre::SceneManager to provide construction and management for graphic objects.
 *@author Grégory Van den Borre
 */
class SceneManager {

public:
    SceneManager(Ogre::SceneManager* sm);

    inline void preloadMesh(const std::string& mesh) {
        LOG_FUNCTION
        this->sceneManager->createEntity("preload_" + mesh, mesh, "General");
    }

    inline void setShadowTextureSize(const int size) {
        LOG_FUNCTION
        this->sceneManager->setShadowTextureSize(size);
    }

    inline void setShadowFarDistance(const int distance) {
        LOG_FUNCTION
        this->sceneManager->setShadowFarDistance(distance);
    }

    inline void setShadowType(const int shadowType) {
        LOG_FUNCTION
        Ogre::ShadowTechnique shadow;
        switch (shadowType) {
        case 0:
            shadow = Ogre::SHADOWTYPE_NONE;
            break;
        case 1:
            shadow = Ogre::SHADOWTYPE_TEXTURE_ADDITIVE;
            break;
        case 2:
            shadow = Ogre::SHADOWTYPE_TEXTURE_MODULATIVE;
            break;
        case 3:
            shadow = Ogre::SHADOWTYPE_STENCIL_ADDITIVE;
            break;
        case 4:
            shadow = Ogre::SHADOWTYPE_STENCIL_MODULATIVE;
            break;
        default:
            shadow = Ogre::SHADOWTYPE_NONE;
            break;
        }
        this->sceneManager->setShadowTechnique(shadow);
    }

    inline void setDebugMode() {
        LOG_FUNCTION
        this->debug = true;
        Ogre::Node::ChildNodeMap children = this->sceneManager->getRootSceneNode()->getChildren();
        for (int i = 0; i < children.size(); i++) {
            static_cast<Ogre::SceneNode*>(children.at(i))->showBoundingBox(true);
	    }
    }

    yz::Camera* createCamera(const std::string& name);

    yz::Query* createQuery(yz::RayProvider* provider);

    yz::GroundQuery* createGroundQuery(yz::RayProvider* provider, yz::Node* e);

    //FIXME use java sky object and retrieve name from native.
    inline void setSkyBox(const std::string& file) {
        LOG_FUNCTION
        this->sceneManager->setSkyBox(true, file);
    }

    inline yz::Node* getRootNode() {
        LOG_FUNCTION
        return this->rootNode;
    }

    yz::PointLight* createPointLight(
        const std::string& name,
        const Ogre::Real x,
        const Ogre::Real y,
        const Ogre::Real z);

    yz::SpotLight* createSpotLight(
        const std::string& name,
        const Ogre::Real x,
        const Ogre::Real y,
        const Ogre::Real z,
        const Ogre::Real dirX,
        const Ogre::Real dirY,
        const Ogre::Real dirZ);

    yz::DirectionalLight* createDirectionalLight(
        const std::string& name,
        const Ogre::Real x,
        const Ogre::Real y,
        const Ogre::Real z,
        const Ogre::Real dirX,
        const Ogre::Real dirY,
        const Ogre::Real dirZ);

    Ogre::Vector3 getPoint(
        const Ogre::Vector3&,
        yz::Camera* cam,
        const Ogre::Real x,
        const Ogre::Real y);

    inline yz::Entity* createEntity(const std::string& mesh) {
        LOG_FUNCTION
        yz::Entity* e = new yz::Entity(this->sceneManager->createEntity(mesh));
        e->setQueryFlags(Ogre::SceneManager::ENTITY_TYPE_MASK);
        return e;
    }

    Ogre::Entity* createUnpickableEntity(const std::string& mesh);

    inline yz::ParticleSystem* createParticleSystem() {
        LOG_FUNCTION
        return new yz::ParticleSystem(this->sceneManager->createParticleSystem());
    }

    inline yz::BillboardSet* createBillboardSet(yz::Material* material) {
        LOG_FUNCTION
        yz::BillboardSet* set = new yz::BillboardSet(this->sceneManager->createBillboardSet());
        set->setMaterial(material);
        return set;
    }

    inline yz::Node* createNode(const std::string& name) {
        LOG_FUNCTION
        yz::Node* node = new yz::Node(this->sceneManager->getRootSceneNode()->createChildSceneNode(name));
        if (this->debug) {
            node->showBoundingBox(true);
        }
        return node;
    }

    /**
     * Create a yz::Node and associate it with an ID.
     */
    inline yz::Node* createNode(yz::Id* id, const std::string& name) {
        LOG_FUNCTION
        yz::Node* node = new yz::Node(this->sceneManager->getRootSceneNode()->createChildSceneNode(name), id);
        if (this->debug) {
            node->showBoundingBox(true);
        }
        return node;
    }

    yz::LensFlare* createLensFlare(
        const std::string& name,
        yz::Material* light,
        yz::Material* streak,
        yz::Material* halo,
        yz::Material* burst,
        const Ogre::Real x,
        const Ogre::Real y,
        const Ogre::Real z);

    inline void setAmbientLight(
    		const Ogre::Real red,
    		const Ogre::Real green,
    		const Ogre::Real blue,
    		const Ogre::Real alpha) {
        LOG_FUNCTION
        this->sceneManager->setAmbientLight(Ogre::ColourValue(red, green, blue, alpha));
    }

    inline yz::Entity* createCube(const std::string& name) {
        LOG_FUNCTION
        return this->createEntity(this->sceneManager->createEntity(name, Ogre::SceneManager::PT_CUBE));
    }

    inline yz::Entity* createCube() {
        LOG_FUNCTION
        return this->createEntity(this->sceneManager->createEntity(Ogre::SceneManager::PT_CUBE));
    }

    inline yz::Entity* createPlane(const std::string& name) {
        LOG_FUNCTION
        return new yz::Entity(this->sceneManager->createEntity(name, Ogre::SceneManager::PT_PLANE));
    }

    inline yz::Entity* createPlane() {
        LOG_FUNCTION
        return new yz::Entity(this->sceneManager->createEntity(Ogre::SceneManager::PT_PLANE));
    }

    inline yz::Entity* createSphere(const std::string& name) {
        LOG_FUNCTION
        return this->createEntity(this->sceneManager->createEntity(name, Ogre::SceneManager::PT_SPHERE));
    }

    yz::Entity* createSphere(
        const std::string& name,
        const int ring,
        const int segment,
        const float radius = 100.0f);

    inline yz::Entity* createSphere() {
        LOG_FUNCTION
        return this->createEntity(this->sceneManager->createEntity(Ogre::SceneManager::PT_SPHERE));

    }

    inline Ogre::SceneManager* getSceneManager() {
        LOG_FUNCTION
        return this->sceneManager;
    }

    inline yz::ElectricArc* createElectricArc(
          const std::string& name,
          const Ogre::Real x,
          const Ogre::Real y,
          const Ogre::Real z,
          const Ogre::Real eX,
          const Ogre::Real eY,
          const Ogre::Real eZ,
          const Ogre::Real width) {
        LOG_FUNCTION
        Node* start = this->createNode(name + "01");
        start->setPosition(x, y, z);
        Node* end = this->createNode(name + "02");
        end->setPosition(eX, eY, eZ);
        Node* base = this->createNode(name + "03");
        return new yz::ElectricArc(start, end, base, name, width);
    }

private:
    Ogre::SceneManager* sceneManager;
    bool debug;
    yz::Node* rootNode;

    yz::Entity* createEntity(Ogre::Entity* e) {
        e->setMaterialName("_internal_red_");
        e->setQueryFlags(Ogre::SceneManager::ENTITY_TYPE_MASK);
        return new yz::Entity(e);
    }
};
}
#endif

<|endoftext|>


<commit_before><commit_msg>Fix syntax accessing enum scoped to class, to fix GCC builds. Review URL: http://codereview.chromium.org/183007<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkCoverageDelta.h"

SkCoverageDeltaList::SkCoverageDeltaList(SkArenaAlloc* alloc, int top, int bottom, bool forceRLE) {
    fAlloc              = alloc;
    fTop                = top;
    fBottom             = bottom;
    fForceRLE           = forceRLE;

    // Init the anti-rect to be empty
    fAntiRect.fY        = bottom;
    fAntiRect.fHeight   = 0;

    fSorted     = fAlloc->makeArrayDefault<bool>(bottom - top);
    fCounts     = fAlloc->makeArrayDefault<int>((bottom - top) * 2);
    fMaxCounts  = fCounts + bottom - top;
    fRows       = fAlloc->makeArrayDefault<SkCoverageDelta*>(bottom - top) - top;
    fRows[top]  = fAlloc->makeArrayDefault<SkCoverageDelta>(INIT_ROW_SIZE * (bottom - top));

    memset(fSorted, true, bottom - top);
    memset(fCounts, 0, sizeof(int) * (bottom - top));

    // Minus top so we can directly use fCounts[y] instead of fCounts[y - fTop].
    // Same for fMaxCounts, fRows, and fSorted.
    fSorted    -= top;
    fCounts    -= top;
    fMaxCounts -= top;

    for(int y = top; y < bottom; ++y) {
        fMaxCounts[y] = INIT_ROW_SIZE;
    }
    for(int y = top + 1; y < bottom; ++y) {
        fRows[y] = fRows[y - 1] + INIT_ROW_SIZE;
    }
}

int SkCoverageDeltaMask::ExpandWidth(int width) {
    int result = width + PADDING * 2;
    return result + (SIMD_WIDTH - result % SIMD_WIDTH) % SIMD_WIDTH;
}

bool SkCoverageDeltaMask::CanHandle(const SkIRect& bounds) {
    // Expand width so we don't have to worry about the boundary
    return ExpandWidth(bounds.width()) * bounds.height() + PADDING * 2 < MAX_MASK_SIZE;
}

bool SkCoverageDeltaMask::Suitable(const SkIRect& bounds) {
    return bounds.width() <= SUITABLE_WIDTH && CanHandle(bounds);
}

SkCoverageDeltaMask::SkCoverageDeltaMask(SkArenaAlloc* alloc, const SkIRect& bounds) {
    SkASSERT(CanHandle(bounds));

    fBounds             = bounds;

    // Init the anti-rect to be empty
    fAntiRect.fY        = fBounds.fBottom;
    fAntiRect.fHeight   = 0;

    fExpandedWidth      = ExpandWidth(fBounds.width());

    int size            = fExpandedWidth * bounds.height() + PADDING * 2;
    fDeltaStorage       = alloc->makeArrayDefault<SkFixed>(size);
    fMask               = alloc->makeArrayDefault<SkAlpha>(size);

    // Add PADDING columns so we may access fDeltas[index(-PADDING, 0)]
    // Minus index(fBounds.fLeft, fBounds.fTop) so we can directly access fDeltas[index(x, y)]
    fDeltas             = fDeltaStorage + PADDING - this->index(fBounds.fLeft, fBounds.fTop);

    memset(fDeltaStorage, 0, size * sizeof(SkFixed));
}

// TODO As this function is so performance-critical (and we're thinking so much about SIMD), use
// SkOpts framework to compile multiple versions of this function so we can choose the best one
// available at runtime.
void SkCoverageDeltaMask::convertCoverageToAlpha(bool isEvenOdd, bool isInverse, bool isConvex) {
    SkFixed* deltaRow = &this->delta(fBounds.fLeft, fBounds.fTop);
    SkAlpha* maskRow = fMask;
    for(int iy = 0; iy < fBounds.height(); ++iy) {
        // If we're inside fAntiRect, blit it to the mask and advance to its bottom
        if (fAntiRect.fHeight && iy == fAntiRect.fY - fBounds.fTop) {
            // Blit the mask
            int L = fAntiRect.fX - fBounds.fLeft;
            for(int i = 0; i < fAntiRect.fHeight; ++i) {
                SkAlpha* tMask = maskRow + L;
                if (fAntiRect.fLeftAlpha) {
                    tMask[0] = fAntiRect.fLeftAlpha;
                }
                memset(tMask + 1, 0xff, fAntiRect.fWidth);
                if (fAntiRect.fRightAlpha) {
                    tMask[fAntiRect.fWidth + 1] = fAntiRect.fRightAlpha;
                }
                maskRow += fBounds.width();
            }

            // Advance to the bottom (maskRow is already advanced to the bottom).
            deltaRow    += fExpandedWidth * fAntiRect.fHeight;
            iy          += fAntiRect.fHeight - 1; // -1 because we'll ++iy after continue
            continue;
        }

        // Otherwise, cumulate deltas into coverages, and convert them into alphas
        SkFixed c[SIMD_WIDTH] = {0}; // prepare SIMD_WIDTH coverages at a time
        for(int ix = 0; ix < fExpandedWidth; ix += SIMD_WIDTH) {
            // Future todo: is it faster to process SIMD_WIDTH rows at a time so we can use SIMD
            // for coverage accumulation?

            // Cumulate deltas to get SIMD_WIDTH new coverages
            c[0] = c[SIMD_WIDTH - 1] + deltaRow[ix];
            for(int j = 1; j < SIMD_WIDTH; ++j) {
                c[j] = c[j - 1] + deltaRow[ix + j];
            }

            using SkNi = SkNx<SIMD_WIDTH, int>;
            SkNi cn = SkNi::Load(c);
            SkNi an = isConvex ? ConvexCoverageToAlpha(cn, isInverse)
                               : CoverageToAlpha(cn, isEvenOdd, isInverse);
            SkNx_cast<SkAlpha>(an).store(maskRow + ix);
        }

        // Finally, advance to the next row
        deltaRow    += fExpandedWidth;
        maskRow     += fBounds.width();
    }
}
<commit_msg>Upload the missing change in 42101<commit_after>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkCoverageDelta.h"

SkCoverageDeltaList::SkCoverageDeltaList(SkArenaAlloc* alloc, int top, int bottom, bool forceRLE) {
    fAlloc              = alloc;
    fTop                = top;
    fBottom             = bottom;
    fForceRLE           = forceRLE;

    // Init the anti-rect to be empty
    fAntiRect.fY        = bottom;
    fAntiRect.fHeight   = 0;

    fSorted     = fAlloc->makeArrayDefault<bool>(bottom - top);
    fCounts     = fAlloc->makeArrayDefault<int>((bottom - top) * 2);
    fMaxCounts  = fCounts + bottom - top;
    fRows       = fAlloc->makeArrayDefault<SkCoverageDelta*>(bottom - top) - top;
    fRows[top]  = fAlloc->makeArrayDefault<SkCoverageDelta>(INIT_ROW_SIZE * (bottom - top));

    memset(fSorted, true, bottom - top);
    memset(fCounts, 0, sizeof(int) * (bottom - top));

    // Minus top so we can directly use fCounts[y] instead of fCounts[y - fTop].
    // Same for fMaxCounts, fRows, and fSorted.
    fSorted    -= top;
    fCounts    -= top;
    fMaxCounts -= top;

    for(int y = top; y < bottom; ++y) {
        fMaxCounts[y] = INIT_ROW_SIZE;
    }
    for(int y = top + 1; y < bottom; ++y) {
        fRows[y] = fRows[y - 1] + INIT_ROW_SIZE;
    }
}

int SkCoverageDeltaMask::ExpandWidth(int width) {
    int result = width + PADDING * 2;
    return result + (SIMD_WIDTH - result % SIMD_WIDTH) % SIMD_WIDTH;
}

bool SkCoverageDeltaMask::CanHandle(const SkIRect& bounds) {
    // Expand width so we don't have to worry about the boundary
    return ExpandWidth(bounds.width()) * bounds.height() + PADDING * 2 < MAX_MASK_SIZE;
}

bool SkCoverageDeltaMask::Suitable(const SkIRect& bounds) {
    return bounds.width() <= SUITABLE_WIDTH && CanHandle(bounds);
}

SkCoverageDeltaMask::SkCoverageDeltaMask(SkArenaAlloc* alloc, const SkIRect& bounds) {
    SkASSERT(CanHandle(bounds));

    fBounds             = bounds;

    // Init the anti-rect to be empty
    fAntiRect.fY        = fBounds.fBottom;
    fAntiRect.fHeight   = 0;

    fExpandedWidth      = ExpandWidth(fBounds.width());

    int size            = fExpandedWidth * bounds.height() + PADDING * 2;
    fDeltaStorage       = alloc->makeArray<SkFixed>(size);
    fMask               = alloc->makeArrayDefault<SkAlpha>(size);

    // Add PADDING columns so we may access fDeltas[index(-PADDING, 0)]
    // Minus index(fBounds.fLeft, fBounds.fTop) so we can directly access fDeltas[index(x, y)]
    fDeltas             = fDeltaStorage + PADDING - this->index(fBounds.fLeft, fBounds.fTop);
}

// TODO As this function is so performance-critical (and we're thinking so much about SIMD), use
// SkOpts framework to compile multiple versions of this function so we can choose the best one
// available at runtime.
void SkCoverageDeltaMask::convertCoverageToAlpha(bool isEvenOdd, bool isInverse, bool isConvex) {
    SkFixed* deltaRow = &this->delta(fBounds.fLeft, fBounds.fTop);
    SkAlpha* maskRow = fMask;
    for(int iy = 0; iy < fBounds.height(); ++iy) {
        // If we're inside fAntiRect, blit it to the mask and advance to its bottom
        if (fAntiRect.fHeight && iy == fAntiRect.fY - fBounds.fTop) {
            // Blit the mask
            int L = fAntiRect.fX - fBounds.fLeft;
            for(int i = 0; i < fAntiRect.fHeight; ++i) {
                SkAlpha* tMask = maskRow + L;
                if (fAntiRect.fLeftAlpha) {
                    tMask[0] = fAntiRect.fLeftAlpha;
                }
                memset(tMask + 1, 0xff, fAntiRect.fWidth);
                if (fAntiRect.fRightAlpha) {
                    tMask[fAntiRect.fWidth + 1] = fAntiRect.fRightAlpha;
                }
                maskRow += fBounds.width();
            }

            // Advance to the bottom (maskRow is already advanced to the bottom).
            deltaRow    += fExpandedWidth * fAntiRect.fHeight;
            iy          += fAntiRect.fHeight - 1; // -1 because we'll ++iy after continue
            continue;
        }

        // Otherwise, cumulate deltas into coverages, and convert them into alphas
        SkFixed c[SIMD_WIDTH] = {0}; // prepare SIMD_WIDTH coverages at a time
        for(int ix = 0; ix < fExpandedWidth; ix += SIMD_WIDTH) {
            // Future todo: is it faster to process SIMD_WIDTH rows at a time so we can use SIMD
            // for coverage accumulation?

            // Cumulate deltas to get SIMD_WIDTH new coverages
            c[0] = c[SIMD_WIDTH - 1] + deltaRow[ix];
            for(int j = 1; j < SIMD_WIDTH; ++j) {
                c[j] = c[j - 1] + deltaRow[ix + j];
            }

            using SkNi = SkNx<SIMD_WIDTH, int>;
            SkNi cn = SkNi::Load(c);
            SkNi an = isConvex ? ConvexCoverageToAlpha(cn, isInverse)
                               : CoverageToAlpha(cn, isEvenOdd, isInverse);
            SkNx_cast<SkAlpha>(an).store(maskRow + ix);
        }

        // Finally, advance to the next row
        deltaRow    += fExpandedWidth;
        maskRow     += fBounds.width();
    }
}
<|endoftext|>