<commit_before>#ifndef VARIABLE_SUBSET_HPP_
#define VARIABLE_SUBSET_HPP_

#include "clotho/powerset/config.hpp"

#include <iostream>
#include "clotho/powerset/powerset.hpp"

namespace clotho {
namespace powersets {

template < class Element, class Block = unsigned long, class BlockMap = block_map< Element, Block>, class ElementKeyer = element_key_of< Element > >
class variable_subset {
public:
    typedef variable_subset< Element, Block, BlockMap, ElementKeyer > self_type;
    typedef Element value_type;

    typedef clotho::powersets::powerset< Element, variable_subset< Element, Block, BlockMap, ElementKeyer >, Block, BlockMap, ElementKeyer > powerset_type;
    typedef boost::dynamic_bitset< unsigned long > bitset_type;
    typedef size_t index_type;

    typedef std::vector< bitset_type::block_type, bitset_type::allocator_type >::iterator block_iterator;
    typedef std::vector< bitset_type::block_type, bitset_type::allocator_type >::const_iterator cblock_iterator;

    typedef typename powerset_type::subset_ptr pointer;

    friend class clotho::powersets::powerset< Element, variable_subset< Element, Block, BlockMap, ElementKeyer >, Block, BlockMap, ElementKeyer >;

    pointer clone() const;

//    void    copy();
//    void                release();
//
//    unsigned int        ref_count() const;

    powerset_type *     getParent() const;

    bool                isSameFamily( pointer other ) const;

    std::pair< typename powerset_type::element_index_type, bool >   addElement( const value_type & elem );
    void                removeElement( const value_type & elem );

    /**
     *  Returns whether an element is a member of this subset
     */
    bool                operator[]( const value_type & elem );

    /**
     *  Returns whether bit index is set; equivalent to determining whether
     *  a known element is a member of this subset
     */
    bool                check_state( index_type idx ) const;

    /**
     *  Returns number of blocks allocated for bitset
     */
    size_t              num_blocks() const;

    /**
     *  Returns the number of elements in subset
     */
    size_t              count() const;

    /**
     * Returns the numbers the size of the subset in bits;
     *
     * NOTE: not necessarily equal to the number of total possible elements in the parent set
     */
    size_t              size() const;

    /**
     * Returns the maximum number of elements in parent set
     */
    size_t              max_size() const;

    /**
     *  block_iterator for subset
     */
    block_iterator begin();
    block_iterator end();

    cblock_iterator begin() const;
    cblock_iterator end() const;

    size_t find_first() const;
    size_t find_next( size_t idx ) const;

    template < class E, class B, class BM, class EK >
    friend bool operator==(const variable_subset< E, B, BM, EK> & lhs, const variable_subset< E, B, BM, EK> & rhs );

    template < class E, class B, class BM, class EK >
    friend std::ostream & operator<<( std::ostream & lhs, const variable_subset< E, B, BM, EK> & rhs );

    virtual ~variable_subset();

    CLOTHO_PROTECTED

    variable_subset(powerset_type * p);
    variable_subset(powerset_type * p, const bitset_type & b);
    variable_subset( const variable_subset & vs );

