Merge pull request 'dev' (#2) from dev into main
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

Reviewed-on: chizeta/CNORXZ#2
This commit is contained in:
Christian Zimmermann 2024-02-02 19:36:53 +00:00
commit 6793fc1bdb
51 changed files with 3069 additions and 510 deletions

View file

@ -7,7 +7,7 @@ steps:
- source /opt/rh/gcc-toolset-9/enable
- mkdir build-gcc
- cd build-gcc
- cmake3 -DRUN_PIPELINE=on -DSCALAR_BUILD=on ..
- cmake3 -DSCALAR_BUILD=on ..
- make -j2
- make test
- cd ..

View file

@ -2,27 +2,44 @@ cmake_minimum_required(VERSION 3.0)
project(cnorxz)
# LIB VERSION
set(VERSION_PART "pre")
set(VERSION_TAG_HASH "6857e3fc7d0af25db3a925791d1cabc6342b930a")
# OPTIONS
option(SCALAR_BUILD "" OFF)
# INCLUDES
include(cmake/check_avx.cmake)
# GIT VARIABLES
execute_process(COMMAND bash "-c" "git rev-parse HEAD" OUTPUT_VARIABLE GIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND bash "-c" "git tag -l --sort=refname 'v*' | tail -n1" OUTPUT_VARIABLE GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND bash "-c" "git rev-list -n 1 ${GIT_TAG}" OUTPUT_VARIABLE GIT_TAG_HASH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND bash "-c" "git rev-parse --abbrev-ref HEAD" OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE)
# BUILD / CHECK VERSION STRING
message(STATUS "${GIT_HASH}")
option(RUN_PIPELINE "" OFF)
option(SCALAR_BUILD "" OFF)
if(RUN_PIPELINE)
set(VERSION "v0.0.0-test")
else()
message(STATUS "${GIT_TAG}")
message(STATUS "${GIT_TAG_HASH}")
string(SUBSTRING "${GIT_TAG}" 1 -1 VERSION)
if(NOT ("${GIT_HASH}" EQUAL "${GIT_TAG_HASH}"))
message(STATUS "${VERSION_PART}")
message(STATUS "${VERSION_TAG_HASH}")
set(VERSION "${VERSION_PART}")
if(NOT ("${GIT_BRANCH}" EQUAL "release"))
if(NOT ("${GIT_HASH}" EQUAL "${VERSION_TAG_HASH}"))
string(SUBSTRING ${GIT_HASH} 0 7 GIT_HASH_SHORT)
set(VERSION "${VERSION}-${GIT_HASH_SHORT}")
set(VERSION "${VERSION}-${GIT_BRANCH}-${GIT_HASH_SHORT}")
endif()
else()
if(NOT ("${GIT_HASH}" EQUAL "${VERSION_TAG_HASH}"))
message(FATAL_ERROR "version mash-up, do not use, contact maintainer")
endif()
endif()
message(STATUS "version = ${VERSION}")
# CHECK COMPILER
if(CMAKE_COMPILER_IS_GNUCXX)
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0)
message(FATAL_ERROR "require gcc version >= 7.0")
@ -31,10 +48,16 @@ else()
message(WARNING "compiler ${CMAKE_CXX_COMPILER_ID} officially not supported")
endif()
# FLAGS
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -std=c++17 -Wpedantic -O2 -march=native -faligned-new -funroll-loops -fopenmp")
# TESTING
enable_testing()
# INSTALL PATH
if(IS_ABSOLUTE "${CMAKE_INSTALL_PREFIX}")
set(INSTALL_PATH ${CMAKE_INSTALL_PREFIX})
else()
@ -43,6 +66,8 @@ else()
endif()
message(STATUS "found absolute install path '${INSTALL_PATH}'")
# SCALAR / INTRINSICS
if(NOT ${SCALAR_BUILD})
message(STATUS "check for intrinsics")
check_avx()
@ -55,6 +80,8 @@ if(NOT ${SCALAR_BUILD})
endif()
endif()
# CHECK LIBRARIES : GTest
message(STATUS "check for libraries")
find_package( GTest REQUIRED )
if(GTest_FOUND)
@ -63,6 +90,8 @@ else()
message(FATAL_ERROR "GTest not found")
endif()
# CHECK LIBRARIES : Threads
find_package(Threads REQUIRED)
if(Threads_FOUND)
#include_directories(${Threads_INCLUDE_DIRS})
@ -70,12 +99,16 @@ else()
message(FATAL_ERROR "Threads not found")
endif()
# CHECK LIBRARIES : hdf5
if(DEFINED ENABLE_hdf5)
set(ENABLE_hdf5 ${ENABLE_hdf5} CACHE BOOL "enable hdf5")
else()
set(ENABLE_hdf5 TRUE CACHE BOOL "enable hdf5")
endif()
# CHECK LIBRARIES : cereal
if(DEFINED ENABLE_cereal)
set(ENABLE_cereal ${ENABLE_cereal} CACHE BOOL "enable hdf5")
else()
@ -96,8 +129,12 @@ else()
endif()
endif()
# DEFINES
add_definitions(-DVERSION="${VERSION}")
add_definitions(-DGIT_COMMIT="${GIT_HASH}")
add_definitions(-DCXX_FLAGS="${CMAKE_CXX_FLAGS}")
# CONTINUE WITH SUB-DIRECTORIES
add_subdirectory(src)

View file

@ -36,9 +36,9 @@ The tools of the library are accessible within the namespace `CNORXZ`.
### Basics and Library organization
This library consists of several building blocks. For simple usage, the most important building blocks are [ranges](#ranges), [indices](#indices) and [array types](#arrays).
This library consists of several building blocks. For simple usage, the most important building blocks are [ranges](#sec-ranges), [indices](#sec-indices) and [arrays](#sec-array-types).
#### Ranges
#### Ranges {#sec-ranges}
Basically, a *range* defines a meta data space. There are several range class types, which are derived from the abstract base class `RangeBase`. Ranges can only be created by the corresponding factory and exclusively exist within a shared pointer; they cannot be copied. Available range class types are:
@ -54,7 +54,7 @@ Basically, a *range* defines a meta data space. There are several range class ty
* `YRange` : The same as `MRange` but the number of ranges and their types can be specified at runtime.
#### Indices
#### Indices {#sec-indices}
For each range type there is a corresponding index type (`CIndex`, `UIndex<MetaT>`, `SIndex<MetaT,S>`, `PIndex<IndexT>`, `MIndex<IndexTs...>`, `YIndex`). They act as const iterators on the ranges and are a crucial component to define operations on containers. In contrast to the ranges, all index types must be known at compile time (static polymorphism, `IndexInterface<Index,MetaT>`).
@ -66,7 +66,7 @@ Apart from range specific indices, there exist also special indices:
* `BIndex<T>` : The same as `AIndex`, but not const.
#### Array types
#### Array types {#sec-array-types}
Finally, there are the container classes (arrays), which are derived from `CArrayBase<T>` (const) or `ArrayBase<T>` for a given data type `T`. All arrays are defined on a range, their data can be accessed or iterated over using suitable indices. The array-type actually containing data is called `MArray<T>`. Moreover, there exist array-types that do not contain data, but view the data of other arrays or at least parts of the data. These are called `CSlice<T>` (const view) or `Slice`.

View file

@ -33,11 +33,16 @@ namespace CNORXZ
{
std::stringstream ss;
ss << "[";
auto it = a.begin();
for(; it != a.end()-1; ++it){
ss << toString(*it) << ",";
if(a.size() == 0){
ss << "]";
}
else {
auto it = a.begin();
for(; it != a.end()-1; ++it){
ss << toString(*it) << ",";
}
ss << toString(*it) << "]";
}
ss << toString(*it) << "]";
return ss.str();
}
@ -46,11 +51,16 @@ namespace CNORXZ
{
std::stringstream ss;
ss << "(";
auto it = a.begin();
for(; it != a.end()-1; ++it){
ss << toString(*it) << ",";
if constexpr(N == 0){
ss << ")";
}
else {
auto it = a.begin();
for(; it != a.end()-1; ++it){
ss << toString(*it) << ",";
}
ss << toString(*it) << ")";
}
ss << toString(*it) << ")";
return ss.str();
}
@ -73,6 +83,26 @@ namespace CNORXZ
return String("(") + toString(p.first) + "," + toString(p.second) + ")";
}
template <typename T, typename S>
String ToString<std::map<T,S>>::func(const std::map<T,S>& p)
{
std::stringstream ss;
ss << "{";
if(p.size() == 0){
ss << "}";
}
else {
auto it = p.begin();
auto e = p.end();
e--;
for(; it != e; ++it){
ss << toString(it->first) << ":" << toString(it->second) << ",";
}
ss << toString(it->first) << ":" << toString(it->second) << "}";
}
return ss.str();
}
template <typename T>
String toString(const T& a)
{

View file

@ -97,6 +97,20 @@ namespace CNORXZ
static String func(const std::pair<T,S>& t);
};
/** ***
Specialization of ToString for maps
@tparam T key type
@tparam S value type
*/
template <typename T, typename S>
struct ToString<std::map<T,S>>
{
/** cast to string
@param a map to be casted
*/
static String func(const std::map<T,S>& t);
};
/** ***
Specialization of ToString for DType
*/

View file

@ -6,7 +6,7 @@
This file contains the declaration of all library types
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -28,9 +28,9 @@
namespace CNORXZ
{
/**********************
* standard types *
**********************/
/*====================+
| standard types |
=====================*/
typedef std::intptr_t PtrId;
typedef int32_t Int;
@ -80,9 +80,9 @@ namespace CNORXZ
template <SizeT N>
using CSizeT = std::integral_constant<SizeT,N>;
/*********************
* library types *
*********************/
/*===================+
| library types |
+===================*/
/***
Naming Prefixes:
@ -302,9 +302,9 @@ namespace CNORXZ
template <class CXpr>
class Contraction;
/*********************
* derived types *
*********************/
/*===================+
| derived types |
+===================*/
template <typename T>
using Vector = std::vector<T,Allocator<T>>;

View file

@ -10,9 +10,9 @@
namespace CNORXZ
{
/**********************
* COpInterface *
**********************/
/*====================+
| COpInterface |
+====================*/
template <class OpT>
template <class F, class IndexT>
@ -37,9 +37,9 @@ namespace CNORXZ
}
/*********************
* OpInterface *
*********************/
/*===================+
| OpInterface |
+===================*/
template <class OpT>
template <class IndexT, class F, class... Args>
@ -56,9 +56,9 @@ namespace CNORXZ
}
/***************
* COpRoot *
***************/
/*=============+
| COpRoot |
+=============*/
template <typename T, class IndexT>
constexpr COpRoot<T,IndexT>::COpRoot(const CArrayBase<T>& a, const Sptr<IndexT>& ind) :
@ -123,9 +123,52 @@ namespace CNORXZ
return COpRoot<T,IndexT>(a, ind);
}
/****************
* OpCont *
****************/
/*=============+
| POpRoot |
+=============*/
template <class IndexT, class Op>
constexpr POpRoot<IndexT,Op>::POpRoot(const Sptr<IndexT>& ind, const SizeT* parts, Op&& op) :
mIndex(ind),
mFp(1,parts),
mOp(std::forward<Op>(op))
{}
template <class IndexT, class Op>
template <class PosT>
constexpr decltype(auto) POpRoot<IndexT,Op>::operator()(const PosT& pos) const
{
return mOp(mFp(pos));
}
template <class IndexT, class Op>
constexpr decltype(auto) POpRoot<IndexT,Op>::operator()() const
{
return mOp(mFp(SPos<0>()));
}
template <class IndexT, class Op>
template <SizeT I>
constexpr decltype(auto) POpRoot<IndexT,Op>::rootSteps(const IndexId<I>& id) const
{
return mIndex->stepSize(id);
}
template <class IndexT, class Op>
constexpr decltype(auto) POpRoot<IndexT,Op>::data() const
{
return mOp->data();
}
template <class IndexT, class Op>
constexpr decltype(auto) poproot(const Sptr<IndexT>& ind, const SizeT* parts, Op&& op)
{
return POpRoot(ind, parts, std::forward<Op>(op));
}
/*==============+
| OpCont |
+==============*/
template <typename T, class IndexT>
constexpr OpCont<T,IndexT>::OpCont(const Sptr<IndexT>& ind) :
@ -236,9 +279,9 @@ namespace CNORXZ
return mC.data();
}
/****************
* OpRoot *
****************/
/*==============+
| OpRoot |
+==============*/
template <typename T, class IndexT>
constexpr OpRoot<T,IndexT>::OpRoot(ArrayBase<T>& a, const Sptr<IndexT>& ind) :
@ -327,9 +370,9 @@ namespace CNORXZ
return OpRoot<T,IndexT>(a, ind);
}
/*******************
* Operation *
*******************/
/*=================+
| Operation |
+=================*/
template <class F, class... Ops>
constexpr Operation<F,Ops...>::Operation(F&& f, const Ops&... ops) :
@ -411,9 +454,9 @@ namespace CNORXZ
}
}
/*********************
* Contraction *
*********************/
/*===================+
| Contraction |
+===================*/
template <class CXpr>
constexpr Contraction<CXpr>::Contraction(CXpr&& cxpr) :
@ -447,9 +490,9 @@ namespace CNORXZ
return Contraction<CXprT>( i->ifor( op, f ) );
}
/************************
* various functions *
************************/
/*======================+
| various functions |
+======================*/
template <class IndexT>
constexpr decltype(auto) indexOp(const Sptr<IndexT>& i)

View file

