<commit_before>/*
    Copyright 2013 KU Leuven, Dept. Electrical Engineering, Medical Image Computing
    Herestraat 49 box 7003, 3000 Leuven, Belgium

    Written by Daan Christiaens, 06/06/13.

    This file is part of the Global Tractography module for MRtrix.

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

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

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "mhsampler.h"

#include "math/math.h"

namespace MR {
  namespace DWI {
    namespace Tractography {
      namespace GT {

        MHSampler::MHSampler(const Image::Info &dwi, Properties &p, Stats &s, ParticleGrid &pgrid,
                             EnergyComputer* e, Image::BufferPreload<bool>* m)
          : props(p), stats(s), pGrid(pgrid), E(e), T(dwi), sigpos(Particle::L / 8.), sigdir(0.2)
        {
          lock = new SpatialLock<>(5*Particle::L);  // FIXME take voxel size into account for setting lock threshold.
          if (m) {
            T = Image::Transform(*m);
            dims[0] = m->dim(0);
            dims[1] = m->dim(1);
            dims[2] = m->dim(2);
            mask = new Image::BufferPreload<bool>::voxel_type(*m);
          }
          else {
            dims[0] = dwi.dim(0);
            dims[1] = dwi.dim(1);
            dims[2] = dwi.dim(2);
          }
        }

        // RUNTIME METHODS --------------------------------------------------------------

        void MHSampler::execute()
        {
          do {
            next();
          } while (stats.next());

        }

        void MHSampler::next()
        {
          float p = rng.uniform();
          float s = props.p_birth;
          if (p < s)
            return birth();
          s += props.p_death;
          if (p < s)
            return death();
          s += props.p_shift;
          if (p < s)
            return randshift();
          s += props.p_optshift;
          if (p < s)
            return optshift();
          s += props.p_connect;
          if (p < s)
            return connect();
        }

        // PROPOSAL DISTRIBUTIONS -------------------------------------------------------

        void MHSampler::birth()
        {
          //TRACE;
          stats.incN('b');

          Point_t pos;
          do {
            pos = getRandPosInMask();
          } while (! lock->lockIfNotLocked(pos));
          Point_t dir = getRandDir();

          double dE = E->stageAdd(pos, dir);
          double R = std::exp(-dE) * props.density / (pGrid.getTotalCount()+1) * props.p_death / props.p_birth;
          if (R > rng.uniform()) {
            E->acceptChanges();
            pGrid.add(pos, dir);
            stats.incNa('b');
          }
          else {
            E->clearChanges();
          }
          lock->unlock(pos);
        }

        void MHSampler::death()
        {
          //TRACE;
          stats.incN('d');

          unsigned int idx;
          Particle* par;
           do {
            par = pGrid.getRandom(idx);
            if (par == NULL || par->hasPredecessor() || par->hasSuccessor())
              return;
          } while (! lock->lockIfNotLocked(par->getPosition()));
          Point_t pos0 = par->getPosition();

          double dE = E->stageRemove(par);
          double R = std::exp(-dE) * pGrid.getTotalCount() / props.density * props.p_birth / props.p_death;
          if (R > rng.uniform()) {
            E->acceptChanges();
            pGrid.remove(idx);
            stats.incNa('d');
          }
          else {
            E->clearChanges();
          }

          lock->unlock(pos0);
        }

        void MHSampler::randshift()
        {
          //TRACE;
          stats.incN('r');

          unsigned int idx;
          Particle* par;
          do {
            par = pGrid.getRandom(idx);
            if (par == NULL)
              return;
          } while (! lock->lockIfNotLocked(par->getPosition()));
          Point_t pos0 = par->getPosition();

          Point_t pos, dir;
          moveRandom(par, pos, dir);

          if (!inMask(T.scanner2voxel(pos))) {
            lock->unlock(pos0);
            return;
          }
          double dE = E->stageShift(par, pos, dir);
          double R = exp(-dE);
          if (R > rng.uniform()) {
            E->acceptChanges();
            pGrid.shift(idx, pos, dir);
            stats.incNa('r');
          }
          else {
            E->clearChanges();
          }

          lock->unlock(pos0);
        }

        void MHSampler::optshift()
        {
          //TRACE;
          stats.incN('o');

          unsigned int idx;
          Particle* par;
          do {
            par = pGrid.getRandom(idx);
            if (par == NULL)
              return;
          } while (! lock->lockIfNotLocked(par->getPosition()));
          Point_t pos0 = par->getPosition();

          Point_t pos, dir;
          bool moved = moveOptimal(par, pos, dir);
          if (!moved || !inMask(T.scanner2voxel(pos))) {
            lock->unlock(pos0);
            return;
          }

          double dE = E->stageShift(par, pos, dir);
          double p_prop = calcShiftProb(par, pos, dir);
          double R = exp(-dE) * props.p_shift * p_prop / (props.p_shift * p_prop + props.p_optshift);
          if (R > rng.uniform()) {
            E->acceptChanges();
            pGrid.shift(idx, pos, dir);
            stats.incNa('o');
          }
          else {
            E->clearChanges();
          }

          lock->unlock(pos0);
        }

        void MHSampler::connect()       // TODO Current implementation does not prevent loops.
        {
          //TRACE;
          stats.incN('c');

          unsigned int idx;
          Particle* par;
          do {
            par = pGrid.getRandom(idx);
            if (par == NULL)
              return;
          } while (! lock->lockIfNotLocked(par->getPosition()));
          Point_t pos0 = par->getPosition();
          int alpha0 = (rng.uniform() < 0.5) ? -1 : 1;
          ParticleEnd pe0;
          pe0.par = par;
          pe0.alpha = alpha0;

          ParticleEnd pe2;
          pe2.par = NULL;
          double dE = E->stageConnect(pe0, pe2);
          double R = exp(-dE);
          if (R > rng.uniform()) {
            E->acceptChanges();
            if (pe2.par) {
              if (alpha0 == -1)
                par->connectPredecessor(pe2.par, pe2.alpha);
              else
                par->connectSuccessor(pe2.par, pe2.alpha);
            } else {
              if ((alpha0 == -1) && par->hasPredecessor())
                par->removePredecessor();
              else if ((alpha0 == +1) && par->hasSuccessor())
                par->removeSuccessor();
            }
            stats.incNa('c');
          }
          else {
            E->clearChanges();
          }

          lock->unlock(pos0);
        }

        // SUPPORTING METHODS -----------------------------------------------------------

        Point_t MHSampler::getRandPosInMask()
        {
          Point_t p;
          do {
            p[0] = rng.uniform() * (dims[0]-1);
            p[1] = rng.uniform() * (dims[1]-1);
            p[2] = rng.uniform() * (dims[2]-1);
          } while (!inMask(p));           // FIXME Schrijf dit expliciet uit ifv random integer initialisatie,
          return T.voxel2scanner(p);      // voeg hier dan nog random ruis aan toe. Dan kan je inMask terug ifv
        }                                 // scanner positie schrijven.

        bool MHSampler::inMask(const Point_t p) const
        {
//          if ((p[0] <= -0.5) || (p[0] >= dims[0]-0.5) ||
//              (p[1] <= -0.5) || (p[1] >= dims[1]-0.5) ||
//              (p[2] <= -0.5) || (p[2] >= dims[2]-0.5))
          if ((p[0] <= 0.0) || (p[0] >= dims[0]-1.0) ||
              (p[1] <= 0.0) || (p[1] >= dims[1]-1.0) ||
              (p[2] <= 0.0) || (p[2] >= dims[2]-1.0))
            return false;
          if (mask) {
            (*mask)[0] = std::round<size_t>(p[0]);
            (*mask)[1] = std::round<size_t>(p[1]);
            (*mask)[2] = std::round<size_t>(p[2]);
            return mask->value();
          }
          return true;
        }

        Point_t MHSampler::getRandDir()
        {
          Point_t dir = Point_t(rng.normal(), rng.normal(), rng.normal());
          dir.normalise();
          return dir;
        }

        void MHSampler::moveRandom(const Particle *par, Point_t &pos, Point_t &dir)
        {
          pos = par->getPosition() + Point_t(rng.normal(sigpos), rng.normal(sigpos), rng.normal(sigpos));
          dir = par->getDirection() + Point_t(rng.normal(sigdir), rng.normal(sigdir), rng.normal(sigdir));
          dir.normalise();
        }

        bool MHSampler::moveOptimal(const Particle *par, Point_t &pos, Point_t &dir) const
        {
          // assert(par != NULL)
          if (par->hasPredecessor() && par->hasSuccessor())
          {
            int a1 = (par->getPredecessor()->getPredecessor() == par) ? -1 : 1;
            int a3 = (par->getSuccessor()->getPredecessor() == par) ? -1 : 1;
            pos = (par->getPredecessor()->getEndPoint(a1) + par->getSuccessor()->getEndPoint(a3)) / 2;
            dir = par->getSuccessor()->getPosition() - par->getPredecessor()->getPosition();
            dir.normalise();
            return true;
          }
          else if (par->hasPredecessor())
          {
            int a = (par->getPredecessor()->getPredecessor() == par) ? -1 : 1;
            pos = par->getPredecessor()->getEndPoint(2*a);
            dir = par->getPredecessor()->getDirection() * a;
            return true;
          }
          else if (par->hasSuccessor())
          {
            int a = (par->getSuccessor()->getPredecessor() == par) ? -1 : 1;
            pos = par->getSuccessor()->getEndPoint(2*a);
            dir = par->getSuccessor()->getDirection() * (-a);
            return true;
          }
          else
          {
            return false;
          }
        }

        double MHSampler::calcShiftProb(const Particle *par, const Point_t &pos, const Point_t &dir) const
        {
          Point_t Dpos = par->getPosition() - pos;
          Point_t Ddir = par->getDirection() - dir;
          return gsl_ran_gaussian_pdf(Dpos[0], sigpos) * gsl_ran_gaussian_pdf(Dpos[1], sigpos) * gsl_ran_gaussian_pdf(Dpos[2], sigpos) *
              gsl_ran_gaussian_pdf(Ddir[0], sigdir) * gsl_ran_gaussian_pdf(Ddir[1], sigdir) * gsl_ran_gaussian_pdf(Ddir[2], sigdir);
//	  Point_t Dep1 = par->getEndPoint(-1) - (pos - Particle::L * dir);
//	  Point_t Dep2 = par->getEndPoint(1) - (pos + Particle::L * dir);
//	  double sigma = Particle::L/2;
//	  return gsl_ran_gaussian_pdf(Dep1[0], sigma) * gsl_ran_gaussian_pdf(Dep1[1], sigma) * gsl_ran_gaussian_pdf(Dep1[2], sigma) *
//		 gsl_ran_gaussian_pdf(Dep2[0], sigma) * gsl_ran_gaussian_pdf(Dep2[1], sigma) * gsl_ran_gaussian_pdf(Dep2[2], sigma);
        }

      }
    }
  }
}

<commit_msg>Fix floating-point rounding at the edge of the brain mask.<commit_after>/*
    Copyright 2013 KU Leuven, Dept. Electrical Engineering, Medical Image Computing
    Herestraat 49 box 7003, 3000 Leuven, Belgium

    Written by Daan Christiaens, 06/06/13.

    This file is part of the Global Tractography module for MRtrix.

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

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

    You should have received a copy of the GNU General Public License
    along with MRtrix.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "mhsampler.h"

#include "math/math.h"

namespace MR {
  namespace DWI {
    namespace Tractography {
      namespace GT {

        MHSampler::MHSampler(const Image::Info &dwi, Properties &p, Stats &s, ParticleGrid &pgrid,
                             EnergyComputer* e, Image::BufferPreload<bool>* m)
          : props(p), stats(s), pGrid(pgrid), E(e), T(dwi), sigpos(Particle::L / 8.), sigdir(0.2)
        {
          lock = new SpatialLock<>(5*Particle::L);  // FIXME take voxel size into account for setting lock threshold.
          if (m) {
            T = Image::Transform(*m);
            dims[0] = m->dim(0);
            dims[1] = m->dim(1);
            dims[2] = m->dim(2);
            mask = new Image::BufferPreload<bool>::voxel_type(*m);
          }
          else {
            dims[0] = dwi.dim(0);
            dims[1] = dwi.dim(1);
            dims[2] = dwi.dim(2);
          }
        }

        // RUNTIME METHODS --------------------------------------------------------------

        void MHSampler::execute()
        {
          do {
            next();
          } while (stats.next());

        }

        void MHSampler::next()
        {
          float p = rng.uniform();
          float s = props.p_birth;
          if (p < s)
            return birth();
          s += props.p_death;
          if (p < s)
            return death();
          s += props.p_shift;
          if (p < s)
            return randshift();
          s += props.p_optshift;
          if (p < s)
            return optshift();
          s += props.p_connect;
          if (p < s)
            return connect();
        }

        // PROPOSAL DISTRIBUTIONS -------------------------------------------------------

        void MHSampler::birth()
        {
          //TRACE;
          stats.incN('b');

          Point_t pos;
          do {
            pos = getRandPosInMask();
          } while (! lock->lockIfNotLocked(pos));
          Point_t dir = getRandDir();

          double dE = E->stageAdd(pos, dir);
          double R = std::exp(-dE) * props.density / (pGrid.getTotalCount()+1) * props.p_death / props.p_birth;
          if (R > rng.uniform()) {
            E->acceptChanges();
            pGrid.add(pos, dir);
            stats.incNa('b');
          }
          else {
            E->clearChanges();
          }
          lock->unlock(pos);
        }

        void MHSampler::death()
        {
          //TRACE;
          stats.incN('d');

          unsigned int idx;
          Particle* par;
           do {
            par = pGrid.getRandom(idx);
            if (par == NULL || par->hasPredecessor() || par->hasSuccessor())
              return;
          } while (! lock->lockIfNotLocked(par->getPosition()));
          Point_t pos0 = par->getPosition();

          double dE = E->stageRemove(par);
          double R = std::exp(-dE) * pGrid.getTotalCount() / props.density * props.p_birth / props.p_death;
          if (R > rng.uniform()) {
            E->acceptChanges();
            pGrid.remove(idx);
            stats.incNa('d');
          }
          else {
            E->clearChanges();
          }

          lock->unlock(pos0);
        }

        void MHSampler::randshift()
        {
          //TRACE;
          stats.incN('r');

          unsigned int idx;
          Particle* par;
          do {
            par = pGrid.getRandom(idx);
            if (par == NULL)
              return;
          } while (! lock->lockIfNotLocked(par->getPosition()));
          Point_t pos0 = par->getPosition();

          Point_t pos, dir;
          moveRandom(par, pos, dir);

          if (!inMask(T.scanner2voxel(pos))) {
            lock->unlock(pos0);
            return;
          }
          double dE = E->stageShift(par, pos, dir);
          double R = exp(-dE);
          if (R > rng.uniform()) {
            E->acceptChanges();
            pGrid.shift(idx, pos, dir);
            stats.incNa('r');
          }
          else {
            E->clearChanges();
          }

          lock->unlock(pos0);
        }

        void MHSampler::optshift()
        {
          //TRACE;
          stats.incN('o');

          unsigned int idx;
          Particle* par;
          do {
            par = pGrid.getRandom(idx);
            if (par == NULL)
              return;
          } while (! lock->lockIfNotLocked(par->getPosition()));
          Point_t pos0 = par->getPosition();

          Point_t pos, dir;
          bool moved = moveOptimal(par, pos, dir);
          if (!moved || !inMask(T.scanner2voxel(pos))) {
            lock->unlock(pos0);
            return;
          }

          double dE = E->stageShift(par, pos, dir);
          double p_prop = calcShiftProb(par, pos, dir);
          double R = exp(-dE) * props.p_shift * p_prop / (props.p_shift * p_prop + props.p_optshift);
          if (R > rng.uniform()) {
            E->acceptChanges();
            pGrid.shift(idx, pos, dir);
            stats.incNa('o');
          }
          else {
            E->clearChanges();
          }

          lock->unlock(pos0);
        }

        void MHSampler::connect()       // TODO Current implementation does not prevent loops.
        {
          //TRACE;
          stats.incN('c');

          unsigned int idx;
          Particle* par;
          do {
            par = pGrid.getRandom(idx);
            if (par == NULL)
              return;
          } while (! lock->lockIfNotLocked(par->getPosition()));
          Point_t pos0 = par->getPosition();
          int alpha0 = (rng.uniform() < 0.5) ? -1 : 1;
          ParticleEnd pe0;
          pe0.par = par;
          pe0.alpha = alpha0;

          ParticleEnd pe2;
          pe2.par = NULL;
          double dE = E->stageConnect(pe0, pe2);
          double R = exp(-dE);
          if (R > rng.uniform()) {
            E->acceptChanges();
            if (pe2.par) {
              if (alpha0 == -1)
                par->connectPredecessor(pe2.par, pe2.alpha);
              else
                par->connectSuccessor(pe2.par, pe2.alpha);
            } else {
              if ((alpha0 == -1) && par->hasPredecessor())
                par->removePredecessor();
              else if ((alpha0 == +1) && par->hasSuccessor())
                par->removeSuccessor();
            }
            stats.incNa('c');
          }
          else {
            E->clearChanges();
          }

          lock->unlock(pos0);
        }

        // SUPPORTING METHODS -----------------------------------------------------------

        Point_t MHSampler::getRandPosInMask()
        {
          Point_t p;
          do {
            p[0] = rng.uniform() * (dims[0]-1);
            p[1] = rng.uniform() * (dims[1]-1);
            p[2] = rng.uniform() * (dims[2]-1);
          } while (!inMask(p));           // FIXME Schrijf dit expliciet uit ifv random integer initialisatie,
          return T.voxel2scanner(p);      // voeg hier dan nog random ruis aan toe. Dan kan je inMask terug ifv
        }                                 // scanner positie schrijven.

        bool MHSampler::inMask(const Point_t p) const
        {
          if ((p[0] <= -0.5) || (p[0] >= dims[0]-0.5) ||
              (p[1] <= -0.5) || (p[1] >= dims[1]-0.5) ||
              (p[2] <= -0.5) || (p[2] >= dims[2]-0.5))
//          if ((p[0] <= 0.0) || (p[0] >= dims[0]-1.0) ||
//              (p[1] <= 0.0) || (p[1] >= dims[1]-1.0) ||
//              (p[2] <= 0.0) || (p[2] >= dims[2]-1.0))
            return false;
          if (mask) {
            (*mask)[0] = Math::round<size_t>(p[0]);
            (*mask)[1] = Math::round<size_t>(p[1]);
            (*mask)[2] = Math::round<size_t>(p[2]);
            return mask->value();
          }
          return true;
        }

        Point_t MHSampler::getRandDir()
        {
          Point_t dir = Point_t(rng.normal(), rng.normal(), rng.normal());
          dir.normalise();
          return dir;
        }

        void MHSampler::moveRandom(const Particle *par, Point_t &pos, Point_t &dir)
        {
          pos = par->getPosition() + Point_t(rng.normal(sigpos), rng.normal(sigpos), rng.normal(sigpos));
          dir = par->getDirection() + Point_t(rng.normal(sigdir), rng.normal(sigdir), rng.normal(sigdir));
          dir.normalise();
        }

        bool MHSampler::moveOptimal(const Particle *par, Point_t &pos, Point_t &dir) const
        {
          // assert(par != NULL)
          if (par->hasPredecessor() && par->hasSuccessor())
          {
            int a1 = (par->getPredecessor()->getPredecessor() == par) ? -1 : 1;
            int a3 = (par->getSuccessor()->getPredecessor() == par) ? -1 : 1;
            pos = (par->getPredecessor()->getEndPoint(a1) + par->getSuccessor()->getEndPoint(a3)) / 2;
            dir = par->getSuccessor()->getPosition() - par->getPredecessor()->getPosition();
            dir.normalise();
            return true;
          }
          else if (par->hasPredecessor())
          {
            int a = (par->getPredecessor()->getPredecessor() == par) ? -1 : 1;
            pos = par->getPredecessor()->getEndPoint(2*a);
            dir = par->getPredecessor()->getDirection() * a;
            return true;
          }
          else if (par->hasSuccessor())
          {
            int a = (par->getSuccessor()->getPredecessor() == par) ? -1 : 1;
            pos = par->getSuccessor()->getEndPoint(2*a);
            dir = par->getSuccessor()->getDirection() * (-a);
            return true;
          }
          else
          {
            return false;
          }
        }

        double MHSampler::calcShiftProb(const Particle *par, const Point_t &pos, const Point_t &dir) const
        {
          Point_t Dpos = par->getPosition() - pos;
          Point_t Ddir = par->getDirection() - dir;
          return gsl_ran_gaussian_pdf(Dpos[0], sigpos) * gsl_ran_gaussian_pdf(Dpos[1], sigpos) * gsl_ran_gaussian_pdf(Dpos[2], sigpos) *
              gsl_ran_gaussian_pdf(Ddir[0], sigdir) * gsl_ran_gaussian_pdf(Ddir[1], sigdir) * gsl_ran_gaussian_pdf(Ddir[2], sigdir);
//	  Point_t Dep1 = par->getEndPoint(-1) - (pos - Particle::L * dir);
//	  Point_t Dep2 = par->getEndPoint(1) - (pos + Particle::L * dir);
//	  double sigma = Particle::L/2;
//	  return gsl_ran_gaussian_pdf(Dep1[0], sigma) * gsl_ran_gaussian_pdf(Dep1[1], sigma) * gsl_ran_gaussian_pdf(Dep1[2], sigma) *
//		 gsl_ran_gaussian_pdf(Dep2[0], sigma) * gsl_ran_gaussian_pdf(Dep2[1], sigma) * gsl_ran_gaussian_pdf(Dep2[2], sigma);
        }

      }
    }
  }
}

<|endoftext|>


<commit_before>/*
* Modular Reducer
* (C) 1999-2011 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/reducer.h>

namespace Botan {

/*
* Modular_Reducer Constructor
*/
Modular_Reducer::Modular_Reducer(const BigInt& mod)
   {
   if(mod <= 0)
      throw Invalid_Argument("Modular_Reducer: modulus must be positive");

   m_modulus = mod;
   m_mod_words = m_modulus.sig_words();

   m_modulus_2 = Botan::square(m_modulus);

   m_mu = BigInt::power_of_2(2 * BOTAN_MP_WORD_BITS * m_mod_words) / m_modulus;
   }

