diff --git a/doc/big_whole.html b/doc/big_whole.html new file mode 100644 index 000000000..7321cb9f0 --- /dev/null +++ b/doc/big_whole.html @@ -0,0 +1,434 @@ + + + +Boost Arbitrary-length Whole-number Library + + +

c++boost.gif (8819 bytes)Arbitrary-length Whole-number Library

+ +

The headers boost/math/big_whole_core.hpp and boost/math/big_whole.hpp cover the definition of and operations for unlimited-length nonnegative integers (only memory constraints should limit the numbers supported).

+ +

Contents

+ +
    +
  1. Contents
  2. +
  3. Rationale
  4. +
  5. Core Definition and Routines +
  6. +
  7. Additional Routines +
  8. +
  9. References
  10. +
  11. Credits +
  12. +
+ +

Rationale

+ +

Various "bignum" classes provide objects that model numbers beyond the limits of the built-in numeric types. The class provided in this library gives a portable implementation of nonnegative integers (also known as "whole" numbers). The implementation tries to lean towards good performance, but it's probably not as good as the various highly-refined "bignum" types available.

+ +

Core Definition and Routines

+ +

The boost/math/big_whole_core.hpp header contains the declaration for the unlimited-length nonnegative integer type and declarations for various core routines.

+ +

Header Synopsis

+ +
+#include <limits>  // for std::numeric_limits
+
+namespace boost
+{
+namespace math
+{
+
+class big_whole;
+
+void  swap( big_whole &a, big_whole &b );
+
+big_whole  operator !( big_whole const &w );
+
+}
+}
+
+namespace std
+{
+
+template < >  class numeric_limits< boost::math::big_whole >;
+
+}
+
+ +

Unlimited-Length Nonnegative Integer Type

+ +

Objects from the boost::math::big_whole class represent unlimited-length nonnegative integers. Even though the implemenation is advanced, objects from this type can be passed around like any other value-based type. The usual mathematical functions and operators are provided. These objects have a binary (i.e. radix-2) representation, so various bit-twiddling functions and operators are also provided.

+ +
+#include <boost/cstdint.hpp>  // for boost::uintmax_t
+#include <cstddef>            // for std::size_t
+#include <valarray>           // for std::valarray
+
+class boost::math::big_whole
+{
+public:
+    // Lifetime management
+    big_whole();
+    big_whole( big_whole const &other );
+
+    big_whole( boost::uintmax_t v );
+
+    explicit  big_whole( std::valarray<bool> const &b );
+    explicit  big_whole( std::valarray<std::size_t> const &i );
+
+    // Object-mutating operations
+    void  swap( big_whole &other );
+
+    void  assign( big_whole const &other );
+    void  assign( boost::uintmax_t v );
+
+    void  reconfigure( std::valarray<bool> const &b );
+    void  reconfigure( std::valarray<std::size_t> const &i );
+
+    // Value-accessing operations
+    uintmax_t                   to_uintmax() const;
+    std::valarray<bool>         to_bit_vector() const;
+    std::valarray<std::size_t>  to_bit_indices() const;
+
+    // Bit-twiddling operations
+    void  reset();
+    void  reset( std::size_t from, std::size_t to );
+    void  reset( std::size_t i );
+
+    void  set( std::size_t from, std::size_t to );
+    void  set( std::size_t i );
+
+    void  flip( std::size_t from, std::size_t to );
+    void  flip( std::size_t i );
+
+    void  bit_assign( std::size_t from, std::size_t to, bool value );
+    void  bit_assign( std::size_t i, bool value );
+
+    // Bit-inspecting operations
+    std::size_t  length() const;
+
+    std::size_t  count() const;
+    bool         any() const;
+    bool         none() const;
+
+    bool       test( std::size_t i ) const;
+    big_whole  tests( std::size_t from, std::size_t to ) const;
+
+    big_whole  reverse( std::size_t cap ) const;
+    big_whole  reverse() const;
+
+    // Self-operator mutators
+    void  not_self();
+
+    // Operators
+    big_whole &  operator =( big_whole const &rhs );
+
+    operator bool_type() const;
+
+};
+
+ +

Constructors

+ +

Note: the automatically-defined destructor is used.

+ +
+
big_whole(); +
+ Effects: sets the internal state such that the stored numerical value is zero (using a minimal amount of memory)
+ Rationale: standard default-state creation + +
big_whole( big_whole &other ); +
+ Effects: sets the internal state such that the stored numerical value is the same as the numerical value stored in other
+ Rationale: standard creation via copying + +
big_whole( boost::uintmax_t v ); +
+ Effects: sets the internal state such that the stored numerical value is the same as v
+ Rationale: creation via conversion + +
explicit big_whole( std::valarray<bool> const &b ); +
+ Effects: sets the internal state such that the stored numerical value has the same bit pattern as b
+ Rationale: creation via bit-pattern + +
explicit big_whole( std::valarray<std::size_t> const &i ); +
+ Effects: sets the internal state such that the stored numerical value has its set bits at the positions given by i
+ Rationale: creation via set-bit-location specification +
+ +

Observer Member Functions

+ +
+
boost::uintmax_t to_uintmax() const; +
+ Returns: the numeric value stored in *this, reduced modulo 2std::numeric_limits< boost::uintmax_t >::digits
+ Rationale: explicit reverse conversion + +
std::valarray<bool> to_bit_vector() const; +
+ Returns: the bit pattern for the numeric value stored in *this
+ Rationale: break down to a bit pattern + +
std::valarray<std::size_t> to_bit_indices() const; +
+ Returns: the places of the set bits for the numeric value stored in *this
+ Rationale: break down to a set-bit index list + +
std::size_t length() const; +
+ Returns: the smallest nonnegative integer, n, such that 2n is greater than the numeric value stored in *this (returns 0 if *this represents zero)
+ Note: same as this->to_bit_vector().size() or (for nonzero length) 1 + this->to_bit_indices().max(), but is probably implemented more efficiently
+ Rationale: size of bit-pattern vector + +
std::size_t count() const; +
+ Returns: the number of set bits in the numeric value stored in *this
+ Note: same as this->to_bit_indices().size(), but is probably implemented more efficiently
+ Rationale: size of set-bit index list + +
bool any() const; +
+ Returns: whether any bits in the numeric value stored in *this are set
+ Note: same as this->count() > 0, but is probably implemented more efficiently
+ Rationale: reversed zero test + +
bool none() const; +
+ Returns: whether no bits in the numeric value stored in *this are set
+ Note: same as !this->any()
+ Rationale: zero test + +
bool test( std::size_t i ) const; +
+ Returns: whether the bit corresponding to the 2i place for the numeric value stored in *this is set
+ Rationale: inspect a specific bit + +
big_whole tests( std::size_t from, std::size_t to ) const; +
+ Precondition: from <= to
+ Returns: states of the bits corresponding between the 2from and 2to places (inclusive) for the numeric value stored in *this; equivalent to (*this % 2to + 1) / 2from
+ Rationale: inspect a set of bits at once + +
big_whole reverse( std::size_t cap ) const; +
+ Returns: a copy of the lowest cap + 1 bits (i.e. apply a modulo 2cap + 1) of *this in reverse order (e.g. for n ranging from 0 to cap, the bit in the 2n place now appears in the 2cap - n place)
+ Rationale: generate bit-pattern palidromes + +
big_whole reverse() const; +
+ Returns: 0 if *this represents zero; otherwise, this->reverse( this->length() - 1 )
+ Rationale: shorthand for the most common case of bit-order reversal (minimal amount for all significant bits) +
+ +

Mutating Member Functions