@ -97,6 +97,36 @@ namespace CNORXZ
template <typename T, class IndexT>
constexpr decltype(auto) coproot(const T* a, const Sptr<IndexT>& ind);
template <class IndexT, class Op>
class POpRoot : public COpInterface<POpRoot<IndexT,Op>>
{
public:
typedef COpInterface<POpRoot<IndexT,Op>> OI;
constexpr POpRoot() = default;
constexpr POpRoot(const Sptr<IndexT>& ind, const SizeT* parts, Op&& op);
template <class PosT>
constexpr decltype(auto) operator()(const PosT& pos) const;
constexpr decltype(auto) operator()() const;
template <SizeT I>
constexpr decltype(auto) rootSteps(const IndexId<I>& id) const;
constexpr decltype(auto) data() const;
private:
Sptr<IndexT> mIndex;
FPos mFp;
Op mOp;
};
template <class IndexT, class Op>
constexpr decltype(auto) poproot(const Sptr<IndexT>& ind, const SizeT* parts, Op&& op);
template <typename T, class IndexT>
class OpCont : public OpInterface<OpCont<T,IndexT>>
{

View file

@ -2,10 +2,9 @@
/**
@file include/ranges/crange.h
@brief ...
@brief CRange and CIndex declaration.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -35,8 +34,8 @@ namespace CNORXZ
DEFAULT_MEMBERS(CIndex); /**< default constructors and assignments */
/** Construct index from range and position.
@param range Range to iterate over
@param pos lexicographic position
@param range Range to iterate over.
@param pos lexicographic position.
*/
CIndex(const RangePtr& range, SizeT pos = 0);
@ -80,7 +79,7 @@ namespace CNORXZ
SizeT operator*() const;
/** @copydoc IndexInterface::dim() */
SizeT dim() const; // = 1
SizeT dim() const;
/** @copydoc IndexInterface::range() */
Sptr<RangeType> range() const;
@ -124,30 +123,29 @@ namespace CNORXZ
Sptr<RangeType> mRangePtr;
};
/** make index pack of a CIndex and another index
@tparam type of the second index
@param a pointer to CIndex
@param b pointer to another index
/** Make index pack of a CIndex and another index.
@param a pointer to CIndex.
@param b pointer to another index.
*/
template <class I>
decltype(auto) operator*(const Sptr<CIndex>& a, const Sptr<I>& b);
/** ****
specific factory for CRange
Specific factory for CRange.
*/
class CRangeFactory : public RangeFactoryBase
{
public:
typedef CRange oType;
/** construct and setup factory
@param size size of the range to be constructed
/** Construct and setup factory.
@param size Size of the range to be constructed.
*/
CRangeFactory(SizeT size);
/** construct and setup factory
@param size size of the range to be constructed
@param ref range the range to be constructed is related to
/** Construct and setup factory.
@param size Size of the range to be constructed.
@param ref Range the range to be constructed is related to.
*/
CRangeFactory(SizeT size, RangePtr ref);

View file

@ -5,7 +5,7 @@
@brief ...
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -40,6 +40,12 @@ namespace CNORXZ
}
}
template <class I>
decltype(auto) operator*(const Sptr<DIndex>& a, const Sptr<I>& b)
{
return iptrMul(a, b);
}
template <class I>
I indexAs(const DIndex& i)
{

View file

@ -2,10 +2,9 @@
/**
@file include/ranges/dindex.h
@brief ...
@brief DIndex declaration
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -154,6 +153,13 @@ namespace CNORXZ
XIndexPtr mI;
};
/** Make index pack of a DIndex and another index.
@param a pointer to DIndex.
@param b pointer to another index.
*/
template <class I>
decltype(auto) operator*(const Sptr<DIndex>& a, const Sptr<I>& b);
/** Trait-specialization:
DIndex can have sub-indices
*/

View file

@ -5,7 +5,7 @@
@brief ...
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -20,7 +20,17 @@
namespace CNORXZ
{
/** *****
Extension Index
Elements accessed through this index in a loop
are treated and processed through a single access
allowing the usage of vector extensions
@tparam MetaT Index meta data type
@tparam S Vector size
@tparam L Static index label
*/
template <typename MetaT, SizeT S, SizeT L>
class EIndex : public LIndex<SIndex<MetaT,S>,L>
{
@ -28,9 +38,15 @@ namespace CNORXZ
typedef typename LIndex<SIndex<MetaT,S>,L>::IB IB;
typedef typename LIndex<SIndex<MetaT,S>,L>::RangeType RangeType;
DEFAULT_MEMBERS(EIndex);
DEFAULT_MEMBERS(EIndex); /**< default constructors and assignments */
EIndex(const Sptr<LIndex<SIndex<MetaT,S>,L>>& i);
/** @copydoc IndexInterface::ifor()
Specialization for EIndex: access all elements
at once, allowing usage of vector extensions
@see EFor
*/
template <class Xpr, class F>
decltype(auto) ifor(const Xpr& xpr, F&& f) const;
@ -38,6 +54,10 @@ namespace CNORXZ
Sptr<LIndex<SIndex<MetaT,S>,L>> mLI;
};
/** ***
EIndex is an index
@see is_index
*/
template <typename MetaT, SizeT S, SizeT L>
struct is_index<EIndex<MetaT,S,L>>
{
@ -53,25 +73,52 @@ namespace CNORXZ
{
static constexpr bool value = true;
};
/** Make index pack from EIndex and second index of arbitrary type
*/
template <typename MetaT, SizeT S, SizeT L, class I1>
decltype(auto) operator*(const Sptr<EIndex<MetaT,S,L>>& a, const Sptr<I1>& b);
/** Create Eindex pointer from LIndex pointer
*/
template <typename MetaT, SizeT S, SizeT L>
decltype(auto) eindexPtr(const Sptr<LIndex<SIndex<MetaT,S>,L>>& i);
/** Create Eindex pointer from SIndex pointer
@tparam L Static index label
*/
template <SizeT L, typename MetaT, SizeT S>
decltype(auto) eindexPtr(const Sptr<SIndex<MetaT,S>>& i);
/** Create Eindex pointer from LIndex pointer
@param l Static index label
*/
template <typename MetaT, SizeT S, SizeT L>
decltype(auto) eindexPtr(const Sptr<SIndex<MetaT,S>>& i, CSizeT<L> l);
/** Split given index into pack of EIndex and remainder index
@param i Index to be split
@tparam S Vector size
@tparam L1 label of EIndex
@tparam L2 label of remainder index
*/
template <SizeT S, SizeT L1, SizeT L2, class Index>
decltype(auto) eplex(const Sptr<Index>& i);
/** Split given index into pack of EIndex and remainder index
@param i Index to be split
@param s Vector size
@param l label of EIndex
*/
template <class Index, SizeT S, SizeT L>
decltype(auto) eplex(const Sptr<Index>& i, CSizeT<S> s, CSizeT<L> l);
/** Split given index into pack of EIndex and remainder index
@param i Index to be split
@param s Vector size
@param l1 label of EIndex
@param l2 label of remainder index
*/
template <class Index, SizeT S, SizeT L1, SizeT L2>
decltype(auto) eplex(const Sptr<Index>& i, CSizeT<S> s, CSizeT<L1> l1, CSizeT<L2> l2);

View file

@ -5,7 +5,7 @@
@brief ...
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -18,26 +18,51 @@
namespace CNORXZ
{
/** ****
Type trait: Check if format has static size.
*/
template <class FormatT> struct is_static_format { CXZ_CVAL_FALSE; };
/** ****
Multi index format of static size.
Wrapper of standard array of UPos.
@tparam N Format size
*/
template <SizeT N>
class MFormat
{
public:
typedef Arr<UPos,N> InputType;
SP_DEFAULT_MEMBERS(constexpr,MFormat);
SP_DEFAULT_MEMBERS(constexpr,MFormat); /**< default constructors and assignments */
/** Construct MFormat from standard array.
@param b Input array
*/
explicit constexpr MFormat(const Arr<UPos,N>& b);
/** Construct MFormat from format of arbitrary type.
The input format size has to match the static size N.
@param f Input format
*/
template <class FormatT>
constexpr MFormat(const FormatT& f);
/** Get underlying array. */
const Arr<UPos,N>& all() const;
/** Get format size. */
constexpr decltype(auto) size() const;
/** Get format element.
@param i CSizeT indicating static element position
*/
template <SizeT I>
constexpr decltype(auto) get(CSizeT<I> i) const;
/** Get format element.
@param i CSizeT indicating static element position
*/
template <SizeT I>
constexpr decltype(auto) operator[](CSizeT<I> i) const;
@ -46,27 +71,58 @@ namespace CNORXZ
};
/** ****
MFormat has static size.
@see is_static_format
*/
template <SizeT N> struct is_static_format<MFormat<N>> { CXZ_CVAL_TRUE; };
/** ****
Multi index format of static size.
Wrapper of standard tuple of position types.
@tparam PosT Position types.
*/
template <class... PosT>
class GMFormat
{
public:
typedef Tuple<PosT...> InputType;
SP_DEFAULT_MEMBERS(constexpr,GMFormat);
SP_DEFAULT_MEMBERS(constexpr,GMFormat); /**< default constructors and assignments */
/** Construct from tuple.
@param b Input tuple.
*/
explicit constexpr GMFormat(const Tuple<PosT...>& b);
/** Construct from tuple (move).
@param b Input tuple.
*/
explicit constexpr GMFormat(Tuple<PosT...>&& b);
/** Construct MFormat from format of arbitrary type.
The input format size has to match the number of entries
and the input entries have to be compatible with the position types.
@param f Input format
*/
template <class FormatT>
constexpr GMFormat(const FormatT& f);
/** Get underlying tuple. */
const Tuple<PosT...>& all() const;
/** Get format size. */
constexpr decltype(auto) size() const;
/** Get format element.
@param i CSizeT indicating static element position
*/
template <SizeT I>
constexpr decltype(auto) get(CSizeT<I> i) const;
/** Get format element.
@param i CSizeT indicating static element position
*/
template <SizeT I>
constexpr decltype(auto) operator[](CSizeT<I> i) const;
@ -74,38 +130,76 @@ namespace CNORXZ
Tuple<PosT...> mB;
};
/** Create GMFormat from position types.
@param ps Position types.
*/
template <class... PosT>
constexpr decltype(auto) gmformat(const PosT&... ps);
/** ****
GMFormat has static size.
@see is_static_format
*/
template <class... PosT> struct is_static_format<GMFormat<PosT...>> { CXZ_CVAL_TRUE; };
/** ****
Multi index format of variable size
Wrapper of standard vector of UPos.
*/
class YFormat
{
public:
typedef Vector<UPos> InputType;
DEFAULT_MEMBERS(YFormat);
DEFAULT_MEMBERS(YFormat); /**< default constructors and assignments */
/** Construct from vector.
@param b Input vector.
*/
explicit YFormat(const Vector<UPos>& b);
/** Construct from format of arbitrary type.
@param f Input format.
*/
template <class FormatT>
YFormat(const FormatT& f);
/** Get underlying vector. */
const Vector<UPos>& all() const;
/** Get format size. */
SizeT size() const;
/** Get format element.
@param i CSizeT indicating static element position
*/
template <SizeT I>
const UPos& get(CSizeT<I> i) const;
/** Get format element.
@param i CSizeT indicating static element position
*/
template <SizeT I>
const UPos& operator[](CSizeT<I> i) const;
/** Get format element.
@param i E element position
*/
const UPos& get(SizeT i) const;
/** Get format element.
@param i E element position
*/
const UPos& operator[](SizeT i) const;
private:
Vector<UPos> mB;
};
/** Check if format is trivial, i.e. f[i-1] = f[i]*s[i].
@param f Vector representing the index format.
@param s Vector representing the sub-index maxima.
*/
bool formatIsTrivial(const Vector<SizeT>& f, const Vector<SizeT>& s);
}

View file

@ -2,10 +2,11 @@
/**
@file include/ranges/index_mul.h
@brief ...
@brief Index multiplication
Indices can be multiplied yielding index packs.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -35,30 +36,71 @@ namespace CNORXZ
Isq<Is...> is, Isq<Js...> js);
};
/** Combine two indices to a static index 2-pack.
@param a First index.
@param b Second index.
@return Static index 2-pack
*/
template <class I1, typename Meta1, class I2, typename Meta2>
inline decltype(auto) operator*(const IndexInterface<I1,Meta1>& a,
const IndexInterface<I2,Meta2>& b);
/** Extend static index pack on the l.h.s.
@param a Index to be appended.
@param b Index pack to be extended.
@return Extended pack.
*/
template <class I1, typename Meta1, class... Indices>
inline decltype(auto) operator*(const IndexInterface<I1,Meta1>& a,
const SPack<Indices...>& b);
/** Extend static index pack on the r.h.s.
@param a Index pack to be extended.
@param b Index to be appended.
@return Extended pack.
*/
template <class I2, typename Meta2, class... Indices>
inline decltype(auto) operator*(const SPack<Indices...>& a,
const IndexInterface<I2,Meta2>& b);
/** Combine two static index packs
@param a First Index pack.
@param b Second Index pack.
@return New index pack. a is appended on the l.h.s. of b.
*/
template <class... Indices1, class... Indices2>
inline decltype(auto) operator*(const SPack<Indices1...>& a, const SPack<Indices2...>& b);
/** Extend dynamic index pack on the l.h.s.
@param a Index to be appended.
@param b Index pack to be extended.
@return Extended pack.
*/
template <class I1, typename Meta1>
inline decltype(auto) operator*(const IndexInterface<I1,Meta1>& a, const DPack& b);
/** Extend dynamic index pack on the r.h.s.
@param a Index pack to be extended.
@param b Index to be appended.
@return Extended pack.
*/
template <class I2, typename Meta2>
inline decltype(auto) operator*(const DPack& a, const IndexInterface<I2,Meta2>& b);
/** Combine two dynamic index packs
@param a First Index pack.
@param b Second Index pack.
@return New index pack. a is appended on the l.h.s. of b.
*/
inline decltype(auto) operator*(const DPack& a, const DPack& b);
/** Combine two index pointers to an index 2-pack.
YIndices and DIndices will be combined into a DPack,
otherwise a SPack is returned.
@param a First index.
@param b Second index.
@return Index 2-pack.
*/
template <class I1, class I2>
decltype(auto) iptrMul(const Sptr<I1>& a, const Sptr<I2>& b);
}

View file

@ -4,7 +4,7 @@
@file include/ranges/index_traits.h
@brief index traits
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2023 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/

View file

@ -1,29 +0,0 @@
// -*- C++ -*-
/**
@file include/ranges/index_utils.h
@brief ...
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_index_utils_h__
#define __cxz_index_utils_h__
#include "base/base.h"
#include "index_base.h"
namespace CNORXZ
{
// automatically set static format if SIndices are used!
template <class... Indices>
constexpr decltype(auto) autoiPtr(const SPack<Indices...>& pack);
inline SPtr<YIndex> autoiPtr(const DPack& pack);
}
#endif

View file

@ -2,10 +2,12 @@
/**
@file include/ranges/lindex.h
@brief ...
@brief Statically labeled index.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Static index labels are usefull to resolve extensions and relations to
other indices at compile time.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -20,7 +22,11 @@
namespace CNORXZ
{
// static label to enforce loop unrolling
/** ****
Statically labeled index.
@tparam Index Underlying index.
@tparam L Static label.
*/
template <class Index, SizeT L>
class LIndex : public Index
{
@ -28,14 +34,25 @@ namespace CNORXZ
typedef typename Index::IB IB;
typedef typename Index::RangeType RangeType;
DEFAULT_MEMBERS(LIndex);
DEFAULT_MEMBERS(LIndex); /**< Default constructors and assignments. */
/** Construct from index pointer.
@param i Input index.
*/
LIndex(const Sptr<Index>& i);
/** @copydoc IndexInterface::id()
Specialization: Static id equals L.
*/
IndexId<L> id() const;
/** @copydoc IndexInterface::stepSize()
Specialization: stepSize may be static.
*/
template <SizeT I>
decltype(auto) stepSize(const IndexId<I>& id) const;
/** @copydoc IndexInterface::stepSize() */
template <class Xpr, class F>
decltype(auto) ifor(const Xpr& xpr, F&& f) const;
@ -43,6 +60,10 @@ namespace CNORXZ
Sptr<Index> mI;
};
/** ***
LIndex is an index
@see is_index
*/
template <class Index, SizeT L>
struct is_index<LIndex<Index,L>>
{
@ -59,12 +80,27 @@ namespace CNORXZ
static constexpr bool value = index_expression_exists<Index>::value;
};
/** Specialize index multiplication for LIndex.
@param a Pointer to first index which is a LIndex.
@param b Pointer to second index of arbitrary type.
@return Resulting index pack.
*/
template <class Index, SizeT L, class I1>
decltype(auto) operator*(const Sptr<LIndex<Index,L>>& a, const Sptr<I1>& b);
/** Create LIndex from index pointer.
@param i Input index.
@tparam L Static label.
@return Resulting LIndex.
*/
template <SizeT L, class Index>
decltype(auto) lindexPtr(const Sptr<Index>& i);
/** Create LIndex from index pointer.
@param i Input index.
@param l CSizeT indicating the static label.
@return Resulting LIndex.
*/
template <class Index, SizeT L>
decltype(auto) lindexPtr(const Sptr<Index>& i, CSizeT<L> l);
}

View file

@ -2,10 +2,10 @@
/**
@file include/ranges/mrange.cc.h
@brief ...
@brief MRange, GMIndex and MIndex, member definition.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -21,9 +21,9 @@
namespace CNORXZ
{
/************************
* GMIndex (private) *
************************/
/*=========================+
| GMIndex (private) |
+=========================*/
template <class FormatT, class... Indices>
template <SizeT... Is>
@ -147,9 +147,9 @@ namespace CNORXZ
}
}
/***************
* GMIndex *
***************/
/*===============+
| GMIndex |
+===============*/
template <class FormatT, class... Indices>
constexpr GMIndex<FormatT,Indices...>::GMIndex(const GMIndex& i) :
@ -551,15 +551,21 @@ namespace CNORXZ
GMIndex<FormatT,Indices...>&
GMIndex<FormatT,Indices...>::reformat(const Vector<SizeT>& f, const Vector<SizeT>& s)
{
// f: input format
// s: input sizes
CXZ_ASSERT(f.size() == s.size(), "input error: f.size() != s.size()");
if(f.size() == 1){
CXZ_ASSERT(s[0] == lmax().val(), "got inconsistent size; expeected "
<< lmax().val() << ", got " << s[0]);
return *this;
}
if constexpr(std::is_same<FormatT,None>::value){
CXZ_ASSERT(CNORXZ::formatIsTrivial(f,s),
"cannot reformat MIndex with format type = None");
return *this;
}
else {
CXZ_ASSERT(f.size() == s.size(), "input error: f.size() != s.size()");
// f: input format
// s: input sizes
SizeT j = 0;
SizeT j0 = 0;
SizeT xi = 1;
@ -590,9 +596,7 @@ namespace CNORXZ
mIPack[i]->reformat(nf,ns);
}
else {
// TODO: IMPLEMENT!!!
// check trivial format in this partition
CXZ_ERROR("reformating with lower-dimensional formats has not yet been implemented");
CXZ_ERROR("reformating with lower-dimensional formats is not possible; use sub-indices instead");
}
}, NoF {});
mFormat = FormatT(nformat);
@ -609,15 +613,6 @@ namespace CNORXZ
return *this;
}
template <class BT1, class BT2, class... Indices>
decltype(auto) replaceFormat(const BT1& bs1, const Sptr<GMIndex<BT2,Indices...>>& gmi)
{
return iter<0,sizeof...(Indices)>
( [&](auto i) { return gmi->pack()[CSizeT<i>{}]; },
[&](const auto&... e) { return std::make_shared<GMIndex<BT1,Indices...>>
( bs1, e... ); } );
}
template <class... Indices>
constexpr decltype(auto) mindex(const Sptr<Indices>&... is)
{
@ -648,9 +643,9 @@ namespace CNORXZ
return iptrMul(a, b);
}
/*********************
* MRangeFactory *
*********************/
/*=====================+
| MRangeFactory |
+=====================*/
template <class... Ranges>
MRangeFactory<Ranges...>::MRangeFactory(const Tuple<Sptr<Ranges>...>& rs) :
@ -679,9 +674,9 @@ namespace CNORXZ
}
}
/**************
* MRange *
**************/
/*==============+
| MRange |
+==============*/
template <class... Ranges>
MRange<Ranges...>::MRange(const Tuple<Sptr<Ranges>...>& rs) :
@ -699,7 +694,6 @@ namespace CNORXZ
template <class... Ranges>
MArray<RangePtr> MRange<Ranges...>::sub() const
{
// TODO: ZRange (meta and index pos static!)
if constexpr(NR == 0) {
return MArray<RangePtr>();
}
@ -787,9 +781,9 @@ namespace CNORXZ
return k;
}
/************************
* MRange (private) *
************************/
/*========================+
| MRange (private) |
+========================*/
template <class... Ranges>
decltype(auto) MRange<Ranges...>::mkA() const
@ -798,9 +792,9 @@ namespace CNORXZ
[](const auto&... xs) { return Arr<RangePtr,NR> { xs... }; } );
}
/****************************
* non-member functions *
****************************/
/*============================+
| non-member functions |
+============================*/
template <class... Ranges>
RangePtr mrange(const Sptr<Ranges>&... rs)

View file

