<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3073
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 2052971 by chui@ocl-promo-incrementor on 2020/01/07 03:00:14<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3074
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2122
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1271928 by johtaylo@johtaylo-JTBUILDER03-increment on 2016/05/23 03:00:11<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2123
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>/** \addtogroup examples
  * @{
  * \defgroup algebraic_multigrid algebraic_multigrid
  * @{
  * \brief Benchmark for smoothed algebraic multgrid
  */
#include <ctf.hpp>
using namespace CTF;

void smooth_jacobi(Matrix<> & A, Vector<> & x, Vector <> & b, int nsmooth){
  Timer jacobi("jacobi");
  Timer jacobi_spmv("jacobi_spmv");

  jacobi.start();
  Vector<> d(x.len, *x.wrld);
  d["i"] = A["ii"];
  Transform<>([](double & d){ d= fabs(d) > 0.0 ? 1./d : 0.0; })(d["i"]);
  Matrix<> R(A);
  R["ii"] = 0.0;

  //20 iterations of Jacobi, should probably be a parameter or some convergence check instead
  for (int i=0; i<nsmooth; i++){
    jacobi_spmv.start();
    x["i"] = -1.0*R["ij"]*x["j"];
    jacobi_spmv.stop();
    x["i"] += b["i"];
    x["i"] *= d["i"];
  }
  jacobi.stop();
}

void vcycle(Matrix<> & A, Vector<> & x, Vector<> & b, Matrix<> * T, int64_t n, int nlevel, int nsmooth){
  //do smoothing using Jacobi
  char tlvl_name[] = {'l','v','l',(char)('0'+nlevel),'\0'};
  Timer tlvl(tlvl_name);
  tlvl.start();
  Vector<> r(b);
/*  r["i"] -= A["ij"]*x["j"];
  double rnorm0 = r.norm2();*/
  smooth_jacobi(A,x,b,nsmooth);
//  r["i"] = b["i"];
  r["i"] -= A["ij"]*x["j"];
  double rnorm = r.norm2();
  if (A.wrld->rank == 0) printf("At level %d, residual norm was %1.2E after initial smooth\n",nlevel,rnorm);
  if (nlevel == 0){
    /*if (A.wrld->rank == 0) printf("At level %d (coarsest level), residual norm was %1.2E initially\n",nlevel,rnorm0);
    if (A.wrld->rank == 0) printf("At level %d (coarsest level), residual norm was %1.2E after smooth\n",nlevel,rnorm);*/
    return;
  }
  int64_t m = T[0].lens[1];

  //smooth the restriction/interpolation operator P = (I-omega*diag(A)^{-1}*A)T
  Timer rstr("restriction");
  rstr.start();
  Matrix<> P(T[0].lens[0], T[0].lens[1], SP, *T[0].wrld);
  Matrix<> D(n,n,SP,*A.wrld);
  D["ii"] = A["ii"];
  double omega=.1;
  Transform<>([=](double & d){ d= omega/d; })(D["ii"]);
  Timer trip("triple_matrix_product_to_form_T");
  trip.start();
  P["ik"] = A["ij"]*T[0]["jk"];
  P["ik"] =  D["il"]*P["lk"];
  trip.stop();
  P["ij"] += T[0]["ij"];

  //restrict residual vector
  Vector<> PTr(m, *x.wrld);
  PTr["i"] = P["ji"]*r["j"];

  //coarses initial guess should be zeros
  Vector<> zx(m, *b.wrld);

  int atr = 0;
  if (A.is_sparse){
    atr = atr | SP;
  }
  Matrix<> AP(n, m, atr, *x.wrld);
  Matrix<> PTAP(m, m, atr, *x.wrld);

  Timer trip2("triple_matrix_product_to_form_PTAP");
  trip2.start();
  //restrict A via triple matrix product, should probably be done outside v-cycle
  AP["lj"] = A["lk"]*P["kj"];
  PTAP["ij"] = P["li"]*AP["lj"];

  trip2.stop();
  rstr.stop();
  tlvl.stop();
  //recurse into coarser level
  vcycle(PTAP, zx, PTr, T+1, m, nlevel-1, nsmooth);
  tlvl.start();

  //interpolate solution to residual equation at coraser level back
  x["i"] += P["ij"]*zx["j"];

  //smooth new solution
  /*r["i"] = b["i"];
  r["i"] -= A["ij"]*x["j"];
  double rnorm2 = r.norm2();*/
  smooth_jacobi(A,x,b,nsmooth);
  tlvl.stop();
  /*r["i"] = b["i"];
  r["i"] -= A["ij"]*x["j"];
  double rnorm3 = r.norm2();*/
  //if (A.wrld->rank == 0) printf("At level %d, residual norm was %1.2E initially\n",nlevel,rnorm0);
//  if (A.wrld->rank == 0) printf("At level %d, residual norm was %1.2E after coarse recursion\n",nlevel,rnorm2);
//  if (A.wrld->rank == 0) printf("At level %d, residual norm was %1.2E after final smooth\n",nlevel,rnorm3);
}

/**
 * \brief computes Multigrid for a 3D regular discretization
 */
int algebraic_multigrid(int64_t n,
                        double  sp_frac,
                        int     nlvl,
                        int     ndiv,
                        int     nsmooth,
                        int     decay_exp,
                        World & dw){
  Timer tct("initialization");
  tct.start();
  Vector<> x(n, dw);
  Vector<> b(n, dw);
  x.fill_random(0.0, 1.0);
  b.fill_random(0.0, 1.0);
  Matrix<> A(n, n, SP, dw);
  srand48(dw.rank*12);
  A.fill_sp_random(0.0, 1.0, sp_frac);

  if (dw.rank == 0){
    printf("Generated matrix with dimension %1.2E and %1.2E nonzeros\n", (double)n, (double)A.nnz_tot);
    fflush(stdout);
  }

  A["ij"] += A["ji"];

  double pn = pow(n,1./6);
  A["ii"] += pn;

  Matrix<std::pair<double, int64_t>> B(n,n,SP,dw,Set<std::pair<double, int64_t>>());

  int64_t * inds;
  double * vals;
  std::pair<double,int64_t> * new_vals;
  int64_t nvals;
  A.read_local_nnz(&nvals, &inds, &vals);

  new_vals = (std::pair<double,int64_t>*)malloc(sizeof(std::pair<double,int64_t>)*nvals);

  for (int64_t i=0; i<nvals; i++){
    new_vals[i] = std::pair<double,int64_t>(vals[i],abs((inds[i]%n) - (inds[i]/n)));
  }

  B.write(nvals,inds,new_vals);
  free(vals);
  free(new_vals);
  free(inds);

  int64_t curootn = (int64_t)(pow((double)n,1./3.)+.001);
  Transform< std::pair<double,int64_t> >([=](std::pair<double,int64_t> & d){
    int64_t x =  d.second % curootn;
    int64_t y = (d.second / curootn) % curootn;
    int64_t z =  d.second / curootn  / curootn;
    if (x+y+z > 0)
      d.first = d.first/pow((double)(x+y+z),decay_exp/2.);
    }
  )(B["ij"]);

  A["ij"] = Function< std::pair<double,int64_t>, double >([](std::pair<double,int64_t> p){ return p.first; })(B["ij"]);

  Vector<> r(b);
  r["i"] -= A["ij"]*x["j"];
  double err = r.norm2();

  Matrix<> * T = new Matrix<>[nlvl];
  int64_t m=n;
  for (int i=0; i<nlvl; i++){
    int64_t m2 = m/ndiv;
    T[i] = Matrix<>(m, m2, SP, dw);
    int64_t mmy = m2/dw.np;
    if (dw.rank < m2%dw.np) mmy++;
    Pair<> * pairs = (Pair<>*)malloc(sizeof(Pair<>)*mmy*ndiv);
    int64_t nel = 0;
    for (int64_t j=dw.rank; j<m2; j+=dw.np){
      for (int k=0; k<ndiv; k++){
        pairs[nel] = Pair<>(j*m+j*ndiv+k, 1.0);
        nel++;
      }
    }
    T[i].write(nel, pairs);
    free(pairs);
    m = m2;
  }
  tct.stop();

  Vector<> x2(x);

  Timer_epoch vc("vcycle");
  vc.begin();
  double st_time = MPI_Wtime();
  vcycle(A, x, b, T, n, nlvl, nsmooth);
  double vtime = MPI_Wtime()-st_time;
  vc.end();

  Vector<> r2(x);
  smooth_jacobi(A,x2,b,2*nsmooth);
  r2["i"] = b["i"];
  r2["i"] -= A["ij"]*x2["j"];
  double rnorm_alt = r2.norm2();
  if (A.wrld->rank == 0) printf("Residual norm would have been %1.2E if we skipped the coarsening\n",rnorm_alt);

  delete [] T;

  r["i"]  = b["i"];
  r["i"] -= A["ij"]*x["j"];
  double err2 = r.norm2();

  bool pass = err2 < err;

  if (dw.rank == 0){
#ifndef TEST_SUITE
    printf("Algebraic multigrid with n %ld sp_frac %1.2E nlvl %d ndiv %d nsmooth %d decay_exp %d took %lf seconds, original err = %E, new err = %E\n",n,sp_frac,nlvl,ndiv,nsmooth,decay_exp,vtime,err,err2);
#endif
    if (pass)
      printf("{ algebraic multigrid method } passed \n");
    else
      printf("{ algebraic multigrid method } failed \n");
  }
  return pass;
}

