<commit_before>#include <faunus/faunus.h>

// Manual: http://faunus.sourceforge.net/doxyhtml/index.html

using namespace Faunus;
using namespace std;

class DipoleParticle : public PointParticle {
  public:
    double mu_s;            //!< Dipole moment scalar
    Eigen::Vector3d mu;     //!< Dipole moment unit vector
    Eigen::Matrix3d alpha;  //!< Polarization tensor

    inline DipoleParticle() {
      mu_s=0;
    }

    template<typename OtherDerived>
      DipoleParticle(const Eigen::MatrixBase<OtherDerived>& other) : Tvec(other) {}

    template<typename OtherDerived>
      DipoleParticle& operator=(const Eigen::MatrixBase<OtherDerived> &other) {
        Tvec::operator=(other);
        return *this;
      }
};

// Insert energy functions here!
// Major goal:
//   function: pairpot(particle &a, particle &b, point &vdist)

int main() {
  InputMap mcp("nemo.conf");
  Geometry::Sphere geo(mcp);
  Potential::Coulomb coulomb(mcp);

  cout << geo.info() << coulomb.info(25);

  DipoleParticle a, b;

  Point vdist = geo.vdist(a,b);
  double u = coulomb(a,b, geo.dist(a,b) );

  a.ranunit( slp_global ); // random unit vector
  double r = slp_global(); // random number [0:1[

  // Examples
  cout << "Squared distance = " << geo.sqdist(a,b) << "\n";
  cout << "Bjerrum          = " << coulomb.bjerrumLength() << "\n";
  cout << "Avogadro's number= " << pc::Nav << "\n";  // se "faunus/physconst.h"
}
<commit_msg>Expanded Nemo<commit_after>#include <faunus/faunus.h>

// Manual: http://faunus.sourceforge.net/doxyhtml/index.html

using namespace Faunus;
using namespace std;

class Point {
  public:
    double x,y,z;
    void init(double,double,double);
};

class particle : public Point {
  public:
    std::string name;
    double sigma;
    double eps;
    double q;
    Point mu;
    Eigen::Matrix3d alpha;
    void init(double,double,double,double,double,double,Point,Eigen::Matrix3d);
};

void particle::init (double sigma_in, double eps_in, double x_in, double y_in, double z_in, double q_in, Point mu_in,Eigen::Matrix3d alpha_in) {
  sigma = sigma_in;
  eps = eps_in;
  x = x_in;
  y = y_in;
  z = z_in;
  q = q_in*pc::charge;
  mu = mu_in;
  alpha = alpha_in;
}

void Point::init (double x_in, double y_in, double z_in) {
  x = x_in;
  y = y_in;
  z = z_in;
}

double dist(const Point &p1, const Point &p2) {
  double dx = p1.x - p2.x;
  double dy = p1.y - p2.y;
  double dz = p1.z - p2.z;
  return sqrt(dx*dx+dy*dy+dz*dz);
}

Point getRab(const Point &p1, const Point &p2) {
  Point p;
  p.x = p2.x - p1.x;
  p.y = p2.y - p1.y;
  p.z = p2.z - p1.z;
  return p;
}

double DP(const Point &p1, const Point &p2) {
  return (p1.x*p2.x + p1.y*p2.y + p1.z*p2.z);
}

Point getUnitVector(const particle p1, const particle p2) {
  Point R = getRab(p1,p2);
  double r = dist(p1,p2);
  R.x = R.x/r;
  R.y = R.y/r;
  R.z = R.z/r;
  return R;
}

Point rotatePoint(Point p, double dTheta, double dPhi) {
  double x,y,z;
  Point q = getSPC(p);
  q.y = q.y + dTheta;
  q.z = q.z + dPhi;
  x = q.x*std::sin(q.y)*std::cos(q.z);
  y = q.x*std::sin(q.y)*std::sin(q.z);
  z = q.x*std::cos(q.y);
  p.x = x;
  p.y = y;
  p.z = z;
  return p;
}

double calcKeesom(const particle p1, const particle p2) {
  //std::cout << " Correct? " << DP(p1.mu,p2.mu)/(4*pc::den*pow(dist(p1,p2),3)) << " < " << pc::kT << "\n";
  return -DP(p1.mu,p1.mu)*DP(p2.mu,p2.mu)/(3*pc::den*pc::den*pc::kT*pow(dist(p1, p2),6));
}

double calcDIMean(const particle p1, const particle p2) {
  return -p1.q*p1.q*DP(p2.mu,p2.mu)/(6*pc::den*pc::den*pc::kT*pow(dist(p1,p2),4));
}

double getRand() {
  return ((double)rand()/RAND_MAX);
}

double getRandn() {
  return (getRand()-0.5)/0.5;
}

Point ranunit() {
  Point u;
  double r2;
  do {
    u.x=2*( getRand()-0.5 );
    u.y=2*( getRand()-0.5 );
    u.z=2*( getRand()-0.5 );
    r2=u.x*u.x+u.y*u.y+u.z*u.z;
  } while (r2>1);
  r2=sqrt(r2);
  u.x=u.x/r2;
  u.y=u.y/r2;
  u.z=u.z/r2;
  return u;
}

Point randomRotation(Point p, double step1, double step2) {
  Point u=ranunit();
  Eigen::Vector3d a;
  double theta=getRandn()*pc::pi/2;
  a.x()=u.x;
  a.y()=u.y;
  a.z()=u.z;
  Eigen::Quaterniond q;
  q=Eigen::AngleAxisd(theta, a);
  a.x()=p.x;
  a.y()=p.y;
  a.z()=p.z;
  a=q*a;
  p.x=a.x();
  p.y=a.y();
  p.z=a.z();
  return p;
}

std::vector<particle> getStartConfiguration(double r) {
  particle par1,par2;
  Point mu;
  std::vector<particle> p(2);

  Eigen::Matrix3d alpha(3,3); // se "initializer lists"
  alpha(0,0) = 7.14264826;
  alpha(1,0) = 0.00014943;
  alpha(1,1) = 5.64937691;
  alpha(2,0) = -0.00003816;
  alpha(2,1) = 0.00035990;
  alpha(2,2) = 6.03919669;

  mu.init(0.0,0.0,2.4126*pc::debye);
  par1.init(0.8, 0.1, 0, 0, 0, -1.0, mu,alpha);
  p.at(0) = par1;

  mu = randomRotation(mu,100,100);
  par2.init(0.8, 0.1, r, 0, 0, +1.0, mu,alpha);
  p.at(1) = par2;

  return p;
}

particle randomRadius(particle p, double dr) {
  p.x += dr*getRandn();
  return p;
}

std::vector<particle> initialRandom(std::vector<particle> p, double step, double dr, int opt) {
  double a = getRand();

  switch(opt) {
    case 1:
      if(a < 0.5) {
        p.at(0).mu = randomRotation(p.at(0).mu,step,step);
      } else {
        p.at(1).mu = randomRotation(p.at(1).mu,step,step);
      }
      break;
    case 2:
      p.at(1).mu = randomRotation(p.at(1).mu,step,step);
      break;
    case 3:
      if(a < 0.333333) {
        p.at(0).mu = randomRotation(p.at(0).mu,step,step);
      } else if(a < 0.666667) {
        p.at(1).mu = randomRotation(p.at(1).mu,step,step);
      } else {
        p.at(1) = randomRadius(p.at(1),dr);
      }
      break;
    case 4:
      if(a < 0.5) {
        p.at(1) = randomRadius(p.at(1),dr);
      } else {
        p.at(1).mu = randomRotation(p.at(1).mu,step,step);
      }
      break;
    case 5:
      p.at(1) = randomRadius(p.at(1),dr);
  }
  return p;
}

std::vector<particle> checkEnergy(double dE,std::vector<particle> p,std::vector<particle> p_t) {
  /*double r = dist(p_t.at(0),p_t.at(1));
    if (r < 2.0e-10 || r > 20e-10) {
    return p;
    }*/

  if(getRand() > std::exp(-dE) ) {
    return p;
  }
  accepted++;
  return p_t;
}

double calculateEnergy(std::vector<particle> &p, Energy &ene, int opt) {
  double r = dist(p.at(0),p.at(1));
  if (r < 0.5e-10 || r > 10e-10) {
    return 1e9;
  }

  if (opt == 2 || opt == 4) {
    return ene.q2mu(p.at(0), p.at(1))/(pc::kT);
  } else if (opt == 1 || opt == 3) {
    return ene.mu2mu(p.at(0), p.at(1))/(pc::kT);
  } else if (opt == 5) {
    return ene.q2q(p.at(0),p.at(1))/(pc::kT);
  } else {
    return 0.0;
  }
}

double getMean(std::vector<particle> p, int opt) {
  if(opt == 1 || opt == 3) {
    return calcKeesom(p.at(0), p.at(1))/pc::kT;
  } else if (opt == 2 || opt == 4) {
    return calcDIMean(p.at(0), p.at(1))/pc::kT;
  } else {
    return 0.0;
  }
}

class DipoleParticle : public PointParticle {
  public:
    double mu_s;            //!< Dipole moment scalar
    Eigen::Vector3d mu;     //!< Dipole moment unit vector
    Eigen::Matrix3d alpha;  //!< Polarization tensor

    inline DipoleParticle() {
      mu_s=0;
    }

    template<typename OtherDerived>
      DipoleParticle(const Eigen::MatrixBase<OtherDerived>& other) : Tvec(other) {}

    template<typename OtherDerived>
      DipoleParticle& operator=(const Eigen::MatrixBase<OtherDerived> &other) {
        Tvec::operator=(other);
        return *this;
      }
};

Point getSPC(Point p) {
  double r,theta,phi;
  r = std::sqrt(p.x*p.x + p.y*p.y + p.z*p.z);
  if (r != 0) {
    theta = std::acos(p.z/r);
    if (p.x != 0) {
      phi = std::atan(p.y/p.x);
    } else {
      if (std::sin(theta) != 0) {
        phi = std::acos(r*std::sin(theta));
      } else {
        phi = 0;
      }
    }
  } else {
    theta = 0;
    phi = 0;
  }
  Point q;
  q.x = r;
  q.y = theta;
  q.z = phi;
  return q;
}

class Energy {
  public:
    double q2q(const particle &p1, const particle &p2);
    double q2mu(const particle &p1, const particle &p2);
    double q2Q(const particle &p1, const particle &p2);
    double q2alpha(const particle &p1, const particle &p2);
    double mu2mu(const particle &p1, const particle &p2);
    double mu2Q(const particle &p1, const particle &p2);
    double mu2alpha(const particle &p1, const particle &p2);
    double Q2Q(const particle &p1, const particle &p2);
    double Q2alpha(const particle &p1, const particle &p2);
    double alpha2alpha(const particle &p1, const particle &p2);
    double total(const particle &p1, const particle &p2);
};

double Energy::q2q(const particle &p1, const particle &p2) {
  double R = dist(p1,p2);
  return p1.q*p2.q/(R*pc::den);
}

double Energy::q2mu(const particle &p1, const particle &p2) {
  Point r_0;
  r_0.init(0.0,0.0,0.0);
  Point R = geo.vdist(p1,p2);
  //Point R = getRab(p1,p2);
  double cosT = DP(R,p2.mu)/(dist(R,r_0)*dist(p2.mu,r_0));
  Point q = getSPC(p2.mu);
  double r = dist(p1,p2);
  return -p1.q*q.x*cosT/(pc::den*r*r);
}

double Energy::mu2mu(const particle &p1, const particle &p2) {
  double R = dist(p1,p2);
  Point q1 = getSPC(p1.mu);
  Point q2 = getSPC(p2.mu);
  return -q1.x*q2.x*(2*std::cos(q1.y)*std::cos(q2.y)-std::sin(q1.y)*std::sin(q2.y)*std::cos(q1.z-q2.z))/(pc::den*pow(R,3));
}

// Insert energy functions here!
// Major goal:
//   function: pairpot(particle &a, particle &b, point &vdist)