@ -2,10 +2,15 @@
/**
@file include/ranges/mrange.h
@brief ...
@brief MRange, GMIndex and MIndex declaration.
MRange is a multi-range consisting of of a compile-time fixed number of sub-ranges.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
GMIndex and MIndex are multi-index consisting of a compile-time fixed number of sub-indices.
The difference between the two index types is that MIndex has a statically trivial format,
while GMIndex can have an arbitrary format (MFormat or GMFormat).
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -22,8 +27,13 @@
namespace CNORXZ
{
// template <class FormatT, class... Indices>
// -> Format + IndexTuple
/** ****
Multi-index with fixed number of sub-indices of arbitrary type
and arbitrary index format.
@tparam FormatT Index format type.
@tparam Indices Sub-index types.
*/
template <class FormatT, class... Indices>
class GMIndex : public IndexInterface<GMIndex<FormatT,Indices...>,
Tuple<typename Indices::MetaType...> >
@ -32,75 +42,146 @@ namespace CNORXZ
typedef IndexInterface<GMIndex<FormatT,Indices...>,
Tuple<typename Indices::MetaType...>> IB;
//typedef Tuple<Sptr<Indices>...> IndexPack;
typedef Tuple<typename Indices::MetaType...> MetaType;
typedef MRange<typename Indices::RangeType...> RangeType;
static constexpr SizeT NI = sizeof...(Indices);
INDEX_RANDOM_ACCESS_ITERATOR_DEFS(MetaType);
/** Default constructor. */
constexpr GMIndex() = default;
/** Move constructor (default). */
constexpr GMIndex(GMIndex&& i) = default;
/** Move assignment (default). */
constexpr GMIndex& operator=(GMIndex&& i) = default;
// no defaults:
/** Copy constructor (no default, copy sub-index instances). */
constexpr GMIndex(const GMIndex& i);
/** Copy assignment (no default, copy sub-index instances). */
constexpr GMIndex& operator=(const GMIndex& i);
/** Construct from index pack. */
constexpr GMIndex(const SPack<Indices...>& pack);
/** Construct from index pack and format. */
constexpr GMIndex(const FormatT& format, const SPack<Indices...>& pack);
/** Construct from index pointers. */
constexpr GMIndex(const Sptr<Indices>&... is);
/** Construct from index pointers and format. */
constexpr GMIndex(const FormatT& format, const Sptr<Indices>&... is);
/** Construct from range. */
constexpr GMIndex(const RangePtr& range, SizeT lexpos = 0);
/** Construct from range and format. */
constexpr GMIndex(const RangePtr& range, const FormatT& format, SizeT lexpos = 0);
/** @copydoc IndexInterface::operator=(SizeT) */
GMIndex& operator=(SizeT pos);
/** @copydoc IndexInterface::operator++() */
GMIndex& operator++();
/** @copydoc IndexInterface::operator--() */
GMIndex& operator--();
/** @copydoc IndexInterface::operator+() */
GMIndex operator+(Int n) const;
/** @copydoc IndexInterface::operator-() */
GMIndex operator-(Int n) const;
/** @copydoc IndexInterface::operator-(CIndex) */
SizeT operator-(const GMIndex& i) const;
/** @copydoc IndexInterface::operator+=() */
GMIndex& operator+=(Int n);
/** @copydoc IndexInterface::operator-=() */
GMIndex& operator-=(Int n);
/** @copydoc IndexInterface::lex() */
SizeT lex() const;
/** @copydoc IndexInterface::pmax() */
constexpr decltype(auto) pmax() const;
/** @copydoc IndexInterface::lmax() */
constexpr decltype(auto) lmax() const;
/** @copydoc IndexInterface::id() */
IndexId<0> id() const;
/** @copydoc IndexInterface::operator*() */
MetaType operator*() const;
/** @copydoc IndexInterface::dim() */
constexpr SizeT dim() const;
/** @copydoc IndexInterface::range() */
Sptr<RangeType> range() const;
/** @copydoc IndexInterface::stepSize() */
template <SizeT I>
decltype(auto) stepSize(const IndexId<I>& id) const;
/** @copydoc IndexInterface::stringMeta() */
String stringMeta() const;
/** @copydoc IndexInterface::meta() */
MetaType meta() const;
/** @copydoc IndexInterface::at() */
GMIndex& at(const MetaType& metaPos);
decltype(auto) xpr(const Sptr<MIndex<Indices...>>& _this) const;
template <class Xpr, class F>
constexpr decltype(auto) ifor(const Xpr& xpr, F&& f) const;
// replace sub-index instances; only use if you know what you are doing!
GMIndex& operator()(const Sptr<MIndex<Indices...>>& mi);
GMIndex& operator()();
const SPack<Indices...>& pack() const;
const auto& format() const;
const auto& lexFormat() const;
/** @copydoc IndexInterface::prange() */
RangePtr prange(const GMIndex<FormatT,Indices...>& last) const;
/** @copydoc IndexInterface::deepFormat() */
auto deepFormat() const;
/** @copydoc IndexInterface::deepMax() */
auto deepMax() const;
/** @copydoc IndexInterface::reformat() */
GMIndex& reformat(const Vector<SizeT>& f, const Vector<SizeT>& s);
GMIndex& setFormat(const FormatT& bs);
/** @copydoc IndexInterface::ifor() */
template <class Xpr, class F>
constexpr decltype(auto) ifor(const Xpr& xpr, F&& f) const;
/** @copydoc IndexInterface::formatIsTrivial() */
bool formatIsTrivial() const;
/** @copydoc IndexInterface::xpr() */
decltype(auto) xpr(const Sptr<MIndex<Indices...>>& _this) const;
// replace sub-index instances; only use if you know what you are doing!
/** Replace sub-index instances and update index position correspondingly.
@param new index instances.
*/
GMIndex& operator()(const Sptr<MIndex<Indices...>>& mi);
/** Update index position according to the sub-indices. */
GMIndex& operator()();
/** Get index pack. */
const SPack<Indices...>& pack() const;
/** Get index format. */
const auto& format() const;
/** Get lexicographic index format. */
const auto& lexFormat() const;
/** Assign new index format. */
GMIndex& setFormat(const FormatT& bs);
private:
template <SizeT... Is>
static constexpr decltype(auto) mkLexFormat(const SPack<Indices...>& ipack, Isq<Is...> is);
@ -135,53 +216,114 @@ namespace CNORXZ
PMaxT mPMax;
};
template <class BT1, class BT2, class... Indices>
decltype(auto) replaceFormat(const BT1& bs1, const Sptr<GMIndex<BT2,Indices...>>& gmi);
template <class... Indices>
struct index_has_const_size<MIndex<Indices...>>
/** ****
Specialization of index_has_const_size for GMIndex.
@see index_has_const_size
*/
template <class FormatT, class... Indices>
struct index_has_const_size<GMIndex<FormatT,Indices...>>
{ static constexpr bool value = (index_has_const_size<Indices>::value and ...); };
template <class... Indices>
struct index_const_size<MIndex<Indices...>>
/** ****
Specialization of index_const_size for GMIndex.
@see index_const_size
*/
template <class FormatT, class... Indices>
struct index_const_size<GMIndex<FormatT,Indices...>>
{ static constexpr SizeT value = (index_const_size<Indices>::value * ...); };
template <class... Indices>
struct index_dim<MIndex<Indices...>>
/** ****
Specialization of index_dim for GMIndex.
@see index_dim
*/
template <class FormatT, class... Indices>
struct index_dim<GMIndex<FormatT,Indices...>>
{ static constexpr SizeT value = sizeof...(Indices); };
template <class... Indices>
struct has_sub<MIndex<Indices...>>
/** ****
Specialization of has_sub for GMIndex.
@see has_sub
*/
template <class FormatT, class... Indices>
struct has_sub<GMIndex<FormatT,Indices...>>
{ static constexpr bool value = true; };
template <class... Indices>
struct has_static_sub<MIndex<Indices...>>
/** ****
Specialization of has_static_sub for GMIndex.
@see has_static_sub
*/
template <class FormatT, class... Indices>
struct has_static_sub<GMIndex<FormatT,Indices...>>
{ static constexpr bool value = true; };
template <class... Indices>
struct index_is_multi<MIndex<Indices...>>
/** ****
Specialization of index_is_multi for GMIndex.
@see index_is_multi
*/
template <class FormatT, class... Indices>
struct index_is_multi<GMIndex<FormatT,Indices...>>
{ static constexpr bool value = true; };
/** ***
MIndex can be used as expression if all its sub-indices can be used as expression
@see index_expression_exists
*/
template <class... Indices>
struct index_expression_exists<MIndex<Indices...>>
{
static constexpr bool value = (index_expression_exists<Indices>::value and ...);
};
/** Create MIndex from index pointers.
@param is Input index pointers.
*/
template <class... Indices>
constexpr decltype(auto) mindex(const Sptr<Indices>&... is);
/** Create MIndex from index pack.
@param pack Pack of input indices.
*/
template <class... Indices>
constexpr decltype(auto) mindex(const SPack<Indices...>& pack);
/** Create pointer to MIndex from index pack.
@param pack Pack of input indices.
*/
template <class... Indices>
constexpr decltype(auto) mindexPtr(const SPack<Indices...>& pack);
/** Create pointer to GMIndex from index pack and format.
@param bs Index format.
@param pack Pack of input indices.
*/
template <class FormatT, class... Indices>
constexpr decltype(auto) gmindexPtr(const FormatT& bs, const SPack<Indices...>& pack);
/** Specialization for index multiplication with GMIndex on the l.h.s.
@param a First index of type GMIndex.
@param b Second index of arbitrary type.
*/
template <class I1, class FormatT, class... Indices>
decltype(auto) operator*(const Sptr<GMIndex<FormatT,Indices...>>& a, const Sptr<I1>& b);
/** ****
Specific factory for MRange.
@tparam Ranges Types of the sub-ranges.
*/
template <class... Ranges>
class MRangeFactory : public RangeFactoryBase
{
public:
/** Construct and setup factory.
@param rs Tuple of sub-ranges.
*/
MRangeFactory(const Tuple<Sptr<Ranges>...>& rs);
/** Construct and setup factory.
@param rs Tuple of sub-ranges.
@param ref Range the range to be constructed is related to.
*/
MRangeFactory(const Tuple<Sptr<Ranges>...>& rs, const RangePtr& ref);
private:
@ -191,7 +333,11 @@ namespace CNORXZ
Tuple<Sptr<Ranges>...> mRs;
RangePtr mRef;
};
/** ****
Multi Range with compile-time fixed number of sub-ranges
of compile-time fixed type.
*/
template <class... Ranges>
class MRange : public RangeInterface<MRange<Ranges...>>
{
@ -211,19 +357,35 @@ namespace CNORXZ
virtual const TypeInfo& type() const override final;
virtual const TypeInfo& metaType() const override final;
virtual RangePtr extend(const RangePtr& r) const override final;
/** Get sub-ranges. */
decltype(auto) space() const;
/** Get sub-range.
@param pos Position of the sub-range.
*/
const MetaType get(SizeT pos) const;
/** Get lexicographic position according to the given meta data value.
@param metaPos Meta data value.
*/
SizeT getMeta(const MetaType& metaPos) const;
protected:
/** Dafault constructor */
MRange() = default;
MRange(const MRange& in) = delete;
MRange& operator=(const MRange& in) = delete;
/** Construct from sub-ranges
@param rs Tuple of pointers to sub-ranges.
*/
MRange(const Tuple<Sptr<Ranges>...>& rs);
Tuple<Sptr<Ranges>...> mRs;
Arr<RangePtr,NR> mA;
Tuple<Sptr<Ranges>...> mRs; /**< Tuple of pointers to sub-ranges. */
Arr<RangePtr,NR> mA; /**< Array of abstract base pointers to sub-ranges. Redundant to mRs */
virtual Vector<Uuid> key() const override final;
private:
@ -231,24 +393,22 @@ namespace CNORXZ
decltype(auto) mkA() const;
};
/** Create MRange pointer.
@param rs Pointer to sub-ranges.
*/
template <class... Ranges>
RangePtr mrange(const Sptr<Ranges>&... rs);
/** ****
Specialization of RangeCast for MRange.
@see RangeCast.
*/
template <class... Ranges>
struct RangeCast<MRange<Ranges...>>
{
static Sptr<MRange<Ranges...>> func(const RangePtr& r);
};
/** ***
MIndex can be used as expression if all its sub-indices can be used as expression
@see index_expression_exists
*/
template <class... Indices>
struct index_expression_exists<MIndex<Indices...>>
{
static constexpr bool value = (index_expression_exists<Indices>::value and ...);
};
}

View file

@ -2,10 +2,9 @@
/**
@file include/ranges/prange.cc.h
@brief ...
@brief PRange, PRangeFactory and PIndex implementations.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -18,9 +17,9 @@
namespace CNORXZ
{
/**************
* PIndex *
**************/
/*============+
| PIndex |
+============*/
template <class IndexT>
PIndex<IndexT>::PIndex(const RangePtr& range, SizeT pos) :
@ -206,9 +205,7 @@ namespace CNORXZ
template <class IndexT>
decltype(auto) PIndex<IndexT>::xpr(const Sptr<PIndex<IndexT>>& _this) const
{
CXZ_ERROR("implement!!!");
//return poperation( _this, mOrig, mRangePtr->parts(), mOrig->xpr(mOrig) );
return mOrig->xpr(mOrig);
return poproot( _this, mRangePtr->parts(), mOrig->xpr(mOrig) );
}
template <class IndexT>
@ -246,9 +243,9 @@ namespace CNORXZ
return mOrig;
}
/************************
* PIndex (private) *
************************/
/*======================+
| PIndex (private) |
+======================*/
template <class IndexT>
void PIndex<IndexT>::mkPos()
@ -264,9 +261,9 @@ namespace CNORXZ
CXZ_ERROR("meta position '" << toString(mOrig->meta()) << "' not part of range");
}
/***************************
* PIndex (non-member) *
***************************/
/*=========================+
| PIndex (non-member) |
+=========================*/
template <class I, class I1>
decltype(auto) operator*(const Sptr<PIndex<I>>& a, const Sptr<I1>& b)
@ -274,9 +271,9 @@ namespace CNORXZ
return iptrMul(a, b);
}
/*********************
* PRangeFactory *
*********************/
/*===================+
| PRangeFactory |
+===================*/
template <class RangeT>
PRangeFactory<RangeT>::PRangeFactory(const Sptr<RangeT>& range, const Vector<SizeT>& _parts) :
@ -301,9 +298,9 @@ namespace CNORXZ
}
}
/**************
* PRange *
**************/
/*============+
| PRange |
+============*/
template <class RangeT>
SizeT PRange<RangeT>::size() const
@ -338,10 +335,19 @@ namespace CNORXZ
template <class RangeT>
RangePtr PRange<RangeT>::extend(const RangePtr& r) const
{
CXZ_ERROR("implement!!!");
// if r is PRange of same Range, then just add parts
// else derive and add meta of r
return nullptr;
if(r->type() == type()){
Sptr<PRange<RangeT>> rx = std::dynamic_pointer_cast<PRange<RangeT>>(r);
if(rx->orig() == orig()){
Vector<SizeT> p(parts());
for(auto i: rx->parts()){
if(find(p.begin(), p.end(), i) != p.end()){
p.push_back(i);
}
}
return prange(orig(), p);
}
}
return derive()->extend(r);
}
template <class RangeT>
@ -361,16 +367,17 @@ namespace CNORXZ
{
Vector<MetaType> meta(this->size());
auto i = mRange->begin();
SizeT j = 0;
for(const auto& p: mParts){
meta = *(i = p);
meta[j++] = *(i = p);
}
return URangeFactory<MetaType>( meta ).create();
}
/************************
* PRange (private) *
************************/
/*======================+
| PRange (private) |
+======================*/
template <class RangeT>
PRange<RangeT>::PRange(const Sptr<RangeT>& range, const Vector<SizeT>& _parts) :
@ -386,9 +393,9 @@ namespace CNORXZ
return Vector<Uuid> { mRange->id() };
}
/****************************
* non-member functions *
****************************/
/*==========================+
| non-member functions |
+==========================*/
template <class RangeT>
RangePtr prange(const Sptr<RangeT>& range, const Vector<SizeT>& parts)

View file

@ -2,10 +2,9 @@
/**
@file include/ranges/prange.h
@brief ...
@brief PRange, PRangeFactory and PIndex declaration.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -20,7 +19,10 @@
namespace CNORXZ
{
/** ****
Index specific for PRange.
@tparam IndexT Full index type.
*/
template <class IndexT>
class PIndex : public IndexInterface<PIndex<IndexT>,typename IndexT::MetaType>
{
@ -30,51 +32,105 @@ namespace CNORXZ
typedef PRange<typename IndexT::RangeType> RangeType;
typedef typename IndexT::MetaType MetaType;
/** Constructor.
@param range Range to define index on.
@param pos Initial lexicographic position (default = 0).
*/
PIndex(const RangePtr& range, SizeT pos = 0);
/** @copydoc IndexInterface::operator=(SizeT) */
PIndex& operator=(SizeT lexpos);
/** @copydoc IndexInterface::operator++() */
PIndex& operator++();
/** @copydoc IndexInterface::operator--() */
PIndex& operator--();
/** @copydoc IndexInterface::operator+() */
PIndex operator+(Int n) const;
/** @copydoc IndexInterface::operator-() */
PIndex operator-(Int n) const;
/** @copydoc IndexInterface::operator-(PIndex) */
SizeT operator-(const PIndex& i) const;
/** @copydoc IndexInterface::operator+=() */
PIndex& operator+=(Int n);
/** @copydoc IndexInterface::operator-=() */
PIndex& operator-=(Int n);
/** @copydoc IndexInterface::lex() */
SizeT lex() const;
/** @copydoc IndexInterface::pmax() */
UPos pmax() const;
/** @copydoc IndexInterface::lmax() */
UPos lmax() const;
/** @copydoc IndexInterface::id() */
IndexId<0> id() const;
/** @copydoc IndexInterface::operator*() */
decltype(auto) operator*() const;
/** @copydoc IndexInterface::dim() */
SizeT dim() const;
/** @copydoc IndexInterface::range() */
Sptr<RangeType> range() const;
/** @copydoc IndexInterface::stepSize() */
template <SizeT I>
UPos stepSize(const IndexId<I>& id) const;
/** @copydoc IndexInterface::stringMeta() */
String stringMeta() const;
/** @copydoc IndexInterface::meta() */
decltype(auto) meta() const;
/** @copydoc IndexInterface::at() */
PIndex& at(const MetaType& metaPos);
/** @copydoc IndexInterface::prange() */
RangePtr prange(const PIndex<IndexT>& last) const;
/** @copydoc IndexInterface::deepFormat() */
decltype(auto) deepFormat() const;
/** @copydoc IndexInterface::deepMax() */
decltype(auto) deepMax() const;
/** @copydoc IndexInterface::reformat() */
PIndex& reformat(const Vector<SizeT>& f, const Vector<SizeT>& s);
String stringMeta() const;
decltype(auto) meta() const;
PIndex& at(const MetaType& metaPos);
decltype(auto) xpr(const Sptr<PIndex<IndexT>>& _this) const;
/** @copydoc IndexInterface::ifor() */
template <class Xpr, class F>
decltype(auto) ifor(const Xpr& xpr, F&& f) const;
PIndex& operator()();
PIndex& operator()(const Sptr<IndexT>& i);
const Sptr<IndexT>& orig() const;
/** @copydoc IndexInterface::formatIsTrivial() */
bool formatIsTrivial() const;
/** @copydoc IndexInterface::xpr() */
decltype(auto) xpr(const Sptr<PIndex<IndexT>>& _this) const;
/** Replace instance of index on full range and update current position accordingly.
@param i New index instance.
*/
PIndex& operator()(const Sptr<IndexT>& i);
/** Update current index position according to the internal index on the full range. */
PIndex& operator()();
/** Get original index.
@return Index corresponding to original range and current position.
*/
const Sptr<IndexT>& orig() const;
private:
Sptr<RangeType> mRangePtr;
Sptr<IndexT> mOrig;
@ -82,14 +138,31 @@ namespace CNORXZ
void mkPos();
};
/** Make index pack of a PIndex and another index.
@param a pointer to PIndex.
@param b pointer to another index.
*/
template <class I, class I1>
decltype(auto) operator*(const Sptr<PIndex<I>>& a, const Sptr<I1>& b);
/** ****
Specific factory for PRange.
*/
template <class RangeT>
class PRangeFactory : public RangeFactoryBase
{
public:
/** Construct and setup factory.
@param range Full range (explicit type) the constructed range is part of.
@param _parts Integer vector indicating the parts w.r.t. input range to be covered by the PRange.
*/
PRangeFactory(const Sptr<RangeT>& range, const Vector<SizeT>& _parts);
/** Construct and setup factory.
@param range Full range the constructed range is part of.
@param _parts Integer vector indicating the parts of the full range.
*/
PRangeFactory(const RangePtr& range, const Vector<SizeT>& _parts);
private:
@ -99,7 +172,14 @@ namespace CNORXZ
Sptr<RangeT> mRange;
Vector<SizeT> mParts;
};
/** ****
Partial Range.
Ranges of these kind represent a part of a given range (full range).
Using a mathematical nomenclature, this would be called a "sub-range".
(The prefix "sub", as well as the letter "S" are, however, already extensively
used in other contexts.)
*/
template <class RangeT>
class PRange : public RangeInterface<PRange<RangeT>>
{
@ -117,8 +197,20 @@ namespace CNORXZ
virtual const TypeInfo& metaType() const override final;
virtual RangePtr extend(const RangePtr& r) const override final;
/** Get the full range.
@return Pointer to the full range.
*/
Sptr<RangeT> orig() const;
/** Get the parts.
@return Integer vector indicating the parts contained by the PRange w.r.t. the full range.
*/
const Vector<SizeT>& parts() const;
/** Create a new range of the type of the full range but containing only
the parts covered by the PRange.
@return The created range.
*/
RangePtr derive() const;
private:
@ -133,6 +225,11 @@ namespace CNORXZ
Vector<SizeT> mParts;
};
/** Create a PRange.
Internally calls PRangeFactory.
@param range Range to create a PRange on.
@param parts Integer vector indicating the parts w.r.t. input range to be covered by the PRange.
*/
template <class RangeT>
RangePtr prange(const Sptr<RangeT>& range, const Vector<SizeT>& parts);

View file

