<commit_before>#include <random>
#include <chrono>
#include <algorithm>
#include <cmath>
#include <string>
#include <sstream>
#include <fstream>

#include "bch.h"
#include "iterative.h"
#include "util.h"

static double sigma(const double eb_n0, const double R) {
  return sqrt(1.0f / (2 * R * pow(10, eb_n0 / 10.0)));
}

double generate_overview(
    std::mt19937 &generator,
    std::function<std::tuple<std::vector<int>, std::vector<float>, unsigned>(
        std::vector<float>)> decoder,
    const size_t samples, const float eb_n0) {
  constexpr int fk = 3;
  constexpr size_t length = 31;
  constexpr float R = 16.0 / length;

  std::vector<float> b(length);

  std::normal_distribution<float> random(1.0, sigma(eb_n0, R));
  auto noise_gen = std::bind(std::ref(random), std::ref(generator));

  unsigned reconstruction_failures = 0;
  unsigned reconstruction_errors = 0;
  unsigned fk_corr = 0;
  unsigned bit_errors = 0;

  for (size_t sample = 0; sample < samples; sample++) {
    std::generate(std::begin(b), std::end(b), noise_gen);
    try {
      auto result = decoder(b);
      const auto &b_corr = std::get<0>(result);
      auto wrong_bits = std::count_if(std::cbegin(b_corr), std::cend(b_corr),
                                      [](const auto &bit) { return bit != 0; });
      if (wrong_bits) {
        reconstruction_errors++;
        bit_errors += wrong_bits;
      } else {
        auto d = std::count_if(std::cbegin(b), std::cend(b),
                               [](const auto &bit) { return bit < 0; });
        if (d > fk)
          fk_corr++;
      }
    }
    catch (...) {
      reconstruction_failures++;
    }
  }
  /* word error rate */
  // os << std::setprecision(4) << eb_n0 << " ";
  // os << std::setprecision(9) << failures / (float)samples << " ";
  // os << std::setprecision(9) << fk_corr / (float)samples << " ";
  // os << std::setprecision(9) << bit_errors / (float)(samples * length);

  return bit_errors / (double)(samples * length);
}

int main() {
  constexpr size_t max_iterations = 50;
  constexpr float eb_no_step = 0.1f;
  constexpr float alpha_step = 0.01f;
  constexpr unsigned N = 10000;

  std::mt19937 generator(
      std::chrono::high_resolution_clock::now().time_since_epoch().count());

  bch code(5, 0x25, 7);

  std::ofstream file("test.output", std::ofstream::out);

  /* header */
  file << "eb_no ";
  for (float alpha = 0; alpha < 1; alpha += alpha_step) {
    std::ostringstream col_name;
    col_name << "alpha_" << alpha;
    file << col_name.str() << " ";
  }
  file << std::endl;

  file << std::scientific;

  for (double eb_no = 0; eb_no < 10; eb_no += eb_no_step) {
    file << eb_no << " ";
    auto f = std::bind(min_sum<max_iterations, float, float>, std::cref(code.H()),
                       std::placeholders::_1);
    file << generate_overview(generator, f, N, eb_no) << " ";
    file << std::endl;
  }

  for (double eb_no = 0; eb_no < 10; eb_no += eb_no_step) {
    file << eb_no << " ";
    for (float alpha = 0; alpha < 1; alpha += alpha_step) {
      auto f = std::bind(nms<max_iterations, float, float>, std::ref(code.H()),
                         std::placeholders::_1, alpha);
      file << generate_overview(generator, f, N, eb_no) << " ";
      // std::cout << eb_no << " " << alpha << std::endl;
    }
    file << std::endl;
  }
}
<commit_msg>Add decoder_t typedef<commit_after>#include <random>
#include <chrono>
#include <algorithm>
#include <cmath>
#include <string>
#include <sstream>
#include <fstream>

#include "bch.h"
#include "iterative.h"
#include "util.h"

static double sigma(const double eb_n0, const double R) {
  return sqrt(1.0f / (2 * R * pow(10, eb_n0 / 10.0)));
}

using decoder_t =
    std::function<std::tuple<std::vector<int>, std::vector<float>, unsigned>(
        std::vector<float>)>;

double generate_overview(std::mt19937 &generator, decoder_t decoder,
                         const size_t samples, const float eb_n0) {
  constexpr int fk = 3;
  constexpr size_t length = 31;
  constexpr float R = 16.0 / length;

  std::vector<float> b(length);

  std::normal_distribution<float> random(1.0, sigma(eb_n0, R));
  auto noise_gen = std::bind(std::ref(random), std::ref(generator));

  unsigned reconstruction_failures = 0;
  unsigned reconstruction_errors = 0;
  unsigned fk_corr = 0;
  unsigned bit_errors = 0;

  for (size_t sample = 0; sample < samples; sample++) {
    std::generate(std::begin(b), std::end(b), noise_gen);
    try {
      auto result = decoder(b);
      const auto &b_corr = std::get<0>(result);
      auto wrong_bits = std::count_if(std::cbegin(b_corr), std::cend(b_corr),
                                      [](const auto &bit) { return bit != 0; });
      if (wrong_bits) {
        reconstruction_errors++;
        bit_errors += wrong_bits;
      } else {
        auto d = std::count_if(std::cbegin(b), std::cend(b),
                               [](const auto &bit) { return bit < 0; });
        if (d > fk)
          fk_corr++;
      }
    }
    catch (...) {
      reconstruction_failures++;
    }
  }
  /* word error rate */
  // os << std::setprecision(4) << eb_n0 << " ";
  // os << std::setprecision(9) << failures / (float)samples << " ";
  // os << std::setprecision(9) << fk_corr / (float)samples << " ";
  // os << std::setprecision(9) << bit_errors / (float)(samples * length);

  return bit_errors / (double)(samples * length);
}

int main() {
  constexpr size_t max_iterations = 50;
  constexpr float eb_no_step = 0.1f;
  constexpr float alpha_step = 0.01f;
  constexpr unsigned N = 10000;

  std::mt19937 generator(
      std::chrono::high_resolution_clock::now().time_since_epoch().count());

  bch code(5, 0x25, 7);

  std::ofstream file("test.output", std::ofstream::out);

  /* header */
  file << "eb_no ";
  for (float alpha = 0; alpha < 1; alpha += alpha_step) {
    std::ostringstream col_name;
    col_name << "alpha_" << alpha;
    file << col_name.str() << " ";
  }
  file << std::endl;

  file << std::scientific;

  for (double eb_no = 0; eb_no < 10; eb_no += eb_no_step) {
    file << eb_no << " ";
    auto f = std::bind(min_sum<max_iterations, float, float>, std::cref(code.H()),
                       std::placeholders::_1);
    file << generate_overview(generator, f, N, eb_no) << " ";
    file << std::endl;
  }

  for (double eb_no = 0; eb_no < 10; eb_no += eb_no_step) {
    file << eb_no << " ";
    for (float alpha = 0; alpha < 1; alpha += alpha_step) {
      auto f = std::bind(nms<max_iterations, float, float>, std::ref(code.H()),
                         std::placeholders::_1, alpha);
      file << generate_overview(generator, f, N, eb_no) << " ";
      // std::cout << eb_no << " " << alpha << std::endl;
    }
    file << std::endl;
  }
}
<|endoftext|>


<commit_before>/*
#include <iostream>
#include <stdlib.h>
#include <stdio.h>

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;

#include <boost/numeric/ublas/io.hpp>
*/

#define MAX_ITER 100
#define TOL 1.0e-3

#include <random>
#include <algorithm>

#if defined(VIENNACL_WITH_OPENCL) || defined(VIENNACL_WITH_OPENMP) || defined(VIENNACL_WITH_CUDA)
#define VIENNACL
#include "viennacl/ocl/device.hpp"
#include "viennacl/ocl/platform.hpp"
#include "viennacl/scalar.hpp"
#include "viennacl/vector.hpp"
#endif

#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/assignment.hpp>
using namespace boost::numeric;

#include "usi_compression.h"
#include "read_timeseries_matrix.h"
#include "gamma_zero.h"
#include "gamma_s.h"
#include "find.h"
#include "theta_s.h"
#include "lanczos_correlation.h"
#include "L_value.h"
//

#include "mpi.h"

/**
	   Write description of function here.
	   The function should follow these comments.
	   Use of "brief" tag is optional. (no point to it)

	   The function arguments listed with "param" will be compared
	   to the declaration and verified.

	   @param[in]     filename    Filename (string)
	   @param[in]     fields      List of the fields to be extracted (vector of strings0
	   @return                    vector of concatenated field values
	 */

