LCOV - code coverage report
Current view: top level - geospatial - latlong_posting_source.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core 954b5873a738 Lines: 39 109 35.8 %
Date: 2019-06-30 05:20:33 Functions: 10 17 58.8 %
Branches: 23 166 13.9 %

           Branch data     Line data    Source code
       1                 :            : /** @file latlong_posting_source.cc
       2                 :            :  * @brief LatLongDistancePostingSource implementation.
       3                 :            :  */
       4                 :            : /* Copyright 2008 Lemur Consulting Ltd
       5                 :            :  * Copyright 2010,2011 Richard Boulton
       6                 :            :  * Copyright 2012,2015 Olly Betts
       7                 :            :  *
       8                 :            :  * This program is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU General Public License as
      10                 :            :  * published by the Free Software Foundation; either version 2 of the
      11                 :            :  * License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This program is distributed in the hope that it will be useful,
      14                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16                 :            :  * GNU General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU General Public License
      19                 :            :  * along with this program; if not, write to the Free Software
      20                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      21                 :            :  * USA
      22                 :            :  */
      23                 :            : 
      24                 :            : #include <config.h>
      25                 :            : 
      26                 :            : #include "xapian/geospatial.h"
      27                 :            : 
      28                 :            : #include "xapian/error.h"
      29                 :            : #include "xapian/registry.h"
      30                 :            : 
      31                 :            : #include "pack.h"
      32                 :            : #include "serialise-double.h"
      33                 :            : #include "str.h"
      34                 :            : 
      35                 :            : #include <cmath>
      36                 :            : 
      37                 :            : using namespace Xapian;
      38                 :            : using namespace std;
      39                 :            : 
      40                 :            : static double
      41                 :       1655 : weight_from_distance(double dist, double k1, double k2)
      42                 :            : {
      43                 :       1655 :     return k1 * pow(dist + k1, -k2);
      44                 :            : }
      45                 :            : 
      46                 :            : void
      47                 :         90 : LatLongDistancePostingSource::calc_distance()
      48                 :            : {
      49         [ +  - ]:         90 :     dist = (*metric)(centre, get_value());
      50                 :         90 : }
      51                 :            : 
      52                 :            : /// Validate the parameters supplied to LatLongDistancePostingSource.
      53                 :            : static void
      54                 :       1589 : validate_postingsource_params(double k1, double k2) {
      55         [ -  + ]:       1589 :     if (k1 <= 0) {
      56                 :            :         string msg("k1 parameter to LatLongDistancePostingSource must be "
      57         [ #  # ]:          0 :                    "greater than 0; was ");
      58 [ #  # ][ #  # ]:          0 :         msg += str(k1);
      59 [ #  # ][ #  # ]:          0 :         throw InvalidArgumentError(msg);
      60                 :            :     }
      61         [ -  + ]:       1589 :     if (k2 <= 0) {
      62                 :            :         string msg("k2 parameter to LatLongDistancePostingSource must be "
      63         [ #  # ]:          0 :                    "greater than 0; was ");
      64 [ #  # ][ #  # ]:          0 :         msg += str(k2);
      65 [ #  # ][ #  # ]:          0 :         throw InvalidArgumentError(msg);
      66                 :            :     }
      67                 :       1589 : }
      68                 :            : 
      69                 :          0 : LatLongDistancePostingSource::LatLongDistancePostingSource(
      70                 :            :         valueno slot_,
      71                 :            :         const LatLongCoords & centre_,
      72                 :            :         const LatLongMetric * metric_,
      73                 :            :         double max_range_,
      74                 :            :         double k1_,
      75                 :            :         double k2_)
      76                 :            :         : ValuePostingSource(slot_),
      77                 :            :           centre(centre_),
      78                 :            :           metric(metric_),
      79                 :            :           max_range(max_range_),
      80                 :            :           k1(k1_),
      81         [ #  # ]:          0 :           k2(k2_)
      82                 :            : {
      83         [ #  # ]:          0 :     validate_postingsource_params(k1, k2);
      84         [ #  # ]:          0 :     set_maxweight(weight_from_distance(0, k1, k2));
      85                 :          0 : }
      86                 :            : 
      87                 :       1574 : LatLongDistancePostingSource::LatLongDistancePostingSource(
      88                 :            :         valueno slot_,
      89                 :            :         const LatLongCoords & centre_,
      90                 :            :         const LatLongMetric & metric_,
      91                 :            :         double max_range_,
      92                 :            :         double k1_,
      93                 :            :         double k2_)
      94                 :            :         : ValuePostingSource(slot_),
      95                 :            :           centre(centre_),
      96         [ +  - ]:       1574 :           metric(metric_.clone()),
      97                 :            :           max_range(max_range_),
      98                 :            :           k1(k1_),
      99         [ +  - ]:       1574 :           k2(k2_)
     100                 :            : {
     101         [ +  - ]:       1574 :     validate_postingsource_params(k1, k2);
     102         [ +  - ]:       1574 :     set_maxweight(weight_from_distance(0, k1, k2));
     103                 :       1574 : }
     104                 :            : 
     105                 :         15 : LatLongDistancePostingSource::LatLongDistancePostingSource(
     106                 :            :         valueno slot_,
     107                 :            :         const LatLongCoords & centre_,
     108                 :            :         double max_range_,
     109                 :            :         double k1_,
     110                 :            :         double k2_)
     111                 :            :         : ValuePostingSource(slot_),
     112                 :            :           centre(centre_),
     113                 :          0 :           metric(new Xapian::GreatCircleMetric()),
     114                 :            :           max_range(max_range_),
     115                 :            :           k1(k1_),
     116 [ +  - ][ +  - ]:         15 :           k2(k2_)
                 [ +  - ]
     117                 :            : {
     118         [ +  - ]:         15 :     validate_postingsource_params(k1, k2);
     119         [ +  - ]:         15 :     set_maxweight(weight_from_distance(0, k1, k2));
     120                 :         15 : }
     121                 :            : 
     122                 :       4737 : LatLongDistancePostingSource::~LatLongDistancePostingSource()
     123                 :            : {
     124         [ +  - ]:       1589 :     delete metric;
     125         [ -  + ]:       3148 : }
     126                 :            : 
     127                 :            : void
     128                 :         96 : LatLongDistancePostingSource::next(double min_wt)
     129                 :            : {
     130                 :         96 :     ValuePostingSource::next(min_wt);
     131                 :            : 
     132         [ +  + ]:        120 :     while (!ValuePostingSource::at_end()) {
     133                 :         90 :         calc_distance();
     134 [ +  + ][ +  + ]:         90 :         if (max_range == 0 || dist <= max_range)
     135                 :            :             break;
     136                 :         24 :         ValuePostingSource::next(min_wt);
     137                 :            :     }
     138                 :         96 : }
     139                 :            : 
     140                 :            : void
     141                 :          0 : LatLongDistancePostingSource::skip_to(docid min_docid,
     142                 :            :                                       double min_wt)
     143                 :            : {
     144                 :          0 :     ValuePostingSource::skip_to(min_docid, min_wt);
     145                 :            : 
     146         [ #  # ]:          0 :     while (!ValuePostingSource::at_end()) {
     147                 :          0 :         calc_distance();
     148 [ #  # ][ #  # ]:          0 :         if (max_range == 0 || dist <= max_range)
     149                 :            :             break;
     150                 :          0 :         ValuePostingSource::next(min_wt);
     151                 :            :     }
     152                 :          0 : }
     153                 :            : 
     154                 :            : bool
     155                 :          0 : LatLongDistancePostingSource::check(docid min_docid,
     156                 :            :                                     double min_wt)
     157                 :            : {
     158         [ #  # ]:          0 :     if (!ValuePostingSource::check(min_docid, min_wt)) {
     159                 :            :         // check returned false, so we know the document is not in the source.
     160                 :          0 :         return false;
     161                 :            :     }
     162         [ #  # ]:          0 :     if (ValuePostingSource::at_end()) {
     163                 :            :         // return true, since we're definitely at the end of the list.
     164                 :          0 :         return true;
     165                 :            :     }
     166                 :            : 
     167                 :          0 :     calc_distance();
     168 [ #  # ][ #  # ]:          0 :     if (max_range > 0 && dist > max_range) {
     169                 :          0 :         return false;
     170                 :            :     }
     171                 :          0 :     return true;
     172                 :            : }
     173                 :            : 
     174                 :            : double
     175                 :         66 : LatLongDistancePostingSource::get_weight() const
     176                 :            : {
     177                 :         66 :     return weight_from_distance(dist, k1, k2);
     178                 :            : }
     179                 :            : 
     180                 :            : LatLongDistancePostingSource *
     181                 :          0 : LatLongDistancePostingSource::clone() const
     182                 :            : {
     183                 :          0 :     return new LatLongDistancePostingSource(get_slot(), centre,
     184                 :          0 :                                             metric->clone(),
     185         [ #  # ]:          0 :                                             max_range, k1, k2);
     186                 :            : }
     187                 :            : 
     188                 :            : string
     189                 :       1559 : LatLongDistancePostingSource::name() const
     190                 :            : {
     191         [ +  - ]:       1559 :     return "Xapian::LatLongDistancePostingSource";
     192                 :            : }
     193                 :            : 
     194                 :            : string
     195                 :          0 : LatLongDistancePostingSource::serialise() const
     196                 :            : {
     197                 :          0 :     string result;
     198 [ #  # ][ #  # ]:          0 :     result += serialise_double(max_range);
     199 [ #  # ][ #  # ]:          0 :     result += serialise_double(k1);
     200 [ #  # ][ #  # ]:          0 :     result += serialise_double(k2);
     201         [ #  # ]:          0 :     pack_uint(result, get_slot());
     202 [ #  # ][ #  # ]:          0 :     pack_string(result, centre.serialise());
     203 [ #  # ][ #  # ]:          0 :     pack_string(result, metric->name());
     204 [ #  # ][ #  # ]:          0 :     result += metric->serialise();
     205                 :          0 :     return result;
     206                 :            : }
     207                 :            : 
     208                 :            : LatLongDistancePostingSource *
     209                 :          0 : LatLongDistancePostingSource::unserialise_with_registry(const string &s,
     210                 :            :                                              const Registry & registry) const
     211                 :            : {
     212                 :          0 :     const char * p = s.data();
     213                 :          0 :     const char * end = p + s.size();
     214                 :            : 
     215         [ #  # ]:          0 :     double new_max_range = unserialise_double(&p, end);
     216         [ #  # ]:          0 :     double new_k1 = unserialise_double(&p, end);
     217         [ #  # ]:          0 :     double new_k2 = unserialise_double(&p, end);
     218                 :            : 
     219                 :            :     valueno new_slot;
     220         [ #  # ]:          0 :     string new_serialised_centre;
     221         [ #  # ]:          0 :     string new_metric_name;
     222 [ #  # ][ #  # ]:          0 :     if (!unpack_uint(&p, end, &new_slot) ||
     223 [ #  # ][ #  # ]:          0 :         !unpack_string(&p, end, new_serialised_centre) ||
                 [ #  # ]
     224         [ #  # ]:          0 :         !unpack_string(&p, end, new_metric_name)) {
     225 [ #  # ][ #  # ]:          0 :         throw SerialisationError("Bad serialised LatLongDistancePostingSource");
                 [ #  # ]
     226                 :            :     }
     227                 :            : 
     228         [ #  # ]:          0 :     string new_serialised_metric(p, end - p);
     229                 :            : 
     230                 :          0 :     LatLongCoords new_centre;
     231         [ #  # ]:          0 :     new_centre.unserialise(new_serialised_centre);
     232                 :            : 
     233                 :            :     const Xapian::LatLongMetric * metric_type =
     234         [ #  # ]:          0 :             registry.get_lat_long_metric(new_metric_name);
     235         [ #  # ]:          0 :     if (metric_type == NULL) {
     236         [ #  # ]:          0 :         string msg("LatLongMetric ");
     237         [ #  # ]:          0 :         msg += new_metric_name;
     238         [ #  # ]:          0 :         msg += " not registered";
     239 [ #  # ][ #  # ]:          0 :         throw InvalidArgumentError(msg);
     240                 :            :     }
     241                 :            :     LatLongMetric * new_metric =
     242         [ #  # ]:          0 :             metric_type->unserialise(new_serialised_metric);
     243                 :            : 
     244                 :            :     return new LatLongDistancePostingSource(new_slot, new_centre,
     245                 :            :                                             new_metric,
     246 [ #  # ][ #  # ]:          0 :                                             new_max_range, new_k1, new_k2);
     247                 :            : }
     248                 :            : 
     249                 :            : void
     250                 :         30 : LatLongDistancePostingSource::init(const Database & db_)
     251                 :            : {
     252                 :         30 :     ValuePostingSource::init(db_);
     253         [ +  + ]:         30 :     if (max_range > 0.0) {
     254                 :            :         // Possible that no documents are in range.
     255                 :         24 :         set_termfreq_min(0);
     256                 :            :         // Note - would be good to improve termfreq_est here, too, but
     257                 :            :         // I can't think of anything we can do with the information
     258                 :            :         // available.
     259                 :            :     }
     260                 :         30 : }
     261                 :            : 
     262                 :            : string
     263                 :          0 : LatLongDistancePostingSource::get_description() const
     264                 :            : {
     265         [ #  # ]:          0 :     string result("Xapian::LatLongDistancePostingSource(slot=");
     266 [ #  # ][ #  # ]:          0 :     result += str(get_slot());
     267         [ #  # ]:          0 :     result += ")";
     268                 :          0 :     return result;
     269                 :            : }

Generated by: LCOV version 1.11