IAP GITLAB

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • AirShowerPhysics/corsika
  • rulrich/corsika
  • AAAlvesJr/corsika
  • Andre/corsika
  • arrabito/corsika
  • Nikos/corsika
  • olheiser73/corsika
  • AirShowerPhysics/papers/corsika
  • pranav/corsika
9 results
Show changes
Showing
with 0 additions and 1935 deletions
set (
SETUP_HEADERS
SetupStack.h
SetupLogger.h
SetupEnvironment.h
SetupTrajectory.h
)
set (
SETUP_NAMESPACE
corsika/setup
)
add_library (CORSIKAsetup INTERFACE)
CORSIKA_COPY_HEADERS_TO_NAMESPACE (CORSIKAsetup ${SETUP_NAMESPACE} ${SETUP_HEADERS})
target_link_libraries (
CORSIKAsetup
INTERFACE
CORSIKAgeometry
SuperStupidStack
)
target_include_directories (
CORSIKAsetup
INTERFACE
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:include/include>
)
install (
FILES ${SETUP_HEADERS}
DESTINATION include/${SETUP_NAMESPACE}
)
/**
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _include_corsika_setup_environment_h_
#define _include_corsika_setup_environment_h_
#include <corsika/environment/IMediumModel.h>
namespace corsika::setup {
using IEnvironmentModel = corsika::environment::IMediumModel;
}
#endif
/**
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _include_corsika_setup_logger_h_
#define _include_corsika_setup_logger_h_
namespace corsika {}
#endif
/**
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _corsika_setup_setupstack_h_
#define _corsika_setup_setupstack_h_
#include <corsika/stack/super_stupid/SuperStupidStack.h>
namespace corsika::setup {
typedef corsika::stack::super_stupid::SuperStupidStack Stack;
}
#endif
/**
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _corsika_setup_setuptrajectory_h_
#define _corsika_setup_setuptrajectory_h_
#include <corsika/geometry/Helix.h>
#include <corsika/geometry/Line.h>
#include <corsika/geometry/Trajectory.h>
#include <corsika/units/PhysicalUnits.h>
#include <variant>
namespace corsika::setup {
using corsika::geometry::Helix;
using corsika::geometry::Line;
/// definition of Trajectory base class, to be used in tracking and cascades
typedef corsika::geometry::Trajectory<Line> Trajectory;
/*
typedef std::variant<std::monostate, corsika::geometry::Trajectory<Line>,
corsika::geometry::Trajectory<Helix>>
Trajectory;
/// helper visitor to modify Particle by moving along Trajectory
template <typename Particle>
class ParticleUpdate {
Particle& fP;
public:
ParticleUpdate(Particle& p)
: fP(p) {}
void operator()(std::monostate const&) {}
template <typename T>
void operator()(T const& trajectory) {
fP.SetPosition(trajectory.GetPosition(1));
}
};
/// helper visitor to modify Particle by moving along Trajectory
class GetDuration {
public:
corsika::units::si::TimeType operator()(std::monostate const&) {
return 0 * corsika::units::si::second;
}
template <typename T>
corsika::units::si::TimeType operator()(T const& trajectory) {
return trajectory.GetDuration();
}
};
*/
} // namespace corsika::setup
#endif
add_subdirectory (DummyStack)
add_subdirectory (SuperStupidStack)
set (DummyStack_HEADERS DummyStack.h)
set (DummyStack_NAMESPACE corsika/stack/dummy)
add_library (DummyStack INTERFACE)
CORSIKA_COPY_HEADERS_TO_NAMESPACE (DummyStack ${DummyStack_NAMESPACE} ${DummyStack_HEADERS})
target_link_libraries (
DummyStack
INTERFACE
CORSIKAstackinterface
CORSIKAunits
CORSIKAparticles
)
target_include_directories (
DummyStack
INTERFACE
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:include>
)
install (
FILES
${DummyStack_HEADERS}
DESTINATION
include/${DummyStack_NAMESPACE}
)
/**
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _include_dummystack_h_
#define _include_dummystack_h_
#include <corsika/particles/ParticleProperties.h>
#include <corsika/stack/Stack.h>
#include <corsika/units/PhysicalUnits.h>
#include <string>
#include <vector>
namespace corsika::stack {
namespace dummy {
/**
* Example of a particle object on the stack.
*/
template <typename _Stack>
class ParticleRead : public StackIteratorInfo<_Stack, ParticleRead<_Stack> > {
using StackIteratorInfo<_Stack, ParticleRead>::GetIndex;
using StackIteratorInfo<_Stack, ParticleRead>::GetStack;
public:
};
/**
*
* Memory implementation of the most simple (stupid) particle stack object.
*/
class DummyStackImpl {
public:
void Init() {}
void Clear() {}
int GetSize() const { return 0; }
int GetCapacity() const { return 0; }
/**
* Function to copy particle at location i2 in stack to i1
*/
void Copy(const int i1, const int i2) {}
protected:
void IncrementSize() {}
void DecrementSize() {}
}; // end class DummyStackImpl
typedef StackIterator<DummyStackImpl, ParticleRead<DummyStackImpl> > Particle;
typedef Stack<DummyStackImpl, Particle> DummyStack;
} // namespace dummy
} // namespace corsika::stack
#endif
/**
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _include_superstupidstack_h_
#define _include_superstupidstack_h_
#include <corsika/particles/ParticleProperties.h>
#include <corsika/stack/Stack.h>
#include <corsika/units/PhysicalUnits.h>
#include <string>
#include <vector>
namespace corsika::stack {
namespace super_stupid {
using corsika::particles::Code;
using corsika::units::si::EnergyType;
using corsika::units::si::operator""_GeV; // literals;
/**
* Example of a particle object on the stack.
*/
template <typename _Stack>
class ParticleRead : public StackIteratorInfo<_Stack, ParticleRead<_Stack> > {
using StackIteratorInfo<_Stack, ParticleRead>::GetIndex;
using StackIteratorInfo<_Stack, ParticleRead>::GetStack;
public:
void SetId(const Code id) { GetStack().SetId(GetIndex(), id); }
void SetEnergy(const EnergyType& e) { GetStack().SetEnergy(GetIndex(), e); }
Code GetId() const { return GetStack().GetId(GetIndex()); }
const EnergyType& GetEnergy() const { return GetStack().GetEnergy(GetIndex()); }
};
/**
*
* Memory implementation of the most simple (stupid) particle stack object.
*/
class SuperStupidStackImpl {
public:
void Init() {}
void Clear() {
fDataE.clear();
fDataId.clear();
}
int GetSize() const { return fDataId.size(); }
int GetCapacity() const { return fDataId.size(); }
void SetId(const int i, const Code id) { fDataId[i] = id; }
void SetEnergy(const int i, const EnergyType& e) { fDataE[i] = e; }
const Code GetId(const int i) const { return fDataId[i]; }
const EnergyType& GetEnergy(const int i) const { return fDataE[i]; }
/**
* Function to copy particle at location i2 in stack to i1
*/
void Copy(const int i1, const int i2) {
fDataE[i2] = fDataE[i1];
fDataId[i2] = fDataId[i1];
}
protected:
void IncrementSize() {
fDataE.push_back(0_GeV);
fDataId.push_back(Code::unknown);
}
void DecrementSize() {
if (fDataE.size() > 0) {
fDataE.pop_back();
fDataId.pop_back();
}
}
private:
/// the actual memory to store particle data
std::vector<Code> fDataId;
std::vector<EnergyType> fDataE;
}; // end class SuperStupidStackImpl
typedef StackIterator<SuperStupidStackImpl, ParticleRead<SuperStupidStackImpl> >
Particle;
typedef Stack<SuperStupidStackImpl, Particle> SuperStupidStack;
} // namespace super_stupid
} // namespace corsika::stack
#endif
set (SuperStupidStack_HEADERS SuperStupidStack.h)
set (SuperStupidStack_NAMESPACE corsika/stack/super_stupid)
add_library (SuperStupidStack INTERFACE)
CORSIKA_COPY_HEADERS_TO_NAMESPACE (SuperStupidStack ${SuperStupidStack_NAMESPACE} ${SuperStupidStack_HEADERS})
target_link_libraries (
SuperStupidStack
INTERFACE
CORSIKAstackinterface
CORSIKAunits
CORSIKAparticles
CORSIKAgeometry
)
target_include_directories (
SuperStupidStack
INTERFACE
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:include>
)
install (
FILES
${SuperStupidStack_HEADERS}
DESTINATION
include/${SuperStupidStack_NAMESPACE}
)
# ----------------
# code unit testing
add_executable (
testSuperStupidStack
testSuperStupidStack.cc
)
target_link_libraries (
testSuperStupidStack
# CORSIKAutls
ProcessStackInspector
CORSIKAgeometry
CORSIKAunits
CORSIKAthirdparty # for catch2
)
add_test (
NAME testSuperStupidStack
COMMAND testSuperStupidStack
)
/**
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#ifndef _include_superstupidstack_h_
#define _include_superstupidstack_h_
#include <corsika/particles/ParticleProperties.h>
#include <corsika/stack/Stack.h>
#include <corsika/units/PhysicalUnits.h>
#include <corsika/geometry/Point.h>
#include <corsika/geometry/RootCoordinateSystem.h> // remove
#include <corsika/geometry/Vector.h>
#include <algorithm>
#include <vector>
using namespace corsika;
namespace corsika::stack {
namespace super_stupid {
using corsika::geometry::Point;
using corsika::geometry::Vector;
using corsika::particles::Code;
using corsika::units::si::energy_d;
using corsika::units::si::EnergyType;
using corsika::units::si::joule;
using corsika::units::si::meter;
using corsika::units::si::momentum_d;
using corsika::units::si::newton_second;
using corsika::units::si::second;
using corsika::units::si::SpeedType;
using corsika::units::si::TimeType;
typedef Vector<momentum_d> MomentumVector;
/**
* Example of a particle object on the stack.
*/
template <typename StackIteratorInterface>
class ParticleInterface : public ParticleBase<StackIteratorInterface> {
using ParticleBase<StackIteratorInterface>::GetStackData;
using ParticleBase<StackIteratorInterface>::GetIndex;
public:
void SetPID(const Code id) { GetStackData().SetPID(GetIndex(), id); }
void SetEnergy(const EnergyType& e) { GetStackData().SetEnergy(GetIndex(), e); }
void SetMomentum(const MomentumVector& v) {
GetStackData().SetMomentum(GetIndex(), v);
}
void SetPosition(const Point& v) { GetStackData().SetPosition(GetIndex(), v); }
void SetTime(const TimeType& v) { GetStackData().SetTime(GetIndex(), v); }
Code GetPID() const { return GetStackData().GetPID(GetIndex()); }
EnergyType GetEnergy() const { return GetStackData().GetEnergy(GetIndex()); }
MomentumVector GetMomentum() const {
return GetStackData().GetMomentum(GetIndex());
}
Point GetPosition() const { return GetStackData().GetPosition(GetIndex()); }
TimeType GetTime() const { return GetStackData().GetTime(GetIndex()); }
#warning this does not really work, nor make sense:
Vector<SpeedType::dimension_type> GetDirection() const {
auto P = GetMomentum();
return P / P.norm() * 1e10 * (units::si::meter / units::si::second);
}
};
/**
*
* Memory implementation of the most simple (stupid) particle stack object.
*/
class SuperStupidStackImpl {
public:
void Init() {}
void Clear() {
fDataPID.clear();
fDataE.clear();
fMomentum.clear();
fPosition.clear();
fTime.clear();
}
int GetSize() const { return fDataPID.size(); }
int GetCapacity() const { return fDataPID.size(); }
void SetPID(const int i, const Code id) { fDataPID[i] = id; }
void SetEnergy(const int i, const EnergyType e) { fDataE[i] = e; }
void SetMomentum(const int i, const MomentumVector& v) { fMomentum[i] = v; }
void SetPosition(const int i, const Point& v) { fPosition[i] = v; }
void SetTime(const int i, const TimeType& v) { fTime[i] = v; }
Code GetPID(const int i) const { return fDataPID[i]; }
EnergyType GetEnergy(const int i) const { return fDataE[i]; }
MomentumVector GetMomentum(const int i) const { return fMomentum[i]; }
Point GetPosition(const int i) const { return fPosition[i]; }
TimeType GetTime(const int i) const { return fTime[i]; }
/**
* Function to copy particle at location i2 in stack to i1
*/
void Copy(const int i1, const int i2) {
fDataPID[i2] = fDataPID[i1];
fDataE[i2] = fDataE[i1];
fMomentum[i2] = fMomentum[i1];
fPosition[i2] = fPosition[i1];
fTime[i2] = fTime[i1];
}
/**
* Function to copy particle at location i2 in stack to i1
*/
void Swap(const int i1, const int i2) {
std::swap(fDataPID[i2], fDataPID[i1]);
std::swap(fDataE[i2], fDataE[i1]);
std::swap(fMomentum[i2], fMomentum[i1]);
std::swap(fPosition[i2], fPosition[i1]);
std::swap(fTime[i2], fTime[i1]);
}
protected:
void IncrementSize() {
fDataPID.push_back(Code::Unknown);
fDataE.push_back(0 * joule);
//#TODO this here makes no sense: see issue #48
geometry::CoordinateSystem& dummyCS =
geometry::RootCoordinateSystem::GetInstance().GetRootCS();
fMomentum.push_back(MomentumVector(
dummyCS, {0 * newton_second, 0 * newton_second, 0 * newton_second}));
fPosition.push_back(Point(dummyCS, {0 * meter, 0 * meter, 0 * meter}));
fTime.push_back(0 * second);
}
void DecrementSize() {
if (fDataE.size() > 0) {
fDataPID.pop_back();
fDataE.pop_back();
fMomentum.pop_back();
fPosition.pop_back();
fTime.pop_back();
}
}
private:
/// the actual memory to store particle data
std::vector<Code> fDataPID;
std::vector<EnergyType> fDataE;
std::vector<MomentumVector> fMomentum;
std::vector<Point> fPosition;
std::vector<TimeType> fTime;
}; // end class SuperStupidStackImpl
typedef Stack<SuperStupidStackImpl, ParticleInterface> SuperStupidStack;
} // namespace super_stupid
} // namespace corsika::stack
#endif
/**
* (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
*
* See file AUTHORS for a list of contributors.
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#include <corsika/geometry/RootCoordinateSystem.h>
#include <corsika/stack/super_stupid/SuperStupidStack.h>
#include <corsika/units/PhysicalUnits.h>
using namespace corsika::geometry;
using namespace corsika::units::si;
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one
// cpp file
#include <catch2/catch.hpp>
using namespace corsika;
using namespace corsika::stack::super_stupid;
#include <iostream>
using namespace std;
TEST_CASE("SuperStupidStack", "[stack]") {
SECTION("read+write") {
SuperStupidStack s;
auto p = s.NewParticle();
p.SetPID(particles::Code::Electron);
p.SetEnergy(1.5_GeV);
geometry::CoordinateSystem& dummyCS =
geometry::RootCoordinateSystem::GetInstance().GetRootCS();
p.SetMomentum(MomentumVector(
dummyCS, {1 * newton_second, 1 * newton_second, 1 * newton_second}));
p.SetPosition(Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}));
p.SetTime(100_s);
// read
REQUIRE(s.GetSize() == 1);
auto pout = s.GetNextParticle();
REQUIRE(pout.GetPID() == particles::Code::Electron);
REQUIRE(pout.GetEnergy() == 1.5_GeV);
#warning Fix the next two lines:
// REQUIRE(pout.GetMomentum() == MomentumVector(dummyCS, {1 * joule, 1 * joule, 1 *
// joule})); REQUIRE(pout.GetPosition() == Point(dummyCS, {1 * meter, 1 * meter, 1 *
// meter}));
REQUIRE(pout.GetTime() == 100_s);
}
SECTION("write+delete") {
SuperStupidStack s;
for (int i = 0; i < 99; ++i) s.NewParticle();
REQUIRE(s.GetSize() == 99);
for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete();
REQUIRE(s.GetSize() == 0);
}
}
add_library (CORSIKAthirdparty INTERFACE)
target_include_directories (CORSIKAthirdparty SYSTEM
INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty>
$<INSTALL_INTERFACE:include/ThirdParty>
)
install (DIRECTORY phys DESTINATION include/ThirdParty/)
install (DIRECTORY catch2 DESTINATION include/ThirdParty/)
install (DIRECTORY bitset2 DESTINATION include/ThirdParty/)
/**
@page ThirdParty
@tableofcontents
In the directory ThirdParty we provide simple dependencies. This
minimizes the need to install additional software for the user. Note
the individual copyrights and licences here!
@section PhysUnits
The PhysUnits library is an external dependency included here just for
convenience:
Original source code from:
https://github.com/martinmoene/PhysUnits-CT-Cpp11#references
Licence: BSL-1.0
(https://github.com/martinmoene/PhysUnits-CT-Cpp11/blob/master/LICENSE_1_0.txt)
References: https://github.com/martinmoene/PhysUnits-CT-Cpp11#references
@section catch2
The catch2 unit testing library is from:
https://github.com/catchorg/Catch2 Licence: BSL-1.0
(https://github.com/martinmoene/PhysUnits-CT-Cpp11/blob/master/LICENSE_1_0.txt)
References: https://github.com/catchorg/Catch2
@section eigen3
eigen3 ....
@section bitset2
see https://github.com/ClaasBontus/bitset2, this package was obtained
from a Boost Software License 1.0.
*/
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
# bitset2: bitset improved
|Note|
|----|
|This version of bitset2 is for C++17. For C++14 checkout the corresponding [branch](https://github.com/ClaasBontus/bitset2/tree/cpp14).|
Bitset2::bitset2 is a header only library. It provides the same functionality as [std::bitset](http://en.cppreference.com/w/cpp/utility/bitset) with the
following extentions/changes.
Focus was set on having as many functions
implemented as [constexpr](http://en.cppreference.com/w/cpp/language/constexpr)
as possible. Moreover a second template parameter (with appropriate default)
allows control of the underlying data structure (see below).
* Copy and move constructors are specified constexpr.
* Additional constexpr constructor `bitset2( std::array<T,N> const & )`, where `T` needs not necessarily be equal to `base_t`. `T` has to be an unsigned integral type.
* Conversion from and to `std::bitset`.
* Operators implemented as constexpr are `~`, `==`, `!=`, `|`, `&`, `^`, `<<` (shift left), `>>` (shift right), `[]` (bit access).
* Non-const operators implemented as constexpr are `<<=`, `>>=`, `|=`, `&=`, `^=`
* Functions implemented as constexpr are `test`, `none`, `any`, `all`, `count`, `to_ulong`, `to_ullong`.
* Non-const functions implemented as constexpr are `set`, `reset`, `flip`.
* Additional constexpr operator `+` for adding two bitset2 objects.
* Additional constexpr operators `++`, `--`, `+=`.
* Additional constexpr operators `<`, `>`, `<=`, `>=`.
* Additional constexpr functions `rotate_left` and `rotate_right` for binary rotations.
* Additional constexpr member functions `rotate_left` and `rotate_right`.
* Additional member function `to_hex_string()` (see below).
* Additional constexpr member function `test_set( size_t bit, bool value= true )`, which sets or clears the specified bit and returns its previous state. Throws `out_of_range` if bit >= N.
* Additional constexpr function `difference`, which computes the set difference (`bs1 & ~bs2`) of two bitset2 objects.
* Additional constexpr member function `difference`.
* Additional constexpr member functions `find_first()` and `find_next(size_t)` returning the index of the first (next) bit set. Returning npos if all (remaining) bits are false.
* Additional constexpr function `complement2(bs)` computing the [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) (~bs +1).
* Additional constexpr member function `complement2`.
* Additional constexpr function `reverse`, which returns argument with bits reversed.
* Additional constexpr member function `reverse`.
* Additional constexpr function `convert_to<n>` for converting an *m*-bit bitset2 into an *n*-bit bitset2.
* Additional constexpr function `convert_to<n,T>` for converting an *m*-bit bitset2 into an *n*-bit bitset2 with `base_t=T`.
* Constexpr member function `data()` gives read access to the underlying `array<base_t,N>`. Here element with index zero is the least significant word.
* Additional constexpr functions `zip_fold_and` and `zip_fold_or`. See below for details.
## Examples
```.cpp
#include <iostream>
#include <array>
#include <cassert>
#include "bitset2.hpp"
template<size_t n_bits>
using BS2= Bitset2::bitset2<n_bits>;
int main()
{
using bs_128= BS2<128>;
using base_t_128= bs_128::base_t;
constexpr std::array<base_t_128,2>
ar1{{ ~(base_t_128(0)), base_t_128(0xFEDCBA) }};
constexpr bs_128 b1{ ar1 };
constexpr auto b1_add= b1 + b1;
constexpr auto b1_shft= b1 << 1; // binary shift
static_assert( b1_add == b1_shft, "" );
std::cout << b1.to_hex_string() // 0000000000fedcbaffffffffffffffff
<< "\n"
<< b1_add.to_hex_string() // 0000000001fdb975fffffffffffffffe
<< "\n";
BS2<12> b2;
for( size_t c= 0; c < 12; c += 2 ) b2[c]= true;
auto b3= ~b2;
std::cout << b2 << "\n"; // 010101010101
std::cout << b2.flip() << "\n"; // 101010101010
assert( b2 == b3 );
BS2<7> const b4{ "1110000" };
auto const b5= Bitset2::rotate_left( b4, 3 );
std::cout << b4 << "\n" // 1110000
<< b5 << "\n"; // 0000111
BS2<7> b6{ "1010010" };
b6.reverse();
std::cout << b6 << "\n"; // 0100101
}
```
The following example illustrates how
[non-const constexpr](https://stackoverflow.com/q/43592862/3876684)
operators and functions are useful for writing constexpr functions.
It converts between [gray](https://en.wikipedia.org/wiki/Gray_code)
and binary coding.
```.cpp
template<size_t N,class T>
constexpr
Bitset2::bitset2<N,T>
binary_to_gray( Bitset2::bitset2<N,T> const &bs )
{ return bs ^ (bs >> 1); }
template<size_t N,class T>
constexpr
Bitset2::bitset2<N,T>
gray_to_binary( Bitset2::bitset2<N,T> bs )
{
Bitset2::bitset2<N,T> mask= bs >> 1;
for( ; !mask.none(); mask >>= 1 ) bs ^= mask;
return bs;
} // gray_to_binary
int main()
{
using ULLONG= unsigned long long;
constexpr std::array<ULLONG,2> arr_01a{{ 0xFEFDFCFBFAF9F8F7ull, 1ull }};
constexpr Bitset2::bitset2<129> bs_01a{ arr_01a };
constexpr auto gray_01a= binary_to_gray( bs_01a );
constexpr auto bin_01a= gray_to_binary( gray_01a );
static_assert( bs_01a == bin_01a, "" );
}
```
## Template parameters and underlying data type
`bitset2` is declared as
```.cpp
template< size_t N, class T >
class bitset2;
```
`N` is the number of bits and `T` has to be an unsigned
[integral type](http://en.cppreference.com/w/cpp/types/is_integral). Data
represented by `bitset2` objects are stored in elements of type
`std::array<T,n_array>`.
`T` defaults
to `uint8_t`, `uint16_t`, or `uint32_t` if `N` bits fit into these integers
(and the type is supported by the system).
`T` defaults to `unsigned long long` otherwise. The following aliases and
constants are public within `bitset2`:
* `using base_t= T;`
* `size_t n_array;` Number of words in underlying array
* `using array_t= std::array<T,n_array>;` Underlying data type
## to_hex_string
Function `to_hex_string` takes - as an optional argument - an element of type
`hex_params`, which is defined as
```.cpp
template< class CharT = char,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT> >
struct hex_params
{
using str_t= std::basic_string<CharT,Traits,Allocator>;
CharT zeroCh= CharT( '0' );
CharT aCh= CharT( 'a' );
bool leadingZeroes= true;
bool nonEmpty= true;
str_t prefix;
};
```
It allows fine tuning the outcome of the function. In the following
examples the output is shown in the comments.
```.cpp
bitset2<16> b16_a( "0000101000011111" );
bitset2<16> b16_b;
std::cout
<< b16_a.to_hex_string() << '\n' // 0a1f
<< b16_a.to_hex_string( hex_params<>{'0', 'A', false, true, "0x"}) // 0xA1F
<< '\n'
<< b16_b.to_hex_string() << '\n' // 0000
<< b16_b.to_hex_string( hex_params<>{'0', 'a', false, false, "0X"}) // 0X
<< '\n';
```
## zip\_fold\_&ast;
Functions `zip_fold_and(bs1,bs2,f)` and `zip_fold_or(bs1,bs2,f)` expect two
variables of type `bitset2` and a functional object `f`.
The latter must accept two variables of type `base_t` and return a `bool`.
`zip_fold_*` are mapped over the underlying
`std::array<base_t,n>`s. They will
[short-circuit](http://en.cppreference.com/w/cpp/language/operator_logical)
if possible, which can result in performance advantages.
`zip_fold_and` returns `true` if `f`
returns `true` for each pair of `base_t`s, while `zip_fold_or` returns `true`
if `f` returns `true` for at least one pair of `base_t`s.
In other words `zip_fold_and` and `zip_fold_or` are similar to
[`std::inner_product(...,BinOp1 op1,BinOp2 op2)`](http://en.cppreference.com/w/cpp/algorithm/inner_product)
with `op1` set to `&&` and `||`, resp.
For instance `is_subset_of` as proposed in [p0125r0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0125r0.html)
can be implemented as follows.
```.cpp
template<size_t N,class T>
constexpr
bool
is_subset_of( Bitset2::bitset2<N,T> const &bs1,
Bitset2::bitset2<N,T> const &bs2 ) noexcept
{
using base_t= T;
return Bitset2::zip_fold_and( bs1, bs2,
[]( base_t v1, base_t v2 ) noexcept
// Any bit unset in v2 must not be set in v1
{ return (v1 & ~v2) == 0; } );
}
constexpr Bitset2::bitset2<7> b7_a( 0b1000101ull );
constexpr Bitset2::bitset2<7> b7_b( 0b1010101ull );
static_assert( is_subset_of( b7_a, b7_b), "" );
```
Similarly an `unequal` function can be defined as
```.cpp
template<size_t N,class T>
bool
unequal( Bitset2::bitset2<N,T> const &bs1, Bitset2::bitset2<N,T> const &bs2 )
{
using base_t= T;
return Bitset2::zip_fold_or( bs1, bs2,
[]( base_t v1, base_t v2 ) noexcept
{ return v1 != v2; } );
}
```
## Trivia
The following code shows a counter based on a 128-bit integer. If the
counter gets incremented once at each nanosecond, you have to wait for
overflow for *only* [1.078 * 10<sup>22</sup> years](http://www.wolframalpha.com/input/?i=2%5E128+nanoseconds).
```.cpp
Bitset2::bitset2<128> c;
for( ;; ++c ) {}
```
## Caveats
* bitset2 requires a C++17 compliant compiler.
* Tested with gcc 7 and clang 5.
// BITSET2
//
// Copyright Claas Bontus
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ClaasBontus/bitset2
//
#ifndef BITSET2_CB_HPP
#define BITSET2_CB_HPP
#include "detail/hex_params.hpp"
#include "detail/select_base_t.hpp"
#include "detail/hash.hpp"
#include "detail/array_access.hpp"
#include "detail/array_funcs.hpp"
#include "detail/array_add.hpp"
#include "detail/array_ops.hpp"
#include "detail/array_complement2.hpp"
#include "detail/array2array.hpp"
#include "detail/bitset2_impl.hpp"
#include <bitset>
#include <climits>
#include <cstdint>
#include <array>
#include <stdexcept>
#include <utility>
#include <string>
#include <functional>
#include <type_traits>
namespace Bitset2
{
template<size_t N,
class T= Bitset2::detail::select_base_t<N>,
class Enabled=void> class bitset2;
template<size_t N,class T>
class bitset2<N,T,
typename std::enable_if< std::is_integral<T>::value
&& std::is_unsigned<T>::value>::type>
: public detail::bitset2_impl<N,T>
{
enum : size_t { base_t_n_bits= detail::bitset2_impl<N,T>::base_t_n_bits };
public:
using array_t= typename detail::bitset2_impl<N,T>::array_t;
using ULLONG_t= typename detail::bitset2_impl<N,T>::ULLONG_t;
using base_t= T;
using detail::bitset2_impl<N,T>::n_array;
enum : size_t { npos= detail::h_types<T>::npos };
class reference
{
friend class bitset2;
reference() noexcept {}
reference( bitset2<N,T> *ptr, size_t bit ) noexcept
: m_ptr( ptr )
, m_bit( bit )
{}
bitset2<N,T> *m_ptr= nullptr;
size_t m_bit;
public:
~reference() noexcept {}
reference& operator=( bool x ) noexcept
{
m_ptr->set_noexcept( m_bit, x );
return *this;
}
reference& operator=( reference const & r ) noexcept
{
m_ptr->set_noexcept( m_bit, bool( r ) );
return *this;
}
reference& flip() noexcept
{
m_ptr->flip_noexcept( m_bit );
return *this;
}
operator bool() const noexcept
{ return m_ptr->test_noexcept(m_bit); }
bool operator~() const noexcept
{ return !bool(*this); }
}; // class reference
/* ------------------------------------------------------------- */
constexpr
bitset2() noexcept
: detail::bitset2_impl<N,T>()
{}
constexpr
bitset2( bitset2 const & ) noexcept= default;
constexpr
bitset2( bitset2 && ) noexcept= default;
constexpr
bitset2 &
operator=( bitset2 const & ) noexcept= default;
constexpr
bitset2 &
operator=( bitset2 && ) noexcept= default;
explicit
bitset2( const std::bitset<N> &bs ) noexcept
: detail::bitset2_impl<N,T>( bs )
{}
explicit
constexpr
bitset2( ULLONG_t v ) noexcept
: detail::bitset2_impl<N,T>( v )
{}
template<size_t n,class Tsrc>
explicit
constexpr
bitset2( std::array<Tsrc,n> const & value ) noexcept
: detail::bitset2_impl<N,T>( value )
{}
template< class CharT, class Traits, class Alloc >
explicit
bitset2( std::basic_string<CharT,Traits,Alloc> const
& str,
typename std::basic_string<CharT,Traits,Alloc>::size_type
pos = 0,
typename std::basic_string<CharT,Traits,Alloc>::size_type
n = std::basic_string<CharT,Traits,Alloc>::npos,
CharT zero= CharT('0'),
CharT one= CharT('1') )
: detail::bitset2_impl<N,T>( str, pos, n, zero, one )
{}
template< class CharT >
explicit
bitset2( const CharT *str,
typename std::basic_string<CharT>::size_type
n= std::basic_string<CharT>::npos,
CharT zero= CharT('0'),
CharT one= CharT('1') )
: detail::bitset2_impl<N,T>( n == std::basic_string<CharT>::npos
? std::basic_string<CharT>( str )
: std::basic_string<CharT>( str, n ),
0, n, zero, one )
{}
/* ------------------------------------------------------------- */
//****************************************************
/// Bitwise NOT
constexpr
bitset2
operator~() const noexcept
{ return bitset2(detail::array_ops<N,T>( 0 ).flip(this->data())); }
constexpr
bool
operator[]( size_t bit ) const noexcept
{ return detail::bitset2_impl<N,T>::operator[]( bit ); }
reference
operator[]( size_t bit ) noexcept
{ return reference( this, bit ); }
constexpr
bitset2 &
operator<<=( size_t n_shift ) noexcept
{
detail::array_ops<N,T>( n_shift ).shift_left_assgn( this->get_data() );
return *this;
}
constexpr
bitset2 &
operator>>=( size_t n_shift ) noexcept
{
detail::array_ops<N,T>( n_shift ).shift_right_assgn( this->get_data() );
return *this;
}
constexpr
bitset2 &
rotate_left( size_t n_rot ) noexcept
{
this->get_data()= detail::array_ops<N,T>(n_rot).rotate_left( this->data() );
return *this;
}
constexpr
bitset2 &
rotate_right( size_t n_rot ) noexcept
{
this->get_data()= detail::array_ops<N,T>( N - ( n_rot % N ) )
.rotate_left( this->data() );
return *this;
}
constexpr
bitset2 &
reverse() noexcept
{
this->get_data()= detail::array_ops<N,T>( 0 ).reverse( this->data() );
return *this;
}
/// Computes two's complement
constexpr
bitset2 &
complement2() noexcept
{
detail::array_complement2<N,T>().comp2_assgn( this->get_data() );
return *this;
}
constexpr
bitset2 &
operator+=( bitset2 const &bs2 ) noexcept
{
detail::array_add<N,T>().add_assgn(this->get_data(), bs2.data());
return *this;
}
constexpr
bitset2 &
operator++() noexcept
{
detail::array_ops<N,T>(0).increment( this->get_data() );
return *this;
}
constexpr
bitset2
operator++(int) noexcept
{
bitset2 tmp( *this );
operator++();
return tmp;
}
constexpr
bitset2 &
operator--() noexcept
{
detail::array_ops<N,T>(0).decrement( this->get_data() );
return *this;
}
constexpr
bitset2
operator--(int) noexcept
{
bitset2 tmp( *this );
operator--();
return tmp;
}
constexpr
bitset2 &
operator|=( bitset2 const & v2 ) noexcept
{
detail::array_funcs<bitset2::n_array,T>()
.bitwise_or_assgn(this->get_data(), v2.data() );
return *this;
}
constexpr
bitset2 &
operator&=( bitset2 const & v2 ) noexcept
{
detail::array_funcs<bitset2::n_array,T>()
.bitwise_and_assgn( this->get_data(), v2.data() );
return *this;
}
constexpr
bitset2 &
operator^=( bitset2 const & v2 ) noexcept
{
detail::array_funcs<bitset2::n_array,T>()
.bitwise_xor_assgn( this->get_data(), v2.data() );
return *this;
}
/// Computes the set difference, i.e. *this &= ~v2
constexpr
bitset2 &
difference( bitset2 const & v2 ) noexcept
{
detail::array_funcs<bitset2::n_array,T>()
.bitwise_setdiff_assgn( this->get_data(), v2.data() );
return *this;
}
constexpr
bitset2 &
set() noexcept
{ detail::bitset2_impl<N,T>::set(); return *this; }
constexpr
bitset2 &
set( size_t bit, bool value= true )
{ detail::bitset2_impl<N,T>::set( bit, value ); return *this; }
constexpr
bitset2 &
reset() noexcept
{ detail::bitset2_impl<N,T>::reset(); return *this; }
constexpr
bitset2 &
reset( size_t bit )
{
if( bit >= N ) throw std::out_of_range( "bitset2: reset out of range" );
return set( bit, false );
}
/// \brief Sets the specified bit if value==true,
/// clears it otherwise. Returns the previous state of the bit.
constexpr
bool
test_set( size_t bit, bool value= true )
{ return detail::bitset2_impl<N,T>::test_set( bit, value ); }
constexpr
bitset2 &
flip() noexcept
{ detail::bitset2_impl<N,T>::flip(); return *this; }
constexpr
bitset2 &
flip( size_t bit )
{ detail::bitset2_impl<N,T>::flip( bit ); return *this; }
constexpr std::size_t size() const noexcept { return N; }
template<class CharT = char,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT> >
std::basic_string<CharT,Traits,Allocator>
to_string( CharT zero = CharT('0'), CharT one = CharT('1') ) const
{
std::basic_string<CharT,Traits,Allocator> ret_val;
ret_val.reserve( N );
for( size_t ct= N; ct > 0; )
{
--ct;
ret_val += this->operator[]( ct ) ? one : zero;
}
return ret_val;
} // to_string
template<class CharT = char,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>,
typename std::enable_if<base_t_n_bits % 4 == 0>::type* = nullptr >
std::basic_string<CharT,Traits,Allocator>
to_hex_string( hex_params<CharT,Traits,Allocator> const &params=
hex_params<CharT,Traits,Allocator>{} ) const
{
using arr_acc= detail::array_access<N,T>;
arr_acc a_a;
constexpr auto div_four= arr_acc::div_four;
constexpr auto mod_four= arr_acc::mod_four;
constexpr auto n_char= div_four + ( mod_four > 0 );
auto const zeroCh= params.zeroCh;
auto const aCh= params.aCh;
std::basic_string<CharT,Traits,Allocator> ret_val;
ret_val.reserve( n_char + params.prefix.size() );
ret_val= params.prefix;
size_t ct= n_char;
if( !params.leadingZeroes )
{
for( ; ct > 0; --ct )
{
auto const val= a_a.get_four_bits( this->data(), 4 * ct - 1 );
if( val != 0 ) break;
}
}
if( ct == 0 && params.nonEmpty ) ret_val += zeroCh;
for( ; ct > 0; --ct )
{
auto const val= a_a.get_four_bits( this->data(), 4 * ct - 1 );
CharT const c=
( val < 10 ) ? ( zeroCh + val ) : ( aCh + ( val - 10 ) );
ret_val += c;
}
return ret_val;
} // to_hex_string
}; // class bitset2
template<size_t N, class T>
constexpr
bitset2<N,T>
rotate_left( bitset2<N,T> const & bs, size_t n_rot ) noexcept
{
return
bitset2<N,T>( detail::array_ops<N,T>( n_rot ).rotate_left( bs.data() ) );
}
template<size_t N, class T>
constexpr
bitset2<N,T>
rotate_right( bitset2<N,T> const & bs, size_t n_rot ) noexcept
{
return
bitset2<N,T>( detail::array_ops<N,T>( N - ( n_rot % N ) ).
rotate_left( bs.data() ) );
}
/// Computes the set difference, i.e. bs1 & ~bs2
template<size_t N, class T>
constexpr
bitset2<N,T>
difference( bitset2<N,T> const & bs1, bitset2<N,T> const & bs2 ) noexcept
{
return
bitset2<N,T>( detail::array_funcs<bitset2<N,T>::n_array,T>()
.bitwise_setdiff( bs1.data(), bs2.data() ) );
}
/// Returns bs with bits reversed
template<size_t N, class T>
constexpr
bitset2<N,T>
reverse( bitset2<N,T> const & bs ) noexcept
{ return bitset2<N,T>( detail::array_ops<N,T>( 0 ).reverse( bs.data() ) ); }
/// Computes the two's complement
template<size_t N, class T>
constexpr
bitset2<N,T>
complement2( bitset2<N,T> const & bs ) noexcept
{ return bitset2<N,T>( detail::array_complement2<N,T>().comp2(bs.data()) ); }
/// Converts an M-bit bitset2 to an N-bit bitset2.
template<size_t N,class T1,size_t M, class T2>
constexpr
bitset2<N,T1>
convert_to( bitset2<M,T2> const & bs ) noexcept
{
using a2a=
detail::array2array<bitset2<N,T1>::n_array,bitset2<M,T2>::n_array,T1,T2>;
return
bitset2<N,T1>(a2a()(detail::bit_chars<N,T1>::hgh_bit_pattern, bs.data()));
}
/// Converts an M-bit bitset2 to an N-bit bitset2.
template<size_t N,size_t M, class T>
constexpr
bitset2<N,T>
convert_to( bitset2<M,T> const & bs ) noexcept
{ return bitset2<N,T>( bs.data() ); }
/// \brief Returns true if f returns true for each pair
/// of base_t=T values in bs1 and bs2. f should be a binary function
/// taking two base_t values and returning bool.
/// zip_fold_and does short circuit if possible.
template<size_t N, class F, class T>
constexpr
bool
zip_fold_and( bitset2<N,T> const & bs1, bitset2<N,T> const & bs2,
F f ) noexcept(noexcept( f( T(0), T(0) ) ))
{
return
detail::array_funcs<bitset2<N,T>::n_array,T>().zip_fold_and(bs1.data(),
bs2.data(), f);
}
/// \brief Returns true if f returns true for at least one pair
/// of base_t=T values in bs1 and bs2. f should be a binary function
/// taking two base_t values and returning bool.
/// zip_fold_or does short circuit if possible.
template<size_t N, class F,class T>
constexpr
bool
zip_fold_or( bitset2<N,T> const & bs1, bitset2<N,T> const & bs2,
F f ) noexcept(noexcept( f( T(0), T(0) ) ))
{
return
detail::array_funcs<bitset2<N,T>::n_array,T>().zip_fold_or( bs1.data(),
bs2.data(), f );
}
} // namespace Bitset2
/// Stream output
template <class CharT, class Traits, size_t N,class T>
std::basic_ostream<CharT, Traits>&
operator<<( std::basic_ostream<CharT, Traits> & os,
Bitset2::bitset2<N,T> const & x )
{
for( size_t ct= N; ct > 0; )
{
--ct;
os << ( x[ct] ? "1" : "0" );
}
return os;
}
/// Stream input
template <class CharT, class Traits, size_t N,class T>
std::basic_istream<CharT, Traits>&
operator>>( std::basic_istream<CharT, Traits> & is,
Bitset2::bitset2<N,T> & x )
{
std::bitset<N> bs;
is >> bs;
x= Bitset2::bitset2<N,T>( bs );
return is;
}
/// Shift left
template<size_t N,class T>
constexpr
Bitset2::bitset2<N,T>
operator<<( Bitset2::bitset2<N,T> const & bs, size_t n_shift ) noexcept
{
return
Bitset2::bitset2<N,T>( Bitset2::detail::array_ops<N,T>( n_shift )
.shift_left( bs.data() ) );
}
/// Shift right
template<size_t N,class T>
constexpr
Bitset2::bitset2<N,T>
operator>>( Bitset2::bitset2<N,T> const & bs, size_t n_shift ) noexcept
{
return
Bitset2::bitset2<N,T>( Bitset2::detail::array_ops<N,T>( n_shift )
.shift_right( bs.data() ) );
}
template<size_t N,class T>
constexpr
Bitset2::bitset2<N,T>
operator|( Bitset2::bitset2<N,T> const & bs1,
Bitset2::bitset2<N,T> const & bs2 ) noexcept
{
return
Bitset2::bitset2<N,T>(
Bitset2::detail::array_funcs<Bitset2::bitset2<N,T>::n_array,T>()
.bitwise_or( bs1.data(), bs2.data() ) );
}
template<size_t N,class T>
constexpr
Bitset2::bitset2<N,T>
operator&( Bitset2::bitset2<N,T> const & bs1,
Bitset2::bitset2<N,T> const & bs2 ) noexcept
{
return
Bitset2::bitset2<N,T>(
Bitset2::detail::array_funcs<Bitset2::bitset2<N,T>::n_array,T>()
.bitwise_and( bs1.data(), bs2.data() ) );
}
template<size_t N,class T>
constexpr
Bitset2::bitset2<N,T>
operator^( Bitset2::bitset2<N,T> const & bs1,
Bitset2::bitset2<N,T> const & bs2 ) noexcept
{
return
Bitset2::bitset2<N,T>(
Bitset2::detail::array_funcs<Bitset2::bitset2<N,T>::n_array,T>()
.bitwise_xor( bs1.data(), bs2.data() ) );
}
template<size_t N,class T>
constexpr
Bitset2::bitset2<N,T>
operator+( Bitset2::bitset2<N,T> const & bs1,
Bitset2::bitset2<N,T> const & bs2 ) noexcept
{
return
Bitset2::bitset2<N,T>(
Bitset2::detail::array_add<N,T>().add( bs1.data(), bs2.data() ) );
}
namespace std
{
template<size_t N,class T>
struct hash<Bitset2::bitset2<N,T> >
{
private:
enum : size_t
{ n_array= Bitset2::detail::bitset2_impl<N,T>::n_array };
Bitset2::detail::hash_impl<n_array,T> m_func;
public:
using argument_type= Bitset2::bitset2<N,T>;
using result_type=
typename Bitset2::detail::hash_impl<n_array,T>::result_type;
result_type operator()( argument_type const& bs ) const
{ return m_func( bs.data() ); }
}; // struct hash
} // namespace std
#endif // BITSET2_CB_HPP
// BITSET2
//
// Copyright Claas Bontus
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ClaasBontus/bitset2
//
#ifndef BITSET2_ARRAY2ARRAY_CB_HPP
#define BITSET2_ARRAY2ARRAY_CB_HPP
#include "h_types.hpp"
namespace Bitset2
{
namespace detail
{
/// \brief Convert std::array<Tsrc,src_n> to std::array<Ttrgt,trgt_n>
template<size_t trgt_n, size_t src_n, class Ttrgt, class Tsrc>
struct array2array
{
using h_t_trgt= h_types<Ttrgt>;
using h_t_src= h_types<Tsrc>;
using trgt_array_t= typename h_t_trgt::template array_t<trgt_n>;
using src_array_t= typename h_t_src:: template array_t<src_n>;
enum : size_t
{ trgt_base_n_bits= h_t_trgt::base_t_n_bits
, src_base_n_bits= h_t_src:: base_t_n_bits
};
enum : bool
{ small_to_large= ( src_base_n_bits < trgt_base_n_bits ) };
enum : size_t
{ ts_div= small_to_large ? trgt_base_n_bits / src_base_n_bits
: src_base_n_bits / trgt_base_n_bits };
enum : Tsrc
{ h_all_set= Tsrc( Ttrgt(~Ttrgt(0)) ) };
/// Applies pttrn to most significant entry in result
constexpr
trgt_array_t
operator()( Ttrgt pttrn, src_array_t const &src ) const noexcept
{
static_assert( ( small_to_large && trgt_base_n_bits % src_base_n_bits == 0)
|| (!small_to_large && src_base_n_bits % trgt_base_n_bits == 0),
"Conversion between arrays of these types not supported" );
return small_to_large
? conv_small_to_large( pttrn, src, std::make_index_sequence<trgt_n-1>() )
: conv_large_to_small( pttrn, src, std::make_index_sequence<trgt_n-1>() );
}
template<size_t ... S1>
constexpr
trgt_array_t
conv_small_to_large( Ttrgt pttrn,
src_array_t const &src,
std::index_sequence<S1...> ) const noexcept
{
return {{ get_from_smaller( S1, src, S1 * ts_div )...,
Ttrgt( get_from_smaller( trgt_n-1, src, (trgt_n-1) * ts_div )
& pttrn ) }};
}
template<size_t ... S1>
constexpr
trgt_array_t
conv_large_to_small( Ttrgt pttrn,
src_array_t const &src,
std::index_sequence<S1...> ) const noexcept
{
return
{{ get_from_larger( S1 / ts_div, S1 % ts_div, src )...,
Ttrgt( get_from_larger((trgt_n-1) / ts_div, (trgt_n-1) % ts_div, src)
& pttrn ) }};
}
constexpr
Ttrgt
get_from_smaller( size_t trgt_idx,
src_array_t const &src,
size_t src_idx,
size_t src_ct= 0,
Ttrgt so_far= Ttrgt(0) ) const noexcept
{
return ( src_ct >= ts_div || src_idx >= src_n )
? so_far
: get_from_smaller( trgt_idx, src, src_idx + 1, src_ct + 1,
so_far | Ttrgt( Ttrgt(src[src_idx])
<< (src_base_n_bits * src_ct) ) );
}
constexpr
Ttrgt
get_from_larger( size_t div_val,
size_t mod_val,
src_array_t const &src ) const noexcept
{
return ( div_val >= src_n ) ? Ttrgt(0)
: Ttrgt(Tsrc( src[div_val] >> (mod_val*trgt_base_n_bits) ) & h_all_set );
}
}; // struct array2array
} // namespace detail
} // namespace Bitset2
#endif // BITSET2_ARRAY2ARRAY_CB_HPP
// BITSET2
//
// Copyright Claas Bontus
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ClaasBontus/bitset2
//
#ifndef BITSET2_ARRAY2U_LONG_T_CB_HPP
#define BITSET2_ARRAY2U_LONG_T_CB_HPP
#include "bit_chars.hpp"
namespace Bitset2
{
namespace detail
{
/// \brief Takes a std::array 'arr' and returns a variable 'x' of type Tlong.
/// Bits in 'x' are set if corresponding bits in 'arr' are set.
template<size_t N, class T, class Tlong>
struct array2u_long_t
{
using base_t= T;
using b_c= bit_chars<N,T>;
enum : size_t
{ n_bits= N
, base_t_n_bits= b_c::base_t_n_bits
, long_t_n_bits= sizeof( Tlong ) * CHAR_BIT
, n_array= b_c::n_array
, div_val= long_t_n_bits / base_t_n_bits
, mod_val= long_t_n_bits % base_t_n_bits
, use_vals= ce_min( div_val + (mod_val!=0), n_array )
, bit_diff= mod_val == 0 ? 0 : ( base_t_n_bits - mod_val )
};
enum : base_t
{ allset= base_t( ~base_t(0) )
, h_pttrn= use_vals < n_array ? allset : ce_right_shift( allset, bit_diff )
, i_pttrn= base_t( ~h_pttrn )
};
using array_t= typename h_types<T>::template array_t<n_array>;
constexpr
Tlong
operator()( array_t const & arr ) const noexcept
{
return
base_t_n_bits >= long_t_n_bits ? Tlong( arr[0] )
: combine( Tlong(0), arr, 0 );
}
/// \brief Returns true if arr cannot be converted to Tlong.
constexpr
bool
check_overflow( array_t const & arr ) const noexcept
{ return N <= long_t_n_bits ? false : check_impl( arr, use_vals - 1 ); }
constexpr
Tlong
combine( Tlong v, array_t const & arr, size_t idx ) const noexcept
{
return ( idx >= use_vals ) ? v
: idx + 1 == use_vals
? Tlong( v + take_v( arr, idx, h_pttrn ) )
: combine( Tlong( v + take_v( arr, idx ) ), arr, idx + 1 );
}
constexpr
Tlong
take_v( array_t const & arr, size_t idx, base_t pttrn= allset ) const noexcept
{ return ce_left_shift( Tlong( arr[idx] & pttrn ), idx * base_t_n_bits ); }
constexpr
bool
check_impl( array_t const & arr, size_t idx ) const noexcept
{
return idx >= n_array ? false
: ( ( take_check( arr, idx ) != base_t(0) )
|| check_impl( arr, idx + 1 ) );
}
constexpr
base_t
take_check( array_t const & arr, size_t idx ) const noexcept
{ return arr[idx] & ( idx + 1 == use_vals ? i_pttrn : allset ); }
}; // struct array2u_long_t
} // namespace detail
} // namespace Bitset2
#endif // BITSET2_ARRAY2U_LONG_T_CB_HPP
// BITSET2
//
// Copyright Claas Bontus
//
// Use, modification and distribution is subject to the
// Boost Software License, Version 1.0. (See accompanying
// file LICENSE.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Project home: https://github.com/ClaasBontus/bitset2
//
#ifndef BITSET2_ARRAY_ACCESS_CB_HPP
#define BITSET2_ARRAY_ACCESS_CB_HPP
#include "bit_chars.hpp"
namespace Bitset2
{
namespace detail
{
/// \brief array_access is used for getting bunches of 4 bits, which is
/// needed when creating hex-strings
template<size_t N,class T>
struct array_access
{
using base_t= T;
using b_chars= bit_chars<N,T>;
enum : size_t { base_t_n_bits= b_chars::base_t_n_bits
, n_array= b_chars::n_array
};
enum : size_t { div_four= N / 4
, mod_four= N % 4
};
using array_t= typename h_types<T>::template array_t<n_array>;
constexpr
base_t
get_four_bits( array_t const &arr, size_t offset ) const noexcept
{
return
get_four_bits_impl( arr,
offset / base_t_n_bits, offset % base_t_n_bits );
}
constexpr
base_t
get_four_bits_impl( array_t const &arr,
size_t idx, size_t bit_idx ) const noexcept
{
return ( bit_idx >= 3 )
? h1_get_four_bits( arr[idx], bit_idx )
: h2_get_four_bits( arr, idx, bit_idx );
}
constexpr
base_t
h1_get_four_bits( base_t v, size_t bit_idx ) const noexcept
{ return ( v >> ( bit_idx - 3 ) ) & base_t(0xF); }
constexpr
base_t
h2_get_four_bits( array_t const &arr,
size_t idx, size_t bit_idx ) const noexcept
{
return
(( arr[idx] & ( ( base_t(1) << (bit_idx+1) ) - 1 ) ) << ( 3 - bit_idx ))
+ ( ( idx == 0 ) ? base_t(0)
: ( arr[idx-1] >> (base_t_n_bits - (3 - bit_idx)) ) );
}
}; // struct array_access
} // namespace detail
} // namespace Bitset2
#endif // BITSET2_ARRAY_ACCESS_CB_HPP