int main(int argc, char *argv[])
//****************************************************************************80
//
//  Purpose:
//
//    Example of parallel NetCDF functionality
//
//  Discussion:
//
//    This program demonstrates parallel NetCDF functionality.  It reads from
//    a NetCDF file a specified, specified as the first and second arguments of
//    the function.
//
//    This is the first step toward implementing a compression backend which
//    reads a NetCDF stream, and compresses the time series data in parallel
//    using the approaches of Horenko, et al.
//
//  Licensing:
//
//    This code is distributed under the GNU LGPL license.
//
//  Modified:
//
//     Starting October 2013
//
//  Author:
//
//    William Sawyer (CSCS)
//
//  Reference:
//
//    Horenko, Klein, Dolaptchiev, Schuette
//    Automated Generation of Reduced Stochastic Weather Models I:
//    simultaneous dimension and model reduction for time series analysis
//    XXX
//
//  Example execution:
//
//    aprun -n 2 ./netcdf_test /project/csstaff/outputs/echam/echam6/echam_output/t31_196001.01_echam.nc seaice
//
{
  using namespace std;

  /* This will be the netCDF ID for the file and data variable. */
  int ncid, varid, dimid;
  int ndims, nvars_in, ngatts_in, unlimdimid_in;
  int my_rank, mpi_processes;

  /* Loop indexes, and error handling. */
  int x, y, retval ;
  int slab_size ; // is the number of entries in one slab to be read in

  int    *dimids;
  size_t *dims;
  size_t *p;
  size_t *start, *count;

#if defined(VIENNACL_WITH_OPENCL) || defined(VIENNACL_WITH_OPENMP) || defined(VIENNACL_WITH_CUDA)
  viennacl::ocl::set_context_device_type(1, viennacl::ocl::gpu_tag());   // Does not find the GPU
#endif

//
//  Initialize MPI.
//
  MPI_Init ( &argc, &argv );
  MPI_Comm comm = MPI_COMM_WORLD;
  MPI_Info info = MPI_INFO_NULL;

  MPI_Comm_rank( MPI_COMM_WORLD, &my_rank );
  MPI_Comm_size( MPI_COMM_WORLD, &mpi_processes );

  if (argc <= 2)
    {
      std::cout << "Usage: " << argv[0] << " <Filename>" << " <field name>" << std::endl;
      exit(1);
    }

#if defined(VIENNACL_WITH_OPENCL) || defined(VIENNACL_WITH_OPENMP) || defined(VIENNACL_WITH_CUDA)
   typedef std::vector< viennacl::ocl::platform > platforms_type;
   platforms_type platforms = viennacl::ocl::get_platforms();
   viennacl::ocl::platform pf = viennacl::ocl::get_platforms()[1];

   //    for (platforms_type::iterator platform_iter = platforms.begin();
   //                                 platform_iter != platforms.end();
   //                                ++platform_iter)
   if (!my_rank)
   {
    typedef std::vector<viennacl::ocl::device> devices_type;
    devices_type devices = pf.devices(CL_DEVICE_TYPE_ALL);

    //
    // print some platform info
    //
    std::cout << "# =========================================" << std::endl;
    std::cout << "# Platform Information " << std::endl;
    std::cout << "# =========================================" << std::endl;

    std::cout << "#" << std::endl;
    std::cout << "# Vendor and version: " << pf.info() << std::endl;
    std::cout << "#" << std::endl;

    //
    // traverse the devices and print the information
    //
    std::cout << "# " << std::endl;
    std::cout << "# Available Devices: " << std::endl;
    std::cout << "# " << std::endl;
    for(devices_type::iterator iter = devices.begin(); iter != devices.end(); iter++)
    {
        std::cout << std::endl;

        std::cout << " -----------------------------------------" << std::endl;
        std::cout << iter->info();
        std::cout << " -----------------------------------------" << std::endl;
    }
    std::cout << std::endl;
    std::cout << "###########################################" << std::endl;
    std::cout << std::endl;
   }
#endif

  std::cout << "Parallel execution: my_rank " << my_rank << " out of " << mpi_processes << " processes" << std::endl;

  std::string              filename(argv[1]);
  std::vector<std::string> fields(argv+2, argv+argc);

  typedef Array<int, Dynamic, 1> ArrayX1i;

  MatrixXX   X = read_timeseries_matrix<ScalarType>( filename, fields);

  /*
  VectorXd  b = VectorXd::Random(X.cols());
  VectorXd  Xb = X * b;
  std::cout << "matrix rows " << X.rows() << " cols " << X.cols() << std::endl;
  std::cout << "norm rand vect " << b.norm() << " norm matrix * random vector " << Xb.norm() << std::endl;
  */

  //
  // want vector of length X.rows() of random values between {0,k-1}
  //

#define K 10

  // create a blank vector of length X.rows()
  const int Ntl = static_cast<int>(X.rows());
  const int nl = static_cast<int>(X.cols());
  // std::cout << "First row X " << X.block(0,0,Ntl,5) << std::endl;
  ArrayX1i gamma_ind = gamma_zero(nl, K );
  MatrixXX theta = MatrixXX::Zero(Ntl,K);       // Time series means (one for each k), allocate outside loop
  MatrixXX TT(Ntl,K);                 // Eigenvectors (one for each k), allocate outside loop
  MatrixXX Xtranslated( Ntl, nl ) ;   // Maximum size for worst case (all nl in one K)
  MatrixXX eigenvectors( Ntl, 1 ) ;   // Only one eigenvector at this stage

  ScalarType L_value_old = 1.0e19;   // Very big value
  ScalarType L_value_new;
  for ( int iter = 0; iter < MAX_ITER; iter++ ) {
    theta_s<ScalarType>(gamma_ind, X, theta);       // Determine X column means for each active state denoted by gamma_ind
    // if ( iter > 0 ) { std::cout << "L value after theta determination " << L_value( gamma_ind, TT, X, theta ) << std::endl; }
    for(int k = 0; k < K; k++) {              // Principle Component Analysis
      std::vector<int> Nonzeros = find( gamma_ind, k );
      //      std::cout << " For k = " << k << " nbr nonzeros " << Nonzeros.size() << std::endl;
      for (int m = 0; m < Nonzeros.size() ; m++ )        // Translate X columns with mean value at new origin
      {
	Xtranslated.col(m) = X.col(Nonzeros[m]) - theta.col(k);  // bsxfun(@minus,X(:,Nonzeros),Theta(:,k))
      }
      lanczos_correlation(Xtranslated.block(0,0,Ntl,Nonzeros.size()), 1, 1.0e-7, 20, eigenvectors);
      TT.col(k) = eigenvectors.col(0);
    }
    std::cout << "L value after PCA " << L_value( gamma_ind, TT, X, theta ) << std::endl;
    gamma_s( X, theta, TT, gamma_ind );
    L_value_new =  L_value( gamma_ind, TT, X, theta );
    std::cout << "L value after gamma minimization " << L_value_new << std::endl;
    if ( L_value_new > L_value_old ) {
      std::cout << "New L_value " << L_value_new << " larger than old: " << L_value_new << " aborting " << std::endl;
      break;
    }
    else if ( L_value_old - L_value_new < TOL ) {
      std::cout << " Converged: to tolerance " << TOL << std::endl;
      break;
    }
    L_value_old = L_value_new;
  }

//  auto result1 = std::find_if(gamma_ind.data(), gamma_ind.data()+gamma_ind.rows(), std::bind2nd (std::equal_to<int>(), 4));
//  std::cout << "result of find operation is " << std::endl
//    << result1.format(CommaInitFmt) << std::endl;

/*
  for(int k = 0; k < theta.cols(); k++) {
    std::cout << "index set for k =  " << k << std::endl ;
    std::vector<int> found_items = find( gamma_ind, k );

    copy(found_items.begin(), found_items.end(), ostream_iterator<int>(cout, ", "));
    std::cout << std::endl ;
  }
*/

//
//  Terminate MPI.
//
  retval =  0;
  std::cout << "retval " << retval << std::endl;

  MPI::Finalize ( );

  return 0;
}
<commit_msg>Modified convergence criterion to relative tolerance.<commit_after>/*
#include <iostream>
#include <stdlib.h>
#include <stdio.h>

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;

#include <boost/numeric/ublas/io.hpp>
*/

#define MAX_ITER 100
#define TOL 1.0e-3

#include <random>
#include <algorithm>

#if defined(VIENNACL_WITH_OPENCL) || defined(VIENNACL_WITH_OPENMP) || defined(VIENNACL_WITH_CUDA)
#define VIENNACL
#include "viennacl/ocl/device.hpp"
#include "viennacl/ocl/platform.hpp"
#include "viennacl/scalar.hpp"
#include "viennacl/vector.hpp"
#endif

#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/assignment.hpp>
using namespace boost::numeric;

#include "usi_compression.h"
#include "read_timeseries_matrix.h"
#include "gamma_zero.h"
#include "gamma_s.h"
#include "find.h"
#include "theta_s.h"
#include "lanczos_correlation.h"
#include "L_value.h"
//

#include "mpi.h"

/**
	   Write description of function here.
	   The function should follow these comments.
	   Use of "brief" tag is optional. (no point to it)

	   The function arguments listed with "param" will be compared
	   to the declaration and verified.

	   @param[in]     filename    Filename (string)
	   @param[in]     fields      List of the fields to be extracted (vector of strings0
	   @return                    vector of concatenated field values
	 */

int main(int argc, char *argv[])
//****************************************************************************80
//
//  Purpose:
//
//    Example of parallel NetCDF functionality
//
//  Discussion:
//
//    This program demonstrates parallel NetCDF functionality.  It reads from
//    a NetCDF file a specified, specified as the first and second arguments of
//    the function.
//
//    This is the first step toward implementing a compression backend which
//    reads a NetCDF stream, and compresses the time series data in parallel
//    using the approaches of Horenko, et al.
//
//  Licensing:
//
//    This code is distributed under the GNU LGPL license.
//
//  Modified:
//
//     Starting October 2013
//
//  Author:
//
//    William Sawyer (CSCS)
//
//  Reference:
//
//    Horenko, Klein, Dolaptchiev, Schuette
//    Automated Generation of Reduced Stochastic Weather Models I:
//    simultaneous dimension and model reduction for time series analysis
//    XXX
//
//  Example execution:
//
//    aprun -n 2 ./netcdf_test /project/csstaff/outputs/echam/echam6/echam_output/t31_196001.01_echam.nc seaice
//
{
  using namespace std;

  /* This will be the netCDF ID for the file and data variable. */
  int ncid, varid, dimid;
  int ndims, nvars_in, ngatts_in, unlimdimid_in;
  int my_rank, mpi_processes;

  /* Loop indexes, and error handling. */
  int x, y, retval ;
  int slab_size ; // is the number of entries in one slab to be read in

  int    *dimids;
  size_t *dims;
  size_t *p;
  size_t *start, *count;

#if defined(VIENNACL_WITH_OPENCL) || defined(VIENNACL_WITH_OPENMP) || defined(VIENNACL_WITH_CUDA)
  viennacl::ocl::set_context_device_type(1, viennacl::ocl::gpu_tag());   // Does not find the GPU
#endif

//
//  Initialize MPI.
//
  MPI_Init ( &argc, &argv );
  MPI_Comm comm = MPI_COMM_WORLD;
  MPI_Info info = MPI_INFO_NULL;

  MPI_Comm_rank( MPI_COMM_WORLD, &my_rank );
  MPI_Comm_size( MPI_COMM_WORLD, &mpi_processes );

  if (argc <= 2)
    {
      std::cout << "Usage: " << argv[0] << " <Filename>" << " <field name>" << std::endl;
      exit(1);
    }

#if defined(VIENNACL_WITH_OPENCL) || defined(VIENNACL_WITH_OPENMP) || defined(VIENNACL_WITH_CUDA)
   typedef std::vector< viennacl::ocl::platform > platforms_type;
   platforms_type platforms = viennacl::ocl::get_platforms();
   viennacl::ocl::platform pf = viennacl::ocl::get_platforms()[1];

   //    for (platforms_type::iterator platform_iter = platforms.begin();
   //                                 platform_iter != platforms.end();
   //                                ++platform_iter)
   if (!my_rank)
   {
    typedef std::vector<viennacl::ocl::device> devices_type;
    devices_type devices = pf.devices(CL_DEVICE_TYPE_ALL);

    //
    // print some platform info
    //
    std::cout << "# =========================================" << std::endl;
    std::cout << "# Platform Information " << std::endl;
    std::cout << "# =========================================" << std::endl;

    std::cout << "#" << std::endl;
    std::cout << "# Vendor and version: " << pf.info() << std::endl;
    std::cout << "#" << std::endl;

    //
    // traverse the devices and print the information
    //
    std::cout << "# " << std::endl;
    std::cout << "# Available Devices: " << std::endl;
    std::cout << "# " << std::endl;
    for(devices_type::iterator iter = devices.begin(); iter != devices.end(); iter++)
    {
        std::cout << std::endl;

        std::cout << " -----------------------------------------" << std::endl;
        std::cout << iter->info();
        std::cout << " -----------------------------------------" << std::endl;
    }
    std::cout << std::endl;
    std::cout << "###########################################" << std::endl;
    std::cout << std::endl;
   }
#endif

  std::cout << "Parallel execution: my_rank " << my_rank << " out of " << mpi_processes << " processes" << std::endl;

  std::string              filename(argv[1]);
  std::vector<std::string> fields(argv+2, argv+argc);

  typedef Array<int, Dynamic, 1> ArrayX1i;

  MatrixXX   X = read_timeseries_matrix<ScalarType>( filename, fields);

  /*
  VectorXd  b = VectorXd::Random(X.cols());
  VectorXd  Xb = X * b;
  std::cout << "matrix rows " << X.rows() << " cols " << X.cols() << std::endl;
  std::cout << "norm rand vect " << b.norm() << " norm matrix * random vector " << Xb.norm() << std::endl;
  */

  //
  // want vector of length X.rows() of random values between {0,k-1}
  //

#define K 10

  // create a blank vector of length X.rows()
  const int Ntl = static_cast<int>(X.rows());
  const int nl = static_cast<int>(X.cols());
  // std::cout << "First row X " << X.block(0,0,Ntl,5) << std::endl;
  ArrayX1i gamma_ind = gamma_zero(nl, K );
  MatrixXX theta = MatrixXX::Zero(Ntl,K);       // Time series means (one for each k), allocate outside loop
  MatrixXX TT(Ntl,K);                 // Eigenvectors (one for each k), allocate outside loop
  MatrixXX Xtranslated( Ntl, nl ) ;   // Maximum size for worst case (all nl in one K)
  MatrixXX eigenvectors( Ntl, 1 ) ;   // Only one eigenvector at this stage

  ScalarType L_value_old = 1.0e19;   // Very big value
  ScalarType L_value_new;
  for ( int iter = 0; iter < MAX_ITER; iter++ ) {
    theta_s<ScalarType>(gamma_ind, X, theta);       // Determine X column means for each active state denoted by gamma_ind
    // if ( iter > 0 ) { std::cout << "L value after theta determination " << L_value( gamma_ind, TT, X, theta ) << std::endl; }
    for(int k = 0; k < K; k++) {              // Principle Component Analysis
      std::vector<int> Nonzeros = find( gamma_ind, k );
      //      std::cout << " For k = " << k << " nbr nonzeros " << Nonzeros.size() << std::endl;
      for (int m = 0; m < Nonzeros.size() ; m++ )        // Translate X columns with mean value at new origin
      {
	Xtranslated.col(m) = X.col(Nonzeros[m]) - theta.col(k);  // bsxfun(@minus,X(:,Nonzeros),Theta(:,k))
      }
      lanczos_correlation(Xtranslated.block(0,0,Ntl,Nonzeros.size()), 1, 1.0e-7, 20, eigenvectors);
      TT.col(k) = eigenvectors.col(0);
    }
    std::cout << "L value after PCA " << L_value( gamma_ind, TT, X, theta ) << std::endl;
    gamma_s( X, theta, TT, gamma_ind );
    L_value_new =  L_value( gamma_ind, TT, X, theta );
    std::cout << "L value after gamma minimization " << L_value_new << std::endl;
    if ( L_value_new > L_value_old ) {
      std::cout << "New L_value " << L_value_new << " larger than old: " << L_value_new << " aborting " << std::endl;
      break;
    }
    else if ( (L_value_old - L_value_new) < L_value_new*TOL ) {
      std::cout << " Converged: to tolerance " << TOL << std::endl;
      break;
    }
    L_value_old = L_value_new;
  }

//  auto result1 = std::find_if(gamma_ind.data(), gamma_ind.data()+gamma_ind.rows(), std::bind2nd (std::equal_to<int>(), 4));
//  std::cout << "result of find operation is " << std::endl
//    << result1.format(CommaInitFmt) << std::endl;

/*
  for(int k = 0; k < theta.cols(); k++) {
    std::cout << "index set for k =  " << k << std::endl ;
    std::vector<int> found_items = find( gamma_ind, k );

    copy(found_items.begin(), found_items.end(), ostream_iterator<int>(cout, ", "));
    std::cout << std::endl ;
  }
*/

//
//  Terminate MPI.
//
  retval =  0;
  std::cout << "retval " << retval << std::endl;

  MPI::Finalize ( );

  return 0;
}
<|endoftext|>