@ -2,10 +2,9 @@
/**
@file include/ranges/ranges.h
@brief ...
@brief Ranges main header
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/

View file

@ -2,10 +2,9 @@
/**
@file include/ranges/srange.h
@brief ...
@brief SRange, SRangeFactory and SIndex declaration.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -20,6 +19,11 @@
namespace CNORXZ
{
/** ****
Specific index for SRange.
@tparam MetaT Meta data type.
@tparam S Static size of the range.
*/
template <typename MetaT, SizeT S>
class SIndex : public IndexInterface<SIndex<MetaT,S>,MetaT>
{
@ -29,43 +33,88 @@ namespace CNORXZ
typedef MetaT MetaType;
INDEX_RANDOM_ACCESS_ITERATOR_DEFS(MetaType);
DEFAULT_MEMBERS(SIndex);
DEFAULT_MEMBERS(SIndex); /**< default constructors and assignments */
/** Construct index from range and position.
@param range Range to iterate over.
@param pos lexicographic position.
*/
SIndex(const RangePtr& range, SizeT pos = 0);
/** @copydoc IndexInterface::operator=(SizeT) */
SIndex& operator=(SizeT lexpos);
/** @copydoc IndexInterface::operator++() */
SIndex& operator++();
/** @copydoc IndexInterface::operator--() */
SIndex& operator--();
/** @copydoc IndexInterface::operator+() */
SIndex operator+(Int n) const;
/** @copydoc IndexInterface::operator-() */
SIndex operator-(Int n) const;
/** @copydoc IndexInterface::operator-(SIndex) */
SizeT operator-(const SIndex& i) const;
/** @copydoc IndexInterface::operator+=() */
SIndex& operator+=(Int n);
/** @copydoc IndexInterface::operator-=() */
SIndex& operator-=(Int n);
/** @copydoc IndexInterface::lex() */
SizeT lex() const;
/** @copydoc IndexInterface::pmax() */
SPos<S> pmax() const;
/** @copydoc IndexInterface::lmax() */
SPos<S> lmax() const;
/** @copydoc IndexInterface::id() */
IndexId<0> id() const;
/** @copydoc IndexInterface::operator*() */
const MetaT& operator*() const;
/** @copydoc IndexInterface::dim() */
SizeT dim() const; // = 1
/** @copydoc IndexInterface::range() */
Sptr<RangeType> range() const;
/** @copydoc IndexInterface::stepSize() */
template <SizeT I>
UPos stepSize(const IndexId<I>& id) const;
/** @copydoc IndexInterface::stringMeta() */
String stringMeta() const;
const MetaT& meta() const;
SIndex& at(const MetaT& metaPos);
decltype(auto) xpr(const Sptr<SIndex<MetaType,S>>& _this) const;
/** @copydoc IndexInterface::meta() */
const MetaT& meta() const;
/** @copydoc IndexInterface::at() */
SIndex& at(const MetaT& metaPos);
/** @copydoc IndexInterface::prange() */
RangePtr prange(const SIndex<MetaType,S>& last) const;
/** @copydoc IndexInterface::deepFormat() */
SizeT deepFormat() const;
/** @copydoc IndexInterface::deepMax() */
SizeT deepMax() const;
/** @copydoc IndexInterface::reformat() */
SIndex& reformat(const Vector<SizeT>& f, const Vector<SizeT>& s);
/** @copydoc IndexInterface::ifor() */
decltype(auto) xpr(const Sptr<SIndex<MetaType,S>>& _this) const;
/** @copydoc IndexInterface::ifor() */
template <class Xpr, class F>
decltype(auto) ifor(const Xpr& xpr, F&& f) const;
@ -77,16 +126,43 @@ namespace CNORXZ
const MetaT* mMetaPtr;
};
/** Make index pack of a SIndex and another index.
@param a pointer to SIndex.
@param b pointer to another index.
*/
template <typename MetaT, SizeT S, class I1>
decltype(auto) operator*(const Sptr<SIndex<MetaT,S>>& a, const Sptr<I1>& b);
/** ****
Specific factory for SRange.
@tparam MetaT Meta data type.
@tparam S Static size of the range.
*/
template <typename MetaT, SizeT S>
class SRangeFactory : public RangeFactoryBase
{
public:
/** Construct and setup factory.
@param space Meta data array defining the range.
*/
SRangeFactory(const Arr<MetaT,S>& space);
/** Construct and setup factory.
@param space Meta data array defining the range (move).
*/
SRangeFactory(Arr<MetaT,S>&& space);
/** Construct and setup factory.
@param space Meta data array defining the range.
@param ref Range the range to be constructed is related to.
*/
SRangeFactory(const Arr<MetaT,S>& space, const RangePtr& ref);
/** Construct and setup factory.
@param space Meta data array defining the range (move).
@param ref Range the range to be constructed is related to.
*/
SRangeFactory(Arr<MetaT,S>&& space, const RangePtr& ref);
private:
@ -97,6 +173,12 @@ namespace CNORXZ
RangePtr mRef;
};
/** ****
Static size range.
The same as URange, but the range size is compile-time fixed.
@tparam MetaT Meta data type.
@tparam S Static range size.
*/
template <typename MetaT, SizeT S>
class SRange : public RangeInterface<SRange<MetaT,S>>
{
@ -114,8 +196,19 @@ namespace CNORXZ
virtual const TypeInfo& metaType() const override final;
virtual RangePtr extend(const RangePtr& r) const override final;
/** return meta data at given position.
@param pos position, size type
*/
const MetaT& get(SizeT pos) const;
/** Get underlying meta data array.
@return Pointer to first position of meta data array.
*/
const MetaT* get() const;
/** return position for given meta data.
@param metaPos meta data, size type
*/
SizeT getMeta(const MetaT& metaPos) const;
private:
@ -132,9 +225,16 @@ namespace CNORXZ
SERIALIZATION_FUNCTIONS_NOPUB;
};
/** ***
Specialize RangeCast for casts to SRange
@see RangeCast
@tparam MetaT Meta data type.
@tparam S Static range size.
*/
template <typename MetaT, SizeT S>
struct RangeCast<SRange<MetaT,S>>
{
/** cast the range */
static Sptr<SRange<MetaT,S>> func(const RangePtr& r);
};

View file

@ -299,7 +299,10 @@ namespace CNORXZ
{
auto b = mSpace.begin();
auto e = mSpace.end();
return std::lower_bound(b, e, meta, std::less<MetaT>()) - b;
auto i = std::lower_bound(b, e, meta, std::less<MetaT>());
CXZ_ASSERT(i != e, "element with meta data = " << toString(meta) << " not in range"); // check this first, otherwise the next test may potentially result in a seg fault!
CXZ_ASSERT(*i == meta, "element with meta data = " << toString(meta) << " not in range");
return i - b;
}
template <typename MetaT>

View file

