ccgsl 2.7.2
C++wrappersforGnuScientificLibrary
permutation.hpp
Go to the documentation of this file.
1/*
2 * $Id: permutation.hpp 315 2014-02-22 14:31:35Z jdl3 $
3 * Copyright (C) 2010, 2011, 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_PERMUTATION_HPP
21#define CCGSL_PERMUTATION_HPP
22
23#include<cstddef>
24#include<new>
25#include<algorithm>
26#include<gsl/gsl_permutation.h>
27#include"exception.hpp"
28
29namespace gsl {
34 public:
39 ccgsl_pointer = 0;
40 count = 0; // initially nullptr will do
41 }
47 explicit permutation( size_t const n, bool init = false ){
48 ccgsl_pointer = gsl_permutation_alloc( n );
49 // just plausibly we could allocate permutation but not count
50 try { count = new size_t; } catch( std::bad_alloc& e ){
51 // try to tidy up before rethrowing
52 gsl_permutation_free( ccgsl_pointer );
53 throw e;
54 }
55 *count = 1; // initially there is just one reference to ccgsl_pointer
56 if( init ) this->init();
57 }
63 explicit permutation( gsl_permutation* v ){
64 ccgsl_pointer = v;
65 // just plausibly we could fail to allocate count: no further action needed.
66 count = new size_t;
67 *count = 1; // initially there is just one reference to ccgsl_pointer
68 }
69 // copy constructor
75 if( count != 0 ) ++*count; // permutation is now shared.
76 }
77 // assignment operator
83 // first, possibly delete anything pointed to by this
84 if( count == 0 or --*count == 0 ){
85 if( ccgsl_pointer != 0 ) gsl_permutation_free( ccgsl_pointer );
86 delete count;
87 }
88 // Then copy
90 count = v.count;
91 if( count != 0 ) ++*count; // permutation is now shared.
92 return *this;
93 }
94 // clone()
101 permutation copy( get()->size );
102 // Now copy
103 gsl_permutation_memcpy( copy.get(), get() );
104 // return new object
105 return copy;
106 }
107 // destructor
112 if( count == 0 or --*count == 0 ){
113 // could have allocated null pointer
114 if( ccgsl_pointer != 0 ) gsl_permutation_free( ccgsl_pointer );
115 delete count;
116 }
117 }
118#ifdef __GXX_EXPERIMENTAL_CXX0X__
124 std::swap( count, v.count );
125 v.ccgsl_pointer = nullptr;
126 }
133 std::swap( ccgsl_pointer, v.ccgsl_pointer );
134 std::swap( count, v.count );
135 return *this;
136 }
137#endif
138 private:
142 gsl_permutation* ccgsl_pointer;
146 size_t* count;
147 public:
148 // shared reference functions
153 gsl_permutation* get(){ return ccgsl_pointer; }
158 gsl_permutation const* get() const { return ccgsl_pointer; }
164 bool unique() const { return count != 0 and *count == 1; }
169 size_t use_count() const { return count == 0 ? 0 : *count; }
175#ifdef __GXX_EXPERIMENTAL_CXX0X__
176 explicit
177#endif
178 operator bool() const { return ccgsl_pointer != 0; }
179 public:
180 // GSL functions
186 static permutation calloc( size_t const n ){ return permutation( gsl_permutation_calloc( n ) ); }
190 void init(){ gsl_permutation_init( get() ); }
196 int memcpy( permutation const& src ){ return gsl_permutation_memcpy( get(), src.get() ); }
202 int fread( FILE* stream ){ return gsl_permutation_fread( stream, get() ); }
208 int fwrite( FILE* stream ) const { return gsl_permutation_fwrite( stream, get() ); }
214 int fscanf( FILE* stream ){ return gsl_permutation_fscanf( stream, get() ); }
221 int fprintf( FILE* stream, char const* format ) const {
222 return gsl_permutation_fprintf( stream, get(), format ); }
227 size_t size() const { return gsl_permutation_size( get() ); }
232 size_t* data() const { return gsl_permutation_data( get() ); }
239 int swap( size_t const i, size_t const j ){ return gsl_permutation_swap( get(), i, j ); }
244 int valid() const { return gsl_permutation_valid( get() ); }
248 void reverse(){ gsl_permutation_reverse( get() ); }
254 int inverse( permutation const& p ){ return gsl_permutation_inverse( get(), p.get() ); }
259 int next(){ return gsl_permutation_next( get() ); }
264 int prev(){ return gsl_permutation_prev( get() ); }
271 int mul( permutation const& pa, permutation const& pb ){
272 return gsl_permutation_mul( get(), pa.get(), pb.get() ); }
273
280 return gsl_permutation_linear_to_canonical( get(), p.get() ); }
287 return gsl_permutation_canonical_to_linear( get(), q.get() ); }
292 size_t inversions() const { return gsl_permutation_inversions( get() ); }
297 size_t linear_cycles() const { return gsl_permutation_linear_cycles( get() ); }
302 size_t canonical_cycles( ) const { return gsl_permutation_canonical_cycles( get() ); }
308 size_t get( size_t const i ) const { return gsl_permutation_get( get(), i ); }
314 size_t operator[]( size_t const i ) const { return gsl_permutation_get( get(), i ); }
315 private:
320 template<typename container, typename content, bool reverse> class iterator_base {
321 friend class permutation;
322 public:
326 typedef std::random_access_iterator_tag iterator_category;
330 typedef size_t value_type;
339 // // type iterator_traits<permutation>::difference_type
343 typedef ptrdiff_t difference_type;
344 public:
345 // // operator*
351 // Always try to return something
352 static content something = 0;
353 // First check that iterator is initialised.
354 if( v == 0 ){
355 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAULT );
356 return something;
357 } else if( v->ccgsl_pointer == 0 ){
358 gsl_error( "permutation not initialised", __FILE__, __LINE__, exception::GSL_EFAULT );
359 return something;
360 }
361 // Check that position make sense
362 if( position >= static_cast<difference_type>( v->size() ) ){
363 gsl_error( "trying to dereference beyond rbegin()", __FILE__, __LINE__, exception::GSL_EFAILED );
364 return something;
365 }
366 if( position <= -1 ){
367 gsl_error( "trying to dereference beyond begin()", __FILE__, __LINE__, exception::GSL_EFAILED );
368 return something;
369 }
370 // position and v are valid: return data
371 return *(v->ccgsl_pointer->data + position);
372 }
373 // // operator->
379 // First check that iterator is initialised.
380 if( v == 0 ){
381 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
382 return 0;
383 } else if( v->ccgsl_pointer == 0 ){
384 gsl_error( "permutation not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
385 return 0;
386 }
387 // Check that position make sense
388 if( position >= static_cast<difference_type>( v->size() ) ){
389 gsl_error( "trying to dereference end()", __FILE__, __LINE__, exception::GSL_EFAILED );
390 return 0;
391 }
392 if( position <= -1 ){
393 gsl_error( "trying to dereference rend()", __FILE__, __LINE__, exception::GSL_EFAILED );
394 return 0;
395 }
396 // position and v are valid: return data
397 return *(v->ccgsl_pointer->data + position);
398 }
399 // // operator[]
406 // Always try to return something
407 static content something = 0;
408 // First check that iterator is initialised.
409 if( v == 0 ){
410 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
411 return something;
412 } else if( v->ccgsl_pointer == 0 ){
413 gsl_error( "permutation not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
414 return something;
415 }
416 // Check that position make sense
417 difference_type const p = reverse ? position - n : position + n;
418 if( p >= static_cast<difference_type>( v->size() ) ){
419 gsl_error( "trying to dereference beyond rbegin()", __FILE__, __LINE__, exception::GSL_EFAILED );
420 return something;
421 }
422 if( p <= -1 ){
423 gsl_error( "trying to dereference beyond begin()", __FILE__, __LINE__, exception::GSL_EFAILED );
424 return something;
425 }
426 // p is a valid position
427 return *(v->ccgsl_pointer->data + p );
428 }
429 // // operator-: find distance between two iterators
436 // Warn if either iterator undefined
437 if( v == 0 or i.v == 0 ){
438 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
439 return 0;
440 } else if( v->ccgsl_pointer == 0 or i.v->ccgsl_pointer == 0 ){
441 gsl_error( "permutation not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
442 return 0;
443 }
444 // Warn if iterators do not point to same permutation
445 if( v->ccgsl_pointer != i.v->ccgsl_pointer ){
446 gsl_error( "trying to take difference of iterators for different permutations", __FILE__, __LINE__,
448 return 0;
449 }
450 return reverse ? i.position - position : position - i.position;
451 }
452 // // operator!=
453 // // operator<
460 return this->v == i.v and this->position == i.position;
461 }
468 return not this->operator==( i );
469 }
478 // Warn if either iterator undefined
479 if( v == 0 or i.v == 0 ){
480 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
481 return false;
482 }
483 // Warn if iterators do not point to same permutation
484 if( v->ccgsl_pointer != i.v->ccgsl_pointer ){
485 gsl_error( "trying to take difference of iterators for different permutations", __FILE__, __LINE__,
487 return false;
488 }
489 return reverse ? i.position < position : position < i.position;
490 }
491 protected:
496 void increment(){
497 // Only makes sense if v points to a permutation
498 if( v == 0 ){
499 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
500 return;
501 } else if( v->ccgsl_pointer == 0 ){
502 gsl_error( "permutation not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
503 return;
504 }
505 // increment position and check against size
506 if( reverse ){ if( position >= 0 ) --position; }
507 else { if( position < static_cast<difference_type>( v->size() ) ) ++position; }
508 }
513 void decrement(){
514 // Only makes sense if v points to a permutation
515 if( v == 0 ){
516 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
517 return;
518 } else if( v->ccgsl_pointer == 0 ){
519 gsl_error( "permutation not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
520 return;
521 }
522 // decrement position and check against size
523 if( reverse ){ if( position < static_cast<difference_type>( v->size() ) ) ++position; }
524 else { if( position >= 0 ) --position; }
525 }
530 void shift( difference_type const n ){
531 // Warn if iterator undefined
532 if( v == 0 ){
533 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
534 return;
535 } else if( v->ccgsl_pointer == 0 ){
536 gsl_error( "permutation not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
537 return;
538 }
539 position += reverse ? -n : n;
540 }
544 iterator_base(){ v = 0; }
551 : v( v ), position( position ){}
555 container* v;
560 };
564 template<bool reverse> class const_iterator_t
565 : public iterator_base<permutation const,unsigned long,reverse>{
566 public:
567 // // Refines output iterator
568 // // operator=
576 return *this;
577 }
578 // // Refines forward iterator
579 // // operator++ (both)
586 return *this;
587 }
593 // return value
596 return result;
597 }
598 // // Refines bidirectional iterator
599 // // operator-- (both)
606 return *this;
607 }
613 // return value
616 return result;
617 }
623 // // operator+=
630 this->shift( n );
631 return *this;
632 }
633 // // operator-=
640 this->shift( -n );
641 return *this;
642 }
643 // // operator+ (n+i)(i+n)
652 result += n;
653 return result;
654 }
655 // // operator- (n-i)(i-n)(i-j)
664 result -= n;
665 return result;
666 }
674 }
686 }
692 bool operator==( const_iterator_t<reverse> const& i ) const {
693 return this->v == i.v and this->position == i.position;
694 }
700 bool operator!=( const_iterator_t<reverse> const& i ) const {
701 return not this->operator==( i );
702 }
708 bool operator<( const_iterator_t<reverse> const& i ) const {
709 // Warn if either iterator undefined
710 if( this->v == 0 or i.v == 0 ){
711 gsl_error( "iterator not initialised", __FILE__, __LINE__, exception::GSL_EFAILED );
712 return false;
713 }
714 // Warn if iterators do not point to same permutation
715 if( this->v->ccgsl_pointer != i.v->ccgsl_pointer ){
716 gsl_error( "trying to take difference of iterators for different permutations", __FILE__, __LINE__,
718 return false;
719 }
720 return reverse ? i.position < this->position : this->position < i.position;
721 }
722 protected:
723 // We need a constructor for permutation
724 friend class permutation;
731 : iterator_base<permutation const,unsigned long,reverse>( v, position ){}
732 };
733 public:
742 // type difference_type
747 // type size_type
751 typedef size_t size_type;
752 // begin()
758 return const_iterator( this, 0 );
759 }
760 // end()
766 if( ccgsl_pointer == 0 ) return const_iterator( this, 0 );
767 return const_iterator( this, size() );
768 }
769 };
770
771}
772#endif
@ GSL_EFAILED
generic failure
Definition: exception.hpp:476
@ GSL_EFAULT
invalid pointer
Definition: exception.hpp:474
A class template for the const iterators.
const_iterator_t< reverse > operator++(int)
The postfix ++ operator.
const_iterator_t< reverse > & operator=(const_iterator_t< reverse > const &i)
We can assign one output iterator from another.
bool operator==(const_iterator_t< reverse > const &i) const
Comparison with const_iterator.
bool operator<(const_iterator_t< reverse > const &i) const
Comparison with const_iterator.
const_iterator_t(permutation const *v, difference_type position)
This constructor allows permutation to create non-default iterators.
const_iterator_t< reverse > & operator++()
The prefix ++ operator.
bool operator!=(const_iterator_t< reverse > const &i) const
Comparison with const_iterator.
const_iterator_t< reverse > & operator-=(difference_type const n)
The -= operator.
const_iterator_t()
The default constructor.
const_iterator_t< reverse > & operator+=(difference_type const n)
The += operator.
const_iterator_t< reverse > operator--(int)
The postfix – operator.
const_iterator_t< reverse > & operator--()
The prefix – operator.
const_iterator_t< reverse > operator+(difference_type const n) const
The + operator.
const_iterator_t(const_iterator_t< reverse > const &i)
A copy constructor.
iterator_base< permutationconst, unsignedlong, reverse >::difference_type difference_type
Difference type.
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.
The container must have iterator types.
bool operator==(iterator_base< container, content, reverse > const &i) const
The == operator.
container * v
Store a pointer to a permutation we can iterate over: 0 if no permutation.
std::random_access_iterator_tag iterator_category
An iterator must have an iterator category.
reference operator[](difference_type const n) const
Get element at i + n by reference ([] operator).
iterator_base()
The iterator is default constructible.
difference_type operator-(iterator_base< container, content, reverse > const &i) const
The - operator: find distance between two iterators.
ptrdiff_t difference_type
An iterator must have a difference_type.
size_t value_type
An iterator must have a value type.
value_type & reference
An iterator must have a reference type.
value_type * pointer
An iterator must have a pointer typea.
pointer operator->() const
Dereference the pointer.
void increment()
Increment the iterator.
void decrement()
Decrement the iterator.
bool operator!=(iterator_base< container, content, reverse > const &i) const
The != operator.
bool operator<(iterator_base< container, content, reverse > const &i) const
The < operator is used to compare iterators.
iterator_base(container *v, difference_type position)
This constructor allows permutation to create non-default iterators.
void shift(difference_type const n)
Shift iterator n places.
difference_type position
Mark position of iterator within permutation.
reference operator*() const
Dereference the pointer.
This class handles GSL permutation objects.
Definition: permutation.hpp:33
~permutation()
The destructor only deletes the pointers if count reaches zero.
int fread(FILE *stream)
C++ version of gsl_permutation_fread().
void reverse()
C++ version of gsl_permutation_reverse().
int valid() const
C++ version of gsl_permutation_valid().
int linear_to_canonical(permutation const &p)
C++ version of gsl_permutation_linear_to_canonical().
size_t canonical_cycles() const
C++ version of gsl_permutation_canonical_cycles().
size_t * count
The shared reference count.
size_t operator[](size_t const i) const
C++ version of gsl_permutation_get().
permutation & operator=(permutation const &v)
The assignment operator.
Definition: permutation.hpp:82
size_t get(size_t const i) const
C++ version of gsl_permutation_get().
permutation & operator=(permutation &&v)
Move operator.
const_iterator_t< true > const_reverse_iterator
The const_reverse_iterator type.
gsl_permutation const * get() const
Get the gsl_permutation.
size_t use_count() const
Find how many permutation objects share this pointer.
int fscanf(FILE *stream)
C++ version of gsl_permutation_fscanf().
size_t * data() const
C++ version of gsl_permutation_data().
size_t size_type
A container must have a size_type.
size_t inversions() const
C++ version of gsl_permutation_inversions().
int fwrite(FILE *stream) const
C++ version of gsl_permutation_fwrite().
int memcpy(permutation const &src)
C++ version of gsl_permutation_memcpy().
int inverse(permutation const &p)
C++ version of gsl_permutation_inverse().
size_t size() const
C++ version of gsl_permutation_size().
int mul(permutation const &pa, permutation const &pb)
C++ version of gsl_permutation_mul().
bool unique() const
Find if this is the only object sharing the gsl_permutation.
const_iterator end() const
Get iterator pointing beyond last permutation element.
gsl_permutation * get()
Get the gsl_permutation.
const_iterator_t< false > const_iterator
The const_iterator type.
static permutation calloc(size_t const n)
C++ version of gsl_permutation_calloc().
void init()
C++ version of gsl_permutation_init().
int prev()
C++ version of gsl_permutation_prev().
permutation(permutation const &v)
The copy constructor.
Definition: permutation.hpp:74
const_iterator::difference_type difference_type
A container must have a difference_type.
int fprintf(FILE *stream, char const *format) const
C++ version of gsl_permutation_fprintf().
int canonical_to_linear(permutation const &q)
C++ version of gsl_permutation_canonical_to_linear().
int next()
C++ version of gsl_permutation_next().
permutation(size_t const n, bool init=false)
This constructor creates a new permutation with n elements.
Definition: permutation.hpp:47
permutation(permutation &&v)
Move constructor.
permutation()
The default constructor is only really useful for assigning to.
Definition: permutation.hpp:38
gsl_permutation * ccgsl_pointer
The shared pointer.
size_t linear_cycles() const
C++ version of gsl_permutation_linear_cycles().
const_iterator begin() const
Get iterator pointing to first permutation element.
permutation clone() const
The clone function.
int swap(size_t const i, size_t const j)
C++ version of gsl_permutation_swap().
permutation(gsl_permutation *v)
Could construct from a gsl_permutation.
Definition: permutation.hpp:63
size_t n(workspace const &w)
C++ version of gsl_rstat_n().
Definition: rstat.hpp:299
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