<commit_before>#include "roundKing.h"

const string ROUND_KING_ANIM_IDLE = "idle";
const string ROUND_KING_ANIM_CHARGE = "charge";
const string ROUND_KING_ANIM_SHOOT = "shoot";
const string ROUND_KING_ANIM_SLAM = "slam";
const string ROUND_KING_ANIM_JUMP_TELEGRAPH = "jumpTelegraph";
const string ROUND_KING_ANIM_JUMP = "jump";
const string ROUND_KING_ANIM_DIE = "die";

const int ROUND_KING_STATE_IDLE = 1;
const int ROUND_KING_STATE_CHARGE = 2;
const int ROUND_KING_STATE_SHOOT = 3;
const int ROUND_KING_STATE_SLAM = 4;
const int ROUND_KING_STATE_JUMP_TELEGRAPH = 5;
const int ROUND_KING_STATE_JUMP = 6;
const int ROUND_KING_STATE_DEAD = 7;

const int ROUND_KING_PHASE_NORMAL = 1;
const int ROUND_KING_PHASE_DAMAGED = 2;
const int ROUND_KING_PHASE_FRANTIC = 3;

int RoundKing::bossKilled = 0;

RoundKing::RoundKing(AnimationSet* animSet, AnimationSet* bulletAnimSet) {
	this->animSet = animSet;
	this->bulletAnimSet = bulletAnimSet;

	type = "enemy";

	x = Globals::ScreenWidth / 2;
	y = Globals::ScreenHeight / 2;
	moveSpeed = 0;
	moveSpeedMax = 20;
	hp = hpMax = 500;
	damage = 0;
	collisionBoxW = 50;
	collisionBoxH = 30;

	collisionBox.w = collisionBoxW;
	collisionBox.h = collisionBoxH;

	collisionBoxYOffset = -14;

	changeAnimation(ROUND_KING_STATE_IDLE, true);

	updateCollisionBox();
}

void RoundKing::update() {
	//check if dead
	if (hp < 1 && state != ROUND_KING_STATE_DEAD) {
		changeAnimation(ROUND_KING_STATE_DEAD, true);
		moving = false;
		die();
	}

	// ai thinks what to do
	think();

	//update our shooting stuff
	updateShoot();

	updateCollisionBox();
	updateMovement();
	updateCollisions();

	updateHitBox();
	updateDamages();

	updateAnimation();

	updateInvincibleTimer();
}

void RoundKing::updateShoot() {
	if (state == ROUND_KING_STATE_SHOOT) {
		shootTimer -= TimeController::timeController.dT;
		bulletTimer -= TimeController::timeController.dT;

		//if shooting time is over, stop shooting
		if (shootTimer <= 0) {
			changeAnimation(ROUND_KING_STATE_IDLE, true);
		}
		else if(bulletTimer <=0) {   //otherwise if still shootig and it's time to take a shot
			bulletTimer = 0.5;

			Bullet* bullet = new Bullet(bulletAnimSet, x, y);
			SoundManager::soundManager.playSound("shoot");
			bullet->angle = angle;
			Entity::entities.push_back(bullet);
		}
	}
}

void RoundKing::think() {
	// finds closest hero
	findNearestTarget();

	//if there is a hero we can target, do the thinking
	if (target != NULL) {
		//only tick down think timer if in IDLE state
		if (state == ROUND_KING_STATE_IDLE)
			thinkTimer -= TimeController::timeController.dT;

		//keep setting angle to point towards target
		angle = Entity::angleBetweenTwoEntities(this, target);

		// CHECK WHICH PHASE WE ARE IN
		if (hp > 250)
			aiState = ROUND_KING_PHASE_NORMAL;
		else if (hp > 100)
			aiState = ROUND_KING_PHASE_DAMAGED;
		else
			aiState = ROUND_KING_PHASE_FRANTIC;

		// if thinkTimer is up, work out what to do next
		if (thinkTimer <= 0 && state == ROUND_KING_STATE_IDLE) {
			// reset animations, we're about to do something new
			frameTimer = 0;

			//in normal phase do :
			if (aiState == ROUND_KING_PHASE_NORMAL) {
				//reset timer
				thinkTimer = 2;

				// randomly select either slam or charge
				int action = getRandomNumber(4);
				if (action % 2 == 0)
					slam();
				else
					charge();
			}
			//in damaged phase do :
			else if (aiState == ROUND_KING_PHASE_DAMAGED) {
				//reset timer
				thinkTimer = 1.5f;

				// randomly select either slam, charge or jump
				int action = getRandomNumber(6);
				if (action < 2)
					slam();
				else if (action < 4)
					charge();
				else
					jumpTelegraph();
			}
			else {
				//assuming we are in frantic phase
				//reset timer
				thinkTimer = 1;

				// randomly select either charge or jump
				int action = getRandomNumber(4);
				if (action % 2 == 0)
					jumpTelegraph();
				else
					charge();
			}
		}
	}
	else {
		// targeting no one
		moving = 0;
		changeAnimation(ROUND_KING_STATE_IDLE, (state != ROUND_KING_STATE_IDLE));
	}
}

void RoundKing::charge() {
	moving = false;
	SoundManager::soundManager.playSound("laugh");
	changeAnimation(ROUND_KING_STATE_CHARGE, true);
}

void RoundKing::shoot() {
	moving = false;

	shootTimer = 5; // 5 seconds of shooting at the player
	bulletTimer = 0; // take first shot immediately during shooting Time

	//if damaged or frantic, have a shorter shooting time
	if (aiState != ROUND_KING_PHASE_NORMAL)
		shootTimer = 3;

	changeAnimation(ROUND_KING_STATE_SHOOT, true);
}

void RoundKing::slam() {
	moving = false;
	changeAnimation(ROUND_KING_STATE_SLAM, true);
}

void RoundKing::jumpTelegraph() {
	moving = false;
	frameTimer = 0;
	changeAnimation(ROUND_KING_STATE_JUMP_TELEGRAPH, true);
}

void RoundKing::jump() {
	moving = false;
	frameTimer = 0;
	slideAmount = 100;
	slideAngle = angle;
	changeAnimation(ROUND_KING_STATE_JUMP, true);
}

void RoundKing::die() {
	moving = false;
	changeAnimation(ROUND_KING_STATE_DEAD, true);
	SoundManager::soundManager.playSound("enemyDie");

	// add to our score count
	RoundKing::bossKilled++;
}

void RoundKing::findNearestTarget() {
	// TODO cleaner solution than just copy/pasted code
	// suggestion : make another class to help with targeting entities and make glob, grob, and roundking inherit from it

	target = NULL;
	// find closest target
	for (auto entity = Entity::entities.begin(); entity != Entity::entities.end(); entity++) {
		if ((*entity)->type == "hero" && (*entity)->active) {
			// if found first hero in list then set them as the target fo now
			if (target == NULL) {
				target = (LivingEntity*)(*entity); // if can't cast to LivingEntity, throw casting exception
			}
			else {
				// otherwise, is this other hero closer than the previous target
				if (Entity::distanceBetweenTwoEntities(this, (*entity)) < Entity::distanceBetweenTwoEntities(this, target)) {
					target = (LivingEntity*)(*entity);
				}
			}
		}
	}
}

void RoundKing::changeAnimation(int newState, bool resetFrameToBeginning) {
	state = newState;

	if (state == ROUND_KING_STATE_IDLE)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_IDLE);
	if (state == ROUND_KING_STATE_CHARGE)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_CHARGE);
	if (state == ROUND_KING_STATE_SHOOT)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_SHOOT);
	if (state == ROUND_KING_STATE_SLAM)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_SLAM);
	if (state == ROUND_KING_STATE_JUMP_TELEGRAPH)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_JUMP_TELEGRAPH);
	if (state == ROUND_KING_STATE_JUMP)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_JUMP);
	if (state == ROUND_KING_STATE_DEAD)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_DIE);

	if (resetFrameToBeginning)
		currentFrame = currentAnim->getFrame(0);
	else
		currentFrame = currentAnim->getFrame(currentFrame->frameNumber);
}

void RoundKing::updateAnimation() {
	if (currentFrame == NULL || currentAnim == NULL)
		return;

	frameTimer += TimeController::timeController.dT;
	//if frameTimer greater than frame duration;
	if (frameTimer >= currentFrame->duration) {
		// if at the end of animation
		if (currentFrame->frameNumber == currentAnim->getEndFrameNumber()) {
			if (state == ROUND_KING_STATE_CHARGE)
				shoot();
			else if (state == ROUND_KING_STATE_JUMP_TELEGRAPH)
				jump();
			else if (state == ROUND_KING_STATE_SLAM || state == ROUND_KING_STATE_JUMP)
				changeAnimation(ROUND_KING_STATE_IDLE, true);
			else if (state == ROUND_KING_STATE_DEAD) {
				frameTimer = 0;
				// if somehow live again
				if (hp > 0)
					changeAnimation(ROUND_KING_STATE_IDLE, true);
				else
					active = false; // get rid of him in the game loop, bye bye
			}
		}
		else {
			// not end of animation, so move to next frame normally
			currentFrame = currentAnim->getNextFrame(currentFrame);

			// IF THE NEW FRAME IS DEALING DAMAGE, we might want to make sounds
			GroupNumber* damages = (GroupNumber*)GroupBuilder::findGroupByName("damage", currentFrame->frameData);

			//if does damage
			if (damages != NULL && damages->numberOfDataInGroup() > 0) {
				// there is at least one damage value in this group of frames

				//and if it's in slam state
				if (state == ROUND_KING_STATE_SLAM)
					SoundManager::soundManager.playSound("smash");
				else if (state == ROUND_KING_STATE_JUMP) // if in jump state
					SoundManager::soundManager.playSound("crash");
			}
		}
		frameTimer = 0;
	}
}

void RoundKing::updateDamages() {

}<commit_msg>Update round king implementation<commit_after>#include "roundKing.h"

const string ROUND_KING_ANIM_IDLE = "idle";
const string ROUND_KING_ANIM_CHARGE = "charge";
const string ROUND_KING_ANIM_SHOOT = "shoot";
const string ROUND_KING_ANIM_SLAM = "slam";
const string ROUND_KING_ANIM_JUMP_TELEGRAPH = "jumpTelegraph";
const string ROUND_KING_ANIM_JUMP = "jump";
const string ROUND_KING_ANIM_DIE = "die";

const int ROUND_KING_STATE_IDLE = 1;
const int ROUND_KING_STATE_CHARGE = 2;
const int ROUND_KING_STATE_SHOOT = 3;
const int ROUND_KING_STATE_SLAM = 4;
const int ROUND_KING_STATE_JUMP_TELEGRAPH = 5;
const int ROUND_KING_STATE_JUMP = 6;
const int ROUND_KING_STATE_DEAD = 7;