#ifndef TEST_SUITE
char* getCmdOption(char ** begin,
                   char ** end,
                   const   std::string & option){
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end){
    return *itr;
  }
  return 0;
}

int main(int argc, char ** argv){
  int rank, np, pass, nlvl, ndiv, decay_exp, nsmooth;
  int64_t n;
  double sp_frac;
  int const in_num = argc;
  char ** input_str = argv;

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &np);

  if (getCmdOption(input_str, input_str+in_num, "-n")){
    n = atoi(getCmdOption(input_str, input_str+in_num, "-n"));
    if (n < 0) n = 16;
  } else n = 16;

  if (getCmdOption(input_str, input_str+in_num, "-nlvl")){
    nlvl = atoi(getCmdOption(input_str, input_str+in_num, "-nlvl"));
    if (nlvl < 0) nlvl = 3;
  } else nlvl = 3;

  if (getCmdOption(input_str, input_str+in_num, "-ndiv")){
    ndiv = atoi(getCmdOption(input_str, input_str+in_num, "-ndiv"));
    if (ndiv < 0) ndiv = 2;
  } else ndiv = 2;

  if (getCmdOption(input_str, input_str+in_num, "-nsmooth")){
    nsmooth = atoi(getCmdOption(input_str, input_str+in_num, "-nsmooth"));
    if (nsmooth < 0) nsmooth = 3;
  } else nsmooth = 3;

  if (getCmdOption(input_str, input_str+in_num, "-decay_exp")){
    decay_exp = atoi(getCmdOption(input_str, input_str+in_num, "-decay_exp"));
    if (decay_exp < 0) decay_exp = 3;
  } else decay_exp = 3;

  if (getCmdOption(input_str, input_str+in_num, "-sp_frac")){
    sp_frac = atof(getCmdOption(input_str, input_str+in_num, "-sp_frac"));
    if (sp_frac < 0) sp_frac = .01;
  } else sp_frac = .01;

  int64_t tot_ndiv=1;
  for (int i=0; i<nlvl; i++){ tot_ndiv *= ndiv; }

  assert(n%tot_ndiv == 0);

  {
    World dw(argc, argv);

    if (rank == 0){
      printf("Running algebraic smoothed multigrid method with %d levels with divisor %d in V-cycle, matrix dimension %ld, %d smooth iterations, decayed based on 3D indexing with decay exponent of %d\n",nlvl,ndiv,n,nsmooth, decay_exp);
    }
    pass = algebraic_multigrid(n, sp_frac, nlvl, ndiv, nsmooth, decay_exp, dw);
    assert(pass);
  }

  MPI_Finalize();
  return 0;
}
/**
 * @}
 * @}
 */

#endif
<commit_msg>split up multigrid into setup and vcycle and added skeleton for poisson<commit_after>/** \addtogroup examples
  * @{
  * \defgroup algebraic_multigrid algebraic_multigrid
  * @{
  * \brief Benchmark for smoothed algebraic multgrid
  */
#include <ctf.hpp>
using namespace CTF;

void smooth_jacobi(Matrix<> & A, Vector<> & x, Vector <> & b, int nsm){
  Timer jacobi("jacobi");
  Timer jacobi_spmv("jacobi_spmv");

  jacobi.start();
  Vector<> d(x.len, *x.wrld);
  d["i"] = A["ii"];
  Transform<>([](double & d){ d= fabs(d) > 0.0 ? 1./d : 0.0; })(d["i"]);
  Matrix<> R(A);
  R["ii"] = 0.0;

  //20 iterations of Jacobi, should probably be a parameter or some convergence check instead
  for (int i=0; i<nsm; i++){
    jacobi_spmv.start();
    x["i"] = -1.0*R["ij"]*x["j"];
    jacobi_spmv.stop();
    x["i"] += b["i"];
    x["i"] *= d["i"];
  }
  jacobi.stop();
}

void setup(Matrix<> & A, Matrix<> * T, int n, int nlevel, Matrix<> * P, Matrix<> * PTAP){
  if (nlevel == 0) return;
  int64_t m = T[0].lens[1];
  P[0] = Matrix<>(n, m, SP, *T[0].wrld);
  Matrix<> D(n,n,SP,*A.wrld);
  D["ii"] = A["ii"];
  double omega=.1;
  Transform<>([=](double & d){ d= omega/d; })(D["ii"]);
  Timer trip("triple_matrix_product_to_form_T");
  trip.start();
  P[0]["ik"] = A["ij"]*T[0]["jk"];
  P[0]["ik"] = D["il"]*P[0]["lk"];
  trip.stop();
  P[0]["ij"] += T[0]["ij"];

  int atr = 0;
  if (A.is_sparse){
    atr = atr | SP;
  }
  Matrix<> AP(n, m, atr, *A.wrld);
  PTAP[0] = Matrix<>(m, m, atr, *A.wrld);

  Timer trip2("triple_matrix_product_to_form_PTAP");
  trip2.start();
  //restrict A via triple matrix product, should probably be done outside v-cycle
  AP["lj"] = A["lk"]*P[0]["kj"];
  PTAP[0]["ij"] = P[0]["li"]*AP["lj"];

  trip2.stop();
  setup(PTAP[0], T+1, m, nlevel-1, P+1, PTAP+1);

}

void vcycle(Matrix<> & A, Vector<> & x, Vector<> & b, Matrix<> * P, Matrix<> * PTAP, int64_t n, int nlevel, int * nsm){
  //do smoothing using Jacobi
  char tlvl_name[] = {'l','v','l',(char)('0'+nlevel),'\0'};
  Timer tlvl(tlvl_name);
  tlvl.start();
  Vector<> r(b);
/*  r["i"] -= A["ij"]*x["j"];
  double rnorm0 = r.norm2();*/
  smooth_jacobi(A,x,b,nsm[0]);
//  r["i"] = b["i"];
  r["i"] -= A["ij"]*x["j"];
  double rnorm = r.norm2();
  if (x.wrld->rank == 0) printf("At level %d, residual norm was %1.2E after initial smooth\n",nlevel,rnorm);
  if (nlevel == 0){
    /*if (A.wrld->rank == 0) printf("At level %d (coarsest level), residual norm was %1.2E initially\n",nlevel,rnorm0);
    if (A.wrld->rank == 0) printf("At level %d (coarsest level), residual norm was %1.2E after smooth\n",nlevel,rnorm);*/
    return;
  }
  int64_t m = P[0].lens[1];

  //smooth the restriction/interpolation operator P = (I-omega*diag(A)^{-1}*A)T
  Timer rstr("restriction");
  rstr.start();

  //restrict residual vector
  Vector<> PTr(m, *x.wrld);
  PTr["i"] = P[0]["ji"]*r["j"];

  //coarses initial guess should be zeros
  Vector<> zx(m, *b.wrld);
  rstr.stop();
  tlvl.stop();
  //recurse into coarser level
  vcycle(PTAP[0], zx, PTr, P+1, PTAP+1, m, nlevel-1, nsm+1);
  tlvl.start();

  //interpolate solution to residual equation at coraser level back
  x["i"] += P[0]["ij"]*zx["j"];

  //smooth new solution
  /*r["i"] = b["i"];
  r["i"] -= A["ij"]*x["j"];
  double rnorm2 = r.norm2();*/
  smooth_jacobi(A,x,b,nsm[0]);
  tlvl.stop();
  /*r["i"] = b["i"];
  r["i"] -= A["ij"]*x["j"];
  double rnorm3 = r.norm2();*/
  //if (A.wrld->rank == 0) printf("At level %d, residual norm was %1.2E initially\n",nlevel,rnorm0);
//  if (A.wrld->rank == 0) printf("At level %d, residual norm was %1.2E after coarse recursion\n",nlevel,rnorm2);
//  if (A.wrld->rank == 0) printf("At level %d, residual norm was %1.2E after final smooth\n",nlevel,rnorm3);
}