/*
* Barrett Reduction
*/
BigInt Modular_Reducer::reduce(const BigInt& x) const
   {
   if(m_mod_words == 0)
      throw Invalid_State("Modular_Reducer: Never initalized");

   const size_t x_sw = x.sig_words();

   if(x_sw < m_mod_words || x.cmp(m_modulus, false) < 0)
      {
      if(x.is_negative())
         return x + m_modulus; // make positive
      return x;
      }
   else if(x.cmp(m_modulus_2, false) < 0)
      {
      secure_vector<word> ws;

      BigInt t1(x.data() + m_mod_words - 1, x_sw - (m_mod_words - 1));

      t1.mul(m_mu, ws);
      t1 >>= (BOTAN_MP_WORD_BITS * (m_mod_words + 1));

      t1.mul(m_modulus, ws);
      t1.mask_bits(BOTAN_MP_WORD_BITS * (m_mod_words + 1));

      t1.rev_sub(x.data(), std::min(x_sw, m_mod_words + 1), ws);

      if(t1.is_negative())
         {
         t1 += BigInt::power_of_2(BOTAN_MP_WORD_BITS * (m_mod_words + 1));
         }

      t1.reduce_below(m_modulus, ws);

      if(x.is_positive())
         return t1;
      else
         return (m_modulus - t1);
      }
   else
      {
      // too big, fall back to normal division
      return (x % m_modulus);
      }
   }

}
<commit_msg>In Barrett avoid creating an unnecessary temp<commit_after>/*
* Modular Reducer
* (C) 1999-2011 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/reducer.h>

namespace Botan {

/*
* Modular_Reducer Constructor
*/
Modular_Reducer::Modular_Reducer(const BigInt& mod)
   {
   if(mod <= 0)
      throw Invalid_Argument("Modular_Reducer: modulus must be positive");

   m_modulus = mod;
   m_mod_words = m_modulus.sig_words();

   m_modulus_2 = Botan::square(m_modulus);

   m_mu = BigInt::power_of_2(2 * BOTAN_MP_WORD_BITS * m_mod_words) / m_modulus;
   }