const int ROUND_KING_PHASE_NORMAL = 1;
const int ROUND_KING_PHASE_DAMAGED = 2;
const int ROUND_KING_PHASE_FRANTIC = 3;

int RoundKing::bossKilled = 0;

RoundKing::RoundKing(AnimationSet* animSet, AnimationSet* bulletAnimSet) {
	this->animSet = animSet;
	this->bulletAnimSet = bulletAnimSet;

	type = "enemy";

	x = Globals::ScreenWidth / 2;
	y = Globals::ScreenHeight / 2;
	moveSpeed = 0;
	moveSpeedMax = 20;
	hp = hpMax = 500;
	damage = 0;
	collisionBoxW = 50;
	collisionBoxH = 30;

	collisionBox.w = collisionBoxW;
	collisionBox.h = collisionBoxH;

	collisionBoxYOffset = -14;

	changeAnimation(ROUND_KING_STATE_IDLE, true);

	updateCollisionBox();
}

void RoundKing::update() {
	//check if dead
	if (hp < 1 && state != ROUND_KING_STATE_DEAD) {
		changeAnimation(ROUND_KING_STATE_DEAD, true);
		moving = false;
		die();
	}

	// ai thinks what to do
	think();

	//update our shooting stuff
	updateShoot();

	updateCollisionBox();
	updateMovement();
	updateCollisions();

	updateHitBox();
	updateDamages();

	updateAnimation();

	updateInvincibleTimer();
}

void RoundKing::updateShoot() {
	if (state == ROUND_KING_STATE_SHOOT) {
		shootTimer -= TimeController::timeController.dT;
		bulletTimer -= TimeController::timeController.dT;

		//if shooting time is over, stop shooting
		if (shootTimer <= 0) {
			changeAnimation(ROUND_KING_STATE_IDLE, true);
		}
		else if(bulletTimer <=0) {   //otherwise if still shootig and it's time to take a shot
			bulletTimer = 0.5;

			Bullet* bullet = new Bullet(bulletAnimSet, x, y);
			SoundManager::soundManager.playSound("shoot");
			bullet->angle = angle;
			Entity::entities.push_back(bullet);
		}
	}
}

void RoundKing::think() {
	// finds closest hero
	findNearestTarget();

	//if there is a hero we can target, do the thinking
	if (target != NULL) {
		//only tick down think timer if in IDLE state
		if (state == ROUND_KING_STATE_IDLE)
			thinkTimer -= TimeController::timeController.dT;

		//keep setting angle to point towards target
		angle = Entity::angleBetweenTwoEntities(this, target);

		// CHECK WHICH PHASE WE ARE IN
		if (hp > 250)
			aiState = ROUND_KING_PHASE_NORMAL;
		else if (hp > 100)
			aiState = ROUND_KING_PHASE_DAMAGED;
		else
			aiState = ROUND_KING_PHASE_FRANTIC;

		// if thinkTimer is up, work out what to do next
		if (thinkTimer <= 0 && state == ROUND_KING_STATE_IDLE) {
			// reset animations, we're about to do something new
			frameTimer = 0;

			//in normal phase do :
			if (aiState == ROUND_KING_PHASE_NORMAL) {
				//reset timer
				thinkTimer = 2;

				// randomly select either slam or charge
				int action = getRandomNumber(4);
				if (action % 2 == 0)
					slam();
				else
					charge();
			}
			//in damaged phase do :
			else if (aiState == ROUND_KING_PHASE_DAMAGED) {
				//reset timer
				thinkTimer = 1.5f;

				// randomly select either slam, charge or jump
				int action = getRandomNumber(6);
				if (action < 2)
					slam();
				else if (action < 4)
					charge();
				else
					jumpTelegraph();
			}
			else {
				//assuming we are in frantic phase
				//reset timer
				thinkTimer = 1;

				// randomly select either charge or jump
				int action = getRandomNumber(4);
				if (action % 2 == 0)
					jumpTelegraph();
				else
					charge();
			}
		}
	}
	else {
		// targeting no one
		moving = 0;
		changeAnimation(ROUND_KING_STATE_IDLE, (state != ROUND_KING_STATE_IDLE));
	}
}

void RoundKing::charge() {
	moving = false;
	SoundManager::soundManager.playSound("laugh");
	changeAnimation(ROUND_KING_STATE_CHARGE, true);
}

void RoundKing::shoot() {
	moving = false;

	shootTimer = 5; // 5 seconds of shooting at the player
	bulletTimer = 0; // take first shot immediately during shooting Time

	//if damaged or frantic, have a shorter shooting time
	if (aiState != ROUND_KING_PHASE_NORMAL)
		shootTimer = 3;

	changeAnimation(ROUND_KING_STATE_SHOOT, true);
}

void RoundKing::slam() {
	moving = false;
	changeAnimation(ROUND_KING_STATE_SLAM, true);
}

void RoundKing::jumpTelegraph() {
	moving = false;
	frameTimer = 0;
	changeAnimation(ROUND_KING_STATE_JUMP_TELEGRAPH, true);
}

void RoundKing::jump() {
	moving = false;
	frameTimer = 0;
	slideAmount = 100;
	slideAngle = angle;
	changeAnimation(ROUND_KING_STATE_JUMP, true);
}

void RoundKing::die() {
	moving = false;
	changeAnimation(ROUND_KING_STATE_DEAD, true);
	SoundManager::soundManager.playSound("enemyDie");

	// add to our score count
	bossKilled++;
}

void RoundKing::findNearestTarget() {
	// TODO cleaner solution than just copy/pasted code
	// suggestion : make another class to help with targeting entities and make glob, grob, and roundking inherit from it

	target = NULL;
	// find closest target
	for (auto entity = Entity::entities.begin(); entity != Entity::entities.end(); entity++) {
		if ((*entity)->type == "hero" && (*entity)->active) {
			// if found first hero in list then set them as the target fo now
			if (target == NULL) {
				target = (LivingEntity*)(*entity); // if can't cast to LivingEntity, throw casting exception
			}
			else {
				// otherwise, is this other hero closer than the previous target
				if (Entity::distanceBetweenTwoEntities(this, (*entity)) < Entity::distanceBetweenTwoEntities(this, target)) {
					target = (LivingEntity*)(*entity);
				}
			}
		}
	}
}

void RoundKing::changeAnimation(int newState, bool resetFrameToBeginning) {
	state = newState;

	if (state == ROUND_KING_STATE_IDLE)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_IDLE);
	if (state == ROUND_KING_STATE_CHARGE)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_CHARGE);
	if (state == ROUND_KING_STATE_SHOOT)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_SHOOT);
	if (state == ROUND_KING_STATE_SLAM)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_SLAM);
	if (state == ROUND_KING_STATE_JUMP_TELEGRAPH)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_JUMP_TELEGRAPH);
	if (state == ROUND_KING_STATE_JUMP)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_JUMP);
	if (state == ROUND_KING_STATE_DEAD)
		currentAnim = animSet->getAnimation(ROUND_KING_ANIM_DIE);

	if (resetFrameToBeginning)
		currentFrame = currentAnim->getFrame(0);
	else
		currentFrame = currentAnim->getFrame(currentFrame->frameNumber);
}

void RoundKing::updateAnimation() {
	if (currentFrame == NULL || currentAnim == NULL)
		return;

	frameTimer += TimeController::timeController.dT;
	//if frameTimer greater than frame duration;
	if (frameTimer >= currentFrame->duration) {
		// if at the end of animation
		if (currentFrame->frameNumber == currentAnim->getEndFrameNumber()) {
			if (state == ROUND_KING_STATE_CHARGE)
				shoot();
			else if (state == ROUND_KING_STATE_JUMP_TELEGRAPH)
				jump();
			else if (state == ROUND_KING_STATE_SLAM || state == ROUND_KING_STATE_JUMP)
				changeAnimation(ROUND_KING_STATE_IDLE, true);
			else if (state == ROUND_KING_STATE_DEAD) {
				frameTimer = 0;
				// if somehow live again
				if (hp > 0)
					changeAnimation(ROUND_KING_STATE_IDLE, true);
				else
					active = false; // get rid of him in the game loop, bye bye
			}
		}
		else {
			// not end of animation, so move to next frame normally
			currentFrame = currentAnim->getNextFrame(currentFrame);

			// IF THE NEW FRAME IS DEALING DAMAGE, we might want to make sounds
			GroupNumber* damages = (GroupNumber*)GroupBuilder::findGroupByName("damage", currentFrame->frameData);

			//if does damage
			if (damages != NULL && damages->numberOfDataInGroup() > 0) {
				// there is at least one damage value in this group of frames

				//and if it's in slam state
				if (state == ROUND_KING_STATE_SLAM)
					SoundManager::soundManager.playSound("smash");
				else if (state == ROUND_KING_STATE_JUMP) // if in jump state
					SoundManager::soundManager.playSound("crash");
			}
		}
		frameTimer = 0;
	}
}

void RoundKing::updateDamages() {
	// is roundking hitable
	if (active && hp > 0 && invincibleTimer <= 0) {
		for (auto entity = Entity::entities.begin(); entity != Entity::entities.end(); entity++) {
			if ((*entity)->active && (*entity)->type == "hero") {
				//cast entity pointer to livingEntity pointer
				LivingEntity* enemy = (LivingEntity*)(*entity);

				//if enemy is hitting me
				if (enemy->damage > 0 && Entity::checkCollision(collisionBox, enemy->hitBox)) {
					enemy->hitLanded(this);
					// roundking get hurt by player
					hp -= enemy->damage;

					if (hp > 0) {
						SoundManager::soundManager.playSound("enemyHit");
						invincibleTimer = 0.1f;
					}
				}
			}
		}
	}
}<|endoftext|>


<commit_before>#include <osg/PagedLOD>

using namespace osg;

PagedLOD::PagedLOD()
{
    _centerMode = USER_DEFINED_CENTER;
    _radius = -1;
    _numChildrenThatCannotBeExpired = 0;
}

PagedLOD::PagedLOD(const PagedLOD& plod,const CopyOp& copyop):
    LOD(plod,copyop),
    _radius(plod._radius),
    _numChildrenThatCannotBeExpired(plod._numChildrenThatCannotBeExpired),
    _perRangeDataList(plod._perRangeDataList)
{
}

void PagedLOD::traverse(NodeVisitor& nv)
{

    double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
    bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;

    switch(nv.getTraversalMode())
    {
        case(NodeVisitor::TRAVERSE_ALL_CHILDREN):
            std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
            break;
        case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
        {
            float distance = nv.getDistanceToEyePoint(getCenter(),true);

            int lastChildTraversed = -1;
            bool needToLoadChild = false;
            for(unsigned int i=0;i<_rangeList.size();++i)
            {
                if (_rangeList[i].first<=distance && distance<_rangeList[i].second)
                {
                    if (i<_children.size())
                    {
                        if (updateTimeStamp) _perRangeDataList[i]._timeStamp=timeStamp;

                        //std::cout<<"PagedLOD::traverse() - Selecting child "<<i<<std::endl;
                        _children[i]->accept(nv);
                        lastChildTraversed = (int)i;
                    }
                    else
                    {
                        needToLoadChild = true;
                    }
                }
            }

            if (needToLoadChild)
            {
                unsigned int numChildren = _children.size();

                //std::cout<<"PagedLOD::traverse() - falling back "<<std::endl;
                // select the last valid child.
                if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
                {
                    //std::cout<<"    to child "<<numChildren-1<<std::endl;
                    if (updateTimeStamp) _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
                    _children[numChildren-1]->accept(nv);
                }

                // now request the loading of the next unload child.
                if (nv.getDatabaseRequestHandler() && numChildren<_perRangeDataList.size())
                {
                    float priority = (_rangeList[numChildren].second-distance)/(_rangeList[numChildren].second-_rangeList[numChildren].first);
                    //std::cout<<"    requesting child "<<_fileNameList[numChildren]<<" priotity = "<<priority<<std::endl;
                    nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp());
                }

            }

           break;
        }
        default:
            break;
    }
}

bool PagedLOD::computeBound() const
{
    if (_centerMode==USER_DEFINED_CENTER && _radius>=0.0f)
    {
        _bsphere._center = _userDefinedCenter;
        _bsphere._radius = _radius;
        _bsphere_computed = true;

        return true;
    }
    else
    {
        return LOD::computeBound();
    }
}