+ +
+
void swap( big_whole &other ); +
+ Effects: *this takes ownership of other's state; other takes ownership of the state *this had before this member function call
+ Rationale: standard class-type-specific swap member-function refinement + +
void assign( big_whole const &other ); +
+ Effects: sets the internal state to a copy of other's state
+ Postconditions: *this == other
+ Rationale: member-function repackaging of copy operation + +
void assign( uintmax_t v ); +
+ Effects: sets the internal state to give a numeric value equivalent to v
+ Postconditions: *this == big_whole( v )
+ Rationale: converting copy operation + +
void reconfigure( std::valarray<bool> const &b ); +
+ Effects: sets the internal state to give a numeric value that has the bit pattern given by b
+ Postconditions: *this == big_whole( b )
+ Rationale: re-configuring copy operation with a bit pattern + +
void reconfigure( std::valarray<std::size_t> const &i ); +
+ Effects: sets the internal state to give a numeric value that has only the bit positions given by i set
+ Postconditions: *this == big_whole( i )
+ Rationale: re-configuring copy operation with a list of the set bits + +
void reset();
+ void reset( std::size_t from, std::size_t to );
+ void reset( std::size_t i ); +
+ Effects: changes the internal state so some set of the bits of the represented value become zero; the zero-argument version affects all bits, the two-argument version affects the bits between the 2from and 2to places (inclusive), the one-argument version affects the bit at the 2i place
+ Rationale: specific-bit(s) assignment, unsetting + +
void set( std::size_t from, std::size_t to );
+ void set( std::size_t i ); +
+ Effects: changes the internal state so some set of the bits of the represented value become one; the two-argument version affects the bits between the 2from and 2to places (inclusive), the one-argument version affects the bit at the 2i place
+ Rationale: specific-bit(s) assignment, setting + +
void flip( std::size_t from, std::size_t to );
+ void flip( std::size_t i ); +
+ Effects: changes the internal state so some set of the bits of the represented value become inverted (zeroes become ones, ones become zeroes); the two-argument version affects the bits between the 2from and 2to places (inclusive), the one-argument version affects the bit at the 2i place
+ Rationale: specific-bit(s) assignment, inverting + +
void bit_assign( std::size_t from, std::size_t to, bool value );
+ void bit_assign( std::size_t i, bool value ); +
+ Effects: changes the internal state so some set of the bits of the represented value become value; the three-argument version affects the bits between the 2from and 2to places (inclusive), the two-argument version affects the bit at the 2i place
+ Rationale: specific-bit(s) assignment, user-defined + +
void not_self(); +
+ Effects: changes the internal state so a value of zero becomes one and any nonzero value becomes zero
+ Rationale: doing x = !x without the copying +
+ +

Operators

+ +
+
big_whole & operator =( big_whole const &rhs ); +
+ Effects: calls this->assign( rhs )
+ Returns: *this
+ Rationale: standard copy-assignment operation + +
operator bool_type() const; +
+ Returns: if this->any(), then some non-zero/non-null/true value, otherwise a zero/null/false value
+ Note: bool_type is an unspecified built-in type that supports Boolean semantics and should have a minimum of common non-Boolean semantics (this probably excludes bool since that type [mistakenly?] fully participates in integral and/or numeric operations)
+ Rationale: Boolean (output) conversion +
+ +

Non-Member Functions & Operators

+ +
+void
+boost::math::swap( boost::math::big_whole &a, boost::math::big_whole &b );
+
+ +

Effects: calls a.swap( b )

+ +

Postconditions: a has the state that b had before the function call; b has the state a had before the function call

+ +

Rationale: exchanges the state of two objects; can use in standard(-like) algorithms with ADL

+ +

Operators

+ +
+
boost::math::big_whole boost::math::operator !( boost::math::big_whole const &w ); +
+ Returns: 1 if w represents zero, 0 otherwise
+ Note: calls big_whole::not_self() +
+ +

Numeric Limits

+ +

A std::numeric_limits< boost::math::big_whole > specialization is provided, with the appropiate entries filled.

+ +

Additional Routines

+ +

The boost/math/big_whole.hpp header includes the core header and contains the declarations for routines that work with unlimited-length nonnegative integers but are not needed for pure computation contexts (like the input and output routines).

+ +

Header Synopsis

+ +
+#include <iosfwd>                         // for std::basic_ostream and std::basic_istream (declarations)
+#include <boost/math/big_whole_core.hpp>  // for boost::math::big_whole
+
+namespace boost
+{
+namespace math
+{
+
+template < typename Ch, class Tr >
+    std::basic_ostream<Ch, Tr> &  operator <<( std::basic_ostream<Ch, Tr> &os, big_whole const &w );
+
+template < typename Ch, class Tr >
+    std::basic_istream<Ch, Tr> &  operator >>( std::basic_istream<Ch, Tr> &is, big_whole &w );
+
+}
+}
+
+ +

Input & Output Operators

+ +
+template < typename Ch, class Tr >
+std::basic_ostream<Ch, Tr> &
+boost::math::operator <<( std::basic_ostream<Ch, Tr> &os, boost::math::big_whole const &w );
+
+ +

Effects: writes characters, forming a string representation of the nonnegative integer w, to os; should use the standard numeric I/O options

+ +

Returns: os

+ +

Rationale: enables big_whole objects to be written by streaming

+ +
+template < typename Ch, class Tr >
+std::basic_istream<Ch, Tr> &
+boost::math::operator >>( std::basic_istream<Ch, Tr> &is, boost::math::big_whole &w );
+
+ +

Effects: reads characters, hopefully forming a string representation of a nonnegative integer, from is, saving any successful result in w; should use the standard numeric I/O options

+ +

Returns: is

+ +

Rationale: enables big_whole objects to be read by streaming

+ +

References

+ + + +

Credits

+ +

Contributors

+ +
+
Daryle Walker +
Started the library. +
+ +

History

+ +
+
30 Jan 2004, Daryle Walker +
Initial version +
+ +
+ +

Revised: 5 Feburary 2004

+ +

Copyright 2004 Daryle Walker. Use, modification, and distribution are subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