int main() {
  InputMap mcp("nemo.conf");
  Geometry::Sphere geo(mcp);
  Potential::Coulomb coulomb(mcp);

  cout << geo.info() << coulomb.info(25);

  DipoleParticle a, b;

  Point vdist = geo.vdist(a,b);
  double u = coulomb(a,b, geo.dist(a,b) );

  a.ranunit( slp_global ); // random unit vector
  double r = slp_global(); // random number [0:1[

  // Examples
  cout << "Squared distance = " << geo.sqdist(a,b) << "\n";
  cout << "Bjerrum          = " << coulomb.bjerrumLength() << "\n";
  cout << "Avogadro's number= " << pc::Nav << "\n";  // se "faunus/physconst.h"
}

int main1() {
  accepted=0;
  double r, dr,limit,step,dE;		// Initialize variables
  std::vector<particle> p,p_t;
  Energy ene;
  int N = 1e7;					// Number of random displacements
  r = 10e-10;					    // Radius between particles
  dr = 9e-10;						// Size of radius displacement
  step = 100.0;					// % of possible angle displacement to be displaced
  std::vector<Point> mu1(1);
  std::vector<Point> mu2(1);

  double dbin=0.1;
  std::vector<int> hist(1000);

  for (int i=0; i < hist.size(); i++) {
    hist[i]=0;
  }

  int opt = 3;					// 1 = dipole-dipole (no dr change)      2 = ion-dipole (no dr change)
  // 3 = dipole-dipole (include dr change) 4 = ion-dipole (include dr change)
  // 5 = charge-charge (include dr change)

  p = getStartConfiguration(r);										// Get initial configuration

  for(int n = 1; n < N ; n++) {
    p_t = initialRandom(p,step,dr,opt);								// Random displacement

    dE = calculateEnergy(p_t,ene,opt) - calculateEnergy(p,ene,opt); // Calculate energy differenace
    p = checkEnergy(dE,p,p_t);				                        // Check if move is allowed

    double r=dist(p[0],p[1])*1e10;
    int bin=(int)( (r/dbin)+0.5 );
    hist[bin]++;
  }

  std::ofstream oh("tabHist.dat");
  for (int i=0; i<hist.size(); i++)
    if (hist[i]>0)
      oh << i*dbin << " " << hist[i] << "\n";

  cout << "Acceptance = " << accepted/double(N) << "\n";

  //endLine();
  return 1;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "VisitorUtils.hpp"

#include "ltac/Statement.hpp"
#include "ltac/PseudoRegister.hpp"
#include "ltac/PseudoFloatRegister.hpp"
#include "ltac/LiveRegistersProblem.hpp"

using namespace eddic;

typedef ltac::LiveRegistersProblem::ProblemDomain ProblemDomain;

void ltac::LiveRegisterValues::insert(ltac::PseudoRegister reg){
    registers.insert(reg);
}

void ltac::LiveRegisterValues::insert(ltac::PseudoFloatRegister reg){
    float_registers.insert(reg);
}

void ltac::LiveRegisterValues::erase(ltac::PseudoRegister reg){
    registers.erase(reg);
}

void ltac::LiveRegisterValues::erase(ltac::PseudoFloatRegister reg){
    float_registers.erase(reg);
}

std::size_t ltac::LiveRegisterValues::size(){
    return (static_cast<std::size_t>(std::numeric_limits<unsigned short>::max()) + 1) * registers.size() + float_registers.size();
}

std::ostream& ltac::operator<<(std::ostream& stream, ltac::LiveRegisterValues& value){
    stream << "set{";

    for(auto& v : value.registers){
        stream << v << ", ";
    }

    for(auto& v : value.float_registers){
        stream << v << ", ";
    }

    return stream << "}";
}

ProblemDomain ltac::LiveRegistersProblem::Boundary(mtac::function_p /*function*/){
    auto value = default_element();
    return value;
}

ProblemDomain ltac::LiveRegistersProblem::Init(mtac::function_p /*function*/){
    auto value = default_element();
    return value;
}

ProblemDomain ltac::LiveRegistersProblem::meet(ProblemDomain& in, ProblemDomain& out){
    if(out.top()){
        return in;
    } else if(in.top()){
        return out;
    }

    typename ProblemDomain::Values values;
    ProblemDomain result(values);

    for(auto& value : in.values().registers){
        result.values().insert(value);
    }

    for(auto& value : in.values().float_registers){
        result.values().insert(value);
    }

    for(auto& value : out.values().registers){
        result.values().insert(value);
    }

    for(auto& value : out.values().float_registers){
        result.values().insert(value);
    }

    return result;
}

namespace {

struct LivenessCollector : public boost::static_visitor<> {
    ProblemDomain& in;

    LivenessCollector(ProblemDomain& in) : in(in) {}

    template<typename Arg>
    inline void set_live(Arg& arg){
        if(auto* ptr = boost::get<ltac::PseudoRegister>(&arg)){
            in.values().insert(*ptr);
        } else if(auto* ptr = boost::get<ltac::PseudoFloatRegister>(&arg)){
            in.values().insert(*ptr);
        } else if(auto* ptr = boost::get<ltac::Address>(&arg)){
            set_live_opt(ptr->base_register);
            set_live_opt(ptr->scaled_register);
        }
    }

    template<typename Arg>
    inline void set_dead(Arg& arg){
        if(auto* ptr = boost::get<ltac::PseudoRegister>(&arg)){
            in.values().erase(*ptr);
        } else if(auto* ptr = boost::get<ltac::PseudoFloatRegister>(&arg)){
            in.values().erase(*ptr);
        }
    }

    template<typename Arg>
    inline void set_live_opt(Arg& arg){
        if(arg){
            set_live(*arg);
        }
    }

    void operator()(std::shared_ptr<ltac::Instruction> instruction){
        if(instruction->op != ltac::Operator::NOP){
            if(ltac::erase_result_complete(instruction->op)){
                set_dead(*instruction->arg1);
            } else {
                set_live_opt(instruction->arg1);
            }

            set_live_opt(instruction->arg2);
            set_live_opt(instruction->arg3);
        }

        for(auto& reg : instruction->uses){
            in.values().insert(reg);
        }

        for(auto& reg : instruction->float_uses){
            in.values().insert(reg);
        }
    }

    void operator()(std::shared_ptr<ltac::Jump> instruction){
        for(auto& reg : instruction->uses){
            in.values().insert(reg);
        }

        for(auto& reg : instruction->float_uses){
            in.values().insert(reg);
        }
    }

    template<typename T>
    void operator()(T&){
        //Nothing to do
    }
};

} //End of anonymous namespace

ProblemDomain ltac::LiveRegistersProblem::transfer(mtac::basic_block_p /*basic_block*/, ltac::Statement& statement, ProblemDomain& in){
    auto out = in;

    LivenessCollector collector(out);
    visit(collector, statement);

    return out;
}

bool ltac::LiveRegistersProblem::optimize(ltac::Statement& /*statement*/, std::shared_ptr<mtac::DataFlowResults<ProblemDomain>> /*results*/){
    //This analysis is only made to gather information, not to optimize anything
    throw "Unimplemented";
}
<commit_msg>Kill registers defined by the calls<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "VisitorUtils.hpp"

#include "ltac/Statement.hpp"
#include "ltac/PseudoRegister.hpp"
#include "ltac/PseudoFloatRegister.hpp"
#include "ltac/LiveRegistersProblem.hpp"

using namespace eddic;

typedef ltac::LiveRegistersProblem::ProblemDomain ProblemDomain;

void ltac::LiveRegisterValues::insert(ltac::PseudoRegister reg){
    registers.insert(reg);
}

void ltac::LiveRegisterValues::insert(ltac::PseudoFloatRegister reg){
    float_registers.insert(reg);
}

void ltac::LiveRegisterValues::erase(ltac::PseudoRegister reg){
    registers.erase(reg);
}

void ltac::LiveRegisterValues::erase(ltac::PseudoFloatRegister reg){
    float_registers.erase(reg);
}

std::size_t ltac::LiveRegisterValues::size(){
    return (static_cast<std::size_t>(std::numeric_limits<unsigned short>::max()) + 1) * registers.size() + float_registers.size();
}

std::ostream& ltac::operator<<(std::ostream& stream, ltac::LiveRegisterValues& value){
    stream << "set{";

    for(auto& v : value.registers){
        stream << v << ", ";
    }

    for(auto& v : value.float_registers){
        stream << v << ", ";
    }

    return stream << "}";
}

ProblemDomain ltac::LiveRegistersProblem::Boundary(mtac::function_p /*function*/){
    auto value = default_element();
    return value;
}

ProblemDomain ltac::LiveRegistersProblem::Init(mtac::function_p /*function*/){
    auto value = default_element();
    return value;
}

ProblemDomain ltac::LiveRegistersProblem::meet(ProblemDomain& in, ProblemDomain& out){
    if(out.top()){
        return in;
    } else if(in.top()){
        return out;
    }

    typename ProblemDomain::Values values;
    ProblemDomain result(values);

    for(auto& value : in.values().registers){
        result.values().insert(value);
    }

    for(auto& value : in.values().float_registers){
        result.values().insert(value);
    }

    for(auto& value : out.values().registers){
        result.values().insert(value);
    }

    for(auto& value : out.values().float_registers){
        result.values().insert(value);
    }

    return result;
}

namespace {

struct LivenessCollector : public boost::static_visitor<> {
    ProblemDomain& in;

    LivenessCollector(ProblemDomain& in) : in(in) {}

    template<typename Arg>
    inline void set_live(Arg& arg){
        if(auto* ptr = boost::get<ltac::PseudoRegister>(&arg)){
            in.values().insert(*ptr);
        } else if(auto* ptr = boost::get<ltac::PseudoFloatRegister>(&arg)){
            in.values().insert(*ptr);
        } else if(auto* ptr = boost::get<ltac::Address>(&arg)){
            set_live_opt(ptr->base_register);
            set_live_opt(ptr->scaled_register);
        }
    }

    template<typename Arg>
    inline void set_dead(Arg& arg){
        if(auto* ptr = boost::get<ltac::PseudoRegister>(&arg)){
            in.values().erase(*ptr);
        } else if(auto* ptr = boost::get<ltac::PseudoFloatRegister>(&arg)){
            in.values().erase(*ptr);
        }
    }

    template<typename Arg>
    inline void set_live_opt(Arg& arg){
        if(arg){
            set_live(*arg);
        }
    }

    void operator()(std::shared_ptr<ltac::Instruction> instruction){
        if(instruction->op != ltac::Operator::NOP){
            if(ltac::erase_result_complete(instruction->op)){
                set_dead(*instruction->arg1);
            } else {
                set_live_opt(instruction->arg1);
            }

            set_live_opt(instruction->arg2);
            set_live_opt(instruction->arg3);
        }

        for(auto& reg : instruction->uses){
            in.values().insert(reg);
        }

        for(auto& reg : instruction->float_uses){
            in.values().insert(reg);
        }
    }

    void operator()(std::shared_ptr<ltac::Jump> instruction){
        for(auto& reg : instruction->uses){
            in.values().insert(reg);
        }

        for(auto& reg : instruction->float_uses){
            in.values().insert(reg);
        }

        for(auto& reg : instruction->kills){
            in.values().erase(reg);
        }

        for(auto& reg : instruction->float_kills){
            in.values().erase(reg);
        }
    }

    template<typename T>
    void operator()(T&){
        //Nothing to do
    }
};

} //End of anonymous namespace

ProblemDomain ltac::LiveRegistersProblem::transfer(mtac::basic_block_p /*basic_block*/, ltac::Statement& statement, ProblemDomain& in){
    auto out = in;

    LivenessCollector collector(out);
    visit(collector, statement);

    return out;
}

bool ltac::LiveRegistersProblem::optimize(ltac::Statement& /*statement*/, std::shared_ptr<mtac::DataFlowResults<ProblemDomain>> /*results*/){
    //This analysis is only made to gather information, not to optimize anything
    throw "Unimplemented";
}
<|endoftext|>


<commit_before>//   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <thread>
#include "paddle/fluid/framework/channel.h"
#include "paddle/fluid/operators/reader/reader_op_registry.h"

namespace paddle {
namespace operators {
namespace reader {

static constexpr size_t kDoubleBufferSize = 2;

class DoubleBufferReader : public framework::DecoratedReader {
 public:
  explicit DoubleBufferReader(
      ReaderBase* reader, platform::Place target_place = platform::CPUPlace())
      : DecoratedReader(reader), place_(target_place) {
    start_thread();
  }

  void start_thread() {
    buffer_ = framework::MakeChannel<std::vector<framework::LoDTensor>>(
        kDoubleBufferSize);
    std::thread prefetch([this] { PrefetchThreadFunc(); });
    prefetch.detach();
  }

  void ReadNext(std::vector<framework::LoDTensor>* out) override;
  void ReInit() override;

  ~DoubleBufferReader() { buffer_->Close(); }

  bool HasNext() const override;

 private:
  void PrefetchThreadFunc();

  framework::Channel<std::vector<framework::LoDTensor>>* buffer_;
  platform::Place place_;
  mutable std::vector<framework::LoDTensor> local_buffer_;
};

class CreateDoubleBufferReaderOp : public framework::OperatorBase {
 public:
  using framework::OperatorBase::OperatorBase;

 private:
  void RunImpl(const framework::Scope& scope,
               const platform::Place& dev_place) const override {
    const auto& underlying_reader = scope.FindVar(Input("UnderlyingReader"))
                                        ->Get<framework::ReaderHolder>();
    auto* out = scope.FindVar(Output("Out"))
                    ->template GetMutable<framework::ReaderHolder>();

    auto place_str = Attr<std::string>("place");
    platform::Place place;
    if (place_str == "CPU") {
      place = platform::CPUPlace();
    } else {
      std::istringstream sin(place_str);
      sin.seekg(std::string("CUDA:").size(), std::ios::beg);
      size_t num;
      sin >> num;
      place = platform::CUDAPlace(static_cast<int>(num));
    }

    out->Reset(new DoubleBufferReader(underlying_reader.Get(), place));
  }
};

class CreateDoubleBufferReaderOpMaker : public DecoratedReaderMakerBase {
 public:
  CreateDoubleBufferReaderOpMaker(OpProto* op_proto, OpAttrChecker* op_checker)
      : DecoratedReaderMakerBase(op_proto, op_checker) {
    AddComment(R"DOC(
      CreateDoubleBufferReader Operator

      A double buffer reader takes another reader as its 'underlying reader'.
      It launches another thread to execute the 'underlying reader' asynchronously,
      which prevents reading process from blocking subsequent training.
    )DOC");
    std::unordered_set<std::string> enum_range;
    constexpr size_t kMaxCUDADevs = 128;
    for (size_t i = 0; i < kMaxCUDADevs; ++i) {
      enum_range.insert(string::Sprintf("CUDA:%d", i));
    }
    enum_range.insert("CPU");
    AddAttr<std::string>("place", "The double buffer place, default is CPU")
        .SetDefault("CPU")
        .InEnum({enum_range});
  }
};

void DoubleBufferReader::ReadNext(std::vector<framework::LoDTensor>* out) {
  out->clear();
  if (local_buffer_.empty()) {
    buffer_->Receive(out);
  } else {
    *out = local_buffer_;
    local_buffer_.clear();
  }
}

void DoubleBufferReader::ReInit() {
  reader_->ReInit();
  buffer_->Close();
  start_thread();
}

void DoubleBufferReader::PrefetchThreadFunc() {
  VLOG(5) << "A new prefetch thread starts.";
  while (reader_->HasNext()) {
    std::vector<framework::LoDTensor> batch;
    reader_->ReadNext(&batch);
    if (platform::is_gpu_place(place_)) {
      std::vector<framework::LoDTensor> gpu_batch;
      gpu_batch.resize(batch.size());
      for (size_t i = 0; i < batch.size(); ++i) {
        framework::TensorCopy(batch[i], place_, &gpu_batch[i]);
        gpu_batch[i].set_lod(batch[i].lod());
      }
    }

    if (!buffer_->Send(&batch)) {
      VLOG(5) << "WARNING: The double buffer channel has been closed. The "
                 "prefetch thread terminates.";
      break;
    }
  }
  buffer_->Close();
}

bool DoubleBufferReader::HasNext() const {
  if (local_buffer_.empty()) {
    bool ok = buffer_->Receive(&local_buffer_);
    return ok;
  } else {
    return true;
  }
}

}  // namespace reader
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators::reader;
REGISTER_DECORATED_READER_OPERATOR(create_double_buffer_reader,
                                   ops::CreateDoubleBufferReaderOp,
                                   ops::CreateDoubleBufferReaderOpMaker);
<commit_msg>Make double_buffer reader async<commit_after>//   Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <thread>
#include "paddle/fluid/framework/channel.h"
#include "paddle/fluid/operators/reader/reader_op_registry.h"

namespace paddle {
namespace operators {
namespace reader {

static constexpr size_t kDoubleBufferSize = 2;

class DoubleBufferReader : public framework::DecoratedReader {
 public:
  struct Item {
    Item() : ctx_(nullptr) {}

    std::vector<framework::LoDTensor> payloads_;
    platform::DeviceContext* ctx_;
  };

  explicit DoubleBufferReader(
      ReaderBase* reader, platform::Place target_place = platform::CPUPlace())
      : DecoratedReader(reader), place_(target_place) {
    for (size_t i = 0; i < kDoubleBufferSize; ++i) {
      if (platform::is_gpu_place(place_)) {
#ifdef PADDLE_WITH_CUDA
        ctxs_.emplace_back(new platform::CUDADeviceContext(
            boost::get<platform::CUDAPlace>(place_)));
#else
#endif
      }
    }

    start_thread();
  }

  void start_thread() {
    buffer_ = framework::MakeChannel<Item>(kDoubleBufferSize);
    std::thread prefetch([this] { PrefetchThreadFunc(); });
    prefetch.detach();
  }

  void ReadNext(std::vector<framework::LoDTensor>* out) override;
  void ReInit() override;

  ~DoubleBufferReader() { buffer_->Close(); }

  bool HasNext() const override;

 private:
  void PrefetchThreadFunc();

  framework::Channel<Item>* buffer_;
  platform::Place place_;
  std::vector<std::unique_ptr<platform::DeviceContext>> ctxs_;
  mutable Item local_buffer_;
};

class CreateDoubleBufferReaderOp : public framework::OperatorBase {
 public:
  using framework::OperatorBase::OperatorBase;

 private:
  void RunImpl(const framework::Scope& scope,
               const platform::Place& dev_place) const override {
    const auto& underlying_reader = scope.FindVar(Input("UnderlyingReader"))
                                        ->Get<framework::ReaderHolder>();
    auto* out = scope.FindVar(Output("Out"))
                    ->template GetMutable<framework::ReaderHolder>();

    auto place_str = Attr<std::string>("place");
    platform::Place place;
    if (place_str == "CPU") {
      place = platform::CPUPlace();
    } else {
      std::istringstream sin(place_str);
      sin.seekg(std::string("CUDA:").size(), std::ios::beg);
      size_t num;
      sin >> num;
      place = platform::CUDAPlace(static_cast<int>(num));
    }

    out->Reset(new DoubleBufferReader(underlying_reader.Get(), place));
  }
};

class CreateDoubleBufferReaderOpMaker : public DecoratedReaderMakerBase {
 public:
  CreateDoubleBufferReaderOpMaker(OpProto* op_proto, OpAttrChecker* op_checker)
      : DecoratedReaderMakerBase(op_proto, op_checker) {
    AddComment(R"DOC(
      CreateDoubleBufferReader Operator

      A double buffer reader takes another reader as its 'underlying reader'.
      It launches another thread to execute the 'underlying reader' asynchronously,
      which prevents reading process from blocking subsequent training.
    )DOC");
    std::unordered_set<std::string> enum_range;
    constexpr size_t kMaxCUDADevs = 128;
    for (size_t i = 0; i < kMaxCUDADevs; ++i) {
      enum_range.insert(string::Sprintf("CUDA:%d", i));
    }
    enum_range.insert("CPU");
    AddAttr<std::string>("place", "The double buffer place, default is CPU")
        .SetDefault("CPU")
        .InEnum({enum_range});
  }
};

void DoubleBufferReader::ReadNext(std::vector<framework::LoDTensor>* out) {
  if (local_buffer_.payloads_.empty()) {
    buffer_->Receive(&local_buffer_);
  }

  *out = local_buffer_.payloads_;
  local_buffer_.payloads_.clear();
  if (local_buffer_.ctx_) {
    local_buffer_.ctx_->Wait();
  }
}

void DoubleBufferReader::ReInit() {
  reader_->ReInit();
  buffer_->Close();
  start_thread();
}

void DoubleBufferReader::PrefetchThreadFunc() {
  VLOG(5) << "A new prefetch thread starts.";
  size_t gpu_ctx_offset = 0;
  while (reader_->HasNext()) {
    Item batch;
    reader_->ReadNext(&batch.payloads_);
    if (platform::is_gpu_place(place_)) {
      std::vector<framework::LoDTensor> gpu_batch;
      auto& gpu_ctx = this->ctxs_[gpu_ctx_offset++];
      gpu_ctx_offset %= this->ctxs_.size();
      gpu_batch.resize(batch.payloads_.size());
      for (size_t i = 0; i < batch.payloads_.size(); ++i) {
        framework::TensorCopy(batch.payloads_[i], place_, *gpu_ctx,
                              &gpu_batch[i]);
        gpu_batch[i].set_lod(batch.payloads_[i].lod());
      }
      batch.ctx_ = gpu_ctx.get();
      std::swap(gpu_batch, batch.payloads_);
    }

    if (!buffer_->Send(&batch)) {
      VLOG(5) << "WARNING: The double buffer channel has been closed. The "
                 "prefetch thread terminates.";
      break;
    }
  }
  buffer_->Close();
}

bool DoubleBufferReader::HasNext() const {
  if (local_buffer_.payloads_.empty()) {
    bool ok = buffer_->Receive(&local_buffer_);
    return ok;
  } else {
    return true;
  }
}

}  // namespace reader
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators::reader;
REGISTER_DECORATED_READER_OPERATOR(create_double_buffer_reader,
                                   ops::CreateDoubleBufferReaderOp,
                                   ops::CreateDoubleBufferReaderOpMaker);
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(port): the ifdefs in here are a first step towards trying to determine
// the correct abstraction for all the OS functionality required at this
// stage of process initialization. It should not be taken as a final
// abstraction.

#include "build/build_config.h"

#if defined(OS_WIN)
#include <algorithm>
#include <atlbase.h>
#include <atlapp.h>
#include <malloc.h>
#include <new.h>
#endif

#if defined(OS_LINUX)
#include <gtk/gtk.h>
#endif

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/debug_util.h"
#include "base/icu_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/stats_table.h"
#include "base/string_util.h"
#if defined(OS_WIN)
#include "base/win_util.h"
#endif
#include "chrome/app/scoped_ole_initializer.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/sandbox_init_wrapper.h"
#if defined(OS_WIN)
#include "sandbox/src/sandbox.h"
#include "tools/memory_watcher/memory_watcher.h"
#endif
#if defined(OS_MACOSX)
#include "third_party/WebKit/WebKit/mac/WebCoreSupport/WebSystemInterface.h"
#endif

extern int BrowserMain(const MainFunctionParams&);
extern int RendererMain(const MainFunctionParams&);
extern int PluginMain(const MainFunctionParams&);
extern int WorkerMain(const MainFunctionParams&);

#if defined(OS_WIN)
// TODO(erikkay): isn't this already defined somewhere?
#define DLLEXPORT __declspec(dllexport)

// We use extern C for the prototype DLLEXPORT to avoid C++ name mangling.
extern "C" {
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
                                 sandbox::SandboxInterfaceInfo* sandbox_info,
                                 TCHAR* command_line);
}
#elif defined(OS_POSIX)
extern "C" {
int ChromeMain(int argc, const char** argv);
}
#endif

namespace {

#if defined(OS_WIN)
const wchar_t kProfilingDll[] = L"memory_watcher.dll";

// Load the memory profiling DLL.  All it needs to be activated
// is to be loaded.  Return true on success, false otherwise.
bool LoadMemoryProfiler() {
  HMODULE prof_module = LoadLibrary(kProfilingDll);
  return prof_module != NULL;
}

CAppModule _Module;

#pragma optimize("", off)
// Handlers for invalid parameter and pure call. They generate a breakpoint to
// tell breakpad that it needs to dump the process.
void InvalidParameter(const wchar_t* expression, const wchar_t* function,
                      const wchar_t* file, unsigned int line,
                      uintptr_t reserved) {
  __debugbreak();
}

void PureCall() {
  __debugbreak();
}

int OnNoMemory(size_t memory_size) {
  __debugbreak();
  // Return memory_size so it is not optimized out. Make sure the return value
  // is at least 1 so malloc/new is retried, especially useful when under a
  // debugger.
  return memory_size ? static_cast<int>(memory_size) : 1;
}

// Handlers to silently dump the current process when there is an assert in
// chrome.
void ChromeAssert(const std::string& str) {
  // Get the breakpad pointer from chrome.exe
  typedef void (__stdcall *DumpProcessFunction)();
  DumpProcessFunction DumpProcess = reinterpret_cast<DumpProcessFunction>(
      ::GetProcAddress(::GetModuleHandle(L"chrome.exe"), "DumpProcess"));
  if (DumpProcess)
    DumpProcess();
}

#pragma optimize("", on)

// Early versions of Chrome incorrectly registered a chromehtml: URL handler.
// Later versions fixed the registration but in some cases (e.g. Vista and non-
// admin installs) the fix could not be applied.  This prevents Chrome to be
// launched with the incorrect format.
// CORRECT: <broser.exe> -- "chromehtml:<url>"
// INVALID: <broser.exe> "chromehtml:<url>"
bool IncorrectChromeHtmlArguments(const std::wstring& command_line) {
  const wchar_t kChromeHtml[] = L"-- \"chromehtml:";
  const wchar_t kOffset = 5;  // Where chromehtml: starts in above
  std::wstring command_line_lower = command_line;

  // We are only searching for ASCII characters so this is OK.
  StringToLowerASCII(&command_line_lower);

  std::wstring::size_type pos = command_line_lower.find(
      kChromeHtml + kOffset);

  if (pos == std::wstring::npos)
    return false;

  // The browser is being launched with chromehtml: somewhere on the command
  // line.  We will not launch unless it's preceded by the -- switch terminator.
  if (pos >= kOffset) {
    if (equal(kChromeHtml, kChromeHtml + arraysize(kChromeHtml) - 1,
        command_line_lower.begin() + pos - kOffset)) {
      return false;
    }
  }

  return true;
}

#endif  // OS_WIN

// Register the invalid param handler and pure call handler to be able to
// notify breakpad when it happens.
void RegisterInvalidParamHandler() {
#if defined(OS_WIN)
  _set_invalid_parameter_handler(InvalidParameter);
  _set_purecall_handler(PureCall);
  // Gather allocation failure.
  _set_new_handler(&OnNoMemory);
  // Make sure malloc() calls the new handler too.
  _set_new_mode(1);
#endif
}

void SetupCRT(const CommandLine& parsed_command_line) {
#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
#else
  if (!parsed_command_line.HasSwitch(switches::kDisableBreakpad)) {
    _CrtSetReportMode(_CRT_ASSERT, 0);
  }
#endif

  // Enable the low fragmentation heap for the CRT heap. The heap is not changed
  // if the process is run under the debugger is enabled or if certain gflags
  // are set.
  bool use_lfh = false;
  if (parsed_command_line.HasSwitch(switches::kUseLowFragHeapCrt))
    use_lfh = parsed_command_line.GetSwitchValue(switches::kUseLowFragHeapCrt)
        != L"false";
  if (use_lfh) {
    void* crt_heap = reinterpret_cast<void*>(_get_heap_handle());
    ULONG enable_lfh = 2;
    HeapSetInformation(crt_heap, HeapCompatibilityInformation,
                       &enable_lfh, sizeof(enable_lfh));
  }
#endif
}

// Enable the heap profiler if the appropriate command-line switch is
// present, bailing out of the app we can't.
void EnableHeapProfiler(const CommandLine& parsed_command_line) {
#if defined(OS_WIN)
  if (parsed_command_line.HasSwitch(switches::kMemoryProfiling))
    if (!LoadMemoryProfiler())
      exit(-1);
#endif
}

void CommonSubprocessInit() {
  // Initialize ResourceBundle which handles files loaded from external
  // sources.  The language should have been passed in to us from the
  // browser process as a command line flag.
  ResourceBundle::InitSharedInstance(std::wstring());

#if defined(OS_WIN)
  // HACK: Let Windows know that we have started.  This is needed to suppress
  // the IDC_APPSTARTING cursor from being displayed for a prolonged period
  // while a subprocess is starting.
  PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
  MSG msg;
  PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
#endif
}

}  // namespace

#if defined(OS_WIN)
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
                                 sandbox::SandboxInterfaceInfo* sandbox_info,
                                 TCHAR* command_line) {
#elif defined(OS_POSIX)
int ChromeMain(int argc, const char** argv) {
#endif

#if defined(OS_MACOSX)
  DebugUtil::DisableOSCrashDumps();
#endif
  RegisterInvalidParamHandler();

  // The exit manager is in charge of calling the dtors of singleton objects.
  base::AtExitManager exit_manager;

  // We need this pool for all the objects created before we get to the
  // event loop, but we don't want to leave them hanging around until the
  // app quits. Each "main" needs to flush this pool right before it goes into
  // its main event loop to get rid of the cruft.
  base::ScopedNSAutoreleasePool autorelease_pool;

#if defined(OS_LINUX)
  // gtk_init() can change |argc| and |argv| and thus must be called before
  // CommandLine::Init().
  // TODO(estade): we should make a copy of |argv| instead of const_casting
  // it.
  gtk_init(&argc, const_cast<char***>(&argv));
#endif

  // Initialize the command line.
#if defined(OS_WIN)
  CommandLine::Init(0, NULL);
#else
  CommandLine::Init(argc, argv);
#endif
  const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();

#if defined(OS_WIN)
   // Must do this before any other usage of command line!
  if (::IncorrectChromeHtmlArguments(parsed_command_line.command_line_string()))
    return 1;
#endif

  SetupCRT(parsed_command_line);

  // Initialize the Chrome path provider.
  chrome::RegisterPathProvider();

  // Initialize the Stats Counters table.  With this initialized,
  // the StatsViewer can be utilized to read counters outside of
  // Chrome.  These lines can be commented out to effectively turn
  // counters 'off'.  The table is created and exists for the life
  // of the process.  It is not cleaned up.
  // TODO(port): we probably need to shut this down correctly to avoid
  // leaking shared memory regions on posix platforms.
  std::string statsfile = chrome::kStatsFilename;
  std::string pid_string = StringPrintf("-%d", base::GetCurrentProcId());
  statsfile += pid_string;
  StatsTable *stats_table = new StatsTable(statsfile,
      chrome::kStatsMaxThreads, chrome::kStatsMaxCounters);
  StatsTable::set_current(stats_table);

  StatsScope<StatsCounterTimer>
      startup_timer(chrome::Counters::chrome_main());

  // Enable the heap profiler as early as possible!
  EnableHeapProfiler(parsed_command_line);

  // Enable Message Loop related state asap.
  if (parsed_command_line.HasSwitch(switches::kMessageLoopHistogrammer))
    MessageLoop::EnableHistogrammer(true);

  std::wstring process_type =
    parsed_command_line.GetSwitchValue(switches::kProcessType);

  // Checks if the sandbox is enabled in this process and initializes it if this
  // is the case. The crash handler depends on this so it has to be done before
  // its initialization.
  SandboxInitWrapper sandbox_wrapper;
#if defined(OS_WIN)
  sandbox_wrapper.SetServices(sandbox_info);
#endif
  sandbox_wrapper.InitializeSandbox(parsed_command_line, process_type);

#if defined(OS_WIN)
  _Module.Init(NULL, instance);
#endif

  // Notice a user data directory override if any
  const std::wstring user_data_dir =
      parsed_command_line.GetSwitchValue(switches::kUserDataDir);
  if (!user_data_dir.empty())
    PathService::Override(chrome::DIR_USER_DATA, user_data_dir);

  bool single_process =
#if defined (GOOGLE_CHROME_BUILD)
    // This is an unsupported and not fully tested mode, so don't enable it for
    // official Chrome builds.
    false;
#else
    parsed_command_line.HasSwitch(switches::kSingleProcess);
#endif
  if (single_process)
    RenderProcessHost::set_run_renderer_in_process(true);
#if defined(OS_MACOSX)
  // TODO(port-mac): This is from renderer_main_platform_delegate.cc.
  // shess tried to refactor things appropriately, but it sprawled out
  // of control because different platforms needed different styles of
  // initialization.  Try again once we understand the process
  // architecture needed and where it should live.
  if (single_process)
    InitWebCoreSystemInterface();
#endif

  bool icu_result = icu_util::Initialize();
  CHECK(icu_result);

  logging::OldFileDeletionState file_state =
      logging::APPEND_TO_OLD_LOG_FILE;
  if (process_type.empty()) {
    file_state = logging::DELETE_OLD_LOG_FILE;
  }
  logging::InitChromeLogging(parsed_command_line, file_state);

#ifdef NDEBUG
  if (parsed_command_line.HasSwitch(switches::kSilentDumpOnDCHECK) &&
      parsed_command_line.HasSwitch(switches::kEnableDCHECK)) {
#if defined(OS_WIN)
    logging::SetLogReportHandler(ChromeAssert);
#endif
  }
#endif  // NDEBUG

  if (!process_type.empty())
    CommonSubprocessInit();

  startup_timer.Stop();  // End of Startup Time Measurement.

  MainFunctionParams main_params(parsed_command_line, sandbox_wrapper,
                                 &autorelease_pool);

  // TODO(port): turn on these main() functions as they've been de-winified.
  int rv = -1;
  if (process_type == switches::kRendererProcess) {
    rv = RendererMain(main_params);
  } else if (process_type == switches::kPluginProcess) {
#if defined(OS_WIN)
    rv = PluginMain(main_params);
#endif
  } else if (process_type == switches::kWorkerProcess) {
#if defined(OS_WIN)
    rv = WorkerMain(main_params);
#endif
  } else if (process_type.empty()) {
    ScopedOleInitializer ole_initializer;
    rv = BrowserMain(main_params);
  } else {
    NOTREACHED() << "Unknown process type";
  }

  if (!process_type.empty()) {
    ResourceBundle::CleanupSharedInstance();
  }

#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
  _CrtDumpMemoryLeaks();
#endif  // _CRTDBG_MAP_ALLOC

  _Module.Term();
#endif

  logging::CleanupChromeLogging();

  return rv;
}

<commit_msg>Linux: don't call gtk_init in the renderer process.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(port): the ifdefs in here are a first step towards trying to determine
// the correct abstraction for all the OS functionality required at this
// stage of process initialization. It should not be taken as a final
// abstraction.

#include "build/build_config.h"

#if defined(OS_WIN)
#include <algorithm>
#include <atlbase.h>
#include <atlapp.h>
#include <malloc.h>
#include <new.h>
#endif

#if defined(OS_LINUX)
#include <gtk/gtk.h>
#endif

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/debug_util.h"
#include "base/icu_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/scoped_nsautorelease_pool.h"
#include "base/stats_table.h"
#include "base/string_util.h"
#if defined(OS_WIN)
#include "base/win_util.h"
#endif
#include "chrome/app/scoped_ole_initializer.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/main_function_params.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/common/sandbox_init_wrapper.h"
#if defined(OS_WIN)
#include "sandbox/src/sandbox.h"
#include "tools/memory_watcher/memory_watcher.h"
#endif
#if defined(OS_MACOSX)
#include "third_party/WebKit/WebKit/mac/WebCoreSupport/WebSystemInterface.h"
#endif

extern int BrowserMain(const MainFunctionParams&);
extern int RendererMain(const MainFunctionParams&);
extern int PluginMain(const MainFunctionParams&);
extern int WorkerMain(const MainFunctionParams&);

#if defined(OS_WIN)
// TODO(erikkay): isn't this already defined somewhere?
#define DLLEXPORT __declspec(dllexport)

// We use extern C for the prototype DLLEXPORT to avoid C++ name mangling.
extern "C" {
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
                                 sandbox::SandboxInterfaceInfo* sandbox_info,
                                 TCHAR* command_line);
}
#elif defined(OS_POSIX)
extern "C" {
int ChromeMain(int argc, const char** argv);
}
#endif

namespace {

#if defined(OS_WIN)
const wchar_t kProfilingDll[] = L"memory_watcher.dll";

// Load the memory profiling DLL.  All it needs to be activated
// is to be loaded.  Return true on success, false otherwise.
bool LoadMemoryProfiler() {
  HMODULE prof_module = LoadLibrary(kProfilingDll);
  return prof_module != NULL;
}

CAppModule _Module;

#pragma optimize("", off)
// Handlers for invalid parameter and pure call. They generate a breakpoint to
// tell breakpad that it needs to dump the process.
void InvalidParameter(const wchar_t* expression, const wchar_t* function,
                      const wchar_t* file, unsigned int line,
                      uintptr_t reserved) {
  __debugbreak();
}

void PureCall() {
  __debugbreak();
}

int OnNoMemory(size_t memory_size) {
  __debugbreak();
  // Return memory_size so it is not optimized out. Make sure the return value
  // is at least 1 so malloc/new is retried, especially useful when under a
  // debugger.
  return memory_size ? static_cast<int>(memory_size) : 1;
}

// Handlers to silently dump the current process when there is an assert in
// chrome.
void ChromeAssert(const std::string& str) {
  // Get the breakpad pointer from chrome.exe
  typedef void (__stdcall *DumpProcessFunction)();
  DumpProcessFunction DumpProcess = reinterpret_cast<DumpProcessFunction>(
      ::GetProcAddress(::GetModuleHandle(L"chrome.exe"), "DumpProcess"));
  if (DumpProcess)
    DumpProcess();
}

#pragma optimize("", on)

// Early versions of Chrome incorrectly registered a chromehtml: URL handler.
// Later versions fixed the registration but in some cases (e.g. Vista and non-
// admin installs) the fix could not be applied.  This prevents Chrome to be
// launched with the incorrect format.
// CORRECT: <broser.exe> -- "chromehtml:<url>"
// INVALID: <broser.exe> "chromehtml:<url>"
bool IncorrectChromeHtmlArguments(const std::wstring& command_line) {
  const wchar_t kChromeHtml[] = L"-- \"chromehtml:";
  const wchar_t kOffset = 5;  // Where chromehtml: starts in above
  std::wstring command_line_lower = command_line;

  // We are only searching for ASCII characters so this is OK.
  StringToLowerASCII(&command_line_lower);

  std::wstring::size_type pos = command_line_lower.find(
      kChromeHtml + kOffset);

  if (pos == std::wstring::npos)
    return false;

  // The browser is being launched with chromehtml: somewhere on the command
  // line.  We will not launch unless it's preceded by the -- switch terminator.
  if (pos >= kOffset) {
    if (equal(kChromeHtml, kChromeHtml + arraysize(kChromeHtml) - 1,
        command_line_lower.begin() + pos - kOffset)) {
      return false;
    }
  }

  return true;
}

#endif  // OS_WIN

// Register the invalid param handler and pure call handler to be able to
// notify breakpad when it happens.
void RegisterInvalidParamHandler() {
#if defined(OS_WIN)
  _set_invalid_parameter_handler(InvalidParameter);
  _set_purecall_handler(PureCall);
  // Gather allocation failure.
  _set_new_handler(&OnNoMemory);
  // Make sure malloc() calls the new handler too.
  _set_new_mode(1);
#endif
}

void SetupCRT(const CommandLine& parsed_command_line) {
#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
#else
  if (!parsed_command_line.HasSwitch(switches::kDisableBreakpad)) {
    _CrtSetReportMode(_CRT_ASSERT, 0);
  }
#endif

  // Enable the low fragmentation heap for the CRT heap. The heap is not changed
  // if the process is run under the debugger is enabled or if certain gflags
  // are set.
  bool use_lfh = false;
  if (parsed_command_line.HasSwitch(switches::kUseLowFragHeapCrt))
    use_lfh = parsed_command_line.GetSwitchValue(switches::kUseLowFragHeapCrt)
        != L"false";
  if (use_lfh) {
    void* crt_heap = reinterpret_cast<void*>(_get_heap_handle());
    ULONG enable_lfh = 2;
    HeapSetInformation(crt_heap, HeapCompatibilityInformation,
                       &enable_lfh, sizeof(enable_lfh));
  }
#endif
}

// Enable the heap profiler if the appropriate command-line switch is
// present, bailing out of the app we can't.
void EnableHeapProfiler(const CommandLine& parsed_command_line) {
#if defined(OS_WIN)
  if (parsed_command_line.HasSwitch(switches::kMemoryProfiling))
    if (!LoadMemoryProfiler())
      exit(-1);
#endif
}

void CommonSubprocessInit() {
  // Initialize ResourceBundle which handles files loaded from external
  // sources.  The language should have been passed in to us from the
  // browser process as a command line flag.
  ResourceBundle::InitSharedInstance(std::wstring());

#if defined(OS_WIN)
  // HACK: Let Windows know that we have started.  This is needed to suppress
  // the IDC_APPSTARTING cursor from being displayed for a prolonged period
  // while a subprocess is starting.
  PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
  MSG msg;
  PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
#endif
}

}  // namespace

#if defined(OS_WIN)
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
                                 sandbox::SandboxInterfaceInfo* sandbox_info,
                                 TCHAR* command_line) {
#elif defined(OS_POSIX)
int ChromeMain(int argc, const char** argv) {
#endif

#if defined(OS_MACOSX)
  DebugUtil::DisableOSCrashDumps();
#endif
  RegisterInvalidParamHandler();

  // The exit manager is in charge of calling the dtors of singleton objects.
  base::AtExitManager exit_manager;

  // We need this pool for all the objects created before we get to the
  // event loop, but we don't want to leave them hanging around until the
  // app quits. Each "main" needs to flush this pool right before it goes into
  // its main event loop to get rid of the cruft.
  base::ScopedNSAutoreleasePool autorelease_pool;

  // Initialize the command line.
#if defined(OS_WIN)
  CommandLine::Init(0, NULL);
#else
  CommandLine::Init(argc, argv);
#endif
  const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();

#if defined(OS_WIN)
   // Must do this before any other usage of command line!
  if (::IncorrectChromeHtmlArguments(parsed_command_line.command_line_string()))
    return 1;
#endif

  SetupCRT(parsed_command_line);

  // Initialize the Chrome path provider.
  chrome::RegisterPathProvider();

  // Initialize the Stats Counters table.  With this initialized,
  // the StatsViewer can be utilized to read counters outside of
  // Chrome.  These lines can be commented out to effectively turn
  // counters 'off'.  The table is created and exists for the life
  // of the process.  It is not cleaned up.
  // TODO(port): we probably need to shut this down correctly to avoid
  // leaking shared memory regions on posix platforms.
  std::string statsfile = chrome::kStatsFilename;
  std::string pid_string = StringPrintf("-%d", base::GetCurrentProcId());
  statsfile += pid_string;
  StatsTable *stats_table = new StatsTable(statsfile,
      chrome::kStatsMaxThreads, chrome::kStatsMaxCounters);
  StatsTable::set_current(stats_table);

  StatsScope<StatsCounterTimer>
      startup_timer(chrome::Counters::chrome_main());

  // Enable the heap profiler as early as possible!
  EnableHeapProfiler(parsed_command_line);

  // Enable Message Loop related state asap.
  if (parsed_command_line.HasSwitch(switches::kMessageLoopHistogrammer))
    MessageLoop::EnableHistogrammer(true);

  std::wstring process_type =
    parsed_command_line.GetSwitchValue(switches::kProcessType);

  // Checks if the sandbox is enabled in this process and initializes it if this
  // is the case. The crash handler depends on this so it has to be done before
  // its initialization.
  SandboxInitWrapper sandbox_wrapper;
#if defined(OS_WIN)
  sandbox_wrapper.SetServices(sandbox_info);
#endif
  sandbox_wrapper.InitializeSandbox(parsed_command_line, process_type);

#if defined(OS_WIN)
  _Module.Init(NULL, instance);
#endif

  // Notice a user data directory override if any
  const std::wstring user_data_dir =
      parsed_command_line.GetSwitchValue(switches::kUserDataDir);
  if (!user_data_dir.empty())
    PathService::Override(chrome::DIR_USER_DATA, user_data_dir);

  bool single_process =
#if defined (GOOGLE_CHROME_BUILD)
    // This is an unsupported and not fully tested mode, so don't enable it for
    // official Chrome builds.
    false;
#else
    parsed_command_line.HasSwitch(switches::kSingleProcess);
#endif
  if (single_process)
    RenderProcessHost::set_run_renderer_in_process(true);
#if defined(OS_MACOSX)
  // TODO(port-mac): This is from renderer_main_platform_delegate.cc.
  // shess tried to refactor things appropriately, but it sprawled out
  // of control because different platforms needed different styles of
  // initialization.  Try again once we understand the process
  // architecture needed and where it should live.
  if (single_process)
    InitWebCoreSystemInterface();
#endif

  bool icu_result = icu_util::Initialize();
  CHECK(icu_result);

  logging::OldFileDeletionState file_state =
      logging::APPEND_TO_OLD_LOG_FILE;
  if (process_type.empty()) {
    file_state = logging::DELETE_OLD_LOG_FILE;
  }
  logging::InitChromeLogging(parsed_command_line, file_state);

#ifdef NDEBUG
  if (parsed_command_line.HasSwitch(switches::kSilentDumpOnDCHECK) &&
      parsed_command_line.HasSwitch(switches::kEnableDCHECK)) {
#if defined(OS_WIN)
    logging::SetLogReportHandler(ChromeAssert);
#endif
  }
#endif  // NDEBUG

  if (!process_type.empty())
    CommonSubprocessInit();

  startup_timer.Stop();  // End of Startup Time Measurement.

  MainFunctionParams main_params(parsed_command_line, sandbox_wrapper,
                                 &autorelease_pool);

  // TODO(port): turn on these main() functions as they've been de-winified.
  int rv = -1;
  if (process_type == switches::kRendererProcess) {
    rv = RendererMain(main_params);
  } else if (process_type == switches::kPluginProcess) {
#if defined(OS_WIN)
    rv = PluginMain(main_params);
#endif
  } else if (process_type == switches::kWorkerProcess) {
#if defined(OS_WIN)
    rv = WorkerMain(main_params);
#endif
  } else if (process_type.empty()) {
#if defined(OS_LINUX)
    // gtk_init() can change |argc| and |argv|, but nobody else uses them.
    gtk_init(&argc, const_cast<char***>(&argv));
#endif

    ScopedOleInitializer ole_initializer;
    rv = BrowserMain(main_params);
  } else {
    NOTREACHED() << "Unknown process type";
  }

  if (!process_type.empty()) {
    ResourceBundle::CleanupSharedInstance();
  }

#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
  _CrtDumpMemoryLeaks();
#endif  // _CRTDBG_MAP_ALLOC

  _Module.Term();
#endif

  logging::CleanupChromeLogging();

  return rv;
}

<|endoftext|>


<commit_before>
/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkFontHost.h"
#include "SkDescriptor.h"
#include "SkString.h"
#include "SkStream.h"
#include <stdio.h>

/* define this if we can use mmap() to access fonts from the filesystem */
#define SK_CAN_USE_MMAP

#ifndef SK_FONTPATH
    #define SK_FONTPATH "the complete path for a font file"
#endif

struct FontFaceRec {
    const char* fFileName;
    uint8_t     fFamilyIndex;
    SkBool8     fBold;
    SkBool8     fItalic;

    static const FontFaceRec& FindFace(const FontFaceRec rec[], int count,
                                       int isBold, int isItalic);
};

struct FontFamilyRec {
    const FontFaceRec*  fFaces;
    int                 fFaceCount;
};

const FontFaceRec& FontFaceRec::FindFace(const FontFaceRec rec[], int count,
                                         int isBold, int isItalic)
{
    SkASSERT(count > 0);

    int i;

    // look for an exact match
    for (i = 0; i < count; i++) {
        if (rec[i].fBold == isBold && rec[i].fItalic == isItalic)
            return rec[i];
    }
    // look for a match in the bold field
    for (i = 0; i < count; i++) {
        if (rec[i].fBold == isBold)
            return rec[i];
    }
    // look for a normal/regular face
    for (i = 0; i < count; i++) {
        if (!rec[i].fBold && !rec[i].fItalic)
            return rec[i];
    }
    // give up
    return rec[0];
}

enum {
    DEFAULT_FAMILY_INDEX,

    FAMILY_INDEX_COUNT
};

static const FontFaceRec gDefaultFaces[] = {
    { SK_FONTPATH, DEFAULT_FAMILY_INDEX, 0,  0 }
};

// This table must be in the same order as the ..._FAMILY_INDEX enum specifies
static const FontFamilyRec gFamilies[] = {
    { gDefaultFaces,   SK_ARRAY_COUNT(gDefaultFaces)  }
};

#define DEFAULT_FAMILY_INDEX            DEFAULT_FAMILY_INDEX
#define DEFAULT_FAMILY_FACE_INDEX       0

///////////////////////////////////////////////////////////////////////////////

/* map common "web" font names to our font list */

struct FontFamilyMatchRec {
    const char* fLCName;
    int         fFamilyIndex;
};

/*  This is a table of synonyms for collapsing font names
    down to their pseudo-equivalents (i.e. in terms of fonts
    we actually have.)
    Keep this sorted by the first field so we can do a binary search.
    If this gets big, we could switch to a hash...
*/
static const FontFamilyMatchRec gMatches[] = {
#if 0
    { "Ahem",               Ahem_FAMILY_INDEX },
    { "arial",              SANS_FAMILY_INDEX },
    { "courier",            MONO_FAMILY_INDEX },
    { "courier new",        MONO_FAMILY_INDEX },
    { "cursive",            SERIF_FAMILY_INDEX },
    { "fantasy",            SERIF_FAMILY_INDEX },
    { "georgia",            SERIF_FAMILY_INDEX },
    { "goudy",              SERIF_FAMILY_INDEX },
    { "helvetica",          SANS_FAMILY_INDEX },
    { "palatino",           SERIF_FAMILY_INDEX },
    { "tahoma",             SANS_FAMILY_INDEX },
    { "sans-serif",         SANS_FAMILY_INDEX },
    { "serif",              SERIF_FAMILY_INDEX },
    { "times",              SERIF_FAMILY_INDEX },
    { "times new roman",    SERIF_FAMILY_INDEX },
    { "verdana",            SANS_FAMILY_INDEX }
#endif
};

///////////////////////////////////////////////////////////////////////////////

#include "SkTSearch.h"

static bool contains_only_ascii(const char s[])
{
    for (;;)
    {
        int c = *s++;
        if (c == 0)
            break;
        if ((c >> 7) != 0)
            return false;
    }
    return true;
}

#define TRACE_FONT_NAME(code)
//#define TRACE_FONT_NAME(code)   code

const FontFamilyRec* find_family_rec(const char target[])
{
    int     index;

    //  If we're asked for a font name that contains non-ascii,
    //  1) SkStrLCSearch can't handle it
    //  2) All of our fonts are have ascii names, so...

TRACE_FONT_NAME(printf("----------------- font request <%s>", target);)

    if (contains_only_ascii(target))
    {
        // Search for the font by matching the entire name
        index = SkStrLCSearch(&gMatches[0].fLCName, SK_ARRAY_COUNT(gMatches),
                              target, sizeof(gMatches[0]));
        if (index >= 0)
        {
            TRACE_FONT_NAME(printf(" found %d\n", index);)
            return &gFamilies[gMatches[index].fFamilyIndex];
        }
    }

    // Sniff for key words...

#if 0
    if (strstr(target, "sans") || strstr(target, "Sans"))
    {
        TRACE_FONT_NAME(printf(" found sans\n");)
        return &gFamilies[SANS_FAMILY_INDEX];
    }
    if (strstr(target, "serif") || strstr(target, "Serif"))
    {
        TRACE_FONT_NAME(printf(" found serif\n");)
        return &gFamilies[SERIF_FAMILY_INDEX];
    }
    if (strstr(target, "mono") || strstr(target, "Mono"))
    {
        TRACE_FONT_NAME(printf(" found mono\n");)
        return &gFamilies[MONO_FAMILY_INDEX];
    }
#endif

    TRACE_FONT_NAME(printf(" use default\n");)
    // we give up, just give them the default font
    return &gFamilies[DEFAULT_FAMILY_INDEX];
}

///////////////////////////////////////////////////////////////////////////////

static const FontFaceRec* get_default_face()
{
    return &gFamilies[DEFAULT_FAMILY_INDEX].fFaces[DEFAULT_FAMILY_FACE_INDEX];
}

static SkTypeface::Style get_style(const FontFaceRec& face) {
    int style = 0;
    if (face.fBold) {
        style |= SkTypeface::kBold;
    }
    if (face.fItalic) {
        style |= SkTypeface::kItalic;
    }
    return static_cast<SkTypeface::Style>(style);
}

// This global const reference completely identifies the face
static uint32_t get_id(const FontFaceRec& face) {
    uintptr_t id = reinterpret_cast<uintptr_t>(&face);
    return static_cast<uint32_t>(id);
}

class FontFaceRec_Typeface : public SkTypeface {
public:
    FontFaceRec_Typeface(const FontFaceRec& face) :
                         SkTypeface(get_style(face), get_id(face)),
                         fFace(face)
    {
    }

    // This global const reference completely identifies the face
    const FontFaceRec& fFace;
};

static const FontFaceRec* get_typeface_rec(const SkTypeface* face)
{
    const FontFaceRec_Typeface* f = (FontFaceRec_Typeface*)face;
    return f ? &f->fFace : get_default_face();
}

static uint32_t ptr2uint32(const void* p)
{
    // cast so we avoid warnings on 64bit machines that a ptr difference
    // which might be 64bits is being trucated from 64 to 32
    return (uint32_t)((char*)p - (char*)0);
}

SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
                                       const char familyName[],
                                       SkTypeface::Style style)
{
    const FontFamilyRec* family;

    if (familyFace)
        family = &gFamilies[
                    ((FontFaceRec_Typeface*)familyFace)->fFace.fFamilyIndex];
    else if (familyName)
        family = find_family_rec(familyName);
    else
        family = &gFamilies[DEFAULT_FAMILY_INDEX];

    const FontFaceRec& face = FontFaceRec::FindFace(family->fFaces,
                                            family->fFaceCount,
                                            (style & SkTypeface::kBold) != 0,
                                            (style & SkTypeface::kItalic) != 0);

    // if we're returning our input parameter, no need to create a new instance
    if (familyFace != NULL &&
            &((FontFaceRec_Typeface*)familyFace)->fFace == &face)
    {
        familyFace->ref();
        return (SkTypeface*)familyFace;
    }
    return SkNEW_ARGS(FontFaceRec_Typeface, (face));
}

// static
SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
        uint32_t fontID,
        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
        const uint32_t* glyphIDs,
        uint32_t glyphIDsCount) {
    sk_throw();  // not implemented
    return NULL;
}

SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
    sk_throw();  // not implemented
    return NULL;
}

SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
    sk_throw();  // not implemented
    return NULL;
}

SkStream* SkFontHost::OpenStream(uint32_t fontID) {
    sk_throw();  // not implemented
    return NULL;
}

size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
                               int32_t* index) {
    SkDebugf("SkFontHost::GetFileName unimplemented\n");
    return 0;
}

void SkFontHost::Serialize(const SkTypeface* tface, SkWStream* stream) {
    const FontFaceRec* face = &((const FontFaceRec_Typeface*)tface)->fFace;
    stream->write(face, sizeof(face));
}

SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
    const FontFaceRec* face;
    stream->read(&face, sizeof(face));
    return new FontFaceRec_Typeface(*face);
}

SkScalerContext* SkFontHost::CreateFallbackScalerContext(
                                                const SkScalerContext::Rec& rec)
{
    const FontFaceRec* face = get_default_face();

    SkAutoDescriptor    ad(sizeof(rec) + sizeof(face) +
                           SkDescriptor::ComputeOverhead(2));
    SkDescriptor*       desc = ad.getDesc();
    SkScalerContext::Rec* newRec;

    desc->init();
    newRec = reinterpret_cast<SkScalerContext::Rec*>(
        desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec));
    newRec->fFontID = get_id(*face);
    desc->computeChecksum();

    return SkFontHost::CreateScalerContext(desc);
}
<commit_msg>remove obsolete/orphaned font backend<commit_after><|endoftext|>