@ -2,10 +2,9 @@
/**
@file include/ranges/urange.h
@brief ...
@brief URange, URangeFactory and UIndex declaration.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -23,6 +22,10 @@
namespace CNORXZ
{
/** ****
Specific index for URange.
@tparam MetaT Meta data type.
*/
template <typename MetaT>
class UIndex : public IndexInterface<UIndex<MetaT>,MetaT>
{
@ -33,51 +36,94 @@ namespace CNORXZ
typedef MetaT MetaType;
INDEX_RANDOM_ACCESS_ITERATOR_DEFS(MetaType);
DEFAULT_MEMBERS(UIndex);
DEFAULT_MEMBERS(UIndex); /**< default constructors and assignments */
/** Construct index from range and position.
@param range Range to iterate over.
@param pos lexicographic position.
*/
UIndex(const RangePtr& range, SizeT pos = 0);
/** @copydoc IndexInterface::operator=(SizeT) */
UIndex& operator=(SizeT lexpos);
/** @copydoc IndexInterface::operator++() */
UIndex& operator++();
/** @copydoc IndexInterface::operator--() */
UIndex& operator--();
/** @copydoc IndexInterface::operator+() */
UIndex operator+(Int n) const;
/** @copydoc IndexInterface::operator-() */
UIndex operator-(Int n) const;
/** @copydoc IndexInterface::operator-(UIndex) */
SizeT operator-(const UIndex& i) const;
/** @copydoc IndexInterface::operator+=() */
UIndex& operator+=(Int n);
/** @copydoc IndexInterface::operator-=() */
UIndex& operator-=(Int n);
/** @copydoc IndexInterface::lex() */
SizeT lex() const;
/** @copydoc IndexInterface::pmax() */
UPos pmax() const;
/** @copydoc IndexInterface::lmax() */
UPos lmax() const;
/** @copydoc IndexInterface::id() */
IndexId<0> id() const;
/** @copydoc IndexInterface::operator*() */
const MetaT& operator*() const;
/** @copydoc IndexInterface::dim() */
SizeT dim() const; // = 1
/** @copydoc IndexInterface::range() */
Sptr<RangeType> range() const;
/** @copydoc IndexInterface::stepSize() */
template <SizeT I>
decltype(auto) stepSize(const IndexId<I>& id) const;
/** @copydoc IndexInterface::stringMeta() */
String stringMeta() const;
const MetaT& meta() const;
UIndex& at(const MetaT& metaPos);
decltype(auto) xpr(const Sptr<UIndex<MetaType>>& _this) const;
/** @copydoc IndexInterface::meta() */
const MetaT& meta() const;
/** @copydoc IndexInterface::at() */
UIndex& at(const MetaT& metaPos);
/** @copydoc IndexInterface::prange() */
RangePtr prange(const UIndex<MetaType>& last) const;
/** @copydoc IndexInterface::deepFormat() */
SizeT deepFormat() const;
/** @copydoc IndexInterface::deepMax() */
SizeT deepMax() const;
/** @copydoc IndexInterface::reformat() */
UIndex& reformat(const Vector<SizeT>& f, const Vector<SizeT>& s);
/** @copydoc IndexInterface::ifor() */
template <class Xpr, class F>
decltype(auto) ifor(const Xpr& xpr, F&& f) const;
/** @copydoc IndexInterface::formatIsTrivial() */
bool formatIsTrivial() const;
/** @copydoc IndexInterface::xpr() */
decltype(auto) xpr(const Sptr<UIndex<MetaType>>& _this) const;
private:
Sptr<RangeType> mRangePtr;
const MetaT* mMetaPtr;
@ -86,26 +132,39 @@ namespace CNORXZ
template <typename MetaT>
void swap(UIndex<MetaT>& a, UIndex<MetaT>& b) { a.swap(b); }
template <typename MetaType, class I1>
decltype(auto) operator*(const Sptr<UIndex<MetaType>>& a, const Sptr<I1>& b);
/** Make index pack of a UIndex and another index.
@param a pointer to UIndex.
@param b pointer to another index.
*/
template <typename MetaT, class I1>
decltype(auto) operator*(const Sptr<UIndex<MetaT>>& a, const Sptr<I1>& b);
template <typename MetaType>
/** ****
Specific factory for URange.
@tparam MetaT Meta data type.
*/
template <typename MetaT>
class URangeFactory : public RangeFactoryBase
{
public:
URangeFactory(const Vector<MetaType>& space);
URangeFactory(Vector<MetaType>&& space);
URangeFactory(const Vector<MetaType>& space, const RangePtr& ref);
URangeFactory(Vector<MetaType>&& space, const RangePtr& ref);
URangeFactory(const Vector<MetaT>& space);
URangeFactory(Vector<MetaT>&& space);
URangeFactory(const Vector<MetaT>& space, const RangePtr& ref);
URangeFactory(Vector<MetaT>&& space, const RangePtr& ref);
private:
URangeFactory() = default;
virtual void make() override final;
Vector<MetaType> mSpace;
Vector<MetaT> mSpace;
RangePtr mRef;
};
/** ****
Uni-(1-)dimensional range with non-trivial meta data space
i.e. the parameter space can be arbitrary.
@tparam MetaT Meta data type.
*/
template <typename MetaT>
class URange : public RangeInterface<URange<MetaT>>
{
@ -123,8 +182,21 @@ namespace CNORXZ
virtual const TypeInfo& metaType() const override final;
virtual RangePtr extend(const RangePtr& r) const override final;
/** Get meta data at given range position.
@param pos Integer indicating requested position.
@return Meta data at given postion.
*/
const MetaType& get(SizeT pos) const;
/** Get meta data array.
@return Pointer to first element of the underlying meta data array.
*/
const MetaType* get() const;
/** Get range position for given meta data.
@param metaPos Meta data.
@return Position of the given meta data if it is contained by the range.
*/
SizeT getMeta(const MetaType& metaPos) const;
private:
@ -141,12 +213,21 @@ namespace CNORXZ
SERIALIZATION_FUNCTIONS_NOPUB;
};
/** ***
Specialize RangeCast for casts to URange
@see RangeCast
*/
template <typename MetaType>
struct RangeCast<URange<MetaType>>
{
/** cast the range */
static Sptr<URange<MetaType>> func(const RangePtr& r);
};
/** Create an URange, calls URangeFactory.
@param space Meta data space to create an URange on.
@return Created range.
*/
template <typename MetaT>
RangePtr urange(const Vector<MetaT>& space);

View file

@ -2,10 +2,9 @@
/**
@file include/ranges/xindex.h
@brief ...
@brief XIndexBase and XIndex template declaration.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
@ -20,66 +19,145 @@
namespace CNORXZ
{
/** ****
Abstract index wrapper base.
Can be used for index polymorphism.
Only use if absolutely necessary, indices should always reveal as much as possible
to the compiler!
*/
class XIndexBase
{
public:
//typedef DType MetaType;
DEFAULT_MEMBERS(XIndexBase);
DEFAULT_MEMBERS(XIndexBase); /**< default constructors and assignments */
/** Virtual default destructor */
virtual ~XIndexBase() = default;
/** Copy this index
@return Pointer to the copy.
*/
virtual XIndexPtr copy() const = 0;
/** Current position.
@return Current position.
*/
virtual SizeT pos() const = 0;
/** @copydoc IndexInterface::operator=(SizeT) */
virtual XIndexBase& operator=(SizeT lexpos) = 0;
/** @copydoc IndexInterface::operator++() */
virtual XIndexBase& operator++() = 0;
/** @copydoc IndexInterface::operator--() */
virtual XIndexBase& operator--() = 0;
/** @copydoc IndexInterface::operator+() */
virtual XIndexPtr operator+(Int n) const = 0;
/** @copydoc IndexInterface::operator-() */
virtual XIndexPtr operator-(Int n) const = 0;
/** @copydoc IndexInterface::operator-(UIndex) */
virtual SizeT operator-(const XIndexBase& i) const = 0;
/** @copydoc IndexInterface::operator+=() */
virtual XIndexBase& operator+=(Int n) = 0;
/** @copydoc IndexInterface::operator-=() */
virtual XIndexBase& operator-=(Int n) = 0;
/** @copydoc IndexInterface::lex() */
virtual SizeT lex() const = 0;
/** @copydoc IndexInterface::pmax() */
virtual UPos pmax() const = 0;
/** @copydoc IndexInterface::lmax() */
virtual UPos lmax() const = 0;
/** @copydoc IndexInterface::id() */
virtual IndexId<0> id() const = 0;
/** @copydoc IndexInterface::operator*() */
virtual DType operator*() const = 0;
/** @copydoc IndexInterface::dim() */
virtual SizeT dim() const = 0;
virtual RangePtr range() const = 0;
virtual UPos stepSize(const IndexId<0>& id) const = 0;
virtual RangePtr prange(const XIndexPtr& last) const = 0;
virtual Vector<SizeT> deepFormat() const = 0;
virtual Vector<SizeT> deepMax() const = 0;
virtual XIndexBase& reformat(const Vector<SizeT>& f, const Vector<SizeT>& s) = 0;
/** @copydoc IndexInterface::range() */
virtual RangePtr range() const = 0;
/** @copydoc IndexInterface::stepSize() */
virtual UPos stepSize(const IndexId<0>& id) const = 0;
/** @copydoc IndexInterface::stringMeta() */
virtual String stringMeta() const = 0;
/** @copydoc IndexInterface::meta() */
virtual DType meta() const = 0;
/** @copydoc IndexInterface::at() */
virtual XIndexBase& at(const DType& meta) = 0;
/** @copydoc IndexInterface::prange() */
virtual RangePtr prange(const XIndexPtr& last) const = 0;
/** @copydoc IndexInterface::deepFormat() */
virtual Vector<SizeT> deepFormat() const = 0;
/** @copydoc IndexInterface::deepMax() */
virtual Vector<SizeT> deepMax() const = 0;
/** @copydoc IndexInterface::reformat() */
virtual XIndexBase& reformat(const Vector<SizeT>& f, const Vector<SizeT>& s) = 0;
/** @copydoc IndexInterface::ifor() */
virtual DXpr<None> ifor(const DXpr<None>& xpr, NoF&& f) const = 0;
/** @copydoc IndexInterface::formatIsTrivial() */
virtual bool formatIsTrivial() const = 0;
};
//Sptr<XIndexBase>& operator++(Sptr<XIndexBase>& i);
//Sptr<XIndexBase>& operator--(Sptr<XIndexBase>& i);
// MultiIndex Wrapper:
/** ****
Index Wrapper.
@tparam Index Type of index to be wrapped.
@tparam Meta Meta data type of wrapped index.
*/
template <class Index, typename Meta>
class XIndex : public XIndexBase
{
public:
DEFAULT_C(XIndex);
// no default copy/assignment (have to copy objects in shared ptr)
DEFAULT_C(XIndex); /** < default constructor. */
/** Copy constructor.
No default: have to copy objects in shared ptr.
*/
XIndex(const XIndex& i);
/** Move constructor.
*/
XIndex(XIndex&& i);
/** Copy assignment.
No default: have to copy objects in shared ptr.
*/
XIndex& operator=(const XIndex& i);
/** Move assignment.
*/
XIndex& operator=(XIndex&& i);
/** Construct.
@param i Pointer to index to be wrapped.
*/
XIndex(const IndexPtr<Index,Meta>& i);
/** Construct.
@param i Index to be wrapped.
*/
XIndex(const IndexInterface<Index,Meta>& i);
virtual XIndexPtr copy() const override final;
@ -104,20 +182,24 @@ namespace CNORXZ
virtual SizeT dim() const override final;
virtual RangePtr range() const override final;
virtual UPos stepSize(const IndexId<0>& id) const override final;
virtual String stringMeta() const override final;
virtual DType meta() const override final;
virtual XIndexBase& at(const DType& meta) override final;
virtual RangePtr prange(const XIndexPtr& last) const override final;
virtual Vector<SizeT> deepFormat() const override final;
virtual Vector<SizeT> deepMax() const override final;
virtual XIndex& reformat(const Vector<SizeT>& f, const Vector<SizeT>& s) override final;
virtual String stringMeta() const override final;
virtual DType meta() const override final;
virtual XIndexBase& at(const DType& meta) override final;
virtual DXpr<None> ifor(const DXpr<None>& xpr, NoF&& f) const override final;
virtual bool formatIsTrivial() const override final;
/** Get underlying index instance.
@return Reference to index.
*/
Index& get();
/** Get underlying index instance (const).
@return Reference to index.
*/
const Index& get() const;
private:
@ -125,13 +207,28 @@ namespace CNORXZ
};
/** ****
Specialization: has_sub for XIndexBase.
XIndexBase can have sub-indices.
@see has_sub.
*/
template <>
struct has_sub<XIndexBase>
{ static constexpr bool value = true; };
/** Create XIndex pointer.
@param i Index to be wrapped.
@return Pointer to created index wrapper.
*/
template <class Index>
inline XIndexPtr xindexPtr(const Sptr<Index>& i);
/** Specialization of xindexPtr().
If input index type is already a XIndex, the corresponding pointer is just passed.
This is to avoid unwanted chains of index wrappers.
@param i Input index.
@return i.
*/
template <>
inline XIndexPtr xindexPtr<XIndexBase>(const Sptr<XIndexBase>& i);

View file

@ -2,8 +2,7 @@
/**
@file include/ranges/yrange.h
@brief ...
@brief YRange and YIndex declaration
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
@ -24,6 +23,13 @@
namespace CNORXZ
{
/** ****
Specific index for YRanges.
A YIndex is a multi-index which consists of a set of sub-indices
and a format. In the case the index is used to access data, this format
determines the linearized memory position for a given sub-index combination.
*/
class YIndex : public IndexInterface<YIndex,Vector<DType>>
{
public:
@ -32,59 +38,160 @@ namespace CNORXZ
typedef Vector<DType> MetaType;
INDEX_RANDOM_ACCESS_ITERATOR_DEFS(MetaType);
/** Default constructor. */
YIndex() = default;
/** Move constructor. */
YIndex(YIndex&& i) = default;
/** Move assignment. */
YIndex& operator=(YIndex&& i) = default;
// no defaults:
/** Copy constructor.
No default copy: Have to copy sub-index instances
*/
YIndex(const YIndex& i);
/** Copy assigment.
No default copy: Have to copy sub-index instances
*/
YIndex& operator=(const YIndex& i);
/** Construct from sub-index pointers.
@param is Vector of XIndex pointers.
*/
YIndex(const Vector<XIndexPtr>& is);
/** Construct from sub-index pointers, specify index format.
@param bs Index format (YFormat).
@param is Vector of XIndex pointers.
*/
YIndex(const YFormat& bs, const Vector<XIndexPtr>& is);
/** Construct from a range and an initial lexicographic position
@param range Range to iterate over.
@param lexpos Initial lexicographic position.
*/
YIndex(const RangePtr& range, SizeT lexpos = 0);
/** Construct from a range and an initial lexicographic position, specify format.
@param range Range to iterate over.
@param bs Index format.
@param lexpos Initial lexicographic position.
*/
YIndex(const RangePtr& range, const YFormat& bs, SizeT lexpos = 0);
/** @copydoc IndexInterface::operator=(SizeT) */
YIndex& operator=(SizeT lexpos);
/** @copydoc IndexInterface::operator++() */
YIndex& operator++();
/** @copydoc IndexInterface::operator--() */
YIndex& operator--();
YIndex operator+(Int n) const; // equivalent to applying n times ++
/** @copydoc IndexInterface::operator+() */
YIndex operator+(Int n) const;
/** @copydoc IndexInterface::operator-() */
YIndex operator-(Int n) const;
/** @copydoc IndexInterface::operator-(CIndex) */
SizeT operator-(const YIndex& i) const;
/** @copydoc IndexInterface::operator+=() */
YIndex& operator+=(Int n);
/** @copydoc IndexInterface::operator-=() */
YIndex& operator-=(Int n);
/** @copydoc IndexInterface::lex() */
SizeT lex() const;
/** @copydoc IndexInterface::pmax() */
UPos pmax() const;
/** @copydoc IndexInterface::lmax() */
UPos lmax() const;
/** @copydoc IndexInterface::id() */
IndexId<0> id() const;
/** @copydoc IndexInterface::operator*() */
Vector<DType> operator*() const;
/** @copydoc IndexInterface::dim() */
SizeT dim() const;
/** @copydoc IndexInterface::range() */
Sptr<YRange> range() const;
/** @copydoc IndexInterface::stepSize() */
UPos stepSize(const IndexId<0> id) const;
/** @copydoc IndexInterface::stringMeta() */
String stringMeta() const;
/** @copydoc IndexInterface::meta() */
Vector<DType> meta() const;
/** @copydoc IndexInterface::at() */
YIndex& at(const Vector<DType>& meta);
/** @copydoc IndexInterface::prange() */
RangePtr prange(const YIndex& last) const;
/** @copydoc IndexInterface::deepFormat() */
Vector<SizeT> deepFormat() const;
/** @copydoc IndexInterface::deepMax() */
Vector<SizeT> deepMax() const;
/** @copydoc IndexInterface::reformat() */
YIndex& reformat(const Vector<SizeT>& f, const Vector<SizeT>& s);
/** @copydoc IndexInterface::ifor() */
DXpr<None> ifor(const DXpr<None>& xpr, NoF&& f) const;
YIndex& operator()(const Sptr<YIndex>& i);
YIndex& operator()();
const DPack& pack() const;
RangePtr prange(const YIndex& last) const;
Vector<SizeT> deepFormat() const;
Vector<SizeT> deepMax() const;
const YFormat& format() const;
const YFormat& lexFormat() const;
YIndex& setFormat(const YFormat& bs);
YIndex& reformat(const Vector<SizeT>& f, const Vector<SizeT>& s);
/** @copydoc IndexInterface::formatIsTrivial() */
bool formatIsTrivial() const;
/** Replace sub-index instances.
All linearized positions are updated accordingly.
@param i Pointer to YIndex which provides the new sub-index instance
*/
YIndex& operator()(const Sptr<YIndex>& i);
/** Update all linearized positions. */
YIndex& operator()();
/** Get all sub-indices
@return Pack of sub-indices
*/
const DPack& pack() const;
/** Get index format.
@return The format.
*/
const YFormat& format() const;
/** Get lexicographic (trivial) index format.
@return The lexicographic format.
*/
const YFormat& lexFormat() const;
/** Set the index format.
@param bs The new format.
*/
YIndex& setFormat(const YFormat& bs);
/** Set position of given sub index and update total index position.
@param ind Sub-index number [0,dim()-1].
@param lex Lexicographic position to be assigned to the index.
*/
YIndex& setSub(SizeT ind, SizeT lex);
private:
inline Vector<SizeT> mkFormat() const;
inline Vector<SizeT> mkLexFormat() const;
@ -107,26 +214,80 @@ namespace CNORXZ
UPos mLMax = 0;
};
/** ****
Specialization: YIndex is a multi-index.
@see index_is_multi
*/
template <>
struct index_is_multi<YIndex>
{ static constexpr bool value = true; };
/** ****
Specialization: YIndex has sub-indices.
@see has_sub
*/
template <>
struct has_sub<YIndex>
{ static constexpr bool value = true; };
/** Create YIndex from an index pack assuming a trivial index format.
@param pack Dynamic index pack.
@return The created YIndex.
*/
YIndex yindex(const DPack& pack);
/** Create YIndex from sub-indices assuming a trivial index format.
@param is Vector of pointers to the sub-indices used in the YIndex.
@return The created YIndex.
*/
YIndex yindex(const Vector<XIndexPtr>& is);
/** Create YIndex from an index pack assuming a trivial index format.
@param pack Dynamic index pack.
@return A shared pointer to the created YIndex.
*/
Sptr<YIndex> yindexPtr(const DPack& is);
/** Create YIndex from sub-indices assuming a trivial index format.
@param is Vector of pointers to the sub-indices used in the YIndex.
@return A shared pointer to the created YIndex.
*/
Sptr<YIndex> yindexPtr(const Vector<XIndexPtr>& is);
/** Create YIndex from sub-indices.
@param is Vector of pointers to the sub-indices used in the YIndex.
@param bs Index format.
@return A shared pointer to the created YIndex.
*/
Sptr<YIndex> yindexPtr(const Vector<SizeT>& bs, const Vector<XIndexPtr>& is);
/** ****
Specific factory for YRange.
*/
class YRangeFactory : public RangeFactoryBase
{
public:
/** Construct and setup factory.
@param rvec Vector of ranges i.e. the sub-ranges the YRange consists of
*/
YRangeFactory(const Vector<RangePtr>& rvec);
/** Construct and setup factory.
@param rvec Vector of ranges i.e. the sub-ranges the YRange consists of (move)
*/
YRangeFactory(Vector<RangePtr>&& rvec);
/** Construct and setup factory.
@param rvec Vector of ranges i.e. the sub-ranges the YRange consists of
@param ref Range the range to be constructed is related to
*/
YRangeFactory(const Vector<RangePtr>& rvec, const RangePtr& ref);
/** Construct and setup factory.
@param rvec Vector of ranges i.e. the sub-ranges the YRange consists of (move)
@param ref Range the range to be constructed is related to
*/
YRangeFactory(Vector<RangePtr>&& rvec, const RangePtr& ref);
private:
@ -138,6 +299,13 @@ namespace CNORXZ
};
/** ****
Dynamic multi-dimensional range
Dimension and sub-range types are determined at runtime
The size of the range is given by the product of the
sizes of all sub-ranges.
*/
class YRange : public RangeInterface<YRange>
{
public:
@ -169,8 +337,16 @@ namespace CNORXZ
SERIALIZATION_FUNCTIONS_NOPUB;
};
/** Create YRange from sub-ranges.
@param rs Vector of pointers to the sub-ranges used by the YRange.
@return A shared pointer to the created YRange.
*/
RangePtr yrange(const Vector<RangePtr>& rs);
/** ****
Specialize RangeCast for casts to YRange.
@see RangeCast
*/
template <>
struct RangeCast<YRange>
{

View file

@ -334,12 +334,13 @@ namespace CNORXZ
YIndex& YIndex::at(const Vector<DType>& meta)
{
assert(meta.size() == mIs.size());
IB::mPos = 0;
CXZ_ASSERT(meta.size() == mIs.size(), "input meta size ("
<< meta.size() << ") different from expected size ("
<< mIs.size() << ")");
for(SizeT i = 0; i != mIs.size(); ++i){
mIs[i]->at(meta[i]);
IB::mPos += mIs[i]->pos() * mFormat[i].val();
}
mkPos();
return *this;
}
@ -415,9 +416,15 @@ namespace CNORXZ
YIndex& YIndex::reformat(const Vector<SizeT>& f, const Vector<SizeT>& s)
{
CXZ_ASSERT(f.size() == s.size(), "input error: f.size() != s.size()");
// f: input format
// s: input sizes
CXZ_ASSERT(f.size() == s.size(), "input error: f.size() != s.size()");
if(f.size() == 1){
CXZ_ASSERT(s[0] == lmax().val(), "got inconsistent size; expeected "
<< lmax().val() << ", got " << s[0]);
return *this;
}
SizeT j = 0;
SizeT j0 = 0;
SizeT xi = 1;
@ -427,9 +434,7 @@ namespace CNORXZ
xi *= mIs[i]->lmax().val();
SizeT xj = s[j];
if(xi < xj) {
// TODO: IMPLEMENT!!!
// check trivial format in this partition
CXZ_ERROR("reformating with lower-dimensional formats has not yet been implemented");
CXZ_ERROR("reformating with lower-dimensional formats is not possible; use sub-indices instead");
continue;
}
j0 = j;
@ -489,6 +494,19 @@ namespace CNORXZ
return *this;
}
YIndex& YIndex::setSub(SizeT ind, SizeT lex)
{
CXZ_ASSERT(ind < dim(), "got index number (" << ind << ") larger than dimension ("
<< dim() << ")");
auto& idx = mIs[ind];
CXZ_ASSERT(lex < idx->lmax().val(), "tried to set sub-index position " << lex
<< ", which is out of scope; maximum position in range is " << idx->lmax().val() );
(*idx) = lex;
(*this)();
return *this;
}
/****************************
* non-member functions *
****************************/

View file

@ -1,4 +1,16 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/cnorxz_hdf5.cc.h
@brief CNORXZ HDF5 template sources header
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "h5_content_base.cc.h"
#include "h5_type_id.cc.h"
#include "h5_group.cc.h"
#include "h5_table.cc.h"
#include "h5_dataset.cc.h"

View file

@ -1,8 +1,19 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/cnorxz_hdf5.h
@brief CNORXZ HDF5 main header
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "h5_content_base.h"
#include "h5_file.h"
#include "h5_group.h"
#include "h5_table.h"
#include "h5_dataset.h"
#include "h5_type_id.h"
#include "cnorxz_hdf5.cc.h"

View file

@ -0,0 +1,108 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_content_base.cc.h
@brief Implementation of template member functions of ContentBase
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_content_base_cc_h__
#define __cxz_h5_content_base_cc_h__
#include "h5_content_base.h"
namespace CNORXZ
{
namespace hdf5
{
namespace
{
template <typename T>
struct CreateAttribute
{
static inline herr_t write(hid_t id, const String& name, const T& v)
{
CXZ_ERROR("type " << typeid(v).name() << " not supported (name "
<< name << ", id = " << id << ")");
return 0;
}
};
template <>
struct CreateAttribute<Int>
{
static inline herr_t write(hid_t id, const String& name, const Int& v)
{
const hsize_t dim = 1;
const hid_t type_id = H5Tarray_create(H5T_NATIVE_INT, 1, &dim);
const hid_t space_id = H5Screate(H5S_SCALAR);
const hid_t attr_id = H5Acreate(id, name.c_str(), type_id, space_id, H5P_DEFAULT,
H5P_DEFAULT);
const herr_t err = H5Awrite(attr_id, type_id, &v);
H5Aclose(attr_id);
H5Sclose(space_id);
H5Tclose(type_id);
return err;
}
};
template <>
struct CreateAttribute<Double>
{
static inline herr_t write(hid_t id, const String& name, const Double& v)
{
const hsize_t dim = 1;
const hid_t type_id = H5Tarray_create(H5T_NATIVE_DOUBLE, 1, &dim);
const hid_t space_id = H5Screate(H5S_SCALAR);
const hid_t attr_id = H5Acreate(id, name.c_str(), type_id, space_id, H5P_DEFAULT,
H5P_DEFAULT);
const herr_t err = H5Awrite(attr_id, type_id, &v);
H5Aclose(attr_id);
H5Sclose(space_id);
H5Tclose(type_id);
return err;
}
};
template <>
struct CreateAttribute<String>
{
static inline herr_t write(hid_t id, const String& name, const String& v)
{
const hsize_t len = v.size();
const hid_t type_id = H5Tcreate(H5T_STRING, len);
const hid_t space_id = H5Screate(H5S_SCALAR);
const hid_t attr_id = H5Acreate(id, name.c_str(), type_id, space_id, H5P_DEFAULT,
H5P_DEFAULT);
const herr_t err = H5Awrite(attr_id, type_id, v.c_str());
H5Aclose(attr_id);
H5Sclose(space_id);
H5Tclose(type_id);
return err;
}
};
template <typename T>
inline herr_t writeAttr(hid_t id, const String& name, const T& v)
{
return CreateAttribute<T>::write(id, name, v);
}
}
template <typename T>
ContentBase& ContentBase::addAttribute(const String& name, const T& value)
{
const herr_t err = writeAttr(mId, name, value);
CXZ_ASSERT(err >= 0, "error while writing attribute " << name);
return *this;
}
}
}
#endif

View file

@ -1,3 +1,13 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_content_base.h
@brief Abstract content base class declaration
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_content_base_h__
#define __cxz_h5_content_base_h__
@ -10,42 +20,129 @@ namespace CNORXZ
{
namespace hdf5
{
// TODO: IO save error handling !!!
/** *****
Enum indicating the content type.
Used by ContainerBase derivates to indicate the derived type.
*/
enum class ContentType {
ATTR = 1,
FILE = 2,
GROUP = 3,
DSET = 4,
TABLE = 5,
VALUE = 6,
NONE = 0,
FILE = 1,
GROUP = 2,
DSET = 3,
TABLE = 4,
};
/** ****
Abstract base class for handling hdf5 objects.
*/
class ContentBase
{
public:
DEFAULT_MEMBERS(ContentBase);
DEFAULT_MEMBERS(ContentBase); /**< Default constructors and assignments. */
/** Construct the class.
@param _name Content name.
@param _parent Parent content object. Leave null for the root object.
*/
ContentBase(const String& _name, const ContentBase* _parent = nullptr);
/** Virtual default destructor. */
virtual ~ContentBase() = default;
/** Get the content type.
@return Content type.
*/
virtual ContentType type() const = 0;
/** Check if in read-only mode
@return True if read-only else false.
*/
virtual bool ro() const = 0;
/** Open object.
@return Reference to this object.
*/
virtual ContentBase& open() = 0;
/** Close object.
@return Reference to this object.
*/
virtual ContentBase& close() = 0;
/** Get object path.
@return Absolute hdf5 file internal path of this object.
*/
virtual String path() const = 0;
/** Get the file name.
@return Name of the hdf5 file this object is stored in.
*/
virtual String filename() const = 0;
/** Check if group exists in the parent object.
@return True if object exists, else false.
*/
virtual bool exists() const = 0;
/** Get object name.
@return The name of this object.
*/
const String& name() const;
/** Get parent object.
@return Pointer to the parent of this object.
*/
const ContentBase* parent() const;
RangePtr range() const;
/** Get object id.
@return hdf5 id of the h5 object maintained by this object.
*/
hid_t id() const;
inline bool isOpen() const { return mId != 0; }
/** Check if object is open, i.e. if there is a valid hdf5 id.
@return True if object is open else false.
*/
bool isOpen() const;
/** Add attribute to this object.
@tparam T Attribute value type.
@param name Attribute name.
@param value Attribute value.
*/
template <typename T>
ContentBase& addAttribute(const String& name, const T& value);
/** Get an attribute of this object.
@param name Attribute name.
@return The attribute value as DType.
*/
DType getAttribute(const String& name) const;
/** Check if attribute of given name exists in this object.
@param name Attribute name.
@return True if attribute exists else false.
*/
bool attributeExists(const String& name) const;
/** Get all attributes of this object.
@return Std map of key-value pairs.
*/
std::map<String,DType> getAttributes() const;
/** Get all attributes of this object and all its parent objects, recursively.
@return Std map of key-value pairs.
*/
std::map<String,DType> getRecursiveAttributes() const; // + all parent's attributes
protected:
String mName;
const ContentBase* mParent = nullptr;
RangePtr mRange;
hid_t mId = 0;
String mName; /**< Name of this object. */
const ContentBase* mParent = nullptr; /**< Pointer to this object's parent. */
hid_t mId = 0; /**< hdf5 identifier of the hdf5 object handled by this object. */
};
/** Shortcut for a shared pointer to an abstract content object. */
typedef Sptr<ContentBase> ContentPtr;
}

View file

@ -0,0 +1,113 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_dataset.cc.h
@brief Implementation of template member functions of Dataset and SDataset.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_dataset_cc_h__
#define __cxz_h5_dataset_cc_h__
#include "h5_dataset.h"
namespace CNORXZ
{
namespace hdf5
{
template <typename T>
Dataset& Dataset::init(const ArrayBase<T>& data)
{
const hid_t tid = getTypeId(*data.data());
VCHECK(tid);
init(data.range(), tid);
if(data.begin().formatIsTrivial()){
Vector<hsize_t> dims(mDataRange->dim());
for(SizeT i = 0; i != dims.size(); ++i){
dims[i] = mDataRange->sub(i)->size();
}
const hid_t memspace = H5Screate_simple(dims.size(), dims.data(), NULL);
H5Dwrite(mId, mType, memspace, mFilespace, H5P_DEFAULT, data.data());
H5Sclose(memspace);
}
else {
CXZ_ERROR("IMPLEMENT!!!");
}
return *this;
}
template <typename T>
SDataset<T>::SDataset(const String& name, const ContentBase* _parent) :
Dataset(name, _parent)
{}
template <typename T>
MArray<T> SDataset<T>::read() const
{
Vector<hsize_t> dims(mDataRange->dim());
for(SizeT i = 0; i != dims.size(); ++i){
dims[i] = mDataRange->sub(i)->size();
}
const hid_t mem_space_id = H5Screate_simple(static_cast<hsize_t>(dims.size()),
dims.data(), nullptr);
const hid_t xfer_plist_id = H5Pcreate(H5P_DATASET_XFER);
MArray<T> out(mDataRange);
const herr_t err = H5Dread(mId, mType, mem_space_id, mFilespace, xfer_plist_id, out.data());
CXZ_ASSERT(err >= 0, "error while reading dataset '" << mName
<< "', errorcode :" << err);
H5Pclose(xfer_plist_id);
H5Sclose(mem_space_id);
return out;
}
template <typename T>
template <class I, typename M>
MArray<T> SDataset<T>::read(const IndexInterface<I,M>& beg, const IndexInterface<I,M>& end) const
{
CXZ_ASSERT(beg.dim() == mDataRange->dim(), "got index of inconsistent dimension, got"
<< beg.dim() << ", expected " << mDataRange->dim());
const RangePtr outrange = beg.prange(end);
Vector<hsize_t> dims(outrange->dim());
for(SizeT i = 0; i != dims.size(); ++i){
dims[i] = outrange->sub(i)->size();
}
const Vector<hsize_t> fpos = mkFPos(beg);
H5Sselect_hyperslab(mFilespace, H5S_SELECT_SET, fpos.data(), NULL, dims.data(), NULL);
const hid_t mem_space_id = H5Screate_simple(static_cast<hsize_t>(dims.size()),
dims.data(), nullptr);
const hid_t xfer_plist_id = H5Pcreate(H5P_DATASET_XFER);
MArray<T> out(outrange);
const herr_t err = H5Dread(mId, mType, mem_space_id, mFilespace, xfer_plist_id, out.data());
CXZ_ASSERT(err >= 0, "error while reading dataset '" << mName
<< "', errorcode :" << err);
H5Pclose(xfer_plist_id);
H5Sclose(mem_space_id);
return out;
}
template <typename T>
template <class I, typename M>
Vector<hsize_t> SDataset<T>::mkFPos(const IndexInterface<I,M>& beg) const
{
Vector<hsize_t> fpos(beg.dim());
if constexpr(has_static_sub<I>::value){
iter<0,index_dim<I>::value> ( [&](auto i) { fpos[i] = beg.THIS().pack().get(i)->lex(); }, NoF{} );
}
else if constexpr(has_sub<I>::value){
for(SizeT i = 0; i != beg.dim(); ++i){
fpos[i] = beg.THIS().pack().get(i)->lex();
}
}
else {
fpos[0] = beg.lex();
}
return fpos;
}
}
}
#endif

View file

@ -0,0 +1,109 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_dataset.h
@brief Dataset declaration.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_dataset_h__
#define __cxz_h5_dataset_h__
#include "h5_types.h"
#include "h5_content_base.h"
namespace CNORXZ
{
namespace hdf5
{
/** ****
Class to handle hdf5 datasets.
*/
class Dataset : public ContentBase
{
public:
DEFAULT_MEMBERS(Dataset); /**< Default constructors and assignments. */
/** Construct the class.
@param name Dataset name.
@param _parent Parent content object.
*/
Dataset(const String& name, const ContentBase* _parent);
/** Destructor. Release all involved hdf5 ids. */
~Dataset();
virtual ContentType type() const override final;
virtual bool ro() const override final;
virtual Dataset& open() override final;
virtual Dataset& close() override final;
virtual String path() const override final;
virtual String filename() const override final;
virtual bool exists() const override final;
/** Initalize the dataset.
@param dataRange A potentially multi-dimensional range characterizing the dataset.
@param type Data type id.
*/
Dataset& init(const RangePtr& dataRange, hid_t type);
/** Initalize the dataset.
@param data Array containing the dataset.
*/
template <typename T>
Dataset& init(const ArrayBase<T>& data);
/** Get the data range.
@return Pointer to the range.
*/
const RangePtr& dataRange() const;
protected:
RangePtr mDataRange; /**< The data range. */
hid_t mType; /**< The data type identifier. */
hid_t mFilespace; /**< The hdf5 file space identifier. */
};
/** ****
Class to handle hdf5 datasets, the value type is known at compile time.
@tparam T Dataset value type.
*/
template <typename T>
class SDataset : public Dataset
{
public:
DEFAULT_MEMBERS(SDataset); /**< Default constructors and assignments. */
/** Construct the class.
@param name Dataset name.
@param _parent Parent content object.
*/
SDataset(const String& name, const ContentBase* _parent);
/** Read the dataset.
@return Array containing the dataset values.
*/
MArray<T> read() const;
/** Read a given subset of the dataset.
The subset needs to be hypercubic.
@param beg Index indicating the begin edge of the hypercube.
@param end Index indicating the end edge of the hypercube (inclusive).
@return Array containing the dataset values.
*/
template <class I, typename M>
MArray<T> read(const IndexInterface<I,M>& beg, const IndexInterface<I,M>& end) const;
private:
template <class I, typename M>
Vector<hsize_t> mkFPos(const IndexInterface<I,M>& beg) const;
};
}
}
#endif

View file

@ -1,3 +1,13 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_file.h
@brief Group declaration.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_file_h__
#define __cxz_h5_file_h__
@ -10,14 +20,23 @@ namespace CNORXZ
{
namespace hdf5
{
// maybe introduce abstraction layer between as base for File and Group
/** ****
Class to handle hdf5 file objects.
Objects of this type usually serve as root object
so they don't have any parent.
*/
class File : public Group
{
public:
typedef URange<String> RangeT;
DEFAULT_MEMBERS(File);
DEFAULT_MEMBERS(File); /**< Default constructors and assignments. */
/** Construct the class.
@param fname Path to the hdf5 file to be handled.
@param _ro Open in read-only mode if true, otherwise have write access.
*/
File(const String& fname, bool _ro = true);
/** Destructor. Release all involved hdf5 ids. */
~File();
virtual ContentType type() const override final;
@ -26,9 +45,13 @@ namespace CNORXZ
virtual File& close() override final;
virtual String path() const override final;
virtual String filename() const override final;
virtual bool exists() const override final;
/** Check if handled file is in hdf5 format.
@return True if file is in hdf5 format, else false.
*/
bool ishdf5() const;
virtual Int exists() const override final;
private:
bool mRo = true;
};

View file

@ -1,17 +1,50 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_group.cc.h
@brief Implementation of template member functions of Group.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_group_cc_h__
#define __cxz_h5_group_cc_h__
#include "h5_group.h"
#include "xpr/for.h"
namespace CNORXZ
{
namespace hdf5
{
template <SizeT I, typename... Ts>
constexpr const auto& tget(const Tuple<Ts...>& t)
{
return std::get<sizeof...(Ts)-I-1>(t);
}
template <SizeT I, typename... Ts>
constexpr auto& tget(Tuple<Ts...>& t)
{
return std::get<sizeof...(Ts)-I-1>(t);
}
template <SizeT N, typename... Ts>
SizeT getTupleOffset(const Tuple<Ts...>& t, CSizeT<N> i)
{
const PtrId beg = reinterpret_cast<PtrId>(&t);
const PtrId pos = reinterpret_cast<PtrId>(&tget<i>(t));
return pos - beg;
}
template <typename... Ts>
Sptr<STable<Ts...>> Group::getTable(const String& name, Tuple<Ts...> proto)
{
auto i = this->getIndexTo(name);
CXZ_ASSERT((*i)->type() == ContentType::TABLE,
"element '" << name << "' is not of type TABLE");
auto tab = std::dynamic_pointer_cast<Table>( *i );
if(tab == nullptr){
auto stab = std::dynamic_pointer_cast<STable<Ts...>>(*i);
@ -19,33 +52,54 @@ namespace CNORXZ
return stab;
}
else {
const RangePtr fields = tab->fields();
(*i)->close();
*i = std::make_shared<STable<Ts...>>(name, this, fields);
return *i;
auto stab = std::make_shared<STable<Ts...>>(name, this);
*i = stab;
return stab;
}
}
template <typename T>
Group& Group::addData(const String& name, const ArrayBase<T>& data)
Sptr<SDataset<T>> Group::getDataset(const String& name, T proto)
{
auto i = this->getIndexTo(name);
CXZ_ASSERT((*i)->type() == ContentType::DSET,
"element '" << name << "' is not of type DSET");
auto dset = std::dynamic_pointer_cast<Dataset>( *i );
if(dset == nullptr){
auto sdset = std::dynamic_pointer_cast<SDataset<T>>(*i);
CXZ_ASSERT(sdset != nullptr, "wrong format for dataset '" << name << "'");
return sdset;
}
else {
(*i)->close();
auto sdset = std::make_shared<SDataset<T>>(name, this);
*i = sdset;
return sdset;
}
}
template <typename T>
Group& Group::addDataset(const String& name, const ArrayBase<T>& data)
{
CXZ_ASSERT(this->isOpen(), "tried to extend closed group");
CXZ_ERROR("not implemented!!!");
Vector<String> nvec({name});
mCont.extend( URangeFactory<String>( nvec ).create() );
auto ii = getIndexTo(name);
auto dset = std::make_shared<SDataset<T>>(name, this);
dset->init(data);
*ii = dset;
return *this;
}
template <typename... Ts>
Group& Group::addTable(const String& name, const ArrayBase<Tuple<Ts...>>& data,
const Vector<String>& fnames)
const Arr<String,sizeof...(Ts)>& fnames)
{
CXZ_ASSERT(this->isOpen(), "tried to extend closed group");
Vector<String> nvec({name});
Vector<DType> dvec({DType(name)});
auto extr = URangeFactory<String>( nvec ).create();
mCont.extend(extr);
auto ii = mCont.begin();
ii.at(dvec); // 'at' returns YIndex&, so cannot use it inline...
mCont.extend( URangeFactory<String>( nvec ).create() );
auto ii = getIndexTo(name);
auto tab = std::make_shared<STable<Ts...>>(name, this, fnames);
for(auto& d: data){
tab->appendRecord(d);
@ -54,6 +108,41 @@ namespace CNORXZ
return *this;
}
template <class F>
decltype(auto) Group::iter(F&& f) const
{
CXZ_ASSERT(isOpen(), "try to iterate over closed object");
RangePtr gr = *mCont.range()->sub().begin();
auto gi = std::make_shared<UIndex<String>>(gr);
return gi->ifor( operation(std::forward<F>(f), mCont(gi)), NoF{} );
}
template <class F>
decltype(auto) Group::iterRecursive(F&& f) const
{
return iter( [&](const auto& c) {
f(c);
recursion(c, std::forward<F>(f));
});
}
template <class F>
decltype(auto) Group::iter(F&& f)
{
CXZ_ASSERT(isOpen(), "try to iterate over closed object");
RangePtr gr = *mCont.range()->sub().begin();
auto gi = std::make_shared<UIndex<String>>(gr);
return gi->ifor( operation(std::forward<F>(f), mCont(gi)), NoF{} );
}
template <class F>
decltype(auto) Group::iterRecursive(F&& f)
{
return iter( [&](const auto& c) {
f(c);
recursion(c, std::forward<F>(f));
});
}
}
}

View file

@ -1,3 +1,13 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_group.h
@brief Group declaration.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_group_h__
#define __cxz_h5_group_h__
@ -9,11 +19,21 @@ namespace CNORXZ
{
namespace hdf5
{
/** ****
Class to handle hdf5 groups.
*/
class Group : public ContentBase
{
public:
DEFAULT_MEMBERS(Group);
DEFAULT_MEMBERS(Group); /**< Default constructors and assignments. */
/** Construct the class.
@param gname Group name.
@param _parent Parent content object.
*/
Group(const String& gname, const ContentBase* _parent);
/** Destructor. Release all involved hdf5 ids. */
~Group();
virtual ContentType type() const override;
@ -22,31 +42,138 @@ namespace CNORXZ
virtual Group& close() override;
virtual String path() const override;
virtual String filename() const override;
virtual bool exists() const override;
virtual Int exists() const;
/** Get object contained by this group.
@param name Object name.
@return Pointer to the object.
*/
const ContentPtr& get(const String& name) const;
/** Get object contained by this group as group.
Checks if the object is a group.
@param name Group name.
@return Pointer to the group.
*/
Sptr<Group> getGroup(const String& name) const;
/** Get object contained by this group as table.
Checks if the object is a table.
@param name Table name.
@return Pointer to the table.
*/
Sptr<Table> getTable(const String& name) const;
/** Get object contained by this group as dataset.
Checks if the object is a table.
@param name Dataset name.
@return Pointer to the dataset.
*/
Sptr<Dataset> getDataset(const String& name) const;
/** Get object contained by this group as table for given value type.
Checks if the object is a table.
@tparam Ts Table entry types.
@param name Table name.
@param proto Empty prototype (template argument resolution).
@return Pointer to the table.
*/
template <typename... Ts>
Sptr<STable<Ts...>> getTable(const String& name, Tuple<Ts...> proto);
/** Get object contained by this group as dataset for given value type.
Checks if the object is a dataset.
@tparam T Dataset value type.
@param name Dataset name.
@param proto Empty prototype (template argument resolution).
@return Pointer to the dataset.
*/
template <typename T>
Sptr<SDataset<T>> getDataset(const String& name, T proto);
/** Get objects contained by this group.
@returns MArray of object pointers.
*/
const MArray<ContentPtr>& get() const;
/** Add a new group to this group.
@param name Name of the created group.
*/
Group& addGroup(const String& name);
template <typename T>
Group& addData(const String& name, const ArrayBase<T>& data);
/** Add a new table to this group.
@tparam Ts Table element types.
@param name Name of the created table.
@param data Table data.
@param fnames Table field names.
*/
template <typename... Ts>
Group& addTable(const String& name, const ArrayBase<Tuple<Ts...>>& data,
const Vector<String>& fnames);
protected:
MArray<ContentPtr> mCont;
const Arr<String,sizeof...(Ts)>& fnames);
/** Add a new dataset to this group.
@tparam T Value type.
@param name Name of the created dataset.
@param data Dataset data.
*/
template <typename T>
Group& addDataset(const String& name, const ArrayBase<T>& data);
/** Iterate over all group elements (const).
@param f function object to be executed on each group element.
*/
template <class F>
decltype(auto) iter(F&& f) const;
/** Iterate recursively over all group elements (const).
@param f function object to be executed on each group element.
*/
template <class F>
decltype(auto) iterRecursive(F&& f) const;
/** Iterate over all group elements.
@param f function object to be executed on each group element.
*/
template <class F>
decltype(auto) iter(F&& f);
/** Iterate recursively over all group elements.
@param f function object to be executed on each group element.
*/
template <class F>
decltype(auto) iterRecursive(F&& f);
protected:
MArray<ContentPtr> mCont; /**< Group elements. */
/** Recursion helper functon.
@param c Group element.
@param f Function to be executed.
*/
template <typename C, class F>
static void recursion(const C& c, F&& f)
{
if(c->type() == ContentType::GROUP){
auto cx = std::dynamic_pointer_cast<Group>(c);
cx->open();
if(cx->get().range() != nullptr){
cx->iterRecursive(std::forward<F>(f))();
}
}
}
/** Setup group content. */
void mkCont();
/** Get index to requested group element (const).
@param name Element name.
*/
AIndex<ContentPtr> getIndexTo(const String& name) const;
/** Get index to requested group element.
@param name Element name.
*/
BIndex<ContentPtr> getIndexTo(const String& name);
};
}

View file

@ -1,3 +1,13 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_table.cc.h
@brief Implementation of template member functions of Table and STable.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_table_cc_h__
#define __cxz_h5_table_cc_h__
@ -9,6 +19,16 @@ namespace CNORXZ
{
namespace hdf5
{
template <class F>
decltype(auto) Table::iterRecords(F&& f) const
{
auto ri = std::make_shared<CIndex>(mRecords);
return ri->ifor
( operation( std::forward<F>(f),
operation( [&](const SizeT pos) { return readRecord(pos); } ,
xpr(ri) ) ), NoF{} );
}
template <typename... Ts>
template <class F>
decltype(auto) STable<Ts...>::iterRecords(F&& f) const
@ -18,51 +38,69 @@ namespace CNORXZ
}
template <typename... Ts>
STable<Ts...>::STable(const String& name, const ContentBase* _parent,
const Vector<String>& fnames) :
STable<Ts...>::STable(const String& name, const ContentBase* _parent) :
Table(name, _parent)
{
constexpr SizeT N = sizeof...(Ts);
if(mFields == nullptr){
CXZ_ASSERT(fnames.size() != 0, "field names have to be initialized");
Vector<FieldID> fields(fnames.size());
for(SizeT i = 0; i != fields.size(); ++i){
fields[i].first = i;
fields[i].second = fnames[i];
}
mFields = URangeFactory<FieldID>(fields).create();
}
CXZ_ASSERT(mFields->size() == sizeof...(Ts), "expected tuple of size = " << mFields->size()
<< ", got: " << sizeof...(Ts));
if(mFields != nullptr){
Tuple<Ts...> x;
if(mRecords == nullptr) {
mOffsets = MArray<SizeT>( mFields, iter<0,N>
( [&](auto i) { return getTupleOffset(x, i); },
[](const auto&... e) { return Vector<SizeT>({e...}); }) );
mSizes = MArray<SizeT>( mFields, iter<0,N>
( [&](auto i) { return sizeof(std::get<i>(x)); },
[](const auto&... e) { return Vector<SizeT>({e...}); }) );
mTypes = MArray<hid_t>( mFields, iter<0,N>
( [&](auto i) { return getTypeId(std::get<i>(x)); },
[](const auto&... e) { return Vector<hid_t>({e...}); }) );
}
else {
CXZ_ASSERT(mFields->size() == N, "expected tuple of size = " << mFields->size()
<< ", got: " << N);
Tuple<Ts...> x;
iter<0,N>( [&](auto i) { CXZ_ASSERT
( getTupleOffset(x, i) == mOffsets.data()[i],
"wrong offset for field " << i << ": " << getTupleOffset(x, i)
<< " vs " << mOffsets.data()[i] ); }, NoF{} );
iter<0,N>( [&](auto i) { CXZ_ASSERT
( sizeof(std::get<i>(x)) == mSizes.data()[i],
"wrong size for field " << i << ": " << sizeof(std::get<i>(x))
( sizeof(tget<i>(x)) == mSizes.data()[i],
"wrong size for field " << i << ": " << sizeof(tget<i>(x))
<< " vs " << mSizes.data()[i] ); }, NoF{} );
iter<0,N>( [&](auto i) { CXZ_ASSERT
( getTypeId(std::get<i>(x)) == mTypes.data()[i],
"wrong type for field " << i << ": " << getTypeId(std::get<i>(x))
( H5Tget_class(getTypeId(tget<i>(x))) == mTypes.data()[i],
"wrong type for field " << i
<< ": " << H5Tget_class(getTypeId(tget<i>(x)))
<< " vs " << mTypes.data()[i] ); }, NoF{} );
}
}
template <typename... Ts>
STable<Ts...>::STable(const String& name, const ContentBase* _parent,
const Arr<String,sizeof...(Ts)>& fnames) :
Table(name, _parent)
{
initFields(fnames);
}
template <typename... Ts>
STable<Ts...>& STable<Ts...>::initFields(const Arr<String,sizeof...(Ts)>& fnames)
{
constexpr SizeT N = sizeof...(Ts);
CXZ_ASSERT(mFields == nullptr and mRecords == nullptr,
"tried to initialize an existing table");
Vector<FieldID> fields(fnames.size());
for(SizeT i = 0; i != fields.size(); ++i){
fields[i].first = i;
fields[i].second = fnames[i];
}
mFields = URangeFactory<FieldID>(fields).create();
Tuple<Ts...> x;
mOffsets = MArray<SizeT>
( mFields, iter<0,N>
( [&](auto i) { return getTupleOffset(x, i); },
[](const auto&... e) { return Vector<SizeT>({e...}); }) );
mSizes = MArray<SizeT>
( mFields, iter<0,N>
( [&](auto i) { return sizeof(tget<i>(x)); },
[](const auto&... e) { return Vector<SizeT>({e...}); }) );
mTypes = MArray<hid_t>
( mFields, iter<0,N>
( [&](auto i) { return getTypeId(tget<i>(x)); },
[](const auto&... e) { return Vector<hid_t>({e...}); }) );
return *this;
}
template <typename... Ts>
STable<Ts...>& STable<Ts...>::appendRecord(const Tuple<Ts...>& t)
{
@ -71,10 +109,20 @@ namespace CNORXZ
initTable(1, &t, sizeof(t), sizeof(t));
}
else {
Table::appendRecord(1, &t, sizeof(t));
Table::appendRecords(1, &t);
}
return *this;
}
template <typename... Ts>
MArray<Tuple<Ts...>> STable<Ts...>::read() const
{
CXZ_ASSERT(isOpen(), "attempt to read table that has not been opened");
MArray<Tuple<Ts...>> out(mRecords);
H5TBread_table(mParent->id(), mName.c_str(), mTypesize, mOffsets.data(),
mSizes.data(), out.data());
return out;
}
}
}

View file

@ -1,3 +1,13 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_table.h
@brief Table declaration.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_table_h__
#define __cxz_h5_table_h__
@ -9,13 +19,23 @@ namespace CNORXZ
{
namespace hdf5
{
/** ****
Class to handle hdf5 tables.
*/
class Table : public ContentBase
{
public:
typedef std::pair<SizeT,String> FieldID;
typedef std::pair<SizeT,String> FieldID; /**< Meta data type of fields range. */
DEFAULT_MEMBERS(Table);
DEFAULT_MEMBERS(Table); /**< Default constructors and assignments. */
/** Construct the class.
@param name Table name.
@param _parent Parent content object.
*/
Table(const String& name, const ContentBase* _parent);
/** Destructor. Release all involved hdf5 ids. */
~Table();
virtual ContentType type() const override final;
@ -24,36 +44,130 @@ namespace CNORXZ
virtual Table& close() override final;
virtual String path() const override final;
virtual String filename() const override final;
virtual bool exists() const override final;
/** Ininitialize table field names.
@param fnames Table field names.
*/
Table& initFieldNames(const Vector<String>& fnames);
/** Initialize the table.
@param n Number of records (rows).
@param data Table data.
@param dsize Record type size.
@param chunk_size Chunk size.
*/
Table& initTable(SizeT n, const void* data, SizeT dsize, SizeT chunk_size);
Table& appendRecord(SizeT n, const void* data, SizeT dsize);
Table& readRecord(SizeT pos, SizeT n, char* data);
/** Append records to the table.
@param n Number of records to append.
@param data Records data.
*/
Table& appendRecords(SizeT n, const void* data);
/** Read records.
@param pos Number of first record to read.
@param n Number of records to read.
@param data Target pointer.
*/
Table& readRecords(SizeT pos, SizeT n, char* data);
/** Read record.
@param pos Number of the record to be read.
@return DType array with containing the record data.
*/
MArray<DType> readRecord(SizeT pos) const;
/** Read table.
@return DType array containing the table data.
*/
MArray<DType> read() const;
/** Iterate over table records.
@param f function object to be executed on each table record.
*/
template <class F>
decltype(auto) iterRecords(F&& f) const;
/** Get fields range.
@return Pointer to the range.
*/
const RangePtr& fields() const;
/** Get records range.
@return Pointer to the range.
*/
const RangePtr& records() const;
protected:
RangePtr mRecords;
RangePtr mFields; // -> FIndex (position -> offset)
MArray<SizeT> mSizes;
MArray<SizeT> mOffsets;
MArray<hid_t> mTypes;
hid_t mType = 0;
RangePtr mRecords; /**< Records range. */
RangePtr mFields; /**< Fields range. */ // -> FIndex (position -> offset)
MArray<SizeT> mSizes; /**< Field element type sizes. */
MArray<SizeT> mOffsets; /**< Field element offsets. */
MArray<hid_t> mTypes; /**< Field element type ids. */
hid_t mType = 0; /**< Record type id. */
SizeT mTypesize = 0; /**< Record type size. */
MArray<std::function<DType(const char*)>> mInterpret; /**< Field element type interpreting functions. */
void mkTypes(); /**< Type setup function. */
};
/** ****
Class to handle hdf5 tables, the record type is known at compile time.
The records are accessed by a std tuple.
Caution: The ordering of the record entries is fixed by their memory location.
The std tuple has a reverse ordering w.r.t. the memory location, i.e. a record
with element types T1-T2-T3 (memory ordering) and field names "T1", "T2", "T3",
requires template argumens <T3,T2,T1>.
@tparam Ts Record element types.
*/
template <typename... Ts>
class STable : public Table
{
public:
DEFAULT_MEMBERS(STable);
STable(const String& name, const ContentBase* _parent, const Vector<String>& fnames);
DEFAULT_MEMBERS(STable); /**< Default constructors and assignments. */
/** Construct the class.
@param name Table name.
@param _parent Parent content object.
*/
STable(const String& name, const ContentBase* _parent);
/** Construct the class.
@param name Table name.
@param _parent Parent content object.
@param fnames Field names.
*/
STable(const String& name, const ContentBase* _parent,
const Arr<String,sizeof...(Ts)>& fnames);
/** Ininitialize and setup table fields.
@param fnames Table field names.
*/
STable& initFields(const Arr<String,sizeof...(Ts)>& fnames);
/** Append record to the table.
@param t Tuple containing the record entries.
*/
STable& appendRecord(const Tuple<Ts...>& t);
/** Append records to the table.
@param t Array of tuples containing the records.
*/
STable& appendRecord(const MArray<Tuple<Ts...>>& t);
/** Read the table.
@return Array of tuples containing the records.
*/
MArray<Tuple<Ts...>> read() const;
/** Iterate over all table records.
@param f Function object to be executed on each record.
*/
template <class F>
decltype(auto) iterRecords(F&& f) const;
};
}
}

View file

@ -1,3 +1,13 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_type_id.h
@brief TypeId template implementation.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_type_id_cc_h__
#define __cxz_h5_type_id_cc_h__
@ -8,17 +18,9 @@ namespace CNORXZ
{
namespace hdf5
{
template <SizeT N, typename... Ts>
SizeT getTupleOffset(const Tuple<Ts...>& t, CSizeT<N> i)
{
const PtrId beg = reinterpret_cast<PtrId>(&t);
const PtrId pos = reinterpret_cast<PtrId>(&std::get<i>(t));
return pos - beg;
}
/**************
* TypeId *
**************/
/*============+
| TypeId |
+============*/
template <typename T>
inline hid_t TypeId<T>::get()
@ -28,17 +30,17 @@ namespace CNORXZ
inline hid_t TypeId<SizeT>::get()
{
return H5T_NATIVE_ULONG;
return H5Tcopy( H5T_NATIVE_ULONG );
}
inline hid_t TypeId<Int>::get()
{
return H5T_NATIVE_INT;
return H5Tcopy( H5T_NATIVE_INT );
}
inline hid_t TypeId<Double>::get()
{
return H5T_NATIVE_DOUBLE;
return H5Tcopy( H5T_NATIVE_DOUBLE );
}
template <typename T, SizeT N>
@ -48,9 +50,9 @@ namespace CNORXZ
return arrtype;
}
/*****************
* getTypeId *
*****************/
/*===============+
| getTypeId |
+===============*/
template <typename T>
hid_t getTypeId(T x)

View file

@ -1,37 +1,74 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/h5_type_id.h
@brief TypeId template declaration.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_h5_type_id_h__
#define __cxz_h5_type_id_h__
#include "base/types.h"
namespace CNORXZ
{
namespace hdf5
{
template <SizeT N, typename... Ts>
SizeT getTupleOffset(const Tuple<Ts...>& t, CSizeT<N> i);
/**************
* TypeId *
**************/
/** ****
Get a valid hdf5 id for a given type.
Return 0 if not implemented.
@tparam T The type.
*/
template <typename T>
struct TypeId { static inline hid_t get(); };
struct TypeId
{
/** Get the type id. */
static inline hid_t get();
};
/** Specialization of TypeId for SizeT. */
template <>
struct TypeId<SizeT> { static inline hid_t get(); };
struct TypeId<SizeT>
{
/** Get the type id for SizeT. */
static inline hid_t get();
};
/** Specialization of TypeId for Int. */
template <>
struct TypeId<Int> { static inline hid_t get(); };
struct TypeId<Int>
{
/** Get the type id for Int. */
static inline hid_t get();
};
/** Specialization of TypeId for Double. */
template <>
struct TypeId<Double> { static inline hid_t get(); };
struct TypeId<Double>
{
/** Get the type id for Double. */
static inline hid_t get();
};
/** Specialization of TypeId for an array
@tparam T Element type.
@tparam N Array size.
*/
template <typename T, SizeT N>
struct TypeId<Arr<T,N>> { static inline hid_t get(); };
/*****************
* getTypeId *
*****************/
struct TypeId<Arr<T,N>>
{
/** Get the type id for the given array. */
static inline hid_t get();
};
/** Wrapper function for TypeId::get()
@param Variable of given type.
@return A type id of the input variable's type.
*/
template <typename T>
hid_t getTypeId(T x);
}

View file

@ -1,3 +1,15 @@
// -*- C++ -*-
/**
@file opt/hdf5/include/types.h
@brief Declaration of hdf5 related library types
This file contains the declaration of all hdf5 related library types
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __h5_types_h__
#define __h5_types_h__
@ -21,7 +33,14 @@ namespace CNORXZ
// definition -> h5_table.h
template <typename... Ts>
class STable;
// definition -> h5_dataset.h
class Dataset;
// definition -> h5_dataset.h
template <typename T>
class SDataset;
}
}

View file

@ -4,6 +4,7 @@ set(libcnorxzhdf5_a_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/h5_file.cc
${CMAKE_CURRENT_SOURCE_DIR}/h5_group.cc
${CMAKE_CURRENT_SOURCE_DIR}/h5_table.cc
${CMAKE_CURRENT_SOURCE_DIR}/h5_dataset.cc
)
add_library(cnorxzhdf5_obj OBJECT

View file

@ -1,3 +1,15 @@
// -*- C++ -*-
/**
@file opt/hdf5/lib/h5_content_base.cc
@brief Content base member function implementation.
Implementation of all non-virtual member functions of ContentBase.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "h5_content_base.h"
@ -19,14 +31,121 @@ namespace CNORXZ
return mParent;
}
RangePtr ContentBase::range() const
{
return mRange;
}
hid_t ContentBase::id() const
{
return mId;
}
bool ContentBase::isOpen() const
{
return mId != 0;
}
DType ContentBase::getAttribute(const String& name) const
{
CXZ_ASSERT(attributeExists(name), "no attribute with name '" << name
<< "' in object " << mName);
const hid_t attr = H5Aopen(mId, name.c_str(), H5P_DEFAULT);
CXZ_ASSERT(attr != H5I_INVALID_HID, "error while reading attribute " << name);
const hid_t atype_id = H5Aget_type(attr);
CXZ_ASSERT(atype_id != H5I_INVALID_HID,
"error while determining type of attribute " << name);
const H5T_class_t tc = H5Tget_class(atype_id);
DType o;
switch(tc){
case H5T_INTEGER: {
Int v;
H5Aread(attr, atype_id, &v);
o = DType(v);
break;
}
case H5T_FLOAT: {
Double v;
H5Aread(attr, atype_id, &v);
o = DType(v);
break;
}
case H5T_STRING: {
const SizeT asize = H5Tget_size(atype_id);
Vector<char> v(asize+1);
H5Aread(attr, atype_id, v.data());
o = DType( String( v.data() ) );
break;
}
case H5T_ARRAY: {
const int ndims = H5Tget_array_ndims(atype_id);
CXZ_ASSERT(ndims, "array of dimension " << ndims << " not supported");
hsize_t dims;
H5Tget_array_dims(atype_id, &dims);
const hid_t att_id = H5Tget_super(atype_id);
const H5T_class_t atc = H5Tget_class(att_id);
switch(atc){
case H5T_INTEGER: {
Vector<Int> v(dims);
H5Aread(attr, atype_id, v.data());
o = DType(v);
break;
}
case H5T_FLOAT: {
Vector<Double> v(dims);
H5Aread(attr, atype_id, v.data());
o = DType(v);
break;
}
default:
CXZ_ERROR("attribute type id " << atype_id << " not supported");
}
H5Tclose(att_id);
break;
}
default:
CXZ_ERROR("attribute type id " << atype_id << " not supported");
}
H5Tclose(atype_id);
H5Aclose(attr);
return o;
}
bool ContentBase::attributeExists(const String& name) const
{
CXZ_ASSERT(isOpen(), "tried to get attribute of closed object");
const htri_t ret = H5Aexists(mId, name.c_str());
CXZ_ASSERT(ret > 0, "error while reading attribute " << name);
return ret;
}
std::map<String,DType> ContentBase::getAttributes() const
{
CXZ_ASSERT(isOpen(), "tried to get attribute of closed object");
struct ItData
{
std::map<String,DType> d;
const ContentBase* _this;
} itdata;
itdata._this = this;
auto itop = [](hid_t loc_id, const char *attr_name,
const H5A_info_t* ainfo, void *op_data)
{
ItData* x = reinterpret_cast<ItData*>(op_data);
const String n = attr_name;
x->d[n] = x->_this->getAttribute( String(attr_name) );
return static_cast<herr_t>(0);
};
H5Aiterate(id(), H5_INDEX_NAME, H5_ITER_NATIVE, nullptr,
itop, &itdata);
return itdata.d;
}
std::map<String,DType> ContentBase::getRecursiveAttributes() const
{
std::map<String,DType> out = getAttributes();
if(mParent){
std::map<String,DType> par = mParent->getRecursiveAttributes();
out.insert(par.begin(), par.end());
}
return out;
}
}
}

View file

@ -0,0 +1,104 @@
#include "h5_dataset.h"
namespace CNORXZ
{
namespace hdf5
{
Dataset::Dataset(const String& name, const ContentBase* _parent) :
ContentBase(name, _parent)
{
if(exists()){
open();
}
}
Dataset::~Dataset()
{
this->close();
}
ContentType Dataset::type() const
{
return ContentType::DSET;
}
bool Dataset::ro() const
{
return mParent->ro();
}
Dataset& Dataset::open()
{
if(mId == 0 and exists()){
mId = H5Dopen(mParent->id(), mName.c_str(), H5P_DEFAULT);
mType = H5Dget_type(mId);
mFilespace = H5Dget_space(mId);
SizeT ndims = H5Sget_simple_extent_ndims(mFilespace);
Vector<hsize_t> dims(ndims);
H5Sget_simple_extent_dims(mFilespace, dims.data(), nullptr);
Vector<RangePtr> rs(ndims);
for(SizeT i = 0; i != ndims; ++i){
rs[i] = CRangeFactory(dims[i]).create();
}
mDataRange = yrange(rs);
}
return *this;
}
Dataset& Dataset::close()
{
if(mId != 0){
H5Sclose(mFilespace);
H5Tclose(mType);
H5Dclose(mId);
mId = 0;
}
return *this;
}
String Dataset::path() const
{
return mParent->path() + "/" + mName;
}
String Dataset::filename() const
{
return mParent->filename();
}
bool Dataset::exists() const
{
return H5Lexists(mParent->id(), mName.c_str(), H5P_DEFAULT) > 0;
}
Dataset& Dataset::init(const RangePtr& dataRange, hid_t type)
{
CXZ_ASSERT(not isOpen(), "tried to initialize dataset that is already extisting");
mDataRange = dataRange;
const H5T_class_t tc = H5Tget_class(type);
CXZ_ASSERT(tc != H5T_NO_CLASS, "id does not correspond to a data type"); // (did not found anythng better to check if type id is valid)...
const hid_t dcpl_id = H5Pcreate(H5P_DATASET_CREATE);
// TODO: all sub-ranges explicity!!!:
const SizeT ndim = dataRange->dim();
Vector<hsize_t> exts(ndim);
for(SizeT i = 0; i != ndim; ++i){
exts[i] = static_cast<hsize_t>( dataRange->sub(i)->size() );
}
mFilespace = H5Screate_simple(ndim, exts.data(), NULL);
mType = type;
mId = H5Dcreate(mParent->id(), mName.c_str(), mType, mFilespace,
H5P_DEFAULT, dcpl_id, H5P_DEFAULT);
H5Pclose(dcpl_id);
return *this;
}
const RangePtr& Dataset::dataRange() const
{
return mDataRange;
}
}
}

View file

@ -28,9 +28,12 @@ namespace CNORXZ
File& File::open()
{
if(isOpen()){
return *this;
}
Int ex = this->exists();
const String fn = this->filename();
CXZ_ASSERT( ex != 2, "tried to open non-h5 file '" << fn << "'" );
CXZ_ASSERT( ishdf5(), "tried to open non-h5 file '" << fn << "'" );
if(mRo){
CXZ_ASSERT( ex == 1, "could not open file as read-only: '"
<< fn << "' does not exist'");
@ -67,7 +70,7 @@ namespace CNORXZ
String File::path() const
{
return String("/");
return "";
}
String File::filename() const
@ -75,21 +78,25 @@ namespace CNORXZ
return name();
}
Int File::exists() const
bool File::exists() const
{
Int ex = 0;
bool ex = false;
std::ifstream fs(this->filename().c_str(), std::ios_base::binary);
if(fs.good()){
ex = 1; // file exists
ex = true; // file exists
}
fs.close();
if(ex != 0){
if(H5Fis_hdf5(this->filename().c_str()) <= 0){
ex = 2; // file not in h5 format
}
}
return ex;
}
bool File::ishdf5() const
{
if(exists()){
if(H5Fis_hdf5(this->filename().c_str()) <= 0){
return false;
}
}
return true; // a non-existing file can be created in hdf5 format
}
}
}

View file

@ -1,6 +1,7 @@
#include "h5_group.h"
#include "h5_table.h"
#include "h5_dataset.h"
namespace CNORXZ
{
@ -30,14 +31,16 @@ namespace CNORXZ
Group& Group::open()
{
if(this->exists()){
mId = H5Gopen( mParent->id(), mName.c_str(), H5P_DEFAULT );
if(not isOpen()){
if(this->exists()){
mId = H5Gopen( mParent->id(), mName.c_str(), H5P_DEFAULT );
}
else {
mId = H5Gcreate( mParent->id(), mName.c_str(),
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
}
this->mkCont();
}
else {
mId = H5Gcreate( mParent->id(), mName.c_str(),
H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
}
this->mkCont();
return *this;
}
@ -66,14 +69,23 @@ namespace CNORXZ
return String();
}
Int Group::exists() const
bool Group::exists() const
{
return H5Lexists(mParent->id(), mName.c_str(), H5P_DEFAULT) != 0 ? 1 : 0;
return H5Lexists(mParent->id(), mName.c_str(), H5P_DEFAULT) > 0;
}
const ContentPtr& Group::get(const String& name) const
{
auto i = this->getIndexTo(name);
const String delim = "/";
const SizeT delimpos = name.find(delim);
const String thisname = name.substr(0, delimpos);
if(delimpos != String::npos and delimpos+1 < name.size()){
const String next = name.substr(delimpos+1);
auto g = getGroup(thisname);
g->open();
return g->get(next);
}
auto i = this->getIndexTo(thisname);
return *i;
}
@ -85,6 +97,22 @@ namespace CNORXZ
return std::dynamic_pointer_cast<Group>( group );
}
Sptr<Table> Group::getTable(const String& name) const
{
auto table = this->get(name);
CXZ_ASSERT(table->type() == ContentType::TABLE,
"element '" << name << "' is not of type TABLE");
return std::dynamic_pointer_cast<Table>( table );
}
Sptr<Dataset> Group::getDataset(const String& name) const
{
auto dset = this->get(name);
CXZ_ASSERT(dset->type() == ContentType::DSET,
"element '" << name << "' is not of type DSET");
return std::dynamic_pointer_cast<Dataset>( dset );
}
const MArray<ContentPtr>& Group::get() const
{
CXZ_ASSERT(this->isOpen(), "tried to get content of closed group");
@ -118,10 +146,12 @@ namespace CNORXZ
return 0;
}
static bool isTable(hid_t id)
static bool isTable(hid_t loc_id, const char* name)
{
const hid_t id = H5Dopen(loc_id, name, H5P_DEFAULT);
if(not H5Aexists(id, "CLASS")){
return false;
H5Dclose(id);
}
hid_t attrid = H5Aopen(id, "CLASS", H5P_DEFAULT);
const hid_t atype = H5Aget_type(attrid);
@ -130,6 +160,7 @@ namespace CNORXZ
const herr_t ret = H5Aread(attrid, atype, buff.data());
H5Tclose(atype);
H5Aclose(attrid);
H5Dclose(id);
if(ret != 0){
return false;
}
@ -149,9 +180,9 @@ namespace CNORXZ
index();
H5O_info_t oinfo;
#if H5_VERS_MINOR > 10
H5Oget_info(id, &oinfo, H5O_INFO_BASIC);
H5Oget_info_by_name(id, name, &oinfo, H5O_INFO_BASIC, H5P_DEFAULT);
#else
H5Oget_info(id, &oinfo);
H5Oget_info_by_name(id, name, &oinfo, H5P_DEFAULT);
#endif
switch (oinfo.type) {
case H5O_TYPE_GROUP: {
@ -159,12 +190,11 @@ namespace CNORXZ
break;
}
case H5O_TYPE_DATASET: {
if(isTable(id)){
if(isTable(id, name)){
*index = std::make_shared<Table>(sname, icd->parent);
}
else {
CXZ_ERROR("IMPLEMENT!!!");
//*index = std::make_shared<DSet>(sname, icd->parent);
*index = std::make_shared<Dataset>(sname, icd->parent);
}
break;
}

View file

@ -9,17 +9,20 @@ namespace CNORXZ
Table::Table(const String& name, const ContentBase* _parent) :
ContentBase(name, _parent)
{
if(H5Lexists(mParent->id(), mName.c_str(), H5P_DEFAULT)){
if(exists()){
hsize_t nfields = 0;
hsize_t nrecords = 0;
H5TBget_table_info(mParent->id(), mName.c_str(), &nfields, &nrecords);
mRecords = CRangeFactory( nrecords ).create();
Vector<Arr<char,256>> fieldnames(nfields);
Vector<char*> fieldsptr(nfields);
for(SizeT i = 0; i != nfields; ++i){
fieldsptr[i] = fieldnames[i].data();
}
Vector<SizeT> offsets(nfields);
Vector<SizeT> sizes(nfields);
SizeT typesize = 0;
H5TBget_field_info(mParent->id(), mName.c_str(), fieldsptr.data(), sizes.data(),
offsets.data(), &typesize);
offsets.data(), &mTypesize);
Vector<FieldID> fields(nfields);
for(SizeT i = 0; i != nfields; ++i){
fields[i].first = i;
@ -62,6 +65,7 @@ namespace CNORXZ
if(mId == 0){
mId = H5Dopen(mParent->id(), mName.c_str(), H5P_DEFAULT);
mType = H5Dget_type(mId);
mkTypes();
}
return *this;
}
@ -71,6 +75,7 @@ namespace CNORXZ
if(mId != 0){
H5Tclose(mType);
H5Dclose(mId);
mId = 0;
}
return *this;
}
@ -85,6 +90,11 @@ namespace CNORXZ
return mParent->filename();
}
bool Table::exists() const
{
return H5Lexists(mParent->id(), mName.c_str(), H5P_DEFAULT) > 0;
}
Table& Table::initFieldNames(const Vector<String>& fnames)
{
CXZ_ASSERT(mFields == nullptr, "fields already initialized");
@ -106,28 +116,61 @@ namespace CNORXZ
for(auto fi = fr->begin(); fi != fr->end(); ++fi){
fields[fi.lex()] = (*fi).second.c_str();
}
mTypesize = dsize;
const herr_t err = H5TBmake_table
(mName.c_str(), mParent->id(), mName.c_str(), mFields->size(), mRecords->size(), dsize,
(mName.c_str(), mParent->id(), mName.c_str(), mFields->size(), mRecords->size(), mTypesize,
fields.data(), mOffsets.data(), mTypes.data(), chunk_size, NULL, compress, data);
CXZ_ASSERT(err >= 0, "error while initialzing table: error code = " << err);
return *this;
}
Table& Table::appendRecord(SizeT n, const void* data, SizeT dsize)
Table& Table::appendRecords(SizeT n, const void* data)
{
mRecords = mRecords->extend( CRangeFactory(1).create() );
const herr_t err = H5TBappend_records(mParent->id(), mName.c_str(), n, dsize,
mRecords = mRecords->extend( CRangeFactory(n).create() );
const herr_t err = H5TBappend_records(mParent->id(), mName.c_str(), n, mTypesize,
mOffsets.data(), mSizes.data(), data);
CXZ_ASSERT(err >= 0, "error while appending record to table: error code = " << err);
return *this;
}
Table& Table::readRecord(SizeT pos, SizeT n, char* data)
Table& Table::readRecords(SizeT pos, SizeT n, char* data)
{
CXZ_ERROR("not implemented!!!");
H5TBread_records(mParent->id(), mName.c_str(), pos, n, mTypesize, mOffsets.data(),
mSizes.data(), data);
return *this;
}
MArray<DType> Table::readRecord(SizeT pos) const
{
Vector<char> buf(mTypesize);
H5TBread_records(mParent->id(), mName.c_str(), pos, 1, mTypesize, mOffsets.data(),
mSizes.data(), buf.data());
MArray<DType> out(mFields);
auto fi = std::make_shared<CIndex>(mFields);
out(fi) = operation( [&](const SizeT& off, const std::function<DType(const char*)>& f){
return f( buf.data() + off );
}, mOffsets(fi), mInterpret(fi) );
return out;
}
MArray<DType> Table::read() const
{
Vector<char> buf(mTypesize*mRecords->size());
H5TBread_table(mParent->id(), mName.c_str(), mTypesize, mOffsets.data(),
mSizes.data(), buf.data());
MArray<DType> out(mRecords*mFields);
auto fi = std::make_shared<CIndex>(mFields);
auto ri = std::make_shared<CIndex>(mRecords);
out(ri*fi) = operation( [&](const SizeT& off, const std::function<DType(const char*)>& f, const SizeT r){
return f( buf.data() + r*mTypesize + off );
}, mOffsets(fi), mInterpret(fi), xpr(ri) );
return out;
}
const RangePtr& Table::fields() const
{
return mFields;
@ -138,5 +181,64 @@ namespace CNORXZ
return mRecords;
}
void Table::mkTypes()
{
mTypes = MArray<hid_t>(mFields);
auto i = std::make_shared<CIndex>(mFields);
mTypes(i) = operation( [&](const SizeT n){ return H5Tget_member_type( mType, n ); } , xpr(i) );
mInterpret = MArray<std::function<DType(const char*)>>(mFields);
mInterpret(i) = operation( [](const hid_t tid){
const hid_t tc = H5Tget_class(tid);
const size_t ts = H5Tget_size(tid);
const bool sig = H5Tget_sign(tid);
std::function<DType(const char*)> of;
switch(tc){
case H5T_INTEGER:{
switch(ts){
case 1:{ // 8-bit
of = sig ?
[](const char* d){ const int8_t x = *reinterpret_cast<const int8_t*>(d); return DType(static_cast<Int>(x)); } :
[](const char* d){ const uint8_t x = *reinterpret_cast<const uint8_t*>(d); return DType(static_cast<SizeT>(x)); };
break;
}
case 2:{ // 16-bit
of = sig ?
[](const char* d){ const int16_t x = *reinterpret_cast<const int16_t*>(d); return DType(static_cast<Int>(x)); } :
[](const char* d){ const uint16_t x = *reinterpret_cast<const uint16_t*>(d); return DType(static_cast<SizeT>(x)); };
break;
}
case 4:{ // 32-bit
of = sig ?
[](const char* d){ const int32_t x = *reinterpret_cast<const int32_t*>(d); return DType(static_cast<Int>(x)); } :
[](const char* d){ const uint32_t x = *reinterpret_cast<const uint32_t*>(d); return DType(static_cast<SizeT>(x)); };
break;
}
case 8:{ // 64-bit
of = sig ?
[](const char* d){ const int64_t x = *reinterpret_cast<const int64_t*>(d); return DType(static_cast<LInt>(x)); } :
[](const char* d){ const uint64_t x = *reinterpret_cast<const uint64_t*>(d); return DType(static_cast<SizeT>(x)); };
break;
}
default:
CXZ_ERROR("got integer of weird size: " << ts);
}
break;
}
case H5T_FLOAT:{
if(ts == 4) {
of = [](const char* d){ const float x = *reinterpret_cast<const float*>(d); return DType(static_cast<Double>(x)); };
}
else {
CXZ_ASSERT(ts == 8, "got float of weird size: " << ts);
of = [](const char* d){ const double x = *reinterpret_cast<const double*>(d); return DType(static_cast<Double>(x)); };
}
break;
}
default:
CXZ_ERROR("got unsupported type");
};
return of;
}, mTypes(i) );
}
}
}

View file

@ -1,5 +1,7 @@
add_definitions(-DTEST_NUMBER_FILE="${CMAKE_SOURCE_DIR}/src/tests/numbers.txt")
include_directories(${CMAKE_SOURCE_DIR}/src/tests)
add_executable(h5basic h5_basic_unit_test.cc)
add_dependencies(h5basic cnorxz cnorxzhdf5)
target_link_libraries(h5basic ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${HDF5_LIBS} cnorxz cnorxzhdf5)
add_dependencies(h5basic cnorxz cnorxzhdf5 test_lib)
target_link_libraries(h5basic ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${HDF5_LIBS} cnorxz cnorxzhdf5 test_lib)
add_test(NAME h5basic COMMAND h5basic)

View file

@ -7,11 +7,13 @@
#include "gtest/gtest.h"
#include "cnorxz_hdf5.h"
#include "test_numbers.h"
namespace
{
using namespace CNORXZ;
using namespace CNORXZ::hdf5;
using Test::Numbers;
static const String testh5file = "test_file.h5";
@ -39,24 +41,43 @@ namespace
Group_Test()
{
mFileName = testh5file;
mGrps = { "gr1", "gr2" };
mFs = {"field1","second","real"};
Vector<Tuple<SizeT,Int,Double>> v
( { {0, -6, 3.141},
{3, -8, 0.789},
{34, 4, 10.009},
{2, -777, -9.77},
{321, 0, -0.003}
// Tuple has reverse (!) memory ordering:
Vector<Tuple<Double,Int,SizeT>> v
( { { 3.141, -6, 0 },
{ 0.789, -8, 3 },
{ 10.009, 4, 34 },
{ -9.77, -777, 2 },
{ -0.003, 0, 321 }
} );
RangePtr rs = CRangeFactory(v.size()).create();
mTabA = MArray<Tuple<SizeT,Int,Double>>(rs, std::move(v));
RangePtr fs = CRangeFactory(mFs.size()).create();
mTabA = MArray<Tuple<Double,Int,SizeT>>(rs, std::move(v));
mTabD = MArray<DType>(rs*fs);
CIndex i(rs);
CIndex j(fs);
for(i = 0; i.lex() != rs->size(); ++i){
iter<0,3>( [&](auto jj)
{ j = jj; mTabD[i*j] = DType(std::get<3-jj-1>(v[i.lex()])); }, NoF{} );
}
const SizeT ddim = 5;
Vector<RangePtr> dranges(ddim);
dranges[0] = CRangeFactory(7).create();
dranges[1] = CRangeFactory(3).create();
dranges[2] = CRangeFactory(13).create();
dranges[3] = CRangeFactory(5).create();
dranges[4] = CRangeFactory(2).create();
const RangePtr drange = yrange(dranges);
mData = MArray<Double>( drange, Numbers::get(0,drange->size()) );
}
String mFileName;
Vector<String> mGrps;
Vector<String> mFs;
MArray<Tuple<SizeT,Int,Double>> mTabA;
Arr<String,3> mFs;
MArray<Tuple<Double,Int,SizeT>> mTabA;
MArray<DType> mTabD;
MArray<Double> mData;
};
@ -80,9 +101,28 @@ namespace
File h5f(mFileName, false);
EXPECT_FALSE(h5f.ro());
h5f.open();
h5f.addAttribute("fprop", static_cast<Double>(3.141));
h5f.addGroup("gr1");
h5f.getGroup("gr1")->addAttribute("att1", String("text"));
h5f.addGroup("gr2");
EXPECT_EQ(h5f.get().size(), 2u);
h5f.addGroup("foo");
h5f.addGroup("bar");
h5f.addGroup("moregroups");
auto moregroups = h5f.getGroup("moregroups");
moregroups->open().addGroup("evenmore");
auto evenmore = moregroups->getGroup("evenmore");
evenmore->open();
evenmore->addAttribute("moreatt", static_cast<Int>(12));
evenmore->addGroup("we");
evenmore->getGroup("we")->addAttribute("wex", static_cast<Int>(9));
evenmore->getGroup("we")->addAttribute("xy", String("xys"));
evenmore->addGroup("need");
evenmore->getGroup("need")->addAttribute("wex", static_cast<Int>(7));
evenmore->addGroup("more");
evenmore->getGroup("more")->addAttribute("wex", static_cast<Int>(4));
evenmore->addGroup("groups");
evenmore->getGroup("groups")->addAttribute("wex", static_cast<Int>(2));
EXPECT_EQ(h5f.get().size(), 5u);
h5f.close();
}
@ -91,7 +131,15 @@ namespace
File h5f(mFileName, false);
h5f.open();
h5f.getGroup("gr1")->open().addTable("tab1", mTabA, mFs);
h5f.getGroup("gr2")->open().addTable("tab1", mTabA, mFs);
h5f.getGroup("moregroups")->open().getGroup("evenmore")->open().getGroup("need")->open().addTable("tab1", mTabA, mFs);
h5f.close();
}
TEST_F(Group_Test, CreateDataset)
{
File h5f(mFileName, false);
h5f.open();
h5f.getGroup("gr2")->open().addDataset("dat1", mData);
h5f.close();
}
@ -100,7 +148,146 @@ namespace
File h5f(mFileName, true);
h5f.open();
EXPECT_TRUE(h5f.ro());
EXPECT_EQ(h5f.get().size(), 2u);
EXPECT_EQ(h5f.get().size(), 5u);
EXPECT_THROW(h5f.getGroup("gr0"), std::runtime_error);
auto gr1 = h5f.getGroup("gr1");
gr1->open();
auto tab = gr1->getTable("tab1");
DType att = gr1->getAttribute("att1");
EXPECT_EQ(att.str(), "text");
VCHECK(tab->path());
EXPECT_EQ(tab->fields()->size(), 3u);
EXPECT_EQ(tab->records()->size(), 5u);
EXPECT_THROW(h5f.getTable("moregroups/evenmore/need/tab1/a"), std::runtime_error);
auto tab2 = h5f.getTable("moregroups/evenmore/need/tab1/");
EXPECT_EQ(tab2->fields()->size(), 3u);
EXPECT_EQ(tab2->records()->size(), 5u);
h5f.iter( [](const auto& c) { VCHECK(c->path()); } )();
h5f.iterRecursive( [](const auto& c) { VCHECK(c->path()); } )();
h5f.iterRecursive( [](const auto& c) { c->open(); VCHECK(toString(c->getRecursiveAttributes())); } )();
h5f.iterRecursive( [](const auto& c) {
if(c->type() == ContentType::TABLE) { c->open(); VCHECK(toString(c->getRecursiveAttributes())); }
} )();
h5f.close();
}
TEST_F(Group_Test, ReadTable)
{
typedef Tuple<Double,Int,SizeT> RecType;
File h5f(mFileName, true);
h5f.open();
auto tab = h5f.getGroup("gr1")->open().getTable("tab1", RecType());
EXPECT_EQ(tab->fields()->size(), 3u);
EXPECT_EQ(tab->records()->size(), 5u);
tab->open();
auto cont = tab->read();
EXPECT_EQ(cont.size(), mTabA.size());
CIndex i(mTabA.range());
for(; i.lex() != i.lmax().val(); ++i){
EXPECT_EQ( cont[i], mTabA[i] );
}
auto dtab = h5f.getGroup("gr1")->open().getTable("tab1");
auto dcont = dtab->read();
EXPECT_EQ(dcont.range()->dim(), 2u);
EXPECT_EQ(dcont.range()->sub(0)->size(), 5u);
EXPECT_EQ(dcont.range()->sub(1)->size(), 3u);
for(auto ai = dcont.begin(); ai != dcont.end(); ++ai){
EXPECT_EQ(dcont[ai].str(), mTabD[ai].str());
}
h5f.close();
}
TEST_F(Group_Test, ReadDataset)
{
File h5f(mFileName, true);
h5f.open();
auto dset = h5f.getGroup("gr2")->open().getDataset("dat1", Double{});
auto data = dset->read();
EXPECT_EQ(data.range()->dim(), 5u);
for(SizeT i = 0; i != 5u; ++i){
EXPECT_EQ( data.range()->sub(i)->size(), mData.range()->sub(i)->size() );
}
auto i = std::make_shared<CIndex>(data.range());
i->ifor( operation( [](Double a, Double b) { EXPECT_EQ(a,b); }, data(i), mData(i) ), NoF{} )();
h5f.close();
}
TEST_F(Group_Test, ReadDatasetPart)
{
File h5f(mFileName, true);
h5f.open();
auto dset = h5f.getGroup("gr2")->open().getDataset("dat1", Double{});
YIndex beg(dset->dataRange());
beg.setSub(0,2);
YIndex end = beg - 1;
end.setSub(0,2);
auto data = dset->read(beg,end);
EXPECT_EQ( data.range()->dim(), 5u );
EXPECT_EQ( data.range()->sub(0)->size(), 1u );
for(SizeT i = 1; i != 5u; ++i){
EXPECT_EQ( data.range()->sub(i)->size(), mData.range()->sub(i)->size() );
}
auto i = std::make_shared<CIndex>(data.range());
auto j = std::make_shared<DIndex>( beg.pack().get(0) );
i->ifor( operation( [](Double a, Double b) { EXPECT_EQ(a,b); }, data(i), mData(j*i) ), NoF{} )();
h5f.close();
}
TEST_F(Group_Test, Read2)
{
File h5f(mFileName, true);
h5f.open();
Vector<String> paths;
Vector<String> attrs;
auto checkatt = [](const std::map<String,DType>& m,
const std::map<String,DType>& cs) {
for(const auto& c: cs){
if(m.count(c.first)){
if(m.at(c.first).str() != c.second.str()){
return false;
}
}
else {
return false;
}
}
return true;
};
std::map<String,DType> constr;
constr["wex"] = DType(Vector<Int>{7});
constr["second"] = DType(static_cast<Int>(-777));
h5f.iterRecursive( [&](const auto& c) {
if(c->type() == ContentType::TABLE) {
c->open();
auto av = c->getRecursiveAttributes();
auto cx = std::dynamic_pointer_cast<Table>(c);
SizeT cnt = 0;
cx->iterRecords( [&](const MArray<DType>& r) {
auto ax = av;
auto fi = UIndex<std::pair<SizeT,String>>(r.range()->sub(0));
for(; fi.lex() != fi.lmax().val(); ++fi) { ax[fi.meta().second] = r[fi]; }
attrs.push_back(toString(ax));
if(checkatt(ax,constr)){
paths.push_back(c->path()+"/@"+toString(cnt));
}
++cnt;
} )();
}
} )();
for(const auto& x: attrs){
VCHECK(x);
}
for(const auto& p: paths){
VCHECK(p);
}
EXPECT_EQ(paths.size(), 1u);
EXPECT_EQ(paths[0], "/moregroups/evenmore/need/tab1/@3");
h5f.close();
}
}

View file

@ -66,6 +66,7 @@ namespace
{
GMIndex<MFormat<4>,CIndex,CIndex,CIndex,CIndex> mi(mRange);
MIndex<CIndex,CIndex,CIndex,CIndex,CIndex> mi2(mRange2);
GMIndex<MFormat<4>,CIndex,GMIndex<MFormat<3>,CIndex,CIndex,CIndex>,CIndex,CIndex> mi32(mRange);
EXPECT_EQ(mi.lmax().val(), mRange->size());
EXPECT_EQ(mi2.lmax().val(), mRange2->size());
auto yi = indexAs<YIndex>( mRange->begin() );
@ -79,9 +80,20 @@ namespace
yi.setFormat( YFormat( Vector<SizeT>{ mi2.format()[CSizeT<0>{}].val(), mi2.format()[CSizeT<1>{}].val(), mi2.format()[CSizeT<2>{}].val(), mi2.format()[CSizeT<4>{}].val() } ) );
VCHECK(toString(yi.deepFormat()));
mi.reformat( yi.deepFormat(), yi.deepMax() );
VCHECK(toString(mi.deepFormat()));
VCHECK(toString(mi.deepMax()));
yi.setFormat( YFormat( Vector<SizeT>{ 13, 143, 1, 15015 } ) );
VCHECK(toString(yi.deepFormat()));
mi.reformat( yi.deepFormat(), yi.deepMax() );
VCHECK(toString(mi.deepFormat()));
VCHECK(toString(mi.deepMax()));
mi32.reformat( Vector<SizeT> { 105,1,2310,1155 }, Vector<SizeT> { 11,105,13,2 } );
VCHECK(toString(yi.deepFormat()));
mi32.reformat( yi.deepFormat(), yi.deepMax() );
VCHECK(toString(mi32.deepFormat()));
VCHECK(toString(mi32.deepMax()));
}
}