/**
 * \brief computes Multigrid for a 3D regular discretization
 */
int test_alg_multigrid(int64_t    n,
                       int        nlvl,
                       int *      nsm,
                       Matrix<> & A,
                       Matrix<> * P,
                       Matrix<> * PTAP){

  Vector<> x(n, *A.wrld);
  Vector<> b(n, *A.wrld);
  x.fill_random(0.0, 1.0);
  b.fill_random(0.0, 1.0);
  Vector<> x2(x);

  Timer_epoch vc("vcycle");
  vc.begin();
  double st_time = MPI_Wtime();
  vcycle(A, x, b, P, PTAP, n, nlvl, nsm);
  double vtime = MPI_Wtime()-st_time;
  vc.end();

  Vector<> r2(x);
  smooth_jacobi(A,x2,b,2*nsm[0]);
  r2["i"] = b["i"];
  r2["i"] -= A["ij"]*x2["j"];
  double rnorm_alt = r2.norm2();

  Vector<> r(x);
  r["i"]  = b["i"];
  r["i"] -= A["ij"]*x["j"];
  double rnorm = r.norm2();

  bool pass = rnorm < rnorm_alt;

  if (A.wrld->rank == 0){
#ifndef TEST_SUITE
    printf("Algebraic multigrid with n %ld nlvl %d took %lf seconds, fine-grid only err = %E, multigrid err = %E\n",n,nlvl,vtime,rnorm_alt,rnorm);
#endif
    if (pass)
      printf("{ algebraic multigrid method } passed \n");
    else
      printf("{ algebraic multigrid method } failed \n");
  }
  return pass;

}

void setup_unstructured(int64_t     n,
                        int         nlvl,
                        double      sp_frac,
                        int         ndiv,
                        int         decay_exp,
                        Matrix<>  & A,
                        Matrix<> *& P,
                        Matrix<> *& PTAP,
                        World & dw){
  Timer tct("initialization");
  tct.start();
  A = Matrix<>(n, n, SP, dw);
  srand48(dw.rank*12);
  A.fill_sp_random(0.0, 1.0, sp_frac);

  A["ij"] += A["ji"];
  double pn = pow(n,1./6);
  A["ii"] += pn;

  if (dw.rank == 0){
    printf("Generated matrix with dimension %1.2E and %1.2E nonzeros\n", (double)n, (double)A.nnz_tot);
    fflush(stdout);
  }

  Matrix<std::pair<double, int64_t>> B(n,n,SP,dw,Set<std::pair<double, int64_t>>());

  int64_t * inds;
  double * vals;
  std::pair<double,int64_t> * new_vals;
  int64_t nvals;
  A.read_local_nnz(&nvals, &inds, &vals);

  new_vals = (std::pair<double,int64_t>*)malloc(sizeof(std::pair<double,int64_t>)*nvals);

  for (int64_t i=0; i<nvals; i++){
    new_vals[i] = std::pair<double,int64_t>(vals[i],abs((inds[i]%n) - (inds[i]/n)));
  }

  B.write(nvals,inds,new_vals);
  free(vals);
  free(new_vals);
  free(inds);

  int64_t curootn = (int64_t)(pow((double)n,1./3.)+.001);
  Transform< std::pair<double,int64_t> >([=](std::pair<double,int64_t> & d){
    int64_t x =  d.second % curootn;
    int64_t y = (d.second / curootn) % curootn;
    int64_t z =  d.second / curootn  / curootn;
    if (x+y+z > 0)
      d.first = d.first/pow((double)(x+y+z),decay_exp/2.);
    }
  )(B["ij"]);

  A["ij"] = Function< std::pair<double,int64_t>, double >([](std::pair<double,int64_t> p){ return p.first; })(B["ij"]);

  Matrix<> * T = new Matrix<>[nlvl];
  int64_t m=n;
  for (int i=0; i<nlvl; i++){
    int64_t m2 = m/ndiv;
    T[i] = Matrix<>(m, m2, SP, dw);
    int64_t mmy = m2/dw.np;
    if (dw.rank < m2%dw.np) mmy++;
    Pair<> * pairs = (Pair<>*)malloc(sizeof(Pair<>)*mmy*ndiv);
    int64_t nel = 0;
    for (int64_t j=dw.rank; j<m2; j+=dw.np){
      for (int k=0; k<ndiv; k++){
        pairs[nel] = Pair<>(j*m+j*ndiv+k, 1.0);
        nel++;
      }
    }
    T[i].write(nel, pairs);
    free(pairs);
    m = m2;
  }
  tct.stop();

  P = new Matrix<>[nlvl];
  PTAP = new Matrix<>[nlvl];
  setup(A, T, n, nlvl, P, PTAP);
}

void setup_3d_Poisson(int64_t     n,
                      int         nlvl,
                      int         ndiv,
                      Matrix<> ** A,
                      Matrix<> ** P,
                      World & dw){

}

#ifndef TEST_SUITE
char* getCmdOption(char ** begin,
                   char ** end,
                   const   std::string & option){
  char ** itr = std::find(begin, end, option);
  if (itr != end && ++itr != end){
    return *itr;
  }
  return 0;
}

int main(int argc, char ** argv){
  int rank, np, pass, nlvl, ndiv, decay_exp, nsmooth;
  int * nsm;
  int64_t n;
  double sp_frac;
  int const in_num = argc;
  char ** input_str = argv;

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &np);

  if (getCmdOption(input_str, input_str+in_num, "-n")){
    n = atoi(getCmdOption(input_str, input_str+in_num, "-n"));
    if (n < 0) n = 16;
  } else n = 16;

  if (getCmdOption(input_str, input_str+in_num, "-nlvl")){
    nlvl = atoi(getCmdOption(input_str, input_str+in_num, "-nlvl"));
    if (nlvl < 0) nlvl = 3;
  } else nlvl = 3;

  if (getCmdOption(input_str, input_str+in_num, "-ndiv")){
    ndiv = atoi(getCmdOption(input_str, input_str+in_num, "-ndiv"));
    if (ndiv < 0) ndiv = 2;
  } else ndiv = 2;

  if (getCmdOption(input_str, input_str+in_num, "-nsmooth")){
    nsmooth = atoi(getCmdOption(input_str, input_str+in_num, "-nsmooth"));
    if (nsmooth < 0) nsmooth = 3;
  } else nsmooth = 3;

  nsm = (int*)malloc(sizeof(int)*nlvl);
  std::fill(nsm, nsm+nlvl, nsmooth);

  char str[] = {'-','n','s','m','0','\0'};
  for (int i=0; i<nlvl; i++){
    str[4] = '0'+i;
    if (getCmdOption(input_str, input_str+in_num, str)){
      int insm = atoi(getCmdOption(input_str, input_str+in_num, str));
      if (insm > 0) nsm[i] = insm;
    }
  }

  if (getCmdOption(input_str, input_str+in_num, "-decay_exp")){
    decay_exp = atoi(getCmdOption(input_str, input_str+in_num, "-decay_exp"));
    if (decay_exp < 0) decay_exp = 3;
  } else decay_exp = 3;

  if (getCmdOption(input_str, input_str+in_num, "-sp_frac")){
    sp_frac = atof(getCmdOption(input_str, input_str+in_num, "-sp_frac"));
    if (sp_frac < 0) sp_frac = .01;
  } else sp_frac = .01;

  int64_t tot_ndiv=1;
  for (int i=0; i<nlvl; i++){ tot_ndiv *= ndiv; }

  assert(n%tot_ndiv == 0);

  nlvl--;
  {
    World dw(argc, argv);

    if (rank == 0){
      printf("Running algebraic smoothed multigrid method with %d levels with divisor %d in V-cycle, matrix dimension %ld, %d smooth iterations, decayed based on 3D indexing with decay exponent of %d\n",nlvl,ndiv,n,nsmooth, decay_exp);
    }
    Matrix<> A;
    Matrix<> * P;
    Matrix<> * PTAP;
    setup_unstructured(n, nlvl, sp_frac, ndiv, decay_exp, A, P, PTAP, dw);
    pass = test_alg_multigrid(n, nlvl, nsm, A, P, PTAP);
    assert(pass);
  }

  MPI_Finalize();
  return 0;
}
/**
 * @}
 * @}
 */

#endif
<|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.

#include "chrome/browser/views/first_run_bubble.h"

#include "base/win_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/options_window.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/views/standard_layout.h"
#include "chrome/common/l10n_util.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/views/event.h"
#include "chrome/views/controls/button/native_button.h"
#include "chrome/views/controls/label.h"
#include "chrome/views/focus/focus_manager.h"
#include "chrome/views/window/window.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