<commit_before>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

// TestTransform.h
#include <gtest/gtest.h>

#include <vw/Image/ImageView.h>
#include <vw/Image/Transform.h>

using namespace vw;

template <template<class> class TraitT, class T>
static bool bool_trait( T const& /*arg*/ ) {
  return TraitT<T>::value;
}

TEST( Transform, BBoxComp ) { // wikka wikka
  ImageView<double> im(2,3); im(0,0)=1; im(1,0)=2; im(0,1)=3; im(1,1)=4; im(0,2)=5; im(1,2)=6;
  TransformView<InterpolationView<EdgeExtensionView<ImageView<double>, ZeroEdgeExtension>, BilinearInterpolation>, TranslateTransform> im2 = transform(im, TranslateTransform(1,1));
}

TEST( Transform, Translate ) {
  ImageView<double> im(2,3); im(0,0)=1; im(1,0)=2; im(0,1)=3; im(1,1)=4; im(0,2)=5; im(1,2)=6;
  ImageView<double> im3 = transform(im, TranslateTransform(1,1));
  TransformView<InterpolationView<EdgeExtensionView<ImageView<double>, ZeroEdgeExtension>, BilinearInterpolation>, TranslateTransform> im2 = transform(im, TranslateTransform(1,1));
  ASSERT_EQ( im2.cols(), 2 );
  ASSERT_EQ( im2.rows(), 3 );
  EXPECT_EQ( im2(1,1), 1 );
  EXPECT_EQ( im2(0,0), 0 );
  EXPECT_EQ( im2(1,2), 3 );
  EXPECT_EQ( im2(-1,-1), 0 );
  EXPECT_EQ( im2(-100,-100), 0 );

  // Test accessor
  EXPECT_EQ( *(im2.origin().advance(1,1)), 1 );
  EXPECT_EQ( *(im2.origin().advance(-1,-1)), 0 );

  // Test the traits
  ASSERT_TRUE( bool_trait<IsFloatingPointIndexable>( im2 ) );
  ASSERT_TRUE( bool_trait<IsFloatingPointIndexable>( transform(im, TranslateTransform(1,1)) ) );
  ASSERT_FALSE( bool_trait<IsMultiplyAccessible>( transform(im, TranslateTransform(1,1)) ) );
}