void PagedLOD::childRemoved(unsigned int pos, unsigned int numChildrenToRemove)
{
    LOD::childRemoved(pos, numChildrenToRemove);
    //std::cout<<"PagedLOD::childRemoved("<<pos<<","<<numChildrenToRemove<<")"<<std::endl;
}

void PagedLOD::childInserted(unsigned int pos)
{
    LOD::childInserted(pos);
    //std::cout<<"PagedLOD::childInserted("<<pos<<")"<<std::endl;
}

void PagedLOD::rangeRemoved(unsigned int pos, unsigned int numChildrenToRemove)
{
    LOD::rangeRemoved(pos, numChildrenToRemove);
    std::cout<<"PagedLOD::rangeRemoved("<<pos<<","<<numChildrenToRemove<<")"<<std::endl;
}

void PagedLOD::rangeInserted(unsigned int pos)
{
    LOD::rangeInserted(pos);
    std::cout<<"PagedLOD::rangeInserted("<<pos<<")"<<std::endl;
    expandPerRangeDataTo(pos);
}

void PagedLOD::expandPerRangeDataTo(unsigned int pos)
{
    if (pos>=_perRangeDataList.size()) _perRangeDataList.resize(pos+1);
}

bool PagedLOD::addChild( Node *child )
{
    if (LOD::addChild(child))
    {
        expandPerRangeDataTo(_children.size());
        return true;
    }
    return false;
}

bool PagedLOD::addChild(Node *child, float min, float max)
{
    if (LOD::addChild(child,min,max))
    {
        expandPerRangeDataTo(_children.size());
        return true;
    }
    return false;
}

bool PagedLOD::addChild(Node *child, float min, float max,const std::string& filename, float priorityOffset, float priorityScale)
{
    if (LOD::addChild(child,min,max))
    {
        setFileName(_children.size()-1,filename);
        setPriorityOffset(_children.size()-1,priorityOffset);
        setPriorityScale(_children.size()-1,priorityScale);
        return true;
    }
    return false;
}

bool PagedLOD::removeChild( Node *child )
{
    // find the child's position.
    unsigned int pos=getChildIndex(child);
    if (pos==_children.size()) return false;

    if (pos<_rangeList.size()) _rangeList.erase(_rangeList.begin()+pos);
    if (pos<_perRangeDataList.size()) _perRangeDataList.erase(_perRangeDataList.begin()+pos);

    return Group::removeChild(child);
}

void PagedLOD::removeExpiredChildren(double expiryTime,NodeList& removedChildren)
{
    for(unsigned int i=_children.size();i>_numChildrenThatCannotBeExpired;)
    {
        --i;
        if (!_perRangeDataList[i]._filename.empty() && _perRangeDataList[i]._timeStamp<expiryTime)
        {
            //std::cout<<"Removing child "<<_children[i].get()<<std::endl;
            removedChildren.push_back(_children[i]);
            Group::removeChild(_children[i].get());
        }
    }
}
<commit_msg>Added code to scale the priority by the offset and scale.<commit_after>#include <osg/PagedLOD>

using namespace osg;

PagedLOD::PagedLOD()
{
    _centerMode = USER_DEFINED_CENTER;
    _radius = -1;
    _numChildrenThatCannotBeExpired = 0;
}

PagedLOD::PagedLOD(const PagedLOD& plod,const CopyOp& copyop):
    LOD(plod,copyop),
    _radius(plod._radius),
    _numChildrenThatCannotBeExpired(plod._numChildrenThatCannotBeExpired),
    _perRangeDataList(plod._perRangeDataList)
{
}

void PagedLOD::traverse(NodeVisitor& nv)
{

    double timeStamp = nv.getFrameStamp()?nv.getFrameStamp()->getReferenceTime():0.0;
    bool updateTimeStamp = nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR;

    switch(nv.getTraversalMode())
    {
        case(NodeVisitor::TRAVERSE_ALL_CHILDREN):
            std::for_each(_children.begin(),_children.end(),NodeAcceptOp(nv));
            break;
        case(NodeVisitor::TRAVERSE_ACTIVE_CHILDREN):
        {
            float distance = nv.getDistanceToEyePoint(getCenter(),true);

            int lastChildTraversed = -1;
            bool needToLoadChild = false;
            for(unsigned int i=0;i<_rangeList.size();++i)
            {
                if (_rangeList[i].first<=distance && distance<_rangeList[i].second)
                {
                    if (i<_children.size())
                    {
                        if (updateTimeStamp) _perRangeDataList[i]._timeStamp=timeStamp;

                        //std::cout<<"PagedLOD::traverse() - Selecting child "<<i<<std::endl;
                        _children[i]->accept(nv);
                        lastChildTraversed = (int)i;
                    }
                    else
                    {
                        needToLoadChild = true;
                    }
                }
            }

            if (needToLoadChild)
            {
                unsigned int numChildren = _children.size();

                //std::cout<<"PagedLOD::traverse() - falling back "<<std::endl;
                // select the last valid child.
                if (numChildren>0 && ((int)numChildren-1)!=lastChildTraversed)
                {
                    //std::cout<<"    to child "<<numChildren-1<<std::endl;
                    if (updateTimeStamp) _perRangeDataList[numChildren-1]._timeStamp=timeStamp;
                    _children[numChildren-1]->accept(nv);
                }

                // now request the loading of the next unload child.
                if (nv.getDatabaseRequestHandler() && numChildren<_perRangeDataList.size())
                {
                    // compute priority from where abouts in the required range the distance falls.
                    float priority = (_rangeList[numChildren].second-distance)/(_rangeList[numChildren].second-_rangeList[numChildren].first);

                    // modify the priority according to the child's priority offset and scale.
                    priority = _perRangeDataList[numChildren]._priorityOffset + priority * _perRangeDataList[numChildren]._priorityScale;

                    //std::cout<<"    requesting child "<<_fileNameList[numChildren]<<" priotity = "<<priority<<std::endl;
                    nv.getDatabaseRequestHandler()->requestNodeFile(_perRangeDataList[numChildren]._filename,this,priority,nv.getFrameStamp());
                }

            }

           break;
        }
        default:
            break;
    }
}

bool PagedLOD::computeBound() const
{
    if (_centerMode==USER_DEFINED_CENTER && _radius>=0.0f)
    {
        _bsphere._center = _userDefinedCenter;
        _bsphere._radius = _radius;
        _bsphere_computed = true;

        return true;
    }
    else
    {
        return LOD::computeBound();
    }
}

void PagedLOD::childRemoved(unsigned int pos, unsigned int numChildrenToRemove)
{
    LOD::childRemoved(pos, numChildrenToRemove);
    //std::cout<<"PagedLOD::childRemoved("<<pos<<","<<numChildrenToRemove<<")"<<std::endl;
}

void PagedLOD::childInserted(unsigned int pos)
{
    LOD::childInserted(pos);
    //std::cout<<"PagedLOD::childInserted("<<pos<<")"<<std::endl;
}

void PagedLOD::rangeRemoved(unsigned int pos, unsigned int numChildrenToRemove)
{
    LOD::rangeRemoved(pos, numChildrenToRemove);
    std::cout<<"PagedLOD::rangeRemoved("<<pos<<","<<numChildrenToRemove<<")"<<std::endl;
}

void PagedLOD::rangeInserted(unsigned int pos)
{
    LOD::rangeInserted(pos);
    std::cout<<"PagedLOD::rangeInserted("<<pos<<")"<<std::endl;
    expandPerRangeDataTo(pos);
}

void PagedLOD::expandPerRangeDataTo(unsigned int pos)
{
    if (pos>=_perRangeDataList.size()) _perRangeDataList.resize(pos+1);
}

bool PagedLOD::addChild( Node *child )
{
    if (LOD::addChild(child))
    {
        expandPerRangeDataTo(_children.size());
        return true;
    }
    return false;
}

bool PagedLOD::addChild(Node *child, float min, float max)
{
    if (LOD::addChild(child,min,max))
    {
        expandPerRangeDataTo(_children.size());
        return true;
    }
    return false;
}

bool PagedLOD::addChild(Node *child, float min, float max,const std::string& filename, float priorityOffset, float priorityScale)
{
    if (LOD::addChild(child,min,max))
    {
        setFileName(_children.size()-1,filename);
        setPriorityOffset(_children.size()-1,priorityOffset);
        setPriorityScale(_children.size()-1,priorityScale);
        return true;
    }
    return false;
}

bool PagedLOD::removeChild( Node *child )
{
    // find the child's position.
    unsigned int pos=getChildIndex(child);
    if (pos==_children.size()) return false;

    if (pos<_rangeList.size()) _rangeList.erase(_rangeList.begin()+pos);
    if (pos<_perRangeDataList.size()) _perRangeDataList.erase(_perRangeDataList.begin()+pos);

    return Group::removeChild(child);
}