namespace {

// How much extra padding to put around our content over what the InfoBubble
// provides.
static const int kBubblePadding = 4;

std::wstring GetDefaultSearchEngineName(Profile* profile) {
  if (!profile) {
    NOTREACHED();
    return std::wstring();
  }
  const TemplateURL* const default_provider =
      profile->GetTemplateURLModel()->GetDefaultSearchProvider();
  if (!default_provider) {
    // TODO(cpu): bug 1187517. It is possible to have no default provider.
    // returning an empty string is a stopgap measure for the crash
    // http://code.google.com/p/chromium/issues/detail?id=2573
    return std::wstring();
  }
  return default_provider->short_name();
}

}  // namespace

// Implements the client view inside the first run bubble. It is kind of a
// dialog-ish view, but is not a true dialog.
class FirstRunBubbleView : public views::View,
                           public views::ButtonListener,
                           public views::FocusChangeListener {
 public:
  FirstRunBubbleView(FirstRunBubble* bubble_window, Profile* profile)
      : bubble_window_(bubble_window),
        label1_(NULL),
        label2_(NULL),
        label3_(NULL),
        keep_button_(NULL),
        change_button_(NULL) {
    ChromeFont& font =
        ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);

    label1_ = new views::Label(l10n_util::GetString(IDS_FR_BUBBLE_TITLE));
    label1_->SetFont(font.DeriveFont(3, ChromeFont::BOLD));
    label1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    AddChildView(label1_);

    gfx::Size ps = GetPreferredSize();

    label2_ = new views::Label(l10n_util::GetString(IDS_FR_BUBBLE_SUBTEXT));
    label2_->SetMultiLine(true);
    label2_->SetFont(font);
    label2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    label2_->SizeToFit(ps.width() - kBubblePadding * 2);
    AddChildView(label2_);

    std::wstring question_str
        = l10n_util::GetStringF(IDS_FR_BUBBLE_QUESTION,
                                GetDefaultSearchEngineName(profile));
    label3_ = new views::Label(question_str);
    label3_->SetMultiLine(true);
    label3_->SetFont(font);
    label3_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    label3_->SizeToFit(ps.width() - kBubblePadding * 2);
    AddChildView(label3_);

    std::wstring keep_str =
        l10n_util::GetStringF(IDS_FR_BUBBLE_OK,
                              GetDefaultSearchEngineName(profile));
    keep_button_ = new views::NativeButton(this, keep_str);
    keep_button_->SetIsDefault(true);
    AddChildView(keep_button_);

    std::wstring change_str = l10n_util::GetString(IDS_FR_BUBBLE_CHANGE);
    change_button_ = new views::NativeButton(this, change_str);
    AddChildView(change_button_);
  }

  // Overridden from ButtonListener.
  virtual void ButtonPressed(views::Button* sender) {
    bubble_window_->Close();
    if (change_button_ == sender) {
      Browser* browser = BrowserList::GetLastActive();
      if (browser) {
        ShowOptionsWindow(OPTIONS_PAGE_GENERAL, OPTIONS_GROUP_DEFAULT_SEARCH,
                          browser->profile());
      }
    }
  }

  // Overridden from views::View.
  virtual void Layout() {
    gfx::Size canvas = GetPreferredSize();

    // The multiline business that follows is dirty hacks to get around
    // bug 1325257.
    label1_->SetMultiLine(false);
    gfx::Size pref_size = label1_->GetPreferredSize();
    label1_->SetMultiLine(true);
    label1_->SizeToFit(canvas.width() - kBubblePadding * 2);
    label1_->SetBounds(kBubblePadding, kBubblePadding,
                       canvas.width() - kBubblePadding * 2,
                       pref_size.height());

    int next_v_space = label1_->y() + pref_size.height() +
                       kRelatedControlSmallVerticalSpacing;

    pref_size = label2_->GetPreferredSize();
    label2_->SetBounds(kBubblePadding, next_v_space,
                       canvas.width() - kBubblePadding * 2,
                       pref_size.height());

    next_v_space = label2_->y() + label2_->height() +
                   kPanelSubVerticalSpacing;

    pref_size = label3_->GetPreferredSize();
    label3_->SetBounds(kBubblePadding, next_v_space,
                       canvas.width() - kBubblePadding * 2,
                       pref_size.height());

    pref_size = change_button_->GetPreferredSize();
    change_button_->SetBounds(
        canvas.width() - pref_size.width() - kBubblePadding,
        canvas.height() - pref_size.height() - kButtonVEdgeMargin,
        pref_size.width(), pref_size.height());

    pref_size = keep_button_->GetPreferredSize();
    keep_button_->SetBounds(change_button_->x() - pref_size.width() -
                            kRelatedButtonHSpacing, change_button_->y(),
                            pref_size.width(), pref_size.height());
  }

  virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child) {
    if (keep_button_)
      keep_button_->RequestFocus();
  }

  // Overridden from views::View.
  virtual gfx::Size GetPreferredSize() {
    return gfx::Size(views::Window::GetLocalizedContentsSize(
        IDS_FIRSTRUNBUBBLE_DIALOG_WIDTH_CHARS,
        IDS_FIRSTRUNBUBBLE_DIALOG_HEIGHT_LINES));
  }

  virtual void FocusWillChange(View* focused_before, View* focused_now) {
    if (focused_before && focused_before->GetClassName() ==
                          views::NativeButton::kViewClassName) {
      views::NativeButton* before =
          static_cast<views::NativeButton*>(focused_before);
      before->SetIsDefault(false);
    }
    if (focused_now && focused_now->GetClassName() ==
                       views::NativeButton::kViewClassName) {
      views::NativeButton* after =
          static_cast<views::NativeButton*>(focused_now);
      after->SetIsDefault(true);
    }
  }

 private:
  FirstRunBubble* bubble_window_;
  views::Label* label1_;
  views::Label* label2_;
  views::Label* label3_;
  views::NativeButton* change_button_;
  views::NativeButton* keep_button_;

  DISALLOW_COPY_AND_ASSIGN(FirstRunBubbleView);
};

// Keep the bubble around for kLingerTime milliseconds, to prevent accidental
// closure.
static const int kLingerTime = 1000;

void FirstRunBubble::OnActivate(UINT action, BOOL minimized, HWND window) {
  // We might get re-enabled right before we are closed (sequence is: we get
  // deactivated, we call close, before we are actually closed we get
  // reactivated). Don't do the disabling of the parent in such cases.
  if (action == WA_ACTIVE && !has_been_activated_) {
    has_been_activated_ = true;

    // Disable the browser to prevent accidental rapid clicks from closing the
    // bubble.
    ::EnableWindow(GetParent(), false);

    MessageLoop::current()->PostDelayedTask(FROM_HERE,
        enable_window_method_factory_.NewRunnableMethod(
            &FirstRunBubble::EnableParent),
        kLingerTime);
  }
  InfoBubble::OnActivate(action, minimized, window);
}

void FirstRunBubble::InfoBubbleClosing(InfoBubble* info_bubble,
                                       bool closed_by_escape) {
  // Make sure our parent window is re-enabled.
  if (!IsWindowEnabled(GetParent()))
    ::EnableWindow(GetParent(), true);
  enable_window_method_factory_.RevokeAll();
  views::FocusManager* focus_manager =
      views::FocusManager::GetFocusManager(GetNativeView());
  focus_manager->RemoveFocusChangeListener(view_);
}

// static
FirstRunBubble* FirstRunBubble::Show(Profile* profile, HWND parent_hwnd,
                                     const gfx::Rect& position_relative_to) {
  FirstRunBubble* window = new FirstRunBubble();
  FirstRunBubbleView* view = new FirstRunBubbleView(window, profile);
  window->SetDelegate(window);
  window->set_view(view);
  window->Init(parent_hwnd, position_relative_to, view);
  window->ShowWindow(SW_SHOW);
  views::FocusManager* focus_manager =
      views::FocusManager::GetFocusManager(window->GetNativeView());
  focus_manager->AddFocusChangeListener(view);
  return window;
}

void FirstRunBubble::EnableParent() {
  ::EnableWindow(GetParent(), true);
}
<commit_msg>The NativeButton HWND would not be created yet when we were setting the initial focus in the first run bubble view. This CL makes sure to set the focus when everything is set-up.<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.

#include "chrome/browser/views/first_run_bubble.h"

#include "base/win_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/options_window.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/views/standard_layout.h"
#include "chrome/common/l10n_util.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/views/event.h"
#include "chrome/views/controls/button/native_button.h"
#include "chrome/views/controls/label.h"
#include "chrome/views/focus/focus_manager.h"
#include "chrome/views/window/window.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"