/*
* Barrett Reduction
*/
BigInt Modular_Reducer::reduce(const BigInt& x) const
   {
   if(m_mod_words == 0)
      throw Invalid_State("Modular_Reducer: Never initalized");

   const size_t x_sw = x.sig_words();

   if(x_sw < m_mod_words || x.cmp(m_modulus, false) < 0)
      {
      if(x.is_negative())
         return x + m_modulus; // make positive
      return x;
      }
   else if(x.cmp(m_modulus_2, false) < 0)
      {
      secure_vector<word> ws;

      BigInt t1(x.data() + m_mod_words - 1, x_sw - (m_mod_words - 1));

      t1.mul(m_mu, ws);
      t1 >>= (BOTAN_MP_WORD_BITS * (m_mod_words + 1));

      t1.mul(m_modulus, ws);
      t1.mask_bits(BOTAN_MP_WORD_BITS * (m_mod_words + 1));

      t1.rev_sub(x.data(), std::min(x_sw, m_mod_words + 1), ws);

      if(t1.is_negative())
         {
         t1 += BigInt::power_of_2(BOTAN_MP_WORD_BITS * (m_mod_words + 1));
         }

      t1.reduce_below(m_modulus, ws);

      if(x.is_negative())
         t1.rev_sub(m_modulus.data(), m_modulus.size(), ws);

      return t1;
      }
   else
      {
      // too big, fall back to normal division
      return (x % m_modulus);
      }
   }

}
<|endoftext|>


<commit_before>/*
 * Open Pixel Control server for Fadecandy
 *
 * Copyright (c) 2013 Micah Elizabeth Scott
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "opcsink.h"
#include "util.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <iostream>

OPCSink::OPCSink(callback_t cb, void *context, bool verbose)
    : mVerbose(verbose), mCallback(cb), mContext(context) {}

void OPCSink::start(struct ev_loop *loop, struct addrinfo *listenAddr)
{
    int sock = socket(PF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket");
        return;
    }

    if (bind(sock, listenAddr->ai_addr, listenAddr->ai_addrlen)) {
        perror("bind");
        return;
    }

    if (listen(sock, 4) < 0) {
        perror("listen");
        return;
    }

    // Get a callback when we're ready to accept a new connection
    ev_io_init(&mIOAccept, cbAccept, sock, EV_READ);
    ev_io_start(loop, &mIOAccept);

    if (mVerbose) {
        struct sockaddr_in *sin = (struct sockaddr_in*) listenAddr->ai_addr;
        std::clog << "Listening on " << inet_ntoa(sin->sin_addr) << ":" << ntohs(sin->sin_port) << "\n";
    }
}

void OPCSink::cbAccept(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
    OPCSink *self = container_of(watcher, OPCSink, mIOAccept);
    struct sockaddr_in clientAddr;
    socklen_t clientAddrLen = sizeof clientAddr;

    int sock = accept(watcher->fd, (struct sockaddr *)&clientAddr, &clientAddrLen);
    if (sock < 0) {
        perror("accept");
        return;
    }

    Client *cli = new Client();
    cli->bufferPos = 0;
    cli->self = self;

    ev_io_init(&cli->ioRead, cbRead, sock, EV_READ);
    ev_io_start(loop, &cli->ioRead);

    if (self->mVerbose) {
        std::clog << "Client connected from " << inet_ntoa(clientAddr.sin_addr) << "\n";
    }
}

void OPCSink::cbRead(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
    Client *cli = container_of(watcher, Client, ioRead);
    OPCSink *self = cli->self;

    int r = recv(watcher->fd, cli->bufferPos + (uint8_t*)&cli->buffer,
        sizeof(cli->buffer) - cli->bufferPos, 0);

    if (r < 0) {
        perror("read error");
        return;
    }

    if (r == 0) {
        // Client disconnecting

        if (self->mVerbose) {
            std::clog << "Client disconnected\n";
        }

        ev_io_stop(loop, watcher);
        delete cli;
        return;
    }

    cli->bufferPos += r;
    if (cli->bufferPos >= offsetof(Message, data)) {
        // We have a header, at least.

        unsigned length = offsetof(Message, data) + cli->buffer.length();
        if (cli->bufferPos >= length) {
            // Complete packet.
            self->mCallback(cli->buffer, self->mContext);

            // Save any part of the following packet we happened to grab.
            memmove(&cli->buffer, length + (uint8_t*)&cli->buffer, cli->bufferPos - length);
            cli->bufferPos -= length;
        }
    }
}
<commit_msg>Socket options, tcp nodelay & reuseaddr<commit_after>/*
 * Open Pixel Control server for Fadecandy
 *
 * Copyright (c) 2013 Micah Elizabeth Scott
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "opcsink.h"
#include "util.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <iostream>

OPCSink::OPCSink(callback_t cb, void *context, bool verbose)
    : mVerbose(verbose), mCallback(cb), mContext(context) {}

void OPCSink::start(struct ev_loop *loop, struct addrinfo *listenAddr)
{
    int sock = socket(PF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket");
        return;
    }

    int arg = 1;
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof arg);

    if (bind(sock, listenAddr->ai_addr, listenAddr->ai_addrlen)) {
        perror("bind");
        return;
    }

    if (listen(sock, 4) < 0) {
        perror("listen");
        return;
    }

    // Get a callback when we're ready to accept a new connection
    ev_io_init(&mIOAccept, cbAccept, sock, EV_READ);
    ev_io_start(loop, &mIOAccept);

    if (mVerbose) {
        struct sockaddr_in *sin = (struct sockaddr_in*) listenAddr->ai_addr;
        std::clog << "Listening on " << inet_ntoa(sin->sin_addr) << ":" << ntohs(sin->sin_port) << "\n";
    }
}

void OPCSink::cbAccept(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
    OPCSink *self = container_of(watcher, OPCSink, mIOAccept);
    struct sockaddr_in clientAddr;
    socklen_t clientAddrLen = sizeof clientAddr;

    int sock = accept(watcher->fd, (struct sockaddr *)&clientAddr, &clientAddrLen);
    if (sock < 0) {
        perror("accept");
        return;
    }

    int arg = 1;
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &arg, sizeof arg);

    Client *cli = new Client();
    cli->bufferPos = 0;
    cli->self = self;

    ev_io_init(&cli->ioRead, cbRead, sock, EV_READ);
    ev_io_start(loop, &cli->ioRead);

    if (self->mVerbose) {
        std::clog << "Client connected from " << inet_ntoa(clientAddr.sin_addr) << "\n";
    }
}

void OPCSink::cbRead(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
    Client *cli = container_of(watcher, Client, ioRead);
    OPCSink *self = cli->self;

    int r = recv(watcher->fd, cli->bufferPos + (uint8_t*)&cli->buffer,
        sizeof(cli->buffer) - cli->bufferPos, 0);

    if (r < 0) {
        perror("read error");
        return;
    }

    if (r == 0) {
        // Client disconnecting

        if (self->mVerbose) {
            std::clog << "Client disconnected\n";
        }

        ev_io_stop(loop, watcher);
        delete cli;
        return;
    }

    cli->bufferPos += r;
    if (cli->bufferPos >= offsetof(Message, data)) {
        // We have a header, at least.

        unsigned length = offsetof(Message, data) + cli->buffer.length();
        if (cli->bufferPos >= length) {
            // Complete packet.
            self->mCallback(cli->buffer, self->mContext);

            // Save any part of the following packet we happened to grab.
            memmove(&cli->buffer, length + (uint8_t*)&cli->buffer, cli->bufferPos - length);
            cli->bufferPos -= length;
        }
    }
}
<|endoftext|>


<commit_before>#include <QCoreApplication>
#include <QtDebug>

#include <iostream>
#include <fstream>
//#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cerrno>
#include <cmath>
#include <thread>
#include <mutex>

#define OUTPUT_FILE "./trials.csv"
#define NUMBER_THREADS 1
#define USE_MULTIPLE_THREADS
// create a mutex that is used to protect the writing of the data to
// the file.
std::mutex writeToFile;

#ifndef M_PI
#define M_PI 3.14159265359
#endif

#define SHOW_PROGRESS
//#define SHOW_INTERMEDIATE
//#define THREAD_DEBUG
#define BASE_DT 0.00001
#define RADIUS 0.06

#ifndef Q_OS_UNIX
double drand48()
{
    return((double)(rand())/((double)RAND_MAX));
}
#endif

void normalDistRand(double stdDev,double* randomNumbers)
    {
        /* Generate a random number in polar coordinates */
        double radius = sqrt(-2.0*log(drand48()));
        double angle = 2.0*M_PI*drand48();
        /* transform the number back into cartesian coordinates */
        randomNumbers[0] = stdDev*radius*sin(angle);
        randomNumbers[1] = stdDev*radius*cos(angle);
    }

