An open API service indexing awesome lists of open source software.

https://github.com/danielaparker/acons

A modern C++ header-only library for constructing N-dimensional arrays
https://github.com/danielaparker/acons

array cpp cpp11 header-only multi-dimensional-array n-dimensional no-dependencies numerical-methods scientific-computing single-file

Last synced: 10 months ago
JSON representation

A modern C++ header-only library for constructing N-dimensional arrays

Awesome Lists containing this project

README

          

# acons

acons is a modern C++ header-only library for constructing N-dimensional arrays.

It is distributed under the [MIT License](https://opensource.org/licenses/MIT).

## Get acons

Download the latest [single header file](https://raw.githubusercontent.com/danielaparker/acons/master/include/acons/ndarray.hpp).

## How to use it

[Examples](#ExamplesLabel)
[Reference](doc/ref/index.md)

## Supported compilers

Compiler | Versions | Operating System
--------------|---------------|-----------------
VS | 14.0 | Windows 10
g++- | 4.8, 6, 7,8 | Ubuntu
clang | 3.8, 5.0. 6.0 |

### Examples

#### Construct an array with zeros

```c++
#include
#include

int main()
{
// Construct an array of shape 2 x 3 with zeros
acons::ndarray a(2,3,0.0);

std::cout << a << "\n\n";
}
```
Output:
```
[[0,0,0],[0,0,0]]
```

#### Construct a 3-dim array

```c++
#include
#include

int main()
{
// Create a 3-dim array of shape 3 x 4 x 2
acons::ndarray a(3,4,2);

// Assign values to the elements
int x = 0;
for (size_t i = 0; i < a.shape(0); ++i)
{
for (size_t j = 0; j < a.shape(1); ++j)
{
for (size_t k = 0; k < a.shape(2); ++k)
{
a(i,j,k) = x++;
}
}
}

// Print
std::cout << a << "\n";
}
```
Output:
```
[[[0,1],[2,3],[4,5],[6,7]],[[8,9],[10,11],[12,13],[14,15]],[[16,17],[18,19],[20,21],[22,23]]]
```

#### Wrap a C-array

```c++
#include
#include

int main()
{
double a[] = {0,1,2,3,4,5,6};

// Elements of a can be modified through this 2 x 3 interface
acons::ndarray_view v(a,2,3);
v(0,2) = 9;

// Elements of a cannot be modified through this 2 x 3 interface
acons::const_ndarray_view cv(a,2,3);

std::cout << cv << "\n\n";
}
```
Output:
```
[[0,1,9],[3,4,5]]
```

#### Slicing a 1-dimensional array

A `slice` object can be constructed with `start`, `stop` and `step` parameters.
```c++
#include
#include

int main()
{
acons::ndarray a = {0,1,2,3,4,5,6,7,8,9};

// Extracting a part of the array with a slice object
acons::ndarray_view v(a, {acons::slice(2,7,2)});
std::cout << v << "\n\n";
}
```
Output:
```
[2,4,6]
```

#### Slicing a 2-dimensional array

A `slice` object constructed with no parameters identifies all the elements along the dimension of an array.
If `stop` and `step` are not given, `stop` defaults to one past the last element along the dimension,
and `step` defaults to 1.

```c++
#include
#include

int main()
{
// Construct a 2-dimensional 3 x 4 array
acons::ndarray a = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};

// All items from row 1 and columns 0 and 1
acons::ndarray_view v1(a, {acons::slice(1,2),acons::slice(0,2)});
std::cout << "(1) " << v1 << "\n\n";

// All items from column 1 onwards
acons::ndarray_view v2(a, {acons::slice(),acons::slice(1)});
std::cout << "(2) " << v2 << "\n\n";
}
```
Output:
```
(1) [[4,5]]

(2) [[1,2,3],[5,6,7],[9,10,11]]
```

#### Reduction

Construct a view on an array (or another view) that has fewer dimensions than the original.

```c++
#include
#include

int main()
{
// Construct a 2-dimensional 3 x 4 array
acons::ndarray a = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};

// Reduce the 2-dimensional array to a 1-dimensional array, along row 0
acons::ndarray_view v1(a, acons::indices_t<1>{0});
std::cout << "(1) " << v1 << "\n\n";

// Reduce the 2-dimensional array to a 1-dimensional array, along column 2
acons::ndarray_view v2(a, {acons::slice()}, acons::indices_t<1>{2});
std::cout << "(2) " << v2 << "\n\n";
}
```
Output:
```
(1) [[12,13,14,15],[16,17,18,19],[20,21,22,23]]

(2) [14,18,22]
```

#### Creating ndarrays in managed shared memory with Boost interprocess allocators

```c++
#include
#include
#include
#include
#include //std::system
#include
#include

typedef boost::interprocess::allocator shmem_allocator;

typedef acons::ndarray ndarray_shm;

int main(int argc, char *argv[])
{
typedef std::pair MyType;

if(argc == 1) //Parent process
{
//Remove shared memory on construction and destruction
struct shm_remove
{
shm_remove() { boost::interprocess::shared_memory_object::remove("MySharedMemory"); }
~shm_remove(){ boost::interprocess::shared_memory_object::remove("MySharedMemory"); }
}
remover;

//Construct managed shared memory
boost::interprocess::managed_shared_memory segment(boost::interprocess::create_only,
"MySharedMemory", 65536);

//Initialize shared memory STL-compatible allocator
const shmem_allocator allocator(segment.get_segment_manager());

// Create ndarray with all dynamic allocations in shared memory
ndarray_shm* pA = segment.construct("my ndarray")(std::allocator_arg, allocator, 2, 2, 0.0);
ndarray_shm& a = *pA;

a(0,0) = 0;
a(0,1) = 1;
a(1,0) = 2;
a(1,1) = 3;

std::pair res;
res = segment.find("my ndarray");

std::cout << "Parent process:\n";
std::cout << *(res.first) << "\n";

//Launch child process
std::string s(argv[0]); s += " child ";
if(0 != std::system(s.c_str()))
return 1;

//Check child has destroyed all objects
if(segment.find("my ndarray").first)
return 1;
}
else
{
//Open managed shared memory
boost::interprocess::managed_shared_memory segment(boost::interprocess::open_only,
"MySharedMemory");

std::pair res;
res = segment.find("my ndarray");

if (res.first != nullptr)
{
std::cout << "\nChild process:\n";
std::cout << *(res.first) << "\n";
}
else
{
std::cout << "Result is null\n";
}

//We're done, delete all the objects
segment.destroy("my ndarray");
}
}
```
Output:
```
Parent process:
[[0,1],[2,3]]

Child process:
[[0,1],[2,3]]
```