namespace {

// How much extra padding to put around our content over what the InfoBubble
// provides.
static const int kBubblePadding = 4;

std::wstring GetDefaultSearchEngineName(Profile* profile) {
  if (!profile) {
    NOTREACHED();
    return std::wstring();
  }
  const TemplateURL* const default_provider =
      profile->GetTemplateURLModel()->GetDefaultSearchProvider();
  if (!default_provider) {
    // TODO(cpu): bug 1187517. It is possible to have no default provider.
    // returning an empty string is a stopgap measure for the crash
    // http://code.google.com/p/chromium/issues/detail?id=2573
    return std::wstring();
  }
  return default_provider->short_name();
}

}  // namespace

// Implements the client view inside the first run bubble. It is kind of a
// dialog-ish view, but is not a true dialog.
class FirstRunBubbleView : public views::View,
                           public views::ButtonListener,
                           public views::FocusChangeListener {
 public:
  FirstRunBubbleView(FirstRunBubble* bubble_window, Profile* profile)
      : bubble_window_(bubble_window),
        label1_(NULL),
        label2_(NULL),
        label3_(NULL),
        keep_button_(NULL),
        change_button_(NULL) {
    ChromeFont& font =
        ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);

    label1_ = new views::Label(l10n_util::GetString(IDS_FR_BUBBLE_TITLE));
    label1_->SetFont(font.DeriveFont(3, ChromeFont::BOLD));
    label1_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    AddChildView(label1_);

    gfx::Size ps = GetPreferredSize();

    label2_ = new views::Label(l10n_util::GetString(IDS_FR_BUBBLE_SUBTEXT));
    label2_->SetMultiLine(true);
    label2_->SetFont(font);
    label2_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    label2_->SizeToFit(ps.width() - kBubblePadding * 2);
    AddChildView(label2_);

    std::wstring question_str
        = l10n_util::GetStringF(IDS_FR_BUBBLE_QUESTION,
                                GetDefaultSearchEngineName(profile));
    label3_ = new views::Label(question_str);
    label3_->SetMultiLine(true);
    label3_->SetFont(font);
    label3_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    label3_->SizeToFit(ps.width() - kBubblePadding * 2);
    AddChildView(label3_);

    std::wstring keep_str =
        l10n_util::GetStringF(IDS_FR_BUBBLE_OK,
                              GetDefaultSearchEngineName(profile));
    keep_button_ = new views::NativeButton(this, keep_str);
    keep_button_->SetIsDefault(true);
    AddChildView(keep_button_);

    std::wstring change_str = l10n_util::GetString(IDS_FR_BUBBLE_CHANGE);
    change_button_ = new views::NativeButton(this, change_str);
    AddChildView(change_button_);
  }

  void BubbleShown() {
    keep_button_->RequestFocus();
  }

  // Overridden from ButtonListener.
  virtual void ButtonPressed(views::Button* sender) {
    bubble_window_->Close();
    if (change_button_ == sender) {
      Browser* browser = BrowserList::GetLastActive();
      if (browser) {
        ShowOptionsWindow(OPTIONS_PAGE_GENERAL, OPTIONS_GROUP_DEFAULT_SEARCH,
                          browser->profile());
      }
    }
  }

  // Overridden from views::View.
  virtual void Layout() {
    gfx::Size canvas = GetPreferredSize();

    // The multiline business that follows is dirty hacks to get around
    // bug 1325257.
    label1_->SetMultiLine(false);
    gfx::Size pref_size = label1_->GetPreferredSize();
    label1_->SetMultiLine(true);
    label1_->SizeToFit(canvas.width() - kBubblePadding * 2);
    label1_->SetBounds(kBubblePadding, kBubblePadding,
                       canvas.width() - kBubblePadding * 2,
                       pref_size.height());

    int next_v_space = label1_->y() + pref_size.height() +
                       kRelatedControlSmallVerticalSpacing;

    pref_size = label2_->GetPreferredSize();
    label2_->SetBounds(kBubblePadding, next_v_space,
                       canvas.width() - kBubblePadding * 2,
                       pref_size.height());

    next_v_space = label2_->y() + label2_->height() +
                   kPanelSubVerticalSpacing;

    pref_size = label3_->GetPreferredSize();
    label3_->SetBounds(kBubblePadding, next_v_space,
                       canvas.width() - kBubblePadding * 2,
                       pref_size.height());

    pref_size = change_button_->GetPreferredSize();
    change_button_->SetBounds(
        canvas.width() - pref_size.width() - kBubblePadding,
        canvas.height() - pref_size.height() - kButtonVEdgeMargin,
        pref_size.width(), pref_size.height());

    pref_size = keep_button_->GetPreferredSize();
    keep_button_->SetBounds(change_button_->x() - pref_size.width() -
                            kRelatedButtonHSpacing, change_button_->y(),
                            pref_size.width(), pref_size.height());
  }

  // Overridden from views::View.
  virtual gfx::Size GetPreferredSize() {
    return gfx::Size(views::Window::GetLocalizedContentsSize(
        IDS_FIRSTRUNBUBBLE_DIALOG_WIDTH_CHARS,
        IDS_FIRSTRUNBUBBLE_DIALOG_HEIGHT_LINES));
  }

  virtual void FocusWillChange(View* focused_before, View* focused_now) {
    if (focused_before && focused_before->GetClassName() ==
                          views::NativeButton::kViewClassName) {
      views::NativeButton* before =
          static_cast<views::NativeButton*>(focused_before);
      before->SetIsDefault(false);
    }
    if (focused_now && focused_now->GetClassName() ==
                       views::NativeButton::kViewClassName) {
      views::NativeButton* after =
          static_cast<views::NativeButton*>(focused_now);
      after->SetIsDefault(true);
    }
  }

 private:
  FirstRunBubble* bubble_window_;
  views::Label* label1_;
  views::Label* label2_;
  views::Label* label3_;
  views::NativeButton* change_button_;
  views::NativeButton* keep_button_;

  DISALLOW_COPY_AND_ASSIGN(FirstRunBubbleView);
};

// Keep the bubble around for kLingerTime milliseconds, to prevent accidental
// closure.
static const int kLingerTime = 1000;

void FirstRunBubble::OnActivate(UINT action, BOOL minimized, HWND window) {
  // We might get re-enabled right before we are closed (sequence is: we get
  // deactivated, we call close, before we are actually closed we get
  // reactivated). Don't do the disabling of the parent in such cases.
  if (action == WA_ACTIVE && !has_been_activated_) {
    has_been_activated_ = true;

    // Disable the browser to prevent accidental rapid clicks from closing the
    // bubble.
    ::EnableWindow(GetParent(), false);

    MessageLoop::current()->PostDelayedTask(FROM_HERE,
        enable_window_method_factory_.NewRunnableMethod(
            &FirstRunBubble::EnableParent),
        kLingerTime);
  }
  InfoBubble::OnActivate(action, minimized, window);
}

void FirstRunBubble::InfoBubbleClosing(InfoBubble* info_bubble,
                                       bool closed_by_escape) {
  // Make sure our parent window is re-enabled.
  if (!IsWindowEnabled(GetParent()))
    ::EnableWindow(GetParent(), true);
  enable_window_method_factory_.RevokeAll();
  views::FocusManager* focus_manager =
      views::FocusManager::GetFocusManager(GetNativeView());
  focus_manager->RemoveFocusChangeListener(view_);
}

// static
FirstRunBubble* FirstRunBubble::Show(Profile* profile, HWND parent_hwnd,
                                     const gfx::Rect& position_relative_to) {
  FirstRunBubble* window = new FirstRunBubble();
  FirstRunBubbleView* view = new FirstRunBubbleView(window, profile);
  window->SetDelegate(window);
  window->set_view(view);
  window->Init(parent_hwnd, position_relative_to, view);
  window->ShowWindow(SW_SHOW);
  views::FocusManager* focus_manager =
      views::FocusManager::GetFocusManager(window->GetNativeView());
  focus_manager->AddFocusChangeListener(view);
  view->BubbleShown();
  return window;
}

void FirstRunBubble::EnableParent() {
  ::EnableWindow(GetParent(), true);
}
<|endoftext|>


<commit_before>#include <cmath>
#include <Eigen/Eigenvalues>
#include <esn/create_network_nsli.h>
#include <network_nsli.h>

namespace ESN {

    std::unique_ptr< Network > CreateNetwork(
        const NetworkParamsNSLI & params )
    {
        return std::unique_ptr< NetworkNSLI >( new NetworkNSLI( params ) );
    }

