Skip to content
This repository has been archived by the owner on Oct 25, 2019. It is now read-only.

Commit

Permalink
Introduced new namespaces 'cartesian', 'cartesian2d', and 'cartesian3…
Browse files Browse the repository at this point in the history
…d' to facilitate switching
  • Loading branch information
tdegeus committed Oct 8, 2017
1 parent f167559 commit 49d6740
Show file tree
Hide file tree
Showing 20 changed files with 4,475 additions and 5,477 deletions.
594 changes: 594 additions & 0 deletions develop/matrix.cpp

Large diffs are not rendered by default.

1,977 changes: 968 additions & 1,009 deletions develop/verify_tensor2.cpp → develop/tensor.cpp

Large diffs are not rendered by default.

2,005 changes: 668 additions & 1,337 deletions develop/verify_tensor.cpp → develop/tensor2.cpp

Large diffs are not rendered by default.

1,696 changes: 674 additions & 1,022 deletions develop/verify_tensor3.cpp → develop/tensor3.cpp

Large diffs are not rendered by default.

600 changes: 0 additions & 600 deletions develop/verify_matrix.cpp

This file was deleted.

69 changes: 34 additions & 35 deletions docs/compile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,21 @@ Compiling
Introduction
============

This module is header only. So one just has to ``#include <cppmat/matrix.h>`` and/or ``#include <cppmat/tensor.h>`` somewhere in the source code, and to tell the compiler where the header-files are. For the latter, several ways are described below.
This module is header only. So one just has to ``#include <cppmat/matrix.h>`` and/or ``#include <cppmat/tensor.h>``, ... somewhere in the source code, and to tell the compiler where the header-files are. For the latter, several ways are described below.

Before proceeding, a words about optimization. Of course one should use optimization when compiling the release of the code (``-O2`` or ``-O3``). But it is also a good idea to switch of the assertions in the code (mostly checks on size) that facilitate easy debugging, but do cost time. Therefore, include the flag ``-DNDEBUG``. Note that this is all C++ standard. I.e. it should be no surprise, and it always a good idea to do.

Manual compiler flags
=====================

GNU / Clang
===========
-----------

Add the following compiler's arguments:

.. code-block:: bash
-I${PATH_TO_CPPMAT}/include -std=c++14
(or ``-std=c++14``, ...).
-I${PATH_TO_CPPMAT}/src -std=c++14
.. note:: **(Not recommended)**

Expand All @@ -37,36 +38,22 @@ Add the following compiler's arguments:

.. _compile_automatic:

Automating build
================
(Semi-)Automatic compiler flags
===============================

Install
-------

To enable automatic build one should 'install' ``cppmat`` somewhere.

.. note:: **(Not recommended)**

If you do not wish to use ``CMake``, or you want to do something custom. You can of course. Follow these steps:

1. Copy the file ``src/cppmat.pc.in`` to ``cppmat.pc`` to some location that can be found by ``pkg_config`` (for example by adding ``export PKG_CONFIG_PATH=/path/to/cppmat.pc:$PKG_CONFIG_PATH`` to the ``.bashrc``).

2. Modify the line ``prefix=@CMAKE_INSTALL_PREFIX@`` to ``prefix=/path/to/cppmat``.

3. Modify the line ``Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@`` to ``Cflags: -I${prefix}/src``.

4. Modify the line ``Version: @CPPMAT_VERSION_NUMBER@`` to reflect the correct release version.
To enable (semi-)automatic build, one should 'install' ``cppmat`` somewhere.

Install system-wide (root)
^^^^^^^^^^^^^^^^^^^^^^^^^^

1. Make a temporary build directory. For example
1. Proceed to a (temporary) build directory. For example

.. code-block:: bash
$ cd /path/to/cppmat/src
$ mkdir build
$ cd build
$ cd /path/to/cppmat/src/build
2. 'Build' ``cppmat``