void PagedLOD::removeExpiredChildren(double expiryTime,NodeList& removedChildren)
{
    for(unsigned int i=_children.size();i>_numChildrenThatCannotBeExpired;)
    {
        --i;
        if (!_perRangeDataList[i]._filename.empty() && _perRangeDataList[i]._timeStamp<expiryTime)
        {
            //std::cout<<"Removing child "<<_children[i].get()<<std::endl;
            removedChildren.push_back(_children[i]);
            Group::removeChild(_children[i].get());
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef SHARED_PTR_HH_
#define SHARED_PTR_HH_

#include <utility>
#include <type_traits>

template <typename T>
class shared_ptr;

template <typename T>
class enable_shared_from_this;

template <typename T, typename... A>
shared_ptr<T> make_shared(A&&... a);

template <typename T>
shared_ptr<T> make_shared(T&& a);

template <typename T>
shared_ptr<T> make_shared(T& a);

// We want to support two use cases for shared_ptr<T>:
//
//   1. T is any type (primitive or class type)
//
//   2. T is a class type that inherits from enable_shared_from_this<T>.
//
// In the first case, we must wrap T in an object containing the counter,
// since T may be a primitive type and cannot be a base class.
//
// In the second case, we want T to reach the counter through its
// enable_shared_from_this<> base class, so that we can implement
// shared_from_this().
//
// To implement those two conflicting requirements (T alongside its counter;
// T inherits from an object containing the counter) we use std::conditional<>
// and some accessor functions to select between two implementations.

// CRTP from this to enable shared_from_this:
template <typename T>
class enable_shared_from_this {
    long _count;
    using ctor = T;
    T* to_value() { return static_cast<T*>(this); }
    T* to_internal_object() { return static_cast<T*>(this); }
protected:
    enable_shared_from_this& operator=(const enable_shared_from_this&) { return *this; }
    enable_shared_from_this& operator=(enable_shared_from_this&&) { return *this; }
public:
    shared_ptr<T> shared_from_this();
    template <typename X>
    friend class shared_ptr;
};

template <typename T>
struct shared_ptr_no_esft {
    long _count = 0;
    T _value;
    using ctor = shared_ptr_no_esft;

    T* to_value() { return &_value; }
    shared_ptr_no_esft* to_internal_object() { return this; }
    shared_ptr_no_esft() = default;
    shared_ptr_no_esft(const T& x) : _value(x) {}
    shared_ptr_no_esft(T&& x) : _value(std::move(x)) {}
    template <typename... A>
    shared_ptr_no_esft(A&&... a) : _value(std::forward<A>(a)...) {}
    template <typename X>
    friend class shared_ptr;
};

template <typename T>
using shared_ptr_impl
    = std::conditional_t<
        std::is_base_of<enable_shared_from_this<T>, T>::value,
        enable_shared_from_this<T>,
        shared_ptr_no_esft<T>
      >;

template <typename T>
class shared_ptr {
    mutable shared_ptr_impl<T>* _p = nullptr;
private:
    shared_ptr(shared_ptr_impl<T>* p) : _p(p) {
        if (_p) {
            ++_p->_count;
        }
    }
    template <typename... A>
    static shared_ptr make(A&&... a) {
        return shared_ptr(new typename shared_ptr_impl<T>::ctor(std::forward<A>(a)...));
    }
public:
    using element_type = T;

    shared_ptr() = default;
    shared_ptr(const shared_ptr& x) : _p(x._p) {
        if (_p) {
            ++_p->_count;
        }
    }
    shared_ptr(shared_ptr&& x) : _p(x._p) {
        x._p = nullptr;
    }
    ~shared_ptr() {
        if (_p && !--_p->_count) {
            delete _p->to_internal_object();
        }
    }
    shared_ptr& operator=(const shared_ptr& x) {
        if (_p != x._p) {
            this->~shared_ptr();
            new (this) shared_ptr(x);
        }
        return *this;
    }
    shared_ptr& operator=(shared_ptr&& x) {
        if (_p != x._p) {
            this->~shared_ptr();
            new (this) shared_ptr(std::move(x));
        }
        return *this;
    }
    shared_ptr& operator=(T&& x) {
        this->~shared_ptr();
        new (this) shared_ptr(make_shared<T>(std::move(x)));
        return *this;
    }

    T& operator*() const { return *_p->to_value(); }
    T* operator->() const { return _p->to_value(); }
    T* get() const { return _p->to_value(); }

    long int use_count() {
        if (_p) {
            return _p->_count;
        } else {
            return 0;
        }
    }

    operator shared_ptr<const T>() const {
        return shared_ptr<const T>(_p);
    }

    explicit operator bool() const {
        return _p;
    }

    bool owned() const {
        return _p->_count == 1;
    }

    template <typename X, typename... A>
    friend shared_ptr<X> make_shared(A&&...);

    template <typename U>
    friend shared_ptr<U> make_shared(U&&);

    template <typename U>
    friend shared_ptr<U> make_shared(U&);

    template <typename U>
    friend class enable_shared_from_this;
};

template <typename T, typename... A>
inline
shared_ptr<T> make_shared(A&&... a) {
    return shared_ptr<T>::make(std::forward<A>(a)...);
}

template <typename T>
inline
shared_ptr<T> make_shared(T&& a) {
    return shared_ptr<T>::make(std::move(a));
}

template <typename T>
inline
shared_ptr<T> make_shared(T& a) {
    return shared_ptr<T>::make(a);
}

template <typename T>
inline
shared_ptr<T>
enable_shared_from_this<T>::shared_from_this() {
    return shared_ptr<T>(this);
}

#endif /* SHARED_PTR_HH_ */
<commit_msg>shared_ptr: fix uninitialized enable_shared_from_this ref count<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef SHARED_PTR_HH_
#define SHARED_PTR_HH_

#include <utility>
#include <type_traits>

template <typename T>
class shared_ptr;

template <typename T>
class enable_shared_from_this;

template <typename T, typename... A>
shared_ptr<T> make_shared(A&&... a);

template <typename T>
shared_ptr<T> make_shared(T&& a);

template <typename T>
shared_ptr<T> make_shared(T& a);

// We want to support two use cases for shared_ptr<T>:
//
//   1. T is any type (primitive or class type)
//
//   2. T is a class type that inherits from enable_shared_from_this<T>.
//
// In the first case, we must wrap T in an object containing the counter,
// since T may be a primitive type and cannot be a base class.
//
// In the second case, we want T to reach the counter through its
// enable_shared_from_this<> base class, so that we can implement
// shared_from_this().
//
// To implement those two conflicting requirements (T alongside its counter;
// T inherits from an object containing the counter) we use std::conditional<>
// and some accessor functions to select between two implementations.

// CRTP from this to enable shared_from_this:
template <typename T>
class enable_shared_from_this {
    long _count = 0;
    using ctor = T;
    T* to_value() { return static_cast<T*>(this); }
    T* to_internal_object() { return static_cast<T*>(this); }
protected:
    enable_shared_from_this& operator=(const enable_shared_from_this&) { return *this; }
    enable_shared_from_this& operator=(enable_shared_from_this&&) { return *this; }
public:
    shared_ptr<T> shared_from_this();
    template <typename X>
    friend class shared_ptr;
};

template <typename T>
struct shared_ptr_no_esft {
    long _count = 0;
    T _value;
    using ctor = shared_ptr_no_esft;

    T* to_value() { return &_value; }
    shared_ptr_no_esft* to_internal_object() { return this; }
    shared_ptr_no_esft() = default;
    shared_ptr_no_esft(const T& x) : _value(x) {}
    shared_ptr_no_esft(T&& x) : _value(std::move(x)) {}
    template <typename... A>
    shared_ptr_no_esft(A&&... a) : _value(std::forward<A>(a)...) {}
    template <typename X>
    friend class shared_ptr;
};

template <typename T>
using shared_ptr_impl
    = std::conditional_t<
        std::is_base_of<enable_shared_from_this<T>, T>::value,
        enable_shared_from_this<T>,
        shared_ptr_no_esft<T>
      >;

template <typename T>
class shared_ptr {
    mutable shared_ptr_impl<T>* _p = nullptr;
private:
    shared_ptr(shared_ptr_impl<T>* p) : _p(p) {
        if (_p) {
            ++_p->_count;
        }
    }
    template <typename... A>
    static shared_ptr make(A&&... a) {
        return shared_ptr(new typename shared_ptr_impl<T>::ctor(std::forward<A>(a)...));
    }
public:
    using element_type = T;

    shared_ptr() = default;
    shared_ptr(const shared_ptr& x) : _p(x._p) {
        if (_p) {
            ++_p->_count;
        }
    }
    shared_ptr(shared_ptr&& x) : _p(x._p) {
        x._p = nullptr;
    }
    ~shared_ptr() {
        if (_p && !--_p->_count) {
            delete _p->to_internal_object();
        }
    }
    shared_ptr& operator=(const shared_ptr& x) {
        if (_p != x._p) {
            this->~shared_ptr();
            new (this) shared_ptr(x);
        }
        return *this;
    }
    shared_ptr& operator=(shared_ptr&& x) {
        if (_p != x._p) {
            this->~shared_ptr();
            new (this) shared_ptr(std::move(x));
        }
        return *this;
    }
    shared_ptr& operator=(T&& x) {
        this->~shared_ptr();
        new (this) shared_ptr(make_shared<T>(std::move(x)));
        return *this;
    }

    T& operator*() const { return *_p->to_value(); }
    T* operator->() const { return _p->to_value(); }
    T* get() const { return _p->to_value(); }

    long int use_count() {
        if (_p) {
            return _p->_count;
        } else {
            return 0;
        }
    }

    operator shared_ptr<const T>() const {
        return shared_ptr<const T>(_p);
    }

    explicit operator bool() const {
        return _p;
    }

    bool owned() const {
        return _p->_count == 1;
    }

    template <typename X, typename... A>
    friend shared_ptr<X> make_shared(A&&...);

    template <typename U>
    friend shared_ptr<U> make_shared(U&&);

    template <typename U>
    friend shared_ptr<U> make_shared(U&);

    template <typename U>
    friend class enable_shared_from_this;
};

template <typename T, typename... A>
inline
shared_ptr<T> make_shared(A&&... a) {
    return shared_ptr<T>::make(std::forward<A>(a)...);
}

template <typename T>
inline
shared_ptr<T> make_shared(T&& a) {
    return shared_ptr<T>::make(std::move(a));
}

template <typename T>
inline
shared_ptr<T> make_shared(T& a) {
    return shared_ptr<T>::make(a);
}

template <typename T>
inline
shared_ptr<T>
enable_shared_from_this<T>::shared_from_this() {
    return shared_ptr<T>(this);
}

#endif /* SHARED_PTR_HH_ */
<|endoftext|>


<commit_before>#include <stdio.h>

#include <osg/StateSet>
#include <osg/State>
#include <osg/Notify>

#include <osg/AlphaFunc>
#include <osg/Material>
#include <osg/CullFace>
#include <osg/FrontFace>
#include <osg/PolygonMode>
#include <osg/Transparency>
#include <osg/Depth>

using namespace osg;

StateSet::StateSet()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();
}

StateSet::~StateSet()
{
    // note, all attached state attributes will be automatically
    // unreferenced by ref_ptr<> and therefore there is no need to
    // delete the memory manually.
}

int StateSet::compare(const StateSet& rhs) const
{
    // check to see how the modes compare.
    ModeList::const_iterator lhs_mode_itr = _modeList.begin();
    ModeList::const_iterator rhs_mode_itr = rhs._modeList.begin();
    while (lhs_mode_itr!=_modeList.end() && rhs_mode_itr!=rhs._modeList.end())
    {
        if      (lhs_mode_itr->first<rhs_mode_itr->first) return -1;
        else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
        if      (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
        else if (rhs_mode_itr->second<lhs_mode_itr->second) return 1;
        ++lhs_mode_itr;
        ++rhs_mode_itr;
    }
    if (lhs_mode_itr==_modeList.end())
    {
        if (rhs_mode_itr!=rhs._modeList.end()) return -1;
    }
    else if (rhs_mode_itr == rhs._modeList.end()) return 1;

    // we've got here so modes must be equal...

    // now check to see how the attributes compare.
    AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
    AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
    while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
    {
        if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
        else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
        if      (lhs_attr_itr->second.first<rhs_attr_itr->second.first) return -1;
        else if (rhs_attr_itr->second.first<lhs_attr_itr->second.first) return 1;
        if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
        else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
        ++lhs_attr_itr;
        ++rhs_attr_itr;
    }
    if (lhs_attr_itr==_attributeList.end())
    {
        if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
    }
    else if (rhs_attr_itr == rhs._attributeList.end()) return 1;

    return 0;
}

void StateSet::setGlobalDefaults()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();

    setMode(GL_LIGHTING,StateAttribute::OFF);
    setMode(GL_FOG,StateAttribute::OFF);
    setMode(GL_POINT_SMOOTH,StateAttribute::OFF);

    setMode(GL_TEXTURE_2D,StateAttribute::OFF);

    setMode(GL_TEXTURE_GEN_S,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_T,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_R,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_Q,StateAttribute::OFF);

    setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
    setAttributeAndModes(new CullFace,StateAttribute::ON);
    setAttributeAndModes(new FrontFace,StateAttribute::ON);

    Material *material       = new Material;
    material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
    setAttributeAndModes(material,StateAttribute::ON);

    setAttributeAndModes(new PolygonMode,StateAttribute::OFF);
    setAttributeAndModes(new Transparency,StateAttribute::OFF);

    setAttributeAndModes(new Depth,StateAttribute::ON);
}

void StateSet::setAllToInherit()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();

    _modeList.clear();
    _attributeList.clear();
}

void StateSet::setMode(const StateAttribute::GLMode mode, const StateAttribute::GLModeValue value)
{
    if ((value&StateAttribute::INHERIT)) setModeToInherit(mode);
    else _modeList[mode] = value;
}

void StateSet::setModeToInherit(const StateAttribute::GLMode mode)
{
    ModeList::iterator itr = _modeList.find(mode);
    if (itr!=_modeList.end())
    {
        _modeList.erase(itr);
    }
}

const StateAttribute::GLModeValue StateSet::getMode(const StateAttribute::GLMode mode) const
{
    ModeList::const_iterator itr = _modeList.find(mode);
    if (itr!=_modeList.end())
    {
        return itr->second;
    }
    else
        return StateAttribute::INHERIT;
}

void StateSet::setAttribute(StateAttribute *attribute, const StateAttribute::OverrideValue value)
{
    if (attribute)
    {
        if ((value&StateAttribute::INHERIT)) setAttributeToInherit(attribute->getType());
        else _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
    }
}

void StateSet::setAttributeAndModes(StateAttribute *attribute, const StateAttribute::GLModeValue value)
{
    if (attribute)
    {
        _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
        attribute->setStateSetModes(*this,value);
    }
}

void StateSet::setAttributeToInherit(const StateAttribute::Type type)
{
    AttributeList::iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        itr->second.first->setStateSetModes(*this,StateAttribute::INHERIT);
        _attributeList.erase(itr);
    }
}

StateAttribute* StateSet::getAttribute(const StateAttribute::Type type)
{
    AttributeList::iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return itr->second.first.get();
    }
    else
        return NULL;
}

const StateAttribute* StateSet::getAttribute(const StateAttribute::Type type) const
{
    AttributeList::const_iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return itr->second.first.get();
    }
    else
        return NULL;
}

const StateSet::RefAttributePair* StateSet::getAttributePair(const StateAttribute::Type type) const
{
    AttributeList::const_iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return &(itr->second);
    }
    else
        return NULL;
}