void printToCSVFile(double dt, double beta, double g,double tau,
                    double q, double theta, double h,double s,
                    double *x,std::ofstream *fp)
{

    std::lock_guard<std::mutex> guard(writeToFile);  // Make sure that
                                                       // this routine
                                                       // can only
                                                       // access the file once
                                                       // at any one time.

    *fp << dt << ","
        << beta << ","
        << g << ","
        << tau << ","
        << q+1 << ","
        << theta << ","
        << h << ","
        << s << ","
        << 1-h-s << ","
        << x[0] << ","
        << x[1] << ","
        << 1-x[0]-x[1] << ","
        << x[2] << ","
        << x[3] << ","
        << 1-x[2]-x[3]
        << std::endl;

    (*fp).flush();
}

void linear(long steps,
              double a,double gamma,double r,double d,double g,
              double *x,double *y,double *z, double dt,
              int n,
              double beta,double tau,
              std::ofstream *fp,
              int q,
              double h,double s,double *v,double *w, double theta)
    {

        long m=n-1;
        long p=0;
        double B[2];
        int calcRandom=0;

#ifdef THREAD_DEBUG
        std::cout << "My thread id: " << std::this_thread::get_id() << std::endl;
#endif

        // Step through every time step.
        for (long k=0;k<steps;k++)
        {

            // Calculate a new set of random numbers if necessary.
            if(calcRandom==0)
                normalDistRand(sqrt(dt),B); //noise in most recent time step

            //x[0]=y[m]+(y[m]*(gamma-gamma*y[m]+(a-gamma)*z[m])-(g*y[p]/(1-z[p])))*dt
            //x[0]=x[0]+beta*y[m]*(1-y[m])+0.5*beta*y[m]*(1-y[m])*beta*(1-2*y[m])*(B[calcRandom]*B[calcRandom]-dt);

            //Computes the deterministic component for Macroalgae
            x[0] = y[m]+(y[m]*(gamma-gamma*y[m]+(a-gamma)*z[m])-(g*y[p]/(1-z[p])))*dt;

            //Adds in the noise
            //x[0]=x[0]+beta*y[m]*B[calcRandom]+0.5*beta*y[m]*beta*(B[calcRandom]*B[calcRandom]-dt);
            x[0] += beta*y[m]*B[calcRandom]+0.5*beta*beta*y[m]*(B[calcRandom]*B[calcRandom]-dt);

            //Computes the deterministic component for Coral
            x[1] = z[m]+(z[m]*(r-d-(a+r)*y[m]-r*z[m]))*dt;

            x[2] =  v[m]+(v[m]*(gamma-gamma*v[m]+(a-gamma)*w[m])-(g*v[p]/(1-w[p])))*dt;
            x[2] += beta*v[m]*(1-v[m])*B[calcRandom]+0.5*beta*(1-2*v[m])*beta*v[m]*(1-v[m])*(B[calcRandom]*B[calcRandom]-dt);
            x[3] =  w[m]+(w[m]*(r-d-(a+r)*v[m]-r*w[m]))*dt;

            /****************************************************************
                Account for extinction and overgrowing!!
            ****************************************************************/
            for(int i=0;i<4;++i)
                {
                    if(x[i]<0.0)
                        x[i] = 0.0;
                    else if (x[i]>1.0)
                        x[i] = 1.0;
                }

            //Updates delay and cell index
            m=(m+1)%n;
            p=(p+1)%n;
            y[m]=x[0];
            z[m]=x[1];
            v[m]=x[2];
            w[m]=x[3];
            calcRandom = (calcRandom+1)%2; // update which random number to use.

        }

        //printf("%f\t%f\t%f\t%f\t%f\n",dt,beta,tau,x[0],x[1]);
        printToCSVFile(dt,beta,g,tau,q,theta,h,s,x,fp);

 #ifdef SHOW_INTERMEDIATE
        qDebug() << dt << ","
            << beta << ","
            << g << ","
            << tau << ","
            << q+1 << ","
            << h << ","
            << s << ","
            << 1-h-s << ","
            << x[0] << ","
            << x[1] << ","
            << 1-x[0]-x[1] << ","
            << x[2] << ","
            << x[3] << ","
            << 1-x[2]-x[3];
        qDebug() << errno << EDOM << ERANGE;
#endif

    }

/* ****************************************************************
     main

     The main function. Called at the start of the program.
**************************************************************** */
int main(int argc, char *argv[])
{
    QCoreApplication b(argc, argv);

        long steps;    // The number of steps to take in a single simulation.
        double *v,*w,*x,*y,*z;  // The variables used for the state of the system.

        /*
            Define the constants.

            These are the parameters that are used in the operator for the
            differential equations.
         */
        double a    	 = 0.1;
        double g    ;//	 = 0.3;
        double gamma	 = 0.8;
        double r    	 = 1.0;
        double d    	 = 0.44;

        double tau;
        double beta ;//	 = .5;
//        double gZero	 = ((d*a*r+d*d)*(gamma-a))/(r*r);
//        double gOne		 = (gamma*(a+d))/(a+r);
//        double chi		 = r*gamma/(r+a)-gamma+a;					//Intermediate Step
//        double xi		 = -(d*gamma/(r+a)+a);						//Intermediate Step
//        double cbar		 = (-xi-sqrt(xi*xi-4*chi*g))/(2*chi);		//Intermediate Step
//        double coralSaddle		 = 1-cbar;						    //Saddle point value for coral
//        double macroSaddle		 = (r-r*coralSaddle-d)/(r+a);		//Saddle point value for macroalgae

//        long   numberDT;    // The current iteration for the number assocated with the value of dt.
//        double omega	 = sqrt((r*r*(g*g-gZero*gZero))/(d*d));
//        double tauZero	 = (1/omega)*acos(gZero/g);

        double dt        = BASE_DT;          // Set the initial time step
        double final;       // The final time for each simulation.
        long   trials;      // The number of simulations to make.

        final=50.0;  // Set the final time.
        trials=400;   // Set the number of trials to perform.

        // Set the time delay, tau
        //double tau = 0.5;

        // set up the variables for using different approximations on different threads.
        std::thread simulation[NUMBER_THREADS];
        int numberThreads = 0;

        // Sets the seed for the random numbers
#ifdef Q_OS_UNIX
        srand48(time(NULL));
        //qDebug() << "This is a POSIX system!" ;
#else
        srand(time(NULL));
#endif

        // Create a CSV File
        std::ofstream fp;
                //String fileName = "trials-g" + std::toString(g) + "-tau" + std::toString(tau);
        fp.open(OUTPUT_FILE,std::ios::out | std::ios::trunc);

        fp << "dt,beta,g,tau,trial,theta,initMacro,initCoral,initTurf,macroalgae,coral,turf,lgMacro,lgCoral,lgTurf" << std::endl;

        // Allocate the space for the states of the system
        x=(double *) calloc(4,sizeof(double));
        y=(double *) calloc(n,sizeof(double));		//macroalgae for multiplicative noise
        z=(double *) calloc(n,sizeof(double));		//coral for multiplicative noise
        v=(double *) calloc(n,sizeof(double));		//macroalgae for logistic noise
        w=(double *) calloc(n,sizeof(double));		//coral for logistic noise

        for(tau = .2; tau <= .4; tau += .2 ){
        // Determine the number of time steps required to move back to the delay in time.
        // The number of cells needed for the delay (changes with dt)
            int n;
            if(tau != 0)
                n=(int)(tau/BASE_DT+0.5);
            else
                n = 1;

            for(g=.2; g<.8; g += .2) {
                //double omega	 = sqrt((r*r*(g*g-gZero*gZero))/(d*d));
                // double tauZero	 = (1/omega)*acos(gZero/g);

                // Make different approximations for different values of beta.
                for(beta=.2;beta<=1; beta += .2) {

#ifdef SHOW_PROGRESS
                    std::cout << "dt = " << dt << std::endl;
#endif
                        //index = tau/dt;

                        //printf("%i\n",n);
                        steps=(long)(final/dt);

                        for (double theta=0;theta<=M_PI/2;theta+=(M_PI*0.5)*0.025)
                        {

                        // Make an approximation for different initial conditions.
                        // Make an arc through 0 to pi/2 radians from the origin.

                            for (int k=0;k<trials;k++)
                            {
                                y[0] = RADIUS*cos(theta); //initial Macroalgae level
                                z[0] = RADIUS*sin(theta); //initial Coral level
                                v[0] = RADIUS*cos(theta);
                                w[0] = RADIUS*sin(theta);
                                for (int l=1;l<n;l++) //fills in the past times for y, z, v, and w
                                {
                                    y[l]=y[0];
                                    z[l]=z[0];
                                    v[l]=v[0];
                                    w[l]=w[0];
                                }
                                //fprintf(fp,"%f,%f,%f,%f,%f,%f\n",y[0],z[0],1-y[0]-z[0],v[0],w[0],1-v[0]-w[0]);
#ifdef USE_MULTIPLE_THREADS

                                // Make a simulation for each of the available threads.
                                // First check to see how many threads are running.
                                if(numberThreads >= NUMBER_THREADS)
                                {
                                    // There are too many threads. Wait for each run to end.
                                    while(numberThreads>0)
                                    {
#ifdef THREAD_DEBUG
                                        std::cout << "Waiting on thread "
                                                  << simulation[numberThreads-1].get_id()
                                                  << std::endl;
#endif
                                        simulation[--numberThreads].join();
                                    }
                                } // if(numberThreads)

                                // Make a run in a separate thread.
                                simulation[numberThreads++] = std::thread(linear,
                                                                          steps,a,gamma,r,d,g,x,y,z,dt,n,beta,tau,&fp,k,y[0],z[0],v,w,theta);

#else

                                // Ignore the different threads. Just make one approximation in this one thread.
                                linear(steps,a,gamma,r,d,g,x,y,z,dt,n,beta,tau,&fp,k,y[0],z[0],v,w,theta);

#endif

#ifdef SHOW_PROGRESS
                                if(k%20 == 0)
                                    std::cout << "  Simulation number " << k << std::endl;
#endif

                            } // for(k<trials)
                        } // for(theta<pi/2
                   }
            }
        }

            // Free up the allocated memory.
            free(x);
            free(y);
            free(z);
            free(v);
            free(w);

        fp.close();

#ifdef SHOW_PROGRESS
        std::cout << "all done" << std::endl;
#endif

        return b.exec();
}
<commit_msg>Moved the freeing of the vectors for the past times outside of the loops<commit_after>#include <QCoreApplication>
#include <QtDebug>

#include <iostream>
#include <fstream>
//#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <cerrno>
#include <cmath>
#include <thread>
#include <mutex>

#define OUTPUT_FILE "./trials.csv"
#define NUMBER_THREADS 1
#define USE_MULTIPLE_THREADS
// create a mutex that is used to protect the writing of the data to
// the file.
std::mutex writeToFile;

#ifndef M_PI
#define M_PI 3.14159265359
#endif

#define SHOW_PROGRESS
//#define SHOW_INTERMEDIATE
//#define THREAD_DEBUG
#define BASE_DT 0.00001
#define RADIUS 0.06

