A library for working with phylogenetic and population genetic data.
v0.27.0
functions/genome_locus.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_POPULATION_FUNCTIONS_GENOME_LOCUS_H_
2 #define GENESIS_POPULATION_FUNCTIONS_GENOME_LOCUS_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2022 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (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, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
35 
36 #include <cassert>
37 #include <iostream>
38 #include <string>
39 #include <stdexcept>
40 
41 namespace genesis {
42 namespace population {
43 
44 // =================================================================================================
45 // Output
46 // =================================================================================================
47 
48 inline std::string to_string( GenomeLocus const& locus )
49 {
50  // Error case.
51  if( locus.chromosome.empty() ) {
52  throw std::invalid_argument( "Invalid GenomeLocus with empty chromosome." );
53  }
54 
55  // Special case.
56  if( locus.position == 0 ) {
57  return locus.chromosome;
58  }
59 
60  // General case.
61  return locus.chromosome + ":" + std::to_string( locus.position );
62 }
63 
64 inline std::ostream& operator << ( std::ostream& os, GenomeLocus const& locus )
65 {
66  os << to_string( locus );
67  return os;
68 }
69 
70 // =================================================================================================
71 // Comparion Operators
72 // =================================================================================================
73 
74 // Really good example of the claim that C++ needs a lot of boilerplate code...
75 // We here provide all comparison operators for GenomeLocus, but also comparing loci given
76 // as chromosome (`std::string`) and position (`size_t`) separately.
77 // Maybe there is a smarter way to generate this, probably using macros, but then again,
78 // most operators are optimized, and macros are ugly...
79 // So, we live with the boilerplate for clarity - this also works better with code documentation!
80 
81 // -------------------------------------------------------------------------
82 // Spaceship <=>
83 // -------------------------------------------------------------------------
84 
95 inline int locus_compare(
96  std::string const& l_chromosome, size_t l_position,
97  std::string const& r_chromosome, size_t r_position
98 ) {
99  // This is a lot of branching. Maybe there is a smarter way. Good enough for now though.
100  if( l_chromosome < r_chromosome ) {
101  return -1;
102  } else if( l_chromosome > r_chromosome ) {
103  return +1;
104  } else {
105  assert( l_chromosome == r_chromosome );
106  if( l_position < r_position ) {
107  return -1;
108  } else if( l_position > r_position ) {
109  return +1;
110  }
111  }
112  assert( l_chromosome == r_chromosome );
113  assert( l_position == r_position );
114  return 0;
115 }
116 
120 inline int locus_compare(
121  GenomeLocus const& l,
122  std::string const& r_chromosome, size_t r_position
123 ) {
124  return locus_compare( l.chromosome, l.position, r_chromosome, r_position );
125 }
126 
130 inline int locus_compare(
131  std::string const& l_chromosome, size_t l_position,
132  GenomeLocus const& r
133 ) {
134  return locus_compare( l_chromosome, l_position, r.chromosome, r.position );
135 }
136 
140 inline int locus_compare(
141  GenomeLocus const& l,
142  GenomeLocus const& r
143 ) {
144  return locus_compare( l.chromosome, l.position, r.chromosome, r.position );
145 }
146 
147 // Let's be cool and add the actual spaceship, even if genesis is currently using C++11.
148 // Users might compile with later versions, so this might be useful to have.
149 
150 #if __cplusplus >= 202002L
151 
155 inline int operator <=> ( GenomeLocus const& l, GenomeLocus const& r )
156 {
157  return locus_compare( l.chromosome, l.position, r.chromosome, r.position );
158 }
159 
160 #endif // __cplusplus >= 202002L
161 
162 // -------------------------------------------------------------------------
163 // Equality ==
164 // -------------------------------------------------------------------------
165 
169 inline bool locus_equal(
170  std::string const& l_chromosome, size_t l_position,
171  std::string const& r_chromosome, size_t r_position
172 ) {
173  return l_chromosome == r_chromosome && l_position == r_position;
174 }
175 
179 inline bool locus_equal(
180  GenomeLocus const& l,
181  std::string const& r_chromosome, size_t r_position
182 ) {
183  return locus_equal( l.chromosome, l.position, r_chromosome, r_position );
184 }
185 
189 inline bool locus_equal(
190  std::string const& l_chromosome, size_t l_position,
191  GenomeLocus const& r
192 ) {
193  return locus_equal( l_chromosome, l_position, r.chromosome, r.position );
194 }
195 
199 inline bool locus_equal(
200  GenomeLocus const& l,
201  GenomeLocus const& r
202 ) {
203  return locus_equal( l.chromosome, l.position, r.chromosome, r.position );
204 }
205 
209 inline bool operator == ( GenomeLocus const& l, GenomeLocus const& r )
210 {
211  return locus_equal( l.chromosome, l.position, r.chromosome, r.position );
212 }
213 
214 // -------------------------------------------------------------------------
215 // Inequality !=
216 // -------------------------------------------------------------------------
217 
221 inline bool locus_inequal(
222  std::string const& l_chromosome, size_t l_position,
223  std::string const& r_chromosome, size_t r_position
224 ) {
225  return ! locus_equal( l_chromosome, l_position, r_chromosome, r_position );
226 }
227 
231 inline bool locus_inequal(
232  GenomeLocus const& l,
233  std::string const& r_chromosome, size_t r_position
234 ) {
235  return locus_inequal( l.chromosome, l.position, r_chromosome, r_position );
236 }
237 
241 inline bool locus_inequal(
242  std::string const& l_chromosome, size_t l_position,
243  GenomeLocus const& r
244 ) {
245  return locus_inequal( l_chromosome, l_position, r.chromosome, r.position );
246 }
247 
251 inline bool locus_inequal(
252  GenomeLocus const& l,
253  GenomeLocus const& r
254 ) {
255  return locus_inequal( l.chromosome, l.position, r.chromosome, r.position );
256 }
257 
261 inline bool operator != ( GenomeLocus const& l, GenomeLocus const& r )
262 {
263  return locus_inequal( l.chromosome, l.position, r.chromosome, r.position );
264 }
265 
266 // -------------------------------------------------------------------------
267 // Less than <
268 // -------------------------------------------------------------------------
269 
277 inline bool locus_less(
278  std::string const& l_chromosome, size_t l_position,
279  std::string const& r_chromosome, size_t r_position
280 ) {
281  return l_chromosome < r_chromosome || ( l_chromosome == r_chromosome && l_position < r_position );
282 }
283 
287 inline bool locus_less(
288  GenomeLocus const& l,
289  std::string const& r_chromosome, size_t r_position
290 ) {
291  return locus_less( l.chromosome, l.position, r_chromosome, r_position );
292 }
293 
297 inline bool locus_less(
298  std::string const& l_chromosome, size_t l_position,
299  GenomeLocus const& r
300 ) {
301  return locus_less( l_chromosome, l_position, r.chromosome, r.position );
302 }
303 
307 inline bool locus_less(
308  GenomeLocus const& l,
309  GenomeLocus const& r
310 ) {
311  return locus_less( l.chromosome, l.position, r.chromosome, r.position );
312 }
313 
317 inline bool operator < ( GenomeLocus const& l, GenomeLocus const& r )
318 {
319  return locus_less( l.chromosome, l.position, r.chromosome, r.position );
320 }
321 
322 // -------------------------------------------------------------------------
323 // Greater than >
324 // -------------------------------------------------------------------------
325 
331 inline bool locus_greater(
332  std::string const& l_chromosome, size_t l_position,
333  std::string const& r_chromosome, size_t r_position
334 ) {
335  return locus_less( r_chromosome, r_position, l_chromosome, l_position );
336 }
337 
341 inline bool locus_greater(
342  GenomeLocus const& l,
343  std::string const& r_chromosome, size_t r_position
344 ) {
345  return locus_greater( l.chromosome, l.position, r_chromosome, r_position );
346 }
347 
351 inline bool locus_greater(
352  std::string const& l_chromosome, size_t l_position,
353  GenomeLocus const& r
354 ) {
355  return locus_greater( l_chromosome, l_position, r.chromosome, r.position );
356 }
357 
361 inline bool locus_greater(
362  GenomeLocus const& l,
363  GenomeLocus const& r
364 ) {
365  return locus_greater( l.chromosome, l.position, r.chromosome, r.position );
366 }
367 
371 inline bool operator > ( GenomeLocus const& l, GenomeLocus const& r )
372 {
373  return locus_greater( l.chromosome, l.position, r.chromosome, r.position );
374 }
375 
376 // -------------------------------------------------------------------------
377 // Less than or equal <=
378 // -------------------------------------------------------------------------
379 
386  std::string const& l_chromosome, size_t l_position,
387  std::string const& r_chromosome, size_t r_position
388 ) {
389  // We could do the simple default way of implementing this as `a == b || a < b`,
390  // but this seems wasteful; in this case, we can do with fewer comparisons!
391  return l_chromosome < r_chromosome || ( l_chromosome == r_chromosome && l_position <= r_position );
392 }
393 
398  GenomeLocus const& l,
399  std::string const& r_chromosome, size_t r_position
400 ) {
401  return locus_less_or_equal( l.chromosome, l.position, r_chromosome, r_position );
402 }
403 
408  std::string const& l_chromosome, size_t l_position,
409  GenomeLocus const& r
410 ) {
411  return locus_less_or_equal( l_chromosome, l_position, r.chromosome, r.position );
412 }
413 
418  GenomeLocus const& l,
419  GenomeLocus const& r
420 ) {
422 }
423 
427 inline bool operator <= ( GenomeLocus const& l, GenomeLocus const& r )
428 {
430 }
431 
432 // -------------------------------------------------------------------------
433 // Greater than or equal >=
434 // -------------------------------------------------------------------------
435 
442  std::string const& l_chromosome, size_t l_position,
443  std::string const& r_chromosome, size_t r_position
444 ) {
445  return locus_less_or_equal( r_chromosome, r_position, l_chromosome, l_position );
446 }
447 
452  GenomeLocus const& l,
453  std::string const& r_chromosome, size_t r_position
454 ) {
455  return locus_greater_or_equal( l.chromosome, l.position, r_chromosome, r_position );
456 }
457 
462  std::string const& l_chromosome, size_t l_position,
463  GenomeLocus const& r
464 ) {
465  return locus_greater_or_equal( l_chromosome, l_position, r.chromosome, r.position );
466 }
467 
472  GenomeLocus const& l,
473  GenomeLocus const& r
474 ) {
476 }
477 
481 inline bool operator >= ( GenomeLocus const& l, GenomeLocus const& r )
482 {
484 }
485 
486 } // namespace population
487 } // namespace genesis
488 
489 #endif // include guard
genesis::population::locus_equal
bool locus_equal(std::string const &l_chromosome, size_t l_position, std::string const &r_chromosome, size_t r_position)
Equality comparison (==) for two loci in a genome.
Definition: functions/genome_locus.hpp:169
genesis::population::operator!=
bool operator!=(GenomeLocus const &l, GenomeLocus const &r)
Inequality comparison (!=) for two loci in a genome.
Definition: functions/genome_locus.hpp:261
genesis::population::operator<=
bool operator<=(GenomeLocus const &l, GenomeLocus const &r)
Less than or equal comparison (<=) for two loci in a genome.
Definition: functions/genome_locus.hpp:427
genesis::population::GenomeLocus::position
size_t position
Definition: genome_locus.hpp:59
genome_locus.hpp
genesis::population::locus_greater
bool locus_greater(std::string const &l_chromosome, size_t l_position, std::string const &r_chromosome, size_t r_position)
Greater than comparison (>) for two loci in a genome.
Definition: functions/genome_locus.hpp:331
genesis::population::locus_compare
int locus_compare(std::string const &l_chromosome, size_t l_position, std::string const &r_chromosome, size_t r_position)
Three-way comparison (spaceship operator <=>) for two loci in a genome.
Definition: functions/genome_locus.hpp:95
genesis::population::operator==
bool operator==(GenomeLocus const &l, GenomeLocus const &r)
Equality comparison (==) for two loci in a genome.
Definition: functions/genome_locus.hpp:209
genesis::population::GenomeLocus
A single locus, that is, a position (or coordinate) on a chromosome.
Definition: genome_locus.hpp:56
genesis::population::locus_greater_or_equal
bool locus_greater_or_equal(std::string const &l_chromosome, size_t l_position, std::string const &r_chromosome, size_t r_position)
Greater than or equal comparison (>=) for two loci in a genome.
Definition: functions/genome_locus.hpp:441
genesis::population::GenomeLocus::chromosome
std::string chromosome
Definition: genome_locus.hpp:58
genesis::population::operator<<
std::ostream & operator<<(std::ostream &os, BaseCounts const &bs)
Output stream operator for BaseCounts instances.
Definition: population/functions/functions.cpp:486
genesis::population::to_string
std::string to_string(GenomeLocus const &locus)
Definition: functions/genome_locus.hpp:48
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::population::operator<
bool operator<(GenomeLocus const &l, GenomeLocus const &r)
Less than comparison (<) for two loci in a genome.
Definition: functions/genome_locus.hpp:317
genesis::population::operator>
bool operator>(GenomeLocus const &l, GenomeLocus const &r)
Greater than comparison (>) for two loci in a genome.
Definition: functions/genome_locus.hpp:371
genesis::population::locus_less
bool locus_less(std::string const &l_chromosome, size_t l_position, std::string const &r_chromosome, size_t r_position)
Less than comparison (<) for two loci in a genome.
Definition: functions/genome_locus.hpp:277
genesis::population::locus_inequal
bool locus_inequal(std::string const &l_chromosome, size_t l_position, std::string const &r_chromosome, size_t r_position)
Inequality comparison (!=) for two loci in a genome.
Definition: functions/genome_locus.hpp:221
genesis::population::locus_less_or_equal
bool locus_less_or_equal(std::string const &l_chromosome, size_t l_position, std::string const &r_chromosome, size_t r_position)
Less than or equal comparison (<=) for two loci in a genome.
Definition: functions/genome_locus.hpp:385
genesis::population::operator>=
bool operator>=(GenomeLocus const &l, GenomeLocus const &r)
Greater than or equal comparison (>=) for two loci in a genome.
Definition: functions/genome_locus.hpp:481