    NetworkNSLI::NetworkNSLI( const NetworkParamsNSLI & params )
        : mParams( params )
        , mIn( params.inputCount )
        , mWIn( params.neuronCount, params.inputCount )
        , mX( params.neuronCount )
        , mR( params.neuronCount )
        , mW( params.neuronCount, params.neuronCount )
        , mOut( params.outputCount )
        , mWOut( params.outputCount, params.neuronCount )
        , mWFB( params.neuronCount, params.outputCount )
        , mAdaptiveFilter( params.neuronCount,
            params.onlineTrainingForgettingFactor,
            params.onlineTrainingInitialCovariance )
    {
        if ( params.inputCount <= 0 )
            throw std::invalid_argument(
                "NetworkParamsNSLI::inputCount must be not null" );
        if ( params.neuronCount <= 0 )
            throw std::invalid_argument(
                "NetworkParamsNSLI::neuronCount must be not null" );
        if ( params.outputCount <= 0 )
            throw std::invalid_argument(
                "NetworkParamsNSLI::outputCount must be not null" );
        if ( !( params.leakingRate > 0.0 && params.leakingRate <= 1.0 ) )
            throw std::invalid_argument(
                "NetworkParamsNSLI::leakingRate must be withing "
                "interval [0,1)" );

        mWIn = Eigen::MatrixXf::Random(
            params.neuronCount, params.inputCount );

        Eigen::MatrixXf randomWeights = Eigen::MatrixXf::Random(
            params.neuronCount, params.neuronCount );
        float spectralRadius =
            randomWeights.eigenvalues().cwiseAbs().maxCoeff();
        mW = ( randomWeights / spectralRadius ).sparseView() ;

        mWOut = Eigen::MatrixXf::Random(
            params.outputCount, params.neuronCount );

        mWFB = Eigen::MatrixXf::Random(
            params.neuronCount, params.outputCount );

        mIn = Eigen::VectorXf::Zero( params.inputCount );
        mX = Eigen::VectorXf::Random( params.neuronCount );
        mOut = Eigen::VectorXf::Zero( params.outputCount );
    }

    NetworkNSLI::~NetworkNSLI()
    {
    }

    void NetworkNSLI::SetInputs( const std::vector< float > & inputs )
    {
        if ( inputs.size() != mIn.rows() )
            throw std::invalid_argument( "Wrong size of the input vector" );
        mIn = Eigen::Map< Eigen::VectorXf >(
            const_cast< float * >( inputs.data() ), inputs.size() );
    }

    void NetworkNSLI::Step( float step )
    {
        if ( step <= 0.0f )
            throw std::invalid_argument(
                "Step size must be positive value" );

        mR = mX.unaryExpr(
            [] ( float x ) -> float { return std::tanh( x ); } );

        mX = ( 1 - mParams.leakingRate ) * mX +
            mParams.leakingRate * ( mW * mR + mWFB * mOut );

        mOut = mWOut * mR;
    }

    void NetworkNSLI::CaptureOutput( std::vector< float > & output )
    {
        if ( output.size() != mParams.outputCount )
            throw std::invalid_argument(
                "Size of the vector must be equal "
                "actual number of outputs" );

        for ( int i = 0; i < mParams.outputCount; ++ i )
            output[ i ] = mOut( i );
    }

    void NetworkNSLI::Train(
        const std::vector< std::vector< float > > & inputs,
        const std::vector< std::vector< float > > & outputs )
    {
        if ( inputs.size() == 0 )
            throw std::invalid_argument(
                "Number of samples must be not null" );
        if ( inputs.size() != outputs.size() )
            throw std::invalid_argument(
                "Number of input and output samples must be equal" );
        const unsigned kSampleCount = inputs.size();

        Eigen::MatrixXf matX( mParams.neuronCount, kSampleCount );
        Eigen::MatrixXf matY( mParams.outputCount, kSampleCount );
        for ( int i = 0; i < kSampleCount; ++ i )
        {
            SetInputs( inputs[i] );
            Step( 0.1f );
            matX.col( i ) = mX;
            matY.col( i ) = Eigen::Map< Eigen::VectorXf >(
                const_cast< float * >( outputs[i].data() ),
                    mParams.outputCount );
        }

        Eigen::MatrixXf matXT = matX.transpose();

        mWOut = ( matY * matXT * ( matX * matXT ).inverse() );
    }

    void NetworkNSLI::TrainOnline( const std::vector< float > & output,
        bool forceOutput )
    {
        Eigen::VectorXf w = mWOut.row( 0 ).transpose();
        mAdaptiveFilter.Train( w, mOut( 0 ), output[0], mR );
        mWOut.row( 0 ) = w.transpose();

        if ( forceOutput )
            mOut = Eigen::Map< Eigen::VectorXf >(
                const_cast< float * >( output.data() ),
                mParams.outputCount );
    }

} // namespace ESN
<commit_msg>esn : NetworkNSLI : Step : fixed integration; accumulate weighted inputs<commit_after>#include <cmath>
#include <Eigen/Eigenvalues>
#include <esn/create_network_nsli.h>
#include <network_nsli.h>

namespace ESN {

    std::unique_ptr< Network > CreateNetwork(
        const NetworkParamsNSLI & params )
    {
        return std::unique_ptr< NetworkNSLI >( new NetworkNSLI( params ) );
    }

    NetworkNSLI::NetworkNSLI( const NetworkParamsNSLI & params )
        : mParams( params )
        , mIn( params.inputCount )
        , mWIn( params.neuronCount, params.inputCount )
        , mX( params.neuronCount )
        , mR( params.neuronCount )
        , mW( params.neuronCount, params.neuronCount )
        , mOut( params.outputCount )
        , mWOut( params.outputCount, params.neuronCount )
        , mWFB( params.neuronCount, params.outputCount )
        , mAdaptiveFilter( params.neuronCount,
            params.onlineTrainingForgettingFactor,
            params.onlineTrainingInitialCovariance )
    {
        if ( params.inputCount <= 0 )
            throw std::invalid_argument(
                "NetworkParamsNSLI::inputCount must be not null" );
        if ( params.neuronCount <= 0 )
            throw std::invalid_argument(
                "NetworkParamsNSLI::neuronCount must be not null" );
        if ( params.outputCount <= 0 )
            throw std::invalid_argument(
                "NetworkParamsNSLI::outputCount must be not null" );
        if ( !( params.leakingRate > 0.0 && params.leakingRate <= 1.0 ) )
            throw std::invalid_argument(
                "NetworkParamsNSLI::leakingRate must be withing "
                "interval [0,1)" );

        mWIn = Eigen::MatrixXf::Random(
            params.neuronCount, params.inputCount );

        Eigen::MatrixXf randomWeights = Eigen::MatrixXf::Random(
            params.neuronCount, params.neuronCount );
        float spectralRadius =
            randomWeights.eigenvalues().cwiseAbs().maxCoeff();
        mW = ( randomWeights / spectralRadius ).sparseView() ;

        mWOut = Eigen::MatrixXf::Random(
            params.outputCount, params.neuronCount );

        mWFB = Eigen::MatrixXf::Random(
            params.neuronCount, params.outputCount );

        mIn = Eigen::VectorXf::Zero( params.inputCount );
        mX = Eigen::VectorXf::Random( params.neuronCount );
        mOut = Eigen::VectorXf::Zero( params.outputCount );
    }

    NetworkNSLI::~NetworkNSLI()
    {
    }

    void NetworkNSLI::SetInputs( const std::vector< float > & inputs )
    {
        if ( inputs.size() != mIn.rows() )
            throw std::invalid_argument( "Wrong size of the input vector" );
        mIn = Eigen::Map< Eigen::VectorXf >(
            const_cast< float * >( inputs.data() ), inputs.size() );
    }

    void NetworkNSLI::Step( float step )
    {
        if ( step <= 0.0f )
            throw std::invalid_argument(
                "Step size must be positive value" );

        mR = mX.unaryExpr(
            [] ( float x ) -> float { return std::tanh( x ); } );

        mX = ( 1 - mParams.leakingRate ) * mX +
            mParams.leakingRate * ( mWIn * mIn + mW * mR + mWFB * mOut );

        mOut = mWOut * mR;
    }

    void NetworkNSLI::CaptureOutput( std::vector< float > & output )
    {
        if ( output.size() != mParams.outputCount )
            throw std::invalid_argument(
                "Size of the vector must be equal "
                "actual number of outputs" );

        for ( int i = 0; i < mParams.outputCount; ++ i )
            output[ i ] = mOut( i );
    }