#ifndef Q_OS_UNIX
double drand48()
{
    return((double)(rand())/((double)RAND_MAX));
}
#endif

void normalDistRand(double stdDev,double* randomNumbers)
    {
        /* Generate a random number in polar coordinates */
        double radius = sqrt(-2.0*log(drand48()));
        double angle = 2.0*M_PI*drand48();
        /* transform the number back into cartesian coordinates */
        randomNumbers[0] = stdDev*radius*sin(angle);
        randomNumbers[1] = stdDev*radius*cos(angle);
    }

void printToCSVFile(double dt, double beta, double g,double tau,
                    double q, double theta, double h,double s,
                    double *x,std::ofstream *fp)
{

    std::lock_guard<std::mutex> guard(writeToFile);  // Make sure that
                                                       // this routine
                                                       // can only
                                                       // access the file once
                                                       // at any one time.

    *fp << dt << ","
        << beta << ","
        << g << ","
        << tau << ","
        << q+1 << ","
        << theta << ","
        << h << ","
        << s << ","
        << 1-h-s << ","
        << x[0] << ","
        << x[1] << ","
        << 1-x[0]-x[1] << ","
        << x[2] << ","
        << x[3] << ","
        << 1-x[2]-x[3]
        << std::endl;

    (*fp).flush();
}

void linear(long steps,
              double a,double gamma,double r,double d,double g,
              double *x,double *y,double *z, double dt,
              int n,
              double beta,double tau,
              std::ofstream *fp,
              int q,
              double h,double s,double *v,double *w, double theta)
    {

        long m=n-1;
        long p=0;
        double B[2];
        int calcRandom=0;

#ifdef THREAD_DEBUG
        std::cout << "My thread id: " << std::this_thread::get_id() << std::endl;
#endif

        // Step through every time step.
        for (long k=0;k<steps;k++)
        {

            // Calculate a new set of random numbers if necessary.
            if(calcRandom==0)
                normalDistRand(sqrt(dt),B); //noise in most recent time step

            //x[0]=y[m]+(y[m]*(gamma-gamma*y[m]+(a-gamma)*z[m])-(g*y[p]/(1-z[p])))*dt
            //x[0]=x[0]+beta*y[m]*(1-y[m])+0.5*beta*y[m]*(1-y[m])*beta*(1-2*y[m])*(B[calcRandom]*B[calcRandom]-dt);

            //Computes the deterministic component for Macroalgae
            x[0] = y[m]+(y[m]*(gamma-gamma*y[m]+(a-gamma)*z[m])-(g*y[p]/(1-z[p])))*dt;

            //Adds in the noise
            //x[0]=x[0]+beta*y[m]*B[calcRandom]+0.5*beta*y[m]*beta*(B[calcRandom]*B[calcRandom]-dt);
            x[0] += beta*y[m]*B[calcRandom]+0.5*beta*beta*y[m]*(B[calcRandom]*B[calcRandom]-dt);

            //Computes the deterministic component for Coral
            x[1] = z[m]+(z[m]*(r-d-(a+r)*y[m]-r*z[m]))*dt;

            x[2] =  v[m]+(v[m]*(gamma-gamma*v[m]+(a-gamma)*w[m])-(g*v[p]/(1-w[p])))*dt;
            x[2] += beta*v[m]*(1-v[m])*B[calcRandom]+0.5*beta*(1-2*v[m])*beta*v[m]*(1-v[m])*(B[calcRandom]*B[calcRandom]-dt);
            x[3] =  w[m]+(w[m]*(r-d-(a+r)*v[m]-r*w[m]))*dt;

            /****************************************************************
                Account for extinction and overgrowing!!
            ****************************************************************/
            for(int i=0;i<4;++i)
                {
                    if(x[i]<0.0)
                        x[i] = 0.0;
                    else if (x[i]>1.0)
                        x[i] = 1.0;
                }

            //Updates delay and cell index
            m=(m+1)%n;
            p=(p+1)%n;
            y[m]=x[0];
            z[m]=x[1];
            v[m]=x[2];
            w[m]=x[3];
            calcRandom = (calcRandom+1)%2; // update which random number to use.

        }

        //printf("%f\t%f\t%f\t%f\t%f\n",dt,beta,tau,x[0],x[1]);
        printToCSVFile(dt,beta,g,tau,q,theta,h,s,x,fp);

 #ifdef SHOW_INTERMEDIATE
        qDebug() << dt << ","
            << beta << ","
            << g << ","
            << tau << ","
            << q+1 << ","
            << h << ","
            << s << ","
            << 1-h-s << ","
            << x[0] << ","
            << x[1] << ","
            << 1-x[0]-x[1] << ","
            << x[2] << ","
            << x[3] << ","
            << 1-x[2]-x[3];
        qDebug() << errno << EDOM << ERANGE;
#endif

    }

/* ****************************************************************
     main

     The main function. Called at the start of the program.
**************************************************************** */
int main(int argc, char *argv[])
{
    QCoreApplication b(argc, argv);

        long steps;    // The number of steps to take in a single simulation.
        double *v,*w,*x,*y,*z;  // The variables used for the state of the system.

        /*
            Define the constants.

            These are the parameters that are used in the operator for the
            differential equations.
         */
        double a    	 = 0.1;
        double g    ;//	 = 0.3;
        double gamma	 = 0.8;
        double r    	 = 1.0;
        double d    	 = 0.44;

        double tau;
        double beta ;//	 = .5;
//        double gZero	 = ((d*a*r+d*d)*(gamma-a))/(r*r);
//        double gOne		 = (gamma*(a+d))/(a+r);
//        double chi		 = r*gamma/(r+a)-gamma+a;					//Intermediate Step
//        double xi		 = -(d*gamma/(r+a)+a);						//Intermediate Step
//        double cbar		 = (-xi-sqrt(xi*xi-4*chi*g))/(2*chi);		//Intermediate Step
//        double coralSaddle		 = 1-cbar;						    //Saddle point value for coral
//        double macroSaddle		 = (r-r*coralSaddle-d)/(r+a);		//Saddle point value for macroalgae

//        long   numberDT;    // The current iteration for the number assocated with the value of dt.
//        double omega	 = sqrt((r*r*(g*g-gZero*gZero))/(d*d));
//        double tauZero	 = (1/omega)*acos(gZero/g);

        double dt        = BASE_DT;          // Set the initial time step
        double final;       // The final time for each simulation.
        long   trials;      // The number of simulations to make.

        final=50.0;  // Set the final time.
        trials=400;   // Set the number of trials to perform.

        // Set the time delay, tau
        //double tau = 0.5;

        // set up the variables for using different approximations on different threads.
        std::thread simulation[NUMBER_THREADS];
        int numberThreads = 0;

        // Sets the seed for the random numbers
#ifdef Q_OS_UNIX
        srand48(time(NULL));
        //qDebug() << "This is a POSIX system!" ;
#else
        srand(time(NULL));
#endif

        // Create a CSV File
        std::ofstream fp;
                //String fileName = "trials-g" + std::toString(g) + "-tau" + std::toString(tau);
        fp.open(OUTPUT_FILE,std::ios::out | std::ios::trunc);

        fp << "dt,beta,g,tau,trial,theta,initMacro,initCoral,initTurf,macroalgae,coral,turf,lgMacro,lgCoral,lgTurf" << std::endl;

        for(tau = .2; tau <= .4; tau += .2 ){
        // Determine the number of time steps required to move back to the delay in time.
        // The number of cells needed for the delay (changes with dt)
            int n;
            if(tau != 0)
                n=(int)(tau/BASE_DT+0.5);
            else
                n = 1;
            // Allocate the space for the states of the system
            x=(double *) calloc(4,sizeof(double));
            y=(double *) calloc(n,sizeof(double));		//macroalgae for multiplicative noise
            z=(double *) calloc(n,sizeof(double));		//coral for multiplicative noise
            v=(double *) calloc(n,sizeof(double));		//macroalgae for logistic noise
            w=(double *) calloc(n,sizeof(double));		//coral for logistic noise

            for(g=.2; g<.8; g += .2) {
                //double omega	 = sqrt((r*r*(g*g-gZero*gZero))/(d*d));
                // double tauZero	 = (1/omega)*acos(gZero/g);

                // Make different approximations for different values of beta.
                for(beta=.2;beta<=1; beta += .2) {

#ifdef SHOW_PROGRESS
                    std::cout << "dt = " << dt << std::endl;
#endif
                        //index = tau/dt;

                        //printf("%i\n",n);
                        steps=(long)(final/dt);

                        for (double theta=0;theta<=M_PI/2;theta+=(M_PI*0.5)*0.025)
                        {

                        // Make an approximation for different initial conditions.
                        // Make an arc through 0 to pi/2 radians from the origin.

                            for (int k=0;k<trials;k++)
                            {
                                y[0] = RADIUS*cos(theta); //initial Macroalgae level
                                z[0] = RADIUS*sin(theta); //initial Coral level
                                v[0] = RADIUS*cos(theta);
                                w[0] = RADIUS*sin(theta);
                                for (int l=1;l<n;l++) //fills in the past times for y, z, v, and w
                                {
                                    y[l]=y[0];
                                    z[l]=z[0];
                                    v[l]=v[0];
                                    w[l]=w[0];
                                }
                                //fprintf(fp,"%f,%f,%f,%f,%f,%f\n",y[0],z[0],1-y[0]-z[0],v[0],w[0],1-v[0]-w[0]);
#ifdef USE_MULTIPLE_THREADS

                                // Make a simulation for each of the available threads.
                                // First check to see how many threads are running.
                                if(numberThreads >= NUMBER_THREADS)
                                {
                                    // There are too many threads. Wait for each run to end.
                                    while(numberThreads>0)
                                    {
#ifdef THREAD_DEBUG
                                        std::cout << "Waiting on thread "
                                                  << simulation[numberThreads-1].get_id()
                                                  << std::endl;
#endif
                                        simulation[--numberThreads].join();
                                    }
                                } // if(numberThreads)

                                // Make a run in a separate thread.
                                simulation[numberThreads++] = std::thread(linear,
                                                                          steps,a,gamma,r,d,g,x,y,z,dt,n,beta,tau,&fp,k,y[0],z[0],v,w,theta);

#else

                                // Ignore the different threads. Just make one approximation in this one thread.
                                linear(steps,a,gamma,r,d,g,x,y,z,dt,n,beta,tau,&fp,k,y[0],z[0],v,w,theta);

#endif

#ifdef SHOW_PROGRESS
                                if(k%20 == 0)
                                    std::cout << "  Simulation number " << k << std::endl;
#endif

                            } // for(k<trials)
                        } // for(theta<pi/2
                   }
            }

            // Free up the allocated memory.
            free(x);
            free(y);
            free(z);
            free(v);
            free(w);

        }

        fp.close();

#ifdef SHOW_PROGRESS
        std::cout << "all done" << std::endl;
#endif

        return b.exec();
}
<|endoftext|>


