LCOV - code coverage report
Current view: top level - cluster - cluster.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core 4ba52dacf4fb Lines: 154 263 58.6 %
Date: 2019-05-20 14:58:19 Functions: 47 83 56.6 %
Branches: 70 207 33.8 %

           Branch data     Line data    Source code
       1                 :            : /** @file cluster.cc
       2                 :            :  *  @brief Cluster API
       3                 :            :  */
       4                 :            : /* Copyright (C) 2010 Richard Boulton
       5                 :            :  * Copyright (C) 2016 Richhiey Thomas
       6                 :            :  *
       7                 :            :  * This program is free software; you can redistribute it and/or
       8                 :            :  * modify it under the terms of the GNU General Public License as
       9                 :            :  * published by the Free Software Foundation; either version 2 of the
      10                 :            :  * License, or (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This program is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :            :  * GNU General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU General Public License
      18                 :            :  * along with this program; if not, write to the Free Software
      19                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      20                 :            :  * USA
      21                 :            :  */
      22                 :            : 
      23                 :            : #include <config.h>
      24                 :            : 
      25                 :            : #include "xapian/cluster.h"
      26                 :            : 
      27                 :            : #include "cluster/clusterinternal.h"
      28                 :            : #include "xapian/error.h"
      29                 :            : #include "api/termlist.h"
      30                 :            : #include "debuglog.h"
      31                 :            : #include "omassert.h"
      32                 :            : 
      33                 :            : #include <cmath>
      34                 :            : #include <unordered_map>
      35                 :            : #include <vector>
      36                 :            : 
      37                 :            : using namespace Xapian;
      38                 :            : using namespace std;
      39                 :            : 
      40                 :         30 : FreqSource::~FreqSource()
      41                 :            : {
      42                 :            :     LOGCALL_DTOR(API, "FreqSource");
      43         [ -  + ]:         15 : }
      44                 :            : 
      45                 :         12 : Similarity::~Similarity()
      46                 :            : {
      47                 :            :     LOGCALL_DTOR(API, "Similarity");
      48         [ -  + ]:         12 : }
      49                 :            : 
      50                 :         18 : Clusterer::~Clusterer()
      51                 :            : {
      52                 :            :     LOGCALL_DTOR(API, "Clusterer");
      53         [ -  + ]:          9 : }
      54                 :            : 
      55         [ +  - ]:         30 : TermListGroup::TermListGroup(const MSet &docs, const Stopper *stopper)
      56                 :            : {
      57                 :            :     LOGCALL_CTOR(API, "TermListGroup", docs | stopper);
      58 [ +  - ][ +  - ]:        102 :     for (MSetIterator it = docs.begin(); it != docs.end(); ++it)
                 [ +  + ]
      59 [ +  - ][ +  - ]:        102 :         add_document(it.get_document(), stopper);
      60         [ +  - ]:         15 :     num_of_documents = docs.size();
      61                 :         15 : }
      62                 :            : 
      63                 :            : doccount
      64                 :          0 : DummyFreqSource::get_termfreq(const string &) const
      65                 :            : {
      66                 :            :     LOGCALL(API, doccount, "DummyFreqSource::get_termfreq", NO_ARGS);
      67                 :          0 :     return 1;
      68                 :            : }
      69                 :            : 
      70                 :            : doccount
      71                 :          0 : DummyFreqSource::get_doccount() const
      72                 :            : {
      73                 :            :     LOGCALL(API, doccount, "DummyFreqSource::get_doccount", NO_ARGS);
      74                 :          0 :     return 1;
      75                 :            : }
      76                 :            : 
      77                 :            : void
      78                 :         87 : TermListGroup::add_document(const Document &document, const Stopper *stopper)
      79                 :            : {
      80                 :            :     LOGCALL_VOID(API, "TermListGroup::add_document", document | stopper);
      81                 :            : 
      82         [ +  - ]:         87 :     TermIterator titer(document.termlist_begin());
      83                 :            : 
      84 [ +  - ][ +  + ]:       1443 :     for (; titer != document.termlist_end(); ++titer) {
      85         [ +  - ]:       1356 :         const string &term = *titer;
      86                 :            : 
      87                 :            :         // Remove stopwords by using the Xapian::Stopper object
      88 [ -  + ][ #  # ]:       1356 :         if (stopper && (*stopper)(term))
         [ #  # ][ -  + ]
      89                 :          0 :             continue;
      90                 :            : 
      91                 :            :         // Remove unstemmed terms since document vector should
      92                 :            :         // contain only stemmed terms
      93         [ +  + ]:       1356 :         if (term[0] != 'Z')
      94                 :       1140 :             continue;
      95                 :            : 
      96                 :        216 :         unordered_map<string, doccount>::iterator i;
      97         [ +  - ]:        216 :         i = termfreq.find(term);
      98         [ +  + ]:        216 :         if (i == termfreq.end())
      99         [ +  - ]:        144 :             termfreq[term] = 1;
     100                 :            :         else
     101         [ +  + ]:       1356 :             ++i->second;
     102                 :       1443 :     }
     103                 :         87 : }
     104                 :            : 
     105                 :            : doccount
     106                 :         81 : TermListGroup::get_doccount() const
     107                 :            : {
     108                 :            :     LOGCALL(API, doccount, "TermListGroup::get_doccount", NO_ARGS);
     109                 :         81 :     return num_of_documents;
     110                 :            : }
     111                 :            : 
     112                 :            : doccount
     113                 :       1236 : TermListGroup::get_termfreq(const string &tname) const
     114                 :            : {
     115                 :            :     LOGCALL(API, doccount, "TermListGroup::get_termfreq", tname);
     116         [ +  - ]:       1236 :     unordered_map<string, doccount>::const_iterator it = termfreq.find(tname);
     117         [ +  + ]:       1236 :     if (it != termfreq.end())
     118                 :        156 :         return it->second;
     119                 :            :     else
     120                 :       1236 :         return 0;
     121                 :            : }
     122                 :            : 
     123                 :            : DocumentSet::DocumentSet(const DocumentSet &) = default;
     124                 :            : 
     125                 :            : DocumentSet&
     126                 :            : DocumentSet::operator=(const DocumentSet &) = default;
     127                 :            : 
     128                 :            : DocumentSet::DocumentSet(DocumentSet &&) = default;
     129                 :            : 
     130                 :            : DocumentSet&
     131                 :            : DocumentSet::operator=(DocumentSet &&) = default;
     132                 :            : 
     133                 :         36 : DocumentSet::DocumentSet()
     134                 :         36 :     : internal(new Xapian::DocumentSet::Internal)
     135                 :            : {
     136                 :         36 : }
     137                 :            : 
     138                 :            : doccount
     139                 :         48 : DocumentSet::size() const
     140                 :            : {
     141                 :            :     LOGCALL(API, doccount, "DocumentSet::size", NO_ARGS);
     142                 :         48 :     return internal->size();
     143                 :            : }
     144                 :            : 
     145                 :            : doccount
     146                 :         48 : DocumentSet::Internal::size() const
     147                 :            : {
     148                 :         48 :     return documents.size();
     149                 :            : }
     150                 :            : 
     151                 :            : void
     152                 :         75 : DocumentSet::add_document(const Document &document)
     153                 :            : {
     154                 :            :     LOGCALL_VOID(API, "DocumentSet::add_document", document);
     155                 :         75 :     internal->add_document(document);
     156                 :         75 : }
     157                 :            : void
     158                 :         75 : DocumentSet::Internal::add_document(const Document &document)
     159                 :            : {
     160                 :         75 :     documents.push_back(document);
     161                 :         75 : }
     162                 :            : 
     163                 :            : Document&
     164                 :         21 : DocumentSet::operator[](doccount i)
     165                 :            : {
     166                 :         21 :     return internal->get_document(i);
     167                 :            : }
     168                 :            : 
     169                 :            : Document&
     170                 :         21 : DocumentSet::Internal::get_document(doccount i)
     171                 :            : {
     172                 :         21 :     return documents[i];
     173                 :            : }
     174                 :            : 
     175                 :            : const Document&
     176                 :          0 : DocumentSet::operator[](doccount i) const
     177                 :            : {
     178                 :          0 :     return internal->get_document(i);
     179                 :            : }
     180                 :            : 
     181                 :            : const Document&
     182                 :          0 : DocumentSet::Internal::get_document(doccount i) const
     183                 :            : {
     184                 :          0 :     return documents[i];
     185                 :            : }
     186                 :            : 
     187                 :         78 : DocumentSet::~DocumentSet()
     188                 :            : {
     189                 :            :     LOGCALL_DTOR(API, "DocumentSet");
     190                 :         39 : }
     191                 :            : 
     192         [ -  + ]:         24 : class PointTermIterator : public TermIterator::Internal {
     193                 :            :     unordered_map<string, double>::const_iterator i;
     194                 :            :     unordered_map<string, double>::const_iterator end;
     195                 :            :     termcount size;
     196                 :            :     bool started;
     197                 :            :   public:
     198                 :          6 :     PointTermIterator(const unordered_map<string, double> &termlist)
     199                 :            :         : i(termlist.begin()), end(termlist.end()),
     200                 :          6 :           size(termlist.size()), started(false)
     201                 :          6 :     {}
     202                 :          0 :     termcount get_approx_size() const { return size; }
     203 [ #  # ][ #  # ]:          0 :     termcount get_wdf() const { throw UnimplementedError("PointIterator doesn't support get_wdf()"); }
                 [ #  # ]
     204                 :         36 :     string get_termname() const { return i->first; }
     205 [ #  # ][ #  # ]:          0 :     doccount get_termfreq() const { throw UnimplementedError("PointIterator doesn't support get_termfreq()"); }
                 [ #  # ]
     206                 :            :     Internal * next();
     207                 :          0 :     termcount positionlist_count() const {
     208 [ #  # ][ #  # ]:          0 :         throw UnimplementedError("PointTermIterator doesn't support positionlist_count()");
                 [ #  # ]
     209                 :            :     }
     210                 :            :     bool at_end() const;
     211                 :          0 :     PositionList* positionlist_begin() const {
     212 [ #  # ][ #  # ]:          0 :         throw UnimplementedError("PointTermIterator doesn't support positionlist_begin()");
                 [ #  # ]
     213                 :            :     }
     214                 :          0 :     Internal * skip_to(const string &) {
     215 [ #  # ][ #  # ]:          0 :         throw UnimplementedError("PointTermIterator doesn't support skip_to()");
                 [ #  # ]
     216                 :            :     }
     217                 :            : };
     218                 :            : 
     219                 :            : TermIterator::Internal *
     220                 :         24 : PointTermIterator::next()
     221                 :            : {
     222         [ +  + ]:         24 :     if (!started) {
     223                 :          6 :         started = true;
     224                 :          6 :         return NULL;
     225                 :            :     }
     226                 :            :     Assert(i != end);
     227                 :         18 :     ++i;
     228                 :         18 :     return NULL;
     229                 :            : }
     230                 :            : 
     231                 :            : bool
     232                 :         24 : PointTermIterator::at_end() const
     233                 :            : {
     234         [ -  + ]:         24 :     if (!started) return false;
     235                 :         24 :     return i == end;
     236                 :            : }
     237                 :            : 
     238                 :            : TermIterator
     239                 :          6 : PointType::termlist_begin() const
     240                 :            : {
     241                 :            :     LOGCALL(API, TermIterator, "PointType::termlist_begin", NO_ARGS);
     242                 :          6 :     return TermIterator(new PointTermIterator(weights));
     243                 :            : }
     244                 :            : 
     245                 :            : bool
     246                 :          0 : PointType::contains(const string &term) const
     247                 :            : {
     248                 :            :     LOGCALL(API, bool, "PointType::contains", term);
     249         [ #  # ]:          0 :     return weights.find(term) != weights.end();
     250                 :            : }
     251                 :            : 
     252                 :            : double
     253                 :         36 : PointType::get_weight(const string &term) const
     254                 :            : {
     255                 :            :     LOGCALL(API, double, "PointType::get_weight", term);
     256         [ +  - ]:         36 :     unordered_map<string, double>::const_iterator it = weights.find(term);
     257         [ +  + ]:         36 :     return (it == weights.end()) ? 0.0 : it->second;
     258                 :            : }
     259                 :            : 
     260                 :            : double
     261                 :        360 : PointType::get_magnitude() const {
     262                 :            :     LOGCALL(API, double, "PointType::get_magnitude", NO_ARGS);
     263                 :        360 :     return magnitude;
     264                 :            : }
     265                 :            : 
     266                 :            : void
     267                 :          0 : PointType::add_weight(const string &term, double weight)
     268                 :            : {
     269                 :            :     LOGCALL_VOID(API, "PointType::add_weight", term | weight);
     270                 :          0 :     unordered_map<string, double>::iterator it;
     271         [ #  # ]:          0 :     it = weights.find(term);
     272         [ #  # ]:          0 :     if (it != weights.end())
     273                 :          0 :         it->second += weight;
     274                 :            :     else
     275         [ #  # ]:          0 :         weights[term] = weight;
     276                 :          0 : }
     277                 :            : 
     278                 :            : void
     279                 :          0 : PointType::set_weight(const string &term, double weight)
     280                 :            : {
     281                 :            :     LOGCALL_VOID(API, "PointType::set_weight", term | weight);
     282                 :          0 :     weights[term] = weight;
     283                 :          0 : }
     284                 :            : 
     285                 :            : termcount
     286                 :          0 : PointType::termlist_size() const
     287                 :            : {
     288                 :            :     LOGCALL(API, termcount, "PointType::termlist_size", NO_ARGS);
     289                 :          0 :     return weights.size();
     290                 :            : }
     291                 :            : 
     292                 :            : Document
     293                 :         75 : Point::get_document() const
     294                 :            : {
     295                 :            :     LOGCALL(API, Document, "Point::get_document", NO_ARGS);
     296                 :         75 :     return document;
     297                 :            : }
     298                 :            : 
     299         [ +  - ]:        162 : Point::Point(const TermListGroup &tlg, const Document &document_)
     300                 :            : {
     301                 :            :     LOGCALL_CTOR(API, "Point::initialize", tlg | document_);
     302         [ +  - ]:         81 :     doccount size = tlg.get_doccount();
     303         [ +  - ]:         81 :     document = document_;
     304 [ +  - ][ +  - ]:       1317 :     for (TermIterator it = document.termlist_begin(); it != document.termlist_end(); ++it) {
                 [ +  + ]
     305         [ +  - ]:       1236 :         doccount wdf = it.get_wdf();
     306         [ +  - ]:       1236 :         string term = *it;
     307         [ +  - ]:       1236 :         double termfreq = tlg.get_termfreq(term);
     308                 :            : 
     309                 :            :         // If the term exists in only one document, or if it exists in
     310                 :            :         // every document within the MSet, or if it is a filter term, then
     311                 :            :         // these terms are not used for document vector calculations
     312 [ +  - ][ +  + ]:       1236 :         if (wdf < 1 || termfreq <= 1 || size == termfreq)
                 [ +  + ]
     313                 :       1167 :             continue;
     314                 :            : 
     315                 :         69 :         double tf = 1 + log((double)wdf);
     316                 :         69 :         double idf = log(size / termfreq);
     317                 :         69 :         double wt = tf * idf;
     318                 :            : 
     319         [ +  - ]:         69 :         weights[term] = wt;
     320         [ +  + ]:       1236 :         magnitude += wt * wt;
     321                 :       1317 :     }
     322                 :         81 : }
     323                 :            : 
     324                 :          0 : Centroid::Centroid(const Point &point) {
     325                 :            :     LOGCALL_CTOR(API, "Centroid", point);
     326 [ #  # ][ #  # ]:          0 :     for (TermIterator it = point.termlist_begin(); it != point.termlist_end(); ++it)
                 [ #  # ]
     327 [ #  # ][ #  # ]:          0 :         weights[*it] = point.get_weight(*it);
         [ #  # ][ #  # ]
     328                 :          0 :     magnitude = point.get_magnitude();
     329                 :          0 : }
     330                 :            : 
     331                 :            : void
     332                 :          0 : Centroid::divide(double cluster_size)
     333                 :            : {
     334                 :            :     LOGCALL_VOID(API, "Centroid::divide", cluster_size);
     335                 :          0 :     magnitude = 0;
     336                 :          0 :     unordered_map<string, double>::iterator it;
     337         [ #  # ]:          0 :     for (it = weights.begin(); it != weights.end(); ++it) {
     338                 :          0 :         double new_weight = it->second / cluster_size;
     339                 :          0 :         it->second = new_weight;
     340                 :          0 :         magnitude += new_weight * new_weight;
     341                 :            :     }
     342                 :          0 : }
     343                 :            : 
     344                 :            : void
     345                 :          0 : Centroid::clear()
     346                 :            : {
     347                 :            :     LOGCALL_VOID(API, "Centroid::clear", NO_ARGS);
     348                 :          0 :     weights.clear();
     349                 :          0 : }
     350                 :            : 
     351                 :            : Cluster&
     352                 :            : Cluster::operator=(const Cluster &) = default;
     353                 :            : 
     354                 :            : Cluster::Cluster(const Cluster &) = default;
     355                 :            : 
     356                 :            : Cluster::Cluster(Cluster &&) = default;
     357                 :            : 
     358                 :            : Cluster&
     359                 :            : Cluster::operator=(Cluster &&) = default;
     360                 :            : 
     361         [ +  - ]:         66 : Cluster::Cluster() : internal(new Xapian::Cluster::Internal)
     362                 :            : {
     363                 :            :     LOGCALL_CTOR(API, "Cluster", NO_ARGS);
     364                 :         33 : }
     365                 :            : 
     366                 :          0 : Cluster::Cluster(const Centroid &centroid)
     367         [ #  # ]:          0 :     : internal(new Xapian::Cluster::Internal(centroid))
     368                 :            : {
     369                 :            :     LOGCALL_CTOR(API, "Cluster", centroid);
     370                 :          0 : }
     371                 :            : 
     372                 :        186 : Cluster::~Cluster()
     373                 :            : {
     374                 :            :     LOGCALL_DTOR(API, "Cluster");
     375                 :         93 : }
     376                 :            : 
     377                 :         66 : Centroid::Centroid()
     378                 :            : {
     379                 :            :     LOGCALL_CTOR(API, "Centroid", NO_ARGS);
     380                 :         33 : }
     381                 :            : 
     382                 :            : DocumentSet
     383                 :         33 : Cluster::get_documents() const
     384                 :            : {
     385                 :            :     LOGCALL(API, DocumentSet, "Cluster::get_documents", NO_ARGS);
     386                 :         33 :     return internal->get_documents();
     387                 :            : }
     388                 :            : 
     389                 :            : DocumentSet
     390                 :         33 : Cluster::Internal::get_documents() const
     391                 :            : {
     392                 :         33 :     DocumentSet docs;
     393         [ +  + ]:         87 :     for (auto&& point : cluster_docs)
     394 [ +  - ][ +  - ]:         54 :         docs.add_document(point.get_document());
     395                 :         33 :     return docs;
     396                 :            : }
     397                 :            : 
     398                 :            : Point&
     399                 :          0 : Cluster::operator[](Xapian::doccount i)
     400                 :            : {
     401                 :          0 :     return internal->get_point(i);
     402                 :            : }
     403                 :            : 
     404                 :            : Point&
     405                 :          0 : Cluster::Internal::get_point(Xapian::doccount i)
     406                 :            : {
     407                 :          0 :     return cluster_docs[i];
     408                 :            : }
     409                 :            : 
     410                 :            : const Point&
     411                 :          0 : Cluster::operator[](Xapian::doccount i) const
     412                 :            : {
     413                 :          0 :     return internal->get_point(i);
     414                 :            : }
     415                 :            : 
     416                 :            : const Point&
     417                 :          0 : Cluster::Internal::get_point(Xapian::doccount i) const
     418                 :            : {
     419                 :          0 :     return cluster_docs[i];
     420                 :            : }
     421                 :            : 
     422                 :            : ClusterSet&
     423                 :            : ClusterSet::operator=(const ClusterSet &) = default;
     424                 :            : 
     425                 :            : ClusterSet::ClusterSet(const ClusterSet &) = default;
     426                 :            : 
     427                 :            : ClusterSet&
     428                 :            : ClusterSet::operator=(ClusterSet &&) = default;
     429                 :            : 
     430                 :            : ClusterSet::ClusterSet(ClusterSet &&) = default;
     431                 :            : 
     432                 :         18 : ClusterSet::ClusterSet() : internal(new Xapian::ClusterSet::Internal)
     433                 :            : {
     434                 :          9 : }
     435                 :            : 
     436                 :         18 : ClusterSet::~ClusterSet()
     437                 :            : {
     438                 :          9 : }
     439                 :            : 
     440                 :            : doccount
     441                 :        386 : ClusterSet::Internal::size() const
     442                 :            : {
     443                 :        386 :     return clusters.size();
     444                 :            : }
     445                 :            : 
     446                 :            : doccount
     447                 :        386 : ClusterSet::size() const
     448                 :            : {
     449                 :            :     LOGCALL(API, doccount, "ClusterSet::size", NO_ARGS);
     450                 :        386 :     return internal->size();
     451                 :            : }
     452                 :            : 
     453                 :            : void
     454                 :         33 : ClusterSet::Internal::add_cluster(const Cluster &cluster)
     455                 :            : {
     456                 :         33 :     clusters.push_back(cluster);
     457                 :         33 : }
     458                 :            : 
     459                 :            : void
     460                 :         33 : ClusterSet::add_cluster(const Cluster &cluster)
     461                 :            : {
     462                 :            :     LOGCALL_VOID(API, "ClusterSet::add_cluster", cluster);
     463                 :         33 :     internal->add_cluster(cluster);
     464                 :         33 : }
     465                 :            : 
     466                 :            : Cluster&
     467                 :        117 : ClusterSet::Internal::get_cluster(doccount i)
     468                 :            : {
     469                 :        117 :     return clusters[i];
     470                 :            : }
     471                 :            : 
     472                 :            : Cluster&
     473                 :         33 : ClusterSet::operator[](doccount i)
     474                 :            : {
     475                 :         33 :     return internal->get_cluster(i);
     476                 :            : }
     477                 :            : 
     478                 :            : const Cluster&
     479                 :          0 : ClusterSet::Internal::get_cluster(doccount i) const
     480                 :            : {
     481                 :          0 :     return clusters[i];
     482                 :            : }
     483                 :            : 
     484                 :            : const Cluster&
     485                 :         84 : ClusterSet::operator[](doccount i) const
     486                 :            : {
     487                 :         84 :     return internal->get_cluster(i);
     488                 :            : }
     489                 :            : 
     490                 :            : void
     491                 :         12 : ClusterSet::Internal::add_to_cluster(const Point &point, unsigned int index)
     492                 :            : {
     493                 :         12 :     clusters[index].add_point(point);
     494                 :         12 : }
     495                 :            : 
     496                 :            : void
     497                 :         12 : ClusterSet::add_to_cluster(const Point &point, unsigned int index)
     498                 :            : {
     499                 :            :     LOGCALL_VOID(API, "ClusterSet::add_to_cluster", point | index);
     500                 :         12 :     internal->add_to_cluster(point, index);
     501                 :         12 : }
     502                 :            : 
     503                 :            : void
     504                 :          0 : ClusterSet::Internal::recalculate_centroids()
     505                 :            : {
     506         [ #  # ]:          0 :     for (auto&& cluster : clusters)
     507         [ #  # ]:          0 :         cluster.recalculate();
     508                 :          0 : }
     509                 :            : 
     510                 :            : void
     511                 :          0 : ClusterSet::recalculate_centroids()
     512                 :            : {
     513                 :            :     LOGCALL_VOID(API, "ClusterSet::recalculate_centroids", NO_ARGS);
     514                 :          0 :     internal->recalculate_centroids();
     515                 :          0 : }
     516                 :            : 
     517                 :            : void
     518                 :          0 : ClusterSet::clear_clusters()
     519                 :            : {
     520                 :            :     LOGCALL_VOID(API, "ClusterSet::clear_clusters", NO_ARGS);
     521                 :          0 :     internal->clear_clusters();
     522                 :          0 : }
     523                 :            : 
     524                 :            : void
     525                 :          0 : ClusterSet::Internal::clear_clusters()
     526                 :            : {
     527         [ #  # ]:          0 :     for (auto&& cluster : clusters)
     528         [ #  # ]:          0 :         cluster.clear();
     529                 :          0 : }
     530                 :            : 
     531                 :            : doccount
     532                 :          0 : Cluster::size() const
     533                 :            : {
     534                 :            :     LOGCALL(API, doccount, "Cluster::size", NO_ARGS);
     535                 :          0 :     return internal->size();
     536                 :            : }
     537                 :            : 
     538                 :            : doccount
     539                 :          0 : Cluster::Internal::size() const
     540                 :            : {
     541                 :          0 :     return (cluster_docs.size());
     542                 :            : }
     543                 :            : 
     544                 :            : void
     545                 :         54 : Cluster::add_point(const Point &point)
     546                 :            : {
     547                 :            :     LOGCALL_VOID(API, "Cluster::add_point", point);
     548                 :         54 :     internal->add_point(point);
     549                 :         54 : }
     550                 :            : 
     551                 :            : void
     552                 :         54 : Cluster::Internal::add_point(const Point &point)
     553                 :            : {
     554                 :         54 :     cluster_docs.push_back(point);
     555                 :         54 : }
     556                 :            : 
     557                 :            : void
     558                 :          0 : Cluster::clear()
     559                 :            : {
     560                 :            :     LOGCALL_VOID(API, "Cluster::clear", NO_ARGS);
     561                 :          0 :     internal->clear();
     562                 :          0 : }
     563                 :            : 
     564                 :            : void
     565                 :          0 : Cluster::Internal::clear()
     566                 :            : {
     567                 :          0 :     cluster_docs.clear();
     568                 :          0 : }
     569                 :            : 
     570                 :            : const Centroid&
     571                 :         84 : Cluster::get_centroid() const
     572                 :            : {
     573                 :            :     LOGCALL(API, Centroid, "Cluster::get_centroid", NO_ARGS);
     574                 :         84 :     return internal->get_centroid();
     575                 :            : }
     576                 :            : 
     577                 :            : const Centroid&
     578                 :         84 : Cluster::Internal::get_centroid() const
     579                 :            : {
     580                 :         84 :     return centroid;
     581                 :            : }
     582                 :            : 
     583                 :            : void
     584                 :          0 : Cluster::set_centroid(const Centroid &centroid_)
     585                 :            : {
     586                 :            :     LOGCALL_VOID(API, "Cluster::set_centroid", centroid_);
     587                 :          0 :     internal->set_centroid(centroid_);
     588                 :          0 : }
     589                 :            : 
     590                 :            : void
     591                 :          0 : Cluster::Internal::set_centroid(const Centroid &centroid_)
     592                 :            : {
     593                 :          0 :     centroid = centroid_;
     594                 :          0 : }
     595                 :            : 
     596                 :            : void
     597                 :          0 : Cluster::recalculate()
     598                 :            : {
     599                 :            :     LOGCALL_VOID(API, "Cluster::recalculate", NO_ARGS);
     600                 :          0 :     internal->recalculate();
     601                 :          0 : }
     602                 :            : 
     603                 :            : void
     604                 :          0 : Cluster::Internal::recalculate()
     605                 :            : {
     606                 :          0 :     centroid.clear();
     607         [ #  # ]:          0 :     for (const Point& temp : cluster_docs) {
     608 [ #  # ][ #  # ]:          0 :         for (TermIterator titer = temp.termlist_begin(); titer != temp.termlist_end(); ++titer)
                 [ #  # ]
     609 [ #  # ][ #  # ]:          0 :             centroid.add_weight(*titer, temp.get_weight(*titer));
         [ #  # ][ #  # ]
     610                 :            :     }
     611                 :          0 :     centroid.divide(size());
     612                 :          0 : }
     613                 :            : 
     614                 :         28 : StemStopper::StemStopper(const Stem &stemmer_, stem_strategy strategy)
     615 [ +  - ][ +  - ]:         28 :     : stem_action(strategy), stemmer(stemmer_)
     616                 :            : {
     617                 :            :     LOGCALL_CTOR(API, "StemStopper", stemmer_ | strategy);
     618                 :         28 : }
     619                 :            : 
     620                 :            : string
     621                 :          0 : StemStopper::get_description() const
     622                 :            : {
     623         [ #  # ]:          0 :     string desc("Xapian::StemStopper(");
     624                 :          0 :     unordered_set<string>::const_iterator i;
     625         [ #  # ]:          0 :     for (i = stop_words.begin(); i != stop_words.end(); ++i) {
     626 [ #  # ][ #  # ]:          0 :         if (i != stop_words.begin()) desc += ' ';
     627         [ #  # ]:          0 :         desc += *i;
     628                 :            :     }
     629         [ #  # ]:          0 :     desc += ')';
     630                 :          0 :     return desc;
     631                 :            : }
     632                 :            : 
     633                 :            : void
     634                 :         28 : StemStopper::add(const string &term)
     635                 :            : {
     636                 :            :     LOGCALL_VOID(API, "StemStopper::add", term);
     637   [ +  +  +  +  :         28 :     switch (stem_action) {
                      - ]
     638                 :            :         case STEM_NONE:
     639                 :          7 :             stop_words.insert(term);
     640                 :          7 :             break;
     641                 :            :         case STEM_ALL_Z:
     642 [ +  - ][ +  - ]:          7 :             stop_words.insert('Z' + stemmer(term));
     643                 :          7 :             break;
     644                 :            :         case STEM_ALL:
     645         [ +  - ]:          7 :             stop_words.insert(stemmer(term));
     646                 :          7 :             break;
     647                 :            :         case STEM_SOME:
     648                 :            :         case STEM_SOME_FULL_POS:
     649                 :          7 :             stop_words.insert(term);
     650 [ +  - ][ +  - ]:          7 :             stop_words.insert('Z' + stemmer(term));
     651                 :          7 :             break;
     652                 :            :     }
     653                 :         28 : }

Generated by: LCOV version 1.11