Compare commits

..

No commits in common. "main" and "multi-array-stable" have entirely different histories.

269 changed files with 19855 additions and 34828 deletions

View file

@ -1,36 +0,0 @@
# This file is based on https://github.com/satu0king/Github-Documentation-With-Doxygen/blob/master/main.yml
name: Doxygen Action
# Trigger workflow only on pushed to master branch:
on:
workflow_dispatch:
push:
branches: [ main ]
jobs:
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- name: Doxygen Action
uses: mattnotmitt/doxygen-action@v1.1.0
with:
# Path to Doxyfile
doxyfile-path: "./Doxyfile"
# Working directory
working-directory: "./doc/doxy"
- name: Deploy
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./doc/doxy/html
permissions:
contents: write

2
.gitignore vendored
View file

@ -5,5 +5,3 @@ install/
*/build/
*/install/
src/lib/hl_ops/*.cc
doc/doxy/html/
doc/doxy/latex/

17
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,17 @@
before_script:
- export GTEST_ROOT=/opt/gtest-1.8.0
image: docker.io/rqcd/centos-buildtools:7.2.1511
stages:
- build
build-centos:
stage: build
script:
- source /opt/rh/devtoolset-7/enable
- mkdir build
- cd build
- cmake3 ..
- make -j2
- make test

View file

@ -1,18 +0,0 @@
---
steps:
build:
image: chizeta/centos:8
commands:
- source /opt/rh/gcc-toolset-9/enable
- mkdir build-gcc
- cd build-gcc
- cmake3 -DSCALAR_BUILD=on ..
- make -j2
- make test
- cd ..
- mkdir build-clang
- cd build-clang
- CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake3 -DRUN_PIPELINE=on -DSCALAR_BUILD=on ..
- make -j2
- make test

View file

@ -1,38 +1,6 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 2.8)
project(cnorxz)
# LIB VERSION
set(V_MAJOR 0)
set(V_MINOR 0)
set(V_PATCH 0)
set(VERSION "${V_MAJOR}.${V_MINOR}.${V_PATCH}")
# 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 rev-parse --abbrev-ref HEAD" OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE)
# BUILD VERSION STRING
message(STATUS "git hash = ${GIT_HASH}")
message(STATUS "git branch = ${GIT_BRANCH}")
if(NOT ("${GIT_BRANCH}" EQUAL "release"))
string(SUBSTRING ${GIT_HASH} 0 7 GIT_HASH_SHORT)
set(VERSION "${VERSION}-${GIT_BRANCH}-${GIT_HASH_SHORT}")
endif()
message(STATUS "version = ${VERSION}")
# CHECK COMPILER
project(multi_array)
if(CMAKE_COMPILER_IS_GNUCXX)
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0)
@ -42,41 +10,20 @@ 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
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -std=c++17 -Wpedantic -Ofast -march=native -faligned-new -funroll-loops -fopenmp")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -std=c++14 -g -Wpedantic -Ofast -march=native -faligned-new -funroll-loops -fopenmp -ftemplate-backtrace-limit=0")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -std=c++14 -g -Wpedantic -O0 -march=native -faligned-new -funroll-loops -fopenmp")
enable_testing()
# INSTALL PATH
if(IS_ABSOLUTE "${CMAKE_INSTALL_PREFIX}")
set(INSTALL_PATH ${CMAKE_INSTALL_PREFIX})
else()
#set(INSTALL_PATH ${CMAKE_SOURCE_DIR}/install)
get_filename_component(INSTALL_PATH ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_PREFIX} ABSOLUTE)
endif()
message(STATUS "found absolute install path '${INSTALL_PATH}'")
message(WARNING "found absolute install path '${INSTALL_PATH}'")
# SCALAR / INTRINSICS
if(NOT ${SCALAR_BUILD})
message(STATUS "check for intrinsics")
check_avx()
if(AVX_AVAIL)
message(STATUS "AVX available")
add_definitions("-DCXZ_HAVE_AVX")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx")
else()
message(STATUS "AVX not available")
endif()
endif()
# CHECK LIBRARIES : GTest
message(STATUS "check for libraries")
find_package( GTest REQUIRED )
if(GTest_FOUND)
include_directories(${GTEST_INCLUDE_DIRS})
@ -84,8 +31,6 @@ else()
message(FATAL_ERROR "GTest not found")
endif()
# CHECK LIBRARIES : Threads
find_package(Threads REQUIRED)
if(Threads_FOUND)
#include_directories(${Threads_INCLUDE_DIRS})
@ -93,42 +38,4 @@ 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()
set(ENABLE_cereal TRUE CACHE BOOL "enable hdf5")
endif()
find_package(cereal QUIET)
if(cereal_FOUND)
message(STATUS "found cereal")
if(ENABLE_cereal)
message(STATUS "enable cereal")
add_definitions(-DHAVE_CEREAL)
endif()
else()
message(STATUS "no cereal")
if(ENABLE_cereal)
message(FATAL_ERROR "cereal has been enabled but the cereal library has not been found")
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)

21
LICENSE
View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 Christian Zimmermann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

198
README.md
View file

@ -1,154 +1,120 @@
# Container with Native Operation Routines and Expressions (CNORXZ)
(as always, the name was there before the acronym)
![Image](./cnorxz_logo.png)
# Container with Native Operation Routines by XZ (CNORXZ)
## Description
This library provides a framework for handling multi dimensional data containers (arrays or array-like types), their meta data, and several kinds of operations on one or more of them.
This library provides a framework for handling multi dimensional containers. This includes the basic container class template `ArrayBase` and their derivates, the Range class templates on which the containers are defined, as well as some operation class templates, which allow comfortable calling of operations on the containers.
## Build instructions
The library can be installed by the following procedure (`gtest` required):
```bash
git clone git@git.f3l.de:chizeta/cnorxz.git <LIBRARY_ROOT_DIR>
mkdir <BUILD_DIR>
git clone git@git.f3l.de:chizeta/cnorxz.git <SOURCE_DIR>
cd <BUILD_DIR>
cmake -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> <LIBRARY_ROOT_DIR>
cmake -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> <SOURCE_DIR>
make install
```
To build the doxygen:
```bash
cd <SOURCE_DIR>/doc/doxy
doxygen Doxyfile
```
## Linking
## Usage and Examples
To use the features of the libraries one has to include `cnorxz.h` and link against the `libcnorxz.so`.
The tools of the library are accessible within the namespace `CNORXZ`.
The tools of the library are accessible within the namespace `CONORXZ`.
## Documentation
### Some Terms
(Also consider doxygen)
* Ranges: A set of meta data which is mapped onto the linear position. Every container is supposed to be defined on at least one Range. In the simplest case a Range space "containes" the numbers [0,...,rangesize]. Ranges have to be created via the corresponding factory and only exist within a shared pointer. They cannot be copied. The reason is, that every operation performed on the containers, has to identify common sets of ranges, on which the containers are defined. Every range inherits the `RangeBase` class.
### Basics and Library organization
* Indices: They can be thought of as iterators of the range space. In the special case of the `ContainerIndex` it is also an iterator over the corresponding container. The index type must be known at compile time (static polymorphism). Indices on a range can be obtained by `getIndex( range )`. For Container Indices call the `begin()` function of a `Array`. Indices are crucial for defining operations.
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).
* `Array<T,Ranges...>`: Contains data of type `T` and is defined on `Ranges...`.
* `[Const]Slice<T,Ranges...>`: Views data of type `T` and acts as an Array defined on `Ranges...`.
* `FunctionalArray`: Additional template argument indicating the funtion. The value at some position is then defined by the function value obtained from the meta data of the indices/ranges.
#### Ranges {#sec-ranges}
On each of these types one can perform an operation by calling `operator(...)` where within the braces the corresponding indices have to be specified (see example below).
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:
### Example
* `CRange` : Classic one-dimensional range. The meta data space is simply given by integer numbers running from `0` to `size-1`. The range size is determined at runtime.
```c++
* `URange<MetaT>` : Generic One-dimensional range. The meta data space is user defined, the meta data type is passed as template argument. The range size is determined at runtime.
#include "cnorxz.h"
* `SRange<MetaT,S>` : The same as `URange`, but the range length is fixed at compile time by the template integer variable `S`.
namespace cnx = CNORXZ;
* `PRange<RangeT>` : Partial or sub-range, i.e. a user-defined subspace of another range. The type of the range must be known at compile time, the subspace can be specified at runtime.
typedef cnx::SingleRange<double,cnx::SpaceType::ANY> DRange;
typedef cnx::SingleRangeFactory<double,cnx::SpaceType::ANY> DRangeF;
typedef cnx::SingleRange<std::string,cnx::SpaceType::ANY> SRange;
typedef cnx::SingleRangeFactory<std::string,cnx::SpaceType::ANY> SRangeF;
typedef cnx::SingleRange<size_t,cnx::SpaceType::NONE> CRange; // also provided as 'ClassicR'
typedef cnx::SingleRangeFactory<size_t,cnx::SpaceType::NONE> CRangeF;
* `MRange<RangeTs...>` : Multi-dimensional range, spanned by a set of ranges. The number of ranges, as well as their types must be known at compile time.
/*create ranges*/
std::vector<double> meta1({...});
std::vector<double> meta2({...});
std::vector<std::string> meta3({...});
* `YRange` : The same as `MRange` but the number of ranges and their types can be specified at runtime.
DRangeF drf1(meta1);
DRangeF drf2(meta2);
SRangeF srf(meta3);
CRangeF crf(10); // specialized in this case; only size needed.
#### Indices {#sec-indices}
auto dr1 = cnx::createExplicit( drf1 );
auto dr2 = cnx::createExplicit( drf2 );
auto sr = cnx::createExplicit( srf );
auto cr = cnx::createExplicit( crf );
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>`).
cnx::Array<double,DRange,DRange,SRange,CRange> ma_a(dr1,dr2,sr,cr,0);
cnx::Array<double,SRange,SRange> ma_b(sr,sr,0);
Apart from range specific indices, there exist also special indices:
* `DIndex` : Dynamic index wrapper, for the case that the index type cannot be determined at compile time.
* `AIndex<T>` : Array index. Const iterators pointing to the data of an array-type object with data type `T`.
* `BIndex<T>` : The same as `AIndex`, but not const.
#### Array types {#sec-array-types}
Arrays or array-like types contain or view datasets and are derived from `CArrayBase<T>` (const) or `ArrayBase<T>` for a given data type `T`. All array types 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`.
#### Expressions and Operations
In the context of this library, *expressions* are classes representing an expression that is supposed to be executed at given points during an iteration proceedure that involves one or more indexed quantities. Each expression type must fulfill the following requirements:
* There must be an implementation of `operator()` taking a multi-position argument indicating the position for the current iteration of each involved object according to its indices. The function can have an expression defined return value, which can be further processed.
* There must be an implementation of `rootSteps()` taking an index ID as argument. The function should return jump sizes for each involved object corresponding to the given index.
Each expression `Xpr` should be derived from the class `XprInterface<Xpr>`, where `Xpr` is a recurring template argument (static polymorphism).
There are two important expression types:
* *For* expressions: They represent a for loop over a given index.
* *Operations*: They correspond to one or more indexed array types and given operation on or between them. If an operation handles nothing but the access to one single array, it is called *Operation* *Root*.
Example:
```cpp
#include "cnroxz.h"
using namespace CNORZX;
RangePtr r = CRangeFactory(3).create(); // [0,1,2]
RangePtr s = CRangeFactory(5).create(); // [0,1,2,3,4]
RangePtr t = URangeFactory<Int>(Vector<Int>{4,5,6}).create(); // [4,5,6]
i = std::make_shared<CIndex>(r);
j = std::make_shared<CIndex>(s);
k = std::make_shared<UIndex<Int>>(t);
MArray<Double> a(r*s*t); // 3-dim array, dimensions = [3,5,3], size = 45
MArray<Double> b(r*t); // 2-dim array, dimensions = [3,3], size = 9
MArray<Double> c(s*t); // 2-dim array, dimensions = [3,5], size = 15
// set array element values of a,b,c here...
c(j*k) += ( a(i*j*k) * b(j*k) * xpr(k) ).c(i);
/* Explanation of the above line:
c(j*k), a(i*j*k), b(j*k) and xpr(k) are operation roots, i.e.
they manage access to the arrays c,a,b and the meta data space of index k
The operations between the operation roots are also operations in the
sense of this nomenclature, i.e. a(i*j*k) * b(j*k) is again an operation.
The operation member function c() creates contraction, i.e. a for loop
over the given index (i). If no further functions are specified, the values
returned by the underlying operations are summed up for equivalent index
combinations.
The += invokes a for loop over the indices on the l.h.s.. The values returned
by the expression on the r.h.s. are added to the l.h.s. Something similar could be done
with a = operator. Then the values would just be assigned instead of added.
*/
// Equivalent C-stype for loop (if a,b,c were C-style arrays):
for(size_t j = 0; j < s; ++j){
for(size_t k = 0; k < t; ++k){
int kv = k+4;
double x = 0;
// the contraction part:
for(size_t i = 0; i < r; ++i){
x += a[i*s*t+j*t+k] * b[j*t+k] * kv;
}
c[j*t+k] += x;
}
/* assign some values... */
double val = 1.;
for(auto& x: ma_a){
x = val += 1;
}
for(auto& x: ma_b){
x = val /= 2.;
}
cnx::FunctionalArray<double,plus<double>,DRange,DRange> fma(dr1,dr2);
cnx::Array<double,DRange,DRange> res1(dr1,dr2);
cnx::Array<double,DRange,DRange> res2(dr1,dr2);
/* get indices... */
auto i1 = cnx::getIndex( dr1 );
auto i2 = cnx::getIndex( dr2 );
auto i3 = cnx::getIndex( sr );
auto i4 = cnx::getIndex( sr );
auto i5 = cnx::getIndex( cr );
i3->at(<metaString>);
i5->at(<metaNum>);
/* performs plus operation on each element in hypercube spanned by i1,i2,i4
* and sums up resulting values by iterating over i4. i3 and i5 are fixed to the positions
* given by the meta data above : */
res1(i1,i2) += (ma_a(i1,i2,i4,i5) + ma_b(i4,i3)).c(i4);
/* calculates i2.meta() + i1.meta() and divide res1 at the corresponding entry by the result */
res2(i1,i2) = res1(i1,i2) / fma(i2,i1)
```
More documentation will follow...
Further examples will follow; you can also look in the test executable source files in `./src/test/*.cc`
## Acknowledgments
# Multithreading
GitHub Doxygen Task based on work by [satu0king](https://github.com/satu0king/Github-Documentation-With-Doxygen/tree/master).
Multithreading can be enabled by the operation class member function `par()`, which will parallelize the top loop. E.g. for the operation in the example above:
```c++
/* Enable multithreading for the loop over i1 */
res1(i1,i2).par() = (ma_a(i1,i2,i4,i5) + ma_b(i4,i3)).c(i4);
```
Caution: If you want to multithread operations over functional arrays, you have to make sure by yourself that involved functors are either static or const (const member variables).
I want to thank Gesina Schwalbe for creating the logo.
# Planned features
Basically the structure of the operation routines allows in some cases (at least in those, where it is possible for simple c++ for loops) vectorization. So far the necessary implamentations are not done, but it is planned to enable these features.
# Known Issues
I didn't care that much about error handling because of missing time. There it might happen that you declare a `Array` or `Slice` and an operation on it yields a segfault because it was forgotten to instancate the underlying container. Of course, there should be some mechanism, that catches such things, but due to the afore mentioned lack of time, it has not been implemented in every case. If you encounter such problems, pleas tell me, but be aware, that I won't fix it very soon.
There are unit tests, which cover the all crucial parts of this library, but probably not every special case. Hence, there is no warranty, that, if you do something fancy I didn't consider, everything works fine.

14
TODO
View file

@ -1,14 +0,0 @@
include/operation/op_types.cc.h@225: "build and execute assign expression forwarding outer index"
include/operation/op_types.cc.h@498: "implement ifor with func arg"
opt/hdf5/include/h5_content_base.h@23: "IO save error handling"
opt/hdf5/lib/h5_dataset.cc@124: "all sub-ranges explicity"
lib/ranges/crange.cc@94: "preliminary solution (TODO: implement xpr that simply returns PosT value)"
include/ranges/srange.cc.h@307: "check for selected static sizes of SRange -> return SRange"
include/xpr/for.cc.h@324: "check for write access"
include/base/dtype.cc.h@23: "for tuple use vector<DType>"
include/ranges/urange.cc.h@384: "else general transform using DType (better than nothing), to be implemented"
include/ranges/urange.cc.h@448: "else general transform using DType (better than nothing), to be implemented"
include/array/array_base.cc.h@184: "check further compatibility of index/range format"
include/array/array_base.cc.h@376: "check further compatibility of index/range format"
include/ranges/index_base.cc.h@109: "if this assert never applies, remove mPtrId (-> Defaults)"

View file

@ -1,24 +0,0 @@
macro(check_avx)
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_FLAGS "-Wall -Werror -Wpedantic -std=c++17 -mavx")
check_cxx_source_compiles("
#include <immintrin.h>
#include <iostream>
int main()
{
const double a[4] = { 0,0,0,0 };
const double b[4] = { 0,0,0,0 };
double o[4] = { 0,0,0,0 };
__m256d av = _mm256_load_pd(a);
__m256d bv = _mm256_load_pd(b);
__m256d ov = _mm256_add_pd(av, bv);
_mm256_store_pd(o, ov);
std::cout << o[0] << std::endl;
return 0;
}
"
AVX_AVAIL
)
endmacro()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

View file

@ -1,36 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.10.0"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>CNORXZ: Container with Native Operation Routines and Expressions (CNORXZ)</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<script type="text/javascript" src="clipboard.js"></script>
<script type="text/javascript" src="cookie.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<link rel="icon" href="$relpath^cnorxz_logo_mini.png" type="image/x-icon" />
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<td id="projectlogo"><img alt="Logo" src="cnorxz_logo_mini.png"/></td>
<td id="projectalign">
<div id="projectname">CNORXZ
</div>
<div id="projectbrief">Container with Native Operation Routines and Expressions</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->

View file

@ -1 +0,0 @@
../../../cnorxz_logo.png

View file

@ -2,14 +2,5 @@
include_directories(${CMAKE_SOURCE_DIR}/src/include)
add_subdirectory(tests)
add_subdirectory(lib)
add_subdirectory(bin)
if(ENABLE_hdf5)
add_subdirectory(opt/hdf5)
endif()
if(ENABLE_cereal)
add_subdirectory(opt/cereal)
endif()
install(DIRECTORY include/ DESTINATION ${INSTALL_PATH}/include/cnorxz)
install(DIRECTORY include/ DESTINATION ${INSTALL_PATH}/include)

View file

@ -1,6 +0,0 @@
add_executable(cnorxz-config config.cc)
add_dependencies(cnorxz-config cnorxz)
target_link_libraries(cnorxz-config cnorxz)
install(TARGETS cnorxz-config RUNTIME DESTINATION ${INSTALL_PATH}/bin)

View file

@ -1,62 +0,0 @@
// -*- C++ -*-
/**
@file bin/config.cc
@brief Program for printing cnorxz configurations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include <cstdlib>
#include <iostream>
#include <map>
#include <functional>
#include "base/config.h"
using CNORXZ::String;
using CNORXZ::SizeT;
typedef std::map<String,std::function<String(void)>> CMapT;
auto configMap()
{
CMapT m;
m["--version"] = CNORXZ::Config::version;
m["--commit"] = CNORXZ::Config::commit;
m["--flags"] = CNORXZ::Config::flags;
return m;
}
void printUsage(const String& prog, const CMapT& cm)
{
std::cout << "usage: " << prog << " ";
for(const auto& x: cm){
std::cout << "[" << x.first << "] ";
}
std::cout << std::endl;
}
int main(int argc, char** argv)
{
const String prog(argv[0]);
const auto cm = configMap();
if(argc == 1){
printUsage(prog, cm);
}
try {
for(SizeT i = 1; i != static_cast<SizeT>(argc); ++i){
std::cout << cm.at( String(argv[i]) )() << std::endl;
}
}
catch(const std::out_of_range& e){
std::cerr << "caught exception: " << e.what() << std::endl;
printUsage(prog, cm);
return 1;
}
catch(...){
std::cerr << "caught generic exception" << std::endl;
}
return 0;
}

41
src/include/access.cc.h Normal file
View file

@ -0,0 +1,41 @@
#include "access.h"
namespace CNORXZ
{
namespace
{
using namespace CNORXZInternal;
}
/************************
* AccessTemplate *
************************/
template <class AccessClass>
auto AccessTemplate<AccessClass>::get(size_t pos)
{
return THIS().get(pos);
}
template <class AccessClass>
auto AccessTemplate<AccessClass>::get(size_t pos) const
{
return THIS().get(pos);
}
template <class AccessClass>
auto AccessTemplate<AccessClass>::oget(size_t pos) const
{
return THIS().oget(pos);
}
template <class AccessClass>
template <class F, typename Op, class ExtType>
void AccessTemplate<AccessClass>::exec(size_t pos, const Op& op, ExtType e) const
{
return THIS().template exec<F>(pos,op,e);
}
} // namespace CNORXZ

173
src/include/access.h Normal file
View file

@ -0,0 +1,173 @@
#ifndef __cxz_access_h__
#define __cxz_access_h__
namespace CNORXZ
{
namespace
{
using namespace CNORXZInternal;
}
template <class T>
struct VType
{
typedef T type;
static constexpr size_t MULT = sizeof(type)/sizeof(T);
};
template <>
struct VType<double>
{
typedef v256 type;
static constexpr size_t MULT = sizeof(type)/sizeof(double);
};
template <template <typename...> class F,typename... Ts>
inline auto mkVFuncPtr(const std::shared_ptr<F<Ts...>>& f)
{
return std::shared_ptr<F<typename VType<Ts>::type...>>();
// empty, implement corresponding constructors...!!!
}
template <template <typename...> class F,typename... Ts>
inline auto mkVFunc(const F<Ts...>& f)
{
return F<typename VType<Ts>::type...>();
// empty, implement corresponding constructors...!!!
}
template <class F>
using VFunc = decltype(mkVFunc(std::declval<F>()));
//template <class F>
//using VFunc = F;
template <typename T, class F, class... Indices>
class OpAccess
{
private:
std::tuple<std::shared_ptr<Indices>...> mInds;
public:
static constexpr bool ISSTATIC = false;
template <typename Op, class ExtType>
inline void operator()(T*& t, size_t pos, const Op& op, ExtType e)
{
F::selfApply(t[pos](mInds), op.get(e)); // s.th. like that
// TODO for classes related to the r.h.s.:
// forward get(e) to elements returned by get(e) until basic types are reached
// (also same for rootSteps etc...) !!!!
// introduce traits !!!!
// !!!!
}
};
// static polymorphism
template <class AccessClass>
class AccessTemplate
{
public:
typedef AccessClass AC;
AccessTemplate(const AccessTemplate& in) = default;
AccessTemplate(AccessTemplate&& in) = default;
AccessTemplate& operator=(const AccessTemplate& in) = default;
AccessTemplate& operator=(AccessTemplate&& in) = default;
AccessClass& THIS() { return static_cast<AccessClass&>(*this); }
const AccessClass& THIS() const { return static_cast<const AccessClass&>(*this); }
inline auto get(size_t pos);
inline auto get(size_t pos) const;
inline auto oget(size_t pos) const;
template <class F, typename Op, class ExtType>
inline void exec(size_t pos, const Op& op, ExtType e) const;
protected:
AccessTemplate() = default;
};
template <typename T>
class PointerAccess : public AccessTemplate<PointerAccess<T>>
{
public:
typedef T value_type;
typedef T in_type;
static constexpr size_t VSIZE = sizeof(value_type) / sizeof(in_type);
friend class AccessTemplate<PointerAccess<T>>;
private:
PointerAccess() = default;
T* mPtr = nullptr;
T* mOrigPtr = nullptr;
public:
PointerAccess(T* ptr, T* origPtr) : mPtr(ptr), mOrigPtr(origPtr) {}
PointerAccess(const PointerAccess& in) = default;
PointerAccess(PointerAccess&& in) = default;
PointerAccess& operator=(const PointerAccess& in) = default;
PointerAccess& operator=(PointerAccess&& in) = default;
T* get(size_t pos) { return mPtr+pos; }
T* get(size_t pos) const { return mPtr+pos; }
PointerAccess<T>& set(size_t pos) { mPtr = mOrigPtr + pos; return *this; }
T* oget(size_t pos) const { return mOrigPtr+pos; }
template <class F, typename Op, class ExtType>
inline void exec(size_t pos, const Op& op, ExtType e) const
{
F::selfApply(*get(pos),op.get(e));
}
};
template <typename T>
class VPointerAccess : public AccessTemplate<VPointerAccess<T>>
{
public:
typedef typename VType<T>::type value_type;
typedef T in_type;
static constexpr size_t VSIZE = sizeof(value_type) / sizeof(in_type);
friend class AccessTemplate<VPointerAccess<T>>;
private:
VPointerAccess() = default;
T* mPtr = nullptr;
T* mOrigPtr = nullptr;
public:
VPointerAccess(T* ptr, T* origPtr) : mPtr(ptr), mOrigPtr(origPtr) {}
VPointerAccess(const PointerAccess<T>& in) : mPtr(in.get(0)), mOrigPtr(in.oget(0)) {}
VPointerAccess(const VPointerAccess& in) = default;
VPointerAccess(VPointerAccess&& in) = default;
VPointerAccess& operator=(const VPointerAccess& in) = default;
VPointerAccess& operator=(VPointerAccess&& in) = default;
value_type* get(size_t pos) { return reinterpret_cast<value_type*>(mPtr+pos); }
value_type* get(size_t pos) const { return reinterpret_cast<value_type*>(mPtr+pos); }
VPointerAccess<T>& set(size_t pos) { mPtr = mOrigPtr + pos; return *this; }
value_type* oget(size_t pos) const { return reinterpret_cast<value_type*>(mOrigPtr+pos); }
template <class F, typename Op, class ExtType>
inline void exec(size_t pos, const Op& op, ExtType e) const
{
F::selfApply(*get(pos),op.template vget<value_type>(e));
}
};
} // namespace CNORXZ
#endif

89
src/include/allocator.h Normal file
View file

@ -0,0 +1,89 @@
#ifndef __cxz_allocator__
#define __cxz_allocator__
#include <cstdlib>
#include <new>
#include <vector>
#include <cstdint>
#include <cassert>
#include <iostream>
#define MIB_SIZE 1024*1024 // 1MiB
#define WARN_SIZE MIB_SIZE*100 // 100 MiB
namespace CNORXZInternal
{
template <typename T>
struct Allocator
{
typedef T value_type;
static constexpr size_t type_size = sizeof(value_type);
static constexpr size_t N = 32;
struct VX
{
alignas(N) char x[N];
};
Allocator() = default;
template <typename U>
Allocator(const Allocator<U>& x) {}
T* allocate(size_t n)
{
const size_t nn = n*type_size;
if(nn >= WARN_SIZE){
std::cout << __func__ << ": WARNING: allocating " << nn/(MIB_SIZE) << " MiB" << std::endl;
}
const size_t off = nn%N;
const size_t nnx = (off == 0) ? nn : nn + N - off;
const size_t nnd = nnx/N;
VX* vx = new VX[nnd];
return reinterpret_cast<T*>(vx);
}
void deallocate(T* p, size_t n)
{
VX* vx = reinterpret_cast<VX*>(p);
delete [] vx;
}
};
template <class T, class U>
bool operator==(const Allocator<T>& a, const Allocator<U>& b)
{
return true;
}
template <class T, class U>
bool operator!=(const Allocator<T>& a, const Allocator<U>& b)
{
return false;
}
} // namespace CNORXZInternal
namespace CNORXZ
{
template <typename T>
using vector = std::vector<T,CNORXZInternal::Allocator<T>>;
template <typename T>
inline std::vector<T> toStdVec(const vector<T>& v)
{
return std::vector<T>(v.begin(), v.end());
}
template <typename T>
inline vector<T> toMatVec(const std::vector<T>& v)
{
return vector<T>(v.begin(), v.end());
}
} // namespace CNORXZ
#endif

35
src/include/arith.cc.h Normal file
View file

@ -0,0 +1,35 @@
#include "arith.h"
namespace CNORXZ
{
template <class F>
template <class... Ops>
auto StaticFunctionBase<F>::mk(const Ops&... ops)
{
return Operation<typename F::value_type,F,Ops...>(ops...);
}
template <class F>
template <size_t N, class Tuple, typename... As>
inline auto StaticFunctionBase<F>::xapply(const Tuple& tp, As... as)
{
if constexpr(N > 0){
return xapply<N-1>(tp, std::get<N>(tp), as...);
}
else {
return F::apply(std::get<0>(tp), as...);
}
}
template <class F>
template <typename... As>
inline auto StaticFunctionBase<F>::apply(const std::tuple<As...>& arg)
{
return xapply<sizeof...(As)-1>(arg);
//return ArgPack<sizeof...(As)-1>::template mk<F,std::tuple<As...> >(arg);
}
}

213
src/include/arith.h Normal file
View file

@ -0,0 +1,213 @@
#ifndef __cxz_arith_h__
#define __cxz_arith_h__
#include <functional>
namespace CNORXZ
{
//template <typename T, class F, typename... As>
template <class F>
struct StaticFunctionBase
{
static constexpr bool FISSTATIC = true;
typedef F function;
//typedef typename F::value_type value_type;
template <class... Ops>
static auto mk(const Ops&... ops);
template <size_t N, class Tuple, typename... As>
static inline auto xapply(const Tuple& tp, As... as);
template <typename... As>
static inline auto apply(const std::tuple<As...>& arg);
};
// OPERATIONS (STATIC)
template <typename T>
struct identity : public StaticFunctionBase<identity<T>>
{
//static constexpr bool FISSTATIC = true;
using StaticFunctionBase<identity<T>>::apply;
typedef T value_type;
static inline T apply(T a)
{
return a;
}
static inline T selfApply(T& a1, const T& a2)
{
return a1 = a2;
}
};
template <typename T, typename U>
using plusv = decltype(std::declval<T>()+std::declval<U>());
template <typename T, typename U>
using minusv = decltype(std::declval<T>()-std::declval<U>());
template <typename T, typename U>
using multipliesv = decltype(std::declval<T>()*std::declval<U>());
template <typename T, typename U>
using dividesv = decltype(std::declval<T>()/std::declval<U>());
template <typename T, typename U>
struct plusx : public StaticFunctionBase<plusx<T,U>>
{
static constexpr bool FISSTATIC = true;
using StaticFunctionBase<plusx<T,U>>::apply;
typedef plusv<T,U> value_type;
static inline value_type apply(T a1, U a2)
{
return a1 + a2;
}
static inline T& selfApply(T& a1, const T& a2)
{
return a1 += a2;
}
};
template <typename T, typename U>
struct minusx : public StaticFunctionBase<minusx<T,U>>
{
static constexpr bool FISSTATIC = true;
using StaticFunctionBase<minusx<T,U>>::apply;
typedef minusv<T,U> value_type;
static inline value_type apply(T a1, U a2)
{
return a1 - a2;
}
};
template <typename T, typename U>
struct multipliesx : public StaticFunctionBase<multipliesx<T,U>>
{
static constexpr bool FISSTATIC = true;
using StaticFunctionBase<multipliesx<T,U>>::apply;
typedef multipliesv<T,U> value_type;
static inline value_type apply(T a1, U a2)
{
return a1 * a2;
}
};
template <typename T, typename U>
struct dividesx : public StaticFunctionBase<dividesx<T,U>>
{
static constexpr bool FISSTATIC = true;
using StaticFunctionBase<dividesx<T,U>>::apply;
typedef dividesv<T,U> value_type;
static inline value_type apply(T a1, U a2)
{
return a1 / a2;
}
};
template <typename T>
struct negate : public StaticFunctionBase<negate<T>>
{
static constexpr bool FISSTATIC = true;
using StaticFunctionBase<negate<T>>::apply;
typedef T value_type;
static inline T apply(T a)
{
return -a;
}
};
template <typename T>
using plus = plusx<T,T>;
template <typename T>
using minus = minusx<T,T>;
template <typename T>
using multiplies = multipliesx<T,T>;
template <typename T>
using divides = dividesx<T,T>;
// OPERATIONS (STATIC)
template <typename R, typename... Args>
class function
{
public:
static constexpr bool FISSTATIC = false;
private:
std::function<R(Args...)> mF;
public:
function() = default;
function(const std::function<R(Args...)>& in) : mF(in) {}
inline R operator()(const Args&... args)
{
return mF(args...);
}
template <size_t N, class Tuple, typename... As>
static inline auto xapply(const std::function<R(Args...)>& ff, const Tuple& tp, As... as)
{
if constexpr(N > 0){
return xapply<N-1>(ff, tp, std::get<N>(tp), as...);
}
else {
return ff(std::get<0>(tp), as...);
}
}
inline R operator()(const std::tuple<Args...>& args)
{
return xapply<sizeof...(Args)-1>(mF, args);
}
};
#include <cmath>
#define regFunc1(fff) template <typename T>\
struct x_##fff : public StaticFunctionBase<x_##fff<T>> {\
static constexpr bool FISSTATIC = true;\
typedef T value_type; \
static inline T apply(T a){\
return fff(a); } };
#include "extensions/math.h"
#undef regFunc1
template <size_t N>
struct x_ipow
{
static constexpr bool FISSTATIC = true;
template <typename T>
static inline T apply(T a)
{
if constexpr(N > 0){
return a * x_ipow<N-1>::apply(a);
}
else {
return a;
}
}
};
} // end namespace CNORXZInternal
#include "arith.cc.h"
#endif

View file

@ -1,109 +0,0 @@
// -*- C++ -*-
/**
@file include/array/aindex.cc.h
@brief Array index template implementations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_aindex_cc_h__
#define __cxz_aindex_cc_h__
#include "aindex.h"
namespace CNORXZ
{
template <typename T>
AIndex<T>::AIndex(const T* data, const RangePtr& range, SizeT lexpos) :
YIndex(range, lexpos),
mCData(data)
{}
template <typename T>
AIndex<T>::AIndex(const T* data, const YIndex& yindex) :
YIndex(yindex),
mCData(data)
{}
template <typename T>
AIndex<T>::AIndex(const T* data, const AIndex<T>& aindex) :
AIndex<T>(aindex)
{
mCData = data;
}
template <typename T>
AIndex<T> AIndex<T>::operator+(Int n) const
{
AIndex<T> o = *this;
o += n;
return o;
}
template <typename T>
AIndex<T> AIndex<T>::operator-(Int n) const
{
AIndex<T> o = *this;
o -= n;
return o;
}
template <typename T>
const T& AIndex<T>::operator*() const
{
return mCData[IB::mPos];
}
template <typename T>
const T* AIndex<T>::operator->() const
{
return mCData + IB::mPos;
}
template <typename T>
BIndex<T>::BIndex(T* data, const RangePtr& range, SizeT lexpos) :
AIndex<T>(data, range, lexpos),
mData(data)
{}
template <typename T>
BIndex<T>::BIndex(T* data, const AIndex<T>& ai) :
AIndex<T>(data, ai),
mData(data)
{}
template <typename T>
BIndex<T> BIndex<T>::operator+(Int n) const
{
BIndex<T> o = *this;
o += n;
return o;
}
template <typename T>
BIndex<T> BIndex<T>::operator-(Int n) const
{
BIndex<T> o = *this;
o -= n;
return o;
}
template <typename T>
T& BIndex<T>::operator*()
{
return mData[IB::mPos];
}
template <typename T>
T* BIndex<T>::operator->()
{
return mData + IB::mPos;
}
}
#endif

View file

@ -1,71 +0,0 @@
// -*- C++ -*-
/**
@file include/array/aindex.h
@brief Array index declaration.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_aindex_h__
#define __cxz_aindex_h__
#include "ranges/range_base.h"
#include "ranges/index_base.h"
#include "ranges/xindex.h"
#include "ranges/yrange.h"
namespace CNORXZ
{
// AIndex (A = Array)
template <typename T>
class AIndex : public YIndex
{
public:
typedef YIndex::IB IB;
using YIndex::operator=;
DEFAULT_MEMBERS(AIndex);
AIndex(const T* data, const RangePtr& range, SizeT lexpos = 0);
AIndex(const T* data, const YIndex& yindex);
AIndex(const T* data, const AIndex<T>& aindex);
AIndex operator+(Int n) const;
AIndex operator-(Int n) const;
const T& operator*() const;
const T* operator->() const;
protected:
const T* mCData = nullptr;
};
// BIndex (because B comes after A...)
template <typename T>
class BIndex : public AIndex<T>
{
public:
typedef AIndex<T> AI;
typedef typename AI::IB IB;
DEFAULT_MEMBERS(BIndex);
BIndex(T* data, const RangePtr& range, SizeT pos = 0);
BIndex(T* data, const AIndex<T>& cci);
BIndex operator+(Int n) const;
BIndex operator-(Int n) const;
T& operator*();
T* operator->();
private:
T* mData = nullptr;
};
}
#endif

View file

@ -1,15 +0,0 @@
// -*- C++ -*-
/**
@file include/array/array.cc.h
@brief Array main header for template implementations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "array_base.cc.h"
#include "marray.cc.h"
#include "aindex.cc.h"
#include "slice.cc.h"

View file

@ -1,17 +0,0 @@
// -*- C++ -*-
/**
@file include/array/array.h
@brief Array main header.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "array_base.h"
#include "marray.h"
#include "aindex.h"
#include "slice.h"
#include "array.cc.h"

View file

@ -1,382 +0,0 @@
// -*- C++ -*-
/**
@file include/array/array_base.cc.h
@brief Array base class template implementations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_array_base_cc_h__
#define __cxz_array_base_cc_h__
#include "array_base.h"
#include "slice.h"
namespace CNORXZ
{
/*=======================================================+
| Implementations for CArrayBase member functions |
+=======================================================*/
template <typename T>
CArrayBase<T>::CArrayBase(const RangePtr& range) :
mRange(rangeCast<YRange>(range))
{}
template <typename T>
template <typename I, typename M>
const T& CArrayBase<T>::operator[](const IndexInterface<I,M>& i) const
{
if(formatIsTrivial()){
return data()[i.lex()];
}
else {
auto ai = itLex(i);
return *ai;
}
}
template <typename T>
template <typename I, typename M>
const T& CArrayBase<T>::at(const IndexInterface<I,M>& i) const
{
auto ai = itLexSave(i);
return *ai;
}
template <typename T>
template <class... Indices>
const T& CArrayBase<T>::operator[](const SPack<Indices...>& pack) const
{
if(formatIsTrivial()){
return data()[pack.lex()];
}
else {
auto ai = itLex(pack);
return *ai;
}
}
template <typename T>
template <class... Indices>
const T& CArrayBase<T>::at(const SPack<Indices...>& pack) const
{
auto ai = itLexSave(pack);
return *ai;
}
template <typename T>
const T& CArrayBase<T>::operator[](const DPack& pack) const
{
auto ai = itLex(pack);
return *ai;
}
template <typename T>
const T& CArrayBase<T>::at(const DPack& pack) const
{
auto ai = itLexSave(pack);
return *ai;
}
template <typename T>
template <typename I, typename M>
Sptr<CArrayBase<T>> CArrayBase<T>::sl(const IndexInterface<I,M>& begin,
const IndexInterface<I,M>& end) const
{
auto ai = itLexSave(begin);
auto aj = itLexSave(end);
return std::make_shared<CSlice<T>>(ai.prange(aj), this, ai.format(), ai.pos());
}
template <typename T>
SizeT CArrayBase<T>::size() const
{
return mRange->size();
}
template <typename T>
RangePtr CArrayBase<T>::range() const
{
return mRange;
}
template <typename T>
typename CArrayBase<T>::const_iterator CArrayBase<T>::begin() const
{
return this->cbegin();
}
template <typename T>
typename CArrayBase<T>::const_iterator CArrayBase<T>::end() const
{
return this->cend();
}
template <typename T>
template <class Index>
COpRoot<T,Index> CArrayBase<T>::operator()(const Sptr<Index>& i) const
{
if(formatIsTrivial()){
// assert that index format is trivial and has correct extensions
CXZ_ASSERT(i->formatIsTrivial(),
"got non-trivial index for container with trivial format");
this->checkFormatCompatibility(*i);
return coproot(*this, i);
}
else {
if(i->formatIsTrivial()){
// try to apply container format.
// if the reformat changes the index type in any manner
// the format is not applicable:
if constexpr(std::is_same<decltype(i->reformat( Vector<SizeT>(), Vector<SizeT>() )),Index>::value){
auto beg = begin();
auto aformat = beg.deepFormat();
auto amax = beg.deepMax();
auto fi = i->reformat( aformat, amax );
return coproot(*this, moveToPtr( fi ) );
}
else {
this->checkFormatCompatibility(*i);
return coproot(*this, i);
}
}
else {
// check if format is compatible
this->checkFormatCompatibility(*i);
return coproot(*this, i);
}
}
}
template <typename T>
template <class... Indices>
inline decltype(auto) CArrayBase<T>::operator()(const SPack<Indices...>& pack) const
{
return operator()(mindexPtr(pack));
}
template <typename T>
inline decltype(auto) CArrayBase<T>::operator()(const DPack& pack) const
{
return operator()(yindexPtr(pack));
}
/*=================================================================+
| Implementations for protected CArrayBase member functions |
+=================================================================*/
template <typename T>
template <class Acc>
typename CArrayBase<T>::const_iterator CArrayBase<T>::itLex(const Acc& acc) const
{
return begin() + acc.lex();
}
template <typename T>
template <class Acc>
typename CArrayBase<T>::const_iterator CArrayBase<T>::itLexSave(const Acc& acc) const
{
CXZ_ASSERT(acc.lex() < this->size(), "index out of range");
// check further compatibility of index/range format!!!
return begin() + acc.lex();
}
template <typename T>
template <class Acc>
void CArrayBase<T>::checkFormatCompatibility(const Acc& acc) const
{
auto j = begin();
CXZ_ASSERT(acc.lmax().val() == j.lmax().val(),
"got index of iteration space size = " << acc.lmax().val()
<< ", expected size = " << acc.lmax().val());
Vector<SizeT> f1 = toVec(acc.deepFormat());
Vector<SizeT> f2 = j.deepFormat();
std::sort(f1.begin(),f1.end());
std::sort(f2.begin(),f2.end());
SizeT i1 = 0;
SizeT i2 = 0;
CXZ_ASSERT(f1[i1] == f2[i2], "obtained format " << toString(f1)
<< ", which is incompatible to target format " << toString(f2));
++i1;
++i2;
while(i1 < f1.size() and i2 < f2.size()){
if(f1[i1] < f2[i2]) {
if(++i1 == f1.size()) break;
CXZ_ASSERT(f1[i1] <= f2[i2], "obtained format " << toString(f1)
<< ", which is incompatible to target format " << toString(f2));
}
else if(f1[i1] > f2[i2]) {
if(++i2 == f2.size()) break;
CXZ_ASSERT(f1[i1] >= f2[i2], "obtained format " << toString(f1)
<< ", which is incompatible to target format " << toString(f2));
}
else {
++i1;
++i2;
}
}
}
/*======================================================+
| Implementations for ArrayBase member functions |
+======================================================*/
template <typename T>
ArrayBase<T>::ArrayBase(const RangePtr& range) :
CArrayBase<T>(range)
{}
template <typename T>
template <typename I, typename M>
T& ArrayBase<T>::operator[](const IndexInterface<I,M>& i)
{
if(this->formatIsTrivial()){
return data()[i.lex()];
}
else {
auto ai = itLex(i);
return *ai;
}
}
template <typename T>
template <typename I, typename M>
T& ArrayBase<T>::at(const IndexInterface<I,M>& i)
{
auto ai = itLexSave(i);
return *ai;
}
template <typename T>
template <class... Indices>
T& ArrayBase<T>::operator[](const SPack<Indices...>& pack)
{
if(this->formatIsTrivial()){
return data()[pack.lex()];
}
else {
auto ai = itLex(pack);
return *ai;
}
}
template <typename T>
template <class... Indices>
T& ArrayBase<T>::at(const SPack<Indices...>& pack)
{
auto ai = itLexSave(pack);
return *ai;
}
template <typename T>
T& ArrayBase<T>::operator[](const DPack& pack)
{
auto ai = itLex(pack);
return *ai;
}
template <typename T>
T& ArrayBase<T>::at(const DPack& pack)
{
auto ai = itLexSave(pack);
return *ai;
}
template <typename T>
template <typename I, typename M>
Sptr<ArrayBase<T>> ArrayBase<T>::sl(const IndexInterface<I,M>& begin,
const IndexInterface<I,M>& end)
{
auto ai = itLexSave(begin);
auto aj = itLexSave(end);
return std::make_shared<Slice<T>>(ai.prange(aj), this, ai.format(), ai.pos());
}
template <typename T>
typename ArrayBase<T>::iterator ArrayBase<T>::begin()
{
return iterator(this->data(), this->cbegin());
}
template <typename T>
typename ArrayBase<T>::iterator ArrayBase<T>::end()
{
return iterator(this->data(), this->cend());
}
template <typename T>
template <class Index>
OpRoot<T,Index> ArrayBase<T>::operator()(const Sptr<Index>& i)
{
if(this->formatIsTrivial()){
// assert that index format is trivial and has correct extensions
CXZ_ASSERT(i->formatIsTrivial(),
"got non-trivial index for container with trivial format");
this->checkFormatCompatibility(*i);
return oproot(*this, i);
}
else {
if(i->formatIsTrivial()){
// try to apply container format.
// if the reformat changes the index type in any manner
// the format is not applicable:
if constexpr(std::is_same<decltype(i->reformat( Vector<SizeT>(), Vector<SizeT>() )),Index>::value){
auto beg = begin();
auto aformat = beg.deepFormat();
auto amax = beg.deepMax();
auto fi = i->reformat( aformat, amax );
return oproot(*this, moveToPtr( fi ) );
}
else {
this->checkFormatCompatibility(*i);
return oproot(*this, i);
}
}
else {
// check if format is compatible
this->checkFormatCompatibility(*i);
return oproot(*this, i);
}
}
}
template <typename T>
template <class... Indices>
inline decltype(auto) ArrayBase<T>::operator()(const SPack<Indices...>& pack)
{
return operator()(mindexPtr(pack));
}
template <typename T>
inline decltype(auto) ArrayBase<T>::operator()(const DPack& pack)
{
return operator()(yindexPtr(pack));
}
/*================================================================+
| Implementations for protected ArrayBase member functions |
+================================================================*/
template <typename T>
template <class Acc>
typename ArrayBase<T>::iterator ArrayBase<T>::itLex(const Acc& acc)
{
return begin() + acc.lex();
}
template <typename T>
template <class Acc>
typename ArrayBase<T>::iterator ArrayBase<T>::itLexSave(const Acc& acc)
{
CXZ_ASSERT(acc.lex() < this->size(), "index out of range");
// check further compatibility of index/range format!!!
return begin() + acc.lex();
}
}
#endif

View file

@ -1,290 +0,0 @@
// -*- C++ -*-
/**
@file include/array/array_base.h
@brief Array base class declarations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_array_base_h__
#define __cxz_array_base_h__
#include <cstdlib>
#include <vector>
#include <memory>
#include <algorithm>
#include "base/base.h"
#include "aindex.h"
#include "operation/op_types.h"
namespace CNORXZ
{
/** ****
Abstract container base class
only read access to the data
@tparam T data type
*/
template <typename T>
class CArrayBase
{
public:
typedef AIndex<T> const_iterator; /** const iterator type */
DEFAULT_MEMBERS(CArrayBase); /**< default constructors and assignments */
/** construct container on a range
@param range
*/
CArrayBase(const RangePtr& range);
/** default destructor */
virtual ~CArrayBase() = default;
/** const data element access
@tparam I index type
@tparam M meta data type
@param i index
*/
template <typename I, typename M>
const T& operator[](const IndexInterface<I,M>& i) const;
/** const data element access
performs compatibility checks
@tparam I index type
@tparam M meta data type
@param i index
*/
template <typename I, typename M>
const T& at(const IndexInterface<I,M>& i) const;
/** const data element access
@tparam I index type
@tparam M meta data type
@param pack static index pack
*/
template <class... Indices>
const T& operator[](const SPack<Indices...>& pack) const;
/** const data element access
performs compatibility checks
@tparam I index type
@tparam M meta data type
@param i static index pack
*/
template <class... Indices>
const T& at(const SPack<Indices...>& pack) const;
/** const data element access
@param pack index pack
*/
const T& operator[](const DPack& pack) const;
/** const data element access
performs compatibility checks
@param i index pack
*/
const T& at(const DPack& pack) const;
/** create hypercubic slice from this container
@tparam I type of index used to indicate slice edges
@tparam M index meta type
@param begin begin edge
@param end end edge
*/
template <typename I, typename M>
Sptr<CArrayBase<T>> sl(const IndexInterface<I,M>& begin,
const IndexInterface<I,M>& end) const;
/** create operation on this container
@tparam Index type of operation index
@param i operation index
*/
template <class Index>
COpRoot<T,Index> operator()(const Sptr<Index>& i) const;
/** create operation on this container
@tparam Indices types of operation indices
@param pack pack of operation index
*/
template <class... Indices>
inline decltype(auto) operator()(const SPack<Indices...>& pack) const;
/** create operation on this container
@param pack pack of operation index
*/
inline decltype(auto) operator()(const DPack& pack) const;
/** get pointer to container data */
virtual const T* data() const = 0;
/** get number of elements in the container */
virtual SizeT size() const;
/** get container range */
virtual RangePtr range() const;
/** get index pointing to first position */
virtual const_iterator begin() const;
/** get index pointing to position after last position */
virtual const_iterator end() const;
/** get index pointing to first position */
virtual const_iterator cbegin() const = 0;
/** get index pointing to position after last position */
virtual const_iterator cend() const = 0;
/** check if container views the data, i.e. it does not own it */
virtual bool isView() const = 0;
protected:
RangePtr mRange; /**< the container range */
/** Get valid data index.
Create well-formated index from index pack (unformatted)
or index using trivial format.
@tparam Acc index type or index pack type
@param acc index or index pack
*/
template <class Acc>
const_iterator itLex(const Acc& acc) const;
/** Get valid data index.
Create well-formated index from index pack (unformatted)
or index using trivial format.
Perform compatibility checks.
@tparam Acc index type or index pack type
@param acc index or index pack
*/
template <class Acc>
const_iterator itLexSave(const Acc& acc) const;
/** Perform compatibility checks
@tparam Acc index type or index pack type
@param acc index or index pack.
*/
template <class Acc>
void checkFormatCompatibility(const Acc& acc) const;
/** check if format is trivial
@return true if container is data owning array, else return
result of the corresponding container index
*/
virtual bool formatIsTrivial() const = 0;
};
/** ****
Abstract container base class
read and write access to the data
@tparam T data type
*/
template <typename T>
class ArrayBase : public CArrayBase<T>
{
public:
typedef CArrayBase<T> CAB;
typedef typename CAB::const_iterator const_iterator; /**< constant iterator type */
typedef BIndex<T> iterator; /**< read/write iterator type */
using CAB::operator[];
using CAB::operator();
using CAB::at;
using CAB::data;
using CAB::begin;
using CAB::end;
using CAB::cbegin;
using CAB::cend;
using CAB::sl;
DEFAULT_MEMBERS(ArrayBase); /**< default constructors and assignments */
/** construct a container on a range
*/
ArrayBase(const RangePtr& range);
/** @copydoc CArrayBase::operator[]()
*/
template <typename I, typename M>
T& operator[](const IndexInterface<I,M>& i);
/** @copydoc CArrayBase::at()
*/
template <typename I, typename M>
T& at(const IndexInterface<I,M>& i);
/** @copydoc CArrayBase::operator[]()
*/
template <class... Indices>
T& operator[](const SPack<Indices...>& pack);
/** @copydoc CArrayBase::at()
*/
template <class... Indices>
T& at(const SPack<Indices...>& pack);
/** @copydoc CArrayBase::operator[]()
*/
T& operator[](const DPack& pack);
/** @copydoc CArrayBase::at()
*/
T& at(const DPack& pack);
/** @copydoc CArrayBase::operator()()
*/
template <class Index>
OpRoot<T,Index> operator()(const Sptr<Index>& i);
/** @copydoc CArrayBase::operator()()
*/
template <class... Indices>
inline decltype(auto) operator()(const SPack<Indices...>& pack);
/** @copydoc CArrayBase::operator()()
*/
inline decltype(auto) operator()(const DPack& pack);
/** @copydoc CArrayBase::sl()
*/
template <typename I, typename M>
Sptr<ArrayBase<T>> sl(const IndexInterface<I,M>& begin,
const IndexInterface<I,M>& end);
/** @copydoc CArrayBase::data()
read/write access
*/
virtual T* data() = 0;
/** @copydoc CArrayBase::begin()
read/write access
*/
virtual iterator begin();
/** @copydoc CArrayBase::end()
read/write access
*/
virtual iterator end();
protected:
/** @copydoc CArrayBase::itLex()
*/
template <class Acc>
iterator itLex(const Acc& acc);
/** @copydoc CArrayBase::itLexSave()
*/
template <class Acc>
iterator itLexSave(const Acc& acc);
};
}
#endif

View file

@ -1,105 +0,0 @@
// -*- C++ -*-
/**
@file include/array/marray.cc.h
@brief MArray implementations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_marray_cc_h__
#define __cxz_marray_cc_h__
#include "marray.h"
namespace CNORXZ
{
/*=======================================================+
| Implementation of MArray public member functions |
+=======================================================*/
template <typename T>
MArray<T>::MArray(const RangePtr& range) :
ArrayBase<T>(range), mCont(range->size())
{}
template <typename T>
MArray<T>::MArray(const RangePtr& range, const Vector<T>& vec) :
ArrayBase<T>(range), mCont(vec)
{}
template <typename T>
MArray<T>::MArray(const RangePtr& range, Vector<T>&& vec) :
ArrayBase<T>(range), mCont(vec)
{}
template <typename T>
MArray<T>& MArray<T>::init(const RangePtr& range)
{
AB::mRange = rangeCast<YRange>(range);
mCont.resize(AB::mRange->size());
return *this;
}
template <typename T>
MArray<T>& MArray<T>::extend(const RangePtr& range)
{
if(AB::mRange == nullptr) {
return this->init(range);
}
MArray<T> tmp(AB::mRange->extend(range));
auto ei = this->end();
auto ti = tmp.begin();
// this is not very efficient; remove by sub-index operation once available:
for(auto ii = this->begin(); ii != ei; ++ii){
ti.at(ii.meta());
*ti = *ii;
}
*this = std::move(tmp);
return *this;
}
template <typename T>
const T* MArray<T>::data() const
{
return mCont.data();
}
template <typename T>
T* MArray<T>::data()
{
return mCont.data();
}
template <typename T>
typename MArray<T>::const_iterator MArray<T>::cbegin() const
{
return const_iterator(mCont.data(), AB::mRange);
}
template <typename T>
typename MArray<T>::const_iterator MArray<T>::cend() const
{
return const_iterator(mCont.data(), AB::mRange, mCont.size());
}
template <typename T>
bool MArray<T>::isView() const
{
return false;
}
/*==========================================================+
| Implementation of MArray protected member functions |
+==========================================================*/
template <typename T>
bool MArray<T>::formatIsTrivial() const
{
return true;
}
}
#endif

View file

@ -1,58 +0,0 @@
// -*- C++ -*-
/**
@file include/array/marray.h
@brief MArray declarations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_marray_h__
#define __cxz_marray_h__
#include "array_base.h"
namespace CNORXZ
{
/** ***
Generic multi-dimensional array class
This class owns the data that can be accessed through it
**/
template <typename T>
class MArray : public ArrayBase<T>
{
public:
typedef CArrayBase<T> AB;
typedef typename AB::const_iterator const_iterator;
using CArrayBase<T>::operator[];
using ArrayBase<T>::operator[];
DEFAULT_MEMBERS(MArray);
MArray(const RangePtr& range);
MArray(const RangePtr& range, const Vector<T>& vec);
MArray(const RangePtr& range, Vector<T>&& vec);
MArray& init(const RangePtr& range);
MArray& extend(const RangePtr& range);
virtual const T* data() const override;
virtual T* data() override;
virtual const_iterator cbegin() const override;
virtual const_iterator cend() const override;
virtual bool isView() const override;
SERIALIZATION_FUNCTIONS;
protected:
virtual bool formatIsTrivial() const override final;
private:
Vector<T> mCont;
};
}
#endif

View file

@ -1,120 +0,0 @@
// -*- C++ -*-
/**
@file include/array/slice.cc.h
@brief Slice implementations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_slice_cc_h__
#define __cxz_slice_cc_h__
#include "slice.h"
namespace CNORXZ
{
/*========================================================+
| Implementation of public CSlice member functions |
+========================================================*/
template <typename T>
CSlice<T>::CSlice(const RangePtr& range, const CArrayBase<T>* parent,
const YFormat& blockSizes, SizeT off) :
CArrayBase<T>(range),
mCParent(parent),
mBlockSizes(blockSizes),
mOff(off)
{}
template <typename T>
const T* CSlice<T>::data() const
{
return mCParent->data() + mOff;
}
template <typename T>
typename CSlice<T>::const_iterator CSlice<T>::cbegin() const
{
return const_iterator(data(),YIndex(AB::mRange, mBlockSizes, 0));
}
template <typename T>
typename CSlice<T>::const_iterator CSlice<T>::cend() const
{
return const_iterator(data(),YIndex(AB::mRange, mBlockSizes, AB::mRange->size()));
}
template <typename T>
bool CSlice<T>::isView() const
{
return true;
}
/*===========================================================+
| Implementation of protected CSlice member functions |
+===========================================================*/
template <typename T>
bool CSlice<T>::formatIsTrivial() const
{
return cbegin().formatIsTrivial();
}
/*=======================================================+
| Implementation of public Slice member functions |
+=======================================================*/
template <typename T>
Slice<T>::Slice(const RangePtr& range, ArrayBase<T>* parent,
const YFormat& blockSizes, SizeT off) :
ArrayBase<T>(range),
mParent(parent),
mBlockSizes(blockSizes),
mOff(off)
{}
template <typename T>
T* Slice<T>::data()
{
return mParent->data() + mOff;
}
template <typename T>
const T* Slice<T>::data() const
{
return mParent->data() + mOff;
}
template <typename T>
typename Slice<T>::const_iterator Slice<T>::cbegin() const
{
return const_iterator(data(),YIndex(AB::mRange, mBlockSizes, 0));
}
template <typename T>
typename Slice<T>::const_iterator Slice<T>::cend() const
{
return const_iterator(data(),YIndex(AB::mRange, mBlockSizes, AB::mRange->size()));
}
template <typename T>
bool Slice<T>::isView() const
{
return true;
}
/*==========================================================+
| Implementation of protected Slice member functions |
+==========================================================*/
template <typename T>
bool Slice<T>::formatIsTrivial() const
{
return cbegin().formatIsTrivial();
}
}
#endif

View file

@ -1,102 +0,0 @@
// -*- C++ -*-
/**
@file include/array/slice.h
@brief Slice declarations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_slice_h__
#define __cxz_slice_h__
#include "base/base.h"
#include "array_base.h"
namespace CNORXZ
{
/** ****
constant and possibly partial view on the data
of another container
@tparam T data type
*/
template <typename T>
class CSlice : public CArrayBase<T>
{
public:
typedef CArrayBase<T> AB;
typedef typename AB::const_iterator const_iterator;
DEFAULT_MEMBERS(CSlice); /**< default constructors and assignments */
/** create slice from an array
@param range the slice's container range
@param parent the original container
@param blockSizes the format of the slice
@param off the initial pointer position w.r.t. the original initial position
*/
CSlice(const RangePtr& range, const CArrayBase<T>* parent,
const YFormat& blockSizes, SizeT off);
virtual const T* data() const override;
virtual const_iterator cbegin() const override;
virtual const_iterator cend() const override;
virtual bool isView() const override final;
protected:
virtual bool formatIsTrivial() const override final;
const CArrayBase<T>* mCParent = nullptr; /**< pointer to the original container */
YFormat mBlockSizes; /**< the format */
SizeT mOff = 0; /** pointer offset w.r.t. the original pointer */
};
/** ****
possibly partial view on the data
of another container
@tparam T data type
*/
template <typename T>
class Slice : public ArrayBase<T>
{
public:
typedef CArrayBase<T> AB;
typedef typename AB::const_iterator const_iterator;
DEFAULT_MEMBERS(Slice); /**< default constructors and assignments */
/** create slice from an array
@param range the slice's container range
@param parent the original container
@param blockSizes the format of the slice
@param off the initial pointer position w.r.t. the original initial position
*/
Slice(const RangePtr& range, ArrayBase<T>* parent,
const YFormat& blockSizes, SizeT off);
virtual const T* data() const override;
virtual T* data() override;
virtual const_iterator cbegin() const override;
virtual const_iterator cend() const override;
virtual bool isView() const override final;
protected:
virtual bool formatIsTrivial() const override final;
private:
ArrayBase<T>* mParent = nullptr;
YFormat mBlockSizes;
SizeT mOff = 0;
};
}
#endif

View file

@ -1,40 +0,0 @@
// -*- C++ -*-
/**
@file include/base/assert.h
@brief warning and error makros
Definition of macros that can be used for convenient error handling and warnings
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include <iostream>
#include <sstream>
/** library error tag */
#define CXZ_ERRTAG __FILE__ << '@' << __LINE__ << '(' << __func__ << "): error"
/** library warning tag */
#define CXZ_WARNTAG __FILE__ << '@' << __LINE__ << ": warning"
/** throw error
@param errmsg error message
*/
#define CXZ_ERROR(errmsg) { \
auto mkerr = [&](){ std::stringstream ss; ss << CXZ_ERRTAG << ": " << errmsg << std::flush; return ss.str(); }; \
throw std::runtime_error(mkerr()); }
/** print warning
@param errmsg warning message
*/
#define CXZ_WARNING(errmsg) {\
std::cerr << CXZ_WARNTAG << ": " << errmsg << std::endl; }
/** throw error if given statement is not fulfilled
@param statement statement to be checked
@param errmsg error message
*/
#define CXZ_ASSERT(statement, errmsg) if(not (statement)) { CXZ_ERROR(errmsg); }

View file

@ -1,18 +0,0 @@
// -*- C++ -*-
/**
@file include/base/base.cc.h
@brief basic cc headers
Include basic cc headers containing defintions and macros
used throughout this library
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "dtype.cc.h"
#include "obj_handle.cc.h"
#include "to_string.cc.h"
#include "iter.cc.h"

View file

@ -1,38 +0,0 @@
// -*- C++ -*-
/**
@file include/base/base.h
@brief basic headers
Include basic headers containing defintions and macros
used throughout this library
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_base_h__
#define __cxz_base_h__
#include <cstdlib>
#include <iostream>
#include <utility>
#include "macros.h"
#include "assert.h"
#include "types.h"
#include "obj_handle.h"
#include "dtype.h"
#include "isq.h"
#include "iter.h"
#include "uuid.h"
#include "utils.h"
#include "config.h"
#include "intrin.h"
#include "base.cc.h"
#include "memory/memory.h"
#endif

View file

@ -1,35 +0,0 @@
// -*- C++ -*-
/**
@file include/base/config.h
@brief Runtime config functions declarations.
Declare functions returning version and configuration infos.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_config_h__
#define __cxz_config_h__
#include <cstdlib>
#include "base/types.h"
namespace CNORXZ
{
namespace Config
{
/** return cnorxz version */
String version();
/** return git hash */
String commit();
/** return compile flags */
String flags();
}
}
#endif

View file

@ -1,74 +0,0 @@
// -*- C++ -*-
/**
@file include/base/dtype.cc.h
@brief DType template member function definitions
Definitions of the template member functions of the DType class.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_dtype_cc_h__
#define __cxz_dtype_cc_h__
#include <sstream>
#include "dtype.h"
#include "to_string.h"
namespace CNORXZ
{
// for tuple use vector<DType> !!!
// (yes DType is slow, thats why one should only use it for debugging)
template <typename T>
DType::DType(const T& d) : mD(d)
{
_mkToStr<T>();
_mkComp<T>();
}
template <typename T>
DType& DType::operator=(const T& d)
{
mD = d;
_mkToStr<T>();
_mkComp<T>();
return *this;
}
template <typename T>
void DType::_mkToStr()
{
mToStr = [](const std::any& d){
return toString(std::any_cast<T>(d));
};
}
template <typename T>
void DType::_mkComp()
{
mComp = [](const std::any& d, const std::any& a){
if(d.type() != a.type()){
return 2;
}
else {
auto& at = std::any_cast<const T&>(a);
auto& dt = std::any_cast<const T&>(d);
if(std::equal_to<T>{}(dt,at)){
return 0;
}
else if(std::less<T>{}(dt,at)){
return -1;
}
else {
return 1;
}
}
};
}
}
#endif

View file

@ -1,104 +0,0 @@
// -*- C++ -*-
/**
@file include/base/dtype.h
@brief DType declaration
DType is a generic type-erasing class that wrapps std::any.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_dynamic_meta_h__
#define __cxz_dynamic_meta_h__
#include <cstdlib>
#include <utility>
#include <memory>
#include <any>
#include <functional>
#include "macros.h"
#include "types.h"
namespace CNORXZ
{
/** ****
Type erasing class wrapping std::any
*/
class DType
{
private:
std::any mD;
std::function<String(const std::any&)> mToStr;
std::function<Int(const std::any&,const std::any&)> mComp;
template <typename T>
void _mkToStr();
template <typename T>
void _mkComp();
public:
DEFAULT_MEMBERS(DType); /**< default constructors and assignments */
/** Generic constructor template
Constructs a DType from the given argument
@tparam T input data type
@param d input
*/
template <typename T>
DType(const T& d);
/** Generic assignment template
Assigns the given argument to the DType
@tparam T input data type
@param d input
*/
template <typename T>
DType& operator=(const T& d);
/** convert contained data so string */
String str() const { return mToStr(mD); }
/** return reference to type-erased data */
const std::any& get() const { return mD; }
/** check for equality
@param a variable to compare with
*/
bool operator==(const DType& a) const { return mComp(mD,a.mD) == 0; }
/** check for inequality
@param a variable to compare with
*/
bool operator!=(const DType& a) const { return mComp(mD,a.mD) != 0; }
/** check smaller
@param a variable to compare with
*/
bool operator<(const DType& a) const { return mComp(mD,a.mD) == -1; }
/** check greater
@param a variable to compare with
*/
bool operator>(const DType& a) const { return mComp(mD,a.mD) == 1; }
/** check not greater
@param a variable to compare with
*/
bool operator<=(const DType& a) const { auto c = mComp(mD,a.mD); return c <= 0; }
/** check not smaller
@param a variable to compare with
*/
bool operator>=(const DType& a) const { auto c = mComp(mD,a.mD); return c == 1 or c == 0; }
};
} // namespace CNORXZ
#endif

View file

@ -1,25 +0,0 @@
// -*- C++ -*-
/**
@file include/base/intrin.h
@brief Definitions related to intrinsics
**/
#ifndef __cxz_intrin_h__
#define __cxz_intrin_h__
#define MAX_VSIZE 1
// AVX:
#define AVX_BITS 256
#define AVX_VSIZE (AVX_BITS/8)
#ifdef CXZ_HAVE_AVX
#undef MAX_VSIZE
#define MAX_VSIZE AVX_VSIZE
#endif
// ...:
// ...
#endif

View file

@ -1,48 +0,0 @@
// -*- C++ -*-
/**
@file include/base/isq.h
@brief Integer sequence range and creation functions
Declaration of integer sequence range and corresponding creating function templates
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_isq_h__
#define __cxz_isq_h__
#include <cstdlib>
#include <utility>
#include "types.h"
namespace CNORXZ
{
/** @cond 0 */
template <SizeT O, SizeT... Is>
std::index_sequence<(Is+O)...> mkIsqAdd(std::index_sequence<Is...> is) { return {}; }
template <SizeT B, SizeT E>
struct MkIsq
{
static auto make()
{
static_assert(B <= E, "begin of sequence must be smaller than end of sequence");
return mkIsqAdd<B>( std::make_index_sequence<E-B>{} );
}
typedef decltype(make()) type;
};
/** @endcond */
/** static consecutive integer sequence
@tparam B begin integer
@tparam E end integer
*/
template <SizeT B, SizeT E>
using Isqr = typename MkIsq<B,E>::type;
}
#endif

View file

@ -1,69 +0,0 @@
// -*- C++ -*-
/**
@file include/base/iter.cc.h
@brief Static for-loops
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_iter_cc_h__
#define __cxz_iter_cc_h__
#include "iter.h"
#include "xpr/func.h"
namespace CNORXZ
{
/** @cond 0 */
template <class G, class F, SizeT... Is>
constexpr decltype(auto) iteri(const G& g, const F& f, Isq<Is...> is)
{
if constexpr(std::is_same<F,NoF>::value){
( g(CSizeT<Is>{}), ... );
}
else {
return f( g(CSizeT<Is>{}) ... );
}
}
/** @endcond */
template <SizeT B, SizeT E, class G, class F>
constexpr decltype(auto) iter(const G& g, const F& f)
{
return iteri(g, f, Isqr<B,E>{});
}
/** @cond 0 */
template <SizeT E, SizeT I, class G, class F, class C, typename... Args>
constexpr decltype(auto) iterIfi(const G& g, const F& f, const C& c, const Args&... args)
{
if constexpr(I >= E){
if constexpr(std::is_same<F,NoF>::value){
return;
}
else {
return f(args...);
}
}
else {
if constexpr(c(CSizeT<I>{})){
return iterIfi<E,I+1>(g, f, c, args..., g(CSizeT<I>{}));
}
else {
return iterIfi<E,I+1>(g, f, c, args...);
}
}
}
/** @endcond */
template <SizeT B, SizeT E, class G, class F, class C>
constexpr decltype(auto) iterIf(const G& g, const F& f, const C& c)
{
return iterIfi<E,B>(g, f, c);
}
}
#endif

View file

@ -1,57 +0,0 @@
// -*- C++ -*-
/**
@file include/base/iter.h
@brief Static for-loops
Declaration of function templates that can be used to implement a static for-loop
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_iter_h__
#define __cxz_iter_h__
#include <cstdlib>
#include "types.h"
namespace CNORXZ
{
/** @cond 0 */
template <class G, class F, SizeT... Is>
constexpr decltype(auto) iteri(const G& g, const F& f, Isq<Is...> is);
/** @endcond */
/** static for loop
@tparam B begin index
@tparam E end index
@tparam G type of expression to executed for each element
@tparam F type of accumulating expression collecting result for all elements
@param g expression to executed for each element
@param f accumulating expression collecting result for all elements
*/
template <SizeT B, SizeT E, class G, class F>
constexpr decltype(auto) iter(const G& g, const F& f);
/** @cond 0 */
template <SizeT E, SizeT I, class G, class F, class C, typename... Args>
constexpr decltype(auto) iterIfi(const G& g, const F& f, const C& c, const Args&... args);
/** @endcond */
/** static conditional for loop
@tparam B begin index
@tparam E end index
@tparam G type of expression to executed for each element
@tparam F type of accumulating expression collecting result for all elements
@tparam C type of condition expression
@param g expression to executed for each element
@param f accumulating expression collecting result for all elements
@param c condition expression
*/
template <SizeT B, SizeT E, class G, class F, class C>
constexpr decltype(auto) iterIf(const G& g, const F& f, const C& c);
}
#endif

View file

@ -1,135 +0,0 @@
// -*- C++ -*-
/**
@file include/base/macros.h
@brief useful macros
Define useful macros that are used throughout this library for convenience,
briefnes and/or debugging.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_macros_h__
#define __cxz_macros_h__
#include <iostream>
#ifndef CHECK
#define CHECK std::cout << __FILE__ << ": @" << __LINE__ << " in " << __func__ << std::endl;
#endif
#ifndef VCHECK
#define VCHECK(a) std::cout << __FILE__ << ": @" << __LINE__ \
<< " in " << __func__ << ": " << #a << " = " << a << std::endl;
#endif
/** shortcut for defining default constructor */
#define DEFAULT_C(__class_name__) __class_name__() = default
/** shortcut for defining default copy constructor */
#define DEFAULT_COPY_C(__class_name__) __class_name__(const __class_name__& a) = default
/** shortcut for defining default copy assignment */
#define DEFAULT_COPY_A(__class_name__) __class_name__& operator=(const __class_name__& a) = default
/** shortcut for defining default move constructor */
#define DEFAULT_MOVE_C(__class_name__) __class_name__(__class_name__&& a) = default
/** shortcut for defining default move assignment */
#define DEFAULT_MOVE_A(__class_name__) __class_name__& operator=(__class_name__&& a) = default
/** shortcut for defining default copy constructor and assignment */
#define DEFAULT_COPY(__class_name__) DEFAULT_COPY_C(__class_name__); DEFAULT_COPY_A(__class_name__)
/** shortcut for defining default move constructor and assignment */
#define DEFAULT_MOVE(__class_name__) DEFAULT_MOVE_C(__class_name__); DEFAULT_MOVE_A(__class_name__)
/** shortcut for defining default copy and move constructor and assignment */
#define DEFAULT_MEMBERS_X(__class_name__) DEFAULT_COPY(__class_name__); DEFAULT_MOVE(__class_name__)
/** shortcut for defining default constructor, default copy and move constructor and assignment */
#define DEFAULT_MEMBERS(__class_name__) DEFAULT_C(__class_name__); DEFAULT_MEMBERS_X(__class_name__)
/** shortcut for defining default constructor
@param __spec__ specifier
@param __class_name__ class name
*/
#define SP_DEFAULT_C(__spec__,__class_name__) __spec__ __class_name__() = default
/** shortcut for defining default copy constructor
@param __spec__ specifier
@param __class_name__ class name
*/
#define SP_DEFAULT_COPY_C(__spec__,__class_name__) __spec__ __class_name__(const __class_name__& a) = default
/** shortcut for defining default copy assignment
@param __spec__ specifier
@param __class_name__ class name
*/
#define SP_DEFAULT_COPY_A(__spec__,__class_name__) __spec__ __class_name__& operator=(const __class_name__& a) = default
/** shortcut for defining default move constructor
@param __spec__ specifier
@param __class_name__ class name
*/
#define SP_DEFAULT_MOVE_C(__spec__,__class_name__) __spec__ __class_name__(__class_name__&& a) = default
/** shortcut for defining default move assignment
@param __spec__ specifier
@param __class_name__ class name
*/
#define SP_DEFAULT_MOVE_A(__spec__,__class_name__) __spec__ __class_name__& operator=(__class_name__&& a) = default
/** shortcut for defining default copy constructor and assignment
@param __spec__ specifier
@param __class_name__ class name
*/
#define SP_DEFAULT_COPY(__spec__,__class_name__) SP_DEFAULT_COPY_C(__spec__,__class_name__); SP_DEFAULT_COPY_A(__spec__,__class_name__)
/** shortcut for defining default move constructor and assignment
@param __spec__ specifier
@param __class_name__ class name
*/
#define SP_DEFAULT_MOVE(__spec__,__class_name__) SP_DEFAULT_MOVE_C(__spec__,__class_name__); SP_DEFAULT_MOVE_A(__spec__,__class_name__)
/** shortcut for defining default copy and move constructor and assignment
@param __spec__ specifier
@param __class_name__ class name
*/
#define SP_DEFAULT_MEMBERS_X(__spec__,__class_name__) SP_DEFAULT_COPY(__spec__,__class_name__); SP_DEFAULT_MOVE(__spec__,__class_name__)
/** shortcut for defining default constructor, default copy and move constructor and assignment
@param __spec__ specifier
@param __class_name__ class name
*/
#define SP_DEFAULT_MEMBERS(__spec__,__class_name__) SP_DEFAULT_C(__spec__,__class_name__); SP_DEFAULT_MEMBERS_X(__spec__,__class_name__)
/** shortcut for all typedefs needed to use a class as iterator
@param __meta_type__ meta data type
*/
#define INDEX_RANDOM_ACCESS_ITERATOR_DEFS(__meta_type__) typedef std::random_access_iterator_tag iterator_category; \
typedef SizeT difference_type; \
typedef __meta_type__ value_type; \
typedef const __meta_type__* pointer; \
typedef const __meta_type__& reference
#define CXZ_CVAL_FALSE static constexpr bool value = false
#define CXZ_CVAL_TRUE static constexpr bool value = true
#define IS_SAME(a,b) std::is_same<a,b>::value
#define IS_NOT_SAME(a,b) (not std::is_same<a,b>::value)
#ifdef HAVE_CEREAL
#define SERIALIZATION_FUNCTIONS template <class Archive> void save(Archive& ar, const std::uint32_t version) const; \
template <class Archive> void load(Archive& ar, const std::uint32_t version)
#define SERIALIZATION_FUNCTIONS_NOPUB friend class cereal::access; \
template <class Archive> void save(Archive& ar, const std::uint32_t version) const; \
template <class Archive> void load(Archive& ar, const std::uint32_t version)
#else
#define SERIALIZATION_FUNCTIONS static const int v = 0
#define SERIALIZATION_FUNCTIONS_NOPUB static const int v = 0
#endif
#endif

View file

@ -1,74 +0,0 @@
// -*- C++ -*-
/**
@file include/base/obj_handle.cc.h
@brief ObjHandle function definition
Implementation of the member functions of template ObjHandle
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_obj_handle_cc_h__
#define __cxz_obj_handle_cc_h__
#include "obj_handle.h"
namespace CNORXZ
{
template <typename T>
ObjHandle<T>::ObjHandle() {}
template <typename T>
ObjHandle<T>::ObjHandle(Uptr<T>&& a) : mC(std::forward<Uptr<T>>(a)) {}
template <typename T>
ObjHandle<T>::ObjHandle(const ObjHandle& a) : mC(a.mC->copy()) {}
template <typename T>
ObjHandle<T>::ObjHandle(ObjHandle&& a) : mC(a.mC) {}
template <typename T>
ObjHandle<T>& ObjHandle<T>::operator=(const ObjHandle& a)
{
mC = std::make_unique<T>(*a.mC);
return *this;
}
template <typename T>
ObjHandle<T>& ObjHandle<T>::operator=(ObjHandle&& a)
{
mC = a.mC;
return *this;
}
template <typename T>
T& ObjHandle<T>::operator*()
{
return *mC;
}
template <typename T>
T* ObjHandle<T>::operator->()
{
return &*mC;
}
template <typename T>
const T& ObjHandle<T>::operator*() const
{
return *mC;
}
template <typename T>
const T* ObjHandle<T>::operator->() const
{
return &*mC;
}
}
#endif

View file

@ -1,84 +0,0 @@
// -*- C++ -*-
/**
@file include/base/obj_handle.h
@brief ObjHandle template declaration
Pointer wrapper for directly handling objects via abstract base class;
Provides appropriate copy implementation
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_obj_handle_h__
#define __cxz_obj_handle_h__
#include "types.h"
namespace CNORXZ
{
/** ****
unique pointer wrapper
Allows to handle objects accessed through abstract base class pointers
as if they were complete (non-virtual) types.
Each type to be handled is required to have a copy() member function
that returns a copy of itself
@tparam T object type
*/
template <typename T>
class ObjHandle
{
protected:
Uptr<T> mC; /**< pointer to the object data */
public:
/** default constructor */
ObjHandle();
/** construct from unique pointer
@param a unique pointer
*/
ObjHandle(Uptr<T>&& a);
/** copy construct
@param a input
*/
ObjHandle(const ObjHandle& a);
/** move construct
@param a input
*/
ObjHandle(ObjHandle&& a);
/** copy assign
@param a input
*/
ObjHandle& operator=(const ObjHandle& a);
/** move assign
@param a input
*/
ObjHandle& operator=(ObjHandle&& a);
/** access data */
T& operator*();
/** get pointer to data */
T* operator->();
/** access data (const) */
const T& operator*() const;
/** get pointer to data (const) */
const T* operator->() const;
};
}
#endif

View file

@ -1,113 +0,0 @@
// -*- C++ -*-
/**
@file include/base/to_string.cc.h
@brief String converter implementation
Implementation of functions that convert a given object/type to a string
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_to_string_cc_h__
#define __cxz_to_string_cc_h__
#include "to_string.h"
#include "iter.h"
#include <sstream>
namespace CNORXZ
{
template <typename T>
String ToString<T>::func(const T& a)
{
std::stringstream ss;
ss << a;
return ss.str();
}
template <typename T>
String ToString<Vector<T>>::func(const Vector<T>& a)
{
std::stringstream ss;
ss << "[";
if(a.size() == 0){
ss << "]";
}
else {
auto it = a.begin();
for(; it != a.end()-1; ++it){
ss << toString(*it) << ",";
}
ss << toString(*it) << "]";
}
return ss.str();
}
template <typename T, size_t N>
String ToString<Arr<T,N>>::func(const Arr<T,N>& a)
{
std::stringstream ss;
ss << "(";
if constexpr(N == 0){
ss << ")";
}
else {
auto it = a.begin();
for(; it != a.end()-1; ++it){
ss << toString(*it) << ",";
}
ss << toString(*it) << ")";
}
return ss.str();
}
template <typename... Ts>
String ToString<Tuple<Ts...>>::func(const Tuple<Ts...>& t)
{
const String blim = "(";
const String elim = ")";
const String dlim = ",";
return iter<1,sizeof...(Ts)>
( [&](auto i) { return toString(std::get<i>(t)); },
[&](const auto&... xs) {
return blim + toString(std::get<0>(t)) + ( (dlim + xs) + ... ) + elim;
} );
}
template <typename T, typename S>
String ToString<std::pair<T,S>>::func(const std::pair<T,S>& p)
{
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)
{
return ToString<T>::func(a);
}
}
#endif

View file

@ -1,135 +0,0 @@
// -*- C++ -*-
/**
@file include/base/to_string.h
@brief String converter declarations.
Declaration of functions that convert a given object/type to a string.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_to_string_h__
#define __cxz_to_string_h__
#include "types.h"
namespace CNORXZ
{
/** ***
Generic cast to string
@tparam T type to be casted
*/
template <typename T>
struct ToString
{
/** cast to string
@param a object to be casted
*/
static String func(const T& a);
};
/** ***
Specialization of ToString for strings
*/
template <>
struct ToString<String>
{
/** cast to string
@param a string to be casted
*/
static String func(const String& a);
};
/** ***
Specialization of ToString for vectors
@tparam T vector element type
*/
template <typename T>
struct ToString<Vector<T>>
{
/** cast to string
@param a vector to be casted
*/
static String func(const Vector<T>& a);
};
/** ***
Specialization of ToString for arrays
@tparam T array element type
@tparam N array size
*/
template <typename T, SizeT N>
struct ToString<Arr<T,N>>
{
/** cast to string
@param a array to be casted
*/
static String func(const Arr<T,N>& a);
};
/** ***
Specialization of ToString for tuples
@tparam Ts tuple element types
*/
template <typename... Ts>
struct ToString<Tuple<Ts...>>
{
/** cast to string
@param a tuple to be casted
*/
static String func(const Tuple<Ts...>& t);
};
/** ***
Specialization of ToString for pairs
@tparam T first element type
@tparam S second element type
*/
template <typename T, typename S>
struct ToString<std::pair<T,S>>
{
/** cast to string
@param a pair to be casted
*/
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
*/
template <>
struct ToString<DType>
{
/** cast to string
@param a DType to be casted
*/
static String func(const DType& a);
};
/** wrapper function for ToString
@tparam T type to be casted
@param a object to be casted
*/
template <typename T>
String toString(const T& a);
}
#endif

View file

@ -1,321 +0,0 @@
// -*- C++ -*-
/**
@file include/base/types.h
@brief Declaration of all library types
This file contains the declaration of all library types
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_types_h__
#define __cxz_types_h__
#include <string>
#include <vector>
#include <memory>
#include <tuple>
#include <complex>
#include <array>
#include <map>
#include <typeinfo>
#include <utility>
#include <numeric>
#include <cstdint>
namespace CNORXZ
{
/*====================+
| standard types |
=====================*/
typedef std::intptr_t PtrId;
typedef int32_t Int;
typedef int64_t LInt;
typedef uint64_t SizeT;
typedef double Double;
typedef Double Real;
typedef std::complex<Real> Complex;
typedef std::string String;
template <typename T, size_t N>
using Arr = std::array<T,N>;
template <typename T>
using Sptr = std::shared_ptr<T>;
template <typename T>
using Wptr = std::weak_ptr<T>;
template <typename T>
using Uptr = std::unique_ptr<T>;
template <typename T, typename U>
using Pair = std::pair<T,U>;
template <typename... T>
using Tuple = std::tuple<T...>;
template <SizeT I, typename... T>
using TupleElem = std::tuple_element<I,Tuple<T...>>;
template <typename T>
using RemoveRef = typename std::remove_reference<T>::type;
template <typename K, typename V>
using Map = std::map<K,V>;
typedef std::type_info TypeInfo;
template <SizeT... Is>
using Isq = std::index_sequence<Is...>;
// cxz helper functions/classes: -> isq.h
template <class... T>
using Isqf = std::index_sequence_for<T...>;
template <SizeT N>
using CSizeT = std::integral_constant<SizeT,N>;
/*===================+
| library types |
+===================*/
/*
Naming Prefixes:
D = Y = Dynamic
V = X = Virtual
S = Static
P = Partial = Sub
C = Classic
M = Multi (Index,Ranges) or !const (Container)
U = One(=Uni) dimensional
N = None = Null
E = Extension (SSE,AVX,etc dof)
T = Thread
R = Rank
A = (const) Array
B = (mutable) Array
F = Functional, Map,...
*/
// default template parameter
class None {};
// definition: base/dtype.h
class DType;
// definition: base/obj_handle.h
template <typename T>
class ObjHandle;
// definition: memory/allocator.h
template <typename T>
class Allocator;
// definition: xpr/vpos_type.h
class VPosBase;
// definition: xpr/vpos_type.h
template <class PosT>
class VPos;
// definition: xpr/vpos_type.h
template <class PosT>
class VPosRef;
// definition: xpr/pos_type.h
class UPos;
// definition: xpr/pos_type.h
template <SizeT N>
class SPos;
// definition: xpr/pos_type.h
class FPos;
// definition: xpr/pos_type.h
template <SizeT N, SizeT... Ms>
class SFPos;
// definition: xpr/pos_type.h
class DPos;
// definition: xpr/pos_type.h
class DPosRef;
// definition: xpr/pos_type.h
template <class PosT1, class PosT2>
class MPos;
// definition: ranges/range_base.h
class RangeBase;
typedef Sptr<RangeBase> RangePtr;
// definition: ranges/index_base.h
template <class I, typename MetaType>
class IndexInterface;
template <class I, typename MetaType>
using IndexPtr = Sptr<IndexInterface<I,MetaType>>;
// definition: ranges/nrange.h
class NRange; // null-range (range over none)
// definition: ranges/nrange.h
class NIndex;
// definition: ranges/urange.h
template <typename Meta>
class URange; // generic simple range (uni-dimensional)
// definition: ranges/urange.h
template <typename Meta>
class UIndex;
// definition: ranges/prange.h
template <class Range>
class PRange;
// definition: ranges/prange.h
template <class Index>
class PIndex;
// definition: ranges/crange.h
class CRange; // classic range, trivial meta data
// definition: ranges/crange.h
class CIndex;
// definition: ranges/srange.h
template <typename Meta, SizeT S>
class SRange; // generic static size range
// definition: ranges/srange.h
template <typename Meta, SizeT S>
class SIndex;
// definition: ranges/mrange.h
template <class... Ranges>
class MRange; // multi range
// definition: ranges/mrange.h
template <class BlockType, class... Indices>
class GMIndex;
template <class... Indices>
using MIndex = GMIndex<None,Indices...>;
// definition: ranges/xindex.h
class XIndexBase; // dynamic index wrapper
typedef Sptr<XIndexBase> XIndexPtr;
// definition: ranges/dindex.h
class DIndex;
// definition: ranges/yrange.h
class YRange; // dynamic multi range
// definition: ranges/yrange.h
class YIndex;
typedef Sptr<YIndex> YIndexPtr;
// definition: ranges/pindex.h
template <class Index>
class PIndex; // partial index (index over sub-ranges and permutations)
// there should be also a static analogue
// definition: ranges/lindex.h
template <class Index, SizeT L>
class LIndex;
// definition: ranges/index_pack.h
template <class... Indices>
class SPack;
// definition: ranges/index_pack.h
class DPack;
// definition: ranges/index_format.h
template <SizeT N>
class MFormat;
// definition: ranges/index_format.h
template <class... PosT>
class GMFormat;
// definition: ranges/index_format.h
class YFormat;
// definition: array/array_base.h
template <typename T>
class CArrayBase;
// definition: array/array_base.h
template <typename T>
class ArrayBase;
// definition: array/array.h
template <typename T>
class MArray;
// definition: array/slice.h
template <typename T>
class CSlice;
// definition: array/slice.h
template <typename T>
class Slice;
// definition: operation/op_types.h
template <class OpT>
class COpInterface;
// definition: operation/op_types.h
template <class OpT>
class OpInterface;
// definition: operation/op_types.h
template <typename T, class IndexT>
class COpRoot;
// definition: operation/op_types.h
template <typename T, class IndexT>
class OpCont;
// definition: operation/op_types.h
template <typename T, class IndexT>
class OpRoot;
// definition: operation/op_types.h
template <class F, class... Ops>
class Operation;
// definition: operation/op_types.h
template <class CXpr>
class Contraction;
/*===================+
| derived types |
+===================*/
template <typename T>
using Vector = std::vector<T,Allocator<T>>;
template <typename T, SizeT N, bool Static>
struct Container
{ typedef Vector<T> type; };
template <typename T, SizeT N>
struct Container<T,N,true>
{ typedef Arr<T,N> type; };
}
#endif

View file

@ -1,147 +0,0 @@
// -*- C++ -*-
/**
@file include/base/utils.h
@brief utilities
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_utils_h__
#define __cxz_utils_h__
#include <cstdlib>
#include <algorithm>
#include "types.h"
namespace CNORXZ
{
template <typename T, SizeT N>
Vector<T> toVec(const Arr<T,N>& a)
{
return iter<0,N>( [&](auto i) { return std::get<i>(a); },
[](const auto&... e) { return Vector<T> { e... }; } );
}
template <typename T>
Vector<T> toVec(const Vector<T>& a)
{
return a;
}
template <typename T>
Vector<T> toVec(const T& a)
{
return Vector<T> { a };
}
template <typename T, SizeT N1, SizeT N2>
constexpr Arr<T,N1+N2> cat2(const Arr<T,N1>& a1, const Arr<T,N2>& a2)
{
return iter<0,N1+N2>
( [&](auto i) { if constexpr(i < N1) { return std::get<i>(a1); } else { return std::get<i-N1>(a2); } },
[](const auto&... e) { return Arr<T,N1+N2> { e... }; } );
}
template <typename T, SizeT N1>
constexpr Arr<T,N1+1> cat2(const Arr<T,N1>& a1, const T& a2)
{
return iter<0,N1>
( [&](auto i) { return std::get<i>(a1); },
[&](const auto&... e) { return Arr<T,N1+1> { e..., a2 }; } );
}
template <typename T, SizeT N1>
constexpr Arr<T,N1+1> cat2(const T& a1, const Arr<T,N1>& a2)
{
return iter<0,N1>
( [&](auto i) { return std::get<i>(a2); },
[&](const auto&... e) { return Arr<T,N1+1> { a1, e... }; } );
}
template <typename T>
constexpr Arr<T,2> cat2(const T& a1, const T& a2)
{
return Arr<T,2> { a1, a2 };
}
template <typename T, SizeT N2>
Vector<T> cat2(const Vector<T>& a1, const Arr<T,N2>& a2)
{
Vector<T> o(a1.size()+N2);
std::copy(a1.begin(), a1.end(), o.begin());
std::copy(a2.begin(), a2.end(), o.begin()+a1.size());
return o;
}
template <typename T, SizeT N1>
Vector<T> cat2(const Arr<T,N1>& a1, const Vector<T>& a2)
{
Vector<T> o(N1+a2.size());
std::copy(a1.begin(), a1.end(), o.begin());
std::copy(a2.begin(), a2.end(), o.begin()+N1);
return o;
}
template <typename T>
Vector<T> cat2(const Vector<T>& a1, const Vector<T>& a2)
{
Vector<T> o(a1.size()+a2.size());
std::copy(a1.begin(), a1.end(), o.begin());
std::copy(a2.begin(), a2.end(), o.begin()+a1.size());
return o;
}
template <typename T>
Vector<T> cat2(const Vector<T>& a1, const T& a2)
{
Vector<T> o(a1);
o.push_back(a2);
return o;
}
template <typename T, SizeT N1>
Vector<T> cat2(const T& a1, const Vector<T>& a2)
{
Vector<T> o { a1 };
o.insert(o.end(), a2.begin(), a2.end());
return o;
}
template <typename T1, typename T2, typename... Ts>
decltype(auto) concat(const T1& a1, const T2& a2, const Ts&... as)
{
if constexpr(sizeof...(Ts) != 0){
return cat2(a1, concat(a2, as...));
}
else {
return cat2(a1, a2);
}
}
template <typename T, SizeT N>
constexpr Arr<T,N> mul(const Arr<T,N>& a, const T& b)
{
return iter<0,N>( [&](auto i) { return std::get<i>(a) * b; },
[](const auto&... e) { return Arr<T,N> { e... }; } );
}
template <typename T>
Vector<T> mul(const Vector<T>& a, const T& b)
{
Vector<T> o(a.size());
std::transform(a.begin(), a.end(), o.begin(), [&](const auto& x) { return x*b; } );
return o;
}
template <typename T>
constexpr T mul(const T& a, const T& b)
{
return a*b;
}
}
#endif

View file

@ -1,87 +0,0 @@
// -*- C++ -*-
/**
@file include/base/uuid.h
@brief cnorxz uuid declaration.
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_uuid_h__
#define __cxz_uuid_h__
#include <stdint.h>
#include <functional>
namespace CNORXZ
{
/** ***
uuid
*/
struct Uuid
{
uint64_t i1; /**< first 8 bytes */
uint64_t i2; /**< second 8 bytes */
};
/** create new uuid */
Uuid mkUuid();
/** operator equal to
@param a left hand side
@param b right hand side
*/
inline bool operator==(const Uuid& a, const Uuid& b)
{
return a.i1 == b.i1 and a.i2 == b.i2;
}
/** operator not equal to
@param a left hand side
@param b right hand side
*/
inline bool operator!=(const Uuid& a, const Uuid& b)
{
return a.i1 != b.i1 or a.i2 != b.i2;
}
/** operator less than
@param a left hand side
@param b right hand side
*/
inline bool operator<(const Uuid& a, const Uuid& b)
{
return (a.i1 == b.i1) ? a.i2 < b.i2 : a.i1 < b.i1;
}
/** operator greater than
@param a left hand side
@param b right hand side
*/
inline bool operator>(const Uuid& a, const Uuid& b)
{
return (a.i1 == b.i1) ? a.i2 > b.i2 : a.i1 > b.i1;
}
/** operator less or equal
@param a left hand side
@param b right hand side
*/
inline bool operator<=(const Uuid& a, const Uuid& b)
{
return not( (a.i1 == b.i1) ? a.i2 > b.i2 : a.i1 > b.i1 );
}
/** operator greater or equal
@param a left hand side
@param b right hand side
*/
inline bool operator>=(const Uuid& a, const Uuid& b)
{
return not( (a.i1 == b.i1) ? a.i2 < b.i2 : a.i1 < b.i1 );
}
}
#endif

39
src/include/base_def.h Normal file
View file

@ -0,0 +1,39 @@
// -*- C++ -*-
#ifndef __cxz_base_def_h__
#define __cxz_base_def_h__
#include <cassert>
#define DEBUG_MODE_X
#ifdef DEBUG_MODE_X
#include <iostream>
#ifndef CHECK
#define CHECK std::cout << __FILE__ << ": @" << __LINE__ << " in " << __func__ << std::endl;
#endif
#ifndef VCHECK
#define VCHECK(a) std::cout << __FILE__ << ": @" << __LINE__ \
<< " in " << __func__ << ": " << #a << " = " << a << std::endl;
#endif
#else
#define CHECK
#define VCHECK(a)
#endif
#define DEFAULT_MEMBERS(__class_name__) __class_name__() = default; \
__class_name__(const __class_name__& in) = default; \
__class_name__& operator=(const __class_name__& in) = default; \
__class_name__(__class_name__&& in) = default; \
__class_name__& operator=(__class_name__&& in) = default
#define DEFAULT_MEMBERS_X(__class_name__) __class_name__(const __class_name__& in) = default; \
__class_name__& operator=(const __class_name__& in) = default; \
__class_name__(__class_name__&& in) = default; \
__class_name__& operator=(__class_name__&& in) = default
#endif

18
src/include/basic_types.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef __cxz_basic_types_h__
#define __cxz_basic_types_h__
#include <string>
namespace CNORXZ
{
// just to fix this forever:
typedef int32_t Int;
typedef uint64_t SizeT;
typedef double Double;
typedef Double Real;
typedef std::string String;
}
#endif

View file

@ -1,16 +1,17 @@
// -*- C++ -*-
/**
@file include/cnorxz.cc.h
@brief cnorxz main template header
#include "ranges/ranges_header.cc.h"
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
#include "container_index.cc.h"
#include "cxz_operation.cc.h"
#include "functional_array.cc.h"
#include "helper_tools.cc.h"
#include "map_range.cc.h"
#include "cxz_array_base.cc.h"
#include "cxz_array.cc.h"
#include "slice.cc.h"
#include "dynamic_operation.cc.h"
#include "access.cc.h"
#include "op_expressions.cc.h"
//#include "high_level_operation.cc.h"
//#include "expressions.cc.h"
**/
#include "base/base.cc.h"
#include "memory/memory.cc.h"
#include "ranges/ranges.cc.h"
#include "array/array.cc.h"
#include "operation/operation.cc.h"

View file

@ -1,22 +1,19 @@
// -*- C++ -*-
/**
@file include/cnorxz.h
@brief cnorxz main header
Copyright (c) 2022 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_cnorxz_h__
#define __cxz_cnorxz_h__
#include "base/base.h"
#include "memory/memory.h"
#include "ranges/ranges.h"
#include "array/array.h"
#include "operation/operation.h"
#include <cstdlib>
#include "container_index.h"
#include "cxz_operation.h"
#include "cxz_array_base.h"
#include "cxz_array.h"
#include "functional_array.h"
#include "helper_tools.h"
#include "operation_def.h"
#include "map_range.h"
#include "dynamic_operation.h"
//#include "high_level_operation.h"
#include "cnorxz.cc.h"

View file

@ -0,0 +1,440 @@
#include "container_index.h"
namespace CNORXZ
{
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>::ConstContainerIndex(const ConstContainerIndex& in, bool copy) :
IB(in),
mNonTrivialBlocks(in.mNonTrivialBlocks),
mExternControl(false),
mBlockSizes(in.mBlockSizes),
mData(in.mData),
mObjPtrNum(in.mObjPtrNum),
mCPos(in.mCPos)
{
sfor_pn<0,sizeof...(Indices)>
( [&](auto i)
{
typedef typename std::remove_reference<decltype(*std::get<i>(mIPack))>::type
SubType;
std::get<i>(mIPack) = std::make_shared<SubType>( in.template get<i>() ) ;
return true;
});
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::copy(const ConstContainerIndex& in)
{
IB::operator=(in);
mNonTrivialBlocks = in.mNonTrivialBlocks;
mExternControl = false;
mBlockSizes = in.mBlockSizes;
mData = in.mData;
mObjPtrNum = in.mObjPtrNum;
mCPos = in.mCPos;
sfor_pn<0,sizeof...(Indices)>
( [&](auto i)
{
typedef typename std::remove_reference<decltype(*std::get<i>(mIPack))>::type
SubType;
std::get<i>(mIPack) = std::make_shared<SubType>( in.template get<i>() ) ;
return true;
});
return *this;
}
template <typename T, class... Indices>
template <class MRange>
ConstContainerIndex<T,Indices...>::ConstContainerIndex(const std::shared_ptr<MRange>& range,
std::intptr_t objPtrNum) :
IndexInterface<ConstContainerIndex<T,Indices...>,std::tuple<typename Indices::MetaType...> >(range, 0),
mObjPtrNum(objPtrNum)
{
std::get<sizeof...(Indices)>(mBlockSizes) = 1;
sfor_mn<sizeof...(Indices),0>
( [&](auto i) {
auto r = range->template getPtr<i>();
std::get<i>(mIPack) = r->beginPtr();
*std::get<i>(mIPack) = 0;
std::get<i>(mBlockSizes) = sfor_p<i,sizeof...(Indices)>
( [&](auto j) { return std::get<j>(mIPack)->max(); } ,
[&](auto a, auto b) { return a * b; });
return 0;
});
IB::mPos = sfor_m<sizeof...(Indices),0>
( [&](auto i) { return std::get<i>(mIPack); },
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
mCPos = RangeHelper::makePos<sizeof...(Indices)-1>(mIPack, mBlockSizes);
}
template <typename T, class... Indices>
template <class MRange>
ConstContainerIndex<T,Indices...>::ConstContainerIndex(const std::shared_ptr<MRange>& range,
std::intptr_t objPtrNum,
const std::array<size_t,sizeof...(Indices)+1>& blockSizes) :
IndexInterface<ConstContainerIndex<T,Indices...>,std::tuple<typename Indices::MetaType...> >(range, 0),
mObjPtrNum(objPtrNum)
{
sfor_mn<sizeof...(Indices),0>
( [&](auto i) {
auto r = range->template getPtr<i>();
std::get<i>(mIPack) = r->beginPtr();
*std::get<i>(mIPack) = 0;
return 0;
});
IB::mPos = sfor_m<sizeof...(Indices),0>
( [&](auto i) { return std::get<i>(mIPack); },
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
mCPos = RangeHelper::makePos<sizeof...(Indices)-1>(mIPack, mBlockSizes);
mNonTrivialBlocks = true;
}
template <typename T, class... Indices>
template <typename X>
ConstContainerIndex<T,Indices...>&
ConstContainerIndex<T,Indices...>::operator=(const ConstContainerIndex<X,Indices...>& in)
{
mIPack = in.mIPack;
return (*this)();
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::sync()
{
if(mExternControl){
IB::mPos = sfor_m<sizeof...(Indices),0>
( [&](auto i) { return std::get<i>(mIPack); },
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
mCPos = RangeHelper::makePos<sizeof...(Indices)-1>(mIPack, mBlockSizes);
}
return *this;
}
template <typename T, class... Indices>
template <size_t N>
auto& ConstContainerIndex<T,Indices...>::get() const
{
return *std::get<N>( mIPack );
}
template <typename T, class... Indices>
template <size_t N>
auto ConstContainerIndex<T,Indices...>::getPtr() const
{
return std::get<N>( mIPack );
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::operator()(const std::shared_ptr<Indices>&... inds)
{
return (*this)(std::make_tuple(inds...));
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::operator()(const std::tuple<std::shared_ptr<Indices>...>& inds)
{
sfor_pn<0,sizeof...(Indices)>
( [&](auto i) { std::get<i>(mIPack) = std::get<i>(inds); return 0; } );
mExternControl = true;
return sync();
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::operator()()
{
return sync();
}
template <typename T, class... Indices>
IndexType ConstContainerIndex<T,Indices...>::type() const { return IndexType::CONT; }
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::operator++()
{
if(mExternControl){
IB::mPos = sfor_m<sizeof...(Indices),0>
( [&](auto i) { return std::get<i>(mIPack); },
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
}
sfor_m<sizeof...(Indices),0>
( [&](auto i) {
auto& si = *std::get<i>( mIPack );
if(si.last() and i != 0) { si = 0; return true; }
else { ++si; return false; }
return false;
} );
mCPos = RangeHelper::makePos<sizeof...(Indices)-1>(mIPack, mBlockSizes);
++IB::mPos;
return *this;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::operator--()
{
if(mExternControl){
IB::mPos = sfor_m<sizeof...(Indices),0>
( [&](auto i) { return std::get<i>(mIPack); },
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
}
sfor_m<sizeof...(Indices),0>
( [&](auto i) {
auto& si = *std::get<i>( mIPack );
if(si.first() and i != 0) { si = si.max()-1; return true; }
else { --si; return false; }
return false;
} );
mCPos = RangeHelper::makePos<sizeof...(Indices)-1>(mIPack, mBlockSizes);
--IB::mPos;
return *this;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::operator=(size_t pos)
{
IB::mPos = pos;
RangeHelper::setIndexPack<sizeof...(Indices)-1>(mIPack, pos);
mCPos = RangeHelper::makePos<sizeof...(Indices)-1>(mIPack, mBlockSizes);
return *this;
}
template <typename T, class... Indices>
int ConstContainerIndex<T,Indices...>::pp(std::intptr_t idxPtrNum)
{
const int tmp = RangeHelper::ppx<sizeof...(Indices)-1>(mIPack, mBlockSizes, idxPtrNum);
IB::mPos += tmp;
return tmp;
}
template <typename T, class... Indices>
int ConstContainerIndex<T,Indices...>::mm(std::intptr_t idxPtrNum)
{
const int tmp = RangeHelper::mmx<sizeof...(Indices)-1>(mIPack, mBlockSizes, idxPtrNum);
IB::mPos -= tmp;
return tmp;
}
template <typename T, class... Indices>
std::string ConstContainerIndex<T,Indices...>::stringMeta() const
{
return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr )->stringMeta(IB::mPos);
}
template <typename T, class... Indices>
typename ConstContainerIndex<T,Indices...>::MetaType ConstContainerIndex<T,Indices...>::meta() const
{
MetaType metaTuple;
sfor_pn<0,sizeof...(Indices)>
( [&](auto i) { std::get<i>(metaTuple) = std::get<i>(mIPack)->meta(); return 0; } );
return metaTuple;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::at(const MetaType& metaPos)
{
sfor_pn<0,sizeof...(Indices)>
( [&](auto i) { std::get<i>(mIPack)->at( std::get<i>(metaPos) ); return 0; } );
IB::mPos = RangeHelper::makePos<sizeof...(Indices)-1>(mIPack, mBlockSizes);
return *this;
}
template <typename T, class... Indices>
size_t ConstContainerIndex<T,Indices...>::dim() const
{
return sizeof...(Indices);
}
template <typename T, class... Indices>
bool ConstContainerIndex<T,Indices...>::first() const
{
return IB::pos() == 0;
}
template <typename T, class... Indices>
bool ConstContainerIndex<T,Indices...>::last() const
{
return IB::pos() == IB::mMax - 1;
}
template <typename T, class... Indices>
bool ConstContainerIndex<T,Indices...>::sliceMode() const
{
return mNonTrivialBlocks;
}
template <typename T, class... Indices>
std::shared_ptr<typename ConstContainerIndex<T,Indices...>::RangeType>
ConstContainerIndex<T,Indices...>::range()
{
return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr );
}
template <typename T, class... Indices>
size_t ConstContainerIndex<T,Indices...>::getStepSize(size_t n)
{
if(n >= sizeof...(Indices)){
assert(0);
// throw !!
}
return mBlockSizes[n+1];
}
template <typename T, class... Indices>
template <class Exprs>
auto ConstContainerIndex<T,Indices...>::ifor(size_t step, Exprs exs) const
{
return RangeHelper::mkFor<0>(step, mIPack, mBlockSizes, exs);
}
template <typename T, class... Indices>
template <class Exprs>
auto ConstContainerIndex<T,Indices...>::iforh(size_t step, Exprs exs) const
{
return RangeHelper::mkForh<0>(step, mIPack, mBlockSizes, exs);
}
template <typename T, class... Indices>
template <class Exprs>
auto ConstContainerIndex<T,Indices...>::pifor(size_t step, Exprs exs) const
{
return RangeHelper::mkPFor<0>(step, mIPack, mBlockSizes, exs);
}
template <typename T, class... Indices>
std::intptr_t ConstContainerIndex<T,Indices...>::container() const
{
return mObjPtrNum;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::
format(const std::array<size_t,sizeof...(Indices)+1>& blocks)
{
mBlockSizes = blocks;
mNonTrivialBlocks = true;
return *this;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::setData(const T* data)
{
mData = data;
return *this;
}
template <typename T, class... Indices>
const T& ConstContainerIndex<T,Indices...>::operator*() const
{
return mData[mCPos];
}
template <typename T, class... Indices>
const T* ConstContainerIndex<T,Indices...>::operator->() const
{
return &mData[mCPos];
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...> ConstContainerIndex<T,Indices...>::operator++(int)
{
auto tmp = *this;
++(*this);
return tmp;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...> ConstContainerIndex<T,Indices...>::operator--(int)
{
auto tmp = *this;
--(*this);
return tmp;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::operator+=(int diff)
{
if(diff < 0){
for(int i = 0; i != diff; ++i){
(*this)--;
}
}
else {
for(int i = 0; i != diff; ++i){
(*this)++;
}
}
return *this;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...>& ConstContainerIndex<T,Indices...>::operator-=(int diff)
{
if(diff < 0){
for(int i = 0; i != diff; ++i){
(*this)++;
}
}
else {
for(int i = 0; i != diff; ++i){
(*this)--;
}
}
return *this;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...> ConstContainerIndex<T,Indices...>::operator+(int num) const
{
auto tmp = *this;
return tmp += num;
}
template <typename T, class... Indices>
ConstContainerIndex<T,Indices...> ConstContainerIndex<T,Indices...>::operator-(int num) const
{
auto tmp = *this;
return tmp -= num;
}
template <typename T, class... Indices>
int ConstContainerIndex<T,Indices...>::operator-(const ConstContainerIndex<T,Indices...>& it) const
{
return static_cast<int>( IB::mPos ) - static_cast<int>( it.pos() );
}
template <typename T, class... Indices>
const T& ConstContainerIndex<T,Indices...>::operator[](int num) const
{
return mData[IB::mPos + num];
}
template <typename T, class... Indices>
bool ConstContainerIndex<T,Indices...>::operator<(const ConstContainerIndex<T,Indices...>& it) const
{
return IB::mPos < it.pos();
}
template <typename T, class... Indices>
bool ConstContainerIndex<T,Indices...>::operator>(const ConstContainerIndex<T,Indices...>& it) const
{
return IB::mPos > it.pos();
}
template <typename T, class... Indices>
bool ConstContainerIndex<T,Indices...>::operator<=(const ConstContainerIndex<T,Indices...>& it) const
{
return IB::mPos <= it.pos();
}
template <typename T, class... Indices>
bool ConstContainerIndex<T,Indices...>::operator>=(const ConstContainerIndex<T,Indices...>& it) const
{
return IB::mPos >= it.pos();
}
} // namespace CNORXZ

View file

@ -0,0 +1,306 @@
// -*- C++ -*-
#ifndef __cxz_container_index_h__
#define __cxz_container_index_h__
#include <cstdlib>
#include <tuple>
#include <memory>
#include "ranges/range_base.h"
#include "ranges/index_base.h"
#include "mbase_def.h"
#include "statics/static_for.h"
#include "ranges/range_helper.h"
namespace CNORXZ
{
template <typename T, class... Indices>
class ConstContainerIndex : public IndexInterface<ConstContainerIndex<T,Indices...>,
std::tuple<typename Indices::MetaType...> >
{
public:
typedef IndexInterface<ConstContainerIndex<T,Indices...>,
std::tuple<typename Indices::MetaType...> > IB;
typedef std::tuple<typename Indices::MetaType...> MetaType;
typedef std::tuple<std::shared_ptr<Indices>...> IndexPack;
typedef ContainerRange<typename Indices::RangeType...> RangeType;
static constexpr IndexType sType() { return IndexType::CONT; }
static constexpr size_t sDim() { return sizeof...(Indices); }
static constexpr size_t totalDim() { return (... * Indices::totalDim()); }
static constexpr SpaceType STYPE = SpaceType::ANY;
static constexpr bool PARALLEL = std::tuple_element<0,std::tuple<Indices...>>::type::PARALLEL;
template <typename X>
using CIX = ConstContainerIndex<X,Indices...>;
template <typename X>
friend class CIX;
private:
ConstContainerIndex() = default;
bool mNonTrivialBlocks = false;
bool mExternControl = false;
IndexPack mIPack;
std::array<size_t,sizeof...(Indices)+1> mBlockSizes;
const T* mData = nullptr;
std::intptr_t mObjPtrNum;
protected:
size_t mCPos;
public:
ConstContainerIndex(const ConstContainerIndex& in) = default;
ConstContainerIndex& operator=(const ConstContainerIndex& in) = default;
ConstContainerIndex(const ConstContainerIndex& in, bool copy);
ConstContainerIndex& copy(const ConstContainerIndex& in);
template <typename X>
ConstContainerIndex& operator=(const ConstContainerIndex<X,Indices...>& in);
template <class MRange>
ConstContainerIndex(const std::shared_ptr<MRange>& range,
std::intptr_t objPtrNum);
template <class MRange>
ConstContainerIndex(const std::shared_ptr<MRange>& range,
std::intptr_t objPtrNum,
const std::array<size_t,sizeof...(Indices)+1>& blockSizes);
template <size_t N>
size_t getBlockSize() const { return std::get<N>(mBlockSizes); }
const IndexPack& pack() const { return mIPack; }
ConstContainerIndex& sync(); // recalculate 'IB::mPos' when externalControl == true
ConstContainerIndex& operator()(const std::shared_ptr<Indices>&... inds); // control via external indices
ConstContainerIndex& operator()(const std::tuple<std::shared_ptr<Indices>...>& inds);
ConstContainerIndex& operator()(); // -> sync; just to shorten the code
// ==== >>>>> STATIC POLYMORPHISM <<<<< ====
IndexType type() const;
ConstContainerIndex& operator++();
ConstContainerIndex& operator--();
ConstContainerIndex& operator=(size_t pos);
int pp(std::intptr_t idxPtrNum);
int mm(std::intptr_t idxPtrNum);
std::string stringMeta() const;
MetaType meta() const;
ConstContainerIndex& at(const MetaType& metaPos);
size_t dim() const;
bool first() const;
bool last() const;
bool sliceMode() const;
std::shared_ptr<RangeType> range();
template <size_t N>
auto& get() const;
template <size_t N>
auto getPtr() const;
size_t getStepSize(size_t n);
template <class Exprs>
auto ifor(size_t step, Exprs exs) const;
template <class Exprs>
auto iforh(size_t step, Exprs exs) const;
template <class Exprs>
auto pifor(size_t step, Exprs exs) const;
std::intptr_t container() const;
ConstContainerIndex& format(const std::array<size_t,sizeof...(Indices)+1>& blocks);
// Iterator Stuff
ConstContainerIndex& setData(const T* data);
const T& operator*() const;
const T* operator->() const;
//T& operator*();
//T* operator->();
ConstContainerIndex operator++(int);
ConstContainerIndex operator--(int);
ConstContainerIndex& operator+=(int diff);
ConstContainerIndex& operator-=(int diff);
ConstContainerIndex operator+(int num) const;
ConstContainerIndex operator-(int num) const;
int operator-(const ConstContainerIndex& it) const;
const T& operator[](int num) const;
bool operator<(const ConstContainerIndex& it) const;
bool operator>(const ConstContainerIndex& it) const;
bool operator<=(const ConstContainerIndex& it) const;
bool operator>=(const ConstContainerIndex& it) const;
};
template <typename T, class... Indices>
class ContainerIndex : public ConstContainerIndex<T,Indices...>
{
public:
typedef ConstContainerIndex<T,Indices...> CCI;
typedef CCI IB;
typedef typename CCI::MetaType MetaType;
typedef typename CCI::IndexPack IndexPack;
typedef typename CCI::RangeType RangeType;
static constexpr IndexType sType() { return CCI::sType(); }
static constexpr size_t sDim() { return CCI::sDim(); }
static constexpr size_t totalDim() { return CCI::totalDim(); }
static constexpr SpaceType STYPE = CCI::STYPE;
static constexpr bool PARALLEL = CCI::PARALLEL;
template <typename X>
using CIX = ContainerIndex<X,Indices...>;
template <typename X>
friend class CIX;
private:
ContainerIndex() = default;
T* mMData = nullptr;
public:
ContainerIndex(const ContainerIndex& in) = default;
ContainerIndex& operator=(const ContainerIndex& in) = default;
ContainerIndex(const ContainerIndex& in, bool copy) : CCI(in,copy)
{ mMData = in.mMData; }
ContainerIndex(const ConstContainerIndex<T,Indices...>& in, T* data) : CCI(in)
{ mMData = data; }
ContainerIndex(const ConstContainerIndex<T,Indices...>& in, T* data, bool copy) :
CCI(in,copy)
{ mMData = data; }
ContainerIndex& copy(const ContainerIndex& in)
{ CCI::copy(in); mMData = in.mMData; }
template <typename X>
ContainerIndex& operator=(const ContainerIndex<X,Indices...>& in)
{ CCI::operator=(in); return *this; }
template <class MRange>
ContainerIndex(const std::shared_ptr<MRange>& range,
std::intptr_t objPtrNum) : CCI(range, objPtrNum) {}
template <class MRange>
ContainerIndex(const std::shared_ptr<MRange>& range,
std::intptr_t objPtrNum,
const std::array<size_t,sizeof...(Indices)+1>& blockSizes)
: CCI(range, objPtrNum, blockSizes) {}
template <size_t N>
size_t getBlockSize() const { return CCI::template getBlockSize<N>(); }
const IndexPack& pack() const { CCI::pack(); return *this; }
ContainerIndex& sync() { return CCI::sync(); return *this; }
ContainerIndex& operator()(const std::shared_ptr<Indices>&... inds)
{ CCI::operator()(inds...); return *this; }
ContainerIndex& operator()(const std::tuple<std::shared_ptr<Indices>...>& inds)
{ CCI::operator()(inds); return *this; }
ContainerIndex& operator()() { CCI::operator()(); return *this; }
// ==== >>>>> STATIC POLYMORPHISM <<<<< ====
IndexType type() const { return CCI::type(); }
ContainerIndex& operator++() { CCI::operator++(); return *this; }
ContainerIndex& operator--() { CCI::operator--(); return *this; }
ContainerIndex& operator=(size_t pos) { CCI::operator=(pos); return *this; }
int pp(std::intptr_t idxPtrNum) { return CCI::pp(idxPtrNum); }
int mm(std::intptr_t idxPtrNum) { return CCI::mm(idxPtrNum); }
std::string stringMeta() const { return CCI::stringMeta; }
MetaType meta() const { return CCI::meta(); }
ContainerIndex& at(const MetaType& metaPos) { CCI::at(metaPos); return *this; }
size_t dim() const { return CCI::dim(); }
bool first() const { return CCI::first(); }
bool last() const { return CCI::last(); }
bool sliceMode() const { return CCI::sliceMode(); }
std::shared_ptr<RangeType> range() { return CCI::range(); }
template <size_t N>
auto& get() const { return CCI::template get<N>(); }
template <size_t N>
auto getPtr() const { return CCI::template getPtr<N>(); }
size_t getStepSize(size_t n) { return getStepSize(n); }
template <class Exprs>
auto ifor(size_t step, Exprs exs) const { return CCI::ifor(step, exs); }
template <class Exprs>
auto iforh(size_t step, Exprs exs) const { return CCI::iforh(step, exs); }
template <class Exprs>
auto pifor(size_t step, Exprs exs) const { return CCI::pifor(step, exs); }
std::intptr_t container() const { return CCI::container(); }
ContainerIndex& format(const std::array<size_t,sizeof...(Indices)+1>& blocks)
{ CCI::format(blocks); return *this; }
// Iterator Stuff
ContainerIndex& setData(T* data) { CCI::setData(data); mMData = data; return *this; }
const T& operator*() const { return CCI::operator*(); }
const T* operator->() const { return CCI::operator->(); }
T& operator*() { return mMData[CCI::mCPos]; }
T* operator->() { return &mMData[CCI::mCPos]; }
ContainerIndex operator++(int) { auto tmp = *this; ++(*this); return tmp; }
ContainerIndex operator--(int) { auto tmp = *this; --(*this); return tmp; }
ContainerIndex& operator+=(int diff) { CCI::operator+=(diff); return *this; }
ContainerIndex& operator-=(int diff) { CCI::operator-=(diff); return *this; }
ContainerIndex operator+(int num) const { CCI::operator+(num); return *this; }
ContainerIndex operator-(int num) const { CCI::operator-(num); return *this; }
int operator-(const ContainerIndex& it) const { return CCI::operator-(it); }
const T& operator[](int num) const { return CCI::operator[](num); }
bool operator<(const ContainerIndex& it) const { return CCI::operator<(it); }
bool operator>(const ContainerIndex& it) const { return CCI::operator>(it); }
bool operator<=(const ContainerIndex& it) const { return CCI::operator<=(it); }
bool operator>=(const ContainerIndex& it) const { return CCI::operator>=(it); }
};
} // end namespace CNORXZ
#endif

122
src/include/conversions.h Normal file
View file

@ -0,0 +1,122 @@
#ifndef __cxz_conversions_h__
#define __cxz_conversions_h__
#include "cxz_array.h"
#include "slice.h"
namespace CNORXZ
{
namespace ConversionSizes
{
template <size_t N>
struct OrigSize
{
template <typename C, typename T>
struct FromTo
{
static void check() { static_assert( not N % (sizeof(T) / sizeof(C)), "conversion does not fit" ); }
static constexpr size_t SIZE = N * sizeof(T) / sizeof(C);
};
};
template <>
struct OrigSize<MUI>
{
template <typename C, typename T>
struct FromTo
{
static void check() {}
static constexpr size_t SIZE = MUI;
};
};
}
namespace
{
template <typename C, typename T, size_t N>
using SC = typename ConversionSizes::OrigSize<N>::template FromTo<C,T>;
template <typename C, typename T, class Range>
using SCR = SC<C,T,Range::SIZE>;
template <typename C, typename T, class Range>
using SCRR = GenSingleRange<typename Range::MetaType,SpaceType::NONE,SCR<C,T,Range>::SIZE>;
}
template <size_t N>
struct SubTuple
{
template <class RTP, class... Ranges>
static inline auto mk(const RTP& rtp, const Ranges&... rs)
-> decltype(SubTuple<N-1>::mk(rtp, std::get<N>(rtp), rs...))
{
return SubTuple<N-1>::mk(rtp, std::get<N>(rtp), rs...);
}
};
template <>
struct SubTuple<0>
{
template <class RTP, class... Ranges>
static inline auto mk(const RTP& rtp, const Ranges&... rs)
-> decltype(std::make_tuple(std::get<0>(rtp), rs...))
{
return std::make_tuple(std::get<0>(rtp), rs...);
}
};
template <class... Ranges>
using LastR = typename std::tuple_element<sizeof...(Ranges)-1,std::tuple<Ranges...>>::type;
template <typename C, typename T, class... Ranges>
auto rtcast(const std::tuple<std::shared_ptr<Ranges>...>& rtp)
-> decltype(std::tuple_cat(SubTuple<sizeof...(Ranges)-2>::mk(rtp),
std::make_tuple( std::dynamic_pointer_cast<SCRR<C,T,LastR<Ranges...>>>
( SCRR<C,T,LastR<Ranges...>>::factory().create() ) ) ))
{
return std::tuple_cat(SubTuple<sizeof...(Ranges)-2>::mk(rtp),
std::make_tuple( std::dynamic_pointer_cast<SCRR<C,T,LastR<Ranges...>>>
( SCRR<C,T,LastR<Ranges...>>::factory().create() ) ) );
}
template <typename T, class... Ranges>
inline Slice<T,Ranges...> rangeTpToSlice( const std::tuple<std::shared_ptr<Ranges>...>& rtp, T* data )
{
return Slice<T,Ranges...>(rtp, data);
}
template <typename T, class... Ranges>
inline ConstSlice<T,Ranges...> rangeTpToSlice( const std::tuple<std::shared_ptr<Ranges>...>& rtp, const T* data )
{
return ConstSlice<T,Ranges...>(rtp, data);
}
template <typename C, typename T, class... Ranges>
auto tcast(Array<T,Ranges...>& ma)
-> decltype(rangeTpToSlice
( rtcast<C,T>( ma.range()->space() ),
reinterpret_cast<C*>( ma.data() ) ))
{
// VCHECK(reinterpret_cast<std::intptr_t>(ma.data()) % 32);
//VCHECK(reinterpret_cast<std::intptr_t>(reinterpret_cast<C*>(ma.data())) % 32);
return rangeTpToSlice
( rtcast<C,T>( ma.range()->space() ),
reinterpret_cast<C*>( ma.data() ) );
}
template <typename C, typename T, class... Ranges>
auto tcast(const Array<T,Ranges...>& ma)
-> decltype(rangeTpToSlice
( rtcast<C,T>( ma.range()->space() ),
reinterpret_cast<const C*>( ma.data() ) ))
{
//VCHECK(reinterpret_cast<std::intptr_t>(ma.data()) % 32);
//VCHECK(reinterpret_cast<std::intptr_t>(reinterpret_cast<C*>(ma.data())) % 32);
return rangeTpToSlice
( rtcast<C,T>( ma.range()->space() ),
reinterpret_cast<const C*>( ma.data() ) );
}
}
#endif

269
src/include/cxz_array.cc.h Normal file
View file

@ -0,0 +1,269 @@
#include "cxz_array.h"
#include "statics/static_for.h"
namespace CNORXZ
{
template <typename T>
Scalar<T> scalar(const T& in)
{
NullRF nrf;
return Scalar<T>( std::dynamic_pointer_cast<NullRange>( nrf.create() ), vector<T>( { in } ) );
}
/*******************
* Array *
*******************/
template <typename T, class... SRanges>
Array<T,SRanges...>::Array(const typename CRange::Space& space) :
MutableArrayBase<T,SRanges...>(space),
mCont(MAB::mRange->size())
{
MAB::mInit = true;
}
template <typename T, class... SRanges>
Array<T,SRanges...>::Array(const typename CRange::Space& space,
const vector<T>& vec) :
MutableArrayBase<T,SRanges...>(space),
mCont(vec)
{
MAB::mInit = true;
if(mCont.size() > MAB::mRange->size()){
mCont.erase(mCont.begin() + MAB::mRange->size(), mCont.end());
}
}
template <typename T, class... SRanges>
Array<T,SRanges...>::Array(const std::shared_ptr<SRanges>&... ranges) :
MutableArrayBase<T,SRanges...>(ranges...),
mCont(MAB::mRange->size())
{
MAB::mInit = true;
}
template <typename T, class... SRanges>
Array<T,SRanges...>::Array(const std::shared_ptr<SRanges>&... ranges, const T& val) :
MutableArrayBase<T,SRanges...>(ranges...),
mCont(MAB::mRange->size(), val)
{
MAB::mInit = true;
}
template <typename T, class... SRanges>
Array<T,SRanges...>::Array(const std::shared_ptr<SRanges>&... ranges, const vector<T>& vec) :
MutableArrayBase<T,SRanges...>(ranges...),
mCont(vec)
{
MAB::mInit = true;
if(mCont.size() > MAB::mRange->size()){
mCont.erase(mCont.begin() + MAB::mRange->size(), mCont.end());
}
}
template <typename T, class... SRanges>
Array<T,SRanges...>::Array(const std::shared_ptr<SRanges>&... ranges, vector<T>&& vec) :
MutableArrayBase<T,SRanges...>(ranges...),
mCont(std::forward<vector<T>>(vec))
{
MAB::mInit = true;
if(mCont.size() > MAB::mRange->size()){
mCont.erase(mCont.begin() + MAB::mRange->size(), mCont.end());
}
}
template <typename T, class... SRanges>
template <class... Ranges>
Array<T,SRanges...>::Array(const std::shared_ptr<SRanges>&... ranges, Array<T,Ranges...>&& in) :
MutableArrayBase<T,SRanges...>(ranges...),
mCont( std::move( in.mCont ) )
{
// maybe some checks here in the future...
assert(mCont.size() == MAB::mRange->size());
MAB::mInit = true;
in.mInit = false;
}
template <typename T, class... SRanges>
Array<T,SRanges...>::Array(Array<T,AnonymousRange>&& ama, SIZET<SRanges>... sizes) :
MutableArrayBase<T,SRanges...>
( ama.range()->template get<0>().template scast<SRanges...>(sizes...)->space() ),
mCont( std::move( ama.mCont ) )
{
MAB::mInit = true;
ama.mInit = false;
}
template <typename T, class... SRanges>
T& Array<T,SRanges...>::operator[](const IndexType& i)
{
return mCont[ i.pos() ];
}
template <typename T, class... SRanges>
const T& Array<T,SRanges...>::operator[](const IndexType& i) const
{
return mCont[ i.pos() ];
}
template <typename T, class... SRanges>
T& Array<T,SRanges...>::at(const typename IndexType::MetaType& meta)
{
return mCont[ MAB::cbegin().at(meta).pos() ];
}
template <typename T, class... SRanges>
const T& Array<T,SRanges...>::at(const typename IndexType::MetaType& meta) const
{
return mCont[ MAB::cbegin().at(meta).pos() ];
}
template <typename T, class... SRanges>
bool Array<T,SRanges...>::isConst() const
{
return false;
}
template <typename T, class... SRanges>
bool Array<T,SRanges...>::isSlice() const
{
return false;
}
template <typename T, class... SRanges>
template <class... SRanges2>
Array<T,SRanges2...> Array<T,SRanges...>::format(const std::shared_ptr<SRanges2>&... nrs)
{
//MAB::mInit = false;
return Array<T,SRanges2...>( nrs... , mCont );
}
template <typename T, class... SRanges>
template <class... SRanges2>
Array<T,SRanges2...> Array<T,SRanges...>::format(const std::tuple<std::shared_ptr<SRanges2>...>& nrs)
{
//MAB::mInit = false;
return Array<T,SRanges2...>( nrs , mCont );
}
template <typename T, class... SRanges>
template <class... SRanges2>
Slice<T,SRanges2...> Array<T,SRanges...>::slformat(const std::shared_ptr<SRanges2>&... nrs)
{
return Slice<T,SRanges2...>( nrs..., mCont.data() );
}
template <typename T, class... SRanges>
template <class... SRanges2>
ConstSlice<T,SRanges2...> Array<T,SRanges...>::slformat(const std::shared_ptr<SRanges2>&... nrs) const
{
return ConstSlice<T,SRanges2...>( nrs..., mCont.data() );
}
template <typename T, class... SRanges>
const T* Array<T,SRanges...>::data() const
{
return mCont.data();
}
template <typename T, class... SRanges>
T* Array<T,SRanges...>::data()
{
return mCont.data();
}
template <typename T, class... SRanges>
std::shared_ptr<ArrayBase<T,AnonymousRange> > Array<T,SRanges...>::anonymous(bool slice) const
{
AnonymousRangeFactory arf(MAB::mRange->space());
if(slice){
return std::make_shared<ConstSlice<T,AnonymousRange> >
( std::dynamic_pointer_cast<AnonymousRange>( arf.create() ),
data() );
}
else {
return std::make_shared<Array<T,AnonymousRange> >
( std::dynamic_pointer_cast<AnonymousRange>( arf.create() ),
mCont );
}
}
template <typename T, class... SRanges>
Array<T,SRanges...>& Array<T,SRanges...>::operator=(const T& in)
{
for(auto& x: mCont){
x = in;
}
return *this;
}
template <typename T, class... SRanges>
Array<T,SRanges...>& Array<T,SRanges...>::operator+=(const Array& in)
{
if(not MAB::mInit){ // not initialized by default constructor !!
(*this) = in;
}
else {
sfor_p<0,sizeof...(SRanges),0>
( [&](auto i) { return std::get<i>(MAB::mRange->space()).get() == std::get<i>(in.mRange->space()).get(); },
[&](auto a, auto b) { return a and b; });
for(size_t i = 0; i != mCont.size(); ++i){
mCont[i] += in.mCont[i];
}
}
return *this;
}
template <typename T, class... SRanges>
Array<T,SRanges...>& Array<T,SRanges...>::operator-=(const Array& in)
{
if(not MAB::mInit){ // not initialized by default constructor !!
(*this) = in;
}
else {
sfor_p<0,sizeof...(SRanges),0>
( [&](auto i) { return std::get<i>(MAB::mRange->space()).get() == std::get<i>(in.mRange->space()).get(); },
[&](auto a, auto b) { return a and b; });
for(size_t i = 0; i != mCont.size(); ++i){
mCont[i] -= in.mCont[i];
}
}
return *this;
}
template <typename T, class... SRanges>
Array<T,SRanges...>& Array<T,SRanges...>::operator*=(const T& in)
{
for(auto& x: mCont){
x *= in;
}
return *this;
}
template <typename T, class... SRanges>
Array<T,SRanges...>& Array<T,SRanges...>::operator/=(const T& in)
{
for(auto& x: mCont){
x /= in;
}
return *this;
}
template <typename T, class... SRanges>
Array<T,SRanges...>::operator T() const
{
//static_assert( sizeof...(SRanges) == 1, "try to cast non-scalar type into scalar" );
// TODO: check that SIZE is statically = 1 !!!
return mCont[0];
}
template <typename T, class... SRanges>
auto Array<T,SRanges...>::cat() const
-> decltype(ArrayCatter<T>::cat(*this))
{
return ArrayCatter<T>::cat(*this);
}
}

151
src/include/cxz_array.h Normal file
View file

@ -0,0 +1,151 @@
// -*- C++ -*-
#ifndef __cxz_array_h__
#define __cxz_array_h__
#include <algorithm>
#include "cxz_array_base.h"
#include "ranges/anonymous_range.h"
namespace CNORXZ
{
template <typename T>
struct ArrayCatter;
template <typename T>
struct ArrayCatter
{
template <class... Ranges>
static auto cat(const Array<T,Ranges...>& ma)
-> Array<T,Ranges...>
{
return ma;
}
};
template <typename T, class... SRanges>
class Array : public MutableArrayBase<T,SRanges...>
{
public:
typedef ContainerRange<SRanges...> CRange;
typedef ArrayBase<T,SRanges...> MAB;
typedef ConstContainerIndex<T,typename SRanges::IndexType...> IndexType;
using ArrayBase<T,SRanges...>::operator[];
using MutableArrayBase<T,SRanges...>::operator[];
DEFAULT_MEMBERS(Array);
Array(const std::shared_ptr<SRanges>&... ranges);
Array(const std::shared_ptr<SRanges>&... ranges, const T& val);
Array(const std::shared_ptr<SRanges>&... ranges, const vector<T>& vec);
Array(const std::shared_ptr<SRanges>&... ranges, vector<T>&& vec);
template <class... Ranges>
Array(const std::shared_ptr<SRanges>&... ranges, Array<T,Ranges...>&& in); // same effect as format
Array(const typename CRange::Space& space);
Array(const typename CRange::Space& space, const vector<T>& vec);
Array(Array<T,AnonymousRange>&& ama, SIZET<SRanges>... sizes);
// Only if ALL ranges have default extensions:
//Array(const vector<T>& vec);
//Array(vector<T>&& vec);
// template <class Range2, class Range3>
// Array(const Array<Array<T,Range2>,Range3> in);
// implement contstructor using FunctionalArray as Input !!!
//template <class Range2, class Range3>
//Array& operator=(const Array<Array<T,Range2>,Range3> in);
virtual T& operator[](const IndexType& i) final;
virtual const T& operator[](const IndexType& i) const final;
virtual T& at(const typename IndexType::MetaType& meta) override;
virtual const T& at(const typename IndexType::MetaType& meta) const override;
virtual bool isConst() const override;
virtual bool isSlice() const override;
template <class... SRanges2>
Array<T,SRanges2...> format(const std::shared_ptr<SRanges2>&... nrs); // reformat array using 'nr' which in
// total must have the same size as mRange
template <class... SRanges2>
Array<T,SRanges2...> format(const std::tuple<std::shared_ptr<SRanges2>...>& nrs);
template <class... SRanges2>
Slice<T,SRanges2...> slformat(const std::shared_ptr<SRanges2>&... nrs);
template <class... SRanges2>
ConstSlice<T,SRanges2...> slformat(const std::shared_ptr<SRanges2>&... nrs) const;
virtual const T* data() const override;
virtual T* data() override;
virtual vector<T>& vdata() { return mCont; }
virtual const vector<T>& vdata() const { return mCont; }
vector<T>&& vmove() { MAB::mInit = false; return std::move(mCont); }
virtual std::shared_ptr<ArrayBase<T,AnonymousRange> > anonymous(bool slice = false) const override;
//virtual std::shared_ptr<ArrayBase<T,AnonymousRange> > anonymousMove() override;
auto cat() const
-> decltype(ArrayCatter<T>::cat(*this));
operator T() const;
Array& operator=(const T& in);
Array& operator+=(const Array& in);
Array& operator-=(const Array& in);
Array& operator*=(const T& in);
Array& operator/=(const T& in);
template <typename U, class... SRanges2>
friend class Array;
private:
vector<T> mCont;
};
template <typename T>
using Scalar = Array<T,NullRange>;
template <typename T>
Scalar<T> scalar(const T& in);
template <typename T, class... ERanges>
struct ArrayCatter<Array<T,ERanges...> >
{
template <class... Ranges>
static auto cat(const Array<Array<T,ERanges...>,Ranges...>& ma)
-> Array<T,Ranges...,ERanges...>
{
auto sma = *ma.begin();
const size_t smas = sma.size();
const size_t mas = ma.size();
auto cr = ma.range()->cat(sma.range());
vector<T> ov;
ov.reserve(mas * smas);
for(auto& x: ma){
assert(x.size() == smas);
ov.insert(ov.end(), x.vdata().begin(), x.vdata().end());
}
return Array<T,Ranges...,ERanges...>(cr->space(), std::move(ov));
}
};
}
/* ========================= *
* --- TEMPLATE CODE --- *
* ========================= */
#endif

View file

@ -0,0 +1,274 @@
#include "cxz_array_base.h"
namespace CNORXZ
{
/**********************
* ArrayBase *
**********************/
template <typename T, class... SRanges>
ArrayBase<T,SRanges...>::ArrayBase(const ArrayBase& in) :
mInit(in.mInit),
mRange(in.mRange)
{
if(mRange){
mProtoI = std::make_shared<IndexType>( mRange, reinterpret_cast<std::intptr_t>(this) );
}
}
template <typename T, class... SRanges>
ArrayBase<T,SRanges...>::ArrayBase(ArrayBase&& in) :
mInit(in.mInit),
mRange(in.mRange)
{
if(mRange){
mProtoI = std::make_shared<IndexType>( mRange, reinterpret_cast<std::intptr_t>(this) );
}
}
template <typename T, class... SRanges>
ArrayBase<T,SRanges...>& ArrayBase<T,SRanges...>::operator=(const ArrayBase& in)
{
mInit = in.mInit;
mRange = in.mRange;
if(mRange){
mProtoI = std::make_shared<IndexType>( mRange, reinterpret_cast<std::intptr_t>(this) );
}
return *this;
}
template <typename T, class... SRanges>
ArrayBase<T,SRanges...>& ArrayBase<T,SRanges...>::operator=(ArrayBase&& in)
{
mInit = in.mInit;
mRange = in.mRange;
if(mRange){
mProtoI = std::make_shared<IndexType>( mRange, reinterpret_cast<std::intptr_t>(this) );
}
return *this;
}
template <typename T, class... SRanges>
ArrayBase<T,SRanges...>::ArrayBase(const std::shared_ptr<SRanges>&... ranges)
{
ContainerRangeFactory<SRanges...> crf(ranges...);
mRange = std::dynamic_pointer_cast<ContainerRange<SRanges...> >( crf.create() );
mProtoI = std::make_shared<IndexType>( mRange, reinterpret_cast<std::intptr_t>(this) );
}
template <typename T, class... SRanges>
ArrayBase<T,SRanges...>::ArrayBase(const typename CRange::Space& space)
{
ContainerRangeFactory<SRanges...> crf(space);
mRange = std::dynamic_pointer_cast<ContainerRange<SRanges...> >( crf.create() );
mProtoI = std::make_shared<IndexType>( mRange, reinterpret_cast<std::intptr_t>(this) );
}
template <typename T, class... SRanges>
template <typename X>
const T& ArrayBase<T,SRanges...>::operator[](const ConstContainerIndex<X,typename SRanges::IndexType...>& i)
{
IndexType ii(*mProtoI);
ii = i;
return (*this)[ii];
}
template <typename T, class... SRanges>
const T& ArrayBase<T,SRanges...>::operator[](const std::tuple<IPTR<typename SRanges::IndexType>...>& is) const
{
IndexType ii(*mProtoI);
ii(is);
return (*this)[ii];
}
template <typename T, class... SRanges>
size_t ArrayBase<T,SRanges...>::size() const
{
return mRange->size();
}
template <typename T, class... SRanges>
typename ArrayBase<T,SRanges...>::CIndexType ArrayBase<T,SRanges...>::begin() const
{
return cbegin();
}
template <typename T, class... SRanges>
typename ArrayBase<T,SRanges...>::CIndexType ArrayBase<T,SRanges...>::end() const
{
return end();
}
template <typename T, class... SRanges>
typename ArrayBase<T,SRanges...>::CIndexType ArrayBase<T,SRanges...>::cbegin() const
{
CIndexType i(*mProtoI,true);
i = 0;
return i.setData(data());
}
template <typename T, class... SRanges>
typename ArrayBase<T,SRanges...>::CIndexType ArrayBase<T,SRanges...>::cend() const
{
CIndexType i(*mProtoI,true);
i = i.max();
return i.setData(data());
}
template <typename T, class... SRanges>
const std::shared_ptr<typename ArrayBase<T,SRanges...>::CRange>&
ArrayBase<T,SRanges...>::range() const
{
return mRange;
}
template <typename T, class... SRanges>
bool ArrayBase<T,SRanges...>::isConst() const
{
return true;
}
template <typename T, class... SRanges>
ConstOperationRoot<T,SRanges...>
ArrayBase<T,SRanges...>::operator()(const std::shared_ptr<typename SRanges::IndexType>&... inds) const
{
return ConstOperationRoot<T,SRanges...>(*this, inds...);
}
template <typename T, class... SRanges>
ConstOperationRoot<T,SRanges...>
ArrayBase<T,SRanges...>::op(const std::shared_ptr<CIndexType>& ind) const
{
return ConstOperationRoot<T,SRanges...>(data(), *ind);
}
template <typename T, class... SRanges>
template <class... MappedRanges>
ConstOperationRoot<T,MappedRanges...>
ArrayBase<T,SRanges...>::m(const std::shared_ptr<typename MappedRanges::IndexType>&... inds) const
{
static_assert(sizeof...(SRanges) == sizeof...(MappedRanges),
"number of mapped ranges must be equal to number of original ranges");
return ConstOperationRoot<T,MappedRanges...>(*this, inds...);
}
template <typename T, class... SRanges>
bool ArrayBase<T,SRanges...>::isInit() const
{
return mInit;
}
template <typename T, class... SRanges>
template <size_t N>
auto ArrayBase<T,SRanges...>::getRangePtr() const
-> decltype(mRange->template getPtr<N>())
{
return mRange->template getPtr<N>();
}
/******************************
* MutableArrayBase *
******************************/
template <typename T, class... SRanges>
MutableArrayBase<T,SRanges...>::MutableArrayBase(const std::shared_ptr<SRanges>&... ranges) :
ArrayBase<T,SRanges...>(ranges...) {}
template <typename T, class... SRanges>
MutableArrayBase<T,SRanges...>::MutableArrayBase(const typename CRange::Space& space) :
ArrayBase<T,SRanges...>(space) {}
template <typename T, class... SRanges>
template <typename X>
T& MutableArrayBase<T,SRanges...>::operator[](const ConstContainerIndex<X,typename SRanges::IndexType...>& i)
{
IndexType ii(*MAB::mProtoI);
ii = i;
return (*this)[ii];
}
template <typename T, class... SRanges>
T& MutableArrayBase<T,SRanges...>::operator[](const std::tuple<IPTR<typename SRanges::IndexType>...>& is)
{
IndexType ii(*MAB::mProtoI,this->data());
ii(is);
return (*this)[ii];
}
template <typename T, class... SRanges>
typename MutableArrayBase<T,SRanges...>::IndexType MutableArrayBase<T,SRanges...>::begin()
{
IndexType i(*MAB::mProtoI,this->data(),true);
i = 0;
return i.setData(data());
}
template <typename T, class... SRanges>
typename MutableArrayBase<T,SRanges...>::IndexType MutableArrayBase<T,SRanges...>::end()
{
IndexType i(*MAB::mProtoI,this->data(),true);
i = i.max();
return i.setData(data());
}
template <typename T, class... SRanges>
bool MutableArrayBase<T,SRanges...>::isConst() const
{
return false;
}
template <typename T, class... SRanges>
OperationRoot<T,SRanges...>
MutableArrayBase<T,SRanges...>::operator()(const std::shared_ptr<typename SRanges::IndexType>&... inds)
{
return OperationRoot<T,SRanges...>(*this, inds...);
}
template <typename T, class... SRanges>
OperationRoot<T,SRanges...>
MutableArrayBase<T,SRanges...>::op(const std::shared_ptr<CIndexType>& ind)
{
return OperationRoot<T,SRanges...>(data(), *ind);
}
template <typename T, class... SRanges>
ConstOperationRoot<T,SRanges...>
MutableArrayBase<T,SRanges...>::operator()(const std::shared_ptr<typename SRanges::IndexType>&... inds) const
{
return ConstOperationRoot<T,SRanges...>(*this, inds...);
}
template <typename T, class... SRanges>
ConstOperationRoot<T,SRanges...>
MutableArrayBase<T,SRanges...>::op(const std::shared_ptr<CIndexType>& ind) const
{
return ConstOperationRoot<T,SRanges...>(data(), *ind);
}
template <typename T, class... SRanges>
template <class... MappedRanges>
OperationRoot<T,MappedRanges...>
MutableArrayBase<T,SRanges...>::m(const std::shared_ptr<typename MappedRanges::IndexType>&... inds)
{
static_assert(sizeof...(SRanges) == sizeof...(MappedRanges),
"number of mapped ranges must be equal to number of original ranges");
return OperationRoot<T,MappedRanges...>(*this, inds...);
}
template <typename T, class... SRanges>
template <class... MappedRanges>
ConstOperationRoot<T,MappedRanges...>
MutableArrayBase<T,SRanges...>::m(const std::shared_ptr<typename MappedRanges::IndexType>&... inds) const
{
static_assert(sizeof...(SRanges) == sizeof...(MappedRanges),
"number of mapped ranges must be equal to number of original ranges");
return ConstOperationRoot<T,MappedRanges...>(*this, inds...);
}
} // end namespace CNORXZ

View file

@ -0,0 +1,187 @@
#ifndef __cxz_array_base_h__
#define __cxz_array_base_h__
#include <cstdlib>
#include <vector>
#include <memory>
#include <algorithm>
#include "base_def.h"
#include "mbase_def.h"
#include "ranges/rheader.h"
namespace CNORXZ
{
template <class IndexType>
using IPTR = std::shared_ptr<IndexType>;
template <class IndexType1, class IndexType2>
inline auto operator|(const IPTR<IndexType1>& i1, const IPTR<IndexType2>& i2)
-> decltype(std::make_tuple(i1,i2))
{
return std::make_tuple(i1,i2);
}
template <class IndexType1, class... IndexTypes2>
inline auto operator|(const IPTR<IndexType1>& i1,
const std::tuple<IPTR<IndexTypes2>...>& i2)
-> decltype(std::tuple_cat(std::make_tuple(i1),i2))
{
return std::tuple_cat(std::make_tuple(i1),i2);
}
template <class IndexType2, class... IndexTypes1>
inline auto operator|(const std::tuple<IPTR<IndexTypes1>...>& i1,
const IPTR<IndexType2>& i2)
-> decltype(std::tuple_cat(i1,std::make_tuple(i2)))
{
return std::tuple_cat(i1,std::make_tuple(i2));
}
template <class IndexType>
inline auto operator~(const IPTR<IndexType>& i)
-> decltype(std::make_tuple(i))
{
return std::make_tuple(i);
}
// Explicitely specify subranges in template argument !!!
template <typename T, class... SRanges>
class ArrayBase
{
public:
typedef T value_type;
typedef ContainerRange<SRanges...> CRange;
typedef ConstContainerIndex<T,typename SRanges::IndexType...> CIndexType;
typedef ContainerIndex<T,typename SRanges::IndexType...> IndexType;
protected:
bool mInit = false;
std::shared_ptr<CRange> mRange;
std::shared_ptr<CIndexType> mProtoI;
public:
//DEFAULT_MEMBERS(ArrayBase);
ArrayBase(const std::shared_ptr<SRanges>&... ranges);
ArrayBase(const typename CRange::Space& space);
ArrayBase() = default;
ArrayBase(const ArrayBase& in);
ArrayBase(ArrayBase&& in);
ArrayBase& operator=(const ArrayBase& in);
ArrayBase& operator=(ArrayBase&& in);
virtual ~ArrayBase() = default;
template <typename X>
const T& operator[](const ConstContainerIndex<X,typename SRanges::IndexType...>& i);
const T& operator[](const std::tuple<IPTR<typename SRanges::IndexType>...>& is) const;
virtual const T& operator[](const CIndexType& i) const = 0;
virtual const T& at(const typename CRange::IndexType::MetaType& meta) const = 0;
virtual const T* data() const = 0;
virtual size_t size() const;
virtual bool isSlice() const = 0;
virtual CIndexType begin() const;
virtual CIndexType end() const;
virtual CIndexType cbegin() const;
virtual CIndexType cend() const;
virtual const std::shared_ptr<CRange>& range() const;
virtual bool isConst() const;
virtual std::shared_ptr<ArrayBase<T,AnonymousRange> > anonymous(bool slice = false) const = 0;
virtual ConstOperationRoot<T,SRanges...>
op(const std::shared_ptr<CIndexType>& ind) const;
virtual ConstOperationRoot<T,SRanges...>
operator()(const std::shared_ptr<typename SRanges::IndexType>&... inds) const;
template <class... MappedRanges>
ConstOperationRoot<T,MappedRanges...>
m(const std::shared_ptr<typename MappedRanges::IndexType>&... inds) const;
virtual bool isInit() const;
template <size_t N>
auto getRangePtr() const
-> decltype(mRange->template getPtr<N>());
};
template <typename T, class... SRanges>
class MutableArrayBase : public ArrayBase<T,SRanges...>
{
public:
typedef ContainerRange<SRanges...> CRange;
typedef ArrayBase<T,SRanges...> MAB;
typedef ContainerIndex<T,typename SRanges::IndexType...> IndexType;
typedef ConstContainerIndex<T,typename SRanges::IndexType...> CIndexType;
using ArrayBase<T,SRanges...>::operator[];
using ArrayBase<T,SRanges...>::at;
using ArrayBase<T,SRanges...>::data;
using ArrayBase<T,SRanges...>::begin;
using ArrayBase<T,SRanges...>::end;
using ArrayBase<T,SRanges...>::cbegin;
using ArrayBase<T,SRanges...>::cend;
DEFAULT_MEMBERS(MutableArrayBase);
MutableArrayBase(const std::shared_ptr<SRanges>&... ranges);
MutableArrayBase(const typename CRange::Space& space);
template <typename X>
T& operator[](const ConstContainerIndex<X,typename SRanges::IndexType...>& i);
T& operator[](const std::tuple<IPTR<typename SRanges::IndexType>...>& is);
virtual T& operator[](const CIndexType& i) = 0;
virtual T& at(const typename CRange::IndexType::MetaType& meta) = 0;
virtual T* data() = 0;
virtual IndexType begin();
virtual IndexType end();
virtual bool isConst() const override;
virtual ConstOperationRoot<T,SRanges...>
op(const std::shared_ptr<CIndexType>& ind) const override;
virtual ConstOperationRoot<T,SRanges...>
operator()(const std::shared_ptr<typename SRanges::IndexType>&... inds) const override;
virtual OperationRoot<T,SRanges...>
op(const std::shared_ptr<CIndexType>& ind);
virtual OperationRoot<T,SRanges...> operator()(const std::shared_ptr<typename SRanges::IndexType>&... inds);
template <class... MappedRanges>
OperationRoot<T,MappedRanges...>
m(const std::shared_ptr<typename MappedRanges::IndexType>&... inds);
template <class... MappedRanges>
ConstOperationRoot<T,MappedRanges...>
m(const std::shared_ptr<typename MappedRanges::IndexType>&... inds) const;
};
} // end namespace CNORXZ
/* ========================= *
* --- TEMPLATE CODE --- *
* ========================= */
#endif

15
src/include/cxz_assert.h Normal file
View file

@ -0,0 +1,15 @@
#include <iostream>
#include <sstream>
#define MA_ERRTAG __FILE__ << '@' << __LINE__ << '(' << __func__ << "): error"
#define MA_WARNTAG __FILE__ << '@' << __LINE__ << ": warning"
#define MA_ERROR(errmsg) {\
std::stringstream ss;\
ss << MA_ERRTAG << ": " << errmsg << std::flush;\
throw std::runtime_error(ss.str()); }
#define MA_WARNING(errmsg) {\
std::cerr << MA_WARNTAG << ": " << errmsg << std::endl; }
#define MA_ASSERT(statement, errmsg) if(not (statement)) { MA_ERROR(errmsg); }

File diff suppressed because it is too large Load diff

715
src/include/cxz_operation.h Normal file
View file

@ -0,0 +1,715 @@
// -*- C++ -*-
#ifndef __cxz_operation_h__
#define __cxz_operation_h__
#include <cstdlib>
#include <tuple>
#include <cmath>
#include <map>
#include <utility>
#include <type_traits>
#include "base_def.h"
#include "mbase_def.h"
#include "ranges/rheader.h"
#include "arith.h"
#include "xfor/xfor.h"
#include "type_operations.h"
#include "op_expressions.h"
#include "access.h"
#include "statics/static_for.h"
namespace CNORXZ
{
namespace
{
using namespace CNORXZInternal;
}
template <typename T, class OperationClass>
class OperationBase
{
public:
OperationClass& THIS() { return static_cast<OperationClass&>(*this); }
const OperationClass& THIS() const { return static_cast<OperationClass const&>(*this); }
template <typename U, class Second>
auto operator+(const OperationBase<U,Second>& in) const;
template <typename U, class Second>
auto operator-(const OperationBase<U,Second>& in) const;
template <typename U, class Second>
auto operator*(const OperationBase<U,Second>& in) const;
template <typename U, class Second>
auto operator/(const OperationBase<U,Second>& in) const;
template <class IndexType>
auto c(const std::shared_ptr<IndexType>& ind) const;
template <class... Indices>
auto sl(const std::shared_ptr<Indices>&... inds) const;
template <class... Indices>
auto p(const std::shared_ptr<Indices>&... inds) const;
template <class... Indices>
auto to(const std::shared_ptr<Indices>&... inds) const;
template <class... Indices>
auto addto(const std::shared_ptr<Indices>&... inds) const;
template <class... Indices>
auto pto(const std::shared_ptr<Indices>&... inds) const;
template <class... Indices>
auto paddto(const std::shared_ptr<Indices>&... inds) const;
template <typename R, class... Args> // Args = Operation Classes
auto a(const std::shared_ptr<function<R,T,typename Args::value_type...>>& ll, const Args&... args) const;
auto ptr() const;
private:
friend OperationClass;
friend OperationTemplate<T,OperationClass>;
OperationBase() = default;
};
template <typename T, class OperationClass>
class OperationTemplate : public OperationBase<T,OperationClass>
{
/* empty per default; specialize if needed */
private:
OperationTemplate() = default;
friend OperationClass;
};
template <typename T>
struct SelfIdentity
{
static inline T& sapply(T& a, T b)
{
return a = b;
}
};
template <class... Ops>
struct OperationTuple
{
OperationTuple(const Ops&... ops) : mOps(ops...) {}
std::tuple<Ops...> mOps;
auto rootSteps(std::intptr_t iPtrNum) const;
};
template <class... Ops>
auto OperationTuple<Ops...>::rootSteps(std::intptr_t iPtrNum) const
{
return sfor_p<0,sizeof...(Ops)>
( [&](auto i){ return std::get<i>(mOps).rootSteps(iPtrNum); },
[&](auto f, auto next) { return f.extend(next); } );
}
template <typename T, class... Ops>
class MOp
{
private:
MOp() = default;
OperationTuple<Ops...> mOps;
public:
static constexpr size_t LAYER = 0;
static constexpr size_t NHLAYER = 0;
static constexpr size_t SIZE = (... + Ops::SIZE);
typedef decltype(mOps.rootSteps(0)) ExtType;
MOp(const Ops&... exprs);
MOp(const MOp& in) = default;
MOp(MOp&& in) = default;
MOp& operator=(const MOp& in) = default;
MOp& operator=(MOp&& in) = default;
inline size_t get(ExtType last) const;
template <typename V>
inline size_t vget(ExtType last) const { return get(last); }
inline MOp& set(ExtType last);
auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType;
template <class Expr>
auto loop(Expr exp) const;
T* data() const { assert(0); return nullptr; }
};
template <class OpClass, class NextExpr>
class GetExpr : public ExpressionBase
{
private:
GetExpr() = default;
OpClass mSec;
NextExpr mNExpr;
public:
static constexpr size_t LAYER = 0;
static constexpr size_t NHLAYER = 0;
static constexpr size_t SIZE = OpClass::SIZE + NextExpr::SIZE;
typedef decltype(mSec.rootSteps(0).extend( mNExpr.rootSteps(0) ) ) ExtType;
GetExpr(const OpClass& sec, const NextExpr& nexpr);
GetExpr(const GetExpr& in) = default;
GetExpr(GetExpr&& in) = default;
GetExpr& operator=(const GetExpr& in) = default;
GetExpr& operator=(GetExpr&& in) = default;
virtual std::shared_ptr<ExpressionBase> deepCopy() const override final
{
return std::make_shared<GetExpr<OpClass,NextExpr>>(*this);
}
inline void operator()(size_t start = 0);
inline void get(ExtType last);
template <typename V>
inline void vget(ExtType last) { get(last); }
inline void operator()(size_t start, ExtType last);
auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType;
inline void operator()(size_t mlast, DExt last) override final;
inline DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final;
inline DExt dExtension() const override final;
};
template <class OpClass, class NextExpr>
auto mkGetExpr(const OpClass& op, const NextExpr& nexpr)
{
return GetExpr<OpClass,NextExpr>(op, nexpr);
}
template <typename T, class... Ops>
auto mkMOp(const Ops&... exprs)
{
return MOp<T,Ops...>(exprs...);
}
template <typename T, class... Ranges>
class ConstOperationRoot : public OperationTemplate<T,ConstOperationRoot<T,Ranges...> >
{
public:
typedef T value_type;
typedef OperationBase<T,ConstOperationRoot<T,Ranges...> > OT;
typedef ContainerRange<Ranges...> CRange;
typedef ConstContainerIndex<T,typename Ranges::IndexType...> IndexType;
static constexpr size_t SIZE = 1;
static constexpr bool CONT = true;
static constexpr bool VABLE = true;
ConstOperationRoot(const ArrayBase<T,Ranges...>& ma,
const std::shared_ptr<typename Ranges::IndexType>&... indices);
ConstOperationRoot(std::shared_ptr<ArrayBase<T,Ranges...> > maptr,
const std::shared_ptr<typename Ranges::IndexType>&... indices);
ConstOperationRoot(const T* data, const IndexType& ind);
template <class ET>
inline const T& get(ET pos) const;
template <typename V, class ET>
inline const V& vget(ET pos) const;
template <class ET>
inline ConstOperationRoot& set(ET pos);
MExt<None> rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
const T* data() const;
private:
const T* mDataPtr;
const T* mOrigDataPtr;
IndexType mIndex;
std::shared_ptr<ArrayBase<T,Ranges...> > mMaPtr; // never remove this ptr, otherwise we lose temporary container instances!
};
template <typename T, class Op>
class StaticCast : public OperationTemplate<T,StaticCast<T,Op> >
{
private:
Op mOp;
public:
typedef T value_type;
typedef OperationBase<T,StaticCast<T,Op> > OT;
typedef typename Op::CRange CRange;
typedef typename Op::IndexType IndexType;
static constexpr size_t SIZE = Op::SIZE;
static constexpr bool CONT = false;
static constexpr bool VABLE = false;
StaticCast(const Op& op);
template <class ET>
inline T get(ET pos) const;
template <typename V, class ET>
inline V vget(ET pos) const;
template <class ET>
inline StaticCast& set(ET pos);
auto rootSteps(std::intptr_t iPtrNum = 0) const
-> decltype(mOp.rootSteps(iPtrNum));
template <class Expr>
Expr loop(Expr exp) const;
};
template <typename T, class Op>
StaticCast<T,Op> staticcast(const Op& op)
{
return StaticCast<T,Op>(op);
}
template <class Range>
class MetaOperationRoot : public OperationTemplate<typename Range::MetaType,
MetaOperationRoot<Range> >
{
public:
typedef typename Range::IndexType IndexType;
typedef typename IndexType::MetaType value_type;
typedef OperationBase<value_type,MetaOperationRoot<Range> > OT;
static constexpr size_t SIZE = 1;
static constexpr bool CONT = false;
static constexpr bool VABLE = false;
MetaOperationRoot(const std::shared_ptr<IndexType>& ind);
template <class ET>
inline value_type get(ET pos) const;
template <typename V, class ET>
inline V vget(ET pos) const;
template <class ET>
inline MetaOperationRoot& set(ET pos);
MExt<None> rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
private:
mutable IndexType mWorkIndex;
std::shared_ptr<IndexType> mIndex;
};
template <typename T, class... Ranges>
class OperationRoot : public OperationTemplate<T,OperationRoot<T,Ranges...> >
{
public:
typedef T value_type;
typedef OperationBase<T,OperationRoot<T,Ranges...> > OT;
typedef ContainerRange<Ranges...> CRange;
typedef ConstContainerIndex<T,typename Ranges::IndexType...> IndexType;
static constexpr size_t SIZE = 1;
static constexpr bool CONT = true;
static constexpr bool VABLE = true;
private:
T* mDataPtr;
T* mOrigDataPtr;
PointerAccess<T> mDataAcc;
IndexType mIndex;
public:
OperationRoot(MutableArrayBase<T,Ranges...>& ma,
const std::shared_ptr<typename Ranges::IndexType>&... indices);
OperationRoot(MutableArrayBase<T,Ranges...>& ma,
const std::tuple<std::shared_ptr<typename Ranges::IndexType>...>& indices);
OperationRoot(T* data, const IndexType& ind);
template <class Func, class Access, class OpClass>
auto asx(const OpClass& in) const;
template <class Func, class Access, class OpClass>
auto asxExpr(const OpClass& in) const;
template <class Func, class Access, class OpClass, class Index>
auto asx(const OpClass& in, const std::shared_ptr<Index>& i) const;
template <class OpClass>
auto assign(const OpClass& in) const;
template <class OpClass>
auto assignExpr(const OpClass& in) const;
template <class OpClass, class Index>
auto assign(const OpClass& in, const std::shared_ptr<Index>& i) const;
template <class OpClass>
auto plus(const OpClass& in) const;
template <class OpClass, class Index>
auto plus(const OpClass& in, const std::shared_ptr<Index>& i) const;
template <class OpClass>
OperationRoot& operator=(const OpClass& in);
template <class OpClass>
OperationRoot& operator+=(const OpClass& in);
OperationRoot& operator=(const OperationRoot& in);
auto par() { return *this; }
template <class ET>
inline T& get(ET pos) const;
template <typename V, class ET>
inline V& vget(ET pos) const;
template <class ET>
inline OperationRoot& set(ET pos);
MExt<None> rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
T* data() const;
template <class... Indices>
auto sl(const std::shared_ptr<Indices>&... inds)
-> Slice<T,typename Indices::RangeType...>;
};
/*
template <typename T, class... Ranges>
class ParallelOperationRoot : public OperationTemplate<T,ParallelOperationRoot<T,Ranges...> >
{
public:
typedef T value_type;
typedef OperationBase<T,ParallelOperationRoot<T,Ranges...> > OT;
typedef ContainerRange<Ranges...> CRange;
typedef ConstContainerIndex<T,typename Ranges::IndexType...> IndexType;
static constexpr size_t SIZE = 1;
static constexpr bool CONT = true;
static constexpr bool VABLE = true;
private:
T* mDataPtr;
T* mOrigDataPtr;
PointerAccess<T> mDataAcc;
IndexType mIndex;
public:
ParallelOperationRoot(MutableArrayBase<T,Ranges...>& ma,
const std::shared_ptr<typename Ranges::IndexType>&... indices);
ParallelOperationRoot(T* data, const IndexType& ind);
template <class Func, class OpClass>
auto asx(const OpClass& in) const;
template <class Func, class OpClass>
auto asxExpr(const OpClass& in) const;
template <class Func, class OpClass, class Index>
auto asx(const OpClass& in, const std::shared_ptr<Index>& i) const;
template <class OpClass>
auto assign(const OpClass& in) const;
template <class OpClass>
auto assignExpr(const OpClass& in) const;
template <class OpClass, class Index>
auto assign(const OpClass& in, const std::shared_ptr<Index>& i) const;
template <class OpClass>
auto plus(const OpClass& in) const;
template <class OpClass, class Index>
auto plus(const OpClass& in, const std::shared_ptr<Index>& i) const;
template <class OpClass>
ParallelOperationRoot& operator=(const OpClass& in);
template <class OpClass>
ParallelOperationRoot& operator+=(const OpClass& in);
ParallelOperationRoot& operator=(const ParallelOperationRoot& in);
template <class ET>
inline T& get(ET pos) const;
template <typename V, class ET>
inline V& vget(ET pos) const;
template <class ET>
inline ParallelOperationRoot& set(ET pos);
MExt<None> rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
T* data() const;
};
*/
template <typename T>
class OperationValue : public OperationTemplate<T,OperationValue<T> >
{
public:
typedef T value_type;
typedef OperationBase<T,OperationValue<T> > OT;
typedef ContainerRange<NullRange> CRange;
typedef ConstContainerIndex<T,NullIndex> IndexType;
static constexpr size_t SIZE = 0;
static constexpr bool CONT = true;
static constexpr bool VABLE = false;
OperationValue(const T& val);
template <class ET>
inline const T& get(ET pos) const;
template <typename V, class ET>
inline V vget(ET pos) const;
template <class ET>
inline OperationValue& set(ET pos);
None rootSteps(std::intptr_t iPtrNum = 0) const; // nullptr for simple usage with decltype
template <class Expr>
Expr loop(Expr exp) const;
private:
T mVal;
};
template <typename T, class Op>
class OperationPointer : public OperationTemplate<const T*,OperationPointer<T,Op>>
{
public:
typedef T value_type;
typedef OperationTemplate<const T*,OperationPointer<T,Op>> OT;
static constexpr size_t SIZE = Op::SIZE;
static constexpr bool CONT = false;
private:
Op mOp;
public:
OperationPointer(const Op& op) : mOp(op)
{
static_assert(Op::CONT,
"OperationPointer can only be applied to containing operations");
}
template <class ET>
inline const T* get(ET pos) const;
template <class ET>
inline OperationPointer& set(ET pos);
auto rootSteps(std::intptr_t iPtrNum = 0) const // nullptr for simple usage with decltype
-> decltype(mOp.rootSteps(0));
template <class Expr>
auto loop(Expr exp) const
-> decltype(mOp.loop(exp));
T const** data() const { assert(0); return nullptr; }
};
template <typename T, class OpFunction, class... Ops>
class Operation : public OperationTemplate<T,Operation<T,OpFunction,Ops...> >
{
public:
typedef T value_type;
typedef OperationBase<T,Operation<T,OpFunction,Ops...> > OT;
typedef OpFunction F;
static constexpr size_t SIZE = (... + Ops::SIZE);
static constexpr bool FISSTATIC = OpFunction::FISSTATIC;
static constexpr bool CONT = false;
static constexpr bool VABLE =
(... and (Ops::VABLE and std::is_same<T,typename Ops::value_type>::value));
private:
OperationTuple<Ops...> mOps;
std::shared_ptr<OpFunction> mF; // only if non-static
typedef decltype(mOps.rootSteps(0)) ExtType;
public:
Operation(const Ops&... ops);
Operation(std::shared_ptr<OpFunction> ff, const Ops&... ops);
template <class ET>
inline auto get(ET pos) const;
template <typename V, class ET>
inline auto vget(ET pos) const;
template <class ET>
inline Operation& set(ET pos);
auto rootSteps(std::intptr_t iPtrNum = 0) const
-> ExtType; // nullptr for simple usage with decltype
template <class Expr>
auto loop(Expr exp) const;
T* data() const { assert(0); return nullptr; }
};
template <class OpFunction, class... Ops>
auto mkOperation(const std::shared_ptr<OpFunction>& f, const Ops&... ops)
-> Operation<typename OpFunction::value_type,OpFunction,Ops...>
{
if constexpr(OpFunction::FISSTATIC){
return Operation<typename OpFunction::value_type,OpFunction,Ops...>(ops...);
}
else {
return Operation<typename OpFunction::value_type,OpFunction,Ops...>(f,ops...);
}
}
template <typename T, class Op, class IndexType>
class Contraction : public OperationTemplate<T,Contraction<T,Op,IndexType> >
{
public:
typedef T value_type;
typedef OperationBase<T,Contraction<T,Op,IndexType> > OT;
static constexpr size_t SIZE = Op::SIZE;
static constexpr bool CONT = Op::CONT;
static constexpr bool VABLE = Op::VABLE;
private:
Op mOp;
std::shared_ptr<IndexType> mInd;
public:
typedef decltype(mOp.rootSteps(0)) ETuple;
Contraction(const Op& op, std::shared_ptr<IndexType> ind);
template <class ET>
inline auto get(ET pos) const
-> decltype(mOp.template get<ET>(pos));
template <typename V, class ET>
inline auto vget(ET pos) const
-> decltype(mOp.template vget<V,ET>(pos));
template <class ET>
inline Contraction& set(ET pos);
T* data() const { assert(0); return nullptr; }
auto rootSteps(std::intptr_t iPtrNum = 0) const // nullptr for simple usage with decltype
-> decltype(mOp.rootSteps(iPtrNum));
template <class Expr>
auto loop(Expr exp) const
-> decltype(mInd->iforh(1,mOp.loop(exp)));
};
// for SliceArray
/*
template <typename T, class Op>
class HyperOperation : public OperationTemplate<T,HyperOperation<T,Op> >
{
public:
typedef Op value_type;
typedef OperationTemplate<T,HyperOperation<T,Op> > OT;
static constexpr size_t SIZE = Op::SIZE;
static constexpr bool CONT = false;
static constexpr bool VABLE = false;
private:
Op mOp; // proto
public:
//typedef decltype(mOp.rootSteps(0)) ETuple;
template <class ET>
// include ALL indices (external/internal!!!)
inline auto get(ET pos) const
-> decltype(mOp.template get<ET>(pos));
template <typename V, class ET>
inline auto vget(ET pos) const
-> decltype(mOp.template vget<V,ET>(pos));
template <class ET>
inline HyperOperation& set(ET pos);
T* data() const { assert(0); return nullptr; }
auto rootSteps(std::intptr_t iPtrNum = 0) const // nullptr for simple usage with decltype
-> decltype(mOp.rootSteps(iPtrNum));
template <class Expr>
auto loop(Expr exp) const
-> decltype(mInd->iforh(1,mOp.loop(exp)));
};
*/
}
#include "type_operations.h"
#endif

View file

@ -0,0 +1,198 @@
#include "dynamic_operation.h"
#include "helper_tools.h"
namespace CNORXZ
{
template <typename T, class Operation>
T DynamicOperation<T,Operation>::get(const DExtT& pos) const
{
return mOp.get(pos.expl<ET>());
}
template <typename T, class Operation>
DynamicOperationBase<T>& DynamicOperation<T,Operation>::set(const DExtT& pos)
{
mOp.set(pos.expl<ET>());
return *this;
}
template <typename T, class Operation>
DExtT DynamicOperation<T,Operation>::rootSteps(std::intptr_t iPtrNum) const
{
return DExtT(mkDExt(mkExtT(mOp.rootSteps(iPtrNum))),None(0));
}
template <typename T, class Operation>
DynamicExpression DynamicOperation<T,Operation>::loop(const DynamicExpression& exp) const
{
return mOp.loop(exp);
}
template <typename T, class Operation>
const T* DynamicOperation<T,Operation>::data() const
{
return mOp.data();
}
template <typename T, class Operation>
std::shared_ptr<DynamicOperationBase<T>> DynamicOperation<T,Operation>::deepCopy() const
{
return std::make_shared<DynamicOperation<T,Operation>>(*this);
}
template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>::DynamicOuterOp(const DynamicOuterOp& in) :
mThreadId(omp_get_thread_num()), mOp(in.mOp),
mIndices(in.mIndices),
mMa((mThreadId != in.mThreadId) ? std::make_shared<Array<T,Ranges...>>(*in.mMa) : in.mMa),
mProto((mThreadId != in.mThreadId) ? OperationRoot<T,Ranges...>(*mMa,mIndices) : in.mProto),
mL((mThreadId != in.mThreadId) ?
mkILoop(std::make_tuple(*mProto.mOp,mOp), mIndices,
std::make_tuple(mMa),
std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(mIndices) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0})) :
in.mL)
{*mMa = 0;}
template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>::DynamicOuterOp(DynamicOuterOp&& in) :
mThreadId(omp_get_thread_num()), mOp(in.mOp),
mIndices(in.mIndices),
mMa((mThreadId != in.mThreadId) ? std::make_shared<Array<T,Ranges...>>(*in.mMa) : in.mMa),
mProto((mThreadId != in.mThreadId) ? OperationRoot<T,Ranges...>(*mMa,mIndices) : in.mProto),
mL((mThreadId != in.mThreadId) ?
mkILoop(std::make_tuple(*mProto.mOp,mOp), mIndices,
std::make_tuple(mMa),
std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(mIndices) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0})) :
in.mL)
{*mMa = 0;}
template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>&
DynamicOuterOp<T,Operation,Ranges...>::operator=(const DynamicOuterOp& in)
{
mThreadId = omp_get_thread_num();
mOp = in.mOp;
mIndices = in.mIndices;
if(mThreadId != in.mThreadId){
mMa = std::make_shared<Array<T,Ranges...>>(in.mMa);
mProto = OperationRoot<T,Ranges...>(*mMa,mIndices);
mL = mkILoop(std::make_tuple(*mProto.mOp,mOp), mIndices,
std::make_tuple(mMa),
std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(mIndices) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0}));
}
else {
mMa = in.mMa;
mProto = in.mProto;
mL = in.mL;
}
*mMa = 0;
return *this;
}
template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>&
DynamicOuterOp<T,Operation,Ranges...>::operator=(DynamicOuterOp&& in)
{
mThreadId = omp_get_thread_num();
mOp = in.mOp;
mIndices = in.mIndices;
if(mThreadId != in.mThreadId){
mMa = std::make_shared<Array<T,Ranges...>>(in.mMa);
mProto = OperationRoot<T,Ranges...>(*mMa,mIndices);
mL = mkILoop(std::make_tuple(*mProto.mOp,mOp), mIndices,
std::make_tuple(mMa),
std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(mIndices) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0}));
}
else {
mMa = in.mMa;
mProto = in.mProto;
mL = in.mL;
}
*mMa = 0;
return *this;
}
template <typename T, class Operation, class... Ranges>
DynamicOuterOp<T,Operation,Ranges...>::DynamicOuterOp(const Operation& op,
const std::shared_ptr<typename Ranges::IndexType>&... inds)
: mThreadId(omp_get_thread_num()), mOp(op),
mIndices(inds...),
mMa(std::make_shared<Array<T,Ranges...>>(mkArray<T>(inds->range()...))),
mProto(OperationRoot<T,Ranges...>(*mMa,inds...)),
mL(std::make_tuple(*mProto.mOp,mOp), std::make_tuple(inds...),
std::make_tuple(mMa), std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(inds...) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0}))
{}
/*
DynamicOuterOp(const std::shared_ptr<DynamicOperationBase<OpH<OperationRoot<typename Operatrion::value_type,Ranges...>>>>& dyn,
const Operation& op, const std::shared_ptr<Indices>&... inds )
: mThreadId(omp_get_thread_num()),
//mDyn(dyn),
mOp(op), mIndices(inds...),
mMa(std::make_shared<Array<T,Ranges...>>(mkArray<T>(inds->range()...))),
mProto(OperationRoot<T,Ranges...>(*mMa,inds...)),
mL(std::make_tuple(*mProto.mOp,mOp), std::make_tuple(inds...),
std::make_tuple(mMa), std::make_tuple(mProto.mOp->assign( mOp, mkMIndex(inds...) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0}))
{}
*/
template <typename T, class Operation, class... Ranges>
OpH<OperationRoot<T,Ranges...>> DynamicOuterOp<T,Operation,Ranges...>::get(const DExtT& pos) const
{
//if(mPrev) mPrev.get(pos.expl<ET>());
mL(0,pos.expl<ET>());
return mProto; // empty
}
template <typename T, class Operation, class... Ranges>
DynamicOperationBase<OpH<OperationRoot<T,Ranges...>>>&
DynamicOuterOp<T,Operation,Ranges...>::set(const DExtT& pos)
{
mOp.set(pos.expl<ET>());
return *this;
}
template <typename T, class Operation, class... Ranges>
DExtT DynamicOuterOp<T,Operation,Ranges...>::rootSteps(std::intptr_t iPtrNum) const
{
return DExtT(mkDExt(mkExtT(mL.rootSteps(iPtrNum))),None(0));
}
template <typename T, class Operation, class... Ranges>
DynamicExpression DynamicOuterOp<T,Operation,Ranges...>::loop(const DynamicExpression& exp) const
{
return mOp.loop(exp); // ???!!
}
template <typename T, class Operation, class... Ranges>
const OpH<OperationRoot<T,Ranges...>>* DynamicOuterOp<T,Operation,Ranges...>::data() const
{
return &mProto;
}
/*
template <class Op1, class Op2>
template <class ET>
inline T TwoOp<Op1,Op2>::get(const ET& pos) const
{
return mOp2.get(pos);
}
*/
template <typename T, class Operation, class... Ranges>
std::shared_ptr<DynamicOperationBase<OpH<OperationRoot<T,Ranges...>>>>
DynamicOuterOp<T,Operation,Ranges...>::deepCopy() const
{
return std::make_shared<DynamicOuterOp<T,Operation,Ranges...>>(*this);
}
} // namespace CNORXZ

View file

@ -0,0 +1,209 @@
#ifndef __cxz_dynamic_operation_h__
#define __cxz_dynamic_operation_h__
#include "base_def.h"
#include "cxz_operation.h"
namespace CNORXZ
{
template <typename T>
class DynamicOperationBase : public OperationTemplate<T,DynamicOperationBase<T>>
{
public:
typedef T value_type;
typedef OperationBase<T,DynamicOperationBase<T>> OT;
static constexpr size_t SIZE = 1;
static constexpr bool CONT = true;
static constexpr bool VABLE = false;
DynamicOperationBase() = default;
DynamicOperationBase(const DynamicOperationBase& in) = default;
DynamicOperationBase(DynamicOperationBase&& in) = default;
DynamicOperationBase& operator=(const DynamicOperationBase& in) = default;
DynamicOperationBase& operator=(DynamicOperationBase&& in) = default;
virtual T get(const DExtT& pos) const = 0;
virtual DynamicOperationBase& set(const DExtT& pos) = 0;
virtual DExtT rootSteps(std::intptr_t iPtrNum = 0) const = 0;
virtual DynamicExpression loop(const DynamicExpression& exp) const = 0;
virtual const T* data() const = 0;
virtual std::shared_ptr<DynamicOperationBase<T>> deepCopy() const = 0;
};
template <typename T, class Operation>
class DynamicOperation : public DynamicOperationBase<T>
{
private:
Operation mOp;
public:
typedef decltype(mOp.rootSteps()) ET;
//typedef decltype(std::declval<Operation>().rootSteps()) ET;
DynamicOperation() = default;
DynamicOperation(const DynamicOperation& in) = default;
DynamicOperation(DynamicOperation&& in) = default;
DynamicOperation& operator=(const DynamicOperation& in) = default;
DynamicOperation& operator=(DynamicOperation&& in) = default;
DynamicOperation(const Operation& op) : mOp(op) {}
virtual T get(const DExtT& pos) const override final;
virtual DynamicOperationBase<T>& set(const DExtT& pos) override final;
virtual DExtT rootSteps(std::intptr_t iPtrNum = 0) const override final;
virtual DynamicExpression loop(const DynamicExpression& exp) const override final;
virtual const T* data() const override final;
virtual std::shared_ptr<DynamicOperationBase<T>> deepCopy() const override final;
};
template <class Op>
struct OpH
{
std::shared_ptr<Op> mOp;
OpH(const Op& op) : mOp(std::make_shared<Op>(op)) {}
// overload all operations here ...
};
template <typename T, class Operation, class... Ranges>
class DynamicOuterOp : public DynamicOperationBase<OpH<OperationRoot<T,Ranges...>>>
{
private:
size_t mThreadId;
//std::shared_ptr<DynamicOperationBase<OpH<OperationRoot<T,Ranges...>>>> mDyn;
Operation mOp;
//OperationRoot<T,Ranges...> mProto;
std::tuple<std::shared_ptr<typename Ranges::IndexType>...> mIndices;
std::shared_ptr<Array<T,Ranges...>> mMa;
OpH<OperationRoot<T,Ranges...>> mProto;
typedef ILoop<std::tuple<OperationRoot<T,Ranges...>,Operation>,
std::tuple<std::shared_ptr<typename Ranges::IndexType>...>,
std::tuple<std::shared_ptr<Array<T,Ranges...>>>,
std::tuple<decltype(mProto.mOp->assign( mOp, mkMIndex(std::shared_ptr<typename Ranges::IndexType>()...) ))>> LoopT;
mutable LoopT mL;
public:
typedef decltype(mL.rootSteps()) ET;
//typedef decltype(std::declval<Operation>().rootSteps()) ET;
DynamicOuterOp() : mThreadId(omp_get_thread_num()) {}
DynamicOuterOp(const DynamicOuterOp& in);
DynamicOuterOp(DynamicOuterOp&& in);
DynamicOuterOp& operator=(const DynamicOuterOp& in);
DynamicOuterOp& operator=(DynamicOuterOp&& in);
DynamicOuterOp(const Operation& op, const std::shared_ptr<typename Ranges::IndexType>&... inds);
/*
DynamicOuterOp(const std::shared_ptr<DynamicOperationBase<OpH<OperationRoot<typename Operatrion::value_type,Ranges...>>>>& dyn,
const Operation& op, const std::shared_ptr<Indices>&... inds );
*/
virtual OpH<OperationRoot<T,Ranges...>> get(const DExtT& pos) const override final;
virtual DynamicOperationBase<OpH<OperationRoot<T,Ranges...>>>& set(const DExtT& pos) override final;
virtual DExtT rootSteps(std::intptr_t iPtrNum = 0) const override final;
virtual DynamicExpression loop(const DynamicExpression& exp) const override final;
virtual const OpH<OperationRoot<T,Ranges...>>* data() const override final;
virtual std::shared_ptr<DynamicOperationBase<OpH<OperationRoot<T,Ranges...>>>> deepCopy() const override final;
};
template <typename T>
class DynamicO : public OperationTemplate<T,DynamicO<T>>
{
private:
// NOT THREAD SAFE!!!
std::shared_ptr<DynamicOperationBase<T>> mOp;
public:
typedef T value_type;
typedef OperationBase<T,DynamicO<T>> OT;
static constexpr size_t SIZE = 1;
static constexpr bool CONT = true;
static constexpr bool VABLE = false;
DynamicO() = default;
DynamicO(const DynamicO& in) : mOp(in.mOp ? in.mOp->deepCopy() : nullptr) {}
DynamicO(DynamicO&& in) : mOp(in.mOp ? in.mOp->deepCopy() : nullptr) {}
DynamicO& operator=(const DynamicO& in)
{ mOp = in.mOp ? in.mOp->deepCopy() : nullptr; return *this; }
DynamicO& operator=(DynamicO&& in)
{ mOp = in.mOp ? in.mOp->deepCopy() : nullptr; return *this; }
bool init() const { return mOp != nullptr; }
template <class Op>
DynamicO(const Op& op) : mOp(std::make_shared<DynamicOperation<T,Op>>(op)) {}
DynamicO(const std::shared_ptr<DynamicOperationBase<T>>& op) :
mOp(op) {}
template <class X>
inline T get(const DExtTX<X>& pos) const { return mOp->get(pos.reduce()); }
template <typename V,class X>
inline auto vget(const DExtTX<X>& pos) const
{ return mOp->template vget<V>(pos.reduce()); }
template <class X>
inline DynamicO& set(const DExtTX<X>& pos) { mOp->set(pos.reduce()); return *this; }
inline DExtT rootSteps(std::intptr_t iPtrNum = 0) const { return mOp->rootSteps(iPtrNum); }
inline DynamicExpression loop(const DynamicExpression& exp) const { return mOp->loop(exp); }
inline const T* data() const { return mOp->data(); }
};
/*
template <class Op1>
class TwoOp : public OperationTemplate<typename Op2::value_type,TwoOp<Op1>>
{
private:
Op1 mOp1;
typename Op1::value_type mOp2; // mOp1.data()->mOp
public:
typedef typename Op2::value_type value_type;
typedef value_type T;
TwoOp(const Op1& op1);
template <class ET>
inline T get(const ET& pos) const;
};
*/
template <class Operation, class... Indices>
auto mkDynOutOp(const Operation& op, const std::shared_ptr<Indices>&... inds)
{
return DynamicO<OpH<OperationRoot<typename Operation::value_type,
typename Indices::RangeType...>>>
(DynamicOuterOp<typename Operation::value_type,Operation,
typename Indices::RangeType...>(op, inds...));
}
/*
template <class Operation, class... Indices>
auto mkDynOutOp(const std::shared_ptr<DynamicOperationBase<OpH<OperationRoot<typename Operatrion::value_type,Ranges...>>>>& dyn,
const Operation& op, const std::shared_ptr<Indices>&... inds)
{
return DynamicO<OpH<OperationRoot<typename Operation::value_type,
typename Indices::RangeType...>>>
(DynamicOuterOp<typename Operation::value_type,Operation,
typename Indices::RangeType...>(dyn, op, inds...));
}
*/
// Build plan
/*
template <class Operation>
class OperationBuilder
{
};
*/
} // namespace CNORXZ
#endif

View file

@ -0,0 +1,6 @@
#ifdef regFunc1
regFunc1(exp)
#endif

View file

@ -0,0 +1,99 @@
#include "functional_array.h"
namespace CNORXZ
{
/****************************
* FunctionalArray *
****************************/
template <typename T, class Function, class... SRanges>
FunctionalArray<T,Function,SRanges...>::FunctionalArray(const std::shared_ptr<SRanges>&... ranges,
const std::shared_ptr<Function>& func) :
ArrayBase<T,SRanges...>(ranges...), mFunc(func) {}
template <typename T, class Function, class... SRanges>
FunctionalArray<T,Function,SRanges...>::FunctionalArray(const std::shared_ptr<SRanges>&... ranges) :
ArrayBase<T,SRanges...>(ranges...) {}
template <typename T, class Function, class... SRanges>
FunctionalArray<T,Function,SRanges...>::FunctionalArray(const typename CRange::Space& space) :
ArrayBase<T,SRanges...>(space) {}
template <typename T, class Function, class... SRanges>
FunctionalArray<T,Function,SRanges...>::FunctionalArray(const typename CRange::Space& space,
const std::shared_ptr<Function>& func) :
ArrayBase<T,SRanges...>(space), mFunc(func) {}
template <typename T, class Function, class... SRanges>
const T& FunctionalArray<T,Function,SRanges...>::operator[](const IndexType& i) const
{
if constexpr(Function::FISSTATIC){
mVal = Function::apply(i.meta());
}
else {
mVal = (*mFunc)(i.meta());
}
return mVal;
}
template <typename T, class Function, class... SRanges>
const T& FunctionalArray<T,Function,SRanges...>::at(const typename CRange::IndexType::MetaType& meta) const
{
if constexpr(Function::FISSTATIC){
mVal = Function::apply(meta);
}
else {
mVal = (*mFunc)(meta);
}
return mVal;
}
template <typename T, class Function, class... SRanges>
const T* FunctionalArray<T,Function,SRanges...>::data() const
{
return &mVal;
}
template <typename T, class Function, class... SRanges>
bool FunctionalArray<T,Function,SRanges...>::isConst() const
{
return true;
}
template <typename T, class Function, class... SRanges>
bool FunctionalArray<T,Function,SRanges...>::isSlice() const
{
return false;
}
template <typename T, class Function, class... SRanges>
std::shared_ptr<ArrayBase<T,AnonymousRange> > FunctionalArray<T,Function,SRanges...>::anonymous(bool slice) const
{
assert(0); // think about it carefully
return nullptr;
}
template <typename T, class Function, class... SRanges>
ConstOperationRoot<T,SRanges...> FunctionalArray<T,Function,SRanges...>::
operator()(const std::shared_ptr<typename SRanges::IndexType>&... inds) const
{
if(not mMaPtr){
mMaPtr = std::make_shared<MAType>( MAB::mRange->space() );
(*mMaPtr)(inds...) = exec(inds...);
}
return ConstOperationRoot<T,SRanges...>( *mMaPtr, inds... );
}
template <typename T, class Function, class... SRanges>
auto FunctionalArray<T,Function,SRanges...>::
exec(const std::shared_ptr<typename SRanges::IndexType>&... inds) const
-> Operation<T,Function,MetaOperationRoot<SRanges>...>
{
return mkOperation( mFunc, MetaOperationRoot<SRanges>( inds ) ... );
}
} // namespace CNORXZ

View file

@ -0,0 +1,61 @@
#ifndef __cxz_functional_array__
#define __cxz_functional_array__
#include "cxz_array_base.h"
#include "slice.h"
namespace CNORXZ
{
template <typename T, class Function, class... SRanges>
class FunctionalArray : public ArrayBase<T,SRanges...>
{
public:
typedef ContainerRange<SRanges...> CRange;
typedef ArrayBase<T,SRanges...> MAB;
typedef ConstContainerIndex<T,typename SRanges::IndexType...> IndexType;
typedef Array<T,SRanges...> MAType;
typedef T value_type;
private:
mutable T mVal;
std::shared_ptr<Function> mFunc;
mutable std::shared_ptr<MAType> mMaPtr;
public:
DEFAULT_MEMBERS(FunctionalArray);
FunctionalArray(const std::shared_ptr<SRanges>&... ranges, const std::shared_ptr<Function>& func);
FunctionalArray(const std::shared_ptr<SRanges>&... ranges);
FunctionalArray(const typename CRange::Space& space);
FunctionalArray(const typename CRange::Space& space, const std::shared_ptr<Function>& func);
virtual const T& operator[](const IndexType& i) const override;
virtual const T& at(const typename CRange::IndexType::MetaType& meta) const override;
virtual const T* data() const override;
virtual bool isConst() const override;
virtual bool isSlice() const override;
virtual std::shared_ptr<ArrayBase<T,AnonymousRange> > anonymous(bool slice = false) const override;
auto exec(const std::shared_ptr<typename SRanges::IndexType>&... inds) const
-> Operation<T,Function,MetaOperationRoot<SRanges>...>;
virtual ConstOperationRoot<T,SRanges...>
operator()(const std::shared_ptr<typename SRanges::IndexType>&... inds) const override;
};
} // namespace CNORXZ
/* ========================= *
* --- TEMPLATE CODE --- *
* ========================= */
#endif

View file

@ -0,0 +1,398 @@
#include "helper_tools.h"
namespace CNORXZ
{
template <typename... T>
std::ostream& operator<<(std::ostream& out, const std::tuple<T...>& tp)
{
sfor_pn<0,sizeof...(T)-1>( [&](auto i){ out << std::get<i>(tp) << ", "; return 0; } );
out << std::get<sizeof...(T)-1>(tp);
return out;
}
template <class RangeType>
auto getIndex(std::shared_ptr<RangeType> range)
-> std::shared_ptr<typename RangeType::IndexType>
{
return std::make_shared<typename RangeType::IndexType>(range);
}
template <class RangeType>
auto getIndex()
-> std::shared_ptr<typename RangeType::IndexType>
{
static_assert( RangeType::defaultable, "Range not defaultable" );
static auto f = RangeType::factory();
static auto r = std::dynamic_pointer_cast<RangeType>( f.create() );
return std::make_shared<typename RangeType::IndexType>(r);
}
template <class... RangeTypes>
auto mkMulti(std::shared_ptr<RangeTypes>... ranges)
-> std::shared_ptr<MultiRange<RangeTypes...> >
{
MultiRangeFactory<RangeTypes...> mrf( ranges... );
return std::dynamic_pointer_cast<MultiRange<RangeTypes...> >( mrf.create() );
}
namespace
{
template <size_t N>
struct IndexToRangeTuple
{
template <class... IndexTypes>
static inline void set(std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...>& out,
const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
{
std::get<N>(out) = std::get<N>(indices)->range();
IndexToRangeTuple<N-1>::set(out,indices);
}
};
template <>
struct IndexToRangeTuple<0>
{
template <class... IndexTypes>
static inline void set(std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...>& out,
const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
{
std::get<0>(out) = std::get<0>(indices)->range();
}
};
}
template <class... IndexTypes>
auto indexToRangeTuple(const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
-> std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...>
{
std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...> out;
IndexToRangeTuple<sizeof...(IndexTypes)-1>::set(out, indices);
return out;
}
template <class... IndexTypes>
auto mkMIndex(std::shared_ptr<IndexTypes>... indices)
-> decltype( getIndex( mkMulti( indices->range()... ) ) )
{
auto mi = getIndex( mkMulti( indices->range()... ) );
(*mi)( indices... );
return mi;
}
template <class... IndexTypes>
auto mkMIndex(const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
-> decltype( getIndex( mkMulti( indexToRangeTuple(indices) ) ) )
{
auto mi = getIndex( mkMulti( indexToRangeTuple(indices) ) );
(*mi)( indices );
return mi;
}
template <class Index>
auto mkIndexW(const std::shared_ptr<Index>& ind)
-> std::shared_ptr<IndexW>
{
return std::make_shared<IndexWrapper<Index>>(ind);
}
template <SpaceType STYPE, class Op, class MA, class... RangeTypes>
auto mkGenMapR(const std::tuple<Op,MA>& f, std::shared_ptr<RangeTypes>... ranges)
-> std::shared_ptr<GenMapRange<MapORType<Op,STYPE>,Op,STYPE,RangeTypes...> >
{
GenMapRangeFactory<MapORType<Op,STYPE>,Op,STYPE,RangeTypes...> mrf(f, ranges... );
return createExplicit( mrf );
}
template <SpaceType STYPE, class ORType, class Op, class MA, class... RangeTypes>
auto mkGenMapRwith(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& f,
std::shared_ptr<RangeTypes>... ranges)
-> std::shared_ptr<GenMapRange<ORType,Op,STYPE,RangeTypes...> >
{
GenMapRangeFactory<ORType,Op,STYPE,RangeTypes...> mrf(outr, f, ranges... );
return createExplicit( mrf );
}
template <SpaceType STYPE, class Op, class MA, class... IndexTypes>
auto mkGenMapI(const std::tuple<Op,MA>& f, std::shared_ptr<IndexTypes>... indices)
-> decltype( getIndex( mkGenMapR<STYPE>( f, indices->range()... ) ) )
{
auto mi = getIndex( mkGenMapR<STYPE>( f, indices->range()... ) );
(*mi)(indices...);
return mi;
}
template <class Op, class MA, class... RangeTypes>
auto mkMapR(const std::tuple<Op,MA>& f, std::shared_ptr<RangeTypes>... ranges)
-> decltype( mkGenMapR<SpaceType::ANY>(f, ranges... ) )
{
return mkGenMapR<SpaceType::ANY>(f, ranges... );
}
template <class ORType, class Op, class MA, class... RangeTypes>
auto mkMapRwith(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& f,
std::shared_ptr<RangeTypes>... ranges)
-> decltype( mkGenMapRwith<SpaceType::ANY>(outr, f, ranges... ) )
{
return mkGenMapRwith<SpaceType::ANY>(outr, f, ranges... );
}
template <class Func, class... Indices>
auto mkMapR(const std::shared_ptr<Func>& func, const std::shared_ptr<Indices>&... is)
-> decltype( mkMapR( mkMapOp( func, is... ), is->range()... ) )
{
return mkMapR( mkMapOp( func, is... ), is->range()... );
}
template <class ORType, class Func, class... Indices>
auto mkMapRwith(const std::shared_ptr<ORType>& outr, const std::shared_ptr<Func>& func, const std::shared_ptr<Indices>&... is)
-> decltype( mkMapRwith(outr, mkMapOp( func, is... ), is->range()... ) )
{
return mkMapRwith(outr, mkMapOp( func, is... ), is->range()... );
}
template <class Op, class MA, class... IndexTypes>
auto mkMapI(const std::tuple<Op,MA>& f, std::shared_ptr<IndexTypes>... indices)
-> decltype( mkGenMapI<SpaceType::ANY>(f, indices... ) )
{
return mkGenMapI<SpaceType::ANY>(f, indices... );
}
template <class... RangeTypes>
auto mkMulti(std::tuple<std::shared_ptr<RangeTypes>...> rangesTuple)
-> std::shared_ptr<MultiRange<RangeTypes...>>
{
MultiRangeFactory<RangeTypes...> mrf( rangesTuple );
return std::dynamic_pointer_cast<MultiRange<RangeTypes...> >( mrf.create() );
}
template <class RangeFactory>
auto createExplicit(RangeFactory& rf)
-> std::shared_ptr<typename RangeFactory::oType>
{
return std::dynamic_pointer_cast<typename RangeFactory::oType>( rf.create() );
}
template <class RangeFactory>
auto createExplicit(std::shared_ptr<RangeFactory> rfp)
-> std::shared_ptr<typename RangeFactory::oType>
{
return std::dynamic_pointer_cast<typename RangeFactory::oType>( rfp->create() );
}
template <class Range>
auto createRange(const vector<char>& cvec)
-> std::shared_ptr<Range>
{
const char* dp = cvec.data();
auto ff = createRangeFactory(&dp);
auto rbptr = ff->create();
assert(rbptr->spaceType() == Range::STYPE);
// CATCH CAST ERROR HERE !!!
return std::dynamic_pointer_cast<Range>( rbptr );
}
inline auto createRange(const vector<char>* cvec, int metaType, size_t size)
-> std::shared_ptr<RangeBase>
{
auto f = createSingleRangeFactory(cvec, metaType, size);
return f->create();
}
inline auto createRangeA(const vector<char>* cvec, int metaType, size_t size)
-> std::shared_ptr<AnonymousRange>
{
AnonymousRangeFactory arf(createRange(cvec, metaType, size));
return createExplicit(arf);
}
inline auto cvecMetaCast(const std::shared_ptr<SingleRange<vector<char>,SpaceType::ANY>>& r, int metaType)
-> std::shared_ptr<RangeBase>
{
return createRange(&r->get(0), metaType, r->size());
}
inline auto cvecMetaCastA(const std::shared_ptr<SingleRange<vector<char>,SpaceType::ANY>>& r, int metaType)
-> std::shared_ptr<AnonymousRange>
{
return createRangeA(&r->get(0), metaType, r->size());
}
template <class Range, typename... Args>
auto createRangeE(Args&&... args)
-> std::shared_ptr<Range>
{
typename Range::FType f(args...);
return createExplicit(f);
}
template <size_t N, class MArray>
auto rptr(const MArray& ma)
-> decltype(ma.template getRangePtr<N>())
{
return ma.template getRangePtr<N>();
}
template <class MArray>
auto dynamic(const MArray& ma, bool slice)
-> std::shared_ptr<ArrayBase<typename MArray::value_type,DynamicRange>>
{
DynamicRangeFactory drf(ma.range()->space());
if(slice){
return std::make_shared<ConstSlice<typename MArray::value_type,DynamicRange>>
( std::dynamic_pointer_cast<DynamicRange>( drf.create() ),
ma.data() );
}
else {
return std::make_shared<Array<typename MArray::value_type,DynamicRange>>
( std::dynamic_pointer_cast<DynamicRange>( drf.create() ),
ma.vdata() );
}
}
template <class MArray>
auto mdynamic(MArray& ma, bool slice)
-> std::shared_ptr<MutableArrayBase<typename MArray::value_type,DynamicRange>>
{
DynamicRangeFactory drf(ma.range()->space());
if(slice){
return std::make_shared<Slice<typename MArray::value_type,DynamicRange>>
( std::dynamic_pointer_cast<DynamicRange>( drf.create() ),
ma.data() );
}
else {
return std::make_shared<Array<typename MArray::value_type,DynamicRange>>
( std::dynamic_pointer_cast<DynamicRange>( drf.create() ),
ma.vdata() );
}
}
namespace
{
template <size_t N>
struct CopyRanges
{
template <class Space1, class Space2>
static inline void exec(const Space1& space1, Space2& space2)
{
std::get<N>(space2) = std::get<N>(space1);
CopyRanges<N-1>::exec(space1,space2);
}
};
template <>
struct CopyRanges<0>
{
template <class Space1, class Space2>
static inline void exec(const Space1& space1, Space2& space2)
{
std::get<0>(space2) = std::get<0>(space1);
}
};
}
template <typename T, class Range1, class... RangeTypes>
auto anonToDynView(const ArrayBase<T,Range1,RangeTypes...,AnonymousRange>& ma)
-> ConstSlice<T,Range1,RangeTypes...,DynamicRange>
{
constexpr size_t LAST = sizeof...(RangeTypes)+1;
DynamicRangeFactory drf(rptr<LAST>(ma)->orig());
std::tuple<std::shared_ptr<Range1>,std::shared_ptr<RangeTypes>...,
std::shared_ptr<DynamicRange>> mNSpace;
CopyRanges<LAST-1>::exec(ma.range()->space(),mNSpace);
std::get<LAST>(mNSpace) = createExplicit( drf );
return ConstSlice<T,Range1,RangeTypes...,DynamicRange>(mNSpace, ma.data());
}
template <typename T, class Range1, class... RangeTypes>
auto anonToDynView(MutableArrayBase<T,Range1,RangeTypes...,AnonymousRange>& ma)
-> Slice<T,Range1,RangeTypes...,DynamicRange>
{
constexpr size_t LAST = sizeof...(RangeTypes)+1;
DynamicRangeFactory drf(rptr<LAST>(ma)->orig());
std::tuple<std::shared_ptr<Range1>,std::shared_ptr<RangeTypes>...,
std::shared_ptr<DynamicRange>> mNSpace;
CopyRanges<LAST-1>::exec(ma.range()->space(),mNSpace);
std::get<LAST>(mNSpace) = createExplicit( drf );
return Slice<T,Range1,RangeTypes...,DynamicRange>(mNSpace, ma.data());
}
template <typename T, class Range1, class... RangeTypes>
auto dynToAnonMove(Array<T,Range1,RangeTypes...,DynamicRange>&& ma)
-> Array<T,Range1,RangeTypes...,AnonymousRange>
{
constexpr size_t LAST = sizeof...(RangeTypes)+1;
AnonymousRangeFactory arf(rptr<LAST>(ma)->orig());
std::tuple<std::shared_ptr<Range1>,std::shared_ptr<RangeTypes>...,
std::shared_ptr<AnonymousRange>> mNSpace;
CopyRanges<LAST-1>::exec(ma.range()->space(),mNSpace);
std::get<LAST>(mNSpace) = createExplicit( arf );
return ma.format(mNSpace);
}
template <typename T>
auto anonToDynView(const ArrayBase<T,AnonymousRange>& ma)
-> ConstSlice<T,DynamicRange>
{
DynamicRangeFactory drf(rptr<0>(ma)->orig());
auto mNSpace = std::make_tuple( createExplicit( drf ) );
return ConstSlice<T,DynamicRange>(mNSpace, ma.data());
}
template <typename T>
auto anonToDynView(MutableArrayBase<T,AnonymousRange>& ma)
-> Slice<T,DynamicRange>
{
DynamicRangeFactory drf(rptr<0>(ma)->orig());
auto mNSpace = std::make_tuple( createExplicit( drf ) );
return Slice<T,DynamicRange>(mNSpace, ma.data());
}
template <typename T>
auto dynToAnonMove(Array<T,DynamicRange>&& ma)
-> Array<T,AnonymousRange>
{
AnonymousRangeFactory arf(rptr<0>(ma)->orig());
auto mNSpace = std::make_tuple( createExplicit( arf ) );
return ma.format(mNSpace);
}
template <class Range>
auto metaSlice(const std::shared_ptr<Range>& r)
-> ConstSlice<typename Range::MetaType,ClassicRange>
{
ClassicRF crf(r->size());
return ConstSlice<typename Range::MetaType,ClassicRange>( createExplicit(crf), &r->get(0) );
}
template <class Range, class ORange>
auto metaSlice(const std::shared_ptr<Range>& r, const std::shared_ptr<ORange>& ro)
-> ConstSlice<typename Range::MetaType,ORange>
{
return ConstSlice<typename Range::MetaType,ORange>( ro, &r->get(0) );
}
template <typename T, class... Ranges>
auto mkArray(const std::shared_ptr<Ranges>&... rs)
-> Array<T,Ranges...>
{
return Array<T,Ranges...>(rs...);
}
template <typename T, class... Ranges>
auto mkArray(const std::shared_ptr<Ranges>&... rs, const T& val)
-> Array<T,Ranges...>
{
return Array<T,Ranges...>(rs..., val);
}
template <typename T, class... Ranges>
auto mkArrayPtr(const std::shared_ptr<Ranges>&... rs)
-> std::shared_ptr<Array<T,Ranges...>>
{
return std::make_shared<Array<T,Ranges...>>(rs...);
}
}

238
src/include/helper_tools.h Normal file
View file

@ -0,0 +1,238 @@
#ifndef __cxz_helper_tools_h__
#define __cxz_helper_tools_h__
#include "base_def.h"
#include "slice.h"
#include <ostream>
#include "map_range.h"
#include <functional>
#include "xfor/iloop.h"
namespace CNORXZ
{
template <typename... T>
std::ostream& operator<<(std::ostream& out, const std::tuple<T...>& tp);
template <class RangeType>
auto getIndex(std::shared_ptr<RangeType> range)
-> std::shared_ptr<typename RangeType::IndexType>;
// only if 'RangeType' is defaultable and unique (Singleton)
template <class RangeType>
auto getIndex() -> std::shared_ptr<typename RangeType::IndexType>;
template <class... RangeTypes>
auto mkMulti(std::shared_ptr<RangeTypes>... ranges)
-> std::shared_ptr<MultiRange<RangeTypes...> >;
template <class Op, SpaceType XSTYPE>
using MapORType = SingleRange<typename Op::value_type,XSTYPE>;
template <SpaceType STYPE, class Op, class MA, class... RangeTypes>
auto mkGenMapR(const std::tuple<Op,MA>& f, std::shared_ptr<RangeTypes>... ranges)
-> std::shared_ptr<GenMapRange<MapORType<Op,STYPE>,Op,STYPE,RangeTypes...> >;
template <SpaceType STYPE, class ORType, class Op, class MA, class... RangeTypes>
auto mkGenMapRwith(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& f,
std::shared_ptr<RangeTypes>... ranges)
-> std::shared_ptr<GenMapRange<ORType,Op,STYPE,RangeTypes...> >;
template <SpaceType STYPE, class Op, class MA, class... IndexTypes>
auto mkGenMapI(const std::tuple<Op,MA>& f, std::shared_ptr<IndexTypes>... indices)
-> decltype( getIndex( mkGenMapR<STYPE>( f, indices->range()... ) ) );
template <class Op, class MA, class... RangeTypes>
auto mkMapR(const std::tuple<Op,MA>& f, std::shared_ptr<RangeTypes>... ranges)
-> decltype( mkGenMapR<SpaceType::ANY>(f, ranges... ) );
template <class ORType, class Op, class MA, class... RangeTypes>
auto mkMapRwith(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& f, std::shared_ptr<RangeTypes>... ranges)
-> decltype( mkGenMapRwith<SpaceType::ANY>(outr, f, ranges... ) );
template <class Func, class... Indices>
auto mkMapR(const std::shared_ptr<Func>& func, const std::shared_ptr<Indices>&... is)
-> decltype( mkMapR( mkMapOp( func, is... ), is->range()... ) );
template <class ORType, class Func, class... Indices>
auto mkMapRwith(const std::shared_ptr<ORType>& outr, const std::shared_ptr<Func>& func, const std::shared_ptr<Indices>&... is)
-> decltype( mkMapRwith(outr, mkMapOp( func, is... ), is->range()... ) );
template <class Op, class MA, class... IndexTypes>
auto mkMapI(const std::tuple<Op,MA>& f, std::shared_ptr<IndexTypes>... indices)
-> decltype( mkGenMapI<SpaceType::ANY>(f, indices... ) );
template <class... IndexTypes>
auto indexToRangeTuple(const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
-> std::tuple<std::shared_ptr<typename IndexTypes::RangeType>...>;
template <class... RangeTypes>
auto mkMulti(std::tuple<std::shared_ptr<RangeTypes>...> rangesTuple)
-> std::shared_ptr<MultiRange<RangeTypes...>>;
template <class... IndexTypes>
auto mkMIndex(std::shared_ptr<IndexTypes>... indices)
-> decltype( getIndex( mkMulti( indices.range()... ) ) );
template <class... IndexTypes>
auto mkMIndex(const std::tuple<std::shared_ptr<IndexTypes>...>& indices)
-> decltype( getIndex( mkMulti( indexToRangeTuple(indices) ) ) );
template <class Index>
auto mkIndexW(const std::shared_ptr<Index>& ind)
-> std::shared_ptr<IndexW>;
template <class RangeFactory>
auto createExplicit(RangeFactory& rf)
-> std::shared_ptr<typename RangeFactory::oType>;
template <class RangeFactory>
auto createExplicit(std::shared_ptr<RangeFactory> rfp)
-> std::shared_ptr<typename RangeFactory::oType>;
template <class Range>
auto createRange(const vector<char>& cvec)
-> std::shared_ptr<Range>;
inline auto createRange(const vector<char>* cvec, int metaType, size_t size)
-> std::shared_ptr<RangeBase>;
inline auto createRangeA(const vector<char>* cvec, int metaType, size_t size)
-> std::shared_ptr<AnonymousRange>;
template <class Range, typename... Args>
auto createRangeE(Args&&... args)
-> std::shared_ptr<Range>;
template <size_t N, class MArray>
auto rptr(const MArray& ma)
-> decltype(ma.template getRangePtr<N>());
template <size_t I, class MIndex>
auto get(const std::shared_ptr<MIndex>& i)
-> decltype(i->template getPtr<I>())
{
return i->template getPtr<I>();
}
template <class MArray>
auto dynamic(const MArray& ma, bool slice = false)
-> std::shared_ptr<ArrayBase<typename MArray::value_type,DynamicRange>>;
template <class MArray>
auto mdynamic(MArray& ma, bool slice)
-> std::shared_ptr<MutableArrayBase<typename MArray::value_type,DynamicRange>>;
template <typename T, class Range1, class... RangeTypes>
auto anonToDynView(const ArrayBase<T,Range1,RangeTypes...,AnonymousRange>& ma)
-> ConstSlice<T,Range1,RangeTypes...,DynamicRange>;
template <typename T, class Range1, class... RangeTypes>
auto anonToDynView(MutableArrayBase<T,Range1,RangeTypes...,AnonymousRange>& ma)
-> Slice<T,Range1,RangeTypes...,DynamicRange>;
template <typename T, class Range1, class... RangeTypes>
auto dynToAnonMove(Array<T,Range1,RangeTypes...,DynamicRange>&& ma)
-> Array<T,Range1,RangeTypes...,AnonymousRange>;
template <typename T>
auto anonToDynView(const ArrayBase<T,AnonymousRange>& ma)
-> ConstSlice<T,DynamicRange>;
template <typename T>
auto anonToDynView(MutableArrayBase<T,AnonymousRange>& ma)
-> Slice<T,DynamicRange>;
template <typename T>
auto dynToAnonMove(Array<T,DynamicRange>&& ma)
-> Array<T,AnonymousRange>;
template <class Range>
auto metaSlice(const std::shared_ptr<Range>& r)
-> ConstSlice<typename Range::MetaType,ClassicRange>;
template <class Range, class ORange>
auto metaSlice(const std::shared_ptr<Range>& r, const std::shared_ptr<ORange>& ro)
-> ConstSlice<typename Range::MetaType,ORange>;
template <typename T, class... Ranges>
auto mkArray(const std::shared_ptr<Ranges>&... rs)
-> Array<T,Ranges...>;
template <typename T, class... Ranges>
auto mkArrayPtr(const std::shared_ptr<Ranges>&... rs)
-> std::shared_ptr<Array<T,Ranges...>>;
template <typename T, class... Ranges>
auto mkArray(const std::shared_ptr<Ranges>&... rs, const T& val)
-> Array<T,Ranges...>;
template <class OpTp, class IndTp, class VarTp, class LTp>
auto mkILoop(const OpTp& opTp, const IndTp& indTp, const VarTp& varTp, const LTp& lTp,
const std::array<size_t,std::tuple_size<LTp>::value>& umpos,
const std::array<size_t,std::tuple_size<VarTp>::value>& setzero)
-> CNORXZInternal::ILoop<OpTp,IndTp,VarTp,LTp>
{
return CNORXZInternal::ILoop<OpTp,IndTp,VarTp,LTp>(opTp, indTp, varTp, lTp, umpos, setzero);
}
template <class CF>
auto mkPILoop(const CF& cf)
-> CNORXZInternal::PILoop<CF>
{
return CNORXZInternal::PILoop<CF>(cf);
}
template <class IndexType>
inline void For(const std::shared_ptr<IndexType>& ind, const std::function<void(void)>& ll)
{
for((*ind) = 0; ind->pos() != ind->max(); ++(*ind)){
ll();
}
}
// parallel:
template <class IndexType>
inline void PFor(const std::shared_ptr<IndexType>& ind,
const std::function<void(const std::shared_ptr<IndexType>&)>& ll)
{
const int max = static_cast<int>(ind->max());
int i = 0;
#pragma omp parallel shared(ind,ll) private(i)
{
#pragma omp for nowait
for(i = 0; i < max; i++) {
auto ii = getIndex( ind->range() );
((*ii) = i)();
ll(ii);
}
}
}
template <class Index>
inline auto mkOp(const std::shared_ptr<Index>& i)
-> decltype(std::declval<FunctionalArray<typename Index::MetaType,
identity<typename Index::MetaType>,typename Index::RangeType> >
().exec(i))
{
FunctionalArray<typename Index::MetaType,
identity<typename Index::MetaType>,
typename Index::RangeType> fma(i->range());
return fma.exec(i);
}
template <typename R, typename... Ts>
struct Func
{
static inline std::shared_ptr<function<R,Ts...>> mk(const std::function<R(Ts...)>& ll)
{
return std::make_shared<function<R,Ts...>>(ll);
}
};
}
#endif

View file

@ -0,0 +1,448 @@
#include "high_level_operation.h"
namespace CNORXZ
{
template <typename T, class Op>
DynamicO<T> mkDynOp1(const Op& op)
{
return DynamicO<T>(op);
}
template <class ROP>
template <class... Indices>
template <class Op, class... Ops>
void HighLevelOpBase<ROP>::RetT<Indices...>::appendOuterM(const Op& op, const Ops&... ops)
{
// does not check anything regarding input !!!
if(outer.init()){
outer = mkDynOp1<size_t>(mkMOp<size_t>(outer,op,ops...));
}
else {
outer = mkDynOp1<size_t>(mkMOp<size_t>(op,ops...));
}
}
template <class ROP>
template <class... Indices>
void HighLevelOpBase<ROP>::RetT<Indices...>::appendOuterM()
{}
template <class ROP>
template <class... Indices>
void HighLevelOpBase<ROP>::RetT<Indices...>::appendOuter(const DynamicO<size_t>& in)
{
if(in.init()){
if(outer.init()){
outer = mkDynOp1<size_t>(mkMOp<size_t>(outer,in));
}
else {
outer = in;
}
}
}
template <class ROP>
template <class... Indices>
void HighLevelOpBase<ROP>::RetT<Indices...>::appendOuter(const RetT& in)
{
appendOuter(in.outer);
}
template <class ROP>
HighLevelOpRoot<ROP>::HighLevelOpRoot(const ROP& op) : mOp(op) {}
template <class ROP>
bool HighLevelOpRoot<ROP>::root() const
{
return true;
}
template <class ROP>
template <class... Inds>
auto HighLevelOpRoot<ROP>::xcreate(const std::shared_ptr<Inds>&... inds)
-> typename B::template RetT<Inds...>
{
assert(0);
return typename B::template RetT<Inds...>();
}
template <class ROP>
ROP* HighLevelOpRoot<ROP>::get()
{
return &mOp;
}
template <class ROP>
auto HighLevelOpRoot<ROP>::vget()
-> VOP*
{
return nullptr;
}
template <class ROP>
HighLevelOpValue<ROP>::HighLevelOpValue(const VOP& op) : mOp(op) {}
template <class ROP>
bool HighLevelOpValue<ROP>::root() const
{
return true;
}
template <class ROP>
template <class... Inds>
auto HighLevelOpValue<ROP>::xcreate(const std::shared_ptr<Inds>&... inds)
-> typename B::template RetT<Inds...>
{
assert(0);
return typename B::template RetT<Inds...>();
}
template <class ROP>
ROP* HighLevelOpValue<ROP>::get()
{
return nullptr;
}
template <class ROP>
auto HighLevelOpValue<ROP>::vget()
-> VOP*
{
return &mOp;
}
namespace
{
template <size_t N, class... Indices>
struct Create
{
template <class ROP, class OpF, class... OPs>
struct ccx
{
template <size_t M, class... DOPs>
static inline void
cccx(typename HighLevelOpBase<ROP>::template RetT<Indices...>& res,
const std::array<std::shared_ptr<HighLevelOpBase<ROP>>,M>& in,
const std::shared_ptr<Indices>&... inds,
const OPs&... ops,
const DOPs&... dops)
{
//static_assert(N > 0, "N > 0 failed");
auto& inn = std::get<N>(in);
if(not inn->root()){
auto dop = inn->create(inds...);
auto op = *dop.op.data()->mOp;
res.appendOuter(dop);
assert(dop.op.init());
if constexpr(N > 0){
typedef decltype(op) OP;
Create<N-1,Indices...>::template ccx<ROP,OpF,OP,OPs...>::template cccx<M>
(res, in, inds..., op, ops..., dop, dops...);
}
else {
res.op = mkDynOutOp(mkFOp<OpF>(op,ops...), inds...);
res.appendOuterM(dop.op,dops.op...);
}
}
else {
auto op = inn->get();
auto vop = inn->vget();
if constexpr(N > 0){
typedef typename std::remove_reference<decltype(*op)>::type OP;
typedef typename std::remove_reference<decltype(*vop)>::type VOP;
if(op != nullptr){
Create<N-1,Indices...>::template ccx<ROP,OpF,OP,OPs...>::template cccx<M>
(res, in, inds..., *op, ops..., dops...);
}
else {
Create<N-1,Indices...>::template ccx<ROP,OpF,VOP,OPs...>::template cccx<M>
(res, in, inds..., *vop, ops..., dops...);
}
}
else {
if(op != nullptr){
res.op = mkDynOutOp(mkFOp<OpF>(*op,ops...), inds...);
}
else {
res.op = mkDynOutOp(mkFOp<OpF>(*vop,ops...), inds...);
}
res.appendOuterM(dops.op...);
}
}
}
};
};
}
template <class ROP, class OpF, size_t N>
HighLevelOp<ROP,OpF,N>::HighLevelOp(std::array<std::shared_ptr<HighLevelOpBase<ROP>>,N> in) : mIn(in) {}
template <class ROP, class OpF, size_t N>
bool HighLevelOp<ROP,OpF,N>::root() const
{
return false;
}
template <class ROP, class OpF, size_t N>
ROP* HighLevelOp<ROP,OpF,N>::get()
{
assert(0);
return nullptr;
}
template <class ROP, class OpF, size_t N>
auto HighLevelOp<ROP,OpF,N>::vget()
-> VOP*
{
assert(0);
return nullptr;
}
template <class ROP, class OpF, size_t N>
template <class... Inds>
auto HighLevelOp<ROP,OpF,N>::xcreate(const std::shared_ptr<Inds>&... inds)
-> typename B::template RetT<Inds...>
{
typename B::template RetT<Inds...> res;
Create<N-1,Inds...>::template ccx<ROP,OpF>::template cccx<N>
(res,mIn,inds...);
return res;
}
template <class ROP>
HighLevelOpHolder<ROP>::HighLevelOpHolder(const std::shared_ptr<HighLevelOpBase<ROP>>& op) : mOp(op) {}
template <class ROP>
bool HighLevelOpHolder<ROP>::root() const
{
return mOp->root();
}
template <class ROP>
template <class... Inds>
auto HighLevelOpHolder<ROP>::create(const std::shared_ptr<Inds>&... inds) const
-> decltype(mOp->create(inds...))
{
return mOp->create(inds...);
}
template <class ROP>
auto HighLevelOpHolder<ROP>::get()
-> decltype(mOp->get())
{
return mOp->get();
}
template <class ROP>
std::shared_ptr<HighLevelOpBase<ROP>> HighLevelOpHolder<ROP>::op() const
{
return mOp;
}
template <class ROP>
HighLevelOpHolder<ROP> HighLevelOpHolder<ROP>::operator*(const HighLevelOpHolder& in) const
{
return HighLevelOpHolder<ROP>
( std::make_shared<HighLevelOp<ROP,multipliesx<double,double>,2>>
( std::array<std::shared_ptr<HighLevelOpBase<ROP>>,2>({mOp, in.mOp}) ) );
}
template <class ROP>
HighLevelOpHolder<ROP> HighLevelOpHolder<ROP>::operator+(const HighLevelOpHolder& in) const
{
return HighLevelOpHolder<ROP>
( std::make_shared<HighLevelOp<ROP,plusx<double,double>,2>>
( std::array<std::shared_ptr<HighLevelOpBase<ROP>>,2>({mOp, in.mOp}) ) );
}
template <class ROP>
HighLevelOpHolder<ROP> HighLevelOpHolder<ROP>::operator-(const HighLevelOpHolder& in) const
{
return HighLevelOpHolder<ROP>
( std::make_shared<HighLevelOp<ROP,minusx<double,double>,2>>
( std::array<std::shared_ptr<HighLevelOpBase<ROP>>,2>({mOp, in.mOp}) ) );
}
template <class ROP>
HighLevelOpHolder<ROP> HighLevelOpHolder<ROP>::operator/(const HighLevelOpHolder& in) const
{
return HighLevelOpHolder<ROP>
( std::make_shared<HighLevelOp<ROP,dividesx<double,double>,2>>
( std::array<std::shared_ptr<HighLevelOpBase<ROP>>,2>({mOp, in.mOp}) ) );
}
template <class F, class ROP, class... ROPs>
HighLevelOpHolder<ROP> mkSFunc(const HighLevelOpHolder<ROP>& a, const HighLevelOpHolder<ROPs>&... as)
{
constexpr size_t N = sizeof...(ROPs)+1;
return HighLevelOpHolder<ROP>
( std::make_shared<HighLevelOp<ROP,F,N>>
( std::array<std::shared_ptr<HighLevelOpBase<ROP>>,N>({a.op(), as.op()...}) ) );
}
template <class ROP>
template <class... Indices>
HighLevelOpHolder<ROP>& HighLevelOpHolder<ROP>::xassign(const HighLevelOpHolder& in,
const std::shared_ptr<DynamicIndex>& di,
const std::shared_ptr<Indices>&... is)
{
const size_t dim = di->dim();
if(dim > 2){
auto ci1 = di->getP(dim-2)->reduced();
auto ci2 = di->getP(dim-1)->reduced();
assert(ci1 != nullptr);
assert(ci2 != nullptr);
auto odi = mkSubSpaceX(di, dim-2);
auto mi = mkMIndex(is..., odi);
this->assign(in, mi, ci1, ci2);
}
else {
assert(dim == 2 or dim == 1);
auto ci1 = di->getP(dim-1)->reduced();
assert(ci1 != nullptr);
auto odi = mkSubSpaceX(di, dim-1);
auto mi = mkMIndex(is..., odi);
this->assign(in, mi, ci1);
}
return *this;
}
template <class ROP>
template <class... Indices>
HighLevelOpHolder<ROP>& HighLevelOpHolder<ROP>::xplus(const HighLevelOpHolder& in,
const std::shared_ptr<DynamicIndex>& di,
const std::shared_ptr<Indices>&... is)
{
const size_t dim = di->dim();
if(dim > 2){
auto ci1 = di->getP(dim-2)->reduced();
auto ci2 = di->getP(dim-1)->reduced();
assert(ci1 != nullptr);
assert(ci2 != nullptr);
auto odi = mkSubSpaceX(di, dim-2);
auto mi = mkMIndex(is..., odi);
this->plus(in, mi, ci1, ci2);
}
else {
assert(dim == 2 or dim == 1);
auto ci1 = di->getP(dim-1)->reduced();
assert(ci1 != nullptr);
auto odi = mkSubSpaceX(di, dim-1);
auto mi = mkMIndex(is..., odi);
this->plus(in, mi, ci1);
}
return *this;
}
template <class Ind1, class Ind2, class... Inds>
std::string printInd(const std::shared_ptr<Ind1>& ind1, const std::shared_ptr<Ind2>& ind2,
const std::shared_ptr<Inds>&... inds)
{
return std::to_string(reinterpret_cast<std::intptr_t>(ind1.get())) + "(" +
std::to_string(ind1->max()) + "), " + printInd(ind2, inds...);
}
template <class Ind1>
std::string printInd(const std::shared_ptr<Ind1>& ind1)
{
return std::to_string(reinterpret_cast<std::intptr_t>(ind1.get())) + "(" + std::to_string(ind1->max()) + ")";
}
template <class ROP>
template <class MIndex, class... Indices>
HighLevelOpHolder<ROP>& HighLevelOpHolder<ROP>::assign(const HighLevelOpHolder& in,
const std::shared_ptr<MIndex>& mi,
const std::shared_ptr<Indices>&... inds)
{
auto xx = mkArrayPtr<double>(nullr());
ROP& opr = *mOp->get();
if(in.root()){
auto inx = in;
opr.par().assign( *inx.get(), mkMIndex(mi,inds...) )();
return *this;
}
auto loop = mkPILoop
( [&opr,&in,&xx,&inds...,this](){
auto inx = in;
auto dop = inx.create(inds...);
DynamicO<size_t> gexp;
if(dop.outer.init()){
gexp = mkDynOp1<size_t>(mkMOp<size_t>(dop.outer,dop.op));
}
else {
gexp = mkDynOp1<size_t>(mkMOp<size_t>(dop.op));
}
auto xloop = mkILoop(std::make_tuple(*dop.op.data()->mOp),
std::make_tuple(inds...),
std::make_tuple(xx),
std::make_tuple(opr.assign( *dop.op.data()->mOp,
mkMIndex(inds...) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0}));
return mkGetExpr(gexp, xloop); });
mi->pifor(1,loop)();
return *this;
}
template <class ROP>
template <class MIndex, class... Indices>
HighLevelOpHolder<ROP>& HighLevelOpHolder<ROP>::plus(const HighLevelOpHolder& in,
const std::shared_ptr<MIndex>& mi,
const std::shared_ptr<Indices>&... inds)
{
auto xx = mkArrayPtr<double>(nullr());
ROP& opr = *mOp->get();
if(in.root()){
auto inx = in;
opr.par().plus( *inx.get(), mkMIndex(mi,inds...) )();
return *this;
}
auto loop = mkPILoop
( [&opr,&in,&xx,&inds...,this](){
auto inx = in;
auto dop = inx.create(inds...);
DynamicO<size_t> gexp;
if(dop.outer.init()){
gexp = mkDynOp1<size_t>(mkMOp<size_t>(dop.outer,dop.op));
}
else {
gexp = mkDynOp1<size_t>(mkMOp<size_t>(dop.op));
}
auto xloop = mkILoop(std::make_tuple(*dop.op.data()->mOp),
std::make_tuple(inds...),
std::make_tuple(xx),
std::make_tuple(opr.plus( *dop.op.data()->mOp,
mkMIndex(inds...) )),
std::array<size_t,1>({1}), std::array<size_t,1>({0}));
return mkGetExpr(gexp, xloop); });
mi->pifor(1,loop)();
return *this;
}
template <class ROP>
HighLevelOpHolder<ROP> mkHLO(const ROP& op)
{
return HighLevelOpHolder<ROP>(std::make_shared<HighLevelOpRoot<ROP>>( op ) );
}
template <class ROP>
HighLevelOpHolder<ROP> mkHLOV(double val)
{
return HighLevelOpHolder<ROP>(std::make_shared<HighLevelOpValue<ROP>>
( OperationValue<double>(val) ) );
}
#define SP " "
#define regFunc1(fff) template <class ROP> \
HighLevelOpHolder<ROP> hl_##fff (const HighLevelOpHolder<ROP>& in) \
{ return HighLevelOpHolder<ROP>( std::make_shared<HighLevelOp<ROP,x_##fff <double>,1>> \
( std::array<std::shared_ptr<HighLevelOpBase<ROP>>,1>( {in.op()} ) ) ); } \
#include "extensions/math.h"
#undef regFunc1
#undef SP
}

View file

@ -0,0 +1,279 @@
#ifndef __cxz_high_level_operation_h__
#define __cxz_high_level_operation_h__
#include "base_def.h"
#include "ranges/rheader.h"
#include "dynamic_operation.h"
namespace CNORXZ
{
typedef ClassicRange CR;
typedef CR::IndexType CI;
typedef std::shared_ptr<CI> CIP;
typedef OperationRoot<double,CR,DynamicRange> OpCD;
typedef OperationRoot<double,DynamicRange> OpD;
extern template class OperationRoot<double,CR,DynamicRange>;
extern template class OperationRoot<double,DynamicRange>;
template <typename T, class Op>
DynamicO<T> mkDynOp1(const Op& op);
std::shared_ptr<DynamicIndex> mkSubSpaceX(const std::shared_ptr<DynamicIndex>& di, size_t max);
template <class ROP>
class HighLevelOpBase
{
public:
typedef OperationValue<double> VOP;
template <class... Indices>
struct RetT
{
DynamicO<OpH<OperationRoot<double,typename Indices::RangeType...>>> op;
DynamicO<size_t> outer;
template <class Op, class... Ops>
void appendOuterM(const Op& op, const Ops&... ops);
void appendOuterM();
void appendOuter(const DynamicO<size_t>& in);
void appendOuter(const RetT& in);
};
virtual bool root() const = 0;
#define reg_ind1(I1) virtual RetT<I1> create \
(const std::shared_ptr<I1>& ind1) = 0
#define reg_ind2(I1,I2) virtual RetT<I1,I2> create \
(const std::shared_ptr<I1>& ind1,const std::shared_ptr<I2>& ind2) = 0
#define reg_ind3(I1,I2,I3) virtual RetT<I1,I2,I3> create \
(const std::shared_ptr<I1>& ind1,const std::shared_ptr<I2>& ind2,const std::shared_ptr<I3>& ind3) = 0
//#include "hl_reg_ind.h"
reg_ind1(ClassicRange::IndexType);
reg_ind2(ClassicRange::IndexType,ClassicRange::IndexType);
reg_ind3(ClassicRange::IndexType,ClassicRange::IndexType,ClassicRange::IndexType);
#undef reg_ind1
#undef reg_ind2
#undef reg_ind3
virtual ROP* get() = 0;
virtual VOP* vget() = 0;
};
template <class ROP>
class HighLevelOpRoot : public HighLevelOpBase<ROP>
{
private:
typedef HighLevelOpBase<ROP> B;
typedef typename B::VOP VOP;
template <class... Inds>
typename B::template RetT<Inds...> xcreate(const std::shared_ptr<Inds>&... inds);
ROP mOp;
public:
HighLevelOpRoot(const ROP& op);
virtual bool root() const override final;
#define reg_ind1(I1) virtual typename B::template RetT<I1> create \
(const std::shared_ptr<I1>& ind1) \
override final { return xcreate(ind1); }
#define reg_ind2(I1,I2) virtual typename B::template RetT<I1,I2> create \
(const std::shared_ptr<I1>& ind1, const std::shared_ptr<I2>& ind2) \
override final { return xcreate(ind1,ind2); }
#define reg_ind3(I1,I2,I3) virtual typename B::template RetT<I1,I2,I3> create \
(const std::shared_ptr<I1>& ind1, const std::shared_ptr<I2>& ind2, const std::shared_ptr<I3>& ind3) \
override final { return xcreate(ind1,ind2,ind3); }
//#include "hl_reg_ind.h"
reg_ind1(ClassicRange::IndexType);
reg_ind2(ClassicRange::IndexType,ClassicRange::IndexType);
reg_ind3(ClassicRange::IndexType,ClassicRange::IndexType,ClassicRange::IndexType);
virtual ROP* get() override final;
virtual VOP* vget() override final;
};
extern template class HighLevelOpBase<OpCD>;
extern template class HighLevelOpBase<OpD>;
extern template class HighLevelOpRoot<OpCD>;
extern template class HighLevelOpRoot<OpD>;
template <class ROP>
class HighLevelOpValue : public HighLevelOpBase<ROP>
{
private:
typedef HighLevelOpBase<ROP> B;
typedef typename B::VOP VOP;
template <class... Inds>
typename B::template RetT<Inds...> xcreate(const std::shared_ptr<Inds>&... inds);
VOP mOp;
public:
HighLevelOpValue(const VOP& vop);
virtual bool root() const override final;
//#include "hl_reg_ind.h"
reg_ind1(ClassicRange::IndexType);
reg_ind2(ClassicRange::IndexType,ClassicRange::IndexType);
reg_ind3(ClassicRange::IndexType,ClassicRange::IndexType,ClassicRange::IndexType);
virtual ROP* get() override final;
virtual VOP* vget() override final;
};
template <class OpF, class... Ops>
auto mkFOp(const Ops&... ops)
{
return Operation<double,OpF,Ops...>(ops...);
}
template <class ROP, class OpF, size_t N>
class HighLevelOp : public HighLevelOpBase<ROP>
{
public:
typedef HighLevelOpBase<ROP> B;
typedef typename B::VOP VOP;
private:
std::array<std::shared_ptr<HighLevelOpBase<ROP>>,N> mIn;
template <class... Inds>
auto xcreate(const std::shared_ptr<Inds>&... inds)
-> typename B::template RetT<Inds...>;
public:
HighLevelOp(std::array<std::shared_ptr<HighLevelOpBase<ROP>>,N> in);
virtual bool root() const override final;
virtual ROP* get() override final;
virtual VOP* vget() override final;
//#include "hl_reg_ind.h"
reg_ind1(ClassicRange::IndexType);
reg_ind2(ClassicRange::IndexType,ClassicRange::IndexType);
reg_ind3(ClassicRange::IndexType,ClassicRange::IndexType,ClassicRange::IndexType);
#undef reg_ind1
#undef reg_ind2
#undef reg_ind3
};
extern template class HighLevelOp<OpCD,plusx<double,double>,2>;
extern template class HighLevelOp<OpCD,minusx<double,double>,2>;
extern template class HighLevelOp<OpCD,multipliesx<double,double>,2>;
extern template class HighLevelOp<OpCD,dividesx<double,double>,2>;
extern template class HighLevelOp<OpD,plusx<double,double>,2>;
extern template class HighLevelOp<OpD,minusx<double,double>,2>;
extern template class HighLevelOp<OpD,multipliesx<double,double>,2>;
extern template class HighLevelOp<OpD,dividesx<double,double>,2>;
#define regFunc1(fff) \
extern template class HighLevelOp<OpCD,x_##fff<double>,1>; \
extern template class HighLevelOp<OpD,x_##fff<double>,1>;
#include "extensions/math.h"
#undef regFunc1
template <class ROP>
class HighLevelOpHolder
{
private:
std::shared_ptr<HighLevelOpBase<ROP>> mOp;
public:
HighLevelOpHolder() = default;
HighLevelOpHolder(const HighLevelOpHolder& in) = default;
HighLevelOpHolder(HighLevelOpHolder&& in) = default;
HighLevelOpHolder& operator=(const HighLevelOpHolder& in) = default;
HighLevelOpHolder& operator=(HighLevelOpHolder&& in) = default;
HighLevelOpHolder(const std::shared_ptr<HighLevelOpBase<ROP>>& op);
bool root() const;
template <class... Inds>
auto create(const std::shared_ptr<Inds>&... inds) const
-> decltype(mOp->create(inds...));
auto get() -> decltype(mOp->get());
std::shared_ptr<HighLevelOpBase<ROP>> op() const;
HighLevelOpHolder operator*(const HighLevelOpHolder& in) const;
HighLevelOpHolder operator+(const HighLevelOpHolder& in) const;
HighLevelOpHolder operator-(const HighLevelOpHolder& in) const;
HighLevelOpHolder operator/(const HighLevelOpHolder& in) const;
template <class... Indices>
HighLevelOpHolder& xassign(const HighLevelOpHolder& in,
const std::shared_ptr<DynamicIndex>& di,
const std::shared_ptr<Indices>&... is);
template <class... Indices>
HighLevelOpHolder& xplus(const HighLevelOpHolder& in,
const std::shared_ptr<DynamicIndex>& di,
const std::shared_ptr<Indices>&... is);
template <class MIndex, class... Indices>
HighLevelOpHolder& assign(const HighLevelOpHolder& in,
const std::shared_ptr<MIndex>& mi,
const std::shared_ptr<Indices>&... inds);
template <class MIndex, class... Indices>
HighLevelOpHolder& plus(const HighLevelOpHolder& in,
const std::shared_ptr<MIndex>& mi,
const std::shared_ptr<Indices>&... inds);
};
extern template class HighLevelOpHolder<OpCD>;
extern template class HighLevelOpHolder<OpD>;
template <class F, class ROP, class... ROPs>
HighLevelOpHolder<ROP> mkSFunc(const HighLevelOpHolder<ROP>& a, const HighLevelOpHolder<ROPs>&... as);
template <class ROP>
HighLevelOpHolder<ROP> mkHLO(const ROP& op);
template <class ROP>
HighLevelOpHolder<ROP> mkHLOV(double val);
extern template HighLevelOpHolder<OpCD> mkHLO(const OpCD& op);
extern template HighLevelOpHolder<OpD> mkHLO(const OpD& op);
extern template HighLevelOpHolder<OpCD> mkHLOV(double val);
extern template HighLevelOpHolder<OpD> mkHLOV(double val);
#define regFunc1(fff) template <class ROP> \
HighLevelOpHolder<ROP> hl_##fff (const HighLevelOpHolder<ROP>& in);
#include "extensions/math.h"
#undef regFunc1
#define regFunc1(fff) template <class ROP> \
HighLevelOpHolder<ROP> hl_##fff (const HighLevelOpHolder<ROP>& in); \
extern template HighLevelOpHolder<OpCD> hl_##fff (const HighLevelOpHolder<OpCD>& in); \
extern template HighLevelOpHolder<OpD> hl_##fff (const HighLevelOpHolder<OpD>& in);
#include "extensions/math.h"
#undef regFunc1
}
#endif

3
src/include/hl_cnorxz.h Normal file
View file

@ -0,0 +1,3 @@
#include "high_level_operation.h"
#include "high_level_operation.cc.h"

704
src/include/map_range.cc.h Normal file
View file

@ -0,0 +1,704 @@
#include "map_range.h"
#include <type_traits>
namespace CNORXZ
{
namespace
{
using namespace CNORXZInternal;
}
/**************
* OpExpr *
**************/
template <class Op, class Index, class Expr, SpaceType STYPE>
OpExpr<Op,Index,Expr,STYPE>::OpExpr(const Op& mapf, const Index* ind,
size_t step, Expr ex) :
mIndPtr(ind), mSPos(mIndPtr->pos()), mMax(mIndPtr->max()),
mStep(step), mExpr( ex ),
mOp(mapf),
//mExt(ex.rootSteps( reinterpret_cast<std::intptr_t>( mIndPtr )))
mExt( mOp.rootSteps( reinterpret_cast<std::intptr_t>( mIndPtr ) ).extend
( ex.rootSteps( reinterpret_cast<std::intptr_t>( mIndPtr ) ) ) )
{
assert(mIndPtr != nullptr);
}
template <class Op, class Index, class Expr, SpaceType STYPE>
std::shared_ptr<ExpressionBase> OpExpr<Op,Index,Expr,STYPE>::deepCopy() const
{
return std::make_shared<OpExpr<Op,Index,Expr,STYPE>>(*this);
}
template <class Op, class Index, class Expr, SpaceType STYPE>
inline void OpExpr<Op,Index,Expr,STYPE>::operator()(size_t mlast, DExt last)
{
operator()(mlast, std::dynamic_pointer_cast<ExtT<ExtType>>(last)->ext());
}
template <class Op, class Index, class Expr, SpaceType STYPE>
inline void OpExpr<Op,Index,Expr,STYPE>::operator()(size_t mlast,
ExtType last)
{
constexpr size_t NEXT = Op::SIZE;
const ExtType nxpos = last;
const size_t pos = mIndPtr->posAt( mOp.get( nxpos ) );
if(pos != mIndPtr->max()){
const ExtType npos = last + mExt*pos;
const size_t mnpos = PosForward<ForType::DEFAULT>::valuex(mlast, mStep, pos);
mExpr(mnpos, getX<NEXT>( npos ) );
}
}
template <class Op, class Index, class Expr, SpaceType STYPE>
inline void OpExpr<Op,Index,Expr,STYPE>::operator()(size_t mlast)
{
const ExtType last;
constexpr size_t NEXT = Op::SIZE;
const ExtType nxpos = last;
const size_t pos = mIndPtr->posAt( mOp.get( nxpos ) );
if(pos != mIndPtr->max()){
const ExtType npos = last + mExt*pos;
const size_t mnpos = PosForward<ForType::DEFAULT>::valuex(mlast, mStep, pos);
mExpr(mnpos, getX<NEXT>( npos ));
}
}
template <class Op, class Index, class Expr, SpaceType STYPE>
auto OpExpr<Op,Index,Expr,STYPE>::rootSteps(std::intptr_t iPtrNum) const
-> ExtType
{
return mOp.rootSteps(iPtrNum).extend( mExpr.rootSteps(iPtrNum) );
//return mExpr.rootSteps(iPtrNum).extend( mOp.rootSteps(iPtrNum) );
}
template <class Op, class Index, class Expr, SpaceType STYPE>
DExt OpExpr<Op,Index,Expr,STYPE>::dRootSteps(std::intptr_t iPtrNum) const
{
return std::make_shared<ExtT<ExtType>>(rootSteps(iPtrNum));
}
template <class Op, class Index, class Expr, SpaceType STYPE>
DExt OpExpr<Op,Index,Expr,STYPE>::dExtension() const
{
return std::make_shared<ExtT<ExtType>>(mExt);
}
/******************
* MapIndex *
******************/
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
template <class MRange>
GenMapIndex<OIType,Op,XSTYPE,Indices...>::GenMapIndex(const std::shared_ptr<MRange>& range) :
IndexInterface<GenMapIndex<OIType,Op,XSTYPE,Indices...>,typename Op::value_type>(range, 0)
{
std::get<sizeof...(Indices)>(mBlockSizes) = 1;
sfor_mn<sizeof...(Indices),0>
( [&](auto i) {
auto r = range->template getPtr<i>();
std::get<i>(mIPack) = r->beginPtr();
*std::get<i>(mIPack) = 0;
std::get<i>(mBlockSizes) = sfor_p<i,sizeof...(Indices)>
( [&](auto j) { return std::get<j>(mIPack)->max(); } ,
[&](auto a, auto b) { return a * b; });
return 0;
});
IB::mPos = sfor_m<sizeof...(Indices),0>
( [&](auto i) { return std::get<i>(mIPack); },
[&](auto a, auto b) {return a->pos() + b*a->max();}, 0 );
mOutIndex = std::make_shared<OIType>
( std::dynamic_pointer_cast<RangeType>( IB::mRangePtr )->outRange()->begin() );
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
template <size_t DIR>
GenMapIndex<OIType,Op,XSTYPE,Indices...>& GenMapIndex<OIType,Op,XSTYPE,Indices...>::up()
{
static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices");
IB::mPos += sfor_p<DIR,sizeof...(Indices)>
( [&](auto i) { return std::get<i>(mIPack)->max(); },
[&](auto a, auto b) { return a * b; } );
sfor_m<DIR+1,0>
( [&](auto i) {
auto& si = *std::get<i>( mIPack );
if(si.last() and i != 0) { si = 0; return true; }
else { ++si; return false; }
return false;
} );
return *this;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
template <size_t DIR>
GenMapIndex<OIType,Op,XSTYPE,Indices...>& GenMapIndex<OIType,Op,XSTYPE,Indices...>::down()
{
static_assert(DIR < sizeof...(Indices), "DIR exceeds number of sub-indices");
IB::mPos -= sfor_p<DIR,sizeof...(Indices)>
( [&](auto i) { return std::get<i>(mIPack)->max(); },
[&](auto a, auto b) { return a * b; } );
sfor_m<DIR+1,0>
( [&](auto i) {
auto& si = *std::get<i>( mIPack );
if(si.first() and i != 0) { si = si.max()-1; return true; }
else { --si; return false; }
return false;
} );
return *this;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
template <size_t N>
auto GenMapIndex<OIType,Op,XSTYPE,Indices...>::get() const -> decltype( *std::get<N>( mIPack ) )&
{
return *std::get<N>(mIPack);
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
template <size_t N>
auto GenMapIndex<OIType,Op,XSTYPE,Indices...>::getPtr() const -> decltype( std::get<N>( mIPack ) )&
{
return std::get<N>(mIPack);
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
auto GenMapIndex<OIType,Op,XSTYPE,Indices...>::outIndex() const -> std::shared_ptr<OIType>
{
return mOutIndex;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
GenMapIndex<OIType,Op,XSTYPE,Indices...>& GenMapIndex<OIType,Op,XSTYPE,Indices...>::operator()(const std::shared_ptr<Indices>&... indices)
{
return (*this)(std::make_tuple(indices...));
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
GenMapIndex<OIType,Op,XSTYPE,Indices...>& GenMapIndex<OIType,Op,XSTYPE,Indices...>::operator()(const std::tuple<std::shared_ptr<Indices>...>& indices)
{
sfor_pn<0,sizeof...(Indices)>
( [&](auto i) { std::get<i>(mIPack) = std::get<i>(indices); return 0; } );
RangeHelper::setIndexPack<sizeof...(Indices)-1>(mIPack, IB::mPos);
return *this;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
IndexType GenMapIndex<OIType,Op,XSTYPE,Indices...>::type() const
{
return IndexType::MULTI;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
GenMapIndex<OIType,Op,XSTYPE,Indices...>& GenMapIndex<OIType,Op,XSTYPE,Indices...>::operator=(size_t pos)
{
(*mOutIndex) = pos;
IB::mPos = mOutIndex->pos();
return *this;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
GenMapIndex<OIType,Op,XSTYPE,Indices...>& GenMapIndex<OIType,Op,XSTYPE,Indices...>::operator++()
{
++(*mOutIndex);
IB::mPos = mOutIndex->pos();
return *this;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
GenMapIndex<OIType,Op,XSTYPE,Indices...>& GenMapIndex<OIType,Op,XSTYPE,Indices...>::operator--()
{
--(*mOutIndex);
IB::mPos = mOutIndex->pos();
return *this;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
int GenMapIndex<OIType,Op,XSTYPE,Indices...>::pp(std::intptr_t idxPtrNum)
{
mOutIndex->pp(idxPtrNum);
IB::mPos = mOutIndex->pos();
return 1;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
int GenMapIndex<OIType,Op,XSTYPE,Indices...>::mm(std::intptr_t idxPtrNum)
{
mOutIndex->mm(idxPtrNum);
IB::mPos = mOutIndex->pos();
return 1;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
std::string GenMapIndex<OIType,Op,XSTYPE,Indices...>::stringMeta() const
{
return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr )->stringMeta(IB::mPos);
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
typename GenMapIndex<OIType,Op,XSTYPE,Indices...>::MetaType GenMapIndex<OIType,Op,XSTYPE,Indices...>::meta() const
{
return mOutIndex->meta();
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
GenMapIndex<OIType,Op,XSTYPE,Indices...>& GenMapIndex<OIType,Op,XSTYPE,Indices...>::at(const MetaType& metaPos)
{
mOutIndex->at(metaPos);
IB::mPos = mOutIndex->pos();
return *this;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
size_t GenMapIndex<OIType,Op,XSTYPE,Indices...>::posAt(const MetaType& metaPos) const
{
return range()->outRange()->getMeta(metaPos);
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
size_t GenMapIndex<OIType,Op,XSTYPE,Indices...>::dim() const
{
return sizeof...(Indices);
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
bool GenMapIndex<OIType,Op,XSTYPE,Indices...>::first() const
{
return IB::mPos == 0;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
bool GenMapIndex<OIType,Op,XSTYPE,Indices...>::last() const
{
return IB::mPos == IB::mMax - 1;
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
std::shared_ptr<typename GenMapIndex<OIType,Op,XSTYPE,Indices...>::RangeType>
GenMapIndex<OIType,Op,XSTYPE,Indices...>::range() const
{
return std::dynamic_pointer_cast<RangeType>( IB::mRangePtr );
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
template <size_t N>
auto GenMapIndex<OIType,Op,XSTYPE,Indices...>::getPtr() -> decltype( std::get<N>( mIPack ) )&
{
return std::get<N>(mIPack);
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
size_t GenMapIndex<OIType,Op,XSTYPE,Indices...>::getStepSize(size_t n) const
{
if(n >= sizeof...(Indices)){
assert(0);
// throw !!
}
return mBlockSizes[n+1];
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
template <class Exprs>
auto GenMapIndex<OIType,Op,XSTYPE,Indices...>::ifor(size_t step, Exprs exs) const
{
return RangeHelper::mkFor<0>
(0, mIPack, mBlockSizes,
OpExpr<Op,GenMapIndex<OIType,Op,XSTYPE,Indices...>,Exprs,XSTYPE>
( range()->map(), this, step, exs ));
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
template <class Exprs>
auto GenMapIndex<OIType,Op,XSTYPE,Indices...>::pifor(size_t step, Exprs exs) const
{
return ifor(step, exs);
}
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
template <class Exprs>
auto GenMapIndex<OIType,Op,XSTYPE,Indices...>::iforh(size_t step, Exprs exs) const
{
return ifor(step, exs);
}
/*************************
* MapRangeFactory *
*************************/
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class MA>
GenMapRangeFactory<ORType,Op,XSTYPE,Ranges...>::GenMapRangeFactory(const std::shared_ptr<ORType>& outr,
const std::tuple<Op,MA>& mapf,
const std::shared_ptr<Ranges>&... rs)
{
mProd = std::shared_ptr< GenMapRange<ORType,Op,XSTYPE,Ranges...> >
( new GenMapRange<ORType,Op,XSTYPE,Ranges...>( outr, mapf, rs... ) );
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class MA>
GenMapRangeFactory<ORType,Op,XSTYPE,Ranges...>::GenMapRangeFactory(const std::shared_ptr<ORType>& outr,
const std::tuple<Op,MA>& mapf,
const typename GenMapRange<ORType,Op,XSTYPE,Ranges...>::Space& st)
{
mProd = std::shared_ptr< GenMapRange<ORType,Op,XSTYPE,Ranges...> >
( new GenMapRange<ORType,Op,XSTYPE,Ranges...>( outr, mapf, st ) );
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class MA>
GenMapRangeFactory<ORType,Op,XSTYPE,Ranges...>::GenMapRangeFactory(const std::tuple<Op,MA>& mapf,
const std::shared_ptr<Ranges>&... rs)
{
mProd = std::shared_ptr< GenMapRange<ORType,Op,XSTYPE,Ranges...> >
( new GenMapRange<ORType,Op,XSTYPE,Ranges...>( mapf, rs... ) );
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class MA>
GenMapRangeFactory<ORType,Op,XSTYPE,Ranges...>::GenMapRangeFactory(const std::tuple<Op,MA>& mapf,
const typename GenMapRange<ORType,Op,XSTYPE,Ranges...>::Space& st)
{
mProd = std::shared_ptr< GenMapRange<ORType,Op,XSTYPE,Ranges...> >
( new GenMapRange<ORType,Op,XSTYPE,Ranges...>( mapf, st ) );
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
std::shared_ptr<RangeBase> GenMapRangeFactory<ORType,Op,XSTYPE,Ranges...>::create()
{
mProd = checkIfCreated( std::dynamic_pointer_cast<oType>( mProd )->mSpace );
setSelf();
return mProd;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
std::shared_ptr<RangeBase> GenMapRangeFactory<ORType,Op,XSTYPE,Ranges...>::checkIfCreated(const std::tuple<std::shared_ptr<Ranges>...>& ptp)
{
std::shared_ptr<RangeBase> out;
bool check = false;
for(auto& x: MapRangeFactoryProductMap::mAleadyCreated){
if(x.second.size() == sizeof...(Ranges)){
check = sfor_p<0,sizeof...(Ranges)>
( [&](auto i) { return reinterpret_cast<std::intptr_t>( std::get<i>(ptp).get() ) == x.second[i]; },
[&](auto a, auto b) { return a and b; } );
if(check){
out = x.first;
break;
}
}
}
if(not check){
vector<std::intptr_t> pv(sizeof...(Ranges));
sfor_pn<0,sizeof...(Ranges)>
( [&](auto i) { pv[i] = reinterpret_cast<std::intptr_t>( std::get<i>(ptp).get() ); return 0; } );
pv.push_back( reinterpret_cast<std::intptr_t>
( &std::dynamic_pointer_cast<oType>( mProd )->mMapf ) );
MapRangeFactoryProductMap::mAleadyCreated[mProd] = pv;
out = mProd;
}
return out;
}
/******************
* MapRange *
******************/
template <SpaceType XSTYPE>
struct OutRangeMaker
{};
template <>
struct OutRangeMaker<SpaceType::ANY>
{
template <class MapF, class ORType>
static void mk(std::shared_ptr<ORType>& outRange, Array<size_t,ORType>& mapMult, const MapF& mapf)
{
std::map<typename MapF::value_type,size_t> mult;
for(auto ii = mapf.begin(); ii.max() != ii.pos(); ++ii) {
mult[mapf[ii]]++;
}
vector<typename MapF::value_type> outmeta(mult.size());
vector<size_t> outmult(mult.size());
size_t cnt = 0;
for(auto& x: mult){
outmeta[cnt] = x.first;
outmult[cnt] = x.second;
++cnt;
}
typename ORType::FType orf(outmeta);
outRange = std::dynamic_pointer_cast<ORType>( orf.create() );
mapMult = Array<size_t,ORType>( outRange, outmult );
}
};
template <>
struct OutRangeMaker<SpaceType::NONE>
{
template <class MapF, class ORType>
static void mk(std::shared_ptr<ORType>& outRange, Array<size_t,ORType>& mapMult, const MapF& mapf)
{
static_assert( std::is_same<size_t,typename MapF::value_type>::value,
"out range value type for NONE must be size_t" );
size_t max = 0;
for(auto ii = mapf.begin(); ii.max() != ii.pos(); ++ii) {
max = mapf[ii]+1 > max ? mapf[ii]+1 : max;
}
vector<size_t> mult(max,0);
for(auto ii = mapf.begin(); ii.max() != ii.pos(); ++ii) {
mult[mapf[ii]]++;
}
vector<size_t> outmult(mult.size());
size_t cnt = 0;
for(auto& x: mult){
outmult[cnt++] = x;
}
typename ORType::FType orf(max);
outRange = std::dynamic_pointer_cast<ORType>( orf.create() );
mapMult = Array<size_t,ORType>( outRange, outmult );
}
};
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class MA>
void GenMapRange<ORType,Op,XSTYPE,Ranges...>::mkOutRange(const MA& mapf)
{
//FunctionalArray<typename MapF::value_type,MapF,Ranges...> fma(mSpace, mMapf);
OutRangeMaker<XSTYPE>::mk(mOutRange,mMapMult,mapf);
auto i = mapf.begin();
mMapPos.resize(i.max());
for(; i.pos() != i.max(); ++i){
mMapPos[i.pos()] = mOutRange->getMeta( mapf[i] );
}
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class MA>
GenMapRange<ORType,Op,XSTYPE,Ranges...>::GenMapRange(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& mapf,
const std::shared_ptr<Ranges>&... rs) :
mSpace(std::make_tuple(rs...)),
mMapf(std::get<0>(mapf)),
mOutRange(outr),
mMapMult(mOutRange,0),
mMapPos(std::get<1>(mapf).size(),mOutRange->size())
{
auto& ma = std::get<1>(mapf);
auto jj = mMapMult.begin();
for(auto ii = ma.begin(); ii.pos() != ii.max(); ++ii){
++mMapMult[jj.at(ma[ii])];
mMapPos[ii.pos()] = jj.pos();
}
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class MA>
GenMapRange<ORType,Op,XSTYPE,Ranges...>::GenMapRange(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& mapf,
const Space& space) :
mSpace(space),
mMapf(std::get<0>(mapf)),
mOutRange(outr),
mMapMult(mOutRange,0),
mMapPos(std::get<1>(mapf).size(),mOutRange->size())
{
auto& ma = std::get<1>(mapf);
auto jj = mMapMult.begin();
for(auto ii = ma.begin(); ii.pos() != ii.max(); ++ii){
++mMapMult[jj.at(ma[ii])];
mMapPos[ii.pos()] = jj.pos();
}
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class MA>
GenMapRange<ORType,Op,XSTYPE,Ranges...>::GenMapRange(const std::tuple<Op,MA>& mapf,
const std::shared_ptr<Ranges>&... rs) :
mSpace(std::make_tuple(rs...)),
mMapf(std::get<0>(mapf))
{
mkOutRange(std::get<1>(mapf));
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class MA>
GenMapRange<ORType,Op,XSTYPE,Ranges...>::GenMapRange(const std::tuple<Op,MA>& mapf, const Space& space) :
mSpace( space ),
mMapf(std::get<0>(mapf))
{
mkOutRange(std::get<1>(mapf));
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <size_t N>
auto GenMapRange<ORType,Op,XSTYPE,Ranges...>::get() const -> decltype( *std::get<N>( mSpace ) )&
{
return *std::get<N>(mSpace);
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <size_t N>
auto GenMapRange<ORType,Op,XSTYPE,Ranges...>::getPtr() const -> decltype( std::get<N>( mSpace ) )&
{
return std::get<N>(mSpace);
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
auto GenMapRange<ORType,Op,XSTYPE,Ranges...>::outRange() const -> std::shared_ptr<ORType>
{
return mOutRange;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
const Op& GenMapRange<ORType,Op,XSTYPE,Ranges...>::map() const
{
return mMapf;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
size_t GenMapRange<ORType,Op,XSTYPE,Ranges...>::dim() const
{
return sdim;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
size_t GenMapRange<ORType,Op,XSTYPE,Ranges...>::size() const
{
return mOutRange->size();
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
SpaceType GenMapRange<ORType,Op,XSTYPE,Ranges...>::spaceType() const
{
return SpaceType::ANY;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
const typename GenMapRange<ORType,Op,XSTYPE,Ranges...>::Space& GenMapRange<ORType,Op,XSTYPE,Ranges...>::space() const
{
return mSpace;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
vector<size_t> GenMapRange<ORType,Op,XSTYPE,Ranges...>::typeNum() const
{
vector<size_t> o;
RangeHelper::getTypeNum<sizeof...(Ranges)-1>(o,mSpace);
return o;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
size_t GenMapRange<ORType,Op,XSTYPE,Ranges...>::cmeta(char* target, size_t pos) const
{
//MetaType* xtarget = reinterpret_cast<MetaType*>(target);
assert(0);
return 0;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
size_t GenMapRange<ORType,Op,XSTYPE,Ranges...>::cmetaSize() const
{
return RangeHelper::getCMetaSize<0>(mSpace);
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
std::string GenMapRange<ORType,Op,XSTYPE,Ranges...>::stringMeta(size_t pos) const
{
auto i = begin();
i = pos;
return "[ " + RangeHelper::getStringMeta<0>(i) + " ]";
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
vector<char> GenMapRange<ORType,Op,XSTYPE,Ranges...>::data() const
{
DataHeader h = dataHeader();
vector<char> out;
//out.reserve(h.metaSize + sizeof(DataHeader));
char* hcp = reinterpret_cast<char*>(&h);
out.insert(out.end(), hcp, hcp + sizeof(DataHeader));
sfor_pn<0,sizeof...(Ranges)>
( [&](auto i) {
vector<char> part = std::get<i>(mSpace)->data();
out.insert(out.end(), part.begin(), part.end());
return 0;
} );
return out;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
DataHeader GenMapRange<ORType,Op,XSTYPE,Ranges...>::dataHeader() const
{
DataHeader h;
h.spaceType = static_cast<int>( SpaceType::ANY );
h.metaSize = sizeof...(Ranges);
h.multiple = 1;
return h;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
typename GenMapRange<ORType,Op,XSTYPE,Ranges...>::IndexType GenMapRange<ORType,Op,XSTYPE,Ranges...>::begin() const
{
GenMapIndex<typename ORType::IndexType,Op,XSTYPE,typename Ranges::IndexType...>
i( std::dynamic_pointer_cast<GenMapRange<ORType,Op,XSTYPE,Ranges...> >
( std::shared_ptr<RangeBase>( RB::mThis ) ) );
i = 0;
return i;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
typename GenMapRange<ORType,Op,XSTYPE,Ranges...>::IndexType GenMapRange<ORType,Op,XSTYPE,Ranges...>::end() const
{
GenMapIndex<typename ORType::IndexType,Op,XSTYPE,typename Ranges::IndexType...>
i( std::dynamic_pointer_cast<GenMapRange<ORType,Op,XSTYPE,Ranges...> >
( std::shared_ptr<RangeBase>( RB::mThis )) );
i = size();
return i;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
auto GenMapRange<ORType,Op,XSTYPE,Ranges...>::mapMultiplicity() const
-> const Array<size_t,ORType>&
{
return mMapMult;
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
auto GenMapRange<ORType,Op,XSTYPE,Ranges...>::explMapMultiplicity() const
-> ConstSlice<size_t,GenMapRange>
{
/*
auto tmp = mMapMult;
return tmp.format( std::dynamic_pointer_cast<GenMapRange<ORType,Op,XSTYPE,Ranges...> >
( std::shared_ptr<RangeBase>( RB::mThis )) );
*/
return mMapMult.slformat(std::dynamic_pointer_cast<GenMapRange<ORType,Op,XSTYPE,Ranges...> >
( std::shared_ptr<RangeBase>( RB::mThis )));
}
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
vector<size_t> GenMapRange<ORType,Op,XSTYPE,Ranges...>::mapPos() const
{
return mMapPos;
}
/*
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
template <class... ERanges>
auto GenMapRange<ORType,Op,XSTYPE,Ranges...>::cat(const std::shared_ptr<MapRange<ERanges...> >& erange)
-> std::shared_ptr<GenMapRange<Ranges...,ERanges...> >
{
auto crange = std::tuple_cat(mSpace, erange->space());
MapRangeFactory<Ranges...,ERanges...> rf(crange);
return std::dynamic_pointer_cast<MapRange<Ranges...,ERanges...> >(rf.create());
}
*/
}

354
src/include/map_range.h Normal file
View file

@ -0,0 +1,354 @@
// -*- C++ -*-
#ifndef __cxz_map_range_h__
#define __cxz_map_range_h__
#include <cstdlib>
#include <tuple>
#include <memory>
#include <map>
#include "mbase_def.h"
#include "ranges/range_base.h"
#include "ranges/index_base.h"
#include "map_range_factory_product_map.h"
#include "ranges/x_to_string.h"
#include "ranges/type_map.h"
#include "xfor/xfor.h"
namespace CNORXZ
{
namespace
{
using namespace CNORXZInternal;
}
template <class Func, class... Indices>
auto mkMapOp(const std::shared_ptr<Func>& func,
const std::shared_ptr<Indices>&... is)
-> decltype(std::make_tuple(FunctionalArray<typename Func::value_type,Func,
typename Indices::RangeType...>().exec(is...),
FunctionalArray<typename Func::value_type,Func,
typename Indices::RangeType...>()))
{
typedef FunctionalArray<typename Func::value_type,Func,typename Indices::RangeType...> FMA;
if(Func::FISSTATIC){
FMA fma(is->range()...);
return std::make_tuple(fma.exec(is...),fma);
}
else {
FMA fma(is->range()...,func);
return std::make_tuple(fma.exec(is...),fma);
}
}
template <class Op, class Index, class Expr, SpaceType STYPE = SpaceType::ANY>
//template <class MapF, class IndexPack, class Expr, SpaceType STYPE = SpaceType::ANY>
class OpExpr : public ExpressionBase
{
public:
//typedef typename Index::OIType OIType;
//typedef SingleIndex<typename Op::value_type,STYPE> OIType;
static constexpr size_t LAYER = Expr::LAYER + 1;
static constexpr size_t SIZE = Expr::SIZE + Op::SIZE;
static constexpr size_t NHLAYER = Expr::NHLAYER + 1;
private:
OpExpr() = default;
const Index* mIndPtr;
//const OIType* mIndPtr;
size_t mSPos;
size_t mMax;
size_t mStep;
Expr mExpr;
Op mOp;
typedef decltype(mOp.rootSteps(std::declval<intptr_t>()).extend( mExpr.rootSteps(std::declval<intptr_t>()) )) ExtType;
ExtType mExt;
public:
OpExpr(const OpExpr& in) = default;
OpExpr(OpExpr&& in) = default;
OpExpr& operator=(const OpExpr& in) = default;
OpExpr& operator=(OpExpr&& in) = default;
OpExpr(const Op& mapf, const Index* ind, size_t step, Expr ex);
virtual std::shared_ptr<ExpressionBase> deepCopy() const override final;
template <size_t VS>
inline auto vec() const { return *this; }
inline void operator()(size_t mlast, DExt last) override final;
inline void operator()(size_t mlast, ExtType last);
inline void operator()(size_t mlast = 0) override final;
auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType;
virtual DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final;
virtual DExt dExtension() const override final;
};
template <class OIType, class Op, SpaceType XSTYPE, class... Indices>
class GenMapIndex : public IndexInterface<GenMapIndex<OIType,Op,XSTYPE,Indices...>,
typename Op::value_type>
//std::tuple<typename Indices::MetaType...> >
{
public:
typedef IndexInterface<GenMapIndex<OIType,Op,XSTYPE,Indices...>,
typename Op::value_type> IB;
//std::tuple<typename Indices::MetaType...> > IB;
typedef std::tuple<std::shared_ptr<Indices>...> IndexPack;
//typedef std::tuple<typename Indices::MetaType...> MetaType;
typedef typename Op::value_type MetaType;
typedef GenMapRange<typename OIType::RangeType,Op,XSTYPE,typename Indices::RangeType...> RangeType;
typedef GenMapIndex IType;
//typedef SingleIndex<typename Op::value_type,XSTYPE> OIType;
static constexpr IndexType sType() { return IndexType::SINGLE; }
static constexpr size_t sDim() { return sizeof...(Indices); }
static constexpr size_t totalDim() { return (... * Indices::totalDim()); }
static void check_type() { static_assert( std::is_same<typename OIType::MetaType,typename Op::value_type>::value, "inconsitent value types" ); }
static constexpr SpaceType STYPE = XSTYPE;
static constexpr bool PARALLEL = false;
private:
IndexPack mIPack;
std::array<size_t,sizeof...(Indices)+1> mBlockSizes;
std::shared_ptr<OIType> mOutIndex;
public:
const IndexPack& pack() const { return mIPack; }
GenMapIndex() = delete;
// NO DEFAULT HERE !!!
// ( have to assign sub-indices (ptr!) correctly )
//MapIndex(const MapIndex& in);
//MapIndex& operator=(const MapIndex& in);
template <class MRange>
GenMapIndex(const std::shared_ptr<MRange>& range);
template <size_t DIR>
GenMapIndex& up();
template <size_t DIR>
GenMapIndex& down();
template <size_t N>
auto get() const -> decltype( *std::get<N>( mIPack ) )&;
template <size_t N>
auto getPtr() const -> decltype( std::get<N>( mIPack ) )&;
template <size_t N>
size_t getBlockSize() const { return std::get<N>(mBlockSizes); }
std::shared_ptr<OIType> outIndex() const;
// raplace instances (in contrast to its analogon in ConstContainerIndex
// MultiIndices CANNOT be influences be its subindices, so there is
// NO foreign/external controll)
// Do NOT share index instances between two or more MapIndex instances
GenMapIndex& operator()(const std::shared_ptr<Indices>&... indices);
GenMapIndex& operator()(const std::tuple<std::shared_ptr<Indices>...>& indices);
// ==== >>>>> STATIC POLYMORPHISM <<<<< ====
IndexType type() const;
GenMapIndex& operator=(size_t pos);
GenMapIndex& operator++();
GenMapIndex& operator--();
int pp(std::intptr_t idxPtrNum);
int mm(std::intptr_t idxPtrNum);
std::string stringMeta() const;
MetaType meta() const;
GenMapIndex& at(const MetaType& metaPos);
size_t posAt(const MetaType& metaPos) const;
size_t dim() const;
bool first() const;
bool last() const;
std::shared_ptr<RangeType> range() const;
template <size_t N>
auto getPtr() -> decltype( std::get<N>( mIPack ) )&;
size_t getStepSize(size_t n) const;
template <class Exprs>
auto ifor(size_t step, Exprs exs) const; // first step arg not used!
template <class Exprs>
auto pifor(size_t step, Exprs exs) const; // NO MULTITHREADING
template <class Exprs>
auto iforh(size_t step, Exprs exs) const;
};
/*************************
* MapRangeFactory *
*************************/
// NOT THREAD SAVE
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
class GenMapRangeFactory : public RangeFactoryBase
{
public:
//typedef SingleRange<typename Op::value_type,XSTYPE> ORType;
typedef GenMapRange<ORType,Op,XSTYPE,Ranges...> oType;
GenMapRangeFactory() = delete;
template <class MA>
GenMapRangeFactory(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& mapf,
const std::shared_ptr<Ranges>&... rs);
template <class MA>
GenMapRangeFactory(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& mapf,
const typename GenMapRange<ORType,Op,XSTYPE,Ranges...>::Space& st);
template <class MA>
GenMapRangeFactory(const std::tuple<Op,MA>& mapf, const std::shared_ptr<Ranges>&... rs);
template <class MA>
GenMapRangeFactory(const std::tuple<Op,MA>& mapf,
const typename GenMapRange<ORType,Op,XSTYPE,Ranges...>::Space& space);
virtual std::shared_ptr<RangeBase> create() override;
private:
std::shared_ptr<RangeBase> checkIfCreated(const std::tuple<std::shared_ptr<Ranges>...>& ptp);
};
/******************
* MapRange *
******************/
template <class ORType, class Op, SpaceType XSTYPE, class... Ranges>
class GenMapRange : public RangeInterface<GenMapIndex<typename ORType::IndexType,Op,XSTYPE,typename Ranges::IndexType...> >
{
public:
typedef RangeBase RB;
typedef std::tuple<std::shared_ptr<Ranges>...> Space;
typedef GenMapIndex<typename ORType::IndexType,Op,XSTYPE,typename Ranges::IndexType...> IndexType;
typedef typename Op::value_type MetaType;
protected:
GenMapRange() = delete;
GenMapRange(const GenMapRange& in) = delete;
GenMapRange& operator=(const GenMapRange& in) = delete;
template <class MA>
GenMapRange(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& mapf,
const std::shared_ptr<Ranges>&... rs);
template <class MA>
GenMapRange(const std::shared_ptr<ORType>& outr, const std::tuple<Op,MA>& mapf,
const Space& space);
template <class MA>
GenMapRange(const std::tuple<Op,MA>& mapf, const Space& space);
template <class MA>
GenMapRange(const std::tuple<Op,MA>& mapf, const std::shared_ptr<Ranges>&... rs);
Space mSpace;
Op mMapf;
//Op mMapf;
std::shared_ptr<ORType> mOutRange;
Array<size_t,ORType> mMapMult;
vector<size_t> mMapPos;
private:
template <class MA>
void mkOutRange(const MA& mapf);
public:
static constexpr size_t sdim = sizeof...(Ranges);
template <size_t N>
auto get() const -> decltype( *std::get<N>( mSpace ) )&;
template <size_t N>
auto getPtr() const -> decltype( std::get<N>( mSpace ) )&;
std::shared_ptr<ORType> outRange() const;
const Op& map() const;
virtual size_t dim() const final;
virtual size_t size() const final;
virtual SpaceType spaceType() const final;
virtual DataHeader dataHeader() const final;
virtual vector<size_t> typeNum() const final;
virtual size_t cmeta(char* target, size_t pos) const final;
virtual size_t cmetaSize() const final;
virtual std::string stringMeta(size_t pos) const final;
virtual vector<char> data() const final;
const Space& space() const;
virtual IndexType begin() const final;
virtual IndexType end() const final;
const Array<size_t,ORType>& mapMultiplicity() const;
ConstSlice<size_t,GenMapRange> explMapMultiplicity() const;
vector<size_t> mapPos() const;
/*
template <class... ERanges>
auto cat(const std::shared_ptr<GenMapRange<ERanges...> >& erange)
-> std::shared_ptr<GenMapRange<Ranges...,ERanges...> >;
*/
friend GenMapRangeFactory<ORType,Op,XSTYPE,Ranges...>;
static constexpr bool HASMETACONT = false;
static constexpr bool defaultable = false;
static constexpr size_t ISSTATIC = Op::ISSTATIC & (... & Ranges::ISSTATIC);
static constexpr size_t SIZE = Op::SIZE * (... * Ranges::SIZE);
};
// for legacy
template <class OIType, class Op, class... Indices>
using MapIndex = GenMapIndex<OIType,Op,SpaceType::ANY,Indices...>;
template <class ORType, class Op, class... Ranges>
using MapRangeFactory = GenMapRangeFactory<ORType,Op,SpaceType::ANY,Ranges...>;
template <class ORType, class Op, class... Ranges>
using MapRange = GenMapRange<ORType,Op,SpaceType::ANY,Ranges...>;
template <class OIType, class Op, class... Indices>
auto mapResult/*<MapIndex<Op,Indices...> >*/(const std::shared_ptr<MapIndex<OIType,Op,Indices...> >& ind)
-> decltype(ind->outIndex())
{
return ind->outIndex();
}
}
#endif

View file

@ -0,0 +1,26 @@
#ifndef __cxz_map_range_factory_product_map_h__
#define __cxz_map_range_factory_product_map_h__
#include <memory>
#include <vector>
#include <map>
#include "ranges/rbase_def.h"
#include "mbase_def.h"
namespace CNORXZ
{
class MapRangeFactoryProductMap
{
public:
template <class ORType, class MapF, SpaceType XSTYPE, class... Ranges>
friend class GenMapRangeFactory;
private:
static std::map<std::shared_ptr<RangeBase>,vector<std::intptr_t> > mAleadyCreated;
};
}
#endif

104
src/include/mbase_def.h Normal file
View file

@ -0,0 +1,104 @@
#ifndef __cxz_mbase_def_h__
#define __cxz_mbase_def_h__
#include "ranges/rbase_def.h"
#include "allocator.h"
namespace CNORXZ
{
/***********************
* Provided Types *
***********************/
template <class... Ranges>
using ContainerRangeFactory = MultiRangeFactory<Ranges...>;
template <class... Ranges>
using ContainerRange = MultiRange<Ranges...>;
// container_index.h
template <typename T, class... Indices>
class ConstContainerIndex;
// cxz_array.h
template <typename T, class... SRanges>
class ArrayBase;
// cxz_array.h
template <typename T, class... SRanges>
class MutableArrayBase;
// cxz_array.h
template <typename T, class... SRanges>
class Array;
// cxz_operation.h
template <typename T, class OperationClass>
class OperationBase;
// cxz_operation.h
template <typename T, class OperationClass>
class OperationTemplate;
// cxz_operation.h
template <typename T, class... Ranges>
class OperationRoot;
// cxz_operation.h
template <typename T, class... Ranges>
class ParallelOperationRoot;
// cxz_operation.h
template <typename T>
class OperationValue;
// cxz_operation.h
template <typename T, class... Ranges>
class ConstOperationRoot;
// cxz_operation.h
template <typename T, class Op>
class OperationPointer;
// cxz_operation.h
template <typename T, class OpFunction, class... Ops>
class Operation;
// cxz_operation.h
template <typename T, class Op, class IndexType>
class Contraction;
// cxz_operation.h
template <typename T, class Op, class... Indices>
class SliceContraction;
// slice.h
template <typename T, class... SRanges>
class Slice;
template <typename T, class... SRanges>
class ConstSlice;
// slice.h
template <typename T, class... SRanges>
class SliceDef;
// slice.h
template <typename T, class... SRanges>
class ConstSliceDef;
// map_range.h
template <class OITpye, class MapF, SpaceType XSTYPE, class... Indices>
class GenMapIndex;
// map_range.h
template <class ORType, class MapF, SpaceType XSTYPE, class... Ranges>
class GenMapRangeFactory;
// map_range.h
template <class ORType, class MapF, SpaceType XSTYPE, class... Ranges>
class GenMapRange;
}
#endif

View file

@ -1,56 +0,0 @@
// -*- C++ -*-
/**
@file include/memory/allocator.cc.h
@brief Allocator template member function implementation
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_allocator_cc_h__
#define __cxz_allocator_cc_h__
#include "allocator.h"
#include "memcount.h"
namespace CNORXZ
{
template <typename T>
T* Allocator<T>::allocate(SizeT n)
{
const SizeT nn = n*type_size;
MemCount::add(nn);
const SizeT off = nn%N;
const SizeT nnx = (off == 0) ? nn : nn + N - off;
const SizeT nnd = nnx/N;
VX* vx = new VX[nnd];
return reinterpret_cast<T*>(vx);
}
template <typename T>
void Allocator<T>::deallocate(T* p, SizeT n)
{
const SizeT nn = n*type_size;
MemCount::sub(nn);
VX* vx = reinterpret_cast<VX*>(p);
delete [] vx;
}
template <class T, class U>
bool operator==(const Allocator<T>& a, const Allocator<U>& b)
{
return true;
}
template <class T, class U>
bool operator!=(const Allocator<T>& a, const Allocator<U>& b)
{
return false;
}
}
#endif

View file

@ -1,85 +0,0 @@
// -*- C++ -*-
/**
@file include/memory/allocator.h
@brief Allocator declaration
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_allocator__
#define __cxz_allocator__
#include <cstdlib>
#include <new>
#include <vector>
#include <cstdint>
#include <cassert>
#include <iostream>
#include "base/types.h"
#include "base/intrin.h"
#define MIB_SIZE 1024*1024 // 1MiB
#define WARN_SIZE MIB_SIZE*100 // 100 MiB
namespace CNORXZ
{
/** *****
Allocator implementation
Takes care of proper alignment
*/
template <typename T>
class Allocator
{
public:
typedef T value_type;
static constexpr SizeT type_size = sizeof(T); /** < type size */
static constexpr SizeT N = MAX_VSIZE; /** < size of the larges available intrinsics vector */
/** ***
Aligned data block type
The size equals the maximal intrinsics vectors size
*/
struct VX
{
alignas(N) char x[N];
};
/** default constructor */
Allocator() = default;
/** (copy) construct from allocator for different data type
@tparam U input data type
@param x input allocator
*/
template <typename U>
Allocator(const Allocator<U>& x) {}
/** allocate n element of type T
@param n number of elements
*/
T* allocate(SizeT n);
/** deallocate n elements
@param p pointer to first element
@param n number of elements
*/
void deallocate(T* p, SizeT n);
};
/** compare two cnorxz allocators; equality check returns always true */
template <class T, class U>
bool operator==(const Allocator<T>& a, const Allocator<U>& b);
/** compare two cnorxz allocators; unequality check returns always false */
template <class T, class U>
bool operator!=(const Allocator<T>& a, const Allocator<U>& b);
} // namespace CNORXZ
#endif

View file

@ -1,53 +0,0 @@
// -*- C++ -*-
/**
@file include/memory/memcount.h
@brief MemCount declaration.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_memcount_h__
#define __cxz_memcount_h__
#include "base/types.h"
namespace CNORXZ
{
/** *****
Static class to track memory usage by cnorxz types
The usage variable can be changed only be an Allocator instance
@see Allocator
**/
class MemCount
{
private:
static SizeT sMemUsage; /**< current memory usage (bytes) */
/** increas memory usage
@param x number of bytes
*/
static void add(SizeT x);// { sMemUsage += x; }
/** decreas memory usage
@param x number of bytes
*/
static void sub(SizeT x);// { sMemUsage -= x; }
public:
/** no instance construction (static) */
MemCount() = delete;
/** return current memory usage (bytes) */
static SizeT usage();
template <typename T>
friend class Allocator;
};
} // namespace CNORXZ
#endif

View file

@ -1,12 +0,0 @@
// -*- C++ -*-
/**
@file include/memory/memory.cc.h
@brief Memory template implementations main header.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "allocator.cc.h"

View file

@ -1,15 +0,0 @@
// -*- C++ -*-
/**
@file include/memory/memory.h
@brief Memory main heade.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "allocator.h"
#include "memcount.h"
#include "memory.cc.h"

View file

@ -0,0 +1,72 @@
#include "op_expressions.h"
namespace CNORXZ
{
namespace
{
using namespace CNORXZInternal;
}
/************************
* AssignmentExpr *
************************/
template <OpIndexAff OIA, class ExtType>
inline size_t opIndexResolve(size_t start, ExtType last)
{
if constexpr(OIA == OpIndexAff::EXTERN){
return last.val();
}
if constexpr(OIA == OpIndexAff::TARGET){
return start;
}
return 0;
}
template <typename T, class Func, class AT, class Target, class OpClass, OpIndexAff OIA>
AssignmentExpr<T,Func,AT,Target,OpClass,OIA>::AssignmentExpr(const AccessTemplate<AT>& dataAcc, const Target& tar, const OpClass& sec) :
mTar(tar), mSec(sec), mDataAcc(static_cast<const AT&>(dataAcc)) {}
template <typename T, class Func, class AT, class Target, class OpClass, OpIndexAff OIA>
inline void AssignmentExpr<T,Func,AT,Target,OpClass,OIA>::operator()(size_t start)
{
ExtType last = rootSteps();
last.zero();
// TODO: ask MA container for data (ptr)!!!
mDataAcc.template exec<Func>(opIndexResolve<OIA>(start,last),mSec,last.next());
}
template <typename T, class Func, class AT, class Target, class OpClass, OpIndexAff OIA>
inline void AssignmentExpr<T,Func,AT,Target,OpClass,OIA>::operator()(size_t start, ExtType last)
{
mDataAcc.template exec<Func>(opIndexResolve<OIA>(start,last),mSec,last.next());
}
template <typename T, class Func, class AT, class Target, class OpClass, OpIndexAff OIA>
typename AssignmentExpr<T,Func,AT,Target,OpClass,OIA>::ExtType
AssignmentExpr<T,Func,AT,Target,OpClass,OIA>::rootSteps(std::intptr_t iPtrNum) const
{
return mTar.rootSteps(iPtrNum).extend( mSec.rootSteps(iPtrNum) );
}
template <typename T, class Func, class AT, class Target, class OpClass, OpIndexAff OIA>
inline void AssignmentExpr<T,Func,AT,Target,OpClass,OIA>::operator()(size_t mlast, DExt last)
{
(*this)(mlast, std::dynamic_pointer_cast<ExtT<ExtType>>(last)->ext());
}
template <typename T, class Func, class AT, class Target, class OpClass, OpIndexAff OIA>
inline DExt AssignmentExpr<T,Func,AT,Target,OpClass,OIA>::dRootSteps(std::intptr_t iPtrNum) const
{
return std::make_shared<ExtT<ExtType>>(rootSteps(iPtrNum));
}
template <typename T, class Func, class AT, class Target, class OpClass, OpIndexAff OIA>
inline DExt AssignmentExpr<T,Func,AT,Target,OpClass,OIA>::dExtension() const
{
return nullptr; //???!!!
}
} // namespace CNORXZ

View file

@ -0,0 +1,60 @@
#ifndef __cxz_op_expressions__
#define __cxz_op_expressions__
#include "xfor/xfor.h"
#include "access.h"
namespace CNORXZ
{
namespace
{
using namespace CNORXZInternal;
}
enum class OpIndexAff {
EXTERN = 0,
TARGET = 1
};
template <typename T, class Func, class AT, class Target, class OpClass, OpIndexAff OIA=OpIndexAff::EXTERN>
class AssignmentExpr : public ExpressionBase
{
private:
AssignmentExpr() = default;
Target mTar;
OpClass mSec;
AT mDataAcc;
public:
static constexpr size_t LAYER = 0;
static constexpr size_t NHLAYER = 0;
static constexpr size_t SIZE = Target::SIZE + OpClass::SIZE;
typedef decltype(mTar.rootSteps(0).extend( mSec.rootSteps(0) )) ExtType;
AssignmentExpr(const AccessTemplate<AT>& dataAcc, const Target& tar, const OpClass& sec);
AssignmentExpr(const AssignmentExpr& in) = default;
AssignmentExpr(AssignmentExpr&& in) = default;
AssignmentExpr& operator=(const AssignmentExpr& in) = default;
AssignmentExpr& operator=(AssignmentExpr&& in) = default;
virtual std::shared_ptr<ExpressionBase> deepCopy() const override final
{
return std::make_shared<AssignmentExpr<T,Func,AT,Target,OpClass,OIA>>(*this);
}
inline void operator()(size_t start = 0);
inline void operator()(size_t start, ExtType last);
auto rootSteps(std::intptr_t iPtrNum = 0) const -> ExtType;
inline void operator()(size_t mlast, DExt last) override final;
inline DExt dRootSteps(std::intptr_t iPtrNum = 0) const override final;
inline DExt dExtension() const override final;
};
} // namespace CNORXZ
#endif

View file

@ -1,109 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/basic_operations.cc.h
@brief Basic operations implementation
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_basic_operations_cc_h__
#define __cxz_basic_operations_cc_h__
#include "basic_operations.h"
namespace CNORXZ
{
/*==================================+
| standard operatrions (unary) |
+==================================*/
template <class Op>
constexpr decltype(auto) minus(const COpInterface<Op>& op)
{
return operation( [](const auto& a) { return -a; }, op.THIS() );
}
/*===================================+
| standard operatrions (binary) |
+===================================*/
template <class Op1, class Op2>
constexpr decltype(auto) plus(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return operation( [](const auto& a, const auto& b) { return a + b; },
op1.THIS(), op2.THIS() );
}
template <class Op1, class Op2>
constexpr decltype(auto) minus(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return operation( [](const auto& a, const auto& b) { return a - b; },
op1.THIS(), op2.THIS() );
}
template <class Op1, class Op2>
constexpr decltype(auto) multiplies(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return operation( [](const auto& a, const auto& b) { return a * b; },
op1.THIS(), op2.THIS() );
}
template <class Op1, class Op2>
constexpr decltype(auto) divides(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return operation( [](const auto& a, const auto& b) { return a / b; },
op1.THIS(), op2.THIS() );
}
template <class Op1, class Op2>
constexpr decltype(auto) modulo(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return operation( [](const auto& a, const auto& b) { return a % b; },
op1.THIS(), op2.THIS() );
}
/*=======================================+
| operators for standard operations |
+=======================================*/
template <class Op>
constexpr decltype(auto) operator-(const COpInterface<Op>& op)
{
return minus(op);
}
template <class Op1, class Op2>
constexpr decltype(auto) operator+(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return plus(op1, op2);
}
template <class Op1, class Op2>
constexpr decltype(auto) operator-(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return minus(op1, op2);
}
template <class Op1, class Op2>
constexpr decltype(auto) operator*(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return multiplies(op1, op2);
}
template <class Op1, class Op2>
constexpr decltype(auto) operator/(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return divides(op1, op2);
}
template <class Op1, class Op2>
constexpr decltype(auto) operator%(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2)
{
return modulo(op1, op2);
}
}
#endif

View file

@ -1,65 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/basic_operations.h
@brief Basic operations declaration
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_basic_operations_h__
#define __cxz_basic_operations_h__
#include "base/base.h"
#include "operation.h"
namespace CNORXZ
{
// standard operations:
// unary:
template <class Op>
constexpr decltype(auto) minus(const COpInterface<Op>& op);
// binary:
template <class Op1, class Op2>
constexpr decltype(auto) plus(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
template <class Op1, class Op2>
constexpr decltype(auto) minus(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
template <class Op1, class Op2>
constexpr decltype(auto) multiplies(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
template <class Op1, class Op2>
constexpr decltype(auto) divides(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
template <class Op1, class Op2>
constexpr decltype(auto) modulo(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
// operators for standard operations:
template <class Op>
constexpr decltype(auto) operator-(const COpInterface<Op>& op);
template <class Op1, class Op2>
constexpr decltype(auto) operator+(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
template <class Op1, class Op2>
constexpr decltype(auto) operator-(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
template <class Op1, class Op2>
constexpr decltype(auto) operator*(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
template <class Op1, class Op2>
constexpr decltype(auto) operator/(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
template <class Op1, class Op2>
constexpr decltype(auto) operator%(const COpInterface<Op1>& op1, const COpInterface<Op2>& op2);
}
#endif

View file

@ -1,279 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/extensions/avx.cc.h
@brief Register type implementaions for AVX.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_avx_cc_h__
#define __cxz_avx_cc_h__
#include "avx.h"
namespace CNORXZ
{
/*=====================+
| PlusCC / PlusCX |
+=====================*/
inline decltype(auto)
PlusCC<Double,Double,AVX::ND>::eval(const Consecutive<Double,AVX::ND>& a,
const Consecutive<Double,AVX::ND>& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_add_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
inline decltype(auto)
PlusCC<Double,Double,AVX::ND>::aeval(Consecutive<Double,AVX::ND>& a,
const Consecutive<Double,AVX::ND>& b)
{
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_add_pd(av, bv);
_mm256_store_pd(a.mD, ov);
return a;
}
template <typename X>
inline decltype(auto)
PlusCX<Double,X,AVX::ND>::eval(const Consecutive<Double,AVX::ND>& a,
const X& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_set1_pd( static_cast<Double>(b) );
__m256d ov = _mm256_add_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
template <typename X>
inline decltype(auto)
PlusCX<Double,X,AVX::ND>::aeval(Consecutive<Double,AVX::ND>& a, const X& b)
{
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_set1_pd( static_cast<Double>(b) );
__m256d ov = _mm256_add_pd(av, bv);
_mm256_store_pd(a.mD, ov);
return a;
}
template <typename X>
inline decltype(auto)
PlusCX<Double,X,AVX::ND>::eval(const X& a,
const Consecutive<Double,AVX::ND>& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_set1_pd( static_cast<Double>(a) );
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_add_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
/*=======================+
| MinusCC / MinusCX |
+=======================*/
inline decltype(auto)
MinusCC<Double,Double,AVX::ND>::eval(const Consecutive<Double,AVX::ND>& a,
const Consecutive<Double,AVX::ND>& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_sub_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
inline decltype(auto)
MinusCC<Double,Double,AVX::ND>::aeval(Consecutive<Double,AVX::ND>& a,
const Consecutive<Double,AVX::ND>& b)
{
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_sub_pd(av, bv);
_mm256_store_pd(a.mD, ov);
return a;
}
template <typename X>
inline decltype(auto)
MinusCX<Double,X,AVX::ND>::eval(const Consecutive<Double,AVX::ND>& a,
const X& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_set1_pd( static_cast<Double>(b) );
__m256d ov = _mm256_sub_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
template <typename X>
inline decltype(auto)
MinusCX<Double,X,AVX::ND>::aeval(Consecutive<Double,AVX::ND>& a, const X& b)
{
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_set1_pd( static_cast<Double>(b) );
__m256d ov = _mm256_sub_pd(av, bv);
_mm256_store_pd(a.mD, ov);
return a;
}
template <typename X>
inline decltype(auto)
MinusCX<Double,X,AVX::ND>::eval(const X& a,
const Consecutive<Double,AVX::ND>& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_set1_pd( static_cast<Double>(a) );
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_sub_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
/*=================================+
| MultipliesCC / MultipliesCX |
+=================================*/
inline decltype(auto)
MultipliesCC<Double,Double,AVX::ND>::eval(const Consecutive<Double,AVX::ND>& a,
const Consecutive<Double,AVX::ND>& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_mul_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
inline decltype(auto)
MultipliesCC<Double,Double,AVX::ND>::aeval(Consecutive<Double,AVX::ND>& a,
const Consecutive<Double,AVX::ND>& b)
{
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_mul_pd(av, bv);
_mm256_store_pd(a.mD, ov);
return a;
}
template <typename X>
inline decltype(auto)
MultipliesCX<Double,X,AVX::ND>::eval(const Consecutive<Double,AVX::ND>& a,
const X& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_set1_pd( static_cast<Double>(b) );
__m256d ov = _mm256_mul_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
template <typename X>
inline decltype(auto)
MultipliesCX<Double,X,AVX::ND>::aeval(Consecutive<Double,AVX::ND>& a,
const X& b)
{
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_set1_pd( static_cast<Double>(b) );
__m256d ov = _mm256_mul_pd(av, bv);
_mm256_store_pd(a.mD, ov);
return a;
}
template <typename X>
inline decltype(auto)
MultipliesCX<Double,X,AVX::ND>::eval(const X& a,
const Consecutive<Double,AVX::ND>& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_set1_pd( static_cast<Double>(a) );
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_mul_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
/*===========================+
| DividesCC / DividesCX |
+===========================*/
inline decltype(auto)
DividesCC<Double,Double,AVX::ND>::eval(const Consecutive<Double,AVX::ND>& a,
const Consecutive<Double,AVX::ND>& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_div_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
inline decltype(auto)
DividesCC<Double,Double,AVX::ND>::aeval(Consecutive<Double,AVX::ND>& a,
const Consecutive<Double,AVX::ND>& b)
{
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_div_pd(av, bv);
_mm256_store_pd(a.mD, ov);
return a;
}
template <typename X>
inline decltype(auto)
DividesCX<Double,X,AVX::ND>::eval(const Consecutive<Double,AVX::ND>& a,
const X& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_set1_pd( static_cast<Double>(b) );
__m256d ov = _mm256_div_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
template <typename X>
inline decltype(auto)
DividesCX<Double,X,AVX::ND>::aeval(Consecutive<Double,AVX::ND>& a, const X& b)
{
__m256d av = _mm256_load_pd(a.mD);
__m256d bv = _mm256_set1_pd( static_cast<Double>(b) );
__m256d ov = _mm256_div_pd(av, bv);
_mm256_store_pd(a.mD, ov);
return a;
}
template <typename X>
inline decltype(auto)
DividesCX<Double,X,AVX::ND>::eval(const X& a,
const Consecutive<Double,AVX::ND>& b)
{
Consecutive<Double,AVX::ND> o;
__m256d av = _mm256_set1_pd( static_cast<Double>(a) );
__m256d bv = _mm256_load_pd(b.mD);
__m256d ov = _mm256_div_pd(av, bv);
_mm256_store_pd(o.mD, ov);
return o;
}
}
#endif

View file

@ -1,120 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/extensions/avx.h
@brief Register type specialization for AVX.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_avx_h__
#define __cxz_avx_h__
#include <immintrin.h>
#include "base/base.h"
namespace CNORXZ
{
namespace AVX
{
static constexpr SizeT ND = AVX_VSIZE/sizeof(Double);
static constexpr SizeT NF = AVX_VSIZE/sizeof(float);
}
template <>
struct PlusCC<Double,Double,AVX::ND>
{
static inline decltype(auto)
eval(const Consecutive<Double,AVX::ND>& a, const Consecutive<Double,AVX::ND>& b);
static inline decltype(auto)
aeval(Consecutive<Double,AVX::ND>& a, const Consecutive<Double,AVX::ND>& b);
};
template <typename X>
struct PlusCX<Double,X,AVX::ND>
{
static inline decltype(auto)
eval(const Consecutive<Double,AVX::ND>& a, const X& b);
static inline decltype(auto)
aeval(Consecutive<Double,AVX::ND>& a, const X& b);
static inline decltype(auto)
eval(const X& a, const Consecutive<Double,AVX::ND>& b);
};
template <>
struct MinusCC<Double,Double,AVX::ND>
{
static inline decltype(auto)
eval(const Consecutive<Double,AVX::ND>& a, const Consecutive<Double,AVX::ND>& b);
static inline decltype(auto)
aeval(Consecutive<Double,AVX::ND>& a, const Consecutive<Double,AVX::ND>& b);
};
template <typename X>
struct MinusCX<Double,X,AVX::ND>
{
static inline decltype(auto)
eval(const Consecutive<Double,AVX::ND>& a, const X& b);
static inline decltype(auto)
aeval(Consecutive<Double,AVX::ND>& a, const X& b);
static inline decltype(auto)
eval(const X& a, const Consecutive<Double,AVX::ND>& b);
};
template <>
struct MultipliesCC<Double,Double,AVX::ND>
{
static inline decltype(auto)
eval(const Consecutive<Double,AVX::ND>& a, const Consecutive<Double,AVX::ND>& b);
static inline decltype(auto)
aeval(Consecutive<Double,AVX::ND>& a, const Consecutive<Double,AVX::ND>& b);
};
template <typename X>
struct MultipliesCX<Double,X,AVX::ND>
{
static inline decltype(auto)
eval(const Consecutive<Double,AVX::ND>& a, const X& b);
static inline decltype(auto)
aeval(Consecutive<Double,AVX::ND>& a, const X& b);
static inline decltype(auto)
eval(const X& a, const Consecutive<Double,AVX::ND>& b);
};
template <>
struct DividesCC<Double,Double,AVX::ND>
{
static inline decltype(auto)
eval(const Consecutive<Double,AVX::ND>& a, const Consecutive<Double,AVX::ND>& b);
static inline decltype(auto)
aeval(Consecutive<Double,AVX::ND>& a, const Consecutive<Double,AVX::ND>& b);
};
template <typename X>
struct DividesCX<Double,X,AVX::ND>
{
static inline decltype(auto)
eval(const Consecutive<Double,AVX::ND>& a, const X& b);
static inline decltype(auto)
aeval(Consecutive<Double,AVX::ND>& a, const X& b);
static inline decltype(auto)
eval(const X& a, const Consecutive<Double,AVX::ND>& b);
};
}
#endif

View file

@ -1,21 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/extensions/extensions.cc.h
@brief Operation extensions template implementations main header.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_extensions_cc_h__
#define __cxz_extensions_cc_h__
#include "reg.cc.h"
#if CXZ_HAVE_AVX
#include "avx.cc.h"
#endif
#endif

View file

@ -1,23 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/extensions/extensions.h
@brief Operation extensions main header.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_extensions_h__
#define __cxz_extensions_h__
#include "reg.h"
#if CXZ_HAVE_AVX
#include "avx.h"
#endif
#include "extensions.cc.h"
#endif

View file

@ -1,262 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/extensions/reg.cc.h
@brief Register type template implementations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_reg_cc_h__
#define __cxz_reg_cc_h__
#include "reg.h"
#include "xpr/pos_type.h"
namespace CNORXZ
{
template <typename T, class EPosT, SizeT... Is>
inline decltype(auto) vregi(const T* d, const EPosT& pos, std::index_sequence<Is...> is)
{
constexpr SizeT N = epos_size<EPosT>::value;
static_assert(N == sizeof...(Is), "got inconsistent index sequence");
return Consecutive<T,N> { d[pos.template get<Is>().val()]... };
}
template <typename T, class EPosT>
inline decltype(auto) vreg(const T* d, const EPosT& pos)
{
constexpr SizeT N = epos_size<EPosT>::value;
static_assert(is_epos_type<EPosT>::value, "got non-epos-type");
if constexpr(pos_type_is_consecutive<EPosT>::value){
return *reinterpret_cast<const Consecutive<T,N>*>(d+pos.scal().val());
}
else {
return vregi(d, pos, std::make_index_sequence<N>{});
}
}
template <typename T, class EPosT>
inline decltype(auto) vreg(T* d, const EPosT& pos)
{
constexpr SizeT N = epos_size<EPosT>::value;
static_assert(is_epos_type<EPosT>::value, "got non-epos-type");
static_assert(pos_type_is_consecutive<EPosT>::value, "no write access for non-consecutive");
if constexpr(pos_type_is_consecutive<EPosT>::value){
return *reinterpret_cast<Consecutive<T,N>*>(d+pos.scal().val());
}
else {
return vregi(d, pos, std::make_index_sequence<N>{});
}
}
template <SizeT I, typename T>
constexpr decltype(auto) consecGet(const T& a)
{
if constexpr(is_consecutive_type<T>::value){
static_assert(I < consecutive_size<T>::value,
"consecutive index out of range");
return a.mD[I];
}
else {
return a;
}
}
template <SizeT I, typename T>
constexpr decltype(auto) consecGet(T& a)
{
if constexpr(is_consecutive_type<T>::value){
static_assert(I < consecutive_size<T>::value,
"consecutive index out of range");
return a.mD[I];
}
else {
return a;
}
}
template <SizeT I, class F, typename... Args>
constexpr decltype(auto) consecApply(const F& f, const Args&... args)
{
return f( consecGet<I>(args)... );
}
template <SizeT I, class F, typename Dst, typename... Args>
constexpr Dst& consecAssign(const F& f, Dst& dst, const Args&... args)
{
f( consecGet<I>(dst), consecGet<I>(args)... );
return dst;
}
template <class F, typename... Args, SizeT... Is>
constexpr decltype(auto) consecFuncI(const F& f, const Args&... args,
std::index_sequence<Is...> is)
{
typedef decltype(consecApply<0>(f, args...)) OType;
constexpr SizeT N = sizeof...(Is);
return Consecutive<OType,N> { consecApply<Is>(f, args...) ... };
}
template <class F, typename Dst, typename... Args, SizeT... Is>
constexpr Dst& consecFuncAI(const F& f, Dst& dst, const Args&... args,
std::index_sequence<Is...> is)
{
( consecAssign<Is>(f, dst, args...), ... );
return dst;
}
template <SizeT N, class F, typename... Args>
constexpr decltype(auto) consecFunc(const F& f, const Args&... args)
{
return consecFuncI<F,Args...>(f, args..., std::make_index_sequence<N>{});
}
template <SizeT N, class F, typename Dst, typename... Args>
constexpr Dst& consecFuncA(const F& f, Dst& dst, const Args&... args)
{
return consecFuncAI<F,Dst,Args...>(f, dst, args..., std::make_index_sequence<N>{});
}
/*============================+
| basic operations: plus |
+============================*/
template <typename T, typename U, SizeT N>
constexpr decltype(auto)
PlusCC<T,U,N>::eval(const Consecutive<T,N>& a, const Consecutive<U,N>& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x + y; }, a, b );
}
template <typename T, typename U, SizeT N>
constexpr decltype(auto)
PlusCC<T,U,N>::aeval(Consecutive<T,N>& o, const Consecutive<U,N>& a)
{
return consecFuncA<N>( [](auto& x, const auto& y) { return x += y; }, o, a );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) PlusCX<T,X,N>::eval(const Consecutive<T,N>& a, const X& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x + y; }, a, b );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) PlusCX<T,X,N>::eval(const X& a, const Consecutive<T,N>& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x + y; }, a, b );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) PlusCX<T,X,N>::aeval(Consecutive<T,N>& o, const X& a)
{
return consecFuncA<N>( [](auto& x, const auto& y) { return x += y; }, o, a );
}
/*=============================+
| basic operations: minus |
+=============================*/
template <typename T, typename U, SizeT N>
constexpr decltype(auto) MinusCC<T,U,N>::eval(const Consecutive<T,N>& a, const Consecutive<U,N>& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x - y; }, a, b );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) MinusCX<T,X,N>::eval(const Consecutive<T,N>& a, const X& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x - y; }, a, b );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) MinusCX<T,X,N>::eval(const X& a, const Consecutive<T,N>& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x - y; }, a, b );
}
template <typename T, typename U, SizeT N>
constexpr decltype(auto) MinusCC<T,U,N>::aeval(Consecutive<T,N>& o, const Consecutive<U,N>& a)
{
return consecFuncA<N>( [](auto& x, const auto& y) { return x -= y; }, o, a );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) MinusCX<T,X,N>::aeval(Consecutive<T,N>& o, const X& a)
{
return consecFuncA<N>( [](auto& x, const auto& y) { return x -= y; }, o, a );
}
/*=================================+
| basic operations: muliplies |
+=================================*/
template <typename T, typename U, SizeT N>
constexpr decltype(auto) MultipliesCC<T,U,N>::eval(const Consecutive<T,N>& a, const Consecutive<U,N>& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x * y; }, a, b );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) MultipliesCX<T,X,N>::eval(const Consecutive<T,N>& a, const X& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x * y; }, a, b );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) MultipliesCX<T,X,N>::eval(const X& a, const Consecutive<T,N>& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x * y; }, a, b );
}
template <typename T, typename U, SizeT N>
constexpr decltype(auto) MultipliesCC<T,U,N>::aeval(Consecutive<T,N>& o, const Consecutive<U,N>& a)
{
return consecFuncA<N>( [](const auto& x, const auto& y) { return x *= y; }, o, a );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) MultipliesCX<T,X,N>::aeval(Consecutive<T,N>& o, const X& a)
{
return consecFuncA<N>( [](const auto& x, const auto& y) { return x *= y; }, o, a );
}
/*===============================+
| basic operations: divides |
+===============================*/
template <typename T, typename U, SizeT N>
constexpr decltype(auto) DividesCC<T,U,N>::eval(const Consecutive<T,N>& a, const Consecutive<U,N>& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x / y; }, a, b );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) DividesCX<T,X,N>::eval(const Consecutive<T,N>& a, const X& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x / y; }, a, b );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) DividesCX<T,X,N>::eval(const X& a, const Consecutive<T,N>& b)
{
return consecFunc<N>( [](const auto& x, const auto& y) { return x / y; }, a, b );
}
template <typename T, typename U, SizeT N>
constexpr decltype(auto) DividesCC<T,U,N>::aeval(Consecutive<T,N>& o, const Consecutive<U,N>& a)
{
return consecFuncA<N>( [](const auto& x, const auto& y) { return x /= y; }, o, a );
}
template <typename T, typename X, SizeT N>
constexpr decltype(auto) DividesCX<T,X,N>::aeval(Consecutive<T,N>& o, const X& a)
{
return consecFuncA<N>( [](const auto& x, const auto& y) { return x /= y; }, o, a );
}
}
#endif

View file

@ -1,279 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/extensions/reg.h
@brief Register type declaration.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_reg_h__
#define __cxz_reg_h__
#include "base/base.h"
namespace CNORXZ
{
// no use of Arr = std::array here, since I want ensure that
// it has exactly a memory size of N
template <typename T, SizeT N>
struct Consecutive
{
T mD[N];
};
template <typename T>
struct is_consecutive_type { CXZ_CVAL_FALSE; };
template <typename T>
struct consecutive_base { typedef T type; };
template <typename T>
struct consecutive_size { static constexpr SizeT value = 0; };
template <typename T, SizeT N>
struct is_consecutive_type<Consecutive<T,N>> { CXZ_CVAL_TRUE; };
template <typename T, SizeT N>
struct consecutive_base<Consecutive<T,N>> { typedef T type; };
template <typename T, SizeT N>
struct consecutive_size<Consecutive<T,N>> { static constexpr SizeT value = N; };
/*======================================+
| consecutive generating functions |
+======================================*/
template <typename T, class EPosT, SizeT... Is>
inline decltype(auto) vregi(const T* d, const EPosT& pos, std::index_sequence<Is...> is);
template <typename T, class EPosT>
inline decltype(auto) vreg(const T* d, const EPosT& pos);
template <typename T, class EPosT>
inline decltype(auto) vreg(T* d, const EPosT& pos);
/*================+
| ConsecFunc |
+================*/
template <SizeT I, typename T>
constexpr decltype(auto) consecGet(const T& a);
template <SizeT I, typename T>
constexpr decltype(auto) consecGet(T& a);
template <SizeT I, class F, typename... Args>
constexpr decltype(auto) consecApply(const F& f, const Args&... args);
template <SizeT I, class F, typename Dst, typename... Args>
constexpr Dst& consecAssign(const F& f, Dst& dst, const Args&... args);
template <class F, typename... Args, SizeT... Is>
constexpr decltype(auto) consecFuncI(const F& f, const Args&... args,
std::index_sequence<Is...> is);
template <class F, typename Dst, typename... Args, SizeT... Is>
constexpr Dst& consecFuncAI(const F& f, Dst& dst, const Args&... args,
std::index_sequence<Is...> is);
template <SizeT N, class F, typename... Args>
constexpr decltype(auto) consecFunc(const F& f, const Args&... args);
template <SizeT N, class F, typename Dst, typename... Args>
constexpr Dst& consecFuncA(const F& f, Dst& dst, const Args&... args);
/*============================+
| basic operations: plus |
+============================*/
template <typename T, typename U, SizeT N>
struct PlusCC
{
static constexpr decltype(auto)
eval(const Consecutive<T,N>& a, const Consecutive<U,N>& b);
static constexpr decltype(auto)
aeval(Consecutive<T,N>& a, const Consecutive<U,N>& b);
};
template <typename T, typename X, SizeT N>
struct PlusCX
{
static constexpr decltype(auto)
eval(const Consecutive<T,N>& a, const X& b);
static constexpr decltype(auto)
aeval(Consecutive<T,N>& a, const X& b);
static constexpr decltype(auto)
eval(const X& a, const Consecutive<T,N>& b);
};
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator+(const Consecutive<T,N>& a, const Consecutive<U,N>& b)
{ return PlusCC<T,U,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator+(const Consecutive<T,N>& a, const U& b)
{ return PlusCX<T,U,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator+(const T& a, const Consecutive<U,N>& b)
{ return PlusCX<U,T,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr Consecutive<T,N>& operator+=(Consecutive<T,N>& o, const Consecutive<U,N>& a)
{ return PlusCC<T,U,N>::aeval(o,a); }
template <typename T, typename U, SizeT N>
constexpr Consecutive<T,N>& operator+=(Consecutive<T,N>& o, const U& a)
{ return PlusCX<T,U,N>::aeval(o,a); }
/*=============================+
| basic operations: minus |
+=============================*/
template <typename T, typename U, SizeT N>
struct MinusCC
{
static constexpr decltype(auto)
eval(const Consecutive<T,N>& a, const Consecutive<U,N>& b);
static constexpr decltype(auto)
aeval(Consecutive<T,N>& a, const Consecutive<U,N>& b);
};
template <typename T, typename X, SizeT N>
struct MinusCX
{
static constexpr decltype(auto)
eval(const Consecutive<T,N>& a, const X& b);
static constexpr decltype(auto)
aeval(Consecutive<T,N>& a, const X& b);
static constexpr decltype(auto)
eval(const X& a, const Consecutive<T,N>& b);
};
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator-(const Consecutive<T,N>& a, const Consecutive<U,N>& b)
{ return MinusCC<T,U,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator-(const Consecutive<T,N>& a, const U& b)
{ return MinusCX<T,U,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator-(const T& a, const Consecutive<U,N>& b)
{ return MinusCX<U,T,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr Consecutive<T,N>& operator-=(Consecutive<T,N>& o, const Consecutive<U,N>& a)
{ return MinusCC<T,U,N>::eval(o,a); }
template <typename T, typename U, SizeT N>
constexpr Consecutive<T,N>& operator-=(Consecutive<T,N>& o, const U& a)
{ return MinusCX<T,U,N>::eval(o,a); }
/*=================================+
| basic operations: muliplies |
+=================================*/
template <typename T, typename U, SizeT N>
struct MultipliesCC
{
static constexpr decltype(auto)
eval(const Consecutive<T,N>& a, const Consecutive<U,N>& b);
static constexpr decltype(auto)
aeval(Consecutive<T,N>& a, const Consecutive<U,N>& b);
};
template <typename T, typename X, SizeT N>
struct MultipliesCX
{
static constexpr decltype(auto)
eval(const Consecutive<T,N>& a, const X& b);
static constexpr decltype(auto)
aeval(Consecutive<T,N>& a, const X& b);
static constexpr decltype(auto)
eval(const X& a, const Consecutive<T,N>& b);
};
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator*(const Consecutive<T,N>& a, const Consecutive<U,N>& b)
{ return MultipliesCC<T,U,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator*(const Consecutive<T,N>& a, const U& b)
{ return MultipliesCX<T,U,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator*(const T& a, const Consecutive<U,N>& b)
{ return MultipliesCX<U,T,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr Consecutive<T,N>& operator*=(Consecutive<T,N>& o, const Consecutive<U,N>& a)
{ return MultipliesCC<T,U,N>::eval(o,a); }
template <typename T, typename U, SizeT N>
constexpr Consecutive<T,N>& operator*=(Consecutive<T,N>& o, const U& a)
{ return MultipliesCX<T,U,N>::eval(o,a); }
/*===============================+
| basic operations: divides |
+===============================*/
template <typename T, typename U, SizeT N>
struct DividesCC
{
static constexpr decltype(auto)
eval(const Consecutive<T,N>& a, const Consecutive<U,N>& b);
static constexpr decltype(auto)
aeval(Consecutive<T,N>& a, const Consecutive<U,N>& b);
};
template <typename T, typename X, SizeT N>
struct DividesCX
{
static constexpr decltype(auto)
eval(const Consecutive<T,N>& a, const X& b);
static constexpr decltype(auto)
aeval(Consecutive<T,N>& a, const X& b);
static constexpr decltype(auto)
eval(const X& a, const Consecutive<T,N>& b);
};
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator/(const Consecutive<T,N>& a, const Consecutive<U,N>& b)
{ return DividesCC<T,U,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator/(const Consecutive<T,N>& a, const U& b)
{ return DividesCX<T,U,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr decltype(auto) operator/(const T& a, const Consecutive<U,N>& b)
{ return DividesCX<U,T,N>::eval(a,b); }
template <typename T, typename U, SizeT N>
constexpr Consecutive<T,N>& operator/=(Consecutive<T,N>& o, const Consecutive<U,N>& a)
{ return DividesCC<T,U,N>::eval(o,a); }
template <typename T, typename U, SizeT N>
constexpr Consecutive<T,N>& operator/=(Consecutive<T,N>& o, const U& a)
{ return DividesCX<T,U,N>::eval(o,a); }
}
#endif

View file

@ -1,515 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/op_types.cc.h
@brief Operation types template implementations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_op_types_cc_h__
#define __cxz_op_types_cc_h__
#include "op_types.h"
#include "op_utility.h"
#include "extensions/extensions.h"
namespace CNORXZ
{
/*====================+
| COpInterface |
+====================*/
template <class OpT>
template <class F, class IndexT>
constexpr decltype(auto) COpInterface<OpT>::c(F&& f, const Sptr<IndexT>& ind) const
{
return contraction(std::forward<F>(f), THIS().r(), ind);
}
template <class OpT>
template <class IndexT>
constexpr decltype(auto) COpInterface<OpT>::c(const Sptr<IndexT>& ind) const
{
return contraction([](auto& a, const auto& b) { a += b; },
THIS(), ind);
}
template <class OpT>
template <class F, class... Args>
constexpr decltype(auto) COpInterface<OpT>::o(F&& f, Args&&... args) const
{
return operation(std::forward<F>(f), THIS().r(), args...);
}
/*===================+
| OpInterface |
+===================*/
template <class OpT>
template <class IndexT, class F, class... Args>
constexpr decltype(auto) OpInterface<OpT>::ax(const Sptr<IndexT>& ind, F&& f, const Args&... args)
{
return ind->ifor( operation(f, OI::THIS().r(), args...), NoF {} );
}
template <class OpT>
template <class IndexT, class F, class... Args>
inline void OpInterface<OpT>::a(const Sptr<IndexT>& ind, F&& f, const Args&... args)
{
ax(ind, f, args...)();
}
/*=============+
| COpRoot |
+=============*/
template <typename T, class IndexT>
constexpr COpRoot<T,IndexT>::COpRoot(const CArrayBase<T>& a, const Sptr<IndexT>& ind) :
mData(a.data()+ind->pos()),
mIndex(ind)
{}
template <typename T, class IndexT>
constexpr COpRoot<T,IndexT>::COpRoot(const T* data, const Sptr<IndexT>& ind) :
mData(data+ind->pos()),
mIndex(ind)
{}
template <typename T, class IndexT>
constexpr COpRoot<T,IndexT>& COpRoot<T,IndexT>::init(const T* data, const Sptr<IndexT>& ind)
{
mData = data+ind->pos();
mIndex = ind;
return *this;
}
template <typename T, class IndexT>
template <class PosT>
constexpr decltype(auto) COpRoot<T,IndexT>::operator()(const PosT& pos) const
{
if constexpr(is_epos_type<PosT>::value){
return vreg(mData,pos); // distinguish between consecutive/non-consecutive
}
else {
return mData[pos.val()];
}
}
template <typename T, class IndexT>
constexpr decltype(auto) COpRoot<T,IndexT>::operator()() const
{
return mData[0];
}
template <typename T, class IndexT>
template <SizeT I>
constexpr decltype(auto) COpRoot<T,IndexT>::rootSteps(const IndexId<I>& id) const
{
return mIndex->stepSize(id);
}
template <typename T, class IndexT>
const T* COpRoot<T,IndexT>::data() const
{
return mData;
}
template <typename T, class IndexT>
constexpr decltype(auto) coproot(const CArrayBase<T>& a, const Sptr<IndexT>& ind)
{
return COpRoot<T,IndexT>(a, ind);
}
template <typename T, class IndexT>
constexpr decltype(auto) coproot(const T* a, const Sptr<IndexT>& ind)
{
return COpRoot<T,IndexT>(a, ind);
}
/*=============+
| 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) :
mIndex(ind),
mC(std::make_shared<Vector<T>>(mIndex->pmax().val()))
{}
template <typename T, class IndexT>
constexpr OpCont<T,IndexT>& OpCont<T,IndexT>::init(const Sptr<IndexT>& ind)
{
mIndex = ind;
if(mC.size() != mIndex->pmax().val()){
mC.resize(mIndex->pmax().val());
}
return *this;
}
template <typename T, class IndexT>
constexpr OpCont<T,IndexT>& OpCont<T,IndexT>::init(const Sptr<IndexT>& ind,
const Vector<T>& c)
{
init(ind);
CXZ_ASSERT(c.size() == mC.size(),
"size-mismatch: expected " << mC.size() << ", got " << c.size());
std::transform(c.begin(), c.end(), mC.begin(), [](const auto& x) { return x; } );
return *this;
}
template <typename T, class IndexT>
constexpr decltype(auto) OpCont<T,IndexT>::r()
{
return OpRoot<T,IndexT>(data(), mIndex);
}
template <typename T, class IndexT>
constexpr decltype(auto) OpCont<T,IndexT>::r() const
{
return COpRoot<T,IndexT>(data(), mIndex);
}
template <typename T, class IndexT>
template <class Op>
constexpr OpCont<T,IndexT>& OpCont<T,IndexT>::operator=(const Op& o)
{
// TODO: build and execute assign expression forwarding outer index
// if a1 and a2 are non-expression types (like it is the case now),
// just do what is currently implemented
OI::a(mIndex, [](auto& a1, const auto& a2) { a1 = a2; }, o);
return *this;
}
template <typename T, class IndexT>
template <class Op>
constexpr OpCont<T,IndexT>& OpCont<T,IndexT>::operator+=(const Op& o)
{
OI::a(mIndex, [](auto& a1, const auto& a2) { a1 += a2; }, o);
return *this;
}
template <typename T, class IndexT>
constexpr OpCont<T,IndexT>& OpCont<T,IndexT>::operator=(const OpCont<T,IndexT>& o)
{
OI::a(mIndex, [](auto& a1, const auto& a2) { a1 = a2; }, o);
return *this;
}
template <typename T, class IndexT>
template <class PosT>
constexpr decltype(auto) OpCont<T,IndexT>::operator()(const PosT& pos) const
{
if constexpr(is_epos_type<PosT>::value){
if constexpr(pos_type_is_consecutive<PosT>::value){
return vreg(mC.data(),pos);
}
else {
// non-consecutive data cannot be directly accessed
// so there is no non-const (write) access!
return vreg(const_cast<const T*>(mC.data()),pos);
}
}
else {
return mC[pos.val()];
}
}
template <typename T, class IndexT>
constexpr decltype(auto) OpCont<T,IndexT>::operator()() const
{
return mC[0];
}
template <typename T, class IndexT>
template <SizeT I>
constexpr decltype(auto) OpCont<T,IndexT>::rootSteps(const IndexId<I>& id) const
{
return mIndex->stepSize(id);
}
template <typename T, class IndexT>
T* OpCont<T,IndexT>::data()
{
return mC.data();
}
template <typename T, class IndexT>
const T* OpCont<T,IndexT>::data() const
{
return mC.data();
}
/*==============+
| OpRoot |
+==============*/
template <typename T, class IndexT>
constexpr OpRoot<T,IndexT>::OpRoot(ArrayBase<T>& a, const Sptr<IndexT>& ind) :
mData(a.data()+ind->pos()),
mIndex(ind)
{}
template <typename T, class IndexT>
constexpr OpRoot<T,IndexT>::OpRoot(T* data, const Sptr<IndexT>& ind) :
mData(data+ind->pos()),
mIndex(ind)
{}
template <typename T, class IndexT>
constexpr OpRoot<T,IndexT>& OpRoot<T,IndexT>::init(T* data, const Sptr<IndexT>& ind)
{
mData = data+ind->pos();
mIndex = ind;
return *this;
}
template <typename T, class IndexT>
template <class Op>
constexpr OpRoot<T,IndexT>& OpRoot<T,IndexT>::operator=(const Op& o)
{
OI::a(mIndex, [](auto& a, const auto& b) { a = b; }, o);
return *this;
}
template <typename T, class IndexT>
template <class Op>
constexpr OpRoot<T,IndexT>& OpRoot<T,IndexT>::operator+=(const Op& o)
{
OI::a(mIndex, [](auto& a, const auto& b) { a += b; }, o);
return *this;
}
template <typename T, class IndexT>
constexpr OpRoot<T,IndexT>& OpRoot<T,IndexT>::operator=(const OpRoot<T,IndexT>& o)
{
OI::a(mIndex, [](auto& a, const auto& b) { a = b; }, o);
return *this;
}
template <typename T, class IndexT>
template <class PosT>
constexpr decltype(auto) OpRoot<T,IndexT>::operator()(const PosT& pos) const
{
if constexpr(is_epos_type<PosT>::value){
if constexpr(pos_type_is_consecutive<PosT>::value){
return vreg(mData,pos);
}
else {
// non-consecutive data cannot be directly accessed
// so there is no non-const (write) access!
return vreg(const_cast<const T*>(mData),pos);
}
}
else {
return mData[pos.val()];
}
}
template <typename T, class IndexT>
constexpr decltype(auto) OpRoot<T,IndexT>::operator()() const
{
return mData[0];
}
template <typename T, class IndexT>
template <SizeT I>
constexpr decltype(auto) OpRoot<T,IndexT>::rootSteps(const IndexId<I>& id) const
{
return mIndex->stepSize(id);
}
template <typename T, class IndexT>
T* OpRoot<T,IndexT>::data() const
{
return mData;
}
template <typename T, class IndexT>
constexpr decltype(auto) oproot(ArrayBase<T>& a, const Sptr<IndexT>& ind)
{
return OpRoot<T,IndexT>(a, ind);
}
/*=================+
| Operation |
+=================*/
template <class F, class... Ops>
constexpr Operation<F,Ops...>::Operation(F&& f, const Ops&... ops) :
mOps(ops...),
mF(std::forward<F>(f))
{}
template <class F, class... Ops>
template <class PosT>
constexpr decltype(auto) Operation<F,Ops...>::operator()(const PosT& pos) const
{
return pos_unpack_args(mF, pos, mOps);
}
template <class F, class... Ops>
constexpr decltype(auto) Operation<F,Ops...>::operator()() const
{
return exec(std::make_index_sequence<sizeof...(Ops)>{});
}
template <class F, class... Ops>
template <SizeT I>
constexpr decltype(auto) Operation<F,Ops...>::rootSteps(const IndexId<I>& id) const
{
return rootStepsi(id, std::make_index_sequence<sizeof...(Ops)>{});
}
template <class F, class... Ops>
template <SizeT... Is>
constexpr decltype(auto) Operation<F,Ops...>::exec(std::index_sequence<Is...> is) const
{
return mF( std::get<Is>(mOps)() ... );
}
template <class F, class... Ops>
template <SizeT I, SizeT... Is>
constexpr decltype(auto) Operation<F,Ops...>::rootStepsi(const IndexId<I>& id,
std::index_sequence<Is...> is) const
{
return ( std::get<Is>(mOps).rootSteps(id) << ... );
}
template <class F, class... Ops>
constexpr decltype(auto) operation(F&& f, const Ops&... ops)
{
return Operation<F,Ops...>(std::forward<F>(f), ops...);
}
template <class Tar, class Src>
constexpr decltype(auto) assignxpr(const Tar& tar, const Src& src)
{
static_assert(is_xpr<Tar>::value, "expected expression");
if constexpr(is_xpr<Src>::value){
return operation([](auto& a, const auto& b) { a = b; }, tar, src);
}
else {
return operation([&](auto& a) { a = src; }, tar);
}
}
template <class Tar, class Src>
constexpr decltype(auto) assignxpr(Tar& tar, const Src& src)
{
if constexpr(is_xpr<Tar>::value){
if constexpr(is_xpr<Src>::value){
return operation([](auto& a, const auto& b) { a = b; }, tar, src);
}
else {
return operation([&](auto& a) { a = src; }, tar);
}
}
else {
if constexpr(is_xpr<Src>::value){
return operation([&](const auto& b) { tar = b; }, src);
}
else {
return operation([&]() { tar = src; });
}
}
}
/*===================+
| Contraction |
+===================*/
template <class CXpr>
constexpr Contraction<CXpr>::Contraction(CXpr&& cxpr) :
mCXpr(cxpr)
{}
template <class CXpr>
template <class PosT>
constexpr decltype(auto) Contraction<CXpr>::operator()(const PosT& pos) const
{
return mCXpr(pos);
}
template <class CXpr>
constexpr decltype(auto) Contraction<CXpr>::operator()() const
{
return mCXpr();
}
template <class CXpr>
template <SizeT I>
constexpr decltype(auto) Contraction<CXpr>::rootSteps(const IndexId<I>& id) const
{
return mCXpr.rootSteps(id);
}
template <class F, class Op, class IndexT>
constexpr decltype(auto) contraction(F&& f, Op&& op, const Sptr<IndexT>& i)
{
typedef decltype(i->ifor( op, f )) CXprT; // TODO: implement ifor with func arg!!!
return Contraction<CXprT>( i->ifor( op, f ) );
}
/*======================+
| various functions |
+======================*/
template <class IndexT>
constexpr decltype(auto) indexOp(const Sptr<IndexT>& i)
{
return i->xpr(i);
}
}
#endif

View file

@ -1,298 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/op_types.h
@brief Operation types declarations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_op_types_h__
#define __cxz_op_types_h__
#include "base/base.h"
#include "xpr/xpr_base.h"
#include "array/array_base.h"
namespace CNORXZ
{
template <class OpT>
class COpInterface : public XprInterface<OpT>
{
public:
constexpr COpInterface() = default;
OpT& THIS() { return static_cast<OpT&>(*this); }
const OpT& THIS() const { return static_cast<const OpT&>(*this); }
constexpr decltype(auto) r() { return THIS(); }
constexpr decltype(auto) r() const { return THIS(); }
template <class F, class IndexT>
constexpr decltype(auto) c(F&& f, const Sptr<IndexT>& ind) const;
template <class IndexT>
constexpr decltype(auto) c(const Sptr<IndexT>& ind) const;
template <class F, class... Args>
constexpr decltype(auto) o(F&& f, Args&&... args) const;
};
template <class OpT>
class OpInterface : public COpInterface<OpT>
{
public:
typedef COpInterface<OpT> OI;
constexpr OpInterface() = default;
OpT& THIS() { return static_cast<OpT&>(*this); }
const OpT& THIS() const { return static_cast<const OpT&>(*this); }
template <class IndexT, class F, class... Args>
constexpr decltype(auto) ax(const Sptr<IndexT>& ind, F&& f, const Args&... args);
template <class IndexT, class F, class... Args>
inline void a(const Sptr<IndexT>& ind, F&& f, const Args&... args);
};
template <class T>
struct is_operation
{ static constexpr bool value = std::is_base_of<COpInterface<T>,T>::value; };
template <class T>
struct is_mutable_operation
{ static constexpr bool value = std::is_base_of<OpInterface<T>,T>::value; };
template <class T>
struct op_size
{ static constexpr SizeT value = is_operation<T>::value ? 1 : 0; };
template <typename T, class IndexT>
class COpRoot : public COpInterface<COpRoot<T,IndexT>>
{
public:
typedef OpInterface<COpRoot<T,IndexT>> OI;
constexpr COpRoot() = default;
constexpr COpRoot(const CArrayBase<T>& a, const Sptr<IndexT>& ind);
constexpr COpRoot(const T* data, const Sptr<IndexT>& ind);
constexpr COpRoot& init(const T* data, const Sptr<IndexT>& ind);
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;
const T* data() const;
private:
const T* mData = nullptr;
Sptr<IndexT> mIndex;
};
template <typename T, class IndexT>
constexpr decltype(auto) coproot(const CArrayBase<T>& a, const Sptr<IndexT>& ind);
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>>
{
public:
typedef OpInterface<OpCont<T,IndexT>> OI;
typedef typename Container<T,index_const_size<IndexT>::value,
index_has_const_size<IndexT>::value>::type CT;
constexpr OpCont() = default;
constexpr OpCont(const Sptr<IndexT>& ind);
constexpr OpCont& init(const Sptr<IndexT>& ind);
constexpr OpCont& init(const Sptr<IndexT>& ind, const Vector<T>& c);
constexpr decltype(auto) r();
constexpr decltype(auto) r() const;
template <class Op>
constexpr OpCont& operator=(const Op& in);
template <class Op>
constexpr OpCont& operator+=(const Op& in);
constexpr OpCont& operator=(const OpCont& in);
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;
T* data();
const T* data() const;
private:
Sptr<IndexT> mIndex;
CT mC;
};
template <typename T, class IndexT>
class OpRoot : public OpInterface<OpRoot<T,IndexT>>
{
public:
typedef OpInterface<OpRoot<T,IndexT>> OI;
constexpr OpRoot() = default;
constexpr OpRoot(ArrayBase<T>& a, const Sptr<IndexT>& ind);
constexpr OpRoot(T* data, const Sptr<IndexT>& ind);
constexpr OpRoot& init(T* data, const Sptr<IndexT>& ind);
template <class Op>
constexpr OpRoot& operator=(const Op& in);
template <class Op>
constexpr OpRoot& operator+=(const Op& in);
constexpr OpRoot& operator=(const OpRoot& in);
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;
T* data() const;
private:
T* mData = nullptr;
Sptr<IndexT> mIndex;
};
template <typename T, class IndexT>
constexpr decltype(auto) oproot(ArrayBase<T>& a, const Sptr<IndexT>& ind);
template <class F, class... Ops>
class Operation : public OpInterface<Operation<F,Ops...>>
{
public:
typedef OpInterface<Operation<F,Ops...>> OI;
constexpr Operation() = default;
constexpr Operation(F&& f, const Ops&... ops);
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;
private:
template <SizeT... Is>
constexpr decltype(auto) exec(std::index_sequence<Is...> is) const;
template <SizeT I, SizeT... Is>
constexpr decltype(auto) rootStepsi(const IndexId<I>& id,
std::index_sequence<Is...> is) const;
Tuple<Ops...> mOps;
F mF;
};
template <class F, class... Ops>
constexpr decltype(auto) operation(F&& f, const Ops&... ops);
template <class Tar, class Src>
constexpr decltype(auto) assignxpr(const Tar& tar, const Src& src);
template <class Tar, class Src>
constexpr decltype(auto) assignxpr(Tar& tar, const Src& src);
template <class F, class... Ops>
struct op_size<Operation<F,Ops...>>
{ static constexpr SizeT value = ( op_size<Ops>::value + ... ); };
template <class CXpr>
class Contraction : public OpInterface<Contraction<CXpr>>
{
public:
typedef OpInterface<Contraction<CXpr>> OI;
constexpr Contraction() = default;
constexpr Contraction(CXpr&& cxpr);
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;
private:
CXpr mCXpr;
};
template <class CXpr>
struct op_size<Contraction<CXpr>>
{ static constexpr SizeT value = op_size<CXpr>::value; };
template <class F, class Op, class IndexT>
constexpr decltype(auto) contraction(F&& f, Op&& op, const Sptr<IndexT>& i);
template <class IndexT>
constexpr decltype(auto) indexOp(const Sptr<IndexT>& i);
}
#endif

View file

@ -1,63 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/op_utility.cc.h
@brief Operation utilities template implementations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_op_utility_cc_h__
#define __cxz_op_utility_cc_h__
#include "op_utility.h"
#include "xpr/pos_type.h"
namespace CNORXZ
{
template <SizeT I, class PosT>
constexpr decltype(auto) pos_get(const PosT& pos)
{
static_assert(I < static_pos_size<PosT>::value, "index out of range");
if constexpr(I == 0){
return pos;
}
else {
return pos_get<I-1>(pos.next());
}
}
template <SizeT J, SizeT I, SizeT... Is>
constexpr SizeT sum_index_sequence(std::index_sequence<I,Is...> is)
{
static_assert(J < sizeof...(Is)+1, "index out of range");
if constexpr(J == 0){
return 0;
}
else {
return sum_index_sequence<J-1>(std::index_sequence<Is...>{}) + I;
}
}
template <class F, class PosT, class OpTuple, class OpSizes, SizeT... Is>
inline auto pos_unpack_args_i(const F& f, const PosT& pos, const OpTuple& args,
OpSizes opsizes, std::index_sequence<Is...> is)
{
return f(std::get<Is>(args)(pos_get<sum_index_sequence<Is>(opsizes)>(pos))...);
}
template <class F, class PosT, class... Ops>
inline auto pos_unpack_args(const F& f, const PosT& pos, const Tuple<Ops...>& args)
{
static_assert(is_pos_type<PosT>::value, "got non-pos-type");
static_assert((is_operation<Ops>::value and ...), "got non-operation type");
typedef std::make_index_sequence<sizeof...(Ops)> Idxs;
typedef std::index_sequence<op_size<Ops>::value...> OpSizes;
return pos_unpack_args_i(f, pos, args, OpSizes{}, Idxs{});
}
}
#endif

View file

@ -1,34 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/op_utility.h
@brief Operation utilities declarations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#ifndef __cxz_op_utility_h__
#define __cxz_op_utility_h__
#include "base/base.h"
namespace CNORXZ
{
template <SizeT I, class PosT>
constexpr decltype(auto) pos_get(const PosT& pos);
template <SizeT J, SizeT... Is>
constexpr SizeT sum_index_sequence(std::index_sequence<Is...> is);
template <class F, class PosT, class OpTuple, class OpSizes, SizeT... Is>
inline auto pos_unpack_args_i(const F& f, const PosT& pos, const OpTuple& args,
OpSizes opsizes, std::index_sequence<Is...> is);
template <class F, class PosT, class... Ops>
inline auto pos_unpack_args(const F& f, const PosT& pos, const Tuple<Ops...>& args);
}
#endif

View file

@ -1,14 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/operation.cc.h
@brief Operation main header for template implementations.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "op_types.cc.h"
#include "op_utility.cc.h"
#include "basic_operations.cc.h"

View file

@ -1,16 +0,0 @@
// -*- C++ -*-
/**
@file include/operation/operation.h
@brief Operation main header.
Copyright (c) 2024 Christian Zimmermann. All rights reserved.
Mail: chizeta@f3l.de
**/
#include "op_types.h"
#include "op_utility.h"
#include "basic_operations.h"
#include "operation.cc.h"

View file

@ -0,0 +1,94 @@
#ifndef __cxz_operation_def_h__
#define __cxz_operation_def_h__
#include "cxz_operation.h"
namespace CNORXZ
{
template <typename T, class OperationClass>
auto operator+(const T& a, const OperationBase<T,OperationClass>& b)
-> Operation<T,plus<T>,OperationValue<T>,OperationClass>
{
OperationValue<T> v(a);
return Operation<T,plus<T>,OperationValue<T>,OperationClass>(v, b.THIS());
}
template <typename T, class OperationClass>
auto operator-(const T& a, const OperationBase<T,OperationClass>& b)
-> Operation<T,minus<T>,OperationValue<T>,OperationClass>
{
OperationValue<T> v(a);
return Operation<T,minus<T>,OperationValue<T>,OperationClass>(v, b.THIS());
}
template <typename T, class OperationClass>
auto operator*(const T& a, const OperationBase<T,OperationClass>& b)
-> Operation<T,multiplies<T>,OperationValue<T>,OperationClass>
{
OperationValue<T> v(a);
return Operation<T,multiplies<T>,OperationValue<T>,OperationClass>(v, b.THIS());
}
template <typename T, class OperationClass>
auto operator/(const T& a, const OperationBase<T,OperationClass>& b)
-> Operation<T,divides<T>,OperationValue<T>,OperationClass>
{
OperationValue<T> v(a);
return Operation<T,divides<T>,OperationValue<T>,OperationClass>(v, b.THIS());
}
template <typename T, class OperationClass>
auto operator+(const OperationBase<T,OperationClass>& a, const T& b)
-> Operation<T,plus<T>,OperationClass,OperationValue<T> >
{
OperationValue<T> v(b);
return Operation<T,plus<T>,OperationClass,OperationValue<T> >(a.THIS(), v);
}
template <typename T, class OperationClass>
auto operator-(const OperationBase<T,OperationClass>& a, const T& b)
-> Operation<T,minus<T>,OperationClass,OperationValue<T> >
{
OperationValue<T> v(b);
return Operation<T,minus<T>,OperationClass,OperationValue<T> >(a.THIS(), v);
}
template <typename T, class OperationClass>
auto operator*(const OperationBase<T,OperationClass>& a, const T& b)
-> Operation<T,multiplies<T>,OperationClass,OperationValue<T> >
{
OperationValue<T> v(b);
return Operation<T,multiplies<T>,OperationClass,OperationValue<T> >(a.THIS(), v);
}
template <typename T, class OperationClass>
auto operator/(const OperationBase<T,OperationClass>& a, const T& b)
-> Operation<T,divides<T>,OperationClass,OperationValue<T> >
{
OperationValue<T> v(b);
return Operation<T,divides<T>,OperationClass,OperationValue<T> >(a.THIS(), v);
}
#define regFunc1(fff) template <typename T, class OperationClass> \
auto fff(const OperationBase<T,OperationClass>& a) \
-> Operation<T,x_##fff<T>,OperationClass> { \
return Operation<T,x_##fff<T>,OperationClass>(a.THIS()); }
#include "extensions/math.h"
#undef regFunc1
template <size_t N, typename T, class OperationClass>
auto ipow(const OperationBase<T,OperationClass>& a)
-> Operation<T,x_ipow<N-1>,OperationClass>
{
return Operation<T,x_ipow<N-1>,OperationClass>(a.THIS());
}
}
#endif

Some files were not shown because too many files have changed in this diff Show more