TEST( Transform, TranslateFunc ) {
  ImageView<double> im(2,3); im(0,0)=1; im(1,0)=2; im(0,1)=3; im(1,1)=4; im(0,2)=5; im(1,2)=6;
  ImageView<double> im2;
  // FIXME This test exhibits a Heisenbug on gc.cs.cmu.edu when used
  // with the default BilinearInterpolation (Red Hat gcc 4.0.2-8).
  // Attempts at replicating the bug in other contexts fail, so we
  // just work around it here for the moment.
  im2 = translate(im,1.0,1.0,ZeroEdgeExtension(),NearestPixelInterpolation());
  ASSERT_EQ( im2.cols(), 2 );
  ASSERT_EQ( im2.rows(), 3 );
  EXPECT_EQ( im2(1,1), 1 );
  EXPECT_EQ( im2(0,0), 0 );
  EXPECT_EQ( im2(1,2), 3 );
  im2 = translate(im,1,1);
  ASSERT_EQ( im2.cols(), 2 );
  ASSERT_EQ( im2.rows(), 3 );
  EXPECT_EQ( im2(1,1), 1 );
  EXPECT_EQ( im2(0,0), 0 );
  EXPECT_EQ( im2(1,2), 3 );
}

TEST( Transform, Resample ) {
  ImageView<double> im(2,3); im(0,0)=1; im(1,0)=2; im(0,1)=3; im(1,1)=4; im(0,2)=5; im(1,2)=6;
  TransformView<InterpolationView<EdgeExtensionView<ImageView<double>, ConstantEdgeExtension>, BilinearInterpolation>, ResampleTransform> im2 = resample(im, 2, 2);
  ASSERT_EQ( im2.cols(), 4 );
  ASSERT_EQ( im2.rows(), 6 );
  EXPECT_EQ( im2(0,0), 1 );
  EXPECT_EQ( im2(2,2), 4 );
  EXPECT_EQ( im2(1,1), 2.5 );
  EXPECT_EQ( im2(-1,-1), 1 );
  EXPECT_EQ( im2(-100,-100), 1 );
  EXPECT_EQ( im2(100,100), 6 );

  // Test accessor
  EXPECT_EQ( *(im2.origin().advance(0,0)), 1 );
  EXPECT_EQ( *(im2.origin().advance(-1,-1)), 1 );

  // Test the traits
  ASSERT_TRUE( bool_trait<IsFloatingPointIndexable>( im2 ) );
  ASSERT_TRUE( bool_trait<IsFloatingPointIndexable>( transform(im, ResampleTransform(1,1)) ) );
  ASSERT_FALSE( bool_trait<IsMultiplyAccessible>( transform(im, ResampleTransform(1,1)) ) );
}
<commit_msg>add a (currently-failing) test for vw::rotate<commit_after>// __BEGIN_LICENSE__
// Copyright (C) 2006-2010 United States Government as represented by
// the Administrator of the National Aeronautics and Space Administration.
// All Rights Reserved.
// __END_LICENSE__