    void NetworkNSLI::Train(
        const std::vector< std::vector< float > > & inputs,
        const std::vector< std::vector< float > > & outputs )
    {
        if ( inputs.size() == 0 )
            throw std::invalid_argument(
                "Number of samples must be not null" );
        if ( inputs.size() != outputs.size() )
            throw std::invalid_argument(
                "Number of input and output samples must be equal" );
        const unsigned kSampleCount = inputs.size();

        Eigen::MatrixXf matX( mParams.neuronCount, kSampleCount );
        Eigen::MatrixXf matY( mParams.outputCount, kSampleCount );
        for ( int i = 0; i < kSampleCount; ++ i )
        {
            SetInputs( inputs[i] );
            Step( 0.1f );
            matX.col( i ) = mX;
            matY.col( i ) = Eigen::Map< Eigen::VectorXf >(
                const_cast< float * >( outputs[i].data() ),
                    mParams.outputCount );
        }

        Eigen::MatrixXf matXT = matX.transpose();

        mWOut = ( matY * matXT * ( matX * matXT ).inverse() );
    }

    void NetworkNSLI::TrainOnline( const std::vector< float > & output,
        bool forceOutput )
    {
        Eigen::VectorXf w = mWOut.row( 0 ).transpose();
        mAdaptiveFilter.Train( w, mOut( 0 ), output[0], mR );
        mWOut.row( 0 ) = w.transpose();

        if ( forceOutput )
            mOut = Eigen::Map< Eigen::VectorXf >(
                const_cast< float * >( output.data() ),
                mParams.outputCount );
    }

} // namespace ESN
<|endoftext|>


<commit_before>// Copyright (c) 2010 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.

#include "chrome/test/ui/ui_test.h"

#include "chrome/common/url_constants.h"
#include "chrome/test/automation/proxy_launcher.h"
#include "chrome/test/test_switches.h"

// The named testing interface enables the use of a named socket for controlling
// the browser. This eliminates the dependency that the browser must be forked
// from the controlling process.
namespace {

class NamedInterfaceTest : public UITest {
 public:
  NamedInterfaceTest() {
    show_window_ = true;
  }

  virtual ProxyLauncher *CreateProxyLauncher() {
    CommandLine::StringType channel_path =
        CommandLine::ForCurrentProcess()->GetSwitchValueNative(
            switches::kTestingChannel);
    if (channel_path.empty())
      channel_path = ProxyLauncher::kDefaultInterfacePath;

    return new NamedProxyLauncher(channel_path, true, true);
  }
};

// This test is flaky on Linux bots.  http://crbug.com/66414
#if defined(OS_LINUX)
#define MAYBE_BasicNamedInterface FLAKY_BasicNamedInterface
#else
#define MAYBE_BasicNamedInterface BasicNamedInterface
#endif

// Basic sanity test for named testing interface which
// launches a browser instance that uses a named socket, then
// sends it some commands to open some tabs over that socket.
TEST_F(NamedInterfaceTest, MAYBE_BasicNamedInterface) {
  scoped_refptr<BrowserProxy> browser_proxy(
      automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser_proxy.get());

  for (int i = 0; i < 10; ++i)
    ASSERT_TRUE(browser_proxy->AppendTab(GURL(chrome::kAboutBlankURL)));
}

// TODO(dtu): crosbug.com/8514: Write a test that makes sure you can disconnect,
//            then reconnect with a new connection and continue automation.

}  // namespace
<commit_msg>Remove FLAKY prefix from BasicNamedInterface. This test has been passing consistently for some time now. http://test-results.appspot.com/dashboards/flakiness_dashboard.html#tests=NamedInterfaceTest&testType=ui_tests<commit_after>// Copyright (c) 2011 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.

#include "chrome/test/ui/ui_test.h"

#include "chrome/common/url_constants.h"
#include "chrome/test/automation/proxy_launcher.h"
#include "chrome/test/test_switches.h"

// The named testing interface enables the use of a named socket for controlling
// the browser. This eliminates the dependency that the browser must be forked
// from the controlling process.
namespace {

class NamedInterfaceTest : public UITest {
 public:
  NamedInterfaceTest() {
    show_window_ = true;
  }

  virtual ProxyLauncher *CreateProxyLauncher() {
    CommandLine::StringType channel_path =
        CommandLine::ForCurrentProcess()->GetSwitchValueNative(
            switches::kTestingChannel);
    if (channel_path.empty())
      channel_path = ProxyLauncher::kDefaultInterfacePath;

    return new NamedProxyLauncher(channel_path, true, true);
  }
};

// Basic sanity test for named testing interface which
// launches a browser instance that uses a named socket, then
// sends it some commands to open some tabs over that socket.
TEST_F(NamedInterfaceTest, BasicNamedInterface) {
  scoped_refptr<BrowserProxy> browser_proxy(
      automation()->GetBrowserWindow(0));
  ASSERT_TRUE(browser_proxy.get());

  for (int i = 0; i < 10; ++i)
    ASSERT_TRUE(browser_proxy->AppendTab(GURL(chrome::kAboutBlankURL)));
}

// TODO(dtu): crosbug.com/8514: Write a test that makes sure you can disconnect,
//            then reconnect with a new connection and continue automation.

}  // namespace
<|endoftext|>


<commit_before>#include <cassert>
#include <climits>
#include <sstream>
#include <stdexcept>
#include <typeinfo>

#include <map>
#include <set>
#include <string>
#include <tuple>
#include <vector>

#include <Python.h>

namespace dubzzz {
namespace Py2Cpp {

template <class T>
struct CppBuilder
{
  T operator() (PyObject* pyo)
  {
    assert(pyo);

    std::ostringstream oss;
    oss << "No conversion implemented to convert PyObject* into " << typeid(T).name();

    throw std::invalid_argument(oss.str());
    return T {};
  }
};

template <>
struct CppBuilder<PyObject*>
{
  PyObject* operator() (PyObject* pyo)
  {
    assert(pyo);
    return pyo;
  }
};

template <>
struct CppBuilder<bool>
{
  bool operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyBool_Check(pyo))
    {
      return pyo == Py_True;
    }
    throw std::invalid_argument("Not a PyBool instance");
  }
};

template <>
struct CppBuilder<int>
{
  int operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      long v { PyLong_AsLong(pyo) };
      if (v < INT_MIN || v > INT_MAX)
      {
        throw std::overflow_error("Out of <int> boundaries");
      }
      return static_cast<int>(v);
    }
    else if (PyInt_Check(pyo))
    {
      long v { PyInt_AS_LONG(pyo) };
      if (v < INT_MIN || v > INT_MAX)
      {
        throw std::overflow_error("Out of <int> boundaries");
      }
      return static_cast<int>(v);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned int>
{
  unsigned int operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      unsigned long v { PyLong_AsUnsignedLongMask(pyo) };
      if (v > UINT_MAX)
      {
        throw std::overflow_error("Out of <unsigned int> boundaries");
      }
      return static_cast<unsigned int>(v);
    }
    else if (PyInt_Check(pyo))
    {
      unsigned long v { PyInt_AsUnsignedLongMask(pyo) };
      if (v > UINT_MAX)
      {
        throw std::overflow_error("Out of <unsigned int> boundaries");
      }
      return static_cast<int>(v);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<long>
{
  long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned long>
{
  unsigned long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsUnsignedLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AsUnsignedLongMask(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<long long>
{
  long long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsLongLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned long long>
{
  unsigned long long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsUnsignedLongLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AsUnsignedLongLongMask(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<double>
{
  double operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyFloat_Check(pyo))
    {
      return PyFloat_AS_DOUBLE(pyo);
    }
    else if (PyLong_Check(pyo))
    {
      return PyLong_AsDouble(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Neither a PyDouble nor a PyLong instance");
  }
};

template <>
struct CppBuilder<std::string>
{
  std::string operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyUnicode_Check(pyo))
    {
      /**
       * Since: Python 3.3
       * Py_ssize_t size {};
       * char* str { PyUnicode_AsUTF8AndSize(pyo, &size) };
       */
      long unsigned int size { PyUnicode_GET_DATA_SIZE(pyo) }; // depreciated in 3.3
      const char* str { PyUnicode_AS_DATA(pyo) }; // depreciated in 3.3
      return std::string(str, size);
    }
    throw std::invalid_argument("Not a PyUnicode instance");
  }
};

template <class TUPLE, std::size_t pos>
void _feedCppTuple(TUPLE& tuple, PyObject* root)
{}

template <class TUPLE, std::size_t pos, class T, class... Args>
void _feedCppTuple(TUPLE& tuple, PyObject* root)
{

  std::get<pos>(tuple) = CppBuilder<T>()(PyTuple_GetItem(root, pos));
  _feedCppTuple<TUPLE, pos +1, Args...>(tuple, root);
}

template <class... Args>
struct CppBuilder<std::tuple<Args...>>
{
  std::tuple<Args...> operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyTuple_Check(pyo))
    {
      if (PyTuple_Size(pyo) == sizeof...(Args))
      {
        std::tuple<Args...> tuple { std::make_tuple(Args()...) };
        _feedCppTuple<std::tuple<Args...>, 0, Args...>(tuple, pyo);
        return tuple;
      }
      else
      {
        std::ostringstream oss;
        oss << "PyTuple length differs from asked one: "
            << "PyTuple(" << PyTuple_Size(pyo) << ") "
            << "and std::tuple<...>(" << sizeof...(Args) << ")";
        throw std::length_error(oss.str());
      }
    }
    throw std::invalid_argument("Not a PyTuple instance");
  }
};

template <class T>
struct CppBuilder<std::vector<T>>
{
  std::vector<T> operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyList_Check(pyo))
    {
      long size { PyList_Size(pyo) };
      std::vector<T> v(size);
      for (long i { 0 } ; i != size ; ++i)
      {
        v[i] = CppBuilder<T>()(PyList_GetItem(pyo, i));
      }
      return v;
    }
    throw std::invalid_argument("Not a PyList instance");
  }
};

template <class T>
struct CppBuilder<std::set<T>>
{
  std::set<T> operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PySet_Check(pyo))
    {
      long size { PySet_Size(pyo) };
      std::vector<PyObject*> backup(size);
      std::set<T> s;
      for (long i { 0 } ; i != size ; ++i)
      {
        PyObject* popped { PySet_Pop(pyo) };
        backup[i] = popped;
        s.insert(CppBuilder<T>()(popped));
      }
      for (PyObject* popped : backup)
      {
        PySet_Add(pyo, popped);
        Py_DECREF(popped);
      }
      return s;
    }
    throw std::invalid_argument("Not a PySet instance");
  }
};