void StateSet::compile(State& state) const
{
    for(AttributeList::const_iterator itr = _attributeList.begin();
        itr!=_attributeList.end();
        ++itr)
    {
        itr->second.first->compile(state);
    }
}

void StateSet::setRenderingHint(const int hint)
{
    _renderingHint = hint;
    // temporary hack to get new render bins working.
    if (_renderingHint==TRANSPARENT_BIN)
    {
        _binMode = USE_RENDERBIN_DETAILS;
        _binNum = 1;
        _binName = "DepthSortedBin";
//        _binName = "RenderBin";
    }
}

void StateSet::setRenderBinDetails(const int binNum,const std::string& binName,const RenderBinMode mode)
{
    _binMode = mode;
    _binNum = binNum;
    _binName = binName;
}

void StateSet::setRendingBinToInherit()
{
    _binMode = INHERIT_RENDERBIN_DETAILS;
    _binNum = 0;
    _binName = "";
}
<commit_msg>Changed the ordering of comparing modes and attributes in osg::StateAttribute::compare() as part of an investigration into state sorting.<commit_after>#include <stdio.h>

#include <osg/StateSet>
#include <osg/State>
#include <osg/Notify>

#include <osg/AlphaFunc>
#include <osg/Material>
#include <osg/CullFace>
#include <osg/FrontFace>
#include <osg/PolygonMode>
#include <osg/Transparency>
#include <osg/Depth>

using namespace osg;

StateSet::StateSet()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();
}

StateSet::~StateSet()
{
    // note, all attached state attributes will be automatically
    // unreferenced by ref_ptr<> and therefore there is no need to
    // delete the memory manually.
}

int StateSet::compare(const StateSet& rhs) const
{

    // now check to see how the attributes compare.
    AttributeList::const_iterator lhs_attr_itr = _attributeList.begin();
    AttributeList::const_iterator rhs_attr_itr = rhs._attributeList.begin();
    while (lhs_attr_itr!=_attributeList.end() && rhs_attr_itr!=rhs._attributeList.end())
    {
        if      (lhs_attr_itr->first<rhs_attr_itr->first) return -1;
        else if (rhs_attr_itr->first<lhs_attr_itr->first) return 1;
        if      (lhs_attr_itr->second.first<rhs_attr_itr->second.first) return -1;
        else if (rhs_attr_itr->second.first<lhs_attr_itr->second.first) return 1;
        if      (lhs_attr_itr->second.second<rhs_attr_itr->second.second) return -1;
        else if (rhs_attr_itr->second.second<lhs_attr_itr->second.second) return 1;
        ++lhs_attr_itr;
        ++rhs_attr_itr;
    }
    if (lhs_attr_itr==_attributeList.end())
    {
        if (rhs_attr_itr!=rhs._attributeList.end()) return -1;
    }
    else if (rhs_attr_itr == rhs._attributeList.end()) return 1;

    // we've got here so attributes must be equal...

    // check to see how the modes compare.

    ModeList::const_iterator lhs_mode_itr = _modeList.begin();
    ModeList::const_iterator rhs_mode_itr = rhs._modeList.begin();
    while (lhs_mode_itr!=_modeList.end() && rhs_mode_itr!=rhs._modeList.end())
    {
        if      (lhs_mode_itr->first<rhs_mode_itr->first) return -1;
        else if (rhs_mode_itr->first<lhs_mode_itr->first) return 1;
        if      (lhs_mode_itr->second<rhs_mode_itr->second) return -1;
        else if (rhs_mode_itr->second<lhs_mode_itr->second) return 1;
        ++lhs_mode_itr;
        ++rhs_mode_itr;
    }
    if (lhs_mode_itr==_modeList.end())
    {
        if (rhs_mode_itr!=rhs._modeList.end()) return -1;
    }
    else if (rhs_mode_itr == rhs._modeList.end()) return 1;

    return 0;
}

void StateSet::setGlobalDefaults()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();

    setMode(GL_LIGHTING,StateAttribute::OFF);
    setMode(GL_FOG,StateAttribute::OFF);
    setMode(GL_POINT_SMOOTH,StateAttribute::OFF);

    setMode(GL_TEXTURE_2D,StateAttribute::OFF);

    setMode(GL_TEXTURE_GEN_S,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_T,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_R,StateAttribute::OFF);
    setMode(GL_TEXTURE_GEN_Q,StateAttribute::OFF);

    setAttributeAndModes(new AlphaFunc,StateAttribute::OFF);
    setAttributeAndModes(new CullFace,StateAttribute::ON);
    setAttributeAndModes(new FrontFace,StateAttribute::ON);

    Material *material       = new Material;
    material->setColorMode(Material::AMBIENT_AND_DIFFUSE);
    setAttributeAndModes(material,StateAttribute::ON);

    setAttributeAndModes(new PolygonMode,StateAttribute::OFF);
    setAttributeAndModes(new Transparency,StateAttribute::OFF);

    setAttributeAndModes(new Depth,StateAttribute::ON);
}

void StateSet::setAllToInherit()
{
    _renderingHint = DEFAULT_BIN;

    setRendingBinToInherit();

    _modeList.clear();
    _attributeList.clear();
}

void StateSet::setMode(const StateAttribute::GLMode mode, const StateAttribute::GLModeValue value)
{
    if ((value&StateAttribute::INHERIT)) setModeToInherit(mode);
    else _modeList[mode] = value;
}

void StateSet::setModeToInherit(const StateAttribute::GLMode mode)
{
    ModeList::iterator itr = _modeList.find(mode);
    if (itr!=_modeList.end())
    {
        _modeList.erase(itr);
    }
}

const StateAttribute::GLModeValue StateSet::getMode(const StateAttribute::GLMode mode) const
{
    ModeList::const_iterator itr = _modeList.find(mode);
    if (itr!=_modeList.end())
    {
        return itr->second;
    }
    else
        return StateAttribute::INHERIT;
}

void StateSet::setAttribute(StateAttribute *attribute, const StateAttribute::OverrideValue value)
{
    if (attribute)
    {
        if ((value&StateAttribute::INHERIT)) setAttributeToInherit(attribute->getType());
        else _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
    }
}

void StateSet::setAttributeAndModes(StateAttribute *attribute, const StateAttribute::GLModeValue value)
{
    if (attribute)
    {
        _attributeList[attribute->getType()] = RefAttributePair(attribute,value&StateAttribute::OVERRIDE);
        attribute->setStateSetModes(*this,value);
    }
}

void StateSet::setAttributeToInherit(const StateAttribute::Type type)
{
    AttributeList::iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        itr->second.first->setStateSetModes(*this,StateAttribute::INHERIT);
        _attributeList.erase(itr);
    }
}

StateAttribute* StateSet::getAttribute(const StateAttribute::Type type)
{
    AttributeList::iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return itr->second.first.get();
    }
    else
        return NULL;
}

const StateAttribute* StateSet::getAttribute(const StateAttribute::Type type) const
{
    AttributeList::const_iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return itr->second.first.get();
    }
    else
        return NULL;
}

const StateSet::RefAttributePair* StateSet::getAttributePair(const StateAttribute::Type type) const
{
    AttributeList::const_iterator itr = _attributeList.find(type);
    if (itr!=_attributeList.end())
    {
        return &(itr->second);
    }
    else
        return NULL;
}

void StateSet::compile(State& state) const
{
    for(AttributeList::const_iterator itr = _attributeList.begin();
        itr!=_attributeList.end();
        ++itr)
    {
        itr->second.first->compile(state);
    }
}

void StateSet::setRenderingHint(const int hint)
{
    _renderingHint = hint;
    // temporary hack to get new render bins working.
    if (_renderingHint==TRANSPARENT_BIN)
    {
        _binMode = USE_RENDERBIN_DETAILS;
        _binNum = 1;
        _binName = "DepthSortedBin";
//        _binName = "RenderBin";
    }
}

void StateSet::setRenderBinDetails(const int binNum,const std::string& binName,const RenderBinMode mode)
{
    _binMode = mode;
    _binNum = binNum;
    _binName = binName;
}

void StateSet::setRendingBinToInherit()
{
    _binMode = INHERIT_RENDERBIN_DETAILS;
    _binNum = 0;
    _binName = "";
}
<|endoftext|>


<commit_before>
/*

    poedit, a wxWindows i18n catalogs editor

    ---------------
      edapp.cpp

      Application class

      (c) Vaclav Slavik, 1999

*/

#ifdef __GNUG__
#pragma implementation
#endif

#include <wx/wxprec.h>

#include <wx/wx.h>
#include <wx/config.h>
#include <wx/fs_zip.h>
#include <wx/image.h>
#include <wx/log.h>
#include <wx/xrc/xmlres.h>
#include <wx/xrc/xh_all.h>

#include "edapp.h"
#include "edframe.h"
#include "manager.h"
#include "prefsdlg.h"

IMPLEMENT_APP(poEditApp);

wxString poEditApp::GetAppPath() const
{
#if defined(__UNIX__)
    wxString home;
    if (!wxGetEnv(_T("POEDIT_PREFIX"), &home))
        home = POEDIT_PREFIX;
    return home;
#elif defined(__WXMSW__)
    wxString path = wxConfigBase::Get()->Read(_T("application_path"), wxEmptyString);
    if (!path)
    {
        wxLogError(_("poEdit installation is broken, cannot find application's home directory."));
        path = _T(".");
    }
    return path;
#else
#error "Unsupported platform!"
#endif
}

wxString poEditApp::GetAppVersion() const
{
    return _T("1.1.5");
}

#ifdef __UNIX__
#define CFG_FILE (home + _T(".poedit/config"))
#else
#define CFG_FILE wxEmptyString
#endif

bool poEditApp::OnInit()
{
#ifdef __UNIX__
    wxString home = wxGetHomeDir() + _T("/");

    // create poEdit cfg dir, move ~/.poedit to ~/.poedit/config
    // (upgrade from older versions of poEdit which used ~/.poedit file)
    if (!wxDirExists(home + _T(".poedit")))
    {
        if (wxFileExists(home + _T(".poedit")))
            wxRenameFile(home + _T(".poedit"), home + _T(".poedit2"));
        wxMkdir(home + _T(".poedit"));
        if (wxFileExists(home + _T(".poedit2")))
            wxRenameFile(home + _T(".poedit2"), home + _T(".poedit/config"));
    }
#endif

    SetVendorName(_T("Vaclav Slavik"));
    SetAppName(_T("poedit"));
    wxConfigBase::Set(
        new wxConfig(wxEmptyString, wxEmptyString, CFG_FILE, wxEmptyString,
                     wxCONFIG_USE_GLOBAL_FILE | wxCONFIG_USE_LOCAL_FILE));
    wxConfigBase::Get()->SetExpandEnvVars(false);

    wxImage::AddHandler(new wxGIFHandler);
    wxFileSystem::AddHandler(new wxZipFSHandler);

    wxTheXmlResource->InitAllHandlers();
    wxTheXmlResource->Load(GetAppPath() + _T("/share/poedit/resources.zip"));

    SetDefaultCfg(wxConfig::Get());

    if (wxConfig::Get()->Read(_T("translator_name"), _T("nothing")) == _T("nothing"))
    {
        wxMessageBox(_("This is first time you run poEdit.\n"
                       "Please fill in your name and e-mail address.\n"
                       "(This information is used only in catalogs headers)"), _("Setup"),
                       wxOK | wxICON_INFORMATION);

        PreferencesDialog dlg;
        dlg.TransferTo(wxConfig::Get());
        if (dlg.ShowModal() == wxID_OK)
            dlg.TransferFrom(wxConfig::Get());
    }

    if (argc <= 1 && wxConfig::Get()->Read(_T("manager_startup"), (long)false))
        ManagerFrame::Create()->Show(true);
    else
        poEditFrame::Create(argc > 1 ? argv[1] : wxEmptyString);

    return true;
}