#include <gtest/gtest.h>
#include <test/Helpers.h>

#include <vw/Image/ImageView.h>
#include <vw/Image/Transform.h>

using namespace vw;

template <template<class> class TraitT, class T>
static bool bool_trait( T const& /*arg*/ ) {
  return TraitT<T>::value;
}

TEST( Transform, BBoxComp ) { // wikka wikka
  ImageView<double> im(2,3); im(0,0)=1; im(1,0)=2; im(0,1)=3; im(1,1)=4; im(0,2)=5; im(1,2)=6;
  TransformView<InterpolationView<EdgeExtensionView<ImageView<double>, ZeroEdgeExtension>, BilinearInterpolation>, TranslateTransform> im2 = transform(im, TranslateTransform(1,1));
}

TEST( Transform, Translate ) {
  ImageView<double> im(2,3); im(0,0)=1; im(1,0)=2; im(0,1)=3; im(1,1)=4; im(0,2)=5; im(1,2)=6;
  ImageView<double> im3 = transform(im, TranslateTransform(1,1));
  TransformView<InterpolationView<EdgeExtensionView<ImageView<double>, ZeroEdgeExtension>, BilinearInterpolation>, TranslateTransform> im2 = transform(im, TranslateTransform(1,1));
  ASSERT_EQ( im2.cols(), 2 );
  ASSERT_EQ( im2.rows(), 3 );
  EXPECT_EQ( im2(1,1), 1 );
  EXPECT_EQ( im2(0,0), 0 );
  EXPECT_EQ( im2(1,2), 3 );
  EXPECT_EQ( im2(-1,-1), 0 );
  EXPECT_EQ( im2(-100,-100), 0 );

  // Test accessor
  EXPECT_EQ( *(im2.origin().advance(1,1)), 1 );
  EXPECT_EQ( *(im2.origin().advance(-1,-1)), 0 );

  // Test the traits
  ASSERT_TRUE( bool_trait<IsFloatingPointIndexable>( im2 ) );
  ASSERT_TRUE( bool_trait<IsFloatingPointIndexable>( transform(im, TranslateTransform(1,1)) ) );
  ASSERT_FALSE( bool_trait<IsMultiplyAccessible>( transform(im, TranslateTransform(1,1)) ) );
}

