ccgsl 2.7.2
C++wrappersforGnuScientificLibrary
combination.hpp
Go to the documentation of this file.
1/*
2 * $Id: combination.hpp 316 2014-02-22 14:32:31Z jdl3 $
3 * Copyright (C) 2012, 2014, 2024 John D Lamb
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#ifndef CCGSL_COMBINATION_HPP
21#define CCGSL_COMBINATION_HPP
22
23#include<cstddef>
24#include<new>
25#include<algorithm>
26#include<gsl/gsl_combination.h>
27#include"exception.hpp"
28
29namespace gsl {
34 public:
39 ccgsl_pointer = 0;
40 count = 0; // initially nullptr will do
41 }
48 explicit combination( size_t const n, size_t const k, bool init = false ){
49 ccgsl_pointer = gsl_combination_alloc( n, k );
50 // just plausibly we could allocate combination but not count
51 try { count = new size_t; } catch( std::bad_alloc& e ){
52 // try to tidy up before rethrowing
53 gsl_combination_free( ccgsl_pointer );
54 throw e;
55 }
56 *count = 1; // initially there is just one reference to ccgsl_pointer
57 if( init ) this->init_first();
58 }
64 explicit combination( gsl_combination* v ){
65 ccgsl_pointer = v;
66 // just plausibly we could fail to allocate count: no further action needed.
67 count = new size_t;
68 *count = 1; // initially there is just one reference to ccgsl_pointer
69 }
70 // copy constructor
76 if( count != 0 ) ++*count; // combination is now shared.
77 }
78 // assignment operator
84 // first, possibly delete anything pointed to by this
85 if( count == 0 or --*count == 0 ){
86 if( ccgsl_pointer != 0 ) gsl_combination_free( ccgsl_pointer );
87 delete count;
88 }
89 // Then copy
91 count = v.count;
92 if( count != 0 ) ++*count; // combination is now shared.
93 return *this;
94 }
95 // clone()
102 combination copy( get()->n, get()->k );
103 // Now copy
104 gsl_combination_memcpy( copy.get(), get() );
105 // return new object
106 return copy;
107 }
108 // destructor
113 if( count == 0 or --*count == 0 ){
114 // could have allocated null pointer
115 if( ccgsl_pointer != 0 ) gsl_combination_free( ccgsl_pointer );
116 delete count;
117 }
118 }
119#ifdef __GXX_EXPERIMENTAL_CXX0X__
125 std::swap( count, v.count );
126 v.ccgsl_pointer = nullptr;
127 }
134 std::swap( ccgsl_pointer, v.ccgsl_pointer );
135 std::swap( count, v.count );
136 return *this;
137 }
138#endif
139 private:
143 gsl_combination* ccgsl_pointer;
147 size_t* count;
148 public:
149 // shared reference functions
154 gsl_combination* get(){ return ccgsl_pointer; }
159 gsl_combination const* get() const { return ccgsl_pointer; }
165 bool unique() const { return count != 0 and *count == 1; }
170 size_t use_count() const { return count == 0 ? 0 : *count; }
176#ifdef __GXX_EXPERIMENTAL_CXX0X__
177 explicit
178#endif
179 operator bool() const { return ccgsl_pointer != 0; }
180 public:
181 // GSL functions
188 static combination calloc( size_t const n, size_t const k ){
189 return combination( gsl_combination_calloc( n, k ) ); }
193 void init_first(){ gsl_combination_init_first( get() ); }
197 void init_last(){ gsl_combination_init_last( get() ); }
203 int memcpy( combination const& src ){ return gsl_combination_memcpy( get(), src.get() ); }
209 int fread( FILE* stream ){ return gsl_combination_fread( stream, get() ); }
215 int fwrite( FILE* stream ) const { return gsl_combination_fwrite( stream, get() ); }
221 int fscanf( FILE* stream ){ return gsl_combination_fscanf( stream, get() ); }
228 int fprintf( FILE* stream, char const* format ) const {
229 return gsl_combination_fprintf( stream, get(), format ); }
234 size_t n() const { return get()->n; }
239 size_t k() const { return get()->k; }
244 size_t* data() { return get()->data; }
249 int valid() { return gsl_combination_valid( get() ); }
254 int next(){ return gsl_combination_next( get() ); }
259 int prev(){ return gsl_combination_prev( get() ); }
265 size_t get( size_t const i ) const { return gsl_combination_get( get(), i ); }
271 size_t operator[]( size_t const i ) const { return gsl_combination_get( get(), i ); }
272 private:
277 template<typename container, typename content, bool reverse> class iterator_base {
278 friend class combination;
279 public:
283 typedef std::random_access_iterator_tag iterator_category;
287 typedef size_t value_type;
296 // // type iterator_traits<combination>::difference_type
300 typedef ptrdiff_t difference_type;
301 public:
302 // // operator*
308 // Always try to return something
309 static content something = 0;
310 // First check that iterator is initialised.
311 if( v == 0 ){
312 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAULT );
313 return something;
314 } else if( v->ccgsl_pointer == 0 ){
315 gsl_error( "combination not initialised", __FILE__, __LINE__, exception::GSL_EFAULT );
316 return something;
317 }
318 // Check that position make sense
319 if( position >= static_cast<difference_type>( v->k() ) ){
320 gsl_error( "trying to dereference beyond rbegin()", __FILE__, __LINE__, exception::GSL_EFAILED );
321 return something;
322 }
323 if( position <= -1 ){
324 gsl_error( "trying to dereference beyond begin()", __FILE__, __LINE__, exception::GSL_EFAILED );
325 return something;
326 }
327 // position and v are valid: return data
328 return *(v->ccgsl_pointer->data + position);
329 }
330 // // operator->
336 // First check that iterator is initialised.
337 if( v == 0 ){
338 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
339 return 0;
340 } else if( v->ccgsl_pointer == 0 ){
341 gsl_error( "combination not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
342 return 0;
343 }
344 // Check that position make sense
345 if( position >= static_cast<difference_type>( v->k() ) ){
346 gsl_error( "trying to dereference end()", __FILE__, __LINE__, exception::GSL_EFAILED );
347 return 0;
348 }
349 if( position <= -1 ){
350 gsl_error( "trying to dereference rend()", __FILE__, __LINE__, exception::GSL_EFAILED );
351 return 0;
352 }
353 // position and v are valid: return data
354 return *(v->ccgsl_pointer->data + position);
355 }
356 // // operator[]
363 // Always try to return something
364 static content something = 0;
365 // First check that iterator is initialised.
366 if( v == 0 ){
367 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
368 return something;
369 } else if( v->ccgsl_pointer == 0 ){
370 gsl_error( "combination not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
371 return something;
372 }
373 // Check that position make sense
374 difference_type const p = reverse ? position - n : position + n;
375 if( p >= static_cast<difference_type>( v->k() ) ){
376 gsl_error( "trying to dereference beyond rbegin()", __FILE__, __LINE__, exception::GSL_EFAILED );
377 return something;
378 }
379 if( p <= -1 ){
380 gsl_error( "trying to dereference beyond begin()", __FILE__, __LINE__, exception::GSL_EFAILED );
381 return something;
382 }
383 // p is a valid position
384 return *(v->ccgsl_pointer->data + p );
385 }
386 // // operator-: find distance between two iterators
393 // Warn if either iterator undefined
394 if( v == 0 or i.v == 0 ){
395 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
396 return 0;
397 } else if( v->ccgsl_pointer == 0 or i.v->ccgsl_pointer == 0 ){
398 gsl_error( "combination not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
399 return 0;
400 }
401 // Warn if iterators do not point to same combination
402 if( v->ccgsl_pointer != i.v->ccgsl_pointer ){
403 gsl_error( "trying to take difference of iterators for different combinations", __FILE__, __LINE__,
405 return 0;
406 }
407 return reverse ? i.position - position : position - i.position;
408 }
409 // // operator!=
410 // // operator<
417 return this->v == i.v and this->position == i.position;
418 }
425 return not this->operator==( i );
426 }
435 // Warn if either iterator undefined
436 if( v == 0 or i.v == 0 ){
437 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
438 return false;
439 }
440 // Warn if iterators do not point to same combination
441 if( v->ccgsl_pointer != i.v->ccgsl_pointer ){
442 gsl_error( "trying to take difference of iterators for different combinations", __FILE__, __LINE__,
444 return false;
445 }
446 return reverse ? i.position < position : position < i.position;
447 }
448 protected:
453 void increment(){
454 // Only makes sense if v points to a combination
455 if( v == 0 ){
456 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
457 return;
458 } else if( v->ccgsl_pointer == 0 ){
459 gsl_error( "combination not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
460 return;
461 }
462 // increment position and check against size
463 if( reverse ){ if( position >= 0 ) --position; }
464 else { if( position < static_cast<difference_type>( v->k() ) ) ++position; }
465 }
470 void decrement(){
471 // Only makes sense if v points to a combination
472 if( v == 0 ){
473 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
474 return;
475 } else if( v->ccgsl_pointer == 0 ){
476 gsl_error( "combination not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
477 return;
478 }
479 // decrement position and check against size
480 if( reverse ){ if( position < static_cast<difference_type>( v->k() ) ) ++position; }
481 else { if( position >= 0 ) --position; }
482 }
487 void shift( difference_type const n ){
488 // Warn if iterator undefined
489 if( v == 0 ){
490 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
491 return;
492 } else if( v->ccgsl_pointer == 0 ){
493 gsl_error( "combination not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
494 return;
495 }
496 position += reverse ? -n : n;
497 }
501 iterator_base(){ v = 0; }
508 : v( v ), position( position ){}
512 container* v;
517 };
521 template<bool reverse> class const_iterator_t
522 : public iterator_base<combination const,unsigned long,reverse>{
523 public:
524 // // Refines output iterator
525 // // operator=
533 return *this;
534 }
535 // // Refines forward iterator
536 // // operator++ (both)
543 return *this;
544 }
550 // return value
553 return result;
554 }
555 // // Refines bidirectional iterator
556 // // operator-- (both)
563 return *this;
564 }
570 // return value
573 return result;
574 }
580 // // operator+=
587 this->shift( n );
588 return *this;
589 }
590 // // operator-=
597 this->shift( -n );
598 return *this;
599 }
600 // // operator+ (n+i)(i+n)
609 result += n;
610 return result;
611 }
612 // // operator- (n-i)(i-n)(i-j)
621 result -= n;
622 return result;
623 }
631 }
635 const_iterator_t() : iterator_base<combination,unsigned long,reverse>(){}
643 }
649 bool operator==( const_iterator_t<reverse> const& i ) const {
650 return this->v == i.v and this->position == i.position;
651 }
657 bool operator!=( const_iterator_t<reverse> const& i ) const {
658 return not this->operator==( i );
659 }
665 bool operator<( const_iterator_t<reverse> const& i ) const {
666 // Warn if either iterator undefined
667 if( this->v == 0 or i.v == 0 ){
668 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
669 return false;
670 }
671 // Warn if iterators do not point to same combination
672 if( this->v->ccgsl_pointer != i.v->ccgsl_pointer ){
673 gsl_error( "trying to take difference of iterators for different combinations", __FILE__, __LINE__,
675 return false;
676 }
677 return reverse ? i.position < this->position : this->position < i.position;
678 }
679 protected:
680 // We need a constructor for combination
681 friend class combination;
688 : iterator_base<combination const,unsigned long,reverse>( v, position ){}
689 };
690 public:
699 // type difference_type
704 // type size_type
708 typedef size_t size_type;
709 // begin()
715 return const_iterator( this, 0 );
716 }
717 // end()
723 if( ccgsl_pointer == 0 ) return const_iterator( this, 0 );
724 return const_iterator( this, k() );
725 }
726
727 };
728
729}
730#endif
A class template for the const iterators.
const_iterator_t(const_iterator_t< reverse > const &i)
A copy constructor.
const_iterator_t()
The default constructor.
const_iterator_t< reverse > & operator--()
The prefix – operator.
const_iterator_t< reverse > operator++(int)
The postfix ++ operator.
bool operator<(const_iterator_t< reverse > const &i) const
Comparison with const_iterator.
difference_type operator-(const_iterator_t< reverse > const &i) const
The - operator: find distance between two iterators.
const_iterator_t< reverse > operator-(difference_type const n) const
The - operator: subtract distance from iterator.
const_iterator_t< reverse > & operator=(const_iterator_t< reverse > const &i)
We can assign one output iterator from another.
const_iterator_t< reverse > & operator-=(difference_type const n)
The -= operator.
bool operator!=(const_iterator_t< reverse > const &i) const
Comparison with const_iterator.
const_iterator_t< reverse > & operator++()
The prefix ++ operator.
const_iterator_t< reverse > operator+(difference_type const n) const
The + operator.
const_iterator_t< reverse > & operator+=(difference_type const n)
The += operator.
iterator_base< combinationconst, unsignedlong, reverse >::difference_type difference_type
Difference type.
const_iterator_t< reverse > operator--(int)
The postfix – operator.
const_iterator_t(combination const *v, difference_type position)
This constructor allows combination to create non-default iterators.
bool operator==(const_iterator_t< reverse > const &i) const
Comparison with const_iterator.
The container must have iterator types.
void shift(difference_type const n)
Shift iterator n places.
reference operator[](difference_type const n) const
Get element at i + n by reference ([] operator).
void decrement()
Decrement the iterator.
difference_type position
Mark position of iterator within combination.
container * v
Store a pointer to a combination we can iterate over: 0 if no combination.
bool operator==(iterator_base< container, content, reverse > const &i) const
The == operator.
void increment()
Increment the iterator.
ptrdiff_t difference_type
An iterator must have a difference_type.
bool operator!=(iterator_base< container, content, reverse > const &i) const
The != operator.
reference operator*() const
Dereference the pointer.
value_type * pointer
An iterator must have a pointer typea.
pointer operator->() const
Dereference the pointer.
difference_type operator-(iterator_base< container, content, reverse > const &i) const
The - operator: find distance between two iterators.
iterator_base(container *v, difference_type position)
This constructor allows combination to create non-default iterators.
size_t value_type
An iterator must have a value type.
iterator_base()
The iterator is default constructible.
value_type & reference
An iterator must have a reference type.
std::random_access_iterator_tag iterator_category
An iterator must have an iterator category.
bool operator<(iterator_base< container, content, reverse > const &i) const
The < operator is used to compare iterators.
This class handles GSL combination objects.
Definition: combination.hpp:33
const_iterator_t< false > const_iterator
The const_iterator type.
combination(combination const &v)
The copy constructor.
Definition: combination.hpp:75
int next()
C++ version of gsl_combination_next().
combination & operator=(combination const &v)
The assignment operator.
Definition: combination.hpp:83
int prev()
C++ version of gsl_combination_prev().
size_t get(size_t const i) const
C++ version of gsl_combination_get().
gsl_combination const * get() const
Get the gsl_combination.
~combination()
The destructor only deletes the pointers if count reaches zero.
const_iterator_t< true > const_reverse_iterator
The const_reverse_iterator type.
void init_first()
C++ version of gsl_combination_init_first().
bool unique() const
Find if this is the only object sharing the gsl_combination.
int memcpy(combination const &src)
C++ version of gsl_combination_memcpy().
combination(combination &&v)
Move constructor.
combination(gsl_combination *v)
Could construct from a gsl_combination.
Definition: combination.hpp:64
size_t n() const
C++ version of gsl_combination_n(): Size of set.
combination & operator=(combination &&v)
Move operator.
combination()
The default constructor is only really useful for assigning to.
Definition: combination.hpp:38
int fprintf(FILE *stream, char const *format) const
C++ version of gsl_combination_fprintf().
int valid()
C++ version of gsl_combination_valid().
const_iterator end() const
Get iterator pointing beyond last combination element.
size_t * count
The shared reference count.
gsl_combination * get()
Get the gsl_combination.
void init_last()
C++ version of gsl_combination_init_last().
combination clone() const
The clone function.
size_t k() const
C++ version of gsl_combination_k(): Number of selections.
size_t size_type
A container must have a size_type.
const_iterator begin() const
Get iterator pointing to first combination element.
int fwrite(FILE *stream) const
C++ version of gsl_combination_fwrite().
const_iterator::difference_type difference_type
A container must have a difference_type.
int fread(FILE *stream)
C++ version of gsl_combination_fread().
static combination calloc(size_t const n, size_t const k)
C++ version of gsl_combination_calloc().
int fscanf(FILE *stream)
C++ version of gsl_combination_fscanf().
size_t use_count() const
Find how many combination objects share this pointer.
size_t * data()
C++ version of gsl_combination_data().
size_t operator[](size_t const i) const
C++ version of gsl_combination_get().
gsl_combination * ccgsl_pointer
The shared pointer.
combination(size_t const n, size_t const k, bool init=false)
This constructor creates a new combination with n elements from which k are chosen.
Definition: combination.hpp:48
@ GSL_EFAILED
generic failure
Definition: exception.hpp:476
@ GSL_EFAULT
invalid pointer
Definition: exception.hpp:474
int init(series &cs, function_scl const &func, double const a, double const b)
C++ version of gsl_cheb_init().
Definition: chebyshev.hpp:262
gsl_sf_result result
Typedef for gsl_sf_result.
Definition: sf_result.hpp:30
The gsl package creates an interface to the GNU Scientific Library for C++.
Definition: blas.hpp:34