<commit_before>/*
 * The Biomechanical ToolKit
 * Copyright (c) 2009-2011, Arnaud Barré
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *     * Neither the name(s) of the copyright holders nor the names
 *       of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written
 *       permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "ChartOptionsWidget.h"

#include <QPainter>
#include <QHeaderView>
#include <QColorDialog>

ChartOptionsWidget::ChartOptionsWidget(QWidget* parent)
: QWidget(parent, Qt::Popup | Qt::FramelessWindowHint)
{
  this->setupUi(this);

  this->setAttribute(Qt::WA_TranslucentBackground);
  this->resize(150,250);

  QHeaderView* header = this->plotTable->horizontalHeader();
  header->setMovable(false);
  header->resizeSection(1, 25);
  header->setResizeMode(1, QHeaderView::Fixed);
  header->setResizeMode(0, QHeaderView::Stretch);

  this->gridLayout->setAlignment(Qt::AlignJustify | Qt::AlignVCenter);

#ifdef Q_OS_MAC
  QFont f = this->font();
  f.setPixelSize(10);
  this->plotTable->setFont(f);
  this->lineWidthSpinBox->setFont(f);
  this->labelLineWidth->setFont(f);
  this->labelLineColor->setFont(f);
  this->plotTable->setAttribute(Qt::WA_MacShowFocusRect, false);
  this->lineWidthSpinBox->setAttribute(Qt::WA_MacShowFocusRect, false);
#endif
  this->plotTable->verticalHeader()->setDefaultSectionSize(20);
  QLayout* layout = this->layout();
  layout->setSpacing(6);
  layout->setContentsMargins(6, 15, 6, 6);

  connect(this->plotTable, SIGNAL(itemSelectionChanged()), this, SLOT(displayPlotOption()));
  connect(this->lineWidthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setLineWidth(double)));
  connect(this->lineColorButton, SIGNAL(clicked()), this, SLOT(setLineColor()));
};

void ChartOptionsWidget::appendPlot(int itemId, const QString& label, int color[3], double width)
{
  int rowIdx = this->plotTable->rowCount();
  this->plotTable->insertRow(rowIdx);
  QColor c = QColor(color[0], color[1], color[2]);
  QTableWidgetItem* item = new QTableWidgetItem(this->createLineIcon(c, width), label);
  item->setData(LineColor, c);
  item->setData(LineWidth, width);
  item->setData(ItemId, itemId);
  this->plotTable->setItem(rowIdx, 0, item);
  QPushButton* button = new QPushButton("", this);
  button->setFlat(true);
  button->setProperty("plotIndex", rowIdx);
  button->setStyleSheet("QPushButton {image: url(:/Resources/Images/plot_delete.png);} QPushButton:pressed {image: url(:/Resources/Images/plot_delete-down.png);} QPushButton:flat {border: none;}");
  this->plotTable->setCellWidget(rowIdx, 1, button);

  connect(button, SIGNAL(clicked()), this, SLOT(removePlot()));
};

void ChartOptionsWidget::clear()
{
  this->plotTable->clearContents();
  this->plotTable->setRowCount(0);
  this->setPlotOptionEnabled(false);
};

void ChartOptionsWidget::setPlotOptionEnabled(bool enabled)
{
  this->labelLineWidth->setEnabled(enabled);
  this->lineWidthSpinBox->setEnabled(enabled);
  this->labelLineColor->setEnabled(enabled);
  this->lineColorButton->setEnabled(enabled);
  if (!enabled)
  {
    this->lineWidthSpinBox->clear();
    this->setLineColorButtonColor(Qt::white);
  }
};

void ChartOptionsWidget::displayPlotOption()
{
  QList<QTableWidgetItem*> selectedItems = this->plotTable->selectedItems();
  if (selectedItems.isEmpty())
    this->setPlotOptionEnabled(false);
  else
  {
    QColor lineColor;
    double lineWidth = -1.0;
    QList<QTableWidgetItem*>::const_iterator it = selectedItems.begin();
    while (it != selectedItems.end())
    {
      if ((*it)->column() == 0)
      {
        lineColor = (*it)->data(LineColor).value<QColor>();
        lineWidth = (*it)->data(LineWidth).toDouble();
        break;
      }
      ++it;
    }
    while (it != selectedItems.end())
    {
      if ((*it)->column() == 0)
      {
        QColor color = (*it)->data(LineColor).value<QColor>();
        double width = (*it)->data(LineWidth).toDouble();

        if (lineColor != color)
          lineColor = QColor();
        if (lineWidth != width)
          lineWidth = -1.0;
      }

      if (!lineColor.isValid() && (lineWidth == -1.0))
        break;

      ++it;
    }

    if (!lineColor.isValid())
      this->setLineColorButtonColor(Qt::white);
    else
      this->setLineColorButtonColor(lineColor);

    this->lineWidthSpinBox->blockSignals(true);
    if (lineWidth == -1.0)
      this->lineWidthSpinBox->clear();
    else
      this->lineWidthSpinBox->setValue(lineWidth);
    this->lineWidthSpinBox->blockSignals(false);

    this->setPlotOptionEnabled(true);
  }
};

void ChartOptionsWidget::removePlot()
{
  QObject* obj = sender();
  int idx = obj->property("plotIndex").toInt();
  this->plotTable->removeRow(idx);
  // Update the other indices
  for (int i = idx ; i < this->plotTable->rowCount() ; ++i)
    this->plotTable->cellWidget(i,1)->setProperty("plotIndex", i);
  if (this->plotTable->rowCount() == 0)
    this->setPlotOptionEnabled(false);
  emit plotRemoved(idx);
};

void ChartOptionsWidget::setLineColor()
{
  QList<QTableWidgetItem*> selectedItems = this->plotTable->selectedItems();
  if (selectedItems.isEmpty())
    return;

  QColor c = selectedItems[0]->data(LineColor).value<QColor>();
  for (QList<QTableWidgetItem*>::const_iterator it = selectedItems.begin() ; it != selectedItems.end() ; ++it)
  {
    if (c != (*it)->data(LineColor).value<QColor>())
    {
      c = Qt::white;
      break;
    }
  }

  QColor color = QColorDialog::getColor(c, this);
  QList<int> indices;
  if (color.isValid())
  {
    for (QList<QTableWidgetItem*>::const_iterator it = selectedItems.begin() ; it != selectedItems.end() ; ++it)
    {
      if ((*it)->column() == 0)
      {
        (*it)->setIcon(this->createLineIcon(color, (*it)->data(LineWidth).toDouble()));
        (*it)->setData(LineColor, color);
        indices << (*it)->row();
      }
    }
    this->setLineColorButtonColor(color);
    emit lineColorChanged(indices, color);
  }
  // Force the widget to be shown as it disappear when the color dialog is shown
  this->setVisible(true);
};

void ChartOptionsWidget::setLineWidth(double value)
{
  QList<int> indices;
  QList<QTableWidgetItem*> selectedItems = this->plotTable->selectedItems();
  for (QList<QTableWidgetItem*>::const_iterator it = selectedItems.begin() ; it != selectedItems.end() ; ++it)
  {
    if ((*it)->column() == 0)
    {
      (*it)->setIcon(this->createLineIcon((*it)->data(LineColor).value<QColor>(), value));
      (*it)->setData(LineWidth, value);
      indices << (*it)->row();
    }
  }
  emit lineWidthChanged(indices, value);
};

void ChartOptionsWidget::paintEvent(QPaintEvent* event)
{
  Q_UNUSED(event)

  const double midX = (double)this->width()/2.0;
  const double penWidth = 0.5;
  static const QPointF points[3] = {
     QPointF(midX-12.0, 8.75),
     QPointF(midX, 0.0),
     QPointF(midX+12.0, 8.75),
  };

  QPainter painter(this);
  painter.setRenderHint(QPainter::Antialiasing);
  painter.setBrush(Qt::white);

  painter.setPen(QPen(Qt::gray, penWidth));
  //painter.drawRoundedRect(QRectF(0.0, 20.0, this->width(), this->height()-20), 10.0, 10.0);
  painter.drawRect(QRectF(0.0, 8.0, this->width(), this->height()-8.0));

  painter.setPen(QPen(Qt::white, penWidth));
  painter.drawPolygon(points,3);

  painter.setPen(QPen(Qt::gray, penWidth));
  painter.drawPolyline(points,3);
};

QPixmap ChartOptionsWidget::createLineIcon(const QColor& color, double width)
{
  QPen p = color;
  QImage lineImage(16, 16, QImage::Format_ARGB32);
  QPainter painter(&lineImage);
  // painter.setRenderHint(QPainter::Antialiasing);
  painter.setBrush(Qt::NoBrush);
  painter.setPen(Qt::NoPen);
  painter.setCompositionMode(QPainter::CompositionMode_Source);
  painter.fillRect(lineImage.rect(), Qt::transparent);
  painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
  p.setWidthF(width); painter.setPen(p);
  painter.drawLine(QLineF(2.0, 8.0, 14.0, 8.0));
  return QPixmap::fromImage(lineImage);
};

void ChartOptionsWidget::setLineColorButtonColor(const QColor& color)
{
  this->lineColorButton->setStyleSheet("QPushButton {background-color: rgb(" + QString::number(color.red()) + "," + QString::number(color.green())  + "," + QString::number(color.blue()) + "); border: 1px solid lightgray;} QPushButton:pressed {border-color: gray;}");
};<commit_msg>[UPD] Mokka: The widget for the chart's options is wider by default.<commit_after>/*
 * The Biomechanical ToolKit
 * Copyright (c) 2009-2011, Arnaud Barré
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *     * Neither the name(s) of the copyright holders nor the names
 *       of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written
 *       permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "ChartOptionsWidget.h"

#include <QPainter>
#include <QHeaderView>
#include <QColorDialog>

ChartOptionsWidget::ChartOptionsWidget(QWidget* parent)
: QWidget(parent, Qt::Popup | Qt::FramelessWindowHint)
{
  this->setupUi(this);

  this->setAttribute(Qt::WA_TranslucentBackground);
  this->resize(175,250);

  QHeaderView* header = this->plotTable->horizontalHeader();
  header->setMovable(false);
  header->resizeSection(1, 25);
  header->setResizeMode(1, QHeaderView::Fixed);
  header->setResizeMode(0, QHeaderView::Stretch);

  this->gridLayout->setAlignment(Qt::AlignJustify | Qt::AlignVCenter);

#ifdef Q_OS_MAC
  QFont f = this->font();
  f.setPixelSize(10);
  this->plotTable->setFont(f);
  this->lineWidthSpinBox->setFont(f);
  this->labelLineWidth->setFont(f);
  this->labelLineColor->setFont(f);
  this->plotTable->setAttribute(Qt::WA_MacShowFocusRect, false);
  this->lineWidthSpinBox->setAttribute(Qt::WA_MacShowFocusRect, false);
#endif
  this->plotTable->verticalHeader()->setDefaultSectionSize(20);
  QLayout* layout = this->layout();
  layout->setSpacing(6);
  layout->setContentsMargins(6, 15, 6, 6);

  connect(this->plotTable, SIGNAL(itemSelectionChanged()), this, SLOT(displayPlotOption()));
  connect(this->lineWidthSpinBox, SIGNAL(valueChanged(double)), this, SLOT(setLineWidth(double)));
  connect(this->lineColorButton, SIGNAL(clicked()), this, SLOT(setLineColor()));
};

void ChartOptionsWidget::appendPlot(int itemId, const QString& label, int color[3], double width)
{
  int rowIdx = this->plotTable->rowCount();
  this->plotTable->insertRow(rowIdx);
  QColor c = QColor(color[0], color[1], color[2]);
  QTableWidgetItem* item = new QTableWidgetItem(this->createLineIcon(c, width), label);
  item->setData(LineColor, c);
  item->setData(LineWidth, width);
  item->setData(ItemId, itemId);
  this->plotTable->setItem(rowIdx, 0, item);
  QPushButton* button = new QPushButton("", this);
  button->setFlat(true);
  button->setProperty("plotIndex", rowIdx);
  button->setStyleSheet("QPushButton {image: url(:/Resources/Images/plot_delete.png);} QPushButton:pressed {image: url(:/Resources/Images/plot_delete-down.png);} QPushButton:flat {border: none;}");
  this->plotTable->setCellWidget(rowIdx, 1, button);

  connect(button, SIGNAL(clicked()), this, SLOT(removePlot()));
};

void ChartOptionsWidget::clear()
{
  this->plotTable->clearContents();
  this->plotTable->setRowCount(0);
  this->setPlotOptionEnabled(false);
};

void ChartOptionsWidget::setPlotOptionEnabled(bool enabled)
{
  this->labelLineWidth->setEnabled(enabled);
  this->lineWidthSpinBox->setEnabled(enabled);
  this->labelLineColor->setEnabled(enabled);
  this->lineColorButton->setEnabled(enabled);
  if (!enabled)
  {
    this->lineWidthSpinBox->clear();
    this->setLineColorButtonColor(Qt::white);
  }
};

void ChartOptionsWidget::displayPlotOption()
{
  QList<QTableWidgetItem*> selectedItems = this->plotTable->selectedItems();
  if (selectedItems.isEmpty())
    this->setPlotOptionEnabled(false);
  else
  {
    QColor lineColor;
    double lineWidth = -1.0;
    QList<QTableWidgetItem*>::const_iterator it = selectedItems.begin();
    while (it != selectedItems.end())
    {
      if ((*it)->column() == 0)
      {
        lineColor = (*it)->data(LineColor).value<QColor>();
        lineWidth = (*it)->data(LineWidth).toDouble();
        break;
      }
      ++it;
    }
    while (it != selectedItems.end())
    {
      if ((*it)->column() == 0)
      {
        QColor color = (*it)->data(LineColor).value<QColor>();
        double width = (*it)->data(LineWidth).toDouble();

        if (lineColor != color)
          lineColor = QColor();
        if (lineWidth != width)
          lineWidth = -1.0;
      }

      if (!lineColor.isValid() && (lineWidth == -1.0))
        break;

      ++it;
    }

    if (!lineColor.isValid())
      this->setLineColorButtonColor(Qt::white);
    else
      this->setLineColorButtonColor(lineColor);

    this->lineWidthSpinBox->blockSignals(true);
    if (lineWidth == -1.0)
      this->lineWidthSpinBox->clear();
    else
      this->lineWidthSpinBox->setValue(lineWidth);
    this->lineWidthSpinBox->blockSignals(false);

    this->setPlotOptionEnabled(true);
  }
};

void ChartOptionsWidget::removePlot()
{
  QObject* obj = sender();
  int idx = obj->property("plotIndex").toInt();
  this->plotTable->removeRow(idx);
  // Update the other indices
  for (int i = idx ; i < this->plotTable->rowCount() ; ++i)
    this->plotTable->cellWidget(i,1)->setProperty("plotIndex", i);
  if (this->plotTable->rowCount() == 0)
    this->setPlotOptionEnabled(false);
  emit plotRemoved(idx);
};

void ChartOptionsWidget::setLineColor()
{
  QList<QTableWidgetItem*> selectedItems = this->plotTable->selectedItems();
  if (selectedItems.isEmpty())
    return;

  QColor c = selectedItems[0]->data(LineColor).value<QColor>();
  for (QList<QTableWidgetItem*>::const_iterator it = selectedItems.begin() ; it != selectedItems.end() ; ++it)
  {
    if (c != (*it)->data(LineColor).value<QColor>())
    {
      c = Qt::white;
      break;
    }
  }

  QColor color = QColorDialog::getColor(c, this);
  QList<int> indices;
  if (color.isValid())
  {
    for (QList<QTableWidgetItem*>::const_iterator it = selectedItems.begin() ; it != selectedItems.end() ; ++it)
    {
      if ((*it)->column() == 0)
      {
        (*it)->setIcon(this->createLineIcon(color, (*it)->data(LineWidth).toDouble()));
        (*it)->setData(LineColor, color);
        indices << (*it)->row();
      }
    }
    this->setLineColorButtonColor(color);
    emit lineColorChanged(indices, color);
  }
  // Force the widget to be shown as it disappear when the color dialog is shown
  this->setVisible(true);
};

void ChartOptionsWidget::setLineWidth(double value)
{
  QList<int> indices;
  QList<QTableWidgetItem*> selectedItems = this->plotTable->selectedItems();
  for (QList<QTableWidgetItem*>::const_iterator it = selectedItems.begin() ; it != selectedItems.end() ; ++it)
  {
    if ((*it)->column() == 0)
    {
      (*it)->setIcon(this->createLineIcon((*it)->data(LineColor).value<QColor>(), value));
      (*it)->setData(LineWidth, value);
      indices << (*it)->row();
    }
  }
  emit lineWidthChanged(indices, value);
};

void ChartOptionsWidget::paintEvent(QPaintEvent* event)
{
  Q_UNUSED(event)

  const double midX = (double)this->width()/2.0;
  const double penWidth = 0.5;
  static const QPointF points[3] = {
     QPointF(midX-12.0, 8.75),
     QPointF(midX, 0.0),
     QPointF(midX+12.0, 8.75),
  };

  QPainter painter(this);
  painter.setRenderHint(QPainter::Antialiasing);
  painter.setBrush(Qt::white);

  painter.setPen(QPen(Qt::gray, penWidth));
  //painter.drawRoundedRect(QRectF(0.0, 20.0, this->width(), this->height()-20), 10.0, 10.0);
  painter.drawRect(QRectF(0.0, 8.0, this->width(), this->height()-8.0));

  painter.setPen(QPen(Qt::white, penWidth));
  painter.drawPolygon(points,3);

  painter.setPen(QPen(Qt::gray, penWidth));
  painter.drawPolyline(points,3);
};

QPixmap ChartOptionsWidget::createLineIcon(const QColor& color, double width)
{
  QPen p = color;
  QImage lineImage(16, 16, QImage::Format_ARGB32);
  QPainter painter(&lineImage);
  // painter.setRenderHint(QPainter::Antialiasing);
  painter.setBrush(Qt::NoBrush);
  painter.setPen(Qt::NoPen);
  painter.setCompositionMode(QPainter::CompositionMode_Source);
  painter.fillRect(lineImage.rect(), Qt::transparent);
  painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
  p.setWidthF(width); painter.setPen(p);
  painter.drawLine(QLineF(2.0, 8.0, 14.0, 8.0));
  return QPixmap::fromImage(lineImage);
};

void ChartOptionsWidget::setLineColorButtonColor(const QColor& color)
{
  this->lineColorButton->setStyleSheet("QPushButton {background-color: rgb(" + QString::number(color.red()) + "," + QString::number(color.green())  + "," + QString::number(color.blue()) + "); border: 1px solid lightgray;} QPushButton:pressed {border-color: gray;}");
};<|endoftext|>


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

#include "webkit/glue/plugins/plugin_list.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "build/build_config.h"

namespace {

// Return true if we're in debug-plugin-loading mode.
bool DebugPluginLoading() {
  static const char kDebugPluginLoading[] = "debug-plugin-loading";
  return CommandLine::ForCurrentProcess()->HasSwitch(kDebugPluginLoading);
}

// We build up a list of files and mtimes so we can sort them.
typedef std::pair<FilePath, base::Time> FileAndTime;
typedef std::vector<FileAndTime> FileTimeList;

// Comparator used to sort by descending mtime then ascending filename.
bool CompareTime(const FileAndTime& a, const FileAndTime& b) {
  if (a.second == b.second) {
    // Fall back on filename sorting, just to make the predicate valid.
    return a.first < b.first;
  }

  // Sort by mtime, descending.
  return a.second > b.second;
}

// Some plugins are shells around other plugins; we prefer to use the
// real plugin directly, if it's available.  This function returns
// true if we should prefer other plugins over this one.  We'll still
// use a "undesirable" plugin if no other option is available.
bool IsUndesirablePlugin(const WebPluginInfo& info) {
  std::string filename = info.path.BaseName().value();
  return (filename.find("npcxoffice") != std::string::npos || // Crossover
          filename.find("npwrapper") != std::string::npos);   // nspluginwrapper
}

}  // anonymous namespace

namespace NPAPI {

void PluginList::PlatformInit() {
}

void PluginList::GetPluginDirectories(std::vector<FilePath>* plugin_dirs) {
  // See http://groups.google.com/group/chromium-dev/browse_thread/thread/7a70e5fcbac786a9
  // for discussion.
  // We first consult Chrome-specific dirs, then fall back on the logic
  // Mozilla uses.

  // TODO(evanm): maybe consult our own plugins dir, like
  // ~/.config/chromium/Plugins?

  // The Chrome binary dir + "plugins/".
  FilePath dir;
  PathService::Get(base::DIR_EXE, &dir);
  plugin_dirs->push_back(dir.Append("plugins"));

  // Mozilla code to reference:
  // http://mxr.mozilla.org/firefox/ident?i=NS_APP_PLUGINS_DIR_LIST
  // and tens of accompanying files (mxr is very helpful).
  // This code carefully matches their behavior for compat reasons.

  // 1) MOZ_PLUGIN_PATH env variable.
  const char* moz_plugin_path = getenv("MOZ_PLUGIN_PATH");
  if (moz_plugin_path) {
    std::vector<std::string> paths;
    SplitString(moz_plugin_path, ':', &paths);
    for (size_t i = 0; i < paths.size(); ++i)
      plugin_dirs->push_back(FilePath(paths[i]));
  }

  // 2) NS_USER_PLUGINS_DIR: ~/.mozilla/plugins.
  // This is a de-facto standard, so even though we're not Mozilla, let's
  // look in there too.
  const char* home = getenv("HOME");
  if (home)
    plugin_dirs->push_back(FilePath(home).Append(".mozilla/plugins"));

  // 3) NS_SYSTEM_PLUGINS_DIR:
  // This varies across different versions of Firefox, so check 'em all.
  plugin_dirs->push_back(FilePath("/usr/lib/mozilla/plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib/firefox/plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib/xulrunner-addons/plugins"));

#if defined(ARCH_CPU_64_BITS)
  // On my Ubuntu system, /usr/lib64 is a symlink to /usr/lib.
  // But a user reported on their Fedora system they are separate.
  plugin_dirs->push_back(FilePath("/usr/lib64/mozilla/plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib64/firefox/plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib64/xulrunner-addons/plugins"));
#endif
}

void PluginList::LoadPluginsFromDir(const FilePath& path,
                                    std::vector<WebPluginInfo>* plugins) {
  // See ScanPluginsDirectory near
  // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginHostImpl.cpp#5052

  // Construct and stat a list of all filenames under consideration, for
  // later sorting by mtime.
  FileTimeList files;
  file_util::FileEnumerator enumerator(path,
                                       false, // not recursive
                                       file_util::FileEnumerator::FILES);
  for (FilePath path = enumerator.Next(); !path.value().empty();
       path = enumerator.Next()) {
    // Skip over Mozilla .xpt files.
    if (path.MatchesExtension(FILE_PATH_LITERAL(".xpt")))
      continue;

    // Java doesn't like being loaded through a symlink, since it uses
    // its path to find dependent data files.
    // file_util::AbsolutePath calls through to realpath(), which resolves
    // symlinks.
    FilePath orig_path = path;
    file_util::AbsolutePath(&path);
    if (DebugPluginLoading())
      LOG(ERROR) << "Resolved " << orig_path.value() << " -> " << path.value();

    // Flash stops working if the containing directory involves 'netscape'.
    // No joke.  So use the other path if it's better.
    static const char kFlashPlayerFilename[] = "libflashplayer.so";
    static const char kNetscapeInPath[] = "/netscape/";
    if (path.BaseName().value() == kFlashPlayerFilename &&
        path.value().find(kNetscapeInPath) != std::string::npos) {
      if (orig_path.value().find(kNetscapeInPath) == std::string::npos) {
        // Go back to the old path.
        path = orig_path;
      } else {
        LOG(ERROR) << "Flash misbehaves when used from a directory containing "
                   << kNetscapeInPath << ", so skipping " << orig_path.value();
        continue;
      }
    }

    // Get mtime.
    file_util::FileInfo info;
    if (!file_util::GetFileInfo(path, &info))
      continue;

    // Skip duplicates of the same file in our list.
    bool skip = false;
    for (size_t i = 0; i < plugins->size(); ++i) {
      if (plugins->at(i).path == path) {
        skip = true;
        break;
      }
    }
    if (skip) {
      if (DebugPluginLoading())
        LOG(ERROR) << "Skipping duplicate instance of " << path.value();
      continue;
    }

    files.push_back(std::make_pair(path, info.last_modified));
  }

  // Sort the file list by time (and filename).
  std::sort(files.begin(), files.end(), CompareTime);

  // Load the files in order.
  for (FileTimeList::const_iterator i = files.begin(); i != files.end(); ++i) {
    LoadPlugin(i->first, plugins);
  }
}

bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
                                  std::vector<WebPluginInfo>* plugins) {
  if (DebugPluginLoading()) {
    LOG(ERROR) << "Considering " << info.path.value()
              << " (" << info.name << ")";
  }
  if (IsUndesirablePlugin(info)) {
    if (DebugPluginLoading())
      LOG(ERROR) << info.path.value() << " is undesirable.";

    // See if we have a better version of this plugin.
    for (size_t i = 0; i < plugins->size(); ++i) {
      if (plugins->at(i).name == info.name &&
          !IsUndesirablePlugin(plugins->at(i))) {
        // Skip the current undesirable one so we can use the better one
        // we just found.
        if (DebugPluginLoading()) {
          LOG(ERROR) << "Skipping " << info.path.value() << ", preferring "
                    << plugins->at(i).path.value();
        }
        return false;
      }
    }
  }

  // TODO(evanm): prefer the newest version of flash, etc. here?

  if (DebugPluginLoading())
    LOG(ERROR) << "Using " << info.path.value();

  return true;
}

} // namespace NPAPI
<commit_msg>linux: add another path to plugin search path list<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/glue/plugins/plugin_list.h"

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "build/build_config.h"

namespace {

// Return true if we're in debug-plugin-loading mode.
bool DebugPluginLoading() {
  static const char kDebugPluginLoading[] = "debug-plugin-loading";
  return CommandLine::ForCurrentProcess()->HasSwitch(kDebugPluginLoading);
}

// We build up a list of files and mtimes so we can sort them.
typedef std::pair<FilePath, base::Time> FileAndTime;
typedef std::vector<FileAndTime> FileTimeList;

// Comparator used to sort by descending mtime then ascending filename.
bool CompareTime(const FileAndTime& a, const FileAndTime& b) {
  if (a.second == b.second) {
    // Fall back on filename sorting, just to make the predicate valid.
    return a.first < b.first;
  }

  // Sort by mtime, descending.
  return a.second > b.second;
}

// Some plugins are shells around other plugins; we prefer to use the
// real plugin directly, if it's available.  This function returns
// true if we should prefer other plugins over this one.  We'll still
// use a "undesirable" plugin if no other option is available.
bool IsUndesirablePlugin(const WebPluginInfo& info) {
  std::string filename = info.path.BaseName().value();
  return (filename.find("npcxoffice") != std::string::npos || // Crossover
          filename.find("npwrapper") != std::string::npos);   // nspluginwrapper
}

}  // anonymous namespace

namespace NPAPI {

void PluginList::PlatformInit() {
}

void PluginList::GetPluginDirectories(std::vector<FilePath>* plugin_dirs) {
  // See http://groups.google.com/group/chromium-dev/browse_thread/thread/7a70e5fcbac786a9
  // for discussion.
  // We first consult Chrome-specific dirs, then fall back on the logic
  // Mozilla uses.

  // TODO(evanm): maybe consult our own plugins dir, like
  // ~/.config/chromium/Plugins?

  // The Chrome binary dir + "plugins/".
  FilePath dir;
  PathService::Get(base::DIR_EXE, &dir);
  plugin_dirs->push_back(dir.Append("plugins"));

  // Mozilla code to reference:
  // http://mxr.mozilla.org/firefox/ident?i=NS_APP_PLUGINS_DIR_LIST
  // and tens of accompanying files (mxr is very helpful).
  // This code carefully matches their behavior for compat reasons.

  // 1) MOZ_PLUGIN_PATH env variable.
  const char* moz_plugin_path = getenv("MOZ_PLUGIN_PATH");
  if (moz_plugin_path) {
    std::vector<std::string> paths;
    SplitString(moz_plugin_path, ':', &paths);
    for (size_t i = 0; i < paths.size(); ++i)
      plugin_dirs->push_back(FilePath(paths[i]));
  }

  // 2) NS_USER_PLUGINS_DIR: ~/.mozilla/plugins.
  // This is a de-facto standard, so even though we're not Mozilla, let's
  // look in there too.
  const char* home = getenv("HOME");
  if (home)
    plugin_dirs->push_back(FilePath(home).Append(".mozilla/plugins"));

  // 3) NS_SYSTEM_PLUGINS_DIR:
  // This varies across different browsers and versions, so check 'em all.
  plugin_dirs->push_back(FilePath("/usr/lib/browser-plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib/mozilla/plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib/firefox/plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib/xulrunner-addons/plugins"));

#if defined(ARCH_CPU_64_BITS)
  // On my Ubuntu system, /usr/lib64 is a symlink to /usr/lib.
  // But a user reported on their Fedora system they are separate.
  plugin_dirs->push_back(FilePath("/usr/lib64/browser-plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib64/mozilla/plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib64/firefox/plugins"));
  plugin_dirs->push_back(FilePath("/usr/lib64/xulrunner-addons/plugins"));
#endif
}

void PluginList::LoadPluginsFromDir(const FilePath& path,
                                    std::vector<WebPluginInfo>* plugins) {
  // See ScanPluginsDirectory near
  // http://mxr.mozilla.org/firefox/source/modules/plugin/base/src/nsPluginHostImpl.cpp#5052

  // Construct and stat a list of all filenames under consideration, for
  // later sorting by mtime.
  FileTimeList files;
  file_util::FileEnumerator enumerator(path,
                                       false, // not recursive
                                       file_util::FileEnumerator::FILES);
  for (FilePath path = enumerator.Next(); !path.value().empty();
       path = enumerator.Next()) {
    // Skip over Mozilla .xpt files.
    if (path.MatchesExtension(FILE_PATH_LITERAL(".xpt")))
      continue;

    // Java doesn't like being loaded through a symlink, since it uses
    // its path to find dependent data files.
    // file_util::AbsolutePath calls through to realpath(), which resolves
    // symlinks.
    FilePath orig_path = path;
    file_util::AbsolutePath(&path);
    if (DebugPluginLoading())
      LOG(ERROR) << "Resolved " << orig_path.value() << " -> " << path.value();

    // Flash stops working if the containing directory involves 'netscape'.
    // No joke.  So use the other path if it's better.
    static const char kFlashPlayerFilename[] = "libflashplayer.so";
    static const char kNetscapeInPath[] = "/netscape/";
    if (path.BaseName().value() == kFlashPlayerFilename &&
        path.value().find(kNetscapeInPath) != std::string::npos) {
      if (orig_path.value().find(kNetscapeInPath) == std::string::npos) {
        // Go back to the old path.
        path = orig_path;
      } else {
        LOG(ERROR) << "Flash misbehaves when used from a directory containing "
                   << kNetscapeInPath << ", so skipping " << orig_path.value();
        continue;
      }
    }

    // Get mtime.
    file_util::FileInfo info;
    if (!file_util::GetFileInfo(path, &info))
      continue;

    // Skip duplicates of the same file in our list.
    bool skip = false;
    for (size_t i = 0; i < plugins->size(); ++i) {
      if (plugins->at(i).path == path) {
        skip = true;
        break;
      }
    }
    if (skip) {
      if (DebugPluginLoading())
        LOG(ERROR) << "Skipping duplicate instance of " << path.value();
      continue;
    }

    files.push_back(std::make_pair(path, info.last_modified));
  }

  // Sort the file list by time (and filename).
  std::sort(files.begin(), files.end(), CompareTime);

  // Load the files in order.
  for (FileTimeList::const_iterator i = files.begin(); i != files.end(); ++i) {
    LoadPlugin(i->first, plugins);
  }
}

bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
                                  std::vector<WebPluginInfo>* plugins) {
  if (DebugPluginLoading()) {
    LOG(ERROR) << "Considering " << info.path.value()
              << " (" << info.name << ")";
  }
  if (IsUndesirablePlugin(info)) {
    if (DebugPluginLoading())
      LOG(ERROR) << info.path.value() << " is undesirable.";

    // See if we have a better version of this plugin.
    for (size_t i = 0; i < plugins->size(); ++i) {
      if (plugins->at(i).name == info.name &&
          !IsUndesirablePlugin(plugins->at(i))) {
        // Skip the current undesirable one so we can use the better one
        // we just found.
        if (DebugPluginLoading()) {
          LOG(ERROR) << "Skipping " << info.path.value() << ", preferring "
                    << plugins->at(i).path.value();
        }
        return false;
      }
    }
  }

  // TODO(evanm): prefer the newest version of flash, etc. here?

  if (DebugPluginLoading())
    LOG(ERROR) << "Using " << info.path.value();

  return true;
}

} // namespace NPAPI
<|endoftext|>