TEST( Transform, TranslateFunc ) {
  ImageView<double> im(2,3); im(0,0)=1; im(1,0)=2; im(0,1)=3; im(1,1)=4; im(0,2)=5; im(1,2)=6;
  ImageView<double> im2;
  // FIXME This test exhibits a Heisenbug on gc.cs.cmu.edu when used
  // with the default BilinearInterpolation (Red Hat gcc 4.0.2-8).
  // Attempts at replicating the bug in other contexts fail, so we
  // just work around it here for the moment.
  im2 = translate(im,1.0,1.0,ZeroEdgeExtension(),NearestPixelInterpolation());
  ASSERT_EQ( im2.cols(), 2 );
  ASSERT_EQ( im2.rows(), 3 );
  EXPECT_EQ( im2(1,1), 1 );
  EXPECT_EQ( im2(0,0), 0 );
  EXPECT_EQ( im2(1,2), 3 );
  im2 = translate(im,1,1);
  ASSERT_EQ( im2.cols(), 2 );
  ASSERT_EQ( im2.rows(), 3 );
  EXPECT_EQ( im2(1,1), 1 );
  EXPECT_EQ( im2(0,0), 0 );
  EXPECT_EQ( im2(1,2), 3 );
}

TEST( Transform, Resample ) {
  ImageView<double> im(2,3); im(0,0)=1; im(1,0)=2; im(0,1)=3; im(1,1)=4; im(0,2)=5; im(1,2)=6;
  TransformView<InterpolationView<EdgeExtensionView<ImageView<double>, ConstantEdgeExtension>, BilinearInterpolation>, ResampleTransform> im2 = resample(im, 2, 2);
  ASSERT_EQ( im2.cols(), 4 );
  ASSERT_EQ( im2.rows(), 6 );
  EXPECT_EQ( im2(0,0), 1 );
  EXPECT_EQ( im2(2,2), 4 );
  EXPECT_EQ( im2(1,1), 2.5 );
  EXPECT_EQ( im2(-1,-1), 1 );
  EXPECT_EQ( im2(-100,-100), 1 );
  EXPECT_EQ( im2(100,100), 6 );

  // Test accessor
  EXPECT_EQ( *(im2.origin().advance(0,0)), 1 );
  EXPECT_EQ( *(im2.origin().advance(-1,-1)), 1 );

  // Test the traits
  ASSERT_TRUE( bool_trait<IsFloatingPointIndexable>( im2 ) );
  ASSERT_TRUE( bool_trait<IsFloatingPointIndexable>( transform(im, ResampleTransform(1,1)) ) );
  ASSERT_FALSE( bool_trait<IsMultiplyAccessible>( transform(im, ResampleTransform(1,1)) ) );
}

TEST( Transform, Rotate ) {
  typedef PixelRGB<uint8> Px;
  Px gray(0x7f,0x7f,0x7f), r(0xff,0,0), g(0,0xff,0), b(0,0,0xff);

  ImageView<Px> src(2,2);
  src(0,0) = gray;
  src(1,0) = r;
  src(0,1) = g;
  src(1,1) = b;

  ImageView<Px> dst =
    vw::crop(
      vw::rotate(
        vw::translate(src, -src.cols()/2, -src.rows()/2),
        2*M_PI),
      -src.cols()/2, -src.rows()/2, src.cols(), src.rows());

  EXPECT_MATRIX_EQ(src, dst);
}
<|endoftext|>


<commit_before>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-7 15:32:10
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 1 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
const int infty = 1000000007;

int N, M, L, X;
int a[1010];
int DP[1010];
int DP2[1010];
int sum;

int main()
{
  cin >> N >> M >> L >> X;
  for (auto i = 0; i < N; i++)
  {
    cin >> a[i];
  }
  int maxi = (X - 1) * M + L;
  fill(DP, DP + M, infty);
  DP[0] = 0;
  for (auto i = 0; i < N; i++)
  {
    for (auto j = 0; j < M; j++)
    {
      DP2[j] = DP[j];
    }
    for (auto j = 0; j < M; j++)
    {
      if (DP[j] == infty)
        continue;
      sum = DP[j] + a[i];
      DP2[sum % M] = min(DP[sum % M], sum);
    }
    for (auto j = 0; j < M; j++)
    {
      DP[j] = DP2[j];
    }
#if DEBUG == 1
    for (auto j = 0; j < M; j++)
    {
      cerr << DP[j] << " ";
    }
    cerr << endl;
#endif
  }
  cerr << ((DP[L] <= maxi) ? "Yes" : "No") << endl;
}<commit_msg>tried D.cpp to 'D'<commit_after>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-7 15:32:10
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
const int infty = 1000000007;

int N, M, L, X;
int a[10010];
int DP[1010];
int DP2[1010];
int sum;

int main()
{
  cin >> N >> M >> L >> X;
  for (auto i = 0; i < N; i++)
  {
    cin >> a[i];
  }
  int maxi = (X - 1) * M + L;
  fill(DP, DP + M, infty);
  DP[0] = 0;
  for (auto i = 0; i < N; i++)
  {
    for (auto j = 0; j < M; j++)
    {
      DP2[j] = DP[j];
    }
    for (auto j = 0; j < M; j++)
    {
      if (DP[j] == infty)
        continue;
      sum = DP[j] + a[i];
      DP2[sum % M] = min(DP[sum % M], sum);
    }
    for (auto j = 0; j < M; j++)
    {
      DP[j] = DP2[j];
    }
#if DEBUG == 1
    for (auto j = 0; j < M; j++)
    {
      cerr << DP[j] << " ";
    }
    cerr << endl;
#endif
  }
  cerr << ((DP[L] <= maxi) ? "Yes" : "No") << endl;
}<|endoftext|>


<commit_before>/*
 *
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */
#include "config.h"
#include "QWebPopup.h"
#include "PopupMenuStyle.h"

#include <QCoreApplication>
#include <QMouseEvent>

namespace WebCore {

QWebPopup::QWebPopup(PopupMenuClient* client)
    : m_client(client)
    , m_popupVisible(false)
{
    Q_ASSERT(m_client);

    setFont(m_client->itemStyle().font().font());
    connect(this, SIGNAL(activated(int)),
            SLOT(activeChanged(int)));
}

void QWebPopup::exec()
{
    QMouseEvent event(QEvent::MouseButtonPress, QCursor::pos(), Qt::LeftButton,
                      Qt::LeftButton, Qt::NoModifier);
    QCoreApplication::sendEvent(this, &event);
}

void QWebPopup::showPopup()
{
    QComboBox::showPopup();
    m_popupVisible = true;
}

void QWebPopup::hidePopup()
{
    QComboBox::hidePopup();
    if (!m_popupVisible)
        return;

    m_popupVisible = false;
    m_client->hidePopup();
}

void QWebPopup::activeChanged(int index)
{
    if (index < 0)
        return;

    m_client->valueChanged(index);
}

}
<commit_msg>Fix Qt bustage.<commit_after>/*
 *
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */
#include "config.h"
#include "QWebPopup.h"
#include "PopupMenuStyle.h"

#include <QCoreApplication>
#include <QMouseEvent>

namespace WebCore {

QWebPopup::QWebPopup(PopupMenuClient* client)
    : m_client(client)
    , m_popupVisible(false)
{
    Q_ASSERT(m_client);

    setFont(m_client->menuStyle().font().font());
    connect(this, SIGNAL(activated(int)),
            SLOT(activeChanged(int)));
}

void QWebPopup::exec()
{
    QMouseEvent event(QEvent::MouseButtonPress, QCursor::pos(), Qt::LeftButton,
                      Qt::LeftButton, Qt::NoModifier);
    QCoreApplication::sendEvent(this, &event);
}

void QWebPopup::showPopup()
{
    QComboBox::showPopup();
    m_popupVisible = true;
}

void QWebPopup::hidePopup()
{
    QComboBox::hidePopup();
    if (!m_popupVisible)
        return;

    m_popupVisible = false;
    m_client->hidePopup();
}

void QWebPopup::activeChanged(int index)
{
    if (index < 0)
        return;

    m_client->valueChanged(index);
}

}
<|endoftext|>


<commit_before>/**
 * @file ButtonEventMonitor.cpp
 *
 * @author Heinrich Mellmann
 *
 */

#include "ButtonEventMonitor.h"