Expand All @@ -75,16 +62,16 @@ Install system-wide (root)
$ cmake ..
$ make install
(If you've used another build directory, change the first command to ``$ cmake /path/to/cppmat/src``)

Install in custom location (user)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1. Make a temporary build directory. For example
1. Proceed to a (temporary) build directory. For example

.. code-block:: bash
$ cd /path/to/cppmat/src
$ mkdir build
$ cd build
$ cd /path/to/cppmat/src/build
2. 'Build' ``cppmat``, to install it in a custom location

Expand All @@ -94,25 +81,39 @@ Install in custom location (user)
$ cmake .. -DCMAKE_INSTALL_PREFIX:PATH=/custom/install/path
$ make install
(If you've used another build directory, change the first command to ``$ cmake /path/to/cppmat/src``)

3. Add the following path to your ``~/.bashrc`` (or ``~/.zshrc``):

.. code-block:: bash
export PKG_CONFIG_PATH=/custom/install/path/share/pkgconfig:$PKG_CONFIG_PATH
pkg-config
----------
.. note:: **(Not recommended)**

If you do not wish to use ``CMake`` for the installation, or you want to do something custom. You can of course. Follow these steps:

1. Copy the file ``src/cppmat.pc.in`` to ``cppmat.pc`` to some location that can be found by ``pkg_config`` (for example by adding ``export PKG_CONFIG_PATH=/path/to/cppmat.pc:$PKG_CONFIG_PATH`` to the ``.bashrc``).

2. Modify the line ``prefix=@CMAKE_INSTALL_PREFIX@`` to ``prefix=/path/to/cppmat``.

3. Modify the line ``Cflags: -I${prefix}/@INCLUDE_INSTALL_DIR@`` to ``Cflags: -I${prefix}/src``.

4. Modify the line ``Version: @CPPMAT_VERSION_NUMBER@`` to reflect the correct release version.

Compiler arguments from 'pkg-config'
------------------------------------

Instead of ``-I...`` one can now use

.. code-block:: bash
`pkg-config --cflags cppmat` -std=c++14
to compile in a single command.
as compiler argument.

cmake
-----
Compiler arguments from 'cmake'
-------------------------------

Add the following to your ``CMakeLists.txt``:

Expand All @@ -124,5 +125,3 @@ Add the following to your ``CMakeLists.txt``:
pkg_check_modules(CPPMAT REQUIRED cppmat)
include_directories(${CPPMAT_INCLUDE_DIRS})
or use ``set(CMAKE_CXX_STANDARD 14)``, ....
14 changes: 13 additions & 1 deletion docs/develop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,19 @@ Notes for developers
Make changes / additions
========================

Be sure to run the verification codes in ``develop/``! All existing checks should pass, while new check should be added to check new functionality.
Be sure to run the verification code in ``develop/``! All existing checks should pass, while new check should be added to check new functionality.

The `Catch <http://catch-lib.net>`_ library has been used to run the checks, it should be used also for all new checks. To compile the checks:

1. Download and install Catch.

2. Compile all test cases.

.. code-block:: bash
$ clang++ `pkg-config --cflags Eigen3 cppmat` -std=c++14 -Wpedantic -Wall -o test *.cpp
3. Run ``./test``.

Python
======
Expand Down
47 changes: 24 additions & 23 deletions docs/examples/tensorlib/tensorlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,81 +6,82 @@
// double tensor contraction 4-d : 2-d -> 2-d (pure C++)
// =================================================================================================

namespace cm = cppmat::cartesian;

template <class T>
cppmat::tensor2<T> ddot42 ( cppmat::tensor4<T> &A, cppmat::tensor2<T> &B )
cm::tensor2<T> ddot42 ( cm::tensor4<T> &A, cm::tensor2<T> &B )
{
return A.ddot(B);
}

template cppmat::tensor2<int> ddot42<int> (cppmat::tensor4<int> &, cppmat::tensor2<int> &);
template cppmat::tensor2<double> ddot42<double>(cppmat::tensor4<double>&, cppmat::tensor2<double>&);
template cm::tensor2<int> ddot42<int> (cm::tensor4<int> &, cm::tensor2<int> &);
template cm::tensor2<double> ddot42<double>(cm::tensor4<double>&, cm::tensor2<double>&);

// -------------------------------------------------------------------------------------------------

template <class T>
cppmat::tensor2s<T> symmetric ( cppmat::tensor2<T> &B )
cm::tensor2s<T> symmetric ( cm::tensor2<T> &B )
{
cppmat::tensor2s<T> C = B.astensor2s();
cm::tensor2s<T> C = B.astensor2s();
return C;
}

template cppmat::tensor2s<int> symmetric<int> (cppmat::tensor2<int> &);
template cppmat::tensor2s<double> symmetric<double> (cppmat::tensor2<double> &);
template cm::tensor2s<int> symmetric<int> (cm::tensor2<int> &);
template cm::tensor2s<double> symmetric<double> (cm::tensor2<double> &);

// -------------------------------------------------------------------------------------------------

template <class T>
cppmat::tensor2d<T> diagonal ( cppmat::tensor2<T> &B )
cm::tensor2d<T> diagonal ( cm::tensor2<T> &B )
{
cppmat::tensor2d<T> C = B.astensor2d();
cm::tensor2d<T> C = B.astensor2d();
return C;
}

template cppmat::tensor2d<int> diagonal<int> (cppmat::tensor2<int> &);
template cppmat::tensor2d<double> diagonal<double> (cppmat::tensor2<double> &);
template cm::tensor2d<int> diagonal<int> (cm::tensor2<int> &);
template cm::tensor2d<double> diagonal<double> (cm::tensor2<double> &);

// =================================================================================================
// create Python module
// create Python module (pybind11)
// =================================================================================================

PYBIND11_PLUGIN(tensorlib) {
PYBIND11_MODULE(tensorlib, m)
{

py::module m("tensorlib", "Tensor library");
m.doc() = "Tensor library";

m.def("ddot42",py::overload_cast<cppmat::tensor4<int> &,cppmat::tensor2<int> &>(&ddot42<int> ),
m.def("ddot42",py::overload_cast<cm::tensor4<int>&,cm::tensor2<int>&>(&ddot42<int>),
"Double-dot product",
py::arg("A"),
py::arg("B")
);

m.def("ddot42",py::overload_cast<cppmat::tensor4<double>&,cppmat::tensor2<double>&>(&ddot42<double>),
m.def("ddot42",py::overload_cast<cm::tensor4<double>&,cm::tensor2<double>&>(&ddot42<double>),
"Double-dot product",
py::arg("A"),
py::arg("B")
);


m.def("symmetric",py::overload_cast<cppmat::tensor2<int> &>(&symmetric<int> ),
m.def("symmetric",py::overload_cast<cm::tensor2<int>&>(&symmetric<int>),
"Symmetric part of the tensor",
py::arg("A")
);

m.def("symmetric",py::overload_cast<cppmat::tensor2<double>&>(&symmetric<double>),
m.def("symmetric",py::overload_cast<cm::tensor2<double>&>(&symmetric<double>),
"Symmetric part of the tensor",
py::arg("A")
);


m.def("diagonal",py::overload_cast<cppmat::tensor2<int> &>(&diagonal<int> ),
m.def("diagonal",py::overload_cast<cm::tensor2<int>&>(&diagonal<int>),
"Diagonal part of the tensor",
py::arg("A")
);

m.def("diagonal",py::overload_cast<cppmat::tensor2<double>&>(&diagonal<double>),
m.def("diagonal",py::overload_cast<cm::tensor2<double>&>(&diagonal<double>),
"Diagonal part of the tensor",
py::arg("A")
);

return m.ptr();

} // PYBIND11_PLUGIN
} // PYBIND11_MODULE
38 changes: 30 additions & 8 deletions docs/python.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,46 @@
Python interface
****************

This library includes provides an interface to `pybind11 <https://github.com/pybind/pybind11>`_ such that an interface to *NumPy* arrays is automatically provided when including a function with a ``cppmat::matrix`` (rank n *NumPy*-array), ``cppmat::tensor4`` (rank 4 *NumPy*-array), ``cppmat::tensor2`` (rank 2 *NumPy*-array), ``cppmat::tensor2s`` (rank 2 *NumPy*-array), ``cppmat::tensor2d`` (rank 2 *NumPy*-array), or ``cppmat::vector`` (rank 1 *NumPy*-array). To use this feature one has to include (either or both):
This library includes provides an interface to `pybind11 <https://github.com/pybind/pybind11>`_ such that an interface to *NumPy* arrays is automatically provided when including a function with any of the *cppmat* classes:

+---------------------------------+---------------------------+
| ***cppmat* class** | **rank of *NumPy*-array** |
+---------------------------------+---------------------------+
| ``cppmat::matrix`` | n |
| ``cppmat::cartesian::tensor4`` | 4 |
| ``cppmat::cartesian::tensor2`` | 2 |
| ``cppmat::cartesian::tensor2s`` | 2 |
| ``cppmat::cartesian::tensor2d`` | 2 |
| ``cppmat::cartesian::vector`` | 1 |
+---------------------------------+---------------------------+

.. note::

The same holds for ``cppmat::cartesian2d`` and ``cppmat::cartesian3d`` in ``<cppmat/tensor2.h>`` and ``<cppmat/tensor3.h>``.

.. note:: **Warning**

On the Python side all 2nd-order tensors (``cppmat::tensor2``, ``cppmat::tensor2s``, and ``cppmat::tensor2d``) are the same rank 2 *NumPy*-arrays. This means that when a function with has ``cppmat::tensor2s`` as argument, the upper-diagonal part is read; while when it has an argument ``cppmat::tensor2d`` only the diagonal is considered.

**This requires extra attention as information might be lost. To optimize for speed and flexibility no checks are performed in the release libraries derived from *cppmat*!**

You can ask *cppmat* to check for this, by omitting the ``-DNDEBUG`` compiler flag (this enables several assertions, so it may cost you some efficiency).

To use this feature one has to include (part of) the following:

.. code-block:: cpp
#include <cppmat/pybind11_matrix.h>
#include <cppmat/pybind11_tensor.h>
#include <cppmat/pybind11_tensor2.h>
#include <cppmat/pybind11_tensor3.h>
An example is provided in ``docs/examples/tensorlib``. This example includes two forms of building:

1. ``CMakeList.txt`` for building using ``cmake`` (``cmake .`` and then ``make``). For this to work, *pybind11* must be 'installed' on the system. Alternatively you can include *pybind11* as a sub-folder (for example using ``git submodule add https://github.com/pybind/pybind11.git``). In that case, replace ``find_package(pybind11 REQUIRED)`` by ``add_subdirectory(pybind11)`` in ``CMakeList.txt``.

2. ``setup.py`` for building using ``python`` (`python setup.py build` and then `python setup.py install`). Using this option, ``python`` will take care of the *pybind11* and *cppmat* dependencies.
2. ``setup.py`` for building using ``python`` (``python setup.py build`` and then ``python setup.py install``). Using this option, ``python`` will take care of the *pybind11* and *cppmat* dependencies.

*(Replace the executable with your favorite Python version, e.g. with ``python3``)*
*(Replace the executable with your favorite Python version, e.g. with 'python3')*

.. note:: **Warning**

On the Python side all 2nd-order tensors (``cppmat::tensor2``, ``cppmat::tensor2s``, and ``cppmat::tensor2d``) are the same rank 2 *NumPy*-array. This means that when a function with has ``cppmat::tensor2s`` as argument, the upper-diagonal part is read; while when it has an argument ``cppmat::tensor2d`` only the diagonal is considered. You can ask *cppmat* to check for this, by omitting the ``-DNDEBUG`` compiler flag (this enables several assertions, so it may cost you some efficiency).

**This requires extra attention as information might be lost. To optimize for speed and flexibility no checks are performed in the release libraries derived from *cppmat*!**

0 comments on commit 49d6740

Please sign in to comment.