Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ doc/html
.*.swo
.*.swn
.claude
test/python/c2py_clair/*.cxx
test/python/c2py_clair/*.hxx
4 changes: 1 addition & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,14 @@ option(OpenMPSupport "Build with OpenMP support" ON)

# Documentation
option(Build_Documentation "Build documentation" OFF)
if(NOT IS_SUBPROJECT AND (Build_Documentation AND NOT PythonSupport))
message(FATAL_ERROR "Build_Documentation=ON requires PythonSupport to be enabled")
endif()

# Benchmarks
option(Build_Benchs "Build Benchmarks" OFF)

# Testing
option(Build_Tests "Build tests" ON)
option(Build_SSO_Tests "Build same tests with various SSO/Custom Allocators" OFF)
option(Build_c2py_clair_Tests "Build tests for python converters using c2py and clair" OFF)
if(Build_Tests)
enable_testing()
endif()
Expand Down
12 changes: 0 additions & 12 deletions c++/nda/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,6 @@ if(Use_Magma)
install(TARGETS magma EXPORT ${PROJECT_NAME}-targets)
endif()

# ========= Compiler Wrapper ==========

# Get the compiler and linktime flags of nda_c
include(${PROJECT_SOURCE_DIR}/share/cmake/extract_flags.cmake)
extract_flags(nda_c)

# Generate and install python-based compiler wrapper
if(PythonSupport)
configure_file(nda++.in nda++ @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/nda++ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE DESTINATION bin)
endif()

# ========= Static Analyzer Checks ==========

option(ANALYZE_SOURCES OFF "Run static analyzer checks if found (clang-tidy, cppcheck)")
Expand Down
26 changes: 23 additions & 3 deletions python/nda_py/c2py_converters.hpp → c++/nda/c2py/converters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

#pragma once

#include <nda_py/nda_py.hpp>
#include <nda/nda.hpp>
#include "./make_numpy_proxy_from_array.hpp"

namespace c2py {

Expand Down Expand Up @@ -183,14 +184,14 @@ namespace c2py {
// if obj is not an numpy, we make a numpy and rerun
if (not PyArray_Check(obj) or (PyArray_Check(obj) and has_npy_type<T> and (PyArray_TYPE((PyArrayObject *)(obj)) != npy_type<T>))) {

cpp2py::pyref numpy_obj = make_numpy(obj);
c2py::pyref numpy_obj = make_numpy(obj);
EXPECTS(not PyErr_Occurred());
return py2c(numpy_obj);
}

if constexpr (has_npy_type<T>) {
if (not numpy_check_layout<R, nda::C_layout>(obj)) {
cpp2py::pyref obj_c_order = make_numpy(obj);
c2py::pyref obj_c_order = make_numpy(obj);
return array_t{converter_view_T::py2c(obj_c_order)};
}
return converter_view_T::py2c(obj);
Expand All @@ -209,4 +210,23 @@ namespace c2py {
}
};

template <typename T, int R, char Algebra>
struct py_converter<nda::basic_array<T, R, nda::C_layout, Algebra, nda::heap<>> const &> {
using array_t = nda::basic_array<T, R, nda::C_layout, Algebra, nda::heap<>>;
static PyObject *c2py(array_t const &a) { return cxx2py(nda::make_const_view(a)); }
};

template <typename T, int R, char Algebra>
struct py_converter<nda::basic_array<T, R, nda::C_layout, Algebra, nda::heap<>> &> {
using array_t = nda::basic_array<T, R, nda::C_layout, Algebra, nda::heap<>>;
using view_t = nda::basic_array_view<T, R, nda::C_layout, Algebra>;
static PyObject *c2py(array_t &a) { return cxx2py(view_t(a)); }
};

template <typename E>
requires(nda::is_expression<std::decay_t<E>>)
struct py_converter<E> {
static PyObject *c2py(E const &ex) { return cxx2py(nda::make_regular(ex)); }
};

} // namespace c2py
66 changes: 66 additions & 0 deletions c++/nda/c2py/make_numpy_proxy_from_array.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) 2019--present, The Simons Foundation
// This file is part of TRIQS/nda and is licensed under the Apache License, Version 2.0.
// SPDX-License-Identifier: Apache-2.0
// See LICENSE in the root of this distribution for details.

#pragma once
#include <vector>
#include <nda/nda.hpp>
#include <c2py/converters/numpy_proxy.hpp>
#include "./make_py_capsule.hpp"

namespace nda::python {

using c2py::npy_type;

// Given an array or a view, it returns the numpy_proxy viewing its data
// NB : accepts ref, rvalue ref
// AUR is array<T,R> or array_view<T, R>, but NOT a the Array concept.
// It must be a container or a view.
template <MemoryArray AUR>
c2py::numpy_proxy make_numpy_proxy_from_array_or_view(AUR &&a)
requires(is_regular_or_view_v<AUR>)
{

using A = std::decay_t<AUR>;
using value_type = typename A::value_type; // NB May be const
using T = get_value_t<A>; // The canonical type without the possible const
static_assert(not std::is_reference_v<value_type>, "Logical Error");

// If T is a type which has a native Numpy equivalent, or it is PyObject * or pyref.
// we simply take a numpy of the data
if constexpr (c2py::has_npy_type<T>) {
std::vector<long> extents(A::rank), strides(A::rank);

for (int i = 0; i < A::rank; ++i) {
extents[i] = a.indexmap().lengths()[i];
strides[i] = a.indexmap().strides()[i] * sizeof(T);
}

return {A::rank, // dimension
npy_type<T>, // the npy type code
(void *)a.data(), // start of the data
std::is_const_v<value_type>, // if const, the numpy will be immutable in python
std::move(extents),
std::move(strides),
make_pycapsule(a.storage())}; // a PyCapsule with a SHARED view on the data
} else {
// If T is another type, which requires some conversion to python
// we make a new array of pyref and return a numpy view of it.
// each pyref handles the ownership of the object according to the T conversion rule,
// it is not the job of this function to handle this.
// We need to distinguish the special case where a is a RValue, in which case, the python will steal the ownership
// by moving the elements one by one.

nda::array<c2py::pyref, A::rank> aobj = map([](auto &&x) {
if constexpr (is_regular_v<AUR> and !std::is_reference_v<AUR>)
// nda::array rvalue (i.e. AUR is an array, and NOT a ref, so it matches array &&) Be sure to move
return c2py::py_converter<T>::c2py(std::move(x));
else
return c2py::py_converter<T>::c2py(x);
})(a);
return make_numpy_proxy_from_array_or_view(std::move(aobj));
}
}

} // namespace nda::python
File renamed without changes.
8 changes: 8 additions & 0 deletions c++/nda/declarations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,14 @@ namespace nda {
template <char OP, typename L, typename R>
inline constexpr layout_info_t get_layout_info<expr<OP, L, R>> = expr<OP, L, R>::compute_layout_info();

/// Specialization of nda::is_expression for nda::expr_unary types.
template <char OP, Array A>
inline constexpr bool is_expression<expr_unary<OP, A>> = true;

/// Specialization of nda::is_expression for nda::expr types.
template <char OP, typename L, typename R>
inline constexpr bool is_expression<expr<OP, L, R>> = true;

/** @} */

} // namespace nda
4 changes: 4 additions & 0 deletions c++/nda/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ namespace nda {
template <typename F, Array... As>
constexpr char get_algebra<expr_call<F, As...>> = detail::_impl_find_common_algebra(get_algebra<As>...);

/// Specialization of nda::is_expression for nda::expr_call types.
template <typename F, Array... As>
inline constexpr bool is_expression<expr_call<F, As...>> = true;

/**
* @addtogroup av_math
* @{
Expand Down
26 changes: 0 additions & 26 deletions c++/nda/nda++.in

This file was deleted.

2 changes: 1 addition & 1 deletion c++/nda/nda.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@

// If we are using c2py, include converters automatically
#ifdef C2PY_INCLUDED
#include <nda_py/c2py_converters.hpp>
#include "./c2py/converters.hpp"
#endif
9 changes: 9 additions & 0 deletions c++/nda/traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ namespace nda {
return std::tuple_size_v<std::remove_cvref_t<decltype(std::declval<A const>().shape())>>;
}();

/// Constexpr variable that is true if type `A` is a lazy expression type.
template <typename A>
inline constexpr bool is_expression = false;

// Specialization of nda::is_expression for cvref types.
template <typename A>
requires(!std::is_same_v<A, std::remove_cvref_t<A>>)
inline constexpr bool is_expression<A> = is_expression<std::remove_cvref_t<A>>;

/// Constexpr variable that is true if type `A` is a regular array, i.e. an nda::basic_array.
template <typename A>
inline constexpr bool is_regular_v = false;
Expand Down
8 changes: 0 additions & 8 deletions deps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,3 @@ if(MPISupport)
GIT_TAG unstable
)
endif()

## Pybind 11
#find_package(Python)
#add_subdirectory(pybind11)
## Cf https://github.com/pybind/pybind11/issues/1604
#if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
#target_compile_options(pybind11 INTERFACE -fsized-deallocation)
#endif()
3 changes: 1 addition & 2 deletions python/nda_py/nda_py.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@

#pragma once
#include <vector>
#include <nda/c2py/make_py_capsule.hpp>
#include <nda/nda.hpp>
#include <nda/concepts.hpp>

#include <cpp2py/py_converter.hpp>
#include <cpp2py/numpy_proxy.hpp>

#include "make_py_capsule.hpp"

namespace nda::python {

using cpp2py::npy_type;
Expand Down
61 changes: 0 additions & 61 deletions python/nda_py/pybind11_converters.hpp

This file was deleted.

Loading
Loading