void ButtonEventMonitor::execute()
{
  update(getButtonState()[ButtonState::Chest], getButtonData().isPressed[ButtonData::Chest]);
  update(getButtonState()[ButtonState::LeftFoot],
    getButtonData().isPressed[ButtonData::LeftFootLeft] || getButtonData().isPressed[ButtonData::LeftFootRight]);
  update(getButtonState()[ButtonState::RightFoot],
    getButtonData().isPressed[ButtonData::RightFootLeft] || getButtonData().isPressed[ButtonData::RightFootRight]);
  update(getButtonState()[ButtonState::HeadMiddle],
    getButtonData().isPressed[ButtonData::HeadMiddle] || getButtonData().isPressed[ButtonData::HeadMiddle]);
}

void ButtonEventMonitor::update(ButtonEvent& buttonEvent, bool pressed)
{
  const unsigned int maxSequenceLength = 800;

  buttonEvent = ButtonEvent::NONE;

  // detect change in the status of the button
  if(buttonEvent.isPressed != pressed)
  {
    buttonEvent = pressed?ButtonEvent::PRESSED:ButtonEvent::RELEASED;
    buttonEvent.isPressed = pressed;
  }

  // button is pressed not longer than 1s
  if(buttonEvent == ButtonEvent::RELEASED && getFrameInfo().getTime() < buttonEvent.timeOfLastEvent + 1000) {
    buttonEvent = ButtonEvent::CLICKED;

    if(buttonEvent.clicksInSequence > 0  && getFrameInfo().getTime() < buttonEvent.timeOfLastClick + maxSequenceLength) {
      // additional click inside same sequence occured
      buttonEvent.clicksInSequence += 1;
    } else {
      // start a click sequence with an initial click
      buttonEvent.clicksInSequence = 1;
    }
  }

  if(buttonEvent == ButtonEvent::CLICKED) {
//    std::cout << "click sequence with " << buttonEvent.clicksInSequence << " clicks" << std::endl;
    buttonEvent.timeOfLastClick = getFrameInfo().getTime();
  }

  if(!(buttonEvent == ButtonEvent::NONE)) {
    buttonEvent.timeOfLastEvent = getFrameInfo().getTime();
  }
}

<commit_msg>Chest button was far to easy to double press by incident<commit_after>/**
 * @file ButtonEventMonitor.cpp
 *
 * @author Heinrich Mellmann
 *
 */

#include "ButtonEventMonitor.h"

void ButtonEventMonitor::execute()
{
  update(getButtonState()[ButtonState::Chest], getButtonData().isPressed[ButtonData::Chest]);
  update(getButtonState()[ButtonState::LeftFoot],
    getButtonData().isPressed[ButtonData::LeftFootLeft] || getButtonData().isPressed[ButtonData::LeftFootRight]);
  update(getButtonState()[ButtonState::RightFoot],
    getButtonData().isPressed[ButtonData::RightFootLeft] || getButtonData().isPressed[ButtonData::RightFootRight]);
  update(getButtonState()[ButtonState::HeadMiddle],
    getButtonData().isPressed[ButtonData::HeadMiddle] || getButtonData().isPressed[ButtonData::HeadMiddle]);
}

void ButtonEventMonitor::update(ButtonEvent& buttonEvent, bool pressed)
{
  const unsigned int maxSequenceLength = 350;

  buttonEvent = ButtonEvent::NONE;

  // detect change in the status of the button
  if(buttonEvent.isPressed != pressed)
  {
    buttonEvent = pressed?ButtonEvent::PRESSED:ButtonEvent::RELEASED;
    buttonEvent.isPressed = pressed;
  }

  // button is pressed not longer than 1s
  if(buttonEvent == ButtonEvent::RELEASED && getFrameInfo().getTime() < buttonEvent.timeOfLastEvent + 1000) {
    buttonEvent = ButtonEvent::CLICKED;

    if(buttonEvent.clicksInSequence > 0  && getFrameInfo().getTime() < buttonEvent.timeOfLastClick + maxSequenceLength) {
      // additional click inside same sequence occured
      buttonEvent.clicksInSequence += 1;
    } else {
      // start a click sequence with an initial click
      buttonEvent.clicksInSequence = 1;
    }
  }

  if(buttonEvent == ButtonEvent::CLICKED) {
//    std::cout << "click sequence with " << buttonEvent.clicksInSequence << " clicks" << std::endl;
    buttonEvent.timeOfLastClick = getFrameInfo().getTime();
  }

  if(!(buttonEvent == ButtonEvent::NONE)) {
    buttonEvent.timeOfLastEvent = getFrameInfo().getTime();
  }
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014 Nicholas Corgan (n.corgan@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */

#include <fstream>
#include <iostream>
#include <string>

#include <pkmn/enums.hpp>
#include <pkmn/game_save.hpp>
#include <pkmn/paths.hpp>

#include "game_save_impl.hpp"
#include "game_save_gen1impl.hpp"
#include "game_save_gen3impl.hpp"
#include "game_save_gen4impl.hpp"
#include "game_save_gen5impl.hpp"
#include "library_bridge.hpp"
#include "conversions/trainer.hpp"

using namespace std;

namespace pkmn
{
    game_save::sptr game_save::make(string filename)
    {
        //Read save file and get size
        FILE* save_file;
        save_file = fopen(filename.c_str(), "rb");
        fseek(save_file, 0, SEEK_END);
        int size = ftell(save_file);
        rewind(save_file);
        char* buffer = (char*)malloc(size);
        int result = fread(buffer, 1, size, save_file);
        fclose(save_file);

        //Once size is determined, determine whether or not save is valid
        if(size > 0x80000)
        {
            //Check to see if PokeLib accepts it as a proper Gen 4 save
            pokelib_sptr pokelib_save(new PokeLib::Save(filename.c_str()));
            if(pokelib_save->parseRawSave())
            {
                free(buffer);
                return sptr(new game_save_gen4impl(pokelib_save));
            }
            else
            {
                //Check to see if PKMDS accepts it as a proper Gen 5 save
                free(buffer);
                pkmds_g5_sptr sav = pkmds_g5_sptr(new bw2sav_obj);
                read(filename.c_str(), sav.get());
                if(savisbw2(sav.get())) return sptr(new game_save_gen5impl(sav));
            }
        }
        else if(size > 0x40000)
        {
            //Check to see if PokeLib accepts it as a proper Gen 4 save
            pokelib_sptr pokelib_save(new PokeLib::Save(filename.c_str()));
            if(pokelib_save->parseRawSave())
            {
                free(buffer);
                return sptr(new game_save_gen4impl(pokelib_save));
            }
        }
        else if(size >= 0x20000)
        {
            //Check validity by manually using Pokehack checksum function on binary
            block binary_block;
            memcpy(&binary_block, buffer, 4096);
            unsigned short checksum_from_pokehack = pokehack_get_block_checksum(&binary_block);
            unsigned short checksum_from_binary = binary_block.footer.checksum;

            if(checksum_from_pokehack == checksum_from_binary)
            {
                //Check for Gen 3 game by searching for game code
                int game_type = (buffer[int(0xAC)] == 1) ? 1 : 0;

                pokehack_sptr parser(new SaveParser);
                if(!parser->load(filename.c_str(), game_type))
                {
                    return sptr(new game_save_gen3impl(parser, buffer));
                }
            }
        }
        else if(size >= (2 << 14))
        {
            rpokesav_gen1_sptr g1_sav(new rpokesav::gen1_save(filename));
            if(g1_sav->check()) return sptr(new game_save_gen1impl(g1_sav));
        }

        throw std::runtime_error("This is not a valid save file.");
    }

    unsigned int game_save_impl::get_game_id() const {return _game_id;}

    trainer::sptr game_save_impl::get_trainer() const {return _trainer;}

    bag::sptr game_save_impl::get_trainer_bag() const {return _trainer->get_bag();}

    void game_save_impl::get_trainer_party(pokemon_team_t& party) {_trainer->get_party(party);}

    void game_save_impl::set_trainer_party(pokemon_team_t& party) {_trainer->set_party(party);}

    pokemon_text game_save_impl::get_trainer_name() const {return _trainer->get_name();}

    void game_save_impl::set_trainer_name(pokemon_text trainer_name) {_trainer->set_name(trainer_name);}

} /* namespace pkmn */<commit_msg>Fixed game_save size checks<commit_after>/*
 * Copyright (c) 2013-2014 Nicholas Corgan (n.corgan@gmail.com)
 *
 * Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
 * or copy at http://opensource.org/licenses/MIT)
 */

#include <fstream>
#include <iostream>
#include <string>

#include <pkmn/enums.hpp>
#include <pkmn/game_save.hpp>
#include <pkmn/paths.hpp>

#include "game_save_impl.hpp"
#include "game_save_gen1impl.hpp"
#include "game_save_gen3impl.hpp"
#include "game_save_gen4impl.hpp"
#include "game_save_gen5impl.hpp"
#include "library_bridge.hpp"
#include "conversions/trainer.hpp"

using namespace std;

namespace pkmn
{
    game_save::sptr game_save::make(string filename)
    {
        //Read save file and get size
        FILE* save_file;
        save_file = fopen(filename.c_str(), "rb");
        fseek(save_file, 0, SEEK_END);
        int size = ftell(save_file);
        rewind(save_file);
        char* buffer = (char*)malloc(size);
        int result = fread(buffer, 1, size, save_file);
        fclose(save_file);

        //Once size is determined, determine whether or not save is valid
        if(size >= 0x80000)
        {
            //Check to see if PokeLib accepts it as a proper Gen 4 save
            pokelib_sptr pokelib_save(new PokeLib::Save(filename.c_str()));
            if(pokelib_save->parseRawSave())
            {
                free(buffer);
                return sptr(new game_save_gen4impl(pokelib_save));
            }
            else
            {
                //Check to see if PKMDS accepts it as a proper Gen 5 save
                free(buffer);
                pkmds_g5_sptr sav = pkmds_g5_sptr(new bw2sav_obj);
                read(filename.c_str(), sav.get());
                if(savisbw2(sav.get())) return sptr(new game_save_gen5impl(sav));
            }
        }
        else if(size >= 0x40000)
        {
            //Check to see if PokeLib accepts it as a proper Gen 4 save
            pokelib_sptr pokelib_save(new PokeLib::Save(filename.c_str()));
            if(pokelib_save->parseRawSave())
            {
                free(buffer);
                return sptr(new game_save_gen4impl(pokelib_save));
            }
        }
        else if(size >= 0x20000)
        {
            //Check validity by manually using Pokehack checksum function on binary
            block binary_block;
            memcpy(&binary_block, buffer, 4096);
            unsigned short checksum_from_pokehack = pokehack_get_block_checksum(&binary_block);
            unsigned short checksum_from_binary = binary_block.footer.checksum;

            if(checksum_from_pokehack == checksum_from_binary)
            {
                //Check for Gen 3 game by searching for game code
                int game_type = (buffer[int(0xAC)] == 1) ? 1 : 0;

                pokehack_sptr parser(new SaveParser);
                if(!parser->load(filename.c_str(), game_type))
                {
                    return sptr(new game_save_gen3impl(parser, buffer));
                }
            }
        }
        else if(size >= (2 << 14))
        {
            rpokesav_gen1_sptr g1_sav(new rpokesav::gen1_save(filename));
            if(g1_sav->check()) return sptr(new game_save_gen1impl(g1_sav));
        }

        throw std::runtime_error("This is not a valid save file.");
    }

    unsigned int game_save_impl::get_game_id() const {return _game_id;}

    trainer::sptr game_save_impl::get_trainer() const {return _trainer;}

    bag::sptr game_save_impl::get_trainer_bag() const {return _trainer->get_bag();}

    void game_save_impl::get_trainer_party(pokemon_team_t& party) {_trainer->get_party(party);}

    void game_save_impl::set_trainer_party(pokemon_team_t& party) {_trainer->set_party(party);}

    pokemon_text game_save_impl::get_trainer_name() const {return _trainer->get_name();}

    void game_save_impl::set_trainer_name(pokemon_text trainer_name) {_trainer->set_name(trainer_name);}

} /* namespace pkmn */<|endoftext|>