template <class K, class T>
struct CppBuilder<std::map<K,T>>
{
  std::map<K,T> operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyDict_Check(pyo))
    {
      std::map<K,T> dict;
      PyObject *key, *value;
      Py_ssize_t pos = 0;
      while (PyDict_Next(pyo, &pos, &key, &value))
      {
        dict[CppBuilder<K>()(key)] = CppBuilder<T>()(value);
      }
      return dict;
    }
    throw std::invalid_argument("Not a PyDict instance");
  }
};

}
}

<commit_msg>Missing "pragma once"<commit_after>#ifndef __PY2CPP_HPP__
#define __PY2CPP_HPP__

#include <cassert>
#include <climits>
#include <sstream>
#include <stdexcept>
#include <typeinfo>

#include <map>
#include <set>
#include <string>
#include <tuple>
#include <vector>

#include <Python.h>

namespace dubzzz {
namespace Py2Cpp {

template <class T>
struct CppBuilder
{
  T operator() (PyObject* pyo)
  {
    assert(pyo);

    std::ostringstream oss;
    oss << "No conversion implemented to convert PyObject* into " << typeid(T).name();

    throw std::invalid_argument(oss.str());
    return T {};
  }
};

template <>
struct CppBuilder<PyObject*>
{
  PyObject* operator() (PyObject* pyo)
  {
    assert(pyo);
    return pyo;
  }
};

template <>
struct CppBuilder<bool>
{
  bool operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyBool_Check(pyo))
    {
      return pyo == Py_True;
    }
    throw std::invalid_argument("Not a PyBool instance");
  }
};

template <>
struct CppBuilder<int>
{
  int operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      long v { PyLong_AsLong(pyo) };
      if (v < INT_MIN || v > INT_MAX)
      {
        throw std::overflow_error("Out of <int> boundaries");
      }
      return static_cast<int>(v);
    }
    else if (PyInt_Check(pyo))
    {
      long v { PyInt_AS_LONG(pyo) };
      if (v < INT_MIN || v > INT_MAX)
      {
        throw std::overflow_error("Out of <int> boundaries");
      }
      return static_cast<int>(v);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned int>
{
  unsigned int operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      unsigned long v { PyLong_AsUnsignedLongMask(pyo) };
      if (v > UINT_MAX)
      {
        throw std::overflow_error("Out of <unsigned int> boundaries");
      }
      return static_cast<unsigned int>(v);
    }
    else if (PyInt_Check(pyo))
    {
      unsigned long v { PyInt_AsUnsignedLongMask(pyo) };
      if (v > UINT_MAX)
      {
        throw std::overflow_error("Out of <unsigned int> boundaries");
      }
      return static_cast<int>(v);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<long>
{
  long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned long>
{
  unsigned long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsUnsignedLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AsUnsignedLongMask(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<long long>
{
  long long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsLongLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<unsigned long long>
{
  unsigned long long operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyLong_Check(pyo))
    {
      return PyLong_AsUnsignedLongLong(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AsUnsignedLongLongMask(pyo);
    }
    throw std::invalid_argument("Not a PyLong instance");
  }
};

template <>
struct CppBuilder<double>
{
  double operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyFloat_Check(pyo))
    {
      return PyFloat_AS_DOUBLE(pyo);
    }
    else if (PyLong_Check(pyo))
    {
      return PyLong_AsDouble(pyo);
    }
    else if (PyInt_Check(pyo))
    {
      return PyInt_AS_LONG(pyo);
    }
    throw std::invalid_argument("Neither a PyDouble nor a PyLong instance");
  }
};

template <>
struct CppBuilder<std::string>
{
  std::string operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyUnicode_Check(pyo))
    {
      /**
       * Since: Python 3.3
       * Py_ssize_t size {};
       * char* str { PyUnicode_AsUTF8AndSize(pyo, &size) };
       */
      long unsigned int size { PyUnicode_GET_DATA_SIZE(pyo) }; // depreciated in 3.3
      const char* str { PyUnicode_AS_DATA(pyo) }; // depreciated in 3.3
      return std::string(str, size);
    }
    throw std::invalid_argument("Not a PyUnicode instance");
  }
};

template <class TUPLE, std::size_t pos>
void _feedCppTuple(TUPLE& tuple, PyObject* root)
{}

template <class TUPLE, std::size_t pos, class T, class... Args>
void _feedCppTuple(TUPLE& tuple, PyObject* root)
{

  std::get<pos>(tuple) = CppBuilder<T>()(PyTuple_GetItem(root, pos));
  _feedCppTuple<TUPLE, pos +1, Args...>(tuple, root);
}

template <class... Args>
struct CppBuilder<std::tuple<Args...>>
{
  std::tuple<Args...> operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyTuple_Check(pyo))
    {
      if (PyTuple_Size(pyo) == sizeof...(Args))
      {
        std::tuple<Args...> tuple { std::make_tuple(Args()...) };
        _feedCppTuple<std::tuple<Args...>, 0, Args...>(tuple, pyo);
        return tuple;
      }
      else
      {
        std::ostringstream oss;
        oss << "PyTuple length differs from asked one: "
            << "PyTuple(" << PyTuple_Size(pyo) << ") "
            << "and std::tuple<...>(" << sizeof...(Args) << ")";
        throw std::length_error(oss.str());
      }
    }
    throw std::invalid_argument("Not a PyTuple instance");
  }
};

template <class T>
struct CppBuilder<std::vector<T>>
{
  std::vector<T> operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyList_Check(pyo))
    {
      long size { PyList_Size(pyo) };
      std::vector<T> v(size);
      for (long i { 0 } ; i != size ; ++i)
      {
        v[i] = CppBuilder<T>()(PyList_GetItem(pyo, i));
      }
      return v;
    }
    throw std::invalid_argument("Not a PyList instance");
  }
};

template <class T>
struct CppBuilder<std::set<T>>
{
  std::set<T> operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PySet_Check(pyo))
    {
      long size { PySet_Size(pyo) };
      std::vector<PyObject*> backup(size);
      std::set<T> s;
      for (long i { 0 } ; i != size ; ++i)
      {
        PyObject* popped { PySet_Pop(pyo) };
        backup[i] = popped;
        s.insert(CppBuilder<T>()(popped));
      }
      for (PyObject* popped : backup)
      {
        PySet_Add(pyo, popped);
        Py_DECREF(popped);
      }
      return s;
    }
    throw std::invalid_argument("Not a PySet instance");
  }
};

template <class K, class T>
struct CppBuilder<std::map<K,T>>
{
  std::map<K,T> operator() (PyObject* pyo)
  {
    assert(pyo);
    if (PyDict_Check(pyo))
    {
      std::map<K,T> dict;
      PyObject *key, *value;
      Py_ssize_t pos = 0;
      while (PyDict_Next(pyo, &pos, &key, &value))
      {
        dict[CppBuilder<K>()(key)] = CppBuilder<T>()(value);
      }
      return dict;
    }
    throw std::invalid_argument("Not a PyDict instance");
  }
};

}
}

#endif

<|endoftext|>