Changeset 1194 for trunk


Ignore:
Timestamp:
Oct 4, 2010, 1:39:12 AM (10 years ago)
Author:
Peter Johansson
Message:

refs #475. First version using Sparse Vector class. This change is obviously quite invasive and thus the size of this commit is larger than what is preferred. I've tried to limit as much as possible and left optimization and style issues behind with a note 'FIXME'.

Location:
trunk
Files:
1 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/AddStats.cc

    r1003 r1194  
    5454  void AddStats::do_parse(const std::string& path, svn_revnum_t rev)
    5555  {
     56    // FIXME: why not using the log from File object
    5657    SVNlog log(path);
    5758    typedef std::set<svn_revnum_t, std::greater<svn_revnum_t> > RevSet;
    5859    RevSet revs;
     60    std::vector<std::map<std::string, SparseVector> > data;
    5961    std::transform(log.commits().begin(), log.commits().end(),
    6062                   std::inserter(revs, revs.begin()),
     
    6466      SVNblame svn_blame(path, *rev_iter);
    6567      LineTypeParser parser(path);
     68      std::vector<size_t> add_vec(4,0);
     69      std::string author="";
    6670      while (svn_blame.valid()) {
    6771        LineTypeParser::line_type lt = parser.parse(svn_blame.line());
    68         if (*rev_iter==svn_blame.revision())
    69           add(svn_blame.author(), *rev_iter, lt);
     72        if (*rev_iter==svn_blame.revision()) {
     73          author = svn_blame.author();
     74          assert(lt<add_vec.size());
     75          ++add_vec[lt];
     76        }
    7077        // I dont trust blame and log behave consistently (stop-on-copy).
    7178        revs.insert(svn_blame.revision());
    7279        svn_blame.next_line();
    7380      }
     81      if (author.empty()) { // don't add 0 to author ""
     82        assert(add_vec[0]==0);
     83        assert(add_vec[1]==0);
     84        assert(add_vec[2]==0);
     85        assert(add_vec[3]==0);
     86        continue;
     87      }
     88      if (data.size()<add_vec.size())
     89        data.resize(add_vec.size());
     90      for (size_t lt=0; lt<add_vec.size(); ++lt) {
     91        assert(author.size());
     92        SparseVector& vec=data[lt][author];
     93        // add add_vec[lt] to current value
     94        vec.set(*rev_iter, vec[*rev_iter] + add_vec[lt]);
     95        assert(data[lt][author][*rev_iter] >= add_vec[lt]);
     96      }
    7497    }
    75     accumulate_stats(rev);
     98    // add parsed data to member
     99    add(data);
    76100  }
    77101
    78102
    79   unsigned int AddStats::max_element(const std::vector<unsigned int>& v) const
     103  unsigned int AddStats::max_element(const SumVector& v) const
    80104  {
    81105    assert(v.size());
  • trunk/lib/AddStats.h

    r1003 r1194  
    4545  private:
    4646    void do_parse(const std::string&, svn_revnum_t);
    47     unsigned int max_element(const std::vector<unsigned int>&) const;
     47    unsigned int max_element(const SumVector&) const;
    4848
    4949  };
  • trunk/lib/BlameStats.cc

    r1036 r1194  
    2929#include "SVNlog.h"
    3030#include "utility.h"
     31#include "Vector.h"
    3132
    3233#include <algorithm>
     
    6263
    6364
    64   void BlameStats::fill_in(Author2Vector& a2v, svn_revnum_t rev)
    65   {
    66     if (rev==0)
    67       return;
    68     for (std::set<std::string>::const_iterator iter(authors().begin());
    69          iter!=authors().end(); ++iter) {
    70       std::vector<unsigned int>& vec = a2v[*iter];
    71       vec.resize(revision()+1);
    72       assert(rev<static_cast<svn_revnum_t>(vec.size()));
    73       vec[rev]=vec[rev-1];
    74     }
    75   }
    76 
    77 
    7865  void BlameStats::do_parse(const std::string& path, svn_revnum_t first_rev)
    7966  {
     67    // FIXME: using log from File object
    8068    SVNlog log(path);
    8169    typedef std::set<svn_revnum_t> RevSet;
     
    8472                   std::inserter(revs, revs.begin()),
    8573                   std::mem_fun_ref(&Commitment::revision));
     74    // we use a ParseVector here to be able to detect when people are
     75    // absent in a revision.
     76    std::vector<std::map<std::string, SparseVector> > data(4);
    8677    for (RevSet::reverse_iterator rev_iter=revs.rbegin();
    8778         rev_iter!=revs.rend() && *rev_iter>=first_rev; ++rev_iter){
     
    8980      LineTypeParser parser(path);
    9081      while (svn_blame.valid()) {
    91         add(svn_blame.author(), *rev_iter, parser.parse(svn_blame.line()));
    92         // I dont trust blame and log behave consistent (stop-on-copy).
     82        int lt = parser.parse(svn_blame.line());
     83        assert(lt<data.size());
     84        SparseVector& vec = data[lt][svn_blame.author()];
     85        vec.set(*rev_iter, vec[*rev_iter] + 1);
     86        add_author(svn_blame.author());
     87        // I dont trust blame and log behave consistently (stop-on-copy).
    9388        revs.insert(svn_blame.revision());
    9489        svn_blame.next_line();
    9590      }
    9691    }
    97    
    98     // filling in pristine revisions, i.e., revs that are larger than
    99     // first_rev and not occuring in revs.
    100     RevSet::iterator rev_iter=revs.begin();
    101     svn_revnum_t rev = first_rev;
    102     while (rev<=revision()) {
    103       if (rev_iter!=revs.end() && rev>*rev_iter)
    104         ++rev_iter;
    105       else if (rev_iter!=revs.end() && rev==*rev_iter) {
    106         ++rev_iter;
    107         ++rev;
    108       }
    109       else {
    110         fill_in(code_stats(),rev);
    111         fill_in(comment_stats(),rev);
    112         fill_in(other_stats(),rev);
    113         fill_in(copyright_stats(),rev);
    114         ++rev;
     92
     93    // for count=zero we have not created an entry in SumVector and
     94    // value will be "value for previous rev". Therefore we need to
     95    // set the value to zero explicitely.
     96    if (stats_.size()<data.size())
     97      stats_.resize(data.size());
     98    for (int lt =0; lt<data.size(); ++lt) {
     99      // just to avoid long long lines
     100      typedef std::map<std::string,SparseVector>::const_iterator const_iterator;
     101      for (const_iterator av = data[lt].begin(); av!=data[lt].end(); ++av) {
     102        for (RevSet::const_reverse_iterator rev_iter=revs.rbegin();
     103             rev_iter!=revs.rend() && *rev_iter >= first_rev; ++rev_iter) {
     104          // FIXME: use Vector::iterator to avoid logN checkup
     105          stats_[lt][av->first].set(*rev_iter, data[lt][av->first][*rev_iter]);
     106        }
    115107      }
    116108    }
    117109  }
    118110
    119 
    120111}} // end of namespace svndigest and namespace theplu
  • trunk/lib/BlameStats.h

    r1036 r1194  
    4545  private:
    4646    void do_parse(const std::string&, svn_revnum_t);
    47     void fill_in(Author2Vector&, svn_revnum_t rev);
     47    //void fill_in(Author2Vector&, svn_revnum_t rev);
    4848
    4949  };
  • trunk/lib/ClassicStats.cc

    r1036 r1194  
    6565    LineTypeParser parser(path);
    6666    SVNblame svn_blame(path);
     67    std::vector<std::map<std::string, SparseVector> > data(4);
    6768    while (svn_blame.valid()) {
    68       add(svn_blame.author(), svn_blame.revision(),
    69           parser.parse(svn_blame.line()));
     69      LineTypeParser::line_type lt = parser.parse(svn_blame.line());
     70      assert(lt<data.size());
     71      SparseVector& vec = data[lt][svn_blame.author()];
     72      vec.set(svn_blame.revision(), vec[svn_blame.revision()] + 1);
    7073      svn_blame.next_line();
    7174    }
    72     accumulate_stats();
     75    // add parsed data to member
     76    add(data);
    7377  }
    7478
    7579
    7680  unsigned int
    77   ClassicStats::max_element(const std::vector<unsigned int>& v) const
     81  ClassicStats::max_element(const SumVector& v) const
    7882  {
    7983    assert(v.size());
  • trunk/lib/ClassicStats.h

    r1036 r1194  
    4545  private:
    4646    void do_parse(const std::string&, svn_revnum_t);
    47     unsigned int max_element(const std::vector<unsigned int>&) const;
     47    unsigned int max_element(const SumVector&) const;
    4848
    4949  };
  • trunk/lib/Functor.h

    r978 r1194  
    186186  template <typename Key, typename T>
    187187  struct PairValuePlus :
    188     public std::binary_function<std::vector<T>,
    189                                 std::pair<const Key, std::vector<T> >,
    190                                 std::vector<T> >
     188    public std::binary_function<T, std::pair<const Key, T>, T>
    191189  {
    192     std::vector<T> operator()(const std::vector<T>& sum,
    193                               const std::pair<const Key,std::vector<T> >& p)
     190    T operator()(const T& sum, const std::pair<const Key, T>& p)
    194191    {
    195       return VectorPlus<T>()(sum, p.second);
     192      return sum + p.second;
    196193    }
    197194  };
  • trunk/lib/Graph.cc

    r1182 r1194  
    8585
    8686
    87   void Graph::plot(const std::vector<unsigned int>& y, const std::string& label,
     87  void Graph::plot(const SumVector& y, const std::string& label,
    8888                   unsigned int lines)
    8989  {
     
    116116
    117117    pls_.col0(1);
     118    // FIXME: loop over segments instead of revs, i.e., use Vector::iterator
    118119    for (unsigned int i=1; i<y.size(); ++i) {
    119120      PLFLT x0=i-1;
  • trunk/lib/Graph.h

    r1017 r1194  
    2525
    2626#include <config.h>
     27
     28#include "Vector.h"
    2729
    2830#include <string>
     
    9193       legend entry, and so on.
    9294    */
    93     void plot(const std::vector<unsigned int>& data, const std::string& label,
     95    void plot(const SumVector& data, const std::string& label,
    9496              unsigned int lines);
    9597
  • trunk/lib/Makefile.am

    r1187 r1194  
    4848  OptionVersion.cc \
    4949  rmdirhier.cc Stats.cc StatsCollection.cc subversion_info.cc SVN.cc \
    50   SVNblame.cc SVNdiff.cc SVNinfo.cc SVNlog.cc SVNproperty.cc Trac.cc utility.cc
     50  SVNblame.cc SVNdiff.cc SVNinfo.cc SVNlog.cc SVNproperty.cc \
     51  Trac.cc utility.cc Vector.cc
    5152
    5253
  • trunk/lib/Stats.cc

    r1124 r1194  
    4646#include <vector>
    4747
    48 
    4948namespace theplu{
    5049namespace svndigest{
     
    7978  }
    8079
    81 
     80 
     81  void Stats::add(const std::vector<std::map<std::string, SparseVector> >& data)
     82  {
     83    // loop over line types
     84    for (size_t lt = 0; lt<data.size(); ++lt) {
     85      std::map<std::string, SparseVector>::const_iterator iter=data[lt].begin();
     86      std::map<std::string, SparseVector>::const_iterator last=data[lt].end();
     87      // loop over users
     88      for ( ; iter!=last; ++iter) {
     89        add_author(iter->first);
     90        SumVector tmpvec;
     91        accumulate(iter->second, tmpvec);
     92        stats_[lt][iter->first] += tmpvec;
     93      }
     94    }
     95  }
     96
     97
     98  /*
    8299  void Stats::accumulate(std::vector<unsigned int>& vec,
    83100                         svn_revnum_t rev) const
     
    94111      vec.resize(revision()+1, vec.back());
    95112  }
    96 
    97 
     113  */
     114  /*
    98115  void Stats::accumulate_stats(svn_revnum_t rev)
    99116  {
     
    112129    }
    113130  }
    114 
    115 
    116   void Stats::add(const std::string& user, const unsigned int& rev,
    117                   const LineTypeParser::line_type& lt, unsigned int n)
     131  */
     132  /*
     133  void Stats::add(const std::string& user, svn_revnum_t rev,
     134                  LineTypeParser::line_type lt, unsigned int n)
    118135  {
    119136    assert(user.size());
    120137    add_author(user);
    121138
    122     add(code_stats()[user], rev, lt==LineTypeParser::code, n);
    123     add(comment_stats()[user], rev, lt==LineTypeParser::comment, n);
    124     add(other_stats()[user], rev, lt==LineTypeParser::other, n);
    125     add(copyright_stats()[user], rev, lt==LineTypeParser::copyright, n);
     139    if (lt==LineTypeParser::code)
     140      add(code_stats()[user], rev, n);
     141    else if (lt==LineTypeParser::comment)
     142      add(comment_stats()[user], rev, n);
     143    else if (lt==LineTypeParser::other)
     144      add(other_stats()[user], rev, n);
     145    else if (lt==LineTypeParser::copyright)
     146      add(copyright_stats()[user], rev, n);
    126147  }
    127148
    128 
    129   void Stats::add(std::vector<unsigned int>& vec, unsigned int rev, bool x,
    130                   unsigned int n)
     149  void Stats::add(SumVector& vec, svn_revnum_t rev, unsigned int n)
    131150  {
    132     if (vec.size() < rev+1){
    133       vec.reserve(rev+1);
    134       vec.resize(rev);
    135       assert(vec.size()+1<vec.max_size());
    136       if (x) {
    137         vec.push_back(n);
    138       }
    139       else {
    140         vec.push_back(0);
    141       }
    142     }
    143     else if (x)
    144       vec[rev]+=n;
    145   }
     151    vec.set(rev, vec[rev] + n);
     152  }
     153  */
    146154
    147155
     
    167175  void Stats::calc_all(void)
    168176  {
    169     std::vector<unsigned int> init(revision()+1);
     177    // FIXME: we should use operator+=
     178    SumVector init;
    170179    for (int lt=0; lt <= 4; ++lt) {
    171180      stats_[lt]["all"].clear();
     
    173182        std::accumulate(stats_[lt].begin(),
    174183                        stats_[lt].end(), init,
    175                         PairValuePlus<std::string,unsigned int>());
    176     }
    177     VectorPlus<unsigned int> vp;
     184                        PairValuePlus<std::string, SumVector>());
     185    }
     186
    178187    comment_or_copy_stats()["all"] =
    179       vp(comment_stats()["all"], copyright_stats()["all"]);
    180 
    181     total_stats()["all"] =
    182       vp(vp(code_stats()["all"], comment_or_copy_stats()["all"]),
    183          other_stats()["all"]);
     188      comment_stats()["all"] + copyright_stats()["all"];
     189
     190    total_stats()["all"] = code_stats()["all"] +
     191      comment_or_copy_stats()["all"] + other_stats()["all"];
    184192  }
    185193
     
    189197    for (std::set<std::string>::const_iterator iter(authors().begin());
    190198         iter!=authors().end(); ++iter) {
    191       std::vector<unsigned int>& code = code_stats()[*iter];
    192       std::vector<unsigned int>& comments = comment_stats()[*iter];
    193       std::vector<unsigned int>& other = other_stats()[*iter];
    194       std::vector<unsigned int>& copy = copyright_stats()[*iter];
    195 
    196       VectorPlus<unsigned int> vp;
    197       total_stats()[*iter] = vp(vp(vp(code, comments),other),copy);
     199      // FIXME: we should uer operator+=
     200      const SumVector& code = code_stats()[*iter];
     201      const SumVector& comments = comment_stats()[*iter];
     202      const SumVector& other = other_stats()[*iter];
     203      const SumVector& copy = copyright_stats()[*iter];
     204
     205      total_stats()[*iter] = code + comments + other + copy;
     206      assert(total_stats()[*iter][100] ==
     207             code[100]+comments[100]+other[100]+copy[100]);
    198208    }
    199209
     
    205215    for (std::set<std::string>::const_iterator iter(authors().begin());
    206216         iter!=authors().end(); ++iter) {
    207       std::vector<unsigned int>& comments = comment_stats()[*iter];
    208       std::vector<unsigned int>& copy = copyright_stats()[*iter];
    209 
    210       VectorPlus<unsigned int> vp;
    211       comment_or_copy_stats()[*iter] = vp(comments, copy);
     217      const SumVector& comments = comment_stats()[*iter];
     218      const SumVector& copy = copyright_stats()[*iter];
     219
     220      // FIXME: we should use operator+=
     221      comment_or_copy_stats()[*iter] = comments + copy;
    212222    }
    213223
     
    242252
    243253
    244   const std::vector<unsigned int>& Stats::get_vector(const Author2Vector& m,
    245                                               std::string user) const
     254  const SumVector& Stats::get_vector(const Author2Vector& m,
     255                                     const std::string& user) const
    246256  {
    247257    A2VConstIter iter(m.find(std::string(user)));
     
    269279      std::string name;
    270280      std::getline(is, name);
    271       std::vector<unsigned int>& vec=m[name];
     281      SparseVector vec;
    272282      std::string line;
    273283      std::getline(is, line);
     
    281291        if (!count)
    282292          break;
    283         vec.resize(std::max(vec.size(),static_cast<size_t>(rev+1)));
    284         vec[rev]=count;
    285       }
    286       accumulate(vec);
     293        vec.set(rev, count);
     294      }
     295      SumVector& sumvec = m[name];
     296      accumulate(vec, sumvec);
    287297    }
    288298  }
     
    368378      // keys are equivalent
    369379      else {
    370         VectorPlus<Author2Vector::mapped_type::value_type> vp;
    371         first2->second = vp(first1->second, first2->second);
     380        first2->second = first1->second + first2->second;
    372381        ++first1;
    373382        ++first2;
     
    377386
    378387
    379   unsigned int Stats::max_element(const std::vector<unsigned int>& vec) const
    380   {
    381     return *std::max_element(vec.begin(), vec.end());
     388  unsigned int Stats::max_element(const SumVector& vec) const
     389  {
     390    return std::max_element(vec.begin(), vec.end(),
     391       pair_value_compare<const svn_revnum_t, unsigned int>())->second;
    382392  }
    383393
     
    388398    for (size_t i=0; i<stats_.size(); ++i)
    389399      for (A2VIter iter=stats_[i].begin(); iter!=stats_[i].end(); ++iter) {
    390         iter->second.resize(rev,0);
    391         iter->second.resize(revision(),0);
     400        //iter->second.resize(rev,0);
     401        //iter->second.resize(revision(),0);
    392402      }
    393403    do_parse(path, rev);
     
    395405    calc_total();
    396406    calc_all();
     407   
    397408    assert(total_stats().size());
    398409    assert(code_stats().size());
     
    422433                   const std::string& format) const
    423434  {
    424     assert(total_stats().size());
    425435    Graph gp(filename+"."+format, format);
    426436    const Author2Vector* stat=NULL;
     
    436446    assert(stat->size());
    437447    assert(stat->find("all")!=stat->end());
    438     std::vector<unsigned int> total=get_vector(*stat, "all");   
     448    // FIXME: try keep a const& to avoid copying
     449    SumVector total=get_vector(*stat, "all");   
     450    total.resize(revision());
    439451    double yrange_max=1.03 * max_element(total) +1.0;
    440452    gp.ymax(yrange_max);
    441453
    442     typedef std::vector<std::pair<std::string, std::vector<unsigned int> > > vec_type;
     454    typedef std::vector<std::pair<std::string, SumVector> > vec_type;
    443455    vec_type author_cont;
    444456    author_cont.reserve(stat->size());
     
    446458         i != authors_.end(); ++i) {
    447459      assert(stat->find(*i)!=stat->end());
    448       const std::vector<unsigned int>& vec = get_vector(*stat,*i);
     460      // FIXME: avoid this copying?
     461      SumVector vec = get_vector(*stat,*i);
     462      vec.resize(revision());
    449463      if (max_element(vec)) {
    450464        author_cont.push_back(std::make_pair(*i,vec));
     
    452466    }
    453467
    454     LessReversed<std::vector<unsigned int> > lr;
    455     PairSecondCompare<std::string, std::vector<unsigned int>,
    456       LessReversed<std::vector<unsigned int> > > compare(lr);
     468    LessReversed<SumVector> lr;
     469    PairSecondCompare<std::string, SumVector, LessReversed<SumVector> >
     470      compare(lr);
    457471    std::sort(author_cont.begin(), author_cont.end(), compare);
    458472
     
    466480      vec_type::iterator j(i);
    467481      i+=authskip;
    468       std::vector<unsigned int> init(revision()+1);
    469       std::vector<unsigned int> others =
    470         std::accumulate(j, i, init, PairValuePlus<std::string,unsigned int>());
     482      SumVector init;
     483      SumVector others =
     484        std::accumulate(j, i, init, PairValuePlus<std::string, SumVector>());
    471485      unsigned char r, g, b;
    472486      std::string label("others");
     
    504518  {
    505519    Graph gp(filename+"."+format, format);
    506     std::vector<unsigned int> total = get_vector(total_stats(), "all");
     520    // FIXME: why not const&
     521    SumVector total = get_vector(total_stats(), "all");
    507522    double yrange_max=1.03*total.back()+1;
    508523    gp.ymax(yrange_max);
    509524   
    510     std::vector<unsigned int> x(get_vector(code_stats(), "all"));
     525    // FIXME: why not const&
     526    SumVector x(get_vector(code_stats(), "all"));
    511527    gp.current_color(255,255,0);
    512528    gp.plot(x, "code", x.back());
     
    549565    for (A2VConstIter i(m.begin()); i!=m.end(); ++i){
    550566      os << i->first << "\n";
    551       assert(i->second.size());
    552567      if (i->second[0])
    553568        os << 0 << " " << i->second[0] << " ";
     569      // FIXME: ise Vector::iterator
    554570      for (size_t j=1; j<i->second.size(); ++j) {
    555571        // only print if stats changes in this rev
     
    566582    for (size_t i=0; i<stats_.size(); ++i){
    567583      stats_[i].clear();
    568       std::vector<unsigned int>& tmp = stats_[i]["all"];
    569       std::fill(tmp.begin(), tmp.end(), 0);
    570       tmp.resize(revision_+1);
     584      stats_[i]["all"].resize(revision()+1);
    571585    }
    572586    authors_.clear();
     587  }
     588
     589
     590  void Stats::resize(svn_revnum_t rev)
     591  {
     592    // set size on vectors
     593    for (size_t i=0; i<stats_.size(); ++i) {
     594      for (A2VIter iter=stats_[i].begin(); iter!=stats_[i].end(); ++iter) {
     595        iter->second.resize(rev);
     596      }
     597    }
     598  }
     599
     600
     601  svn_revnum_t Stats::revision(void) const
     602  {
     603    return revision_;
    573604  }
    574605
     
    599630      throw std::runtime_error(msg.str());
    600631    }
    601     assert(rev < static_cast<svn_revnum_t>(i->second.size()));
     632    assert(rev <= revision());
     633    //    assert(rev < static_cast<svn_revnum_t>(i->second.size()));
    602634    return i->second[rev];
    603635  }
  • trunk/lib/Stats.h

    r1124 r1194  
    2626
    2727#include "LineTypeParser.h"
     28#include "Vector.h"
    2829
    2930#include <subversion-1/svn_types.h>
     
    5758    /// @brief adding \a n line(s) to \a user from \a revision to the stats
    5859    ///
    59     void add(const std::string& user, const unsigned int& revision,
    60              const LineTypeParser::line_type&, unsigned int n=1);
     60    //    void add(const std::string& user, svn_revnum_t revision,
     61    //       LineTypeParser::line_type, unsigned int n=1);
    6162
    6263    ///
     
    127128    void reset(void);
    128129
     130    /**
     131       set vectors in stats_ to size \a rev
     132    */
     133    void resize(svn_revnum_t rev);
     134
    129135    ///
    130136    /// \return latest revision for whole project
    131137    ///
    132     svn_revnum_t revision(void) const { return revision_; }
     138    svn_revnum_t revision(void) const;
    133139
    134140    /**
     
    146152
    147153  protected:
    148     typedef std::map<std::string, std::vector<unsigned int> > Author2Vector;
     154    typedef std::map<std::string, SumVector> Author2Vector;
    149155    typedef Author2Vector::iterator A2VIter;
    150156    typedef Author2Vector::const_iterator A2VConstIter;
     157
     158    std::vector<Author2Vector> stats_; // from linetype to a2v
     159
     160    /**
     161     */
     162    void add(const std::vector<std::map<std::string, SparseVector> >& data);
    151163
    152164    /**
     
    155167       \see accumulate
    156168     */
    157     void accumulate_stats(svn_revnum_t rev=1);
     169    //    void accumulate_stats(svn_revnum_t rev=1);
    158170    void add_author(std::string);
    159171    void add_authors(std::set<std::string>::const_iterator,
     
    197209    std::set<std::string> authors_;
    198210
    199     const std::vector<unsigned int>& get_vector(const Author2Vector&,
    200                                          std::string user) const;
     211    const SumVector& get_vector(const Author2Vector&,
     212                                const std::string& user) const;
    201213  private:
    202214    /// one liner used in cache file to validate that cache file was
     
    204216    std::string config_code_;
    205217
     218    void add(SumVector& vec, svn_revnum_t rev, unsigned int n);
    206219    /**
    207220       \a vec is resized to revision().
     
    211224       et cetera
    212225     */
    213     void accumulate(std::vector<unsigned int>& vec,
    214                     svn_revnum_t rev=1) const;
    215     void add(std::vector<unsigned int>& vec, unsigned int rev, bool x,
    216              unsigned int n);
     226    //    void accumulate(std::vector<unsigned int>& vec,
     227    //              svn_revnum_t rev=1) const;
     228    //    void add(std::vector<unsigned int>& vec, unsigned int rev, bool x,
     229    //       unsigned int n);
    217230
    218231    /**
     
    231244       called from plot(2)
    232245     */
     246    // FIXME: why should Stats know about plotting?
    233247    void plot(const std::string& basename, const std::string& linetype,
    234248              const std::string& format) const;
     
    237251       called from plot_summary(1)
    238252     */
     253    // FIXME: why should Stats know about plotting?
    239254    void plot_summary(const std::string& basename,
    240255                      const std::string& format) const;
     
    258273       \return the largest largest element in \a v.
    259274    */
    260     virtual unsigned int max_element(const std::vector<unsigned int>& v) const;
     275    virtual unsigned int max_element(const SumVector& v) const;
    261276
    262277    void print(std::ostream& os, const Author2Vector& m) const;
     
    264279    svn_revnum_t revision_; // Should be the latest revision for whole project
    265280    svn_revnum_t last_changed_rev_; // Should be the latest revision for file
    266 
    267     std::vector<Author2Vector> stats_; // from linetype to a2v
    268281
    269282    // using compiler generated copy constructor
  • trunk/lib/Vector.h

    r1187 r1194  
    2323*/
    2424
     25#include <iostream>
     26
    2527#include <subversion-1/svn_types.h>
    2628
     29#include <algorithm>
     30#include <cassert>
    2731#include <map>
    2832
     
    3943    // iterator to underlying container, used in begin() and end()
    4044    typedef typename Map::const_iterator const_iterator;
     45    // iterator to underlying container, used in begin() and end()
     46    typedef typename Map::const_reverse_iterator const_reverse_iterator;
    4147
    4248    /**
    4349       \brief default constructor
    4450     */
    45     Vector(void) {}
     51    Vector(void)
     52      : size_(0)
     53    {}
     54
     55    /**
     56       \note Vector cannot be empty
     57
     58       \return last element
     59     */
     60    T back(void) const
     61    {
     62      // FIXME: avoid logN lookup time
     63      assert(size()>0);
     64      return (*this)[size()-1];
     65    }
    4666
    4767    /**
     
    5777       \brief make container empty
    5878     */
    59     void clear(void) { map_.clear(); }
     79    void clear(void)
     80    {
     81      map_.clear();
     82      size_ = 0;
     83    }
     84
     85    /**
     86       \return true if Vector is empty
     87     */
     88    bool empty(void) const
     89    { return map_.empty(); }
    6090
    6191    /*
     
    6595
    6696    /**
     97       same as begin() but reverse iterator
     98     */
     99    const_reverse_iterator rbegin(void) const { return map_.rbegin(); }
     100
     101    /**
     102       same as end() but reverse iterator
     103     */
     104    const_reverse_iterator rend(void) const { return map_.rend(); }
     105
     106    /*
     107      set size to \a size
     108     */
     109    void resize(svn_revnum_t size)
     110    {
     111      size_ = size;
     112    }
     113
     114    /**
    67115       works as vec[revision] = count
    68116     */
     
    71119      // FIXME: we should let policy collaps map, if possible
    72120      map_[revision] = count;
     121      size_ = std::max(revision+1, size_);
    73122    }
    74123
     
    89138
    90139    /**
    91        \return 0 if Vector is empty; otherwise the largest_rev + 1
    92      */
    93     size_t size(void) const
    94     {
    95       if (map_.empty())
    96         return 0;
    97       return map_.rbegin()->first + 1;
     140       \brief add \a other to this
     141     */
     142    Vector& operator+=(const Vector& other)
     143    {
     144      Vector result;
     145      typename Map::iterator first1 = map_.begin();
     146      typename Map::iterator last1 = map_.end();
     147      const_iterator first2 = other.begin();
     148      const_iterator last2 = other.end();
     149      while (first1!=last1 || first2!=last2) {
     150        svn_revnum_t rev = 0;
     151        if (first1==last1) {
     152          rev = first2->first;
     153          ++first2;
     154        }
     155        else if (first2==last2) {
     156          rev = first1->first;
     157          ++first1;
     158        }
     159        else if (first1->first < first2->first) {
     160          rev = first1->first;
     161          ++first1;
     162        }
     163        else if (first1->first == first2->first) {
     164          rev = first1->first;
     165          ++first1;
     166          ++first2;
     167        }
     168        else if (first1->first > first2->first) {
     169          rev = first2->first;
     170          ++first2;
     171        }
     172        result.set(rev, (*this)[rev] + other[rev]);
     173      }
     174      // assign result map to this
     175      std::swap(map_, result.map_);
     176      resize(std::max(size_, other.size()));
     177    }
     178
     179    /**
     180       \return size of vector
     181     */
     182    svn_revnum_t size(void) const
     183    {
     184      return size_;
    98185    }
    99186
     
    101188    Map map_;
    102189    Policy policy_;
     190    svn_revnum_t size_;
    103191
    104192    // using compiler generated copy constructor
     
    106194    // Vector& operator=(const Vector&);
    107195  };
     196
     197  template<typename T, class Policy>
     198  Vector<T, Policy> operator+(const Vector<T, Policy>& lhs,
     199                              const Vector<T, Policy>& rhs)
     200  {
     201    Vector<T, Policy> result(lhs);
     202    result+=rhs;
     203    assert(result.size()>=lhs.size());
     204    assert(result.size()>=rhs.size());
     205    return result;
     206  }
     207
    108208
    109209  template<typename T>
     
    147247     result[i] = result[i-1] + vec[i];
    148248  */
    149   void accumulate(const SparseVector& vec, SumVector& result)
    150   {
    151     result.clear();
    152     unsigned int value = 0;
    153     for (SumVector::const_iterator iter = vec.begin(); iter!=vec.end();++iter) {
    154       value += iter->second;
    155       result.set(iter->first, value);
    156     }
    157   }
     249  void accumulate(const SparseVector& vec, SumVector& result);
    158250
    159251}} // end of namespace svndigest and namespace theplu
  • trunk/test/graph.cc

    r1189 r1194  
    7575  graph.ymax(10);
    7676  graph.current_color(255, 0, 0);
    77   /*
    7877  SumVector data;
    7978  data.set(99,1);
    80   */
    81   std::vector<unsigned int> data(100,1);
     79  //  std::vector<unsigned int> data(100,1);
    8280  graph.plot(data, "label", 1);
    8381}
  • trunk/test/vector.cc

    r1187 r1194  
    4545
    4646template<class T>
    47 void run_test(T vec, test::Suite&)
     47void run_test(T vec, test::Suite& suite)
    4848{
    4949  vec.begin();
     
    5252  vec[0];
    5353  vec.set(0, 0);
     54
     55  vec.set(5,10);
     56  T vec2(vec);
     57  vec2.set(7,11);
     58  T vec3;
     59  vec3 = vec2;
     60  suite.out() << "testing assignment\n";
     61  if (vec3.size()!=vec2.size()) {
     62    suite.add(false);
     63    suite.out() << "incorrect size: " << vec3.size() << " expected: "
     64                << vec2.size() << "\n";
     65  }
     66
     67  suite.out() << "testing operator+\n";
     68  vec3 = vec + vec2;
     69  if (vec3.size()!=8) {
     70    suite.add(false);
     71    suite.out() << "incorrect size: " << vec3.size() << " expected: "
     72                << 8 << "\n";
     73  }
     74  for (size_t i=0; i<8; ++i)
     75    if (!suite.add(vec3[5]==vec[5]+vec2[5]))
     76      suite.out() << "operator+ failed: result: " << vec3[i]
     77                  << " expected: " << vec[i] + vec2[i] << "\n";
    5478}
    5579
Note: See TracChangeset for help on using the changeset viewer.