void poEditApp::SetDefaultCfg(wxConfigBase *cfg)
{
    if (cfg->Read(_T("version"), wxEmptyString) == GetAppVersion()) return;

    if (cfg->Read(_T("Parsers/List"), wxEmptyString).IsEmpty())
    {
        cfg->Write(_T("Parsers/List"), _T("C/C++"));

        cfg->Write(_T("Parsers/C_C++/Extensions"),
                   _T("*.c;*.cpp;*.h;*.hpp;*.cc;*.C;*.cxx;*.hxx"));
        cfg->Write(_T("Parsers/C_C++/Command"),
                   _T("xgettext --force-po -C -o %o %K %F"));
        cfg->Write(_T("Parsers/C_C++/KeywordItem"),
                   _T("-k%k"));
        cfg->Write(_T("Parsers/C_C++/FileItem"),
                   _T("%f"));
    }

    if (cfg->Read(_T("TM/database_path"), wxEmptyString).IsEmpty())
    {
        wxString dbpath;
#if defined(__UNIX__)
        dbpath = wxGetHomeDir() + _T("/.poedit/tm");
#elif defined(__WXMSW__)
        // VS: this distinguishes between NT and Win9X systems -- the former
        //     has users' home directories while on the latter wxGetHomeDir
        //     will return path of the executable
        if (wxGetHomeDir().IsSameAs(GetAppPath() + _T("\\bin"), false))
            dbpath = GetAppPath() + _T("\\share\\poedit\\tm");
        else
            dbpath = wxGetHomeDir() + _T("\\poedit_tm");
#endif
        cfg->Write(_T("TM/database_path"), dbpath);
    }

    if (cfg->Read(_T("TM/search_paths"), wxEmptyString).IsEmpty())
    {
        wxString paths;
#if defined(__UNIX__)
        paths = wxGetHomeDir() + _T(":/usr/share/locale:/usr/local/share/locale");
#elif defined(__WXMSW__)
        paths = _T("C:");
#endif
        cfg->Write(_T("TM/search_paths"), paths);
    }

    cfg->Write(_T("version"), GetAppVersion());
}
<commit_msg>error message if poEdit cannot find resources.zip<commit_after>
/*

    poedit, a wxWindows i18n catalogs editor

    ---------------
      edapp.cpp

      Application class

      (c) Vaclav Slavik, 1999

*/

#ifdef __GNUG__
#pragma implementation
#endif

#include <wx/wxprec.h>

#include <wx/wx.h>
#include <wx/config.h>
#include <wx/fs_zip.h>
#include <wx/image.h>
#include <wx/log.h>
#include <wx/xrc/xmlres.h>
#include <wx/xrc/xh_all.h>

#include "edapp.h"
#include "edframe.h"
#include "manager.h"
#include "prefsdlg.h"

IMPLEMENT_APP(poEditApp);

wxString poEditApp::GetAppPath() const
{
#if defined(__UNIX__)
    wxString home;
    if (!wxGetEnv(_T("POEDIT_PREFIX"), &home))
        home = POEDIT_PREFIX;
    return home;
#elif defined(__WXMSW__)
    wxString path = wxConfigBase::Get()->Read(_T("application_path"), wxEmptyString);
    if (!path)
    {
        wxLogError(_("poEdit installation is broken, cannot find application's home directory."));
        path = _T(".");
    }
    return path;
#else
#error "Unsupported platform!"
#endif
}

wxString poEditApp::GetAppVersion() const
{
    return _T("1.1.5");
}

#ifdef __UNIX__
#define CFG_FILE (home + _T(".poedit/config"))
#else
#define CFG_FILE wxEmptyString
#endif

bool poEditApp::OnInit()
{
#ifdef __UNIX__
    wxString home = wxGetHomeDir() + _T("/");

    // create poEdit cfg dir, move ~/.poedit to ~/.poedit/config
    // (upgrade from older versions of poEdit which used ~/.poedit file)
    if (!wxDirExists(home + _T(".poedit")))
    {
        if (wxFileExists(home + _T(".poedit")))
            wxRenameFile(home + _T(".poedit"), home + _T(".poedit2"));
        wxMkdir(home + _T(".poedit"));
        if (wxFileExists(home + _T(".poedit2")))
            wxRenameFile(home + _T(".poedit2"), home + _T(".poedit/config"));
    }
#endif

    SetVendorName(_T("Vaclav Slavik"));
    SetAppName(_T("poedit"));
    wxConfigBase::Set(
        new wxConfig(wxEmptyString, wxEmptyString, CFG_FILE, wxEmptyString,
                     wxCONFIG_USE_GLOBAL_FILE | wxCONFIG_USE_LOCAL_FILE));
    wxConfigBase::Get()->SetExpandEnvVars(false);

    wxImage::AddHandler(new wxGIFHandler);
    wxFileSystem::AddHandler(new wxZipFSHandler);

    wxString resPath = GetAppPath() + _T("/share/poedit/resources.zip");
    if (!wxFileExists(resPath))
    {
        wxString msg;

#ifdef __UNIX__
        msg.Printf(_("Cannot find resources file '%s'!\n"
                     "poEdit was configured to be installed in '%s'.\n"
                     "You may try to set POEDIT_PREFIX environment variable to point\n"
                     "to the location where you installed poEdit."),
                     resPath.c_str(), GetAppPath().c_str());
#else
        msg.Printf(_("Cannot find resources file '%s'!\n"
                     "Please reinstall poEdit."),
                     resPath.c_str());
#endif
        wxMessageBox(msg, _("poEdit Error"), wxOK | wxICON_ERROR);
        return false;
    }
    else
    {
        wxTheXmlResource->InitAllHandlers();
        wxTheXmlResource->Load(resPath);
    }

    SetDefaultCfg(wxConfig::Get());

    if (wxConfig::Get()->Read(_T("translator_name"), _T("nothing")) == _T("nothing"))
    {
        wxMessageBox(_("This is first time you run poEdit.\n"
                       "Please fill in your name and e-mail address.\n"
                       "(This information is used only in catalogs headers)"), _("Setup"),
                       wxOK | wxICON_INFORMATION);

        PreferencesDialog dlg;
        dlg.TransferTo(wxConfig::Get());
        if (dlg.ShowModal() == wxID_OK)
            dlg.TransferFrom(wxConfig::Get());
    }

    if (argc <= 1 && wxConfig::Get()->Read(_T("manager_startup"), (long)false))
        ManagerFrame::Create()->Show(true);
    else
        poEditFrame::Create(argc > 1 ? argv[1] : wxEmptyString);

    return true;
}

void poEditApp::SetDefaultCfg(wxConfigBase *cfg)
{
    if (cfg->Read(_T("version"), wxEmptyString) == GetAppVersion()) return;

    if (cfg->Read(_T("Parsers/List"), wxEmptyString).IsEmpty())
    {
        cfg->Write(_T("Parsers/List"), _T("C/C++"));

        cfg->Write(_T("Parsers/C_C++/Extensions"),
                   _T("*.c;*.cpp;*.h;*.hpp;*.cc;*.C;*.cxx;*.hxx"));
        cfg->Write(_T("Parsers/C_C++/Command"),
                   _T("xgettext --force-po -C -o %o %K %F"));
        cfg->Write(_T("Parsers/C_C++/KeywordItem"),
                   _T("-k%k"));
        cfg->Write(_T("Parsers/C_C++/FileItem"),
                   _T("%f"));
    }

    if (cfg->Read(_T("TM/database_path"), wxEmptyString).IsEmpty())
    {
        wxString dbpath;
#if defined(__UNIX__)
        dbpath = wxGetHomeDir() + _T("/.poedit/tm");
#elif defined(__WXMSW__)
        // VS: this distinguishes between NT and Win9X systems -- the former
        //     has users' home directories while on the latter wxGetHomeDir
        //     will return path of the executable
        if (wxGetHomeDir().IsSameAs(GetAppPath() + _T("\\bin"), false))
            dbpath = GetAppPath() + _T("\\share\\poedit\\tm");
        else
            dbpath = wxGetHomeDir() + _T("\\poedit_tm");
#endif
        cfg->Write(_T("TM/database_path"), dbpath);
    }

    if (cfg->Read(_T("TM/search_paths"), wxEmptyString).IsEmpty())
    {
        wxString paths;
#if defined(__UNIX__)
        paths = wxGetHomeDir() + _T(":/usr/share/locale:/usr/local/share/locale");
#elif defined(__WXMSW__)
        paths = _T("C:");
#endif
        cfg->Write(_T("TM/search_paths"), paths);
    }

    cfg->Write(_T("version"), GetAppVersion());
}
<|endoftext|>


<commit_before>/* Tone.cpp

 A Tone Generator Library

 Written by Brett Hagman

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This 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
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 Version Modified By Date     Comments
 ------- ----------- -------- --------
 0001    B Hagman    09/08/02 Initial coding
 0002    B Hagman    09/08/18 Multiple pins
 0003    B Hagman    09/08/18 Moved initialization from constructor to begin()
 0004    B Hagman    09/09/26 Fixed problems with ATmega8
 0005    B Hagman    09/11/23 Scanned prescalars for best fit on 8 bit timers
 09/11/25 Changed pin toggle method to XOR
 09/11/25 Fixed timer0 from being excluded
 0006    D Mellis    09/12/29 Replaced objects with functions
 0007    M Sproul    10/08/29 Changed #ifdefs from cpu to register
 0008    S Kanemoto  12/06/22 Fixed for Leonardo by @maris_HY
 *************************************************/

#include "Arduino.h"
#include "pins_arduino.h"

/*
static int8_t toneBegin(uint8_t _pin) {
    //TODO implement tone
    return 0;
}
*/

void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) {
    //TODO implement tone
}

void noTone(uint8_t _pin) {
    //TODO implement tone
}
<commit_msg>Add tone functionality<commit_after>/*
  Tone.cpp

  A Tone Generator Library for the ESP8266

  Copyright (c) 2016 Ben Pirt. All rights reserved.
  This file is part of the esp8266 core for Arduino environment.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "Arduino.h"
#include "pins_arduino.h"

#define AVAILABLE_TONE_PINS 1
const uint8_t tone_timers[] = { 1 };
static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255, };
static long toggle_counts[AVAILABLE_TONE_PINS] = { 0, };
#define T1INDEX 0

void t1IntHandler();

static int8_t toneBegin(uint8_t _pin) {
  int8_t _index = -1;

  // if we're already using the pin, reuse it.
  for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
    if (tone_pins[i] == _pin) {
      return i;
    }
  }

  // search for an unused timer.
  for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
    if (tone_pins[i] == 255) {
      tone_pins[i] = _pin;
      _index = i;
      break;
    }
  }

  return _index;
}

// frequency (in hertz) and duration (in milliseconds).
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) {
  int8_t _index;

  _index = toneBegin(_pin);

  if (_index >= 0) {
    // Set the pinMode as OUTPUT
    pinMode(_pin, OUTPUT);

    // Calculate the toggle count
    if (duration > 0) {
      toggle_counts[_index] = 2 * frequency * duration / 1000;
    } else {
      toggle_counts[_index] = -1;
    }

    // set up the interrupt frequency
    switch (tone_timers[_index]) {
      case 0:
        // Not currently supported
        break;

      case 1:
        timer1_disable();
        timer1_isr_init();
        timer1_attachInterrupt(t1IntHandler);
        timer1_enable(TIM_DIV1, TIM_EDGE, TIM_LOOP);
        timer1_write((clockCyclesPerMicrosecond() * 500000) / frequency);
        break;
    }
  }
}

void disableTimer(uint8_t _index) {
  tone_pins[_index] = 255;

  switch (tone_timers[_index]) {
    case 0:
      // Not currently supported
      break;

    case 1:
      timer1_disable();
      break;
  }
}

void noTone(uint8_t _pin) {
  for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
    if (tone_pins[i] == _pin) {
      tone_pins[i] = 255;
      disableTimer(i);
      break;
    }
  }
  digitalWrite(_pin, LOW);
}

ICACHE_RAM_ATTR void t1IntHandler() {
  if (toggle_counts[T1INDEX] != 0){
    // toggle the pin
    digitalWrite(tone_pins[T1INDEX], toggle_counts[T1INDEX] % 2);
    toggle_counts[T1INDEX]--;
    // handle the case of indefinite duration
    if (toggle_counts[T1INDEX] < -2){
      toggle_counts[T1INDEX] = -1;
    }
  }else{
    disableTimer(T1INDEX);
    digitalWrite(tone_pins[T1INDEX], LOW);
  }
}
<|endoftext|>