+ + diff --git a/include/boost/math/big_whole.hpp b/include/boost/math/big_whole.hpp new file mode 100644 index 000000000..050a1b5b5 --- /dev/null +++ b/include/boost/math/big_whole.hpp @@ -0,0 +1,67 @@ +// Boost math/big_whole.hpp header file ------------------------------------// + +// Copyright 2004 Daryle Walker. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or a copy at .) + +// See for the library's home page. + +#ifndef BOOST_MATH_BIG_WHOLE_HPP +#define BOOST_MATH_BIG_WHOLE_HPP + +#include // self include +#include // for boost::math::big_whole + +#include // for std::basic_istream +#include // for std::basic_ostream + + +namespace boost +{ +namespace math +{ + + +// Class/template/function/operator forward declarations -------------------// + +template < typename Ch, class Tr > + std::basic_ostream & operator <<( std::basic_ostream &os, + big_whole const &w ); + +template < typename Ch, class Tr > + std::basic_istream & operator >>( std::basic_istream &is, + big_whole &w ); + + +// Arbitrary-length whole-number streaming operator definitions ------------// + +template < typename Ch, class Tr > +inline +std::basic_ostream & +operator << +( + std::basic_ostream & os, + big_whole const & w +) +{ + return os; // FILL IN LATER! +} + +template < typename Ch, class Tr > +inline +std::basic_istream & +operator >> +( + std::basic_istream & is, + big_whole & w +) +{ + return is; // FILL IN LATER! +} + + +} // namespace math +} // namespace boost + + +#endif // BOOST_MATH_BIG_WHOLE_HPP diff --git a/include/boost/math/big_whole_core.hpp b/include/boost/math/big_whole_core.hpp new file mode 100644 index 000000000..f6c7700b6 --- /dev/null +++ b/include/boost/math/big_whole_core.hpp @@ -0,0 +1,978 @@ +// Boost math/big_whole_core.hpp header file -------------------------------// + +// Copyright 2004 Daryle Walker. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or a copy at .) + +// See for the library's home page. + +#ifndef BOOST_MATH_BIG_WHOLE_CORE_HPP +#define BOOST_MATH_BIG_WHOLE_CORE_HPP + +#include // self include + +#include // for boost::uintmax_t + +#include // for std::swap, std::min +#include // for NULL, std::size_t +#include // for std::numeric_limits +#include // for std::auto_ptr +#include // for std::valarray, std::slice + + +namespace boost +{ +namespace math +{ + + +// Class/template/function/operator forward declarations -------------------// + +class big_whole; + +void swap( big_whole &a, big_whole &b ); + +big_whole operator !( big_whole const &w ); + + +// Arbitrary-length whole-number object class declaration ------------------// + +class big_whole +{ + typedef big_whole self_type; + + struct dummy { dummy *d; }; + + typedef dummy * dummy::* bool_type; + +public: + // Lifetime management + big_whole(); + big_whole( self_type const &other ); + + big_whole( uintmax_t v ); + + explicit big_whole( std::valarray const &b ); + explicit big_whole( std::valarray const &i ); + + // Object-mutating operations + void swap( self_type &other ); + + void assign( self_type const &other ); + void assign( uintmax_t v ); + + void reconfigure( std::valarray const &b ); + void reconfigure( std::valarray const &i ); + + // Value-accessing operations + uintmax_t to_uintmax() const; + std::valarray to_bit_vector() const; + std::valarray to_bit_indices() const; + + // Bit-twiddling operations + void reset(); + void reset( std::size_t from, std::size_t to ); + void reset( std::size_t i ); + + void set( std::size_t from, std::size_t to ); + void set( std::size_t i ); + + void flip( std::size_t from, std::size_t to ); + void flip( std::size_t i ); + + void bit_assign( std::size_t from, std::size_t to, bool value ); + void bit_assign( std::size_t i, bool value ); + + // Bit-inspecting operations + std::size_t length() const; + + std::size_t count() const; + bool any() const; + bool none() const; + + bool test( std::size_t i ) const; + self_type tests( std::size_t from, std::size_t to ) const; + + self_type reverse( std::size_t cap ) const; + self_type reverse() const; + + // Self-operator mutators + void not_self(); + + // Operators + self_type & operator =( self_type const &rhs ); + + operator bool_type() const; + +protected: + // Member types + typedef unsigned int word_type; + typedef std::valarray va_type; + typedef std::auto_ptr ap_type; + + typedef std::numeric_limits limits_type; + + // Helper functions + static std::size_t words_for_bits( std::size_t bits ); + + static va_type uintmax_to_va( uintmax_t v ); + static va_type bit_vector_to_va( std::valarray const &b ); + static va_type bit_indices_to_va( std::valarray const &i ); + + static std::size_t wlength( va_type const &v ); + static std::size_t blength( word_type w ); + + static word_type count_set_bits_for_word( word_type w ); + +private: + // More member types + enum bit_operation { reset_bit, set_bit, flip_bit }; + + // Object-specific helper functions + void bit_change( std::size_t from, std::size_t to, bit_operation op ); + void bit_change( std::size_t i, bit_operation op ); + + // Member data + ap_type x_; + +}; // boost::math::big_whole + + +// Arbitrary-length whole-number constructor definitions -------------------// + +inline +big_whole::big_whole +( +) + : x_() +{ +} + +inline +big_whole::big_whole +( + big_whole const & other +) + : x_( other.x_.get() ? new va_type(*other.x_) : NULL ) +{ +} + +inline +big_whole::big_whole +( + uintmax_t v +) + : x_( new va_type(self_type::uintmax_to_va( v )) ) +{ +} + +inline +big_whole::big_whole +( + std::valarray const & b +) + : x_( new va_type(self_type::bit_vector_to_va( b )) ) +{ +} + +inline +big_whole::big_whole +( + std::valarray const & i +) + : x_( new va_type(self_type::bit_indices_to_va( i )) ) +{ +} + + +// Arbitrary-length whole-number object-mutating member definitions --------// + +void +big_whole::swap +( + big_whole & other +) +{ + ap_type temp( other.x_.release() ); + + other.x_.reset( this->x_.release() ); + this->x_.reset( temp.release() ); +} + +inline +void +big_whole::assign +( + big_whole const & other +) +{ + this->x_.reset( other.x_.get() ? new va_type(*other.x_) : NULL ); +} + +inline +void +big_whole::assign +( + uintmax_t v +) +{ + self_type temp( v ); + + this->swap( temp ); +} + +inline +void +big_whole::reconfigure +( + std::valarray const & b +) +{ + self_type temp( b ); + + this->swap( temp ); +} + +inline +void +big_whole::reconfigure +( + std::valarray const & i +) +{ + self_type temp( i ); + + this->swap( temp ); +} + + +// Arbitrary-length whole-number value-accessing member definitions --------// + +uintmax_t +big_whole::to_uintmax +( +) const +{ + // NOTE: this test should be optimized during compile-time + + if ( std::numeric_limits::digits > limits_type::digits ) + { + uintmax_t temp = 0; + + if ( va_type const * const v = this->x_.get() ) + { + for ( std::size_t i = v->size() ; i > 0 ; --i ) + { + temp <<= limits_type::digits; + temp |= static_cast( (*v)[i - 1] ); + } + } + + return temp; + } + else + { + return ( this->x_.get() && this->x_->size() ) ? (*this->x_)[ 0 ] : 0; + } +} + +std::valarray +big_whole::to_bit_vector +( +) const +{ + using std::valarray; + + valarray const indices = this->to_bit_indices(); + valarray temp; + + if ( indices.size() ) + { + temp.resize( indices.max() + 1, false ); + temp[ indices ] = true; + } + + return temp; +} + +std::valarray +big_whole::to_bit_indices +( +) const +{ + using std::valarray; + using std::size_t; + + valarray temp; + + if ( va_type const * const v = this->x_.get() ) + { + if ( size_t const s = v->size() ) + { + int const d = limits_type::digits; + valarray temp2( s * d ); + word_type const mask = 1; + size_t bits_used = 0; + + for ( size_t i = 0, ii = 0 ; i < s ; ++i, ii += d ) + { + for ( int j = 0, jj = ii ; j < d ; ++j, ++jj ) + { + if ( (mask << j) & (*v)[i] ) + { + temp2[ bits_used++ ] = jj; + } + } + } + + if ( bits_used ) + { + temp.resize( bits_used ); + temp = temp2[ std::slice(0, bits_used, 1) ]; + } + } + } + + return temp; +} + + +// Arbitrary-length whole-number bit-twiddling member definitions ----------// + +inline +void +big_whole::reset +( +) +{ + this->x_.reset(); +} + +inline +void +big_whole::reset +( + std::size_t from, + std::size_t to +) +{ + this->bit_change( from, to, reset_bit ); +} + +inline +void +big_whole::reset +( + std::size_t i +) +{ + this->bit_change( i, reset_bit ); +} + +inline +void +big_whole::set +( + std::size_t from, + std::size_t to +) +{ + this->bit_change( from, to, set_bit ); +} + +inline +void +big_whole::set +( + std::size_t i +) +{ + this->bit_change( i, set_bit ); +} + +inline +void +big_whole::flip +( + std::size_t from, + std::size_t to +) +{ + this->bit_change( from, to, flip_bit ); +} + +inline +void +big_whole::flip +( + std::size_t i +) +{ + this->bit_change( i, flip_bit ); +} + +inline +void +big_whole::bit_assign +( + std::size_t from, + std::size_t to, + bool value +) +{ + this->bit_change( from, to, value ? set_bit : reset_bit ); +} + +inline +void +big_whole::bit_assign +( + std::size_t i, + bool value +) +{ + this->bit_change( i, value ? set_bit : reset_bit ); +} + + +// Arbitrary-length whole-number bit-inspecting member definitions ---------// + +std::size_t +big_whole::length +( +) const +{ + if ( va_type const * const v = this->x_.get() ) + { + using std::size_t; + + if ( size_t const o = self_type::wlength(*v) ) + { + size_t const oo = o - 1; + + return self_type::blength( (*v)[oo] ) + oo * limits_type::digits; + } + } + + return 0; +} + +std::size_t +big_whole::count +( +) const +{ + if ( va_type const * const v = this->x_.get() ) + { + return v->size() ? v->apply( self_type::count_set_bits_for_word ).sum() + : 0u; + } + else + { + return 0; + } +} + +inline +bool +big_whole::any +( +) const +{ + return this->x_.get() && this->x_->size() && this->x_->max(); +} + +inline +bool +big_whole::none +( +) const +{ + return !this->any(); +} + +bool +big_whole::test +( + std::size_t i +) const +{ + if ( va_type const * const v = this->x_.get() ) + { + using std::size_t; + + size_t const wi = i / limits_type::digits; + size_t const wj = i % limits_type::digits; + + return ( v->size() > wi ) ? ( (*v)[wi] & (1u << wj) ) : false; + } + else + { + return false; + } +} + +big_whole +big_whole::tests +( + std::size_t from, + std::size_t to +) const +{ + using std::valarray; + using std::size_t; + + if ( from > to ) + { + std::swap( from, to ); + } + + valarray const ids = this->to_bit_indices(); + valarray new_ids = ids[ (ids >= from) && (ids <= to) ]; + + if ( new_ids.size() ) + { + new_ids -= from; + } + + return self_type( new_ids ); +} + +big_whole +big_whole::reverse +( + std::size_t cap +) const +{ + using std::valarray; + using std::size_t; + + valarray const ids = this->to_bit_indices(); + valarray const new_ids = ids[ ids <= cap ]; + + return self_type( cap - new_ids ); +} + +inline +big_whole +big_whole::reverse +( +) const +{ + return this->any() ? this->reverse( this->length() - 1 ) : *this; +} + + +// Arbitrary-length whole-number self-operator member definitions ----------// + +inline +void +big_whole::not_self +( +) +{ + this->x_.reset( this->any() ? NULL : new va_type(1u, 1) ); +} + + +// Arbitrary-length whole-number member operator definitions ---------------// + +inline +big_whole & +big_whole::operator = +( + big_whole const & rhs +) +{ + return this->assign( rhs ), *this; +} + +inline +big_whole::operator big_whole::bool_type +( +) const +{ + return this->any() ? &dummy::d : NULL; +} + + +// Arbitrary-length whole-number helper static member function definitions -// + +inline +std::size_t +big_whole::words_for_bits +( + std::size_t bits +) +{ + return ( bits / limits_type::digits ) + static_cast< std::size_t >( 0 + != (bits % limits_type::digits) ); +} + +big_whole::va_type +big_whole::uintmax_to_va +( + uintmax_t v +) +{ + using std::size_t; + + int const d = std::numeric_limits::digits; + + // NOTE: this test should be optimized during compile-time + + if ( d > limits_type::digits ) + { + size_t const s = self_type::words_for_bits( d ); + va_type temp( 0u, s ); + size_t words_used = 0; + + for ( ; v && (words_used < s) ; ++words_used ) + { + temp[ words_used ] = static_cast< word_type >( v ); + v >>= limits_type::digits; + } + + return words_used ? temp[ std::slice(0, words_used, 1) ] : va_type(); + } + else + { + return va_type( static_cast(v), 1 ); + } +} + +big_whole::va_type +big_whole::bit_vector_to_va +( + std::valarray const & b +) +{ + using std::size_t; + + va_type temp; + + if ( size_t const bs = b.size() ) + { + word_type const m = 1; + int const d = limits_type::digits; + + temp.resize( self_type::words_for_bits(bs), 0u ); + + for ( size_t i = 0 ; i < bs ; ++i ) + { + if ( b[i] ) + { + size_t const wi = i / d; + size_t const wj = i % d; + + temp[ wi ] |= ( m << wj ); + } + } + } + + return temp; +} + +big_whole::va_type +big_whole::bit_indices_to_va +( + std::valarray const & i +) +{ + std::valarray temp; + + if ( i.size() ) + { + temp.resize( i.max() + 1, false ); + temp[ i ] = true; + } + + return self_type::bit_vector_to_va( temp ); +} + +std::size_t +big_whole::wlength +( + big_whole::va_type const & v +) +{ + std::size_t i = v.size(); + + while ( i && !v[i - 1] ) + { + --i; + } + + return i; +} + +std::size_t +big_whole::blength +( + big_whole::word_type w +) +{ + int i = limits_type::digits; + + while ( i && !(w & ( 1u << (i - 1) )) ) + { + --i; + } + + return i; +} + +big_whole::word_type +big_whole::count_set_bits_for_word +( + big_whole::word_type w +) +{ + word_type c = 0; + + for ( int i = 0 ; w && (i < limits_type::digits) ; ++i, w >>= 1 ) + { + c += ( 0u != (w & 1u) ); + } + + return c; +} + + +// Arbitrary-length whole-number helper member function definitions --------// + +void +big_whole::bit_change +( + std::size_t from, + std::size_t to, + big_whole::bit_operation op +) +{ + using std::size_t; + using std::slice; + + if ( from > to ) + { + std::swap( from, to ); + } + + size_t const fi = from / limits_type::digits; + size_t const fj = from % limits_type::digits; + size_t const ti = to / limits_type::digits; + size_t const tj = to % limits_type::digits; + + va_type * v = this->x_.get(); + size_t v_size = v ? v->size() : 0; + + word_type const fm = ~( (1u << fj) - 1u ); + word_type const tm = ( 1u << tj ) | ( (1u << tj) - 1u ); + + if ( (ti >= v_size) && (op != reset_bit) ) + { + ap_type p( new va_type(0u, ti + 1) ); + + if ( v && v_size ) + { + ( *p )[ slice(0, v_size, 1) ] = *v; + } + + this->x_.reset( p.release() ); + v = this->x_.get(); + v_size = v->size(); + } + + if ( fi == ti ) + { + word_type const ftm = fm & tm; + + switch ( op ) + { + case flip_bit: + ( *v )[ fi ] ^= ftm; + break; + + case set_bit: + ( *v )[ fi ] |= ftm; + break; + + case reset_bit: + default: + if ( ti < v_size ) + { + ( *v )[ fi ] &= ~ftm; + } + break; + } + } + else + { + // lowest affected word + switch ( op ) + { + case flip_bit: + ( *v )[ fi ] ^= fm; + break; + + case set_bit: + ( *v )[ fi ] |= fm; + break; + + case reset_bit: + default: + if ( fi < v_size ) + { + ( *v )[ fi ] &= ~fm; + } + break; + } + + // middle affected word(s), if any + size_t const start = fi + 1; + size_t const stop = std::min( v_size, ti ); + + if ( stop > start ) + { + slice const ids( start, stop - start, 1 ); + + switch ( op ) + { + case flip_bit: + ( *v )[ ids ] = static_cast( (*v)[ids] ) ^ limits_type::max(); + break; + + case set_bit: + ( *v )[ ids ] = limits_type::max(); + break; + + case reset_bit: + default: + ( *v )[ ids ] = limits_type::min(); + break; + } + } + + // highest affected word + switch ( op ) + { + case flip_bit: + ( *v )[ ti ] ^= tm; + break; + + case set_bit: + ( *v )[ ti ] |= tm; + break; + + case reset_bit: + default: + if ( ti < v_size ) + { + ( *v )[ ti ] &= ~tm; + } + break; + } + } +} + +inline +void +big_whole::bit_change +( + std::size_t i, + big_whole::bit_operation op +) +{ + this->bit_change( i, i, op ); +} + + +// Arbitrary-length whole-number non-member function definitions -----------// + +inline +void +swap +( + big_whole & a, + big_whole & b +) +{ + a.swap( b ); +} + + +// Arbitrary-length whole-number non-member operator definitions -----------// + +inline +big_whole +operator ! +( + big_whole const & w +) +{ + big_whole temp( w ); + + return temp.not_self(), temp; +} + + +} // namespace math +} // namespace boost + + +namespace std +{ + + +// Specialization of numeric-limits declaration ----------------------------// + +template < > +class numeric_limits< ::boost::math::big_whole > +{ + typedef ::boost::math::big_whole type; + + // NOTE: functions whose definitions aren't given here are never defined + +public: + static bool const is_specialized = true; + static type min() throw() { return type(); } + static type max() throw(); + + static int const digits = 0; + static int const digits10 = 0; + static bool const is_signed = false; + static bool const is_integer = true; + static bool const is_exact = true; + static int const radix = 2; + static type epsilon() throw(); + static type round_error() throw(); + + static int const min_exponent = 0; + static int const min_exponent10 = 0; + static int const max_exponent = 0; + static int const max_exponent10 = 0; + + static bool const has_infinity = false; + static bool const has_quiet_NaN = false; + static bool const has_signaling_NaN = false; + static float_denorm_style const has_denorm = denorm_absent; + static bool const has_denorm_loss = false; + static type infinity() throw(); + static type quiet_NaN() throw(); + static type signaling_NaN() throw(); + static type denorm_min() throw(); + + static bool const is_iec559 = false; + static bool const is_bounded = false; + static bool const is_modulo = false; + + static bool const traps = false; + static bool const tinyness_before = false; + static float_round_style const round_style = round_toward_zero; + +}; // std::numeric_limits + + +} // namespace std + + +#endif // BOOST_MATH_BIG_WHOLE_CORE_HPP diff --git a/test/big_whole_test.cpp b/test/big_whole_test.cpp new file mode 100644 index 000000000..dbdb34346 --- /dev/null +++ b/test/big_whole_test.cpp @@ -0,0 +1,915 @@ +// Boost big_whole_test.cpp test file --------------------------------------// + +// Copyright 2004 Daryle Walker. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or a copy at .) + +// See for the library's home page. + +// Revision History +// 05 Feb 2004 Initial version (Daryle Walker) + +#include // for boost::math::big_whole, etc. +#include // for main, BOOST_CHECK_EQUAL, etc. + +#include // for std::copy +#include // for std::size_t +#include // for std::numeric_limits +#include // for std::set +#include // for std::valarray + + +// Use internal knowledge of big_whole (i.e. cheat) to force situations +// where multiple-word representations have to be used +typedef unsigned int word_type; +typedef std::numeric_limits wlimits_type; + + +// Helper function to compare valarrays +template < typename T > +bool +equal_valarrays +( + std::valarray const & lhs, + std::valarray const & rhs +) +{ + using std::valarray; + + if ( lhs.size() == rhs.size() ) + { + valarray s( lhs.size() ); + + s[ lhs == rhs ] = 1; + return s.sum() == s.size(); + } + + return false; +} + +// Helper function to insert values into sets +template < class SetType, typename ValueType > +void +insert_value_range +( + SetType & s, + ValueType start, + ValueType finish +) +{ + for ( ValueType i = start ; i <= finish ; ++i ) + { + s.insert( i ); + } +} + +// Helper function to remove values from sets +template < class SetType, typename ValueType > +void +erase_value_range +( + SetType & s, + ValueType start, + ValueType finish +) +{ + for ( ValueType i = start ; i <= finish ; ++i ) + { + s.erase( i ); + } +} + +// Helper function to convert sets to valarrays +template < typename T > +std::valarray +set_to_valarray +( + std::set const & s +) +{ + std::valarray temp( s.size() ); + + std::copy( s.begin(), s.end(), &temp[0] ); + return temp; +} + + +// Unit test for the basics +void +basic_bigwhole_unit_test +( +) +{ + using boost::math::big_whole; + using std::valarray; + using std::size_t; + + typedef valarray va_bool_t; + typedef valarray va_size_t; + + // Default construction + big_whole x1; + BOOST_CHECK_EQUAL( 0u, x1.to_uintmax() ); + + // Converting assignment + x1.assign( 5u ); + BOOST_CHECK_EQUAL( 5u, x1.to_uintmax() ); + + // Converting construction + big_whole x2 = 17; + BOOST_CHECK_EQUAL( 17u, x2.to_uintmax() ); + + // Copy construction + big_whole x3( x1 ); + BOOST_CHECK_EQUAL( 5u, x3.to_uintmax() ); + + // Assignment operator + x1 = x2; + BOOST_CHECK_EQUAL( 17u, x1.to_uintmax() ); + + // Swapping + swap( x1, x3 ); + BOOST_CHECK_EQUAL( 5u, x1.to_uintmax() ); + BOOST_CHECK_EQUAL( 17u, x3.to_uintmax() ); + + // Copying assignment + x2.assign( big_whole() ); + BOOST_CHECK_EQUAL( 0u, x2.to_uintmax() ); + + // Bit-vector conversion + va_bool_t const x1_b = x1.to_bit_vector(); + bool const x1_b_check[] = { true, false, true }; + size_t const x1_b_size = sizeof( x1_b_check ) / sizeof( x1_b_check[0] ); + BOOST_CHECK( equal_valarrays(va_bool_t( x1_b_check, x1_b_size ), x1_b) ); + + BOOST_CHECK_EQUAL( 0u, x2.to_bit_vector().size() ); + + va_bool_t const x3_b = x3.to_bit_vector(); + bool const x3_b_check[] = { true, false, false, false, true }; + size_t const x3_b_size = sizeof( x3_b_check ) / sizeof( x3_b_check[0] ); + BOOST_CHECK( equal_valarrays(va_bool_t( x3_b_check, x3_b_size ), x3_b) ); + + // Bit-index conversion + va_size_t const x1_i = x1.to_bit_indices(); + size_t const x1_i_check[] = { 0, 2 }; + size_t const x1_i_size = sizeof( x1_i_check ) / sizeof( x1_i_check[0] ); + BOOST_CHECK( equal_valarrays(va_size_t( x1_i_check, x1_i_size ), x1_i) ); + BOOST_CHECK_EQUAL( x1_b_size, 1u + x1_i.max() ); + + BOOST_CHECK_EQUAL( 0u, x2.to_bit_indices().size() ); + + va_size_t const x3_i = x3.to_bit_indices(); + size_t const x3_i_check[] = { 0, 4 }; + size_t const x3_i_size = sizeof( x3_i_check ) / sizeof( x3_i_check[0] ); + BOOST_CHECK( equal_valarrays(va_size_t( x3_i_check, x3_i_size ), x3_i) ); + BOOST_CHECK_EQUAL( x3_b_size, 1u + x3_i.max() ); + + // Bit-vector construction and assignment + big_whole x4( x1_b ); + BOOST_CHECK_EQUAL( 5u, x4.to_uintmax() ); + + x4.reconfigure( x3_b ); + BOOST_CHECK_EQUAL( 17u, x4.to_uintmax() ); + + x4.reconfigure( va_bool_t() ); + BOOST_CHECK_EQUAL( 0u, x4.to_uintmax() ); + + // Bit-index construction and assignment + big_whole x5( x3_i ); + BOOST_CHECK_EQUAL( 17u, x5.to_uintmax() ); + + x5.reconfigure( x1_i ); + BOOST_CHECK_EQUAL( 5u, x5.to_uintmax() ); + + x5.reconfigure( va_size_t() ); + BOOST_CHECK_EQUAL( 0u, x5.to_uintmax() ); + + // Minimum-required bit length + BOOST_CHECK_EQUAL( x1_b_size, x1.length() ); + BOOST_CHECK_EQUAL( 0u, x2.length() ); + BOOST_CHECK_EQUAL( x3_b_size, x3.length() ); + + // Bit count + BOOST_CHECK_EQUAL( x1_i_size, x1.count() ); + BOOST_CHECK_EQUAL( 0u, x2.count() ); + BOOST_CHECK_EQUAL( x3_i_size, x3.count() ); + + BOOST_CHECK( x1.any() ); + BOOST_CHECK( !x2.any() ); + BOOST_CHECK( x3.any() ); + + BOOST_CHECK( !x1.none() ); + BOOST_CHECK( x2.none() ); + BOOST_CHECK( !x3.none() ); + + // Bit testing + BOOST_CHECK( x1.test(0) && !x1.test(1) && x1.test(2) && !x1.test(3) + && !x1.test(4) && !x1.test(5) && !x1.test(wlimits_type::digits) ); + BOOST_CHECK( !x2.test(0) && !x2.test(1) && !x2.test(2) && !x2.test(3) + && !x2.test(4) && !x2.test(5) && !x2.test(wlimits_type::digits) ); + BOOST_CHECK( x3.test(0) && !x3.test(1) && !x3.test(2) && !x3.test(3) + && x3.test(4) && !x3.test(5) && !x3.test(wlimits_type::digits) ); + + // Boolean test + BOOST_CHECK( x1 ); + BOOST_CHECK( !x2 ); + BOOST_CHECK( x3 ); +} + +// Unit test for "tests" +void +bigwhole_multi_bit_check_unit_test +( +) +{ + using boost::math::big_whole; + using std::size_t; + + size_t const size_max = std::numeric_limits::max(); + + // Non-zero tests + big_whole const x1( 74u ); + size_t const l1 = x1.length(); + + BOOST_CHECK_EQUAL( 7u, l1 ); + + BOOST_CHECK_EQUAL( 74u, x1.tests(0, size_max).to_uintmax() ); + BOOST_CHECK_EQUAL( 74u, x1.tests(0, l1).to_uintmax() ); + BOOST_CHECK_EQUAL( 74u, x1.tests(0, l1 - 1).to_uintmax() ); + BOOST_CHECK_EQUAL( 10u, x1.tests(0, 5).to_uintmax() ); + BOOST_CHECK_EQUAL( 10u, x1.tests(0, 4).to_uintmax() ); + BOOST_CHECK_EQUAL( 10u, x1.tests(0, 3).to_uintmax() ); + BOOST_CHECK_EQUAL( 2u, x1.tests(0, 2).to_uintmax() ); + BOOST_CHECK_EQUAL( 2u, x1.tests(0, 1).to_uintmax() ); + BOOST_CHECK_EQUAL( 0u, x1.tests(0, 0).to_uintmax() ); + + BOOST_CHECK_EQUAL( 37u, x1.tests(1, l1).to_uintmax() ); + BOOST_CHECK_EQUAL( 18u, x1.tests(2, l1).to_uintmax() ); + BOOST_CHECK_EQUAL( 9u, x1.tests(3, l1).to_uintmax() ); + BOOST_CHECK_EQUAL( 4u, x1.tests(4, l1).to_uintmax() ); + BOOST_CHECK_EQUAL( 2u, x1.tests(5, l1).to_uintmax() ); + BOOST_CHECK_EQUAL( 1u, x1.tests(l1 - 1, l1).to_uintmax() ); + BOOST_CHECK_EQUAL( 0u, x1.tests(l1, l1).to_uintmax() ); + + BOOST_CHECK( x1.tests(1, 1) ); + BOOST_CHECK( !x1.tests(2, 2) ); + BOOST_CHECK( x1.tests(3, 3) ); + BOOST_CHECK( !x1.tests(4, 4) ); + BOOST_CHECK( !x1.tests(5, 5) ); + BOOST_CHECK( x1.tests(l1 - 1, l1 - 1) ); + + // Zero tests + big_whole const x2; + + BOOST_CHECK( !x2.tests(0, 4) ); + BOOST_CHECK( !x2.tests(2, size_max) ); + BOOST_CHECK( !x2.tests(0, size_max) ); + BOOST_CHECK( !x2.tests(3, 3) ); +} + +// Unit test for reversing +void +bigwhole_reverse_unit_test +( +) +{ + using boost::math::big_whole; + + // Non-zero tests + big_whole const x1( 1 ); + + BOOST_CHECK_EQUAL( 1u, x1.reverse().to_uintmax() ); + BOOST_CHECK_EQUAL( 1u, x1.length() ); + + BOOST_CHECK_EQUAL( 1u, x1.reverse(0).to_uintmax() ); + BOOST_CHECK_EQUAL( 2u, x1.reverse(1).to_uintmax() ); + BOOST_CHECK_EQUAL( 4u, x1.reverse(2).to_uintmax() ); + BOOST_CHECK_EQUAL( 128u, x1.reverse(7).to_uintmax() ); + + big_whole const x2( 5 ); + + BOOST_CHECK_EQUAL( 5u, x2.reverse().to_uintmax() ); + BOOST_CHECK_EQUAL( 3u, x2.length() ); + + BOOST_CHECK_EQUAL( 1u, x2.reverse(0).to_uintmax() ); + BOOST_CHECK_EQUAL( 2u, x2.reverse(1).to_uintmax() ); + BOOST_CHECK_EQUAL( 5u, x2.reverse(2).to_uintmax() ); + BOOST_CHECK_EQUAL( 10u, x2.reverse(3).to_uintmax() ); + BOOST_CHECK_EQUAL( 20u, x2.reverse(4).to_uintmax() ); + BOOST_CHECK_EQUAL( 160u, x2.reverse(7).to_uintmax() ); + + big_whole const x3( 74 ); + + BOOST_CHECK_EQUAL( 41u, x3.reverse().to_uintmax() ); + BOOST_CHECK_EQUAL( 7u, x3.length() ); + + BOOST_CHECK_EQUAL( 0u, x3.reverse(0).to_uintmax() ); + BOOST_CHECK_EQUAL( 1u, x3.reverse(1).to_uintmax() ); + BOOST_CHECK_EQUAL( 2u, x3.reverse(2).to_uintmax() ); + BOOST_CHECK_EQUAL( 5u, x3.reverse(3).to_uintmax() ); + BOOST_CHECK_EQUAL( 10u, x3.reverse(4).to_uintmax() ); + BOOST_CHECK_EQUAL( 20u, x3.reverse(5).to_uintmax() ); + BOOST_CHECK_EQUAL( 41u, x3.reverse(6).to_uintmax() ); + BOOST_CHECK_EQUAL( 82u, x3.reverse(7).to_uintmax() ); + BOOST_CHECK_EQUAL( 164u, x3.reverse(8).to_uintmax() ); + BOOST_CHECK_EQUAL( 656u, x3.reverse(10).to_uintmax() ); + + // Zero tests + big_whole const x4; + + BOOST_CHECK( !x4.length() ); + BOOST_CHECK( !x4.reverse() ); + BOOST_CHECK( !x4.reverse(0) ); + BOOST_CHECK( !x4.reverse(2 * wlimits_type::digits) ); +} + +// Unit test for resetting every bit +void +bigwhole_all_bit_reset_unit_test +( +) +{ + using boost::math::big_whole; + using std::size_t; + + typedef std::valarray va_size_t; + + // zero + big_whole a1; + + BOOST_CHECK( !a1 ); + + a1.reset(); + BOOST_CHECK( !a1 ); + + // one bit set + big_whole a2( 8 ); + + BOOST_CHECK( a2 ); + + a2.reset(); + BOOST_CHECK( !a2 ); + + // multiple bits set + big_whole a3( 25 ); + + BOOST_CHECK( a3 ); + + a3.reset(); + BOOST_CHECK( !a3 ); + + // two words + size_t const a4_i[] = { 0, wlimits_type::digits + 1 }; + size_t const a4_s = sizeof( a4_i ) / sizeof( a4_i[0] ); + big_whole a4( va_size_t(a4_i, a4_s) ); + + BOOST_CHECK( a4 ); + + a4.reset(); + BOOST_CHECK( !a4 ); + + // more-than-two words + size_t const a5_i[] = { 1, wlimits_type::digits + 3, wlimits_type::digits + 4, 2 * wlimits_type::digits + 5 }; + size_t const a5_s = sizeof( a5_i ) / sizeof( a5_i[0] ); + big_whole a5( va_size_t(a5_i, a5_s) ); + + BOOST_CHECK( a5 ); + + a5.reset(); + BOOST_CHECK( !a5 ); +} + +// Unit test for resetting single bits +void +bigwhole_single_bit_reset_unit_test +( +) +{ + using boost::math::big_whole; + using std::size_t; + + typedef std::valarray va_size_t; + + // zero + big_whole a1; + + BOOST_CHECK_EQUAL( 0u, a1.to_uintmax() ); + + a1.reset( 3 ); + BOOST_CHECK_EQUAL( 0u, a1.to_uintmax() ); + + // one bit set + big_whole a2( 8 ); + + BOOST_CHECK_EQUAL( 8u, a2.to_uintmax() ); + + a2.reset( 2 ); + BOOST_CHECK_EQUAL( 8u, a2.to_uintmax() ); + + a2.reset( 3 ); + BOOST_CHECK_EQUAL( 0u, a2.to_uintmax() ); + + // multiple bits set + big_whole a3( 25 ); + + BOOST_CHECK_EQUAL( 25u, a3.to_uintmax() ); + + a3.reset( 0 ); + BOOST_CHECK_EQUAL( 24u, a3.to_uintmax() ); + + a3.reset( 1 ); + BOOST_CHECK_EQUAL( 24u, a3.to_uintmax() ); + + a3.reset( 4 ); + BOOST_CHECK_EQUAL( 8u, a3.to_uintmax() ); + + // two words + size_t const a4_old_i[] = { 0, wlimits_type::digits + 1 }; + size_t const a4_old_s = sizeof( a4_old_i ) / sizeof( a4_old_i[0] ); + va_size_t const a4_old( a4_old_i, a4_old_s ); + big_whole a4( a4_old ); + + BOOST_CHECK( equal_valarrays(a4_old, a4.to_bit_indices()) ); + + a4.reset( 5 ); + BOOST_CHECK( equal_valarrays(a4_old, a4.to_bit_indices()) ); + + a4.reset( 0 ); + BOOST_CHECK( equal_valarrays(va_size_t( a4_old_i + 1, a4_old_s - 1 ), a4.to_bit_indices()) ); + + // more-than-two words + size_t const a5_old_i[] = { 1, wlimits_type::digits + 3, wlimits_type::digits + 4, 2 * wlimits_type::digits + 5 }; + size_t const a5_old_s = sizeof( a5_old_i ) / sizeof( a5_old_i[0] ); + va_size_t const a5_old( a5_old_i, a5_old_s ); + big_whole a5( a5_old ); + + BOOST_CHECK( equal_valarrays(a5_old, a5.to_bit_indices()) ); + + a5.reset( 4 ); + BOOST_CHECK( equal_valarrays(a5_old, a5.to_bit_indices()) ); + + a5.reset( 2 * wlimits_type::digits + 5 ); + BOOST_CHECK( equal_valarrays(va_size_t( a5_old_i, a5_old_s - 1 ), a5.to_bit_indices()) ); +} + +// Unit test for resetting a group of bits +void +bigwhole_group_bit_reset_unit_test +( +) +{ + using boost::math::big_whole; + using std::size_t; + + typedef std::valarray va_size_t; + + // zero + big_whole a1; + + BOOST_CHECK_EQUAL( 0u, a1.to_uintmax() ); + + a1.reset( 3, 7 ); + BOOST_CHECK_EQUAL( 0u, a1.to_uintmax() ); + + // one bit set + big_whole a2( 8 ); + + BOOST_CHECK_EQUAL( 8u, a2.to_uintmax() ); + + a2.reset( 6, 9 ); + BOOST_CHECK_EQUAL( 8u, a2.to_uintmax() ); + + a2.reset( 2, 3 ); + BOOST_CHECK_EQUAL( 0u, a2.to_uintmax() ); + + // multiple bits set + big_whole a3( 25 ); + + BOOST_CHECK_EQUAL( 25u, a3.to_uintmax() ); + + a3.reset( 3, 3 ); + BOOST_CHECK_EQUAL( 17u, a3.to_uintmax() ); + + a3.reset( 1, 2 ); + BOOST_CHECK_EQUAL( 17u, a3.to_uintmax() ); + + a3.reset( 2, 6 ); + BOOST_CHECK_EQUAL( 1u, a3.to_uintmax() ); + + // two words + size_t const a4_old_i[] = { 0, wlimits_type::digits + 1 }; + size_t const a4_old_s = sizeof( a4_old_i ) / sizeof( a4_old_i[0] ); + va_size_t const a4_old( a4_old_i, a4_old_s ); + big_whole a4( a4_old ); + + BOOST_CHECK( equal_valarrays(a4_old, a4.to_bit_indices()) ); + + a4.reset( 5, 12 ); + BOOST_CHECK( equal_valarrays(a4_old, a4.to_bit_indices()) ); + + a4.reset( 9, 2 * wlimits_type::digits ); + BOOST_CHECK( equal_valarrays(va_size_t( a4_old_i, a4_old_s - 1 ), a4.to_bit_indices()) ); + + // more-than-two words + size_t const a5_old_i[] = { 1, wlimits_type::digits + 3, wlimits_type::digits + 4, 2 * wlimits_type::digits + 5 }; + size_t const a5_old_s = sizeof( a5_old_i ) / sizeof( a5_old_i[0] ); + va_size_t const a5_old( a5_old_i, a5_old_s ); + big_whole a5( a5_old ); + + BOOST_CHECK( equal_valarrays(a5_old, a5.to_bit_indices()) ); + + a5.reset( 3, 12 ); + BOOST_CHECK( equal_valarrays(a5_old, a5.to_bit_indices()) ); + + size_t const a5_new_i[] = { 1, 2 * wlimits_type::digits + 5 }; + size_t const a5_new_s = sizeof( a5_new_i ) / sizeof( a5_new_i[0] ); + + a5.reset( wlimits_type::digits - 1, 2 * wlimits_type::digits + 1 ); + BOOST_CHECK( equal_valarrays(va_size_t( a5_new_i, a5_new_s ), a5.to_bit_indices()) ); + + a5.reset( 2 * wlimits_type::digits + 1, 3 * wlimits_type::digits ); + BOOST_CHECK( equal_valarrays(va_size_t( 1u, 1 ), a5.to_bit_indices()) ); + + a5.reset( wlimits_type::digits + 1, 3 * wlimits_type::digits ); + BOOST_CHECK( equal_valarrays(va_size_t( 1u, 1 ), a5.to_bit_indices()) ); +} + +// Unit test for setting single bits +void +bigwhole_single_bit_set_unit_test +( +) +{ + using boost::math::big_whole; + using std::size_t; + + typedef std::valarray va_size_t; + + // zero + big_whole a1; + + BOOST_CHECK_EQUAL( 0u, a1.to_uintmax() ); + + a1.set( 3 ); + BOOST_CHECK_EQUAL( 8u, a1.to_uintmax() ); + + // one bit set + big_whole a2( 8 ); + + BOOST_CHECK_EQUAL( 8u, a2.to_uintmax() ); + + a2.set( 2 ); + BOOST_CHECK_EQUAL( 12u, a2.to_uintmax() ); + + a2.set( 3 ); + BOOST_CHECK_EQUAL( 12u, a2.to_uintmax() ); + + // multiple bits set + big_whole a3( 25 ); + + BOOST_CHECK_EQUAL( 25u, a3.to_uintmax() ); + + a3.set( 0 ); + BOOST_CHECK_EQUAL( 25u, a3.to_uintmax() ); + + a3.set( 1 ); + BOOST_CHECK_EQUAL( 27u, a3.to_uintmax() ); + + a3.set( 4 ); + BOOST_CHECK_EQUAL( 27u, a3.to_uintmax() ); + + // two words + size_t const a4_old_i[] = { 0, wlimits_type::digits + 1 }; + size_t const a4_old_s = sizeof( a4_old_i ) / sizeof( a4_old_i[0] ); + va_size_t const a4_old( a4_old_i, a4_old_s ); + big_whole a4( a4_old ); + + BOOST_CHECK( equal_valarrays(a4_old, a4.to_bit_indices()) ); + + size_t const a4_new_i[] = { 0, 5, wlimits_type::digits + 1 }; + size_t const a4_new_s = sizeof( a4_new_i ) / sizeof( a4_new_i[0] ); + va_size_t const a4_new( a4_new_i, a4_new_s ); + + a4.set( 5 ); + BOOST_CHECK( equal_valarrays(a4_new, a4.to_bit_indices()) ); + + a4.set( 0 ); + BOOST_CHECK( equal_valarrays(a4_new, a4.to_bit_indices()) ); + + // more-than-two words + size_t const a5_old_i[] = { 1, wlimits_type::digits + 3, wlimits_type::digits + 4, 2 * wlimits_type::digits + 5 }; + size_t const a5_old_s = sizeof( a5_old_i ) / sizeof( a5_old_i[0] ); + va_size_t const a5_old( a5_old_i, a5_old_s ); + big_whole a5( a5_old ); + + BOOST_CHECK( equal_valarrays(a5_old, a5.to_bit_indices()) ); + + size_t const a5_new_i[] = { 1, 4, wlimits_type::digits + 3, wlimits_type::digits + 4, 2 * wlimits_type::digits + 5 }; + size_t const a5_new_s = sizeof( a5_new_i ) / sizeof( a5_new_i[0] ); + va_size_t const a5_new( a5_new_i, a5_new_s ); + + a5.set( 4 ); + BOOST_CHECK( equal_valarrays(a5_new, a5.to_bit_indices()) ); + + a5.set( 2 * wlimits_type::digits + 5 ); + BOOST_CHECK( equal_valarrays(a5_new, a5.to_bit_indices()) ); +} + +// Unit test for setting a group of bits +void +bigwhole_group_bit_set_unit_test +( +) +{ + using boost::math::big_whole; + using std::size_t; + + typedef std::valarray va_size_t; + typedef std::set st_size_t; + + // zero + big_whole a1; + + BOOST_CHECK_EQUAL( 0u, a1.to_uintmax() ); + + a1.set( 3, 7 ); + BOOST_CHECK_EQUAL( 248u, a1.to_uintmax() ); + + // one bit set + big_whole a2( 8 ); + + BOOST_CHECK_EQUAL( 8u, a2.to_uintmax() ); + + a2.set( 6, 9 ); + BOOST_CHECK_EQUAL( 968u, a2.to_uintmax() ); + + a2.set( 2, 3 ); + BOOST_CHECK_EQUAL( 972u, a2.to_uintmax() ); + + // multiple bits set + big_whole a3( 25 ); + + BOOST_CHECK_EQUAL( 25u, a3.to_uintmax() ); + + a3.set( 3, 3 ); + BOOST_CHECK_EQUAL( 25u, a3.to_uintmax() ); + + a3.set( 1, 2 ); + BOOST_CHECK_EQUAL( 31u, a3.to_uintmax() ); + + a3.set( 2, 6 ); + BOOST_CHECK_EQUAL( 127u, a3.to_uintmax() ); + + // two words + size_t const a4_old_i[] = { 0, wlimits_type::digits + 1 }; + size_t const a4_old_s = sizeof( a4_old_i ) / sizeof( a4_old_i[0] ); + va_size_t const a4_old( a4_old_i, a4_old_s ); + big_whole a4( a4_old ); + st_size_t a4_new( a4_old_i, a4_old_i + a4_old_s ); + + BOOST_CHECK( equal_valarrays(a4_old, a4.to_bit_indices()) ); + + a4.set( 5, 12 ); + insert_value_range( a4_new, 5, 12 ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a4_new ), a4.to_bit_indices()) ); + + a4.set( 9, 2 * wlimits_type::digits ); + insert_value_range( a4_new, 9, 2 * wlimits_type::digits ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a4_new ), a4.to_bit_indices()) ); + + // more-than-two words + size_t const a5_old_i[] = { 1, wlimits_type::digits + 3, wlimits_type::digits + 4, 2 * wlimits_type::digits + 5 }; + size_t const a5_old_s = sizeof( a5_old_i ) / sizeof( a5_old_i[0] ); + va_size_t const a5_old( a5_old_i, a5_old_s ); + big_whole a5( a5_old ); + st_size_t a5_new( a5_old_i, a5_old_i + a5_old_s ); + + BOOST_CHECK( equal_valarrays(a5_old, a5.to_bit_indices()) ); + + a5.set( 3, 12 ); + insert_value_range( a5_new, 3, 12 ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a5_new ), a5.to_bit_indices()) ); + + a5.set( wlimits_type::digits - 1, 2 * wlimits_type::digits + 1 ); + insert_value_range( a5_new, wlimits_type::digits - 1, 2 * wlimits_type::digits + 1 ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a5_new ), a5.to_bit_indices()) ); + + a5.set( 2 * wlimits_type::digits + 1, 3 * wlimits_type::digits ); + insert_value_range( a5_new, 2 * wlimits_type::digits + 1, 3 * wlimits_type::digits ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a5_new ), a5.to_bit_indices()) ); + + a5.set( wlimits_type::digits + 1, 3 * wlimits_type::digits ); + insert_value_range( a5_new, wlimits_type::digits + 1, 3 * wlimits_type::digits ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a5_new ), a5.to_bit_indices()) ); +} + +// Unit test for flipping single bits +void +bigwhole_single_bit_flip_unit_test +( +) +{ + using boost::math::big_whole; + using std::size_t; + + typedef std::valarray va_size_t; + + // zero + big_whole a1; + + BOOST_CHECK_EQUAL( 0u, a1.to_uintmax() ); + + a1.flip( 3 ); + BOOST_CHECK_EQUAL( 8u, a1.to_uintmax() ); + + // one bit set + big_whole a2( 8 ); + + BOOST_CHECK_EQUAL( 8u, a2.to_uintmax() ); + + a2.flip( 2 ); + BOOST_CHECK_EQUAL( 12u, a2.to_uintmax() ); + + a2.flip( 3 ); + BOOST_CHECK_EQUAL( 4u, a2.to_uintmax() ); + + // multiple bits set + big_whole a3( 25 ); + + BOOST_CHECK_EQUAL( 25u, a3.to_uintmax() ); + + a3.flip( 0 ); + BOOST_CHECK_EQUAL( 24u, a3.to_uintmax() ); + + a3.flip( 1 ); + BOOST_CHECK_EQUAL( 26u, a3.to_uintmax() ); + + a3.flip( 4 ); + BOOST_CHECK_EQUAL( 10u, a3.to_uintmax() ); + + // two words + size_t const a4_old_i[] = { 0, wlimits_type::digits + 1 }; + size_t const a4_old_s = sizeof( a4_old_i ) / sizeof( a4_old_i[0] ); + va_size_t const a4_old( a4_old_i, a4_old_s ); + big_whole a4( a4_old ); + + BOOST_CHECK( equal_valarrays(a4_old, a4.to_bit_indices()) ); + + size_t const a4_new_i[] = { 0, 5, wlimits_type::digits + 1 }; + size_t const a4_new_s = sizeof( a4_new_i ) / sizeof( a4_new_i[0] ); + va_size_t const a4_new1( a4_new_i, a4_new_s ); + va_size_t const a4_new2( a4_new_i + 1, a4_new_s - 1 ); + + a4.flip( 5 ); + BOOST_CHECK( equal_valarrays(a4_new1, a4.to_bit_indices()) ); + + a4.flip( 0 ); + BOOST_CHECK( equal_valarrays(a4_new2, a4.to_bit_indices()) ); + + // more-than-two words + size_t const a5_old_i[] = { 1, wlimits_type::digits + 3, wlimits_type::digits + 4, 2 * wlimits_type::digits + 5 }; + size_t const a5_old_s = sizeof( a5_old_i ) / sizeof( a5_old_i[0] ); + va_size_t const a5_old( a5_old_i, a5_old_s ); + big_whole a5( a5_old ); + + BOOST_CHECK( equal_valarrays(a5_old, a5.to_bit_indices()) ); + + size_t const a5_new_i[] = { 1, 4, wlimits_type::digits + 3, wlimits_type::digits + 4, 2 * wlimits_type::digits + 5 }; + size_t const a5_new_s = sizeof( a5_new_i ) / sizeof( a5_new_i[0] ); + va_size_t const a5_new1( a5_new_i, a5_new_s ); + va_size_t const a5_new2( a5_new_i, a5_new_s - 1 ); + + a5.flip( 4 ); + BOOST_CHECK( equal_valarrays(a5_new1, a5.to_bit_indices()) ); + + a5.flip( 2 * wlimits_type::digits + 5 ); + BOOST_CHECK( equal_valarrays(a5_new2, a5.to_bit_indices()) ); +} + +// Unit test for flipping a group of bits +void +bigwhole_group_bit_flip_unit_test +( +) +{ + using boost::math::big_whole; + using std::size_t; + + typedef std::valarray va_size_t; + typedef std::set st_size_t; + + // zero + big_whole a1; + + BOOST_CHECK_EQUAL( 0u, a1.to_uintmax() ); + + a1.flip( 3, 7 ); + BOOST_CHECK_EQUAL( 248u, a1.to_uintmax() ); + + a1.flip( 2, 4 ); + BOOST_CHECK_EQUAL( 228u, a1.to_uintmax() ); + + // one bit set + big_whole a2( 8 ); + + BOOST_CHECK_EQUAL( 8u, a2.to_uintmax() ); + + a2.flip( 6, 9 ); + BOOST_CHECK_EQUAL( 968u, a2.to_uintmax() ); + + a2.flip( 2, 3 ); + BOOST_CHECK_EQUAL( 964u, a2.to_uintmax() ); + + // multiple bits set + big_whole a3( 25 ); + + BOOST_CHECK_EQUAL( 25u, a3.to_uintmax() ); + + a3.flip( 3, 3 ); + BOOST_CHECK_EQUAL( 17u, a3.to_uintmax() ); + + a3.flip( 1, 2 ); + BOOST_CHECK_EQUAL( 23u, a3.to_uintmax() ); + + a3.flip( 2, 6 ); + BOOST_CHECK_EQUAL( 107u, a3.to_uintmax() ); + + // two words + size_t const a4_old_i[] = { 0, wlimits_type::digits + 1 }; + size_t const a4_old_s = sizeof( a4_old_i ) / sizeof( a4_old_i[0] ); + va_size_t const a4_old( a4_old_i, a4_old_s ); + big_whole a4( a4_old ); + st_size_t a4_new( a4_old_i, a4_old_i + a4_old_s ); + + BOOST_CHECK( equal_valarrays(a4_old, a4.to_bit_indices()) ); + + a4.flip( 5, 12 ); + insert_value_range( a4_new, 5, 12 ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a4_new ), a4.to_bit_indices()) ); + + a4.flip( 9, 2 * wlimits_type::digits ); + insert_value_range( a4_new, 9, 2 * wlimits_type::digits ); + erase_value_range( a4_new, 9, 12 ); + a4_new.erase( wlimits_type::digits + 1 ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a4_new ), a4.to_bit_indices()) ); + + // more-than-two words + size_t const a5_old_i[] = { 1, wlimits_type::digits + 3, wlimits_type::digits + 4, 2 * wlimits_type::digits + 5 }; + size_t const a5_old_s = sizeof( a5_old_i ) / sizeof( a5_old_i[0] ); + va_size_t const a5_old( a5_old_i, a5_old_s ); + big_whole a5( a5_old ); + st_size_t a5_new( a5_old_i, a5_old_i + a5_old_s ); + + BOOST_CHECK( equal_valarrays(a5_old, a5.to_bit_indices()) ); + + a5.flip( 3, 12 ); + insert_value_range( a5_new, 3, 12 ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a5_new ), a5.to_bit_indices()) ); + + a5.flip( wlimits_type::digits - 1, 2 * wlimits_type::digits + 1 ); + insert_value_range( a5_new, wlimits_type::digits - 1, 2 * wlimits_type::digits + 1 ); + a5_new.erase( wlimits_type::digits + 3 ); + a5_new.erase( wlimits_type::digits + 4 ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a5_new ), a5.to_bit_indices()) ); + + a5.flip( 2 * wlimits_type::digits + 1, 3 * wlimits_type::digits ); + insert_value_range( a5_new, 2 * wlimits_type::digits + 1, 3 * wlimits_type::digits ); + a5_new.erase( 2 * wlimits_type::digits + 1 ); + a5_new.erase( 2 * wlimits_type::digits + 5 ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a5_new ), a5.to_bit_indices()) ); + + a5.flip( wlimits_type::digits + 1, 3 * wlimits_type::digits ); + erase_value_range( a5_new, wlimits_type::digits + 1, 3 * wlimits_type::digits ); + a5_new.insert( wlimits_type::digits + 3 ); + a5_new.insert( wlimits_type::digits + 4 ); + a5_new.insert( 2 * wlimits_type::digits + 1 ); + a5_new.insert( 2 * wlimits_type::digits + 5 ); + BOOST_CHECK( equal_valarrays(set_to_valarray( a5_new ), a5.to_bit_indices()) ); +} + + +// Unit test program +boost::unit_test_framework::test_suite * +init_unit_test_suite +( + int , // "argc" is unused + char * [] // "argv" is unused +) +{ + boost::unit_test_framework::test_suite * test + = BOOST_TEST_SUITE( "big_whole test" ); + + test->add( BOOST_TEST_CASE(basic_bigwhole_unit_test) ); + test->add( BOOST_TEST_CASE(bigwhole_multi_bit_check_unit_test) ); + test->add( BOOST_TEST_CASE(bigwhole_reverse_unit_test) ); + + test->add( BOOST_TEST_CASE(bigwhole_all_bit_reset_unit_test) ); + test->add( BOOST_TEST_CASE(bigwhole_single_bit_reset_unit_test) ); + test->add( BOOST_TEST_CASE(bigwhole_group_bit_reset_unit_test) ); + test->add( BOOST_TEST_CASE(bigwhole_single_bit_set_unit_test) ); + test->add( BOOST_TEST_CASE(bigwhole_group_bit_set_unit_test) ); + test->add( BOOST_TEST_CASE(bigwhole_single_bit_flip_unit_test) ); + test->add( BOOST_TEST_CASE(bigwhole_group_bit_flip_unit_test) ); + + return test; +}