    powerset_type *       m_parent;
    bitset_type         m_data;
//    unsigned int        m_ref_count;
};

#define TEMPLATE_HEADER template < class Element, class Block, class BlockMap, class ElementKeyer >
#define SUBSET_SPECIALIZATION variable_subset< Element, Block, BlockMap, ElementKeyer >
#define POWERSET_SPECIALIZATION SUBSET_SPECIALIZATION::powerset_type

TEMPLATE_HEADER
SUBSET_SPECIALIZATION::variable_subset( powerset_type * p ) :
    m_parent(p)
//    , m_ref_count(1)
{}

TEMPLATE_HEADER
SUBSET_SPECIALIZATION::variable_subset( powerset_type * p, const bitset_type & b ) :
    m_parent(p)
    , m_data( b )
//    , m_ref_count(1)
{}

TEMPLATE_HEADER
SUBSET_SPECIALIZATION::variable_subset( const variable_subset & vs ) :
    m_parent(vs.m_parent)
    , m_data( vs.m_data )
//    , m_ref_count(1)
{}

TEMPLATE_HEADER
SUBSET_SPECIALIZATION::~variable_subset() {}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::powerset_type * SUBSET_SPECIALIZATION::getParent() const {
    return m_parent;
}

TEMPLATE_HEADER
bool SUBSET_SPECIALIZATION::isSameFamily( pointer p ) const {
    return this->m_parent == p->m_parent;
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::pointer SUBSET_SPECIALIZATION::clone() const {
    pointer sub = this->m_parent->create_subset( m_data );
    return sub;
}

//TEMPLATE_HEADER
//void SUBSET_SPECIALIZATION::copy() {
//    ++m_ref_count;
//}
//
//TEMPLATE_HEADER
//void SUBSET_SPECIALIZATION::release() {
//    --m_ref_count;
//}
//
//TEMPLATE_HEADER
//unsigned int SUBSET_SPECIALIZATION::ref_count() const {
//    return m_ref_count;
//}

TEMPLATE_HEADER
bool    SUBSET_SPECIALIZATION::operator[]( const value_type & elem ) {
    typename powerset_type::element_index_type idx = m_parent->find( elem );

    if( 0 <=  idx && idx < m_data.size() ) {
        return m_data[idx];
    }
    return false;
}

TEMPLATE_HEADER
std::pair< typename SUBSET_SPECIALIZATION::powerset_type::element_index_type, bool >   SUBSET_SPECIALIZATION::addElement( const value_type & elem ) {
    std::pair< typename powerset_type::element_index_type, bool > res = m_parent->find_or_create( elem );

    if( res.first == powerset_type::npos ) return res;

    if( res.first >= m_data.size() ) {
        m_data.resize( res.first + 1, false );
    }
    m_data[ res.first ] = true;

    return res;
}

TEMPLATE_HEADER
void SUBSET_SPECIALIZATION::removeElement( const value_type & elem ) {
    typename powerset_type::element_index_type idx = m_parent->find( elem );

    if( idx == powerset_type::npos || m_data.size() <= idx ) return;

    m_data[idx] = false;
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::count( ) const {
    return m_data.count();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::num_blocks( ) const {
    return m_data.num_blocks();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::size() const {
    return m_data.size();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::max_size() const {
    return m_parent->variable_allocated_size();
}

TEMPLATE_HEADER
bool SUBSET_SPECIALIZATION::check_state( index_type idx ) const {
    return m_data[idx];
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::block_iterator SUBSET_SPECIALIZATION::begin() {
    return m_data.m_bits.begin();
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::block_iterator SUBSET_SPECIALIZATION::end() {
    return m_data.m_bits.end();
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::cblock_iterator SUBSET_SPECIALIZATION::begin() const {
    return m_data.m_bits.begin();
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::cblock_iterator SUBSET_SPECIALIZATION::end() const {
    return m_data.m_bits.end();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::find_first() const {
    return m_data.find_first();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::find_next( size_t idx ) const {
    return m_data.find_next( idx );
}

/**
 * Equality of variable_subsets.
 *
 * Note the dynamic_bitset::operator== compares size() of bitsets; if they are not equal the
 * sets.  However, we only attempt to maintain minimal subsets.  That is, we allow a variable
 * length zero extention of a subset to exist.  Therefore, we compare the
 * common prefix length of blocks, then require the longer sequence to be all 0s there after.
 */
TEMPLATE_HEADER
inline bool operator==( const SUBSET_SPECIALIZATION & lhs, const SUBSET_SPECIALIZATION & rhs ) {
    if( lhs.m_parent != rhs.m_parent ) return false;

    typename SUBSET_SPECIALIZATION::cblock_iterator lit = lhs.m_data.m_bits.begin(), lend = lhs.m_data.m_bits.end();
    typename SUBSET_SPECIALIZATION::cblock_iterator rit = rhs.m_data.m_bits.begin(), rend = rhs.m_data.m_bits.end();

    bool is_eq = true;
    while( is_eq ) {
        if( lit == lend ) {
            while( is_eq && rit != rend) {
                is_eq = ((*rit++) == 0);
            }
            break;
        }

        if( rit == rend ) {
            while(is_eq && lit != lend ) {
                is_eq = ((*lit++) == 0);
            }
            break;
        }

        is_eq = ((*lit++) == (*rit++));
    }
    return is_eq;
}

TEMPLATE_HEADER
std::ostream & operator<<( std::ostream & lhs, const SUBSET_SPECIALIZATION & rhs ) {
    lhs << "{" << rhs.m_data << "; " << rhs.m_data.count() << "}";
    return lhs;
}

}   // namespace powersets
}   // namespace clotho
#endif  // VARIABLE_SUBSET_HPP_
<commit_msg>Added iterator include<commit_after>#ifndef VARIABLE_SUBSET_HPP_
#define VARIABLE_SUBSET_HPP_

#include "clotho/powerset/config.hpp"

#include <iostream>
#include "clotho/powerset/powerset.hpp"

namespace clotho {
namespace powersets {

template < class Element, class Block = unsigned long, class BlockMap = block_map< Element, Block>, class ElementKeyer = element_key_of< Element > >
class variable_subset {
public:
    typedef variable_subset< Element, Block, BlockMap, ElementKeyer > self_type;
    typedef Element value_type;

    typedef clotho::powersets::powerset< Element, variable_subset< Element, Block, BlockMap, ElementKeyer >, Block, BlockMap, ElementKeyer > powerset_type;
    typedef boost::dynamic_bitset< unsigned long > bitset_type;
    typedef size_t index_type;

    typedef std::vector< bitset_type::block_type, bitset_type::allocator_type >::iterator block_iterator;
    typedef std::vector< bitset_type::block_type, bitset_type::allocator_type >::const_iterator cblock_iterator;

    typedef typename powerset_type::subset_ptr pointer;

    friend class clotho::powersets::powerset< Element, variable_subset< Element, Block, BlockMap, ElementKeyer >, Block, BlockMap, ElementKeyer >;

    pointer clone() const;

//    void    copy();
//    void                release();
//
//    unsigned int        ref_count() const;

    powerset_type *     getParent() const;

    bool                isSameFamily( pointer other ) const;

    std::pair< typename powerset_type::element_index_type, bool >   addElement( const value_type & elem );
    void                removeElement( const value_type & elem );

    /**
     *  Returns whether an element is a member of this subset
     */
    bool                operator[]( const value_type & elem );

    /**
     *  Returns whether bit index is set; equivalent to determining whether
     *  a known element is a member of this subset
     */
    bool                check_state( index_type idx ) const;

    /**
     *  Returns number of blocks allocated for bitset
     */
    size_t              num_blocks() const;

    /**
     *  Returns the number of elements in subset
     */
    size_t              count() const;

    /**
     * Returns the numbers the size of the subset in bits;
     *
     * NOTE: not necessarily equal to the number of total possible elements in the parent set
     */
    size_t              size() const;

    /**
     * Returns the maximum number of elements in parent set
     */
    size_t              max_size() const;

    /**
     *  block_iterator for subset
     */
    block_iterator begin();
    block_iterator end();

    cblock_iterator begin() const;
    cblock_iterator end() const;

    size_t find_first() const;
    size_t find_next( size_t idx ) const;

    template < class E, class B, class BM, class EK >
    friend bool operator==(const variable_subset< E, B, BM, EK> & lhs, const variable_subset< E, B, BM, EK> & rhs );

    template < class E, class B, class BM, class EK >
    friend std::ostream & operator<<( std::ostream & lhs, const variable_subset< E, B, BM, EK> & rhs );

    virtual ~variable_subset();

    CLOTHO_PROTECTED

    variable_subset(powerset_type * p);
    variable_subset(powerset_type * p, const bitset_type & b);
    variable_subset( const variable_subset & vs );

    powerset_type *       m_parent;
    bitset_type         m_data;
//    unsigned int        m_ref_count;
};

#define TEMPLATE_HEADER template < class Element, class Block, class BlockMap, class ElementKeyer >
#define SUBSET_SPECIALIZATION variable_subset< Element, Block, BlockMap, ElementKeyer >
#define POWERSET_SPECIALIZATION SUBSET_SPECIALIZATION::powerset_type

TEMPLATE_HEADER
SUBSET_SPECIALIZATION::variable_subset( powerset_type * p ) :
    m_parent(p)
//    , m_ref_count(1)
{}

TEMPLATE_HEADER
SUBSET_SPECIALIZATION::variable_subset( powerset_type * p, const bitset_type & b ) :
    m_parent(p)
    , m_data( b )
//    , m_ref_count(1)
{}

TEMPLATE_HEADER
SUBSET_SPECIALIZATION::variable_subset( const variable_subset & vs ) :
    m_parent(vs.m_parent)
    , m_data( vs.m_data )
//    , m_ref_count(1)
{}

TEMPLATE_HEADER
SUBSET_SPECIALIZATION::~variable_subset() {}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::powerset_type * SUBSET_SPECIALIZATION::getParent() const {
    return m_parent;
}

TEMPLATE_HEADER
bool SUBSET_SPECIALIZATION::isSameFamily( pointer p ) const {
    return this->m_parent == p->m_parent;
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::pointer SUBSET_SPECIALIZATION::clone() const {
    pointer sub = this->m_parent->create_subset( m_data );
    return sub;
}

//TEMPLATE_HEADER
//void SUBSET_SPECIALIZATION::copy() {
//    ++m_ref_count;
//}
//
//TEMPLATE_HEADER
//void SUBSET_SPECIALIZATION::release() {
//    --m_ref_count;
//}
//
//TEMPLATE_HEADER
//unsigned int SUBSET_SPECIALIZATION::ref_count() const {
//    return m_ref_count;
//}

TEMPLATE_HEADER
bool    SUBSET_SPECIALIZATION::operator[]( const value_type & elem ) {
    typename powerset_type::element_index_type idx = m_parent->find( elem );

    if( 0 <=  idx && idx < m_data.size() ) {
        return m_data[idx];
    }
    return false;
}

TEMPLATE_HEADER
std::pair< typename SUBSET_SPECIALIZATION::powerset_type::element_index_type, bool >   SUBSET_SPECIALIZATION::addElement( const value_type & elem ) {
    std::pair< typename powerset_type::element_index_type, bool > res = m_parent->find_or_create( elem );

    if( res.first == powerset_type::npos ) return res;

    if( res.first >= m_data.size() ) {
        m_data.resize( res.first + 1, false );
    }
    m_data[ res.first ] = true;

    return res;
}

TEMPLATE_HEADER
void SUBSET_SPECIALIZATION::removeElement( const value_type & elem ) {
    typename powerset_type::element_index_type idx = m_parent->find( elem );

    if( idx == powerset_type::npos || m_data.size() <= idx ) return;

    m_data[idx] = false;
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::count( ) const {
    return m_data.count();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::num_blocks( ) const {
    return m_data.num_blocks();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::size() const {
    return m_data.size();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::max_size() const {
    return m_parent->variable_allocated_size();
}

TEMPLATE_HEADER
bool SUBSET_SPECIALIZATION::check_state( index_type idx ) const {
    return m_data[idx];
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::block_iterator SUBSET_SPECIALIZATION::begin() {
    return m_data.m_bits.begin();
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::block_iterator SUBSET_SPECIALIZATION::end() {
    return m_data.m_bits.end();
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::cblock_iterator SUBSET_SPECIALIZATION::begin() const {
    return m_data.m_bits.begin();
}

TEMPLATE_HEADER
typename SUBSET_SPECIALIZATION::cblock_iterator SUBSET_SPECIALIZATION::end() const {
    return m_data.m_bits.end();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::find_first() const {
    return m_data.find_first();
}

TEMPLATE_HEADER
size_t SUBSET_SPECIALIZATION::find_next( size_t idx ) const {
    return m_data.find_next( idx );
}

/**
 * Equality of variable_subsets.
 *
 * Note the dynamic_bitset::operator== compares size() of bitsets; if they are not equal the
 * sets.  However, we only attempt to maintain minimal subsets.  That is, we allow a variable
 * length zero extention of a subset to exist.  Therefore, we compare the
 * common prefix length of blocks, then require the longer sequence to be all 0s there after.
 */
TEMPLATE_HEADER
inline bool operator==( const SUBSET_SPECIALIZATION & lhs, const SUBSET_SPECIALIZATION & rhs ) {
    if( lhs.m_parent != rhs.m_parent ) return false;

    typename SUBSET_SPECIALIZATION::cblock_iterator lit = lhs.m_data.m_bits.begin(), lend = lhs.m_data.m_bits.end();
    typename SUBSET_SPECIALIZATION::cblock_iterator rit = rhs.m_data.m_bits.begin(), rend = rhs.m_data.m_bits.end();

    bool is_eq = true;
    while( is_eq ) {
        if( lit == lend ) {
            while( is_eq && rit != rend) {
                is_eq = ((*rit++) == 0);
            }
            break;
        }

        if( rit == rend ) {
            while(is_eq && lit != lend ) {
                is_eq = ((*lit++) == 0);
            }
            break;
        }

        is_eq = ((*lit++) == (*rit++));
    }
    return is_eq;
}

TEMPLATE_HEADER
std::ostream & operator<<( std::ostream & lhs, const SUBSET_SPECIALIZATION & rhs ) {
    lhs << "{" << rhs.m_data << "; " << rhs.m_data.count() << "}";
    return lhs;
}

}   // namespace powersets
}   // namespace clotho

#include "clotho/powerset/variable_subset_iterator.hpp"

#endif  // VARIABLE_SUBSET_HPP_
<|endoftext|>


<commit_before>// @(#)root/test:$name:  $:$id: stressSpectrum.cxx,v 1.15 2002/10/25 10:47:51 rdm exp $
// Author: Rene Brun 17/01/2006

/////////////////////////////////////////////////////////////////
//
//    TSPectrum test suite
//    ====================
//
// This stress program tests many elements of the TSpectrum, TSpectrum2 classes.
//
// To run in batch, do
//   stressSpectrum        : run 100 experiments with graphics (default)
//   stressSpectrum 1000   : run 1000 experiments with graphics
//   stressSpectrum -b 100 : run 100 experiments in batch mode
//
// To run interactively, do
// root -b
//  Root > .x stressSpectrum.cxx      : run 100 experiments with graphics (default)
//  Root > .x stressSpectrum.cxx(20)  : run 20 experiments
//  Root > .x stressSpectrum.cxx+(30) : run 30 experiments via ACLIC
//
// Several tests are run sequentially. Each test will produce one line (Test OK or Test FAILED) .
// At the end of the test a table is printed showing the global results
// Real Time and Cpu Time.
// One single number (ROOTMARKS) is also calculated showing the relative
// performance of your machine compared to a reference machine
// a Pentium IV 3.0 Ghz) with 512 MBytes of memory
// and 120 GBytes IDE disk.
//
// An example of output when all the tests run OK is shown below:
//
//////////////////////////////////////////////////////////////////////////
//                                                                      //
//****************************************************************************
//*  Starting  stress S P E C T R U M                                        *
//****************************************************************************
//Peak1 ; found = 64.31/ 68.94, good = 67.26/ 67.11, ghost = 6.79/ 8.56,--- OK
//****************************************************************************
//stressSpectrum: Real Time =  19.37 seconds Cpu Time =  19.37 seconds
//****************************************************************************
//*  ROOTMARKS = 413.1   *  Root5.09/01   20051216/1229//Peak1 ; found = 34.22/ 68.94, good = 69.20/ 67.11, ghost =10.60/ 8.56,--- OK
//****************************************************************************

#include "TApplication.h"
#include "TBenchmark.h"
#include "TCanvas.h"
#include "TH1.h"
#include "TF1.h"
#include "TRandom.h"
#include "TSpectrum.h"
#include "TStyle.h"
#include "Riostream.h"

Int_t npeaks;
Double_t fpeaks(Double_t *x, Double_t *par) {
   Double_t result = par[0] + par[1]*x[0];
   for (Int_t p=0;p<npeaks;p++) {
      Double_t norm  = par[3*p+2];
      Double_t mean  = par[3*p+3];
      Double_t sigma = par[3*p+4];
      result += norm*TMath::Gaus(x[0],mean,sigma);
   }
   return result;
}
void findPeaks(Int_t pmin, Int_t pmax, Int_t &nfound, Int_t &ngood, Int_t &nghost) {
   npeaks = (Int_t)gRandom->Uniform(pmin,pmax);
   Int_t nbins = 500;
   Double_t dxbins = 2;
   TH1F *h = new TH1F("h","test",nbins,0,nbins*dxbins);
   //generate n peaks at random
   Double_t par[3000];
   par[0] = 0.8;
   par[1] = -0.6/1000;
   Int_t p,pf;
   for (p=0;p<npeaks;p++) {
      par[3*p+2] = 1;
      par[3*p+3] = 10+gRandom->Rndm()*(nbins-20)*dxbins;
      par[3*p+4] = 3+2*gRandom->Rndm();
   }
   TF1 *f = new TF1("f",fpeaks,0,nbins*dxbins,2+3*npeaks);
   f->SetNpx(1000);
   f->SetParameters(par);
   h->FillRandom("f",200000);
   TSpectrum *s = new TSpectrum(4*npeaks);
   nfound = s->Search(h,2,"goff");
   //Search found peaks
   ngood = 0;
   Float_t *xpeaks = s->GetPositionX();
   for (p=0;p<npeaks;p++) {
      for (Int_t pf=0;pf<nfound;pf++) {
         Double_t dx = TMath::Abs(xpeaks[pf] - par[3*p+3]);
         if (dx <dxbins) ngood++;
      }
   }
   //Search ghost peaks
   nghost = 0;
   for (pf=0;pf<nfound;pf++) {
      Int_t nf=0;
      for (Int_t p=0;p<npeaks;p++) {
         Double_t dx = TMath::Abs(xpeaks[pf] - par[3*p+3]);
         if (dx <dxbins) nf++;
      }
      if (nf == 0) nghost++;
   }
   delete f;
   delete h;
   delete s;
}
#ifndef __CINT__
void stressSpectrum(Int_t ntimes) {
#else
void stressSpectrum(Int_t ntimes=100) {
#endif
   cout << "****************************************************************************" <<endl;
   cout << "*  Starting  stress S P E C T R U M                                        *" <<endl;
   cout << "****************************************************************************" <<endl;
   gBenchmark->Start("stressSpectrum");
   Int_t pmin = 5;
   Int_t pmax = 55;
   TCanvas *c1 = new TCanvas("c1","Spectrum results",10,10,800,800);
   c1->Divide(2,2);
   gStyle->SetOptFit();
   TH1F *hpeaks = new TH1F("hpeaks","Number of peaks",pmax-pmin,pmin,pmax);
   TH1F *hfound = new TH1F("hfound","% peak founds",100,0,100);
   TH1F *hgood  = new TH1F("hgood", "% good peaks",100,0,100);
   TH1F *hghost = new TH1F("hghost","% ghost peaks",100,0,100);
   Int_t nfound,ngood,nghost;
   for (Int_t i=0;i<ntimes;i++) {
      findPeaks(pmin,pmax,nfound,ngood,nghost);
      hpeaks->Fill(npeaks);
      hfound->Fill(100*Double_t(nfound)/Double_t(npeaks));
      hgood->Fill(100*Double_t(ngood)/Double_t(npeaks));
      hghost->Fill(100*Double_t(nghost)/Double_t(npeaks));
      //printf("npeaks = %d, nfound = %d, ngood = %d, nghost = %d\n",npeaks,nfound,ngood,nghost);
   }
   c1->cd(1);
   hpeaks->Fit("pol1","lq");
   c1->cd(2);
   hfound->Fit("gaus","lq");
   c1->cd(3);
   hgood->Fit("gaus","lq");
   c1->cd(4);
   hghost->Fit("gaus","lq","",0,30);
   c1->cd();
   Double_t p1  = hfound->GetFunction("gaus")->GetParameter(1);
   Double_t ep1 = hfound->GetFunction("gaus")->GetParError(1);
   Double_t p2  = hgood->GetFunction("gaus")->GetParameter(1);
   Double_t ep2 = hgood->GetFunction("gaus")->GetParError(1);
   Double_t p3  = hghost->GetFunction("gaus")->GetParameter(1);
   Double_t ep3 = hghost->GetFunction("gaus")->GetParError(1);
   Double_t p1ref = 68.94; //ref numbers obtained with ntimes=1000
   Double_t p2ref = 67.11;
   Double_t p3ref =  8.56;
   Double_t reftime100 = 10.0; //pcbrun compiled

   //printf("p1=%g+-%g, p2=%g+-%g, p3=%g+-%g\n",p1,ep1,p2,ep2,p3,ep3);

   gBenchmark->Stop ("stressSpectrum");
   Double_t ct = gBenchmark->GetCpuTime("stressSpectrum");
   const Double_t rootmarks = 800*reftime100*ntimes/(100*ct);
   char sok[20];
   if (TMath::Abs(p1ref-p1) < 2*ep1 && TMath::Abs(p2ref-p2) < 2*ep2  && TMath::Abs(p3ref-p3) < 2*ep3 ) {
      sprintf(sok,"OK");
   } else {
      sprintf(sok,"failed");
   }
   printf("Peak1 ; found =%6.2f/%6.2f, good =%6.2f/%6.2f, ghost =%5.2f/%5.2f,--- %s\n",
          p1,p1ref,p2,p2ref,p3,p3ref,sok);
   printf("****************************************************************************\n");

   gBenchmark->Print("stressSpectrum");
   printf("****************************************************************************\n");
   printf("*  ROOTMARKS =%6.1f   *  Root%-8s  %d/%d\n",rootmarks,gROOT->GetVersion(),
         gROOT->GetVersionDate(),gROOT->GetVersionTime());
   printf("****************************************************************************\n");
}
#ifndef __CINT__

int main(int argc, char **argv)
{
   TApplication theApp("App", &argc, argv);
   gBenchmark = new TBenchmark();
   Int_t ntimes = 100;
   if (argc > 1)  ntimes = atoi(argv[1]);
   stressSpectrum(ntimes);
   return 0;
}

#endif
<commit_msg>Extend this stress program to also test the new class TSpectrum2<commit_after>// @(#)root/test:$name:  $:$id: stressSpectrum.cxx,v 1.15 2002/10/25 10:47:51 rdm exp $
// Author: Rene Brun 17/01/2006

/////////////////////////////////////////////////////////////////
//
//    TSPectrum test suite
//    ====================
//
// This stress program tests many elements of the TSpectrum, TSpectrum2 classes.
//
// To run in batch, do
//   stressSpectrum        : run 100 experiments with graphics (default)
//   stressSpectrum 1000   : run 1000 experiments with graphics
//   stressSpectrum -b 200 : run 200 experiments in batch mode
//   stressSpectrum -b     : run 100 experiments in batch mode
//
// To run interactively, do
// root -b
//  Root > .x stressSpectrum.cxx      : run 100 experiments with graphics (default)
//  Root > .x stressSpectrum.cxx(20)  : run 20 experiments
//  Root > .x stressSpectrum.cxx+(30) : run 30 experiments via ACLIC
//
// Several tests are run sequentially. Each test will produce one line (Test OK or Test FAILED) .
// At the end of the test a table is printed showing the global results
// Real Time and Cpu Time.
// One single number (ROOTMARKS) is also calculated showing the relative
// performance of your machine compared to a reference machine
// a Pentium IV 3.0 Ghz) with 512 MBytes of memory
// and 120 GBytes IDE disk.
//
// An example of output when all the tests run OK is shown below:
//
//////////////////////////////////////////////////////////////////////////
//                                                                      //
//****************************************************************************
//*  Starting  stress S P E C T R U M                                        *
//****************************************************************************
//Peak1 : found = 62.52/ 68.94, good = 66.64/ 67.11, ghost = 6.52/ 8.56,--- OK
//Peak2 : found =173/300, good =173, ghost =7,----------------------------- OK
//****************************************************************************
//stressSpectrum: Real Time =  19.86 seconds Cpu Time =  19.04 seconds
//****************************************************************************
//*  ROOTMARKS = 810.9   *  Root5.09/01   20051216/1229
//****************************************************************************

#include "TApplication.h"
#include "TBenchmark.h"
#include "TCanvas.h"
#include "TH2.h"
#include "TF2.h"
#include "TRandom.h"
#include "TSpectrum.h"
#include "TSpectrum2.h"
#include "TStyle.h"
#include "Riostream.h"

Int_t npeaks;
Double_t fpeaks(Double_t *x, Double_t *par) {
   Double_t result = par[0] + par[1]*x[0];
   for (Int_t p=0;p<npeaks;p++) {
      Double_t norm  = par[3*p+2];
      Double_t mean  = par[3*p+3];
      Double_t sigma = par[3*p+4];
      result += norm*TMath::Gaus(x[0],mean,sigma);
   }
   return result;
}
Double_t fpeaks2(Double_t *x, Double_t *par) {
   Double_t result = 0.1;
   for (Int_t p=0;p<npeaks;p++) {
      Double_t norm   = par[5*p+0];
      Double_t mean1  = par[5*p+1];
      Double_t sigma1 = par[5*p+2];
      Double_t mean2  = par[5*p+3];
      Double_t sigma2 = par[5*p+4];
      result += norm*TMath::Gaus(x[0],mean1,sigma1)*TMath::Gaus(x[1],mean2,sigma2);
   }
   return result;
}
void findPeaks(Int_t pmin, Int_t pmax, Int_t &nfound, Int_t &ngood, Int_t &nghost) {
   npeaks = (Int_t)gRandom->Uniform(pmin,pmax);
   Int_t nbins = 500;
   Double_t dxbins = 2;
   TH1F *h = new TH1F("h","test",nbins,0,nbins*dxbins);
   //generate n peaks at random
   Double_t par[3000];
   par[0] = 0.8;
   par[1] = -0.6/1000;
   Int_t p,pf;
   for (p=0;p<npeaks;p++) {
      par[3*p+2] = 1;
      par[3*p+3] = 10+gRandom->Rndm()*(nbins-20)*dxbins;
      par[3*p+4] = 3+2*gRandom->Rndm();
   }
   TF1 *f = new TF1("f",fpeaks,0,nbins*dxbins,2+3*npeaks);
   f->SetNpx(1000);
   f->SetParameters(par);
   h->FillRandom("f",200000);
   TSpectrum *s = new TSpectrum(4*npeaks);
   nfound = s->Search(h,2,"goff");
   //Search found peaks
   ngood = 0;
   Float_t *xpeaks = s->GetPositionX();
   for (p=0;p<npeaks;p++) {
      for (Int_t pf=0;pf<nfound;pf++) {
         Double_t dx = TMath::Abs(xpeaks[pf] - par[3*p+3]);
         if (dx <dxbins) ngood++;
      }
   }
   //Search ghost peaks
   nghost = 0;
   for (pf=0;pf<nfound;pf++) {
      Int_t nf=0;
      for (Int_t p=0;p<npeaks;p++) {
         Double_t dx = TMath::Abs(xpeaks[pf] - par[3*p+3]);
         if (dx <dxbins) nf++;
      }
      if (nf == 0) nghost++;
   }
   delete f;
   delete h;
   delete s;
}

void stress1(Int_t ntimes) {
   Int_t pmin = 5;
   Int_t pmax = 55;
   TCanvas *c1 = new TCanvas("c1","Spectrum results",10,10,800,800);
   c1->Divide(2,2);
   gStyle->SetOptFit();
   TH1F *hpeaks = new TH1F("hpeaks","Number of peaks",pmax-pmin,pmin,pmax);
   TH1F *hfound = new TH1F("hfound","% peak founds",100,0,100);
   TH1F *hgood  = new TH1F("hgood", "% good peaks",100,0,100);
   TH1F *hghost = new TH1F("hghost","% ghost peaks",100,0,100);
   Int_t nfound,ngood,nghost;
   for (Int_t i=0;i<ntimes;i++) {
      findPeaks(pmin,pmax,nfound,ngood,nghost);
      hpeaks->Fill(npeaks);
      hfound->Fill(100*Double_t(nfound)/Double_t(npeaks));
      hgood->Fill(100*Double_t(ngood)/Double_t(npeaks));
      hghost->Fill(100*Double_t(nghost)/Double_t(npeaks));
      //printf("npeaks = %d, nfound = %d, ngood = %d, nghost = %d\n",npeaks,nfound,ngood,nghost);
   }
   c1->cd(1);
   hpeaks->Fit("pol1","lq");
   c1->cd(2);
   hfound->Fit("gaus","lq");
   c1->cd(3);
   hgood->Fit("gaus","lq");
   c1->cd(4);
   hghost->Fit("gaus","lq","",0,30);
   c1->cd();
   Double_t p1  = hfound->GetFunction("gaus")->GetParameter(1);
   Double_t ep1 = hfound->GetFunction("gaus")->GetParError(1);
   Double_t p2  = hgood->GetFunction("gaus")->GetParameter(1);
   Double_t ep2 = hgood->GetFunction("gaus")->GetParError(1);
   Double_t p3  = hghost->GetFunction("gaus")->GetParameter(1);
   Double_t ep3 = hghost->GetFunction("gaus")->GetParError(1);
   Double_t p1ref = 68.94; //ref numbers obtained with ntimes=1000
   Double_t p2ref = 67.11;
   Double_t p3ref =  8.56;

   //printf("p1=%g+-%g, p2=%g+-%g, p3=%g+-%g\n",p1,ep1,p2,ep2,p3,ep3);

   char sok[20];
   if (TMath::Abs(p1ref-p1) < 2*ep1 && TMath::Abs(p2ref-p2) < 2*ep2  && TMath::Abs(p3ref-p3) < 2*ep3 ) {
      sprintf(sok,"OK");
   } else {
      sprintf(sok,"failed");
   }
   printf("Peak1 : found =%6.2f/%6.2f, good =%6.2f/%6.2f, ghost =%5.2f/%5.2f,--- %s\n",
          p1,p1ref,p2,p2ref,p3,p3ref,sok);
}
void stress2(Int_t np2) {
   npeaks = np2;
   TRandom r;
   Int_t nbinsx = 200;
   Int_t nbinsy = 200;
   Double_t xmin   = 0;
   Double_t xmax   = (Double_t)nbinsx;
   Double_t ymin   = 0;
   Double_t ymax   = (Double_t)nbinsy;
   Double_t dx = (xmax-xmin)/nbinsx;
   Double_t dy = (ymax-ymin)/nbinsy;
   TH2F *h2 = new TH2F("h2","test",nbinsx,xmin,xmax,nbinsy,ymin,ymax);
   h2->SetStats(0);
   //generate n peaks at random
   Double_t par[3000];
   Int_t p;
   for (p=0;p<npeaks;p++) {
      par[5*p+0] = r.Uniform(0.2,1);
      par[5*p+1] = r.Uniform(xmin,xmax);
      par[5*p+2] = r.Uniform(dx,5*dx);
      par[5*p+3] = r.Uniform(ymin,ymax);
      par[5*p+4] = r.Uniform(dy,5*dy);
   }
   TF2 *f2 = new TF2("f2",fpeaks2,xmin,xmax,ymin,ymax,5*npeaks);
   f2->SetNpx(100);
   f2->SetNpy(100);
   f2->SetParameters(par);
   h2->FillRandom("f2",500000);
   //now the real stuff
   TSpectrum2 *s = new TSpectrum2(2*npeaks);
   Int_t nfound = s->Search(h2,2,"goff");

   //searching good and ghost peaks (approximation)
   Int_t pf,ngood = 0;
   Float_t *xpeaks = s->GetPositionX();
   Float_t *ypeaks = s->GetPositionY();
   for (p=0;p<npeaks;p++) {
      for (Int_t pf=0;pf<nfound;pf++) {
         Double_t diffx = TMath::Abs(xpeaks[pf] - par[5*p+1]);
         Double_t diffy = TMath::Abs(ypeaks[pf] - par[5*p+3]);
         if (diffx < 2*dx && diffy < 2*dy) ngood++;
      }
   }
   if (ngood > nfound) ngood = nfound;
   //Search ghost peaks (approximation)
   Int_t nghost = 0;
   for (pf=0;pf<nfound;pf++) {
      Int_t nf=0;
      for (Int_t p=0;p<npeaks;p++) {
         Double_t diffx = TMath::Abs(xpeaks[pf] - par[5*p+1]);
         Double_t diffy = TMath::Abs(ypeaks[pf] - par[5*p+3]);
         if (diffx < 2*dx && diffy < 2*dy) nf++;
      }
      if (nf == 0) nghost++;
   }

   delete s;
   delete f2;
   delete h2;
   Int_t nfoundRef = 173;
   Int_t ngoodRef  = 173;
   Int_t nghostRef = 7;
   char sok[20];
   if (nfound == nfoundRef && ngood == ngoodRef && nghost == nghostRef) {
      sprintf(sok,"OK");
   } else {
      sprintf(sok,"failed");
   }
   printf("Peak2 : found =%d/%d, good =%d, ghost =%d,----------------------------- %s\n",
          nfound,npeaks,ngood,nghost,sok);
}

#ifndef __CINT__
void stressSpectrum(Int_t ntimes) {
#else
void stressSpectrum(Int_t ntimes=100) {
#endif
   cout << "****************************************************************************" <<endl;
   cout << "*  Starting  stress S P E C T R U M                                        *" <<endl;
   cout << "****************************************************************************" <<endl;
   gBenchmark->Start("stressSpectrum");
   stress1(ntimes);
   stress2(300);
   gBenchmark->Stop ("stressSpectrum");
   Double_t reftime100 = 19.04; //pcbrun compiled
   Double_t ct = gBenchmark->GetCpuTime("stressSpectrum");
   const Double_t rootmarks = 800*reftime100*ntimes/(100*ct);
   printf("****************************************************************************\n");

   gBenchmark->Print("stressSpectrum");
   printf("****************************************************************************\n");
   printf("*  ROOTMARKS =%6.1f   *  Root%-8s  %d/%d\n",rootmarks,gROOT->GetVersion(),
         gROOT->GetVersionDate(),gROOT->GetVersionTime());
   printf("****************************************************************************\n");
}

#ifndef __CINT__

int main(int argc, char **argv)
{
   TApplication theApp("App", &argc, argv);
   gBenchmark = new TBenchmark();
   Int_t ntimes = 100;
   if (argc > 1)  ntimes = atoi(argv[1]);
   stressSpectrum(ntimes);
   return 0;
}

#endif
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*! \file Stochastic Gradient Descent (SGD) Implementation */

#ifndef DBN_STOCHASTIC_GRADIENT_DESCENT
#define DBN_STOCHASTIC_GRADIENT_DESCENT

namespace dll {

template<typename DBN>
struct sgd_trainer {
    using dbn_t = DBN;
    using weight = typename dbn_t::weight;

    static constexpr const std::size_t layers = dbn_t::layers;

    dbn_t& dbn;
    typename dbn_t::tuple_type& tuples;

    sgd_trainer(dbn_t& dbn) : dbn(dbn), tuples(dbn.tuples) {}

    void init_training(std::size_t /*batch_size*/){
        //TODO
    }

    template<typename RBM, typename Output, typename Errors>
    static void compute_gradients(RBM& rbm, std::size_t n_samples, const Output& output, const Errors& errors){
        using rbm_t = RBM;

        constexpr const auto n_inputs = rbm_t::num_visible;
        constexpr const auto n_outputs = rbm_t::num_hidden;

        rbm.w_grad = 0.0;
        rbm.b_grad = 0.0;
        rbm.c_grad = 0.0;

        //TODO Rewrite that as ETL expressions

        for(std::size_t i = 0; i < n_samples; ++i){
            for(std::size_t a = 0; a < n_inputs; ++a){
                for(std::size_t b = 0; b < n_outputs; ++b){
                    rbm.w_grad(a,b) += output[i][b] * errors[i][b];
                }
            }

            rbm.b_grad += errors[i];
        }

        rbm.w_grad /= n_samples;
        rbm.b_grad /= n_samples;
        rbm.c_grad /= n_samples;
    }

    template<typename RBM>
    void apply_gradients(RBM& rbm){
        using rbm_t = RBM;

        constexpr const auto n_inputs = rbm_t::num_visible;
        constexpr const auto n_outputs = rbm_t::num_hidden;

        auto learning_rate = dbn.learning_rate;

        rbm.w += learning_rate * rbm.w_grad;
        rbm.b += learning_rate * rbm.b_grad;
        rbm.c += learning_rate * rbm.c_grad;
    }

    template<typename T, typename L>
    void train_batch(std::size_t /*epoch*/, const dll::batch<T>& data_batch, const dll::batch<L>& label_batch){
        dll_assert(data_batch.size() == label_batch.size(), "Invalid sizes");

        auto n_samples = label_batch.size();
        constexpr const auto n_outputs = dbn_t::template num_hidden<layers - 1>();

        static std::vector<etl::fast_vector<weight, n_outputs>> outputs;
        outputs.resize(n_samples);

        for(std::size_t i = 0; i < n_samples; ++i){
            dbn.predict_weights(data_batch[i], outputs[i]);
        }

        static std::vector<etl::fast_vector<weight, n_outputs>> errors;
        errors.resize(n_samples);

        // Compute dE/dz_j for each output neuron
        for(std::size_t i = 0; i < n_samples; ++i){
            for(std::size_t j = 0; j < n_outputs; ++j){
                auto output = outputs[i][j];
                errors[i][j] = output * (1 - output) * (label_batch[i][j] - output);
            }
        }

        //TODO Update also the lower levels weights

        compute_gradients(dbn.template layer<layers -1>(), n_samples, outputs, errors);

        apply_gradients(dbn.template layer<layers - 1>());
    }
};

} //end of dbn namespace

#endif<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*! \file Stochastic Gradient Descent (SGD) Implementation */

#ifndef DBN_STOCHASTIC_GRADIENT_DESCENT
#define DBN_STOCHASTIC_GRADIENT_DESCENT

namespace dll {

template<typename DBN>
struct sgd_trainer {
    using dbn_t = DBN;
    using weight = typename dbn_t::weight;

    static constexpr const std::size_t layers = dbn_t::layers;

    dbn_t& dbn;
    typename dbn_t::tuple_type& tuples;

    sgd_trainer(dbn_t& dbn) : dbn(dbn), tuples(dbn.tuples) {}

    void init_training(std::size_t /*batch_size*/){
        //TODO
    }

    template<typename RBM>
    static void reset_gradients(RBM& rbm){
        rbm.w_grad = 0.0;
        rbm.b_grad = 0.0;
        rbm.c_grad = 0.0;
    }

    template<typename RBM, typename Output, typename Errors>
    static void compute_gradients(RBM& rbm, const Output& output, const Errors& errors){
        using rbm_t = RBM;

        constexpr const auto n_inputs = rbm_t::num_visible;
        constexpr const auto n_outputs = rbm_t::num_hidden;

        //TODO Rewrite that as ETL expressions

        for(std::size_t a = 0; a < n_inputs; ++a){
            for(std::size_t b = 0; b < n_outputs; ++b){
                rbm.w_grad(a,b) += output[b] * errors[b];
            }
        }

        rbm.b_grad += errors;
    }

    template<typename RBM>
    static void finalize_gradients(RBM& rbm, std::size_t n_samples){
        rbm.w_grad /= n_samples;
        rbm.b_grad /= n_samples;
        rbm.c_grad /= n_samples;
    }

    template<typename RBM>
    void apply_gradients(RBM& rbm){
        using rbm_t = RBM;

        constexpr const auto n_inputs = rbm_t::num_visible;
        constexpr const auto n_outputs = rbm_t::num_hidden;

        auto learning_rate = dbn.learning_rate;

        rbm.w += learning_rate * rbm.w_grad;
        rbm.b += learning_rate * rbm.b_grad;
        rbm.c += learning_rate * rbm.c_grad;
    }

    template<typename T, typename L>
    void train_batch(std::size_t /*epoch*/, const dll::batch<T>& data_batch, const dll::batch<L>& label_batch){
        dll_assert(data_batch.size() == label_batch.size(), "Invalid sizes");

        auto n_samples = label_batch.size();

        constexpr const auto n_outputs = dbn_t::template num_hidden<layers - 1>();

        //TODO Update also the lower levels weights

        reset_gradients(dbn.template layer<layers - 1>());

        for(std::size_t i = 0; i < n_samples; ++i){
            static etl::fast_vector<weight, n_outputs> outputs;

            dbn.predict_weights(data_batch[i], outputs);

            static etl::fast_vector<weight, n_outputs> errors;

            // Compute dE/dz_j for each output neuron
            for(std::size_t j = 0; j < n_outputs; ++j){
                auto observed = outputs[j];
                errors[j] = observed * (1 - observed) * (label_batch[i][j] - observed);
            }

            compute_gradients(dbn.template layer<layers - 1>(), outputs, errors);
        }

        finalize_gradients(dbn.template layer<layers - 1>(), n_samples);

        apply_gradients(dbn.template layer<layers - 1>());
    }
};

} //end of dbn namespace

#endif<|endoftext|>


<commit_before>
#include <togo/assert.hpp>
#include <togo/log.hpp>
#include <togo/fixed_array.hpp>
#include <togo/string.hpp>
#include <togo/system.hpp>

using namespace togo;

signed main() {
	TOGO_LOGF("num_cores = %u\n", system::num_cores());
	StringRef exec_dir = system::exec_dir();
	TOGO_LOGF("exec_dir: %.*s\n", exec_dir.size, exec_dir.data);
	TOGO_ASSERTE(system::secs_since_epoch() > 1407135980u);

	FixedArray<char, 256> wd_init{};
	unsigned const wd_init_size = system::working_dir(wd_init);
	TOGO_LOGF("wd_init: '%.*s'\n", string::size(wd_init), fixed_array::begin(wd_init));
	TOGO_ASSERTE(wd_init_size > 0 && wd_init_size == fixed_array::size(wd_init));

	system::set_working_dir("/");
	FixedArray<char, 256> wd_root{};
	unsigned const wd_root_size = system::working_dir(wd_root);
	TOGO_LOGF("wd_root: '%.*s'\n", string::size(wd_root), fixed_array::begin(wd_root));
	TOGO_ASSERTE(wd_root_size > 0 && wd_root_size == fixed_array::size(wd_root));
	TOGO_ASSERTE(string::compare_equal(wd_root, "/"));

	TOGO_LOG("\n");
	float const start = system::time_monotonic();
	TOGO_LOGF("start       : time_monotonic() = %.6f\n", start);
	system::sleep_ms(1000u);
	TOGO_LOGF("1000ms delay: time_monotonic() = %.6f\n", system::time_monotonic() - start);
	system::sleep_ms(100u);
	TOGO_LOGF("100ms delay : time_monotonic() = %.6f\n", system::time_monotonic() - start);
	system::sleep_ms(10u);
	TOGO_LOGF("10ms delay  : time_monotonic() = %.6f\n", system::time_monotonic() - start);
	system::sleep_ms(1u);
	TOGO_LOGF("1ms delay   : time_monotonic() = %.6f\n", system::time_monotonic() - start);

	return 0;
}
<commit_msg>test/system/general: moved delay calculations before costly calls.<commit_after>
#include <togo/assert.hpp>
#include <togo/log.hpp>
#include <togo/fixed_array.hpp>
#include <togo/string.hpp>
#include <togo/system.hpp>

using namespace togo;

signed main() {
	TOGO_LOGF("num_cores = %u\n", system::num_cores());
	StringRef exec_dir = system::exec_dir();
	TOGO_LOGF("exec_dir: %.*s\n", exec_dir.size, exec_dir.data);
	TOGO_ASSERTE(system::secs_since_epoch() > 1407135980u);

	FixedArray<char, 256> wd_init{};
	unsigned const wd_init_size = system::working_dir(wd_init);
	TOGO_LOGF("wd_init: '%.*s'\n", string::size(wd_init), fixed_array::begin(wd_init));
	TOGO_ASSERTE(wd_init_size > 0 && wd_init_size == fixed_array::size(wd_init));

	system::set_working_dir("/");
	FixedArray<char, 256> wd_root{};
	unsigned const wd_root_size = system::working_dir(wd_root);
	TOGO_LOGF("wd_root: '%.*s'\n", string::size(wd_root), fixed_array::begin(wd_root));
	TOGO_ASSERTE(wd_root_size > 0 && wd_root_size == fixed_array::size(wd_root));
	TOGO_ASSERTE(string::compare_equal(wd_root, "/"));

	TOGO_LOG("\n");
	float const start = system::time_monotonic();
	system::sleep_ms(1000u);
	float const d_1000ms = system::time_monotonic() - start;
	system::sleep_ms(100u);
	float const d_100ms = system::time_monotonic() - start;
	system::sleep_ms(10u);
	float const d_10ms = system::time_monotonic() - start;
	system::sleep_ms(1u);
	float const d_1ms = system::time_monotonic() - start;

	TOGO_LOGF("start       : time_monotonic() = %.6f\n", start);
	TOGO_LOGF("1000ms delay: time_monotonic() = %.6f\n", d_1000ms);
	TOGO_LOGF("100ms delay : time_monotonic() = %.6f\n", d_100ms);
	TOGO_LOGF("10ms delay  : time_monotonic() = %.6f\n", d_10ms);
	TOGO_LOGF("1ms delay   : time_monotonic() = %.6f\n", d_1ms);

	return 0;
}
<|endoftext|>


<commit_before>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/morphablemodel/EdgeTopology.hpp
 *
 * Copyright 2016 Patrik Huber
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#ifndef EDGETOPOLOGY_HPP_
#define EDGETOPOLOGY_HPP_

#include "cereal/cereal.hpp"
#include "cereal/types/array.hpp"
#include "cereal/types/vector.hpp"
#include "cereal/archives/json.hpp"

#include <array>
#include <vector>
#include <fstream>

namespace eos {
	namespace morphablemodel {

/**
 * @brief A struct containing a 3D shape model's edge topology.
 *
 * This struct contains all edges of a 3D mesh, and for each edge, it
 * contains the two faces and the two vertices that are adjacent to that
 * edge. This is used in the iterated closest edge fitting (ICEF).
 *
 * Note: The indices are 1-based, so 1 needs to be subtracted before using
 * them as mesh indices. An index of 0 as first array element means that
 * it's an edge that lies on the mesh boundary, i.e. they are only
 * adjacent to one face.
 * We should explore a less error-prone way to store this data, but that's
 * how it is done in Matlab by the original code.
 *
 * adjacent_faces.size() is equal to adjacent_vertices.size().
 */
struct EdgeTopology {
	std::vector<std::array<int, 2>> adjacent_faces; // num_edges x 2 matrix storing faces adjacent to each edge
	std::vector<std::array<int, 2>> adjacent_vertices; // num_edges x 2 matrix storing vertices adjacent to each edge

	friend class cereal::access;
	/**
	 * Serialises this class using cereal.
	 *
	 * @param[in] ar The archive to serialise to (or to serialise from).
	 */
	template<class Archive>
	void serialize(Archive& archive)
	{
		archive(CEREAL_NVP(adjacent_faces), CEREAL_NVP(adjacent_vertices));
	};
};

/**
 * Saves a 3DMM edge topology file to a json file.
 *
 * @param[in] edge_topology A model's edge topology.
 * @param[in] filename The file to write.
 * @throws std::runtime_error if unable to open the given file for writing.
 */
void save_edge_topology(EdgeTopology edge_topology, std::string filename)
{
	std::ofstream file(filename);
	if (file.fail()) {
		throw std::runtime_error("Error opening file for writing: " + filename);
	}
	cereal::JSONOutputArchive output_archive(file);
	output_archive(cereal::make_nvp("edge_topology", edge_topology));
};

/**
 * Load a 3DMM edge topology file from a json file.
 *
 * @param[in] filename The file to load the edge topology from.
 * @return A struct containing the edge topology.
 * @throws std::runtime_error if unable to open the given file for writing.
 */
EdgeTopology load_edge_topology(std::string filename)
{
	EdgeTopology edge_topology;
	std::ifstream file(filename);
	if (file.fail()) {
		throw std::runtime_error("Error opening file for reading: " + filename);
	}
	cereal::JSONInputArchive output_archive(file);
	output_archive(cereal::make_nvp("edge_topology", edge_topology));

	return edge_topology;
};

	} /* namespace morphablemodel */
} /* namespace eos */

#endif /* EDGETOPOLOGY_HPP_ */
<commit_msg>Added inline to EdgeTopology load/save functions<commit_after>/*
 * eos - A 3D Morphable Model fitting library written in modern C++11/14.
 *
 * File: include/eos/morphablemodel/EdgeTopology.hpp
 *
 * Copyright 2016 Patrik Huber
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#ifndef EDGETOPOLOGY_HPP_
#define EDGETOPOLOGY_HPP_

#include "cereal/cereal.hpp"
#include "cereal/types/array.hpp"
#include "cereal/types/vector.hpp"
#include "cereal/archives/json.hpp"

#include <array>
#include <vector>
#include <fstream>

namespace eos {
	namespace morphablemodel {

/**
 * @brief A struct containing a 3D shape model's edge topology.
 *
 * This struct contains all edges of a 3D mesh, and for each edge, it
 * contains the two faces and the two vertices that are adjacent to that
 * edge. This is used in the iterated closest edge fitting (ICEF).
 *
 * Note: The indices are 1-based, so 1 needs to be subtracted before using
 * them as mesh indices. An index of 0 as first array element means that
 * it's an edge that lies on the mesh boundary, i.e. they are only
 * adjacent to one face.
 * We should explore a less error-prone way to store this data, but that's
 * how it is done in Matlab by the original code.
 *
 * adjacent_faces.size() is equal to adjacent_vertices.size().
 */
struct EdgeTopology {
	std::vector<std::array<int, 2>> adjacent_faces; // num_edges x 2 matrix storing faces adjacent to each edge
	std::vector<std::array<int, 2>> adjacent_vertices; // num_edges x 2 matrix storing vertices adjacent to each edge

	friend class cereal::access;
	/**
	 * Serialises this class using cereal.
	 *
	 * @param[in] ar The archive to serialise to (or to serialise from).
	 */
	template<class Archive>
	void serialize(Archive& archive)
	{
		archive(CEREAL_NVP(adjacent_faces), CEREAL_NVP(adjacent_vertices));
	};
};

/**
 * Saves a 3DMM edge topology file to a json file.
 *
 * @param[in] edge_topology A model's edge topology.
 * @param[in] filename The file to write.
 * @throws std::runtime_error if unable to open the given file for writing.
 */
inline void save_edge_topology(EdgeTopology edge_topology, std::string filename)
{
	std::ofstream file(filename);
	if (file.fail()) {
		throw std::runtime_error("Error opening file for writing: " + filename);
	}
	cereal::JSONOutputArchive output_archive(file);
	output_archive(cereal::make_nvp("edge_topology", edge_topology));
};

/**
 * Load a 3DMM edge topology file from a json file.
 *
 * @param[in] filename The file to load the edge topology from.
 * @return A struct containing the edge topology.
 * @throws std::runtime_error if unable to open the given file for writing.
 */
inline EdgeTopology load_edge_topology(std::string filename)
{
	EdgeTopology edge_topology;
	std::ifstream file(filename);
	if (file.fail()) {
		throw std::runtime_error("Error opening file for reading: " + filename);
	}
	cereal::JSONInputArchive output_archive(file);
	output_archive(cereal::make_nvp("edge_topology", edge_topology));

	return edge_topology;
};

	} /* namespace morphablemodel */
} /* namespace eos */

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


<commit_before>//
// Copyright (c) 2014 CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-core
// hpp-core is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-core 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 Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core  If not, see
// <http://www.gnu.org/licenses/>.

#ifndef HPP_CORE_DIFFERENTIABLE_FUNCTION_HH
# define HPP_CORE_DIFFERENTIABLE_FUNCTION_HH

# include <boost/algorithm/string/replace.hpp>
# include <roboptim/core/indent.hh>
# include <hpp/core/fwd.hh>

namespace hpp {
  namespace core {
    /// Differentiable function of the robot configuration
    class DifferentiableFunction
    {
    public:
      virtual ~DifferentiableFunction () {}
      /// Evaluate the function at a given parameter.
      ///
      /// \note parameters should be of the correct size.
      void operator () (vectorOut_t result,
			ConfigurationIn_t argument) const
      {
	assert (result.size () == outputSize ());
	assert (argument.size () == inputSize ());
	impl_compute (result, argument);
      }
      /// Computes the jacobian.
      ///
      /// \retval jacobian jacobian will be stored in this argument
      /// \param argument point at which the jacobian will be computed
      void jacobian (matrixOut_t jacobian, ConfigurationIn_t argument) const
      {
	assert (argument.size () == inputSize ());
	assert (jacobian.rows () == outputSize ());
	assert (jacobian.cols () == inputDerivativeSize ());
	impl_jacobian (jacobian, argument);
      }

      /// Get dimension of input vector
      size_type inputSize () const
      {
	return inputSize_;
      }
      /// Get dimension of input derivative vector
      ///
      /// The dimension of configuration vectors might differ from the dimension
      /// of velocity vectors since some joints are represented by non minimal
      /// size vectors: e.g. quaternion for SO(3)
      size_type inputDerivativeSize () const
      {
	return inputDerivativeSize_;
      }
      /// Get dimension of output vector
      size_type  outputSize () const
      {
	return outputSize_;
      }
      /// \brief Get function name.
      ///
      /// \return Function name.
      const std::string& name () const
      {
	return name_;
      }

      /// Display object in a stream
      virtual std::ostream& print (std::ostream& o) const
      {
	if (this->name ().empty ())
	  return o << "Differentiable function";

	std::stringstream ss;
	ss << std::endl;
	char fill = o.fill (' ');
	ss << std::setw ((int)roboptim::indent (o))
	   << ""
	   << std::setfill (fill);
	std::string name = this->name ();
	boost::algorithm::replace_all (name, "\n", ss.str ());

	return o << name << " (differentiable function)";
      }

    protected:
      /// \brief Concrete class constructor should call this constructor.
      ///
      /// \param inputSize function arity
      /// \param outputSize result size
      /// \param name function's name
      DifferentiableFunction (size_type inputSize,
			      size_type inputDerivativeSize,
			      size_type outputSize,
			      std::string name = std::string ()) :
	inputSize_ (inputSize), inputDerivativeSize_ (inputDerivativeSize),
	outputSize_ (outputSize), name_ (name)
      {
      }

      /// User implementation of function evaluation
      virtual void impl_compute (vectorOut_t result,
				 ConfigurationIn_t argument) const = 0;

      virtual void impl_jacobian (matrixOut_t jacobian,
				  ConfigurationIn_t arg) const = 0;

    private:
      /// Dimension of input vector.
      size_type inputSize_;
      /// Dimension of input derivative
      size_type inputDerivativeSize_;
      /// Dimension of output vector
      size_type outputSize_;
      std::string name_;
    }; // class DifferentiableFunction
    inline std::ostream&
    operator<< (std::ostream& os, const DifferentiableFunction& f)
    {
      return f.print (os);
    }
  } // namespace core
} // namespace hpp

#endif // HPP_CORE_DIFFERENTIABLE_FUNCTION_HH
<commit_msg>DifferentiableFunction are parametric<commit_after>//
// Copyright (c) 2014 CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-core
// hpp-core is free software: you can redistribute it
// and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version
// 3 of the License, or (at your option) any later version.
//
// hpp-core 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 Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core  If not, see
// <http://www.gnu.org/licenses/>.

#ifndef HPP_CORE_DIFFERENTIABLE_FUNCTION_HH
# define HPP_CORE_DIFFERENTIABLE_FUNCTION_HH

# include <boost/algorithm/string/replace.hpp>
# include <roboptim/core/indent.hh>
# include <hpp/core/fwd.hh>

namespace hpp {
  namespace core {
    /// Differentiable function of the robot configuration
    class DifferentiableFunction
    {
    public:
      virtual ~DifferentiableFunction () {}
      /// Evaluate the function at a given parameter.
      ///
      /// \note parameters should be of the correct size.
      void operator () (vectorOut_t result,
			ConfigurationIn_t argument) const
      {
	assert (result.size () == outputSize ());
	assert (argument.size () == inputSize ());
	impl_compute (result, argument);
      }
      /// Computes the jacobian.
      ///
      /// \retval jacobian jacobian will be stored in this argument
      /// \param argument point at which the jacobian will be computed
      void jacobian (matrixOut_t jacobian, ConfigurationIn_t argument) const
      {
	assert (argument.size () == inputSize ());
	assert (jacobian.rows () == outputSize ());
	assert (jacobian.cols () == inputDerivativeSize ());
	impl_jacobian (jacobian, argument);
      }

      /// Get dimension of input vector
      size_type inputSize () const
      {
	return inputSize_;
      }
      /// Get dimension of input derivative vector
      ///
      /// The dimension of configuration vectors might differ from the dimension
      /// of velocity vectors since some joints are represented by non minimal
      /// size vectors: e.g. quaternion for SO(3)
      size_type inputDerivativeSize () const
      {
	return inputDerivativeSize_;
      }
      /// Get dimension of output vector
      size_type  outputSize () const
      {
	return outputSize_;
      }
      /// \brief Get function name.
      ///
      /// \return Function name.
      const std::string& name () const
      {
	return name_;
      }

      /// Display object in a stream
      virtual std::ostream& print (std::ostream& o) const
      {
	if (this->name ().empty ())
	  return o << "Differentiable function";

	std::stringstream ss;
	ss << std::endl;
	char fill = o.fill (' ');
	ss << std::setw ((int)roboptim::indent (o))
	   << ""
	   << std::setfill (fill);
	std::string name = this->name ();
	boost::algorithm::replace_all (name, "\n", ss.str ());

	return o << name << " (differentiable function)";
      }

      /// Check whether this function is parametric.
      /// \return True if parametric.
      bool isParametric () const
      {
        return isParametric_;
      }

      /// Make the function parametric or non-parametric.
      /// \param value True if you want a parametric projector.
      /// \note When change from true to false, leaf parameters of any
      /// ConfigProjector containing the function should be recomputed using
      /// ConfigProjector::setLeafParameter.
      void isParametric (const bool& value)
      {
        isParametric_ = value;
      }

    protected:
      /// \brief Concrete class constructor should call this constructor.
      ///
      /// \param inputSize function arity
      /// \param outputSize result size
      /// \param name function's name
      DifferentiableFunction (size_type inputSize,
			      size_type inputDerivativeSize,
			      size_type outputSize,
			      std::string name = std::string ()) :
	inputSize_ (inputSize), inputDerivativeSize_ (inputDerivativeSize),
	outputSize_ (outputSize), isParametric_ (false), name_ (name)
      {
      }

      /// User implementation of function evaluation
      virtual void impl_compute (vectorOut_t result,
				 ConfigurationIn_t argument) const = 0;

      virtual void impl_jacobian (matrixOut_t jacobian,
				  ConfigurationIn_t arg) const = 0;

    private:
      /// Dimension of input vector.
      size_type inputSize_;
      /// Dimension of input derivative
      size_type inputDerivativeSize_;
      /// Dimension of output vector
      size_type outputSize_;
      /// Whether this function is parametric
      bool isParametric_;
      std::string name_;
    }; // class DifferentiableFunction
    inline std::ostream&
    operator<< (std::ostream& os, const DifferentiableFunction& f)
    {
      return f.print (os);
    }
  } // namespace core
} // namespace hpp

#endif // HPP_CORE_DIFFERENTIABLE_FUNCTION_HH
<|endoftext|>


<commit_before>/**
 * @file math.cpp
 * @brief  Brief description of file.
 *
 */

#include <math.h>
#include "model.h"
#include "../perlin.h"

template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}

class ConstantComponent : public ComponentType {
    FloatParameter *pVal;
public:
    ConstantComponent() : ComponentType("const","maths"){}
    virtual void init(){
        setOutput(0,tFloat,"val");
        setParams(pVal=new FloatParameter("val",-10,10,0),NULL);
    }

    virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;
        tFloat->setOutput(ci,0,pVal->get(c));
    }
    virtual const char *getExtraText(Component *c,char *buf){
        sprintf(buf,"%f",pVal->get(c));
        return buf;
    }
};
static ConstantComponent constreg;

class AddComponent : public ComponentType {
public:
    AddComponent() : ComponentType("add","maths"){}
    virtual void init() {
        setInput(0,tFloat,"x");
        setInput(1,tFloat,"y");
        setOutput(0,tFloat,"x+y");
        setParams(
                     pAdd1 = new FloatParameter("add 1",-100,100,0),
                     pMul1 = new FloatParameter("mul 1",-100,100,1),
                     pAdd2 = new FloatParameter("add 2",-100,100,0),
                     pMul2 = new FloatParameter("mul 2",-100,100,1),
                     NULL
                     );
    }

    virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;

        float a = (tFloat->getInput(ci,0)+pAdd1->get(c))*pMul1->get(c);
        float b = (tFloat->getInput(ci,1)+pAdd2->get(c))*pMul2->get(c);

        tFloat->setOutput(ci,0,a+b);
    }

private:
    FloatParameter *pAdd1,*pMul1,*pAdd2,*pMul2;
};

static AddComponent addreg;

class MulComponent : public ComponentType {
public:
    MulComponent() : ComponentType("mul","maths"){}
    virtual void init() {
        setInput(0,tFloat,"x");
        setInput(1,tFloat,"y");
        setOutput(0,tFloat,"x*y");
        setParams(
                     pAdd1 = new FloatParameter("add 1",-100,100,0),
                     pMul1 = new FloatParameter("mul 1",-100,100,1),
                     pAdd2 = new FloatParameter("add 2",-100,100,0),
                     pMul2 = new FloatParameter("mul 2",-100,100,1),
                     NULL
                     );
    }

   virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;

        float a = (tFloat->getInput(ci,0)+pAdd1->get(c))*pMul1->get(c);
        float b = (tFloat->getInput(ci,1)+pAdd2->get(c))*pMul2->get(c);
        tFloat->setOutput(ci,0,a*b);
    }

private:
    FloatParameter *pAdd1,*pMul1,*pAdd2,*pMul2;
};

static MulComponent mulreg;

static const char *funcNames[]=
{
    "sin(x+y)","cos(x+y)","gauss(x+y)",
    "x % y" , "abs(x+y)","tanh(x+y)",
    NULL
};

inline float dofunc(float x,float y,int i){
    switch(i){
    case 0:return sinf(x+y);
    case 1:return cosf(x+y);
    case 2:x=x+y;
        return (1.0f/(2.0f*3.1415927f))*
              powf(2.71828f,-0.5f*x*x);
    case 3:return fmodf(x,y);
    case 4:return fabsf(x+y);
    case 5:return tanhf(x+y);
    }
    return 0;
}

class FuncComponent : public ComponentType {
public:
    FuncComponent() : ComponentType("func","maths"){}
    virtual void init() {
        setInput(0,tFloat,"x");
        setInput(1,tFloat,"y");
        setOutput(0,tFloat,"f(x)");
        setParams(
                  pAddIn1 = new FloatParameter("add-in-x",-100,100,0),
                  pMulIn1 = new FloatParameter("mul-in-x",-100,100,1),
                  pAddIn2 = new FloatParameter("add-in-y",-100,100,0),
                  pMulIn2 = new FloatParameter("mul-in-y",-100,100,1),
                  pFunc = new EnumParameter("func",funcNames,0),
                  pMulOut = new FloatParameter("mul-out",-100,100,1),
                  pAddOut = new FloatParameter("add-out",-100,100,0),
                     NULL
                     );
    }

    virtual void run(ComponentInstance *ci,int outnum){
        Component *c = ci->component;

        float in1 = (tFloat->getInput(ci,0)+pAddIn1->get(c))*pMulIn1->get(c);
        float in2 = (tFloat->getInput(ci,0)+pAddIn2->get(c))*pMulIn2->get(c);
        float out = dofunc(in1,in2,pFunc->get(c));
        out *= pMulOut->get(c);
        out += pAddOut->get(c);

        tFloat->setOutput(ci,0,out);
    }

private:
    FloatParameter *pAddIn1,*pMulIn1;
    FloatParameter *pAddIn2,*pMulIn2;
    FloatParameter *pAddOut,*pMulOut;
    EnumParameter *pFunc;
};
static FuncComponent reg;

struct PCData {
    PerlinNoise p;
    float prev;
};

class PerlinComponent : public ComponentType {
    FloatParameter *pAddIn,*pMulIn1;
    FloatParameter *pMulIn2;
    FloatParameter *pAddOut,*pMulOut;
    IntParameter *pOctaves;
    FloatParameter *pPersist;
public:
    PerlinComponent() : ComponentType("perlin","maths"){}
    virtual void init(){
        setInput(0,tFloat,"x");
        setInput(1,tFloat,"y");
        setOutput(0,tFloat,"perlin(x+y)");
        setOutput(1,tInt,"zerocrosstrig");
        setParams(
                  pOctaves = new IntParameter("octaves",1,8,2),
                  pPersist = new FloatParameter("persistence",0,1,0.5),
                  pMulIn1 = new FloatParameter("mul-in-x",-100,100,1),
                  pMulIn2 = new FloatParameter("mul-in-y",-100,100,1),
                  pAddIn = new FloatParameter("add-in",-100,100,0),
                  pMulOut = new FloatParameter("mul-out",-100,100,1),
                  pAddOut = new FloatParameter("add-out",-100,100,0),
                  NULL
                  );
    }
    virtual void initComponentInstance(ComponentInstance *c){
        PCData *d = new PCData();
        d->prev = 1;
        c->privateData = (void *)d;
    }

    virtual void shutdownComponentInstance(ComponentInstance *c){
        delete ((PCData *)c->privateData);
    }

    virtual void run(ComponentInstance *ci,int outnum){
        Component *c = ci->component;
        PCData *d = (PCData *)ci->privateData;
        d->p.mOctaves = pOctaves->get(c);
        d->p.mPersistence = pPersist->get(c);

        float in1,in2;

        // if neither input connected, use the time (as input 1)
        if(!c->isInputConnected(0) && !c->isInputConnected(1)){
            in1 = Time::now()*pMulIn1->get(c);;
            in2 = 0;
        }  else {
            in1 = tFloat->getInput(ci,0)*pMulIn1->get(c);
            in2 = tFloat->getInput(ci,0)*pMulIn2->get(c);
        }
        float out = d->p.get(in1+in2+pAddIn->get(c));
        out *= pMulOut->get(c);
        out += pAddOut->get(c);

        int zerocrossed;
        if(sgn<float>(out) != sgn<float>(d->prev))
            zerocrossed=1;
        else
            zerocrossed=0;
        d->prev = out;

        tFloat->setOutput(ci,0,out);
        tInt->setOutput(ci,1,zerocrossed);
    }

};
static PerlinComponent perlinreg;

class ClampComponent : public ComponentType {
public:
    ClampComponent() : ComponentType("clamp","maths"){}
    virtual void init() {
        setInput(0,tFloat,"in");
        setOutput(0,tFloat,"out");
        setParams(
                     pMin = new FloatParameter("min",-10,10,0),
                     pMax = new FloatParameter("max",-10,10,1),
                     NULL
                     );
    }

    virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;
        float in = tFloat->getInput(ci,0);
        float mn = pMin->get(c);
        float mx = pMax->get(c);
        if(in<mn)in=mn;
        else if(in>mx)in=mx;

        tFloat->setOutput(ci,0,in);
    }

private:
    FloatParameter *pMin,*pMax;
};
static ClampComponent clampreg;

// several thresholds set, will output 0 or 1 to the corresponding
// output if input is above or below threshold.

class LowHighComponent : public ComponentType {
    static const int NUMINS = 4;
    FloatParameter *pMul,*pAdd,*pThresh[NUMINS];
public:

    LowHighComponent() : ComponentType("lowhigh","maths"){}
    virtual void init() {
        setInput(0,tFloat,"in");
        addParameter(pMul=new FloatParameter("mul",-10,10,1));
        addParameter(pAdd=new FloatParameter("add",-10,10,0));
        for(int i=0;i<NUMINS;i++){
            char buf[32];
            sprintf(buf,"thresh %d",i);
            sprintf(buf,"output %d",i);
            addParameter(pThresh[i] = new FloatParameter(buf,-10,10,0));
            setOutput(i,tFloat,buf);
        }
    }

    virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;
        float in = tFloat->getInput(ci,0);
        in *= pMul->get(c);
        in += pAdd->get(c);

        float r = (in<pThresh[out]->get(c) < 0) ? 0 : 1;

        tFloat->setOutput(ci,out,r);
    }

private:
};

static LowHighComponent lohireg;
<commit_msg>strdup of names<commit_after>/**
 * @file math.cpp
 * @brief  Brief description of file.
 *
 */

#include <math.h>
#include "model.h"
#include "../perlin.h"

template <typename T> int sgn(T val) {
    return (T(0) < val) - (val < T(0));
}

class ConstantComponent : public ComponentType {
    FloatParameter *pVal;
public:
    ConstantComponent() : ComponentType("const","maths"){}
    virtual void init(){
        setOutput(0,tFloat,"val");
        setParams(pVal=new FloatParameter("val",-10,10,0),NULL);
    }

    virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;
        tFloat->setOutput(ci,0,pVal->get(c));
    }
    virtual const char *getExtraText(Component *c,char *buf){
        sprintf(buf,"%f",pVal->get(c));
        return buf;
    }
};
static ConstantComponent constreg;

class AddComponent : public ComponentType {
public:
    AddComponent() : ComponentType("add","maths"){}
    virtual void init() {
        setInput(0,tFloat,"x");
        setInput(1,tFloat,"y");
        setOutput(0,tFloat,"x+y");
        setParams(
                     pAdd1 = new FloatParameter("add 1",-100,100,0),
                     pMul1 = new FloatParameter("mul 1",-100,100,1),
                     pAdd2 = new FloatParameter("add 2",-100,100,0),
                     pMul2 = new FloatParameter("mul 2",-100,100,1),
                     NULL
                     );
    }

    virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;

        float a = (tFloat->getInput(ci,0)+pAdd1->get(c))*pMul1->get(c);
        float b = (tFloat->getInput(ci,1)+pAdd2->get(c))*pMul2->get(c);

        tFloat->setOutput(ci,0,a+b);
    }

private:
    FloatParameter *pAdd1,*pMul1,*pAdd2,*pMul2;
};

static AddComponent addreg;

class MulComponent : public ComponentType {
public:
    MulComponent() : ComponentType("mul","maths"){}
    virtual void init() {
        setInput(0,tFloat,"x");
        setInput(1,tFloat,"y");
        setOutput(0,tFloat,"x*y");
        setParams(
                     pAdd1 = new FloatParameter("add 1",-100,100,0),
                     pMul1 = new FloatParameter("mul 1",-100,100,1),
                     pAdd2 = new FloatParameter("add 2",-100,100,0),
                     pMul2 = new FloatParameter("mul 2",-100,100,1),
                     NULL
                     );
    }

   virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;

        float a = (tFloat->getInput(ci,0)+pAdd1->get(c))*pMul1->get(c);
        float b = (tFloat->getInput(ci,1)+pAdd2->get(c))*pMul2->get(c);
        tFloat->setOutput(ci,0,a*b);
    }

private:
    FloatParameter *pAdd1,*pMul1,*pAdd2,*pMul2;
};

static MulComponent mulreg;

static const char *funcNames[]=
{
    "sin(x+y)","cos(x+y)","gauss(x+y)",
    "x % y" , "abs(x+y)","tanh(x+y)",
    NULL
};

inline float dofunc(float x,float y,int i){
    switch(i){
    case 0:return sinf(x+y);
    case 1:return cosf(x+y);
    case 2:x=x+y;
        return (1.0f/(2.0f*3.1415927f))*
              powf(2.71828f,-0.5f*x*x);
    case 3:return fmodf(x,y);
    case 4:return fabsf(x+y);
    case 5:return tanhf(x+y);
    }
    return 0;
}

class FuncComponent : public ComponentType {
public:
    FuncComponent() : ComponentType("func","maths"){}
    virtual void init() {
        setInput(0,tFloat,"x");
        setInput(1,tFloat,"y");
        setOutput(0,tFloat,"f(x)");
        setParams(
                  pAddIn1 = new FloatParameter("add-in-x",-100,100,0),
                  pMulIn1 = new FloatParameter("mul-in-x",-100,100,1),
                  pAddIn2 = new FloatParameter("add-in-y",-100,100,0),
                  pMulIn2 = new FloatParameter("mul-in-y",-100,100,1),
                  pFunc = new EnumParameter("func",funcNames,0),
                  pMulOut = new FloatParameter("mul-out",-100,100,1),
                  pAddOut = new FloatParameter("add-out",-100,100,0),
                     NULL
                     );
    }

    virtual void run(ComponentInstance *ci,int outnum){
        Component *c = ci->component;

        float in1 = (tFloat->getInput(ci,0)+pAddIn1->get(c))*pMulIn1->get(c);
        float in2 = (tFloat->getInput(ci,0)+pAddIn2->get(c))*pMulIn2->get(c);
        float out = dofunc(in1,in2,pFunc->get(c));
        out *= pMulOut->get(c);
        out += pAddOut->get(c);

        tFloat->setOutput(ci,0,out);
    }

private:
    FloatParameter *pAddIn1,*pMulIn1;
    FloatParameter *pAddIn2,*pMulIn2;
    FloatParameter *pAddOut,*pMulOut;
    EnumParameter *pFunc;
};
static FuncComponent reg;

struct PCData {
    PerlinNoise p;
    float prev;
};

class PerlinComponent : public ComponentType {
    FloatParameter *pAddIn,*pMulIn1;
    FloatParameter *pMulIn2;
    FloatParameter *pAddOut,*pMulOut;
    IntParameter *pOctaves;
    FloatParameter *pPersist;
public:
    PerlinComponent() : ComponentType("perlin","maths"){}
    virtual void init(){
        setInput(0,tFloat,"x");
        setInput(1,tFloat,"y");
        setOutput(0,tFloat,"perlin(x+y)");
        setOutput(1,tInt,"zerocrosstrig");
        setParams(
                  pOctaves = new IntParameter("octaves",1,8,2),
                  pPersist = new FloatParameter("persistence",0,1,0.5),
                  pMulIn1 = new FloatParameter("mul-in-x",-100,100,1),
                  pMulIn2 = new FloatParameter("mul-in-y",-100,100,1),
                  pAddIn = new FloatParameter("add-in",-100,100,0),
                  pMulOut = new FloatParameter("mul-out",-100,100,1),
                  pAddOut = new FloatParameter("add-out",-100,100,0),
                  NULL
                  );
    }
    virtual void initComponentInstance(ComponentInstance *c){
        PCData *d = new PCData();
        d->prev = 1;
        c->privateData = (void *)d;
    }

    virtual void shutdownComponentInstance(ComponentInstance *c){
        delete ((PCData *)c->privateData);
    }

    virtual void run(ComponentInstance *ci,int outnum){
        Component *c = ci->component;
        PCData *d = (PCData *)ci->privateData;
        d->p.mOctaves = pOctaves->get(c);
        d->p.mPersistence = pPersist->get(c);

        float in1,in2;

        // if neither input connected, use the time (as input 1)
        if(!c->isInputConnected(0) && !c->isInputConnected(1)){
            in1 = Time::now()*pMulIn1->get(c);;
            in2 = 0;
        }  else {
            in1 = tFloat->getInput(ci,0)*pMulIn1->get(c);
            in2 = tFloat->getInput(ci,0)*pMulIn2->get(c);
        }
        float out = d->p.get(in1+in2+pAddIn->get(c));
        out *= pMulOut->get(c);
        out += pAddOut->get(c);

        int zerocrossed;
        if(sgn<float>(out) != sgn<float>(d->prev))
            zerocrossed=1;
        else
            zerocrossed=0;
        d->prev = out;

        tFloat->setOutput(ci,0,out);
        tInt->setOutput(ci,1,zerocrossed);
    }

};
static PerlinComponent perlinreg;

class ClampComponent : public ComponentType {
public:
    ClampComponent() : ComponentType("clamp","maths"){}
    virtual void init() {
        setInput(0,tFloat,"in");
        setOutput(0,tFloat,"out");
        setParams(
                     pMin = new FloatParameter("min",-10,10,0),
                     pMax = new FloatParameter("max",-10,10,1),
                     NULL
                     );
    }

    virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;
        float in = tFloat->getInput(ci,0);
        float mn = pMin->get(c);
        float mx = pMax->get(c);
        if(in<mn)in=mn;
        else if(in>mx)in=mx;

        tFloat->setOutput(ci,0,in);
    }

private:
    FloatParameter *pMin,*pMax;
};
static ClampComponent clampreg;

// several thresholds set, will output 0 or 1 to the corresponding
// output if input is above or below threshold.

class LowHighComponent : public ComponentType {
    static const int NUMINS = 4;
    FloatParameter *pMul,*pAdd,*pThresh[NUMINS];
public:

    LowHighComponent() : ComponentType("lowhigh","maths"){}
    virtual void init() {
        setInput(0,tFloat,"in");
        addParameter(pMul=new FloatParameter("mul",-10,10,1));
        addParameter(pAdd=new FloatParameter("add",-10,10,0));
        for(int i=0;i<NUMINS;i++){
            char buf[32];
            sprintf(buf,"thresh %d",i);
            addParameter(pThresh[i] =
                         new FloatParameter(strdup(buf),-10,10,0));
            sprintf(buf,"output %d",i);
            setOutput(i,tFloat,strdup(buf));
        }
    }

    virtual void run(ComponentInstance *ci,int out){
        Component *c = ci->component;
        float in = tFloat->getInput(ci,0);
        in *= pMul->get(c);
        in += pAdd->get(c);

        float r = (in<pThresh[out]->get(c) < 0) ? 0 : 1;

        tFloat->setOutput(ci,out,r);
    }

private:
};

static LowHighComponent lohireg;
<|endoftext|>


<commit_before>/*
* Copyright (c) 2014, Autonomous Systems Lab
* 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 of the Autonomous Systems Lab, ETH Zurich 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 HOLDER 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.
*
*/

#ifndef ROBOCENTRICFEATUREELEMENT_HPP_
#define ROBOCENTRICFEATUREELEMENT_HPP_

#include "lightweight_filtering/common.hpp"
#include "rovio/FeatureCoordinates.hpp"
#include "rovio/FeatureDistance.hpp"

namespace rovio{

class RobocentricFeatureElement: public LWF::ElementBase<RobocentricFeatureElement,RobocentricFeatureElement,3>{
 public:
  typedef LWF::ElementBase<RobocentricFeatureElement,RobocentricFeatureElement,3> Base;
  using typename Base::mtDifVec;
  using typename Base::mtGet;
  using Base::name_;
  mutable LWF::NormalVectorElement::mtDifVec norDifTemp_;
  mutable MXD norCovMatTemp_;
  mutable LWF::NormalVectorElement norTemp_;
  FeatureCoordinates coordinates_;
  FeatureDistance distance_;
  RobocentricFeatureElement():distance_(FeatureDistance::REGULAR), norCovMatTemp_(3,3){}
  RobocentricFeatureElement(const Camera* mpCameras, const FeatureDistance::Type depthType):coordinates_(mpCameras),distance_(depthType), norCovMatTemp_(3,3){}
  RobocentricFeatureElement(const RobocentricFeatureElement& other):distance_(other.distance_.type_), norCovMatTemp_(3,3){
    coordinates_ = other.coordinates_;
    distance_ = other.distance_;
  }

  /** \brief Destructor
   */
  virtual ~RobocentricFeatureElement(){};

  void boxPlus(const mtDifVec& vecIn, RobocentricFeatureElement& stateOut) const{
    stateOut.coordinates_ = coordinates_;
    stateOut.distance_ = distance_;
    coordinates_.get_nor().boxPlus(vecIn.template block<2,1>(0,0),norTemp_);
    stateOut.coordinates_.set_nor(norTemp_);
    stateOut.distance_.p_ = distance_.p_ + vecIn(2);
  }
  void boxMinus(const RobocentricFeatureElement& stateIn, mtDifVec& vecOut) const{
    coordinates_.get_nor().boxMinus(stateIn.coordinates_.get_nor(),norDifTemp_);
    vecOut.template block<2,1>(0,0) = norDifTemp_;
    vecOut(2) = distance_.p_-stateIn.distance_.p_;
  }
  void boxMinusJac(const RobocentricFeatureElement& stateIn, MXD& matOut) const{
    matOut.setIdentity();
    coordinates_.get_nor().boxMinusJac(stateIn.coordinates_.get_nor(),norCovMatTemp_);
    matOut.template block<2,2>(0,0) = norCovMatTemp_;
  }
  void print() const{
    std::cout << "Bearing vector: " << coordinates_.get_nor().getVec().transpose() << " ,depth-parameter: " << distance_.p_ << std::endl;
  }
  void setIdentity(){
    norTemp_.setIdentity();
    coordinates_.set_nor(norTemp_);
    distance_.p_ = 1.0;
  }
  void setRandom(unsigned int& s){
    norTemp_.setRandom(s);
    coordinates_.set_nor(norTemp_);
    std::default_random_engine generator (s);
    std::normal_distribution<double> distribution (0.0,1.0);
    distance_.p_ = distribution(generator) + 1.0;
    s++;
  }
  void fix(){
    norTemp_ = coordinates_.get_nor();
    norTemp_.fix();
    coordinates_.set_nor(norTemp_);
  }
  mtGet& get(unsigned int i = 0){
    assert(i==0);
    return *this;
  }
  const mtGet& get(unsigned int i = 0) const{
    assert(i==0);
    return *this;
  }
  void registerElementToPropertyHandler(LWF::PropertyHandler* mpPropertyHandler, const std::string& str){
    coordinates_.nor_.registerElementToPropertyHandler(mpPropertyHandler,str + name_); // Does not work properly since when loading the info file the validity of nor_/c_ is not adapted
    mpPropertyHandler->doubleRegister_.registerScalar(str + name_ + "_d", distance_.p_);
  }
};

}

#endif /* ROBOCENTRICFEATUREELEMENT_HPP_ */
<commit_msg>made boxPlus cheaper<commit_after>/*
* Copyright (c) 2014, Autonomous Systems Lab
* 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 of the Autonomous Systems Lab, ETH Zurich 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 HOLDER 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.
*
*/

#ifndef ROBOCENTRICFEATUREELEMENT_HPP_
#define ROBOCENTRICFEATUREELEMENT_HPP_

#include "lightweight_filtering/common.hpp"
#include "rovio/FeatureCoordinates.hpp"
#include "rovio/FeatureDistance.hpp"

namespace rovio{

class RobocentricFeatureElement: public LWF::ElementBase<RobocentricFeatureElement,RobocentricFeatureElement,3>{
 public:
  typedef LWF::ElementBase<RobocentricFeatureElement,RobocentricFeatureElement,3> Base;
  using typename Base::mtDifVec;
  using typename Base::mtGet;
  using Base::name_;
  mutable LWF::NormalVectorElement::mtDifVec norDifTemp_;
  mutable MXD norCovMatTemp_;
  mutable LWF::NormalVectorElement norTemp_;
  FeatureCoordinates coordinates_;
  FeatureDistance distance_;
  RobocentricFeatureElement():distance_(FeatureDistance::REGULAR), norCovMatTemp_(3,3){}
  RobocentricFeatureElement(const Camera* mpCameras, const FeatureDistance::Type depthType):coordinates_(mpCameras),distance_(depthType), norCovMatTemp_(3,3){}
  RobocentricFeatureElement(const RobocentricFeatureElement& other):distance_(other.distance_.type_), norCovMatTemp_(3,3){
    coordinates_ = other.coordinates_;
    distance_ = other.distance_;
  }

  /** \brief Destructor
   */
  virtual ~RobocentricFeatureElement(){};

  void boxPlus(const mtDifVec& vecIn, RobocentricFeatureElement& stateOut) const{
    if(&stateOut != this){
      stateOut.coordinates_ = coordinates_;
      stateOut.distance_ = distance_;
    }
    coordinates_.get_nor().boxPlus(vecIn.template block<2,1>(0,0),norTemp_);
    stateOut.coordinates_.set_nor(norTemp_);
    stateOut.distance_.p_ = distance_.p_ + vecIn(2);
  }
  void boxMinus(const RobocentricFeatureElement& stateIn, mtDifVec& vecOut) const{
    coordinates_.get_nor().boxMinus(stateIn.coordinates_.get_nor(),norDifTemp_);
    vecOut.template block<2,1>(0,0) = norDifTemp_;
    vecOut(2) = distance_.p_-stateIn.distance_.p_;
  }
  void boxMinusJac(const RobocentricFeatureElement& stateIn, MXD& matOut) const{
    matOut.setIdentity();
    coordinates_.get_nor().boxMinusJac(stateIn.coordinates_.get_nor(),norCovMatTemp_);
    matOut.template block<2,2>(0,0) = norCovMatTemp_;
  }
  void print() const{
    std::cout << "Bearing vector: " << coordinates_.get_nor().getVec().transpose() << " ,depth-parameter: " << distance_.p_ << std::endl;
  }
  void setIdentity(){
    norTemp_.setIdentity();
    coordinates_.set_nor(norTemp_);
    distance_.p_ = 1.0;
  }
  void setRandom(unsigned int& s){
    norTemp_.setRandom(s);
    coordinates_.set_nor(norTemp_);
    std::default_random_engine generator (s);
    std::normal_distribution<double> distribution (0.0,1.0);
    distance_.p_ = distribution(generator) + 1.0;
    s++;
  }
  void fix(){
    norTemp_ = coordinates_.get_nor();
    norTemp_.fix();
    coordinates_.set_nor(norTemp_);
  }
  mtGet& get(unsigned int i = 0){
    assert(i==0);
    return *this;
  }
  const mtGet& get(unsigned int i = 0) const{
    assert(i==0);
    return *this;
  }
  void registerElementToPropertyHandler(LWF::PropertyHandler* mpPropertyHandler, const std::string& str){
    coordinates_.nor_.registerElementToPropertyHandler(mpPropertyHandler,str + name_); // Does not work properly since when loading the info file the validity of nor_/c_ is not adapted
    mpPropertyHandler->doubleRegister_.registerScalar(str + name_ + "_d", distance_.p_);
  }
};

}

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