3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-23 21:03:45 +01:00

parameters & wrapper

- new parameter class :
  parameters are viewed as form, built in C++, and filled in C++/python.
  Each field of the form as a precise C++ type (erased using standard techniques).
  First tests ok, to be reread/checked.

  TODO : serialization is commented. Lead to long compilation time & large code
  due to boost::serialization. Use h5 when possible.

- wrapper :
  - separated the converters of the wrapped type in the TRIQS library
  - necessary for parameters (it used outside an .so) and potentially
    other codes, outside an .so module
This commit is contained in:
Olivier Parcollet 2014-05-16 19:35:48 +02:00
parent a9bcc33c7e
commit af084f5d59
33 changed files with 902 additions and 1065 deletions

View File

@ -335,9 +335,9 @@ enable_testing()
option(Build_Documentation "Build the documentation ?" OFF)
option(Build_PDF_Documentation "Build the pdf documentation ?" OFF)
#------------------------
#------------------------------------------------------
# link libs for shared libs or for pytriqs
#------------------------
#------------------------------------------------------
set(TRIQS_LINK_LIBS
${TRIQS_LIBRARY_PYTHON}
@ -351,39 +351,39 @@ set(TRIQS_LINK_LIBS
# remove this dep to C++
include_directories(${TRIQS_SOURCE_DIR})
#------------------------
# General triqs libraries
#------------------------
#--------------------------------
# General C++ compilation flags
#--------------------------------
message( STATUS "TRIQS_CXX_DEFINITIONS = ${TRIQS_CXX_DEFINITIONS}")
#message( STATUS "TRIQS_CXX_DEFINITIONS = ${TRIQS_CXX_DEFINITIONS}")
# needed for utility/first_include.hpp that includes either the triqs_config.h installed in the proper directory
# (Case of an installed lib) or the triqs_config.h just generated in the built dir (when compiling the lib itself).
add_definitions ( ${TRIQS_CXX_DEFINITIONS} -DTRIQS_BUILDING_LIBRARY -I ${CMAKE_BINARY_DIR}/Config)
#---------------------------------------------------------------------
# pytriqs modules : MUST be before TRIQS, to have the py_converters
#---------------------------------------------------------------------
if (PythonSupport)
message( STATUS "-------- Preparing python extension modules -------------")
add_subdirectory(${TRIQS_SOURCE_DIR}/pytriqs )
endif (PythonSupport)
#------------------------
# General triqs libraries
#------------------------
add_subdirectory(${TRIQS_SOURCE_DIR}/triqs triqs)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
list (REMOVE_DUPLICATES TRIQS_LINK_LIBS)
endif( ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
#------------------------
# Applications
#------------------------
#add_subdirectory(${TRIQS_SOURCE_DIR}/applications )
#------------------------
# pytriqs modules
#------------------------
if (PythonSupport)
message( STATUS "-------- Preparing python modules -------------")
add_subdirectory(${TRIQS_SOURCE_DIR}/pytriqs )
endif (PythonSupport)
#------------------------
# tests
#------------------------
## Remove the test from the build ?
option(Build_Triqs_General_Tools_Test "Build the test of the general tool ? ( array class , ... ) " ON)
if (Build_Triqs_General_Tools_Test)
message( STATUS "-------- Preparing tests -------------")

View File

@ -6,21 +6,30 @@ include_directories(${PYTHON_INCLUDE_DIRS} ${PYTHON_NUMPY_INCLUDE_DIR})
# ModuleName = the python name of the module
# ModuleDest = path in the pytriqs tree [ FOR INSTALLATION ONLY] IMPROVE MAKE THIS OPTIONAL (for test)
#EXECUTE_PROCESS(COMMAND mkdir -p ${CMAKE_BINARY_DIR}/pytriqs/converters/)
include_directories( ${CMAKE_BINARY_DIR})
macro (triqs_python_extension ModuleName)
message(STATUS "TRIQS: Preparing extension module ${ModuleName} with the interpreter ${TRIQS_PYTHON_INTERPRETER} ")
message(STATUS "Preparing extension module ${ModuleName}")
SET(wrap_name ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_wrap.cpp)
SET(converter_name ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_converter.cpp)
# Adjust pythonpath so that pytriqs is visible and the wrap_generator too...
# pytriqs needed since we import modules with pure python method to extract the doc..
add_custom_command(OUTPUT ${wrap_name} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${ModuleName}_desc.py
COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/pytriqs/wrap_generator:${CMAKE_BINARY_DIR}/ ${PYTHON_INTERPRETER} ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_desc.py ${CMAKE_SOURCE_DIR}/pytriqs/wrap_generator/wrapper.mako.cpp ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_wrap.cpp )
add_custom_command(OUTPUT ${wrap_name} ${converter_name} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${ModuleName}_desc.py
COMMAND PYTHONPATH=${CMAKE_BINARY_DIR}/pytriqs/wrap_generator:${CMAKE_BINARY_DIR}/ ${PYTHON_INTERPRETER} ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_desc.py ${CMAKE_SOURCE_DIR}/pytriqs/wrap_generator/wrapper.mako.cpp ${wrap_name} ${CMAKE_SOURCE_DIR}/pytriqs/wrap_generator/py_converter_wrapper.mako.hpp ${converter_name} )
add_custom_target(python_wrap_${ModuleName} ALL DEPENDS ${wrap_name})
add_dependencies(python_wrap_${ModuleName} py_copy)
set_property (GLOBAL APPEND PROPERTY TRIQS_PY_CONVERTERS_CPP_LIST "${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_converter.cpp")
set_property (GLOBAL APPEND PROPERTY TRIQS_PY_CONVERTERS_TARGETS "python_wrap_${ModuleName}")
add_custom_target(python_wrap_${ModuleName} ALL DEPENDS ${wrap_name} ${converter_name})
#//add_custom_target(${ModuleName}_converter.cpp ALL DEPENDS ${wrap_name})
add_dependencies(python_wrap_${ModuleName} py_copy ${CMAKE_CURRENT_BINARY_DIR}/${ModuleName}_desc.py )
add_library(${ModuleName} MODULE ${wrap_name})
set_target_properties(${ModuleName} PROPERTIES PREFIX "") #eliminate the lib in front of the module name
set_target_properties(${ModuleName} PROPERTIES PREFIX "") #eliminate the lib in front of the module name
target_link_libraries(${ModuleName} ${TRIQS_LINK_LIBS} triqs)
if (${ARGN} MATCHES "")

View File

@ -27,7 +27,9 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/utility/mpi.py.in ${CMAKE_CURRENT_BIN
install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST})
# All subdirs
add_all_subdirectories_with_cmakelist()
#
add_custom_target(wrap_clean COMMAND find ${CMAKE_BINARY_DIR} -name \"*.cpp\" |xargs rm)

View File

@ -1,6 +1,7 @@
from wrap_generator import *
module = module_(full_name = "pytriqs.gf.local.gf", doc = "Local Green functions ...")
module.add_include("<typeindex>")
module.add_include("<triqs/gfs.hpp>")
module.add_include("<triqs/gfs/local/functions.hpp>")
module.add_include("<triqs/gfs/local/pade.hpp>")
@ -302,9 +303,13 @@ def make_gf( py_type, c_tag, is_complex_data = True, is_im = False) :
signature = "void()",
doc = "Put the Green function to 0")
# Pure python methods
# Pure python methods
g.add_pure_python_method("pytriqs.gf.local._gf_%s.plot"%c_tag, py_name = "_plot_")
g.add_method(py_name = "_as_C_pointer",
calling_pattern = 'auto result = PyCapsule_New(new std::pair<void *,std::type_index>(&self_c,typeid(self_c)),NULL,NULL)',
signature = "PyObject*()")
return g
########################
@ -391,4 +396,5 @@ module.add_function(name = "make_gf_from_inverse_fourier", signature="gf_view<re
if __name__ == '__main__' :
module.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
module.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])

View File

@ -4,7 +4,7 @@ SET(PYTHON_SOURCES
install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/parameters)
cython_module(Parameters parameters parameters )
triqs_python_extension(parameters parameters )
FILE(GLOB all_pxd_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.pxd )
install (FILES ${all_pxd_files} DESTINATION "include/pytriqs/parameters")

View File

@ -1,21 +0,0 @@
from libcpp.string cimport string as std_string
from libcpp.vector cimport vector
cdef extern from "triqs/parameters/parameters.hpp" namespace "triqs::parameters" :
cdef cppclass _object "triqs::utility::_object":
#cdef cppclass _object "triqs::parameters::_object":
_object()
#cdef cppclass parameters " triqs::parameters::parameters" :
cdef cppclass parameters "triqs::utility::parameters" :
parameters()
_object operator[](std_string &)
std_string print_ "print" ()
cdef cppclass parameter_defaults "triqs::utility::parameter_defaults" :
parameter_defaults()
vector[vector[std_string]] generate_help()
cdef class Parameters:
cdef parameters _c

View File

@ -1,89 +0,0 @@
from dcomplex cimport *
from shared_ptr cimport *
from arrays cimport *
from inserter_in_map cimport *
from libcpp.pair cimport pair
from libcpp.vector cimport vector
from libcpp.string cimport string as std_string
from cython.operator cimport dereference as deref, preincrement as inc #dereference and increment operator
import numpy as np
cdef extern from "triqs/parameters/parameters.hpp" namespace "triqs::parameters" :
cdef cppclass extract_strict "triqs::utility::extract_strict" [T]:
extract_strict()
bint is_possible(_object &)
T invoke(_object &)
cdef class Parameters:
"""
"""
#cdef parameters _c
def __init__(self) :
""" """
self._c = parameters()
def __getitem__(self, key) :
cdef _object _o = self._c[key]
if extract_strict[long]().is_possible(_o) : return extract_strict[long]().invoke(_o)
if extract_strict[double]().is_possible(_o) : return extract_strict[double]().invoke(_o)
if extract_strict[std_string]().is_possible(_o) : return extract_strict[std_string]().invoke(_o)
if extract_strict[int]().is_possible(_o) : return extract_strict[int]().invoke(_o)
if extract_strict[parameters]().is_possible(_o) :
pp = Parameters()
pp._c = extract_strict[parameters]().invoke(_o)
return pp
if extract_strict[array_view[long, ONE]]().is_possible(_o) : return extract_strict[array_view[long,ONE]]().invoke(_o).to_python()
if extract_strict[array_view[long, TWO]]().is_possible(_o) : return extract_strict[array_view[long,TWO]]().invoke(_o).to_python()
if extract_strict[array_view[long, THREE]]().is_possible(_o): return extract_strict[array_view[long,THREE]]().invoke(_o).to_python()
if extract_strict[array_view[double,ONE]]().is_possible(_o) : return extract_strict[array_view[double,ONE]]().invoke(_o).to_python()
if extract_strict[array_view[double,TWO]]().is_possible(_o) : return extract_strict[array_view[double,TWO]]().invoke(_o).to_python()
if extract_strict[array_view[double,THREE]]().is_possible(_o) : return extract_strict[array_view[double,THREE]]().invoke(_o).to_python()
if extract_strict[vector[std_string]]().is_possible(_o) : return extract_strict[vector[std_string]]().invoke(_o)
if extract_strict[vector[long]]().is_possible(_o) : return extract_strict[vector[long]]().invoke(_o)
raise ValueError, "Can not extract the key %s"%key
def __setitem__(self, key, rhs) :
if isinstance(rhs, int) : inserter_in_map[parameters,long](self._c)(key, rhs)
elif isinstance(rhs, float) : inserter_in_map[parameters,double](self._c)(key, rhs)
elif isinstance(rhs, str) : inserter_in_map[parameters,std_string](self._c)(key, rhs)
elif isinstance(rhs, Parameters) : inserter_in_map[parameters,parameters](self._c)(key, (<Parameters>rhs)._c)
elif isinstance(rhs, dict) : self[key] = Parameters().update(rhs)
elif isinstance(rhs, list) or isinstance(rhs,tuple) :
if set([type(x) for x in rhs]) == set([type('')]) : # list or tuple of string
inserter_in_map[parameters,vector[std_string]](self._c)(key, rhs)
elif set([type(x) for x in rhs]) == set([type(1)]) : # list or tuple of int
inserter_in_map[parameters,vector[long]](self._c)(key, rhs)
else :
raise TypeError, "List and tuple are not supported by Parameters. Please use numpy arrays"
elif isinstance(rhs, np.ndarray) :
try : inserter_in_map[parameters,array_view[long,ONE]](self._c)(key, array_view[long,ONE](rhs))
except : pass
try : inserter_in_map[parameters,array_view[long,TWO]](self._c)(key, array_view[long,TWO](rhs))
except : pass
try : inserter_in_map[parameters,array_view[long,THREE]](self._c)(key, array_view[long,THREE](rhs))
except : pass
try : inserter_in_map[parameters,array_view[double,ONE]](self._c)(key, array_view[double,ONE](rhs))
except : pass
try : inserter_in_map[parameters,array_view[double,TWO]](self._c)(key, array_view[double,TWO](rhs))
except : pass
try : inserter_in_map[parameters,array_view[double,THREE]](self._c)(key, array_view[double,THREE](rhs))
except : pass
else :
raise TypeError, "Unknown object : key = %s, rhs = %s"%(key, rhs)
def __repr__(self) :
return printer[parameters]()(self._c)
def update(self, d) :
for k,v in d.items(): self[k]=v
return self
def update2(self, **d) : return self.update(d)

View File

@ -0,0 +1,41 @@
from wrap_generator import *
# The module
module = module_(full_name = "pytriqs.parameters.parameters.my_module", doc = " Doc of my_module ")
module.add_include("<triqs/parameters/parameters.hpp>")
module.add_include("<triqs/utility/formatted_output.hpp>")
module.add_using("namespace triqs::params")
# one class
g = class_(
py_type = "Parameters",
c_type = "parameters",
#serializable= "tuple",
is_printable= True,
hdf5 = True,
# Add + for merging
arithmetic = ("only_add")
)
#add a constructor
#g.add_constructor(doc = "DOC of constructor", args = [])
g.add_method(py_name = "help", calling_pattern = "auto result = triqs::utility::print_formatted(self_c.generate_help())", signature = "std::string()", doc = "help")
# add getitem/setitem ...
g.add_getitem(signature = "PyObject *(const char * key)",
calling_pattern = "PyObject * result = self_c[key].to_python()",
doc = "")
g.add_setitem(signature = "void(const char * key, PyObject * ob)",
calling_pattern = """
if (!self_c[key].from_python_convertible(ob)) return NULL; // early exit, the error is set by the converter
self_c[key].set_from_python(ob);
""",
doc = "")
module.add_class(g)
if __name__ == '__main__' :
module.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
module.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])

View File

@ -0,0 +1,61 @@
// Specialization of py_converter to types wrapped by the wrap_generator.
// DO NOT EDIT. Generated automatically by wrap_generator
%for file in module.include_list :
%if file.startswith('<'):
#include ${file}
%else:
#include "${file}"
%endif
%endfor
using dcomplex = std::complex<double>;
%for ns in module.using:
using ${ns};
%endfor
//#include <triqs/arrays.hpp>
#include <triqs/python_tools/wrapper_tools.hpp>
namespace triqs { namespace py_tools {
%for n,t in enumerate(module.wrapped_types_by_me) :
template<> struct py_converter<${t}> {
static void ** init();
static PyObject * c2py(${t} const & x);
static ${t}& py2c(PyObject * ob);
static bool is_convertible(PyObject *ob, bool raise_exception);
};
void ** py_converter<${t}>::init() {
PyObject * mod = PyImport_ImportModule("${module.full_name}");
if (mod ==NULL) return NULL;
void ** table = (void **)PyCapsule_Import("${module.full_name}._exported_wrapper_convert_fnt", 0);
return table;
}
PyObject * py_converter<${t}>::c2py(${t} const & x){
static void **wrapped_convert_fnt = init();
if (wrapped_convert_fnt == NULL) return NULL;
return ((PyObject * (*)(${t} const &)) wrapped_convert_fnt[3*${n}])(x);
}
${t}& py_converter<${t}>::py2c(PyObject * ob){
static void **wrapped_convert_fnt = init();
if (wrapped_convert_fnt == NULL) std::terminate(); // It should never happen since py2c is called only is is_convertible is true (py_converter specs)
return ((${t}& (*)(PyObject *)) wrapped_convert_fnt[3*${n}+1])(ob);
}
bool py_converter<${t}>::is_convertible(PyObject *ob, bool raise_exception) {
static void **wrapped_convert_fnt = init();
if (wrapped_convert_fnt == NULL) {
if (!raise_exception && PyErr_Occurred()) {PyErr_Print();PyErr_Clear();}
return false;
}
return ((bool (*)(PyObject *,bool)) wrapped_convert_fnt[3*${n}+2])(ob,raise_exception);
}
%endfor
}}

View File

@ -66,6 +66,8 @@ class cfunction :
self.rtype = kw.pop("rtype", None)
args = kw.pop('args',())
for a in args: # put back the default if there is none
if a[0] == 'const' : a = [' '.join(a[:2])] + list(a[2:])
if a[1] == '*' : a = [' '.join(a[:2])] + list(a[2:])
if len(a) == 2 : (t,n),d = a,None
elif len(a) == 3 : t,n,d = a
else : raise RuntimeError, "Syntax error in overload: args = %s"%args
@ -265,15 +267,17 @@ class class_ :
# expect a tuple : "algebra", "scalar1", "scalar2", etc...
self.number_protocol = {}
if arithmetic :
add = arithmetic[0] in ("algebra", "abelian_group", "vector_space", "only_add")
abelian_group = arithmetic[0] in ("algebra", "abelian_group", "vector_space")
vector_space = arithmetic[0] in ("algebra", "vector_space")
algebra = arithmetic[0] in ("algebra")
if abelian_group :
if add :
# add
add = pyfunction(py_name ="__add__")
add.arity = 2
add.add_overload (calling_pattern = "+", args = [(self.c_type,'x'), (self.c_type,'y')], rtype = self.c_type)
self.number_protocol['add'] = add
if abelian_group :
#sub
sub = pyfunction(py_name ="__sub__")
sub.arity = 2
@ -424,7 +428,6 @@ class module_ :
Representation of a module
Data :
- name : name of the module
- imported_modules : name of the modules to import (with their wrapped type converters)
- doc : the doc string.
- classes : dict : string -> class_. Key is the Python type
- c_types : dict : string -> string. Correspondance Python type -> C++ type
@ -433,7 +436,7 @@ class module_ :
"""
wrapped_types = {}
def __init__(self, full_name, imported_modules = (), doc = '') :
def __init__(self, full_name, doc = '') :
self.full_name = full_name
self.name = full_name.rsplit('.',1)[-1]
self.doc = doc
@ -441,17 +444,11 @@ class module_ :
self.functions = {}
self.include_list = []
self.wrapped_types_by_me = {}
self.imported_wrapped_types = {}
self.enums = []
self.using =[]
self.python_functions = {}
self.hidden_python_functions = {}
assert type(imported_modules) in [type(()), type([])]
for m_desc in imported_modules:
m = importlib.import_module("%s_desc"%m_desc)
self.imported_wrapped_types[m_desc] = m.module.wrapped_types
def add_class(self, cls):
if cls.py_type in self.classes : raise IndexError, "The class %s already exists"%cls.py_type
self.classes[cls.py_type] = cls
@ -510,3 +507,15 @@ class module_ :
rendered = tpl.render(module=self, regular_type_if_view_else_type= regular_type_if_view_else_type, is_type_a_view = is_type_a_view)
with open(wrap_file,'w') as f:
f.write(rendered)
def generate_py_converter_header(self, mako_template, wrap_file) :
self.prepare_for_generation()
tpl = Template(filename=mako_template)
rendered = tpl.render(module=self)
with open(wrap_file,'w') as f:
f.write(rendered)
#def generate_code_and_header(self, arglist) :
# self.generate_code(mako_template = arglist.argv[0], wrap_file = arglist.argv[1])
# self.generate_py_converter_header(mako_template = arglist.argv[2], wrap_file = arglist.argv[3])

View File

@ -23,32 +23,6 @@ using namespace triqs::py_tools;
static PyObject * _module_hidden_python_function = NULL;
%endif
//--------------------- Reconnect the types wrapped in exported modules -----------------------------
%for m, t_dic in module.imported_wrapped_types.items() :
static void ** _imported_wrapped_convert_fnt_from_${m}; // initialized in init function
%for n,t in enumerate(t_dic) :
namespace triqs { namespace py_tools {
template<> struct py_converter<${t}> {
static PyObject * c2py(${t} const & x){
return ((PyObject * (*)(${t} const &)) _imported_wrapped_convert_fnt_from_${m}[3*${n}])(x);
}
static ${t}& py2c(PyObject * ob){
return ((${t}& (*)(PyObject *)) _imported_wrapped_convert_fnt_from_${m}[3*${n}+1])(ob);
}
static bool is_convertible(PyObject *ob, bool raise_exception) {
return ((bool (*)(PyObject *,bool)) _imported_wrapped_convert_fnt_from_${m}[3*${n}+2])(ob,raise_exception);
}
};
}}
%endfor
%endfor
// We use the order, in the following order (which is necessary for compilation : we need the converters in the implementations)
// - function/method declaration
// - implement type, and all tables
@ -1006,16 +980,10 @@ init${module.name}(void)
%endfor
/* Create a Capsule containing the API pointer array's address */
PyObject *c_api_object = PyCapsule_New((void *)_exported_wrapped_convert_fnt, "${module.name}._exported_wrapper_convert_fnt", NULL);
PyObject *c_api_object = PyCapsule_New((void *)_exported_wrapped_convert_fnt, "${module.full_name}._exported_wrapper_convert_fnt", NULL);
if (c_api_object != NULL) PyModule_AddObject(m, "_exported_wrapper_convert_fnt", c_api_object);
%endif
// Now import wrappers from other modules, if any
%for m in module.imported_wrapped_types :
_imported_wrapped_convert_fnt_from_${m} = (void **)PyCapsule_Import("${m}._exported_wrapper_convert_fnt", 0);
//if (_imported_wrapped_convert_fnt_from_${m} ==NULL) // Nothing, the interpreter has raised an error already.
%endfor
%if len(module.python_functions) + len(module.hidden_python_functions) > 0 :
PyObject* main_module = PyImport_AddModule("__main__"); //borrowed

View File

@ -9,6 +9,7 @@ install (FILES ${PYTHON_SOURCES} DESTINATION ${TRIQS_PYTHON_LIB_DEST}/wrap_test)
# Build C extension module
triqs_python_extension(my_module wrap_test)
triqs_python_extension(my_moduleB wrap_test)
# ??triqs_set_rpath_for_target(my_module)
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )

View File

@ -126,28 +126,28 @@ struct A {
};
/// some function using A
void print_a(A const & a) {
inline void print_a(A const & a) {
std::cout << "my a is " << a.x << std::endl;
}
/// function with an error
void print_err(A const &a) {
inline void print_err(A const &a) {
TRIQS_RUNTIME_ERROR << "hum does not look good" << a;
}
/// DOC make_vector...
std::vector<int> make_vector(int size) {
inline std::vector<int> make_vector(int size) {
std::vector<int> r(size, 0);
for (int i = 0; i < size; ++i)
r[i] = i;
return r;
}
std::vector<std::vector<int> > make_vector2(int size) {
inline std::vector<std::vector<int> > make_vector2(int size) {
return { make_vector(size), make_vector(size + 1) };
}
std::vector<int> vector_x2(std::vector<int> const &v) {
inline std::vector<int> vector_x2(std::vector<int> const &v) {
auto r = v;
for (auto &x : r)
x *= 2;
@ -159,35 +159,35 @@ using triqs::arrays::array;
using triqs::arrays::range;
using namespace triqs::arrays;
void iter_on_range(range r){
inline void iter_on_range(range r){
foreach(r, [](int i) { std::cout << i << std::endl;});
}
matrix<double> make_matrix(int size) { return make_unit_matrix<double>(size); }
inline matrix<double> make_matrix(int size) { return make_unit_matrix<double>(size); }
void print_matrix(matrix<double> const &M) {
inline void print_matrix(matrix<double> const &M) {
// std::cout << M <<std::endl;
}
std::function<int(int,int)> make_fnt_ii() {
inline std::function<int(int,int)> make_fnt_ii() {
return [](int i, int j) { return i + 2*j;};
}
std::function<int(int,int,double)> make_fnt_iid() {
inline std::function<int(int,int,double)> make_fnt_iid() {
return [](int i, int j, double a) { return a+ i + 2*j;};
}
void use_fnt_ii(std::function<int(int,int)> f) {
inline void use_fnt_ii(std::function<int(int,int)> f) {
std::cout << "use_fnt ii \n"<< f(1,2) << std::endl;
}
void use_fnt_iid(std::function<int(int,int,double)> f) {
inline void use_fnt_iid(std::function<int(int,int,double)> f) {
std::cout << "use_fnt iid \n"<< f(1,2,4.5) << std::endl;
}
std::function<void(int,int)> make_fnt_void() {
inline std::function<void(int,int)> make_fnt_void() {
return [](int i, int j) { std::cout << " I am a C++ lambda : "<<i <<" "<< j << std::endl;};
}

View File

@ -1,6 +1,6 @@
#include "./a.hpp"
/// some function using A
void print_a2(A const & a) {
inline void print_a2(A const & a) {
std::cout << "module B : my a is " << a.x << std::endl;
}

View File

@ -1,10 +1,11 @@
from wrap_generator import *
# The module
mod = module_(full_name = "pytriqs.wrap_test.my_moduleB", imported_modules = ["my_module"], doc = " Doc of my_module ")
mod.add_include("../c++/b.hpp") # FIX PUT ASOLUTE NAME
mod = module_(full_name = "pytriqs.wrap_test.my_moduleB", doc = " Doc of my_module ")
mod.add_include("<triqs/../pytriqs/wrap_test/b.hpp>")
mod.add_function (name = "print_a2", signature = "void(A a)", doc = "DOC of print_a")
mod.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
mod.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])

View File

@ -2,7 +2,7 @@ from wrap_generator import *
# The module
module = module_(full_name = "pytriqs.wrap_test.my_module", doc = " Doc of my_module ")
module.add_include("./a.hpp")
module.add_include("<triqs/../pytriqs/wrap_test/a.hpp>")
module.add_include("<triqs/arrays.hpp>")
# one class
@ -101,4 +101,5 @@ module.add_python_function(f1)
if __name__ == '__main__' :
module.generate_code(mako_template = sys.argv[1], wrap_file = sys.argv[2])
module.generate_py_converter_header(mako_template = sys.argv[3], wrap_file = sys.argv[4])

View File

@ -2,51 +2,103 @@
#include <iostream>
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
using namespace triqs::utility;
using namespace triqs::params;
using namespace triqs::arrays;
int main() {
try {
parameters P,P2;
parameter_defaults pdef;
pdef.required ( "A", int(), "really ?") ;
P.add_field("A", no_default<int>(), "really ?")
.add_field("D", 2.0, " int ")
.add_field("E", 3u, " unsigned int ")
.add_field("F", long(4), " long ")
.add_field("B", short(0), " short ")
.add_field("C", 1u, " unsigned short ")
.add_field("G", 5ll, " long ")
.add_field("I", double(7.8), " doube ")
.add_field("K", std::complex<double>(12), " double complex ")
.add_field("L", std::string("13"), " string ")
.add_field("M", std::vector<double>{1, 4}, " vector ")
.add_field("Ml", std::vector<double>{1, 2, 3, 4, 5, 6, 7, 8, 9}, " a long vector ")
.add_field("N", double(15), "")
.add_field("s", no_default<std::string>(), "")
.add_field("sc", no_default<std::string>(), "")
.add_field("a1", no_default<array<double, 2>>(), " A nice array")
.add_field("a2", no_default<array<long, 1>>(), "")
.add_field("W", int(16), "");
pdef.optional( "B", short(0), " short ")
.optional( "C", 1u, " unsigned short ")
.optional( "D", int(2), " int ")
.optional( "E", 3u, " unsigned int ")
.optional( "F", long(4), " long ")
.optional( "G", 5ll, " long ")
.optional( "H", float(6), " float ")
.optional( "I", double(7.8), " doube ")
.optional( "K", std::complex<double>(12), " double complex ")
.optional( "L", std::string("13"), " string ")
.optional( "M", std::vector<double> { 1,4 }, " vector ")
.optional( "N", double(15), "")
.optional( "W", int(16), "")
;
std::cout << P << std::endl;
P2 = P;
P2.sort_by_key();
std::cout << P2 << std::endl;
auto P_vide = P ;
P["a"] = long(1);
P["d"] = 2.7;
P["A"] = long(1);
std::cout << P["A"];
P["D"] = 2;
P["D"] = 2.5;
P["s"] = std::string("-14.3");
P["sc"] = "-14.3";
triqs::arrays::array<double,2> A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2;
triqs::arrays::array<long,1> B(3); B()=0;B(0) = 3; B(1) = -8;
P["A"] = std::move(A);
P["B"] = B;
array<double,2> A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2;
array<long,1> B(100); B()=8; B(0) = 3; B(1) = -8;
P["a1"] = std::move(A);
P["a2"] =B;
// errors
//P["D"] = "eee";
//int i = P["D"];
std::cout << P << std::endl;
// P2.update(pdef);
// testing that copy is a copy
P2["A"] = 12;
std::cout << P["A"] << std::endl;
std::cout << P2["A"] << std::endl;
// put a subparameter ...
P.add_group("Group1", " doc ");
P["Group1"].add_field("a", 1, "sub a 1");
P["Group1"]["a"] = 10;
P["Group1"].add_group("subgroup1.2", " doc ");
P["Group1"]["subgroup1.2"].add_field("d", 1.8, "d is a double");
P["Group1"]["subgroup1.2"]["d"] = 10.2;
std::cout << P << std::endl;
std::cout << pdef<< std::endl;
//std::cout << P["Group1"] << std::endl;
// hdf5
{
H5::H5File file( "ess.h5", H5F_ACC_TRUNC );
h5_write( file, "Parameters", P);
}
{
H5::H5File file( "ess.h5", H5F_ACC_RDONLY );
h5_read( file.openGroup("/"), "Parameters", P_vide);
}
std::cout << P_vide << std::endl;
{
H5::H5File file( "ess.h5", H5F_ACC_RDONLY );
h5_read( file.openGroup("/"), "Parameters", P);
}
//std::cout << P << std::endl;
try {
P2 = P;
P2.update(pdef);
}
catch (triqs::runtime_error const & e) {
std::cout<< " Caught as expected : update_with_defaults error "<< e.what() << std::endl ;
std::cout<< " Caught "<< e.what() << std::endl ;
}
std::cout << P2 << std::endl;
}

View File

@ -10,24 +10,28 @@
#include <boost/mpi/communicator.hpp>
#include <boost/serialization/complex.hpp>
using namespace triqs::utility;
using namespace triqs::params;
int main(int argc, char* argv[]) {
boost::mpi::environment env(argc, argv);
boost::mpi::communicator world;
parameters P;
P.add_field("a", 1, "?")
.add_field("d", 2.0, "")
.add_field("s", "", "");
if (world.rank() == 0) {
P["a"] = long(1);
P["d"] = 2.7;
P["s"] = std::string("-14.3");
}
/*
* WITH SERIALIZATION
std::cout << "Before bcast rank " << world.rank() << " : " << P << std::endl ;
boost::mpi::broadcast(world,P,0);
std::cout << "After bcast rank " << world.rank() << " : " << P << std::endl ;
*/
return 0;
}

View File

@ -3,8 +3,9 @@
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
using namespace triqs;
using namespace triqs::utility;
using triqs::arrays::array;
using namespace triqs::params;
using namespace triqs::arrays;
using triqs::arrays::array;
// what is the concept of things that can be put in the dict ?
struct my_obj {
@ -39,43 +40,37 @@ struct my_obj {
void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("i",i); }
};
// just to make the object printable
namespace std {
template<typename K, typename V>
std::ostream & operator << (std::ostream & out, std::map<K,V> const &) { return out << "map";}
}
namespace std {
template<typename K, typename V>
std::string get_triqs_hdf5_data_scheme (std::map<K,V> const &) {
using triqs::get_triqs_hdf5_data_scheme;// for the basic types, not found by ADL
std::stringstream fs;
fs<<"map<"<<get_triqs_hdf5_data_scheme(K())<<","<<get_triqs_hdf5_data_scheme(V())<<">";
return fs.str();
}
}
int main() {
try {
parameters P;
P["myobject1"] = my_obj(18);
P.add_field("a", 1, "?")
.add_field("d", 2.0, "")
.add_field("s", "", "")
.add_field("sc", "", "")
.add_field("U", no_default<array<double, 2>>(), "")
.add_field("A", no_default<matrix<double>>(), "")
.add_field("V", no_default<arrays::vector<double>>(), "")
.add_field("B", no_default<array<long, 1>>(), "")
//.add_field("myobject1", no_default<my_obj>(), "")
;
//P["myobject1"] = my_obj(18);
P["a"] = long(1);
P["d"] = 2.7;
P["s"] = std::string("-14.3");
P["sc"] = "-14.3";
std::map<std::string, int> mm;
mm["qwe"] = 123;
P["mm"] = mm;
std::cout << " map = "<< P["mm"]<< std::endl ;
std::cout << "123 = "<<utility::extract<std::map<std::string,int>>(P["mm"])["qwe"]<< std::endl ;
// raises an error as it should ...
//std::cout << utility::extract<int>(P["d"]) << std::endl;
try {
std::cout << extract<int>(P["d"]) << std::endl;
}
catch(std::exception const & e) {
std::cout << "caught error "<< e.what() <<std::endl;
}
triqs::arrays::array<double,2> A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2;
triqs::arrays::array<long,1> B(3); B()=0;B(0) = 3; B(1) = -8;
@ -92,17 +87,26 @@ int main() {
C = extract<decltype(C)>(P["B"]);
std::cout << "C" << C << std::endl;
array<array<int,2>, 1> aa(2);
// testing that I can extract a view and modify it.
triqs::arrays::array_view<long, 1> VC = extract<triqs::arrays::array_view<long, 1>>(P["B"]);
std::cout << "VC" << VC << std::endl;
VC(0) *= 2;
C = extract<decltype(C)>(P["B"]);
std::cout << "C" << C << std::endl;
/*array<array<int,2>, 1> aa(2);
aa(0) = A; aa(1) = 2*A;
P["aa"] = aa;
std::cout << "get_triqs_hdf5_data_scheme :"<< get_triqs_hdf5_data_scheme(aa)<< std::endl;
*/
long j = P["a"];
double x = P["d"];
double y = P["a"];
double z = P["s"];
double zc = P["sc"];
std::string rs = P["s"];
std::cout << j << std::endl ;
std::cout << x << std::endl;
@ -110,17 +114,8 @@ int main() {
std::cout << z << std::endl ;
std::cout << zc << std::endl ;
std::cout << P["a"] << std::endl ;
std::cout << P["aa"] << std::endl ;
//std::cout << P["aa"] << std::endl ;
std::cout << P["s"] << std::endl ;
std::string rs = P["s"];
// testing that copy is a copy
parameters P2 = P;
P2["a"] = 12.3;
// Put P2 in P ...
P["P2"] = P2;
std::cout << P << std::endl;
@ -129,22 +124,7 @@ int main() {
h5_write( file, "Parameters", P);
}
{
H5::H5File file( "ess2.h5", H5F_ACC_TRUNC );
h5_write( file, "Parameters", P2);
}
std::string s = triqs::serialize(P);
parameters P3 = triqs::deserialize<parameters>(s);
{
H5::H5File file( "ess3.h5", H5F_ACC_TRUNC );
h5_write( file, "Parameters", P3);
}
parameters P4;
parameters::register_type<triqs::arrays::array<double,1>>();
//parameters::register_type<triqs::arrays::array<int,2>>();
std::cout << "P4 before : "<< P4<< std::endl ;
auto P4 = P;
{
H5::H5File file( "ess.h5", H5F_ACC_RDONLY );
h5_read( file.openGroup("/"), "Parameters", P4);
@ -153,11 +133,8 @@ int main() {
H5::H5File file( "ess_relo.h5", H5F_ACC_TRUNC );
h5_write( file.openGroup("/"), "Parameters", P4);
}
std::cout << "P4 after : "<< P4<< std::endl ;
std::cout << "P4 after : \n"<< P4<< std::endl ;
std::cout << "map retrieval "<<utility::extract<std::map<std::string,int>>(P4["mm"])["qwe"]<< std::endl ;
//std::cout << triqs::deserialize<array<array<int,2>,1>>(utility::extract<std::string>(P4["aa"])) << std::endl ;
}
TRIQS_CATCH_AND_ABORT;
}

View File

@ -1,46 +0,0 @@
#include <triqs/parameters.hpp>
#include <iostream>
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
using namespace triqs;
using namespace triqs::utility;
int main() {
parameters P;
P["a"] = long(1);
P["d"] = 2.7;
P["s"] = std::string("-14.3");
P["sc"] = "-14.3";
triqs::arrays::array<double,2> A(2,2); A()=0;A(0,0) = 1.3; A(1,1) = -8.2;
triqs::arrays::array<long,1> B(3); B()=0;B(0) = 3; B(1) = -8;
triqs::arrays::matrix<double> U(2,2);U()=1.;
P["U"] = U;
triqs::arrays::vector<double> V(3);V()=1.;
P["V"] = V;
P["A"] = std::move(A);
P["B"] = B;
std::cout << "A"<< P["A"] << std::endl;
std::cout << "B"<< P["B"] << std::endl;
triqs::arrays::array<long,1> C;
C = extract<decltype(C)>(P["B"]);
std::cout << "C" << C << std::endl;
// testing that I can extract a view and modify it.
triqs::arrays::array_view <long,1> VC = extract<triqs::arrays::array_view <long,1>>(P["B"]);
std::cout << "VC" << VC << std::endl;
VC(0) *=2;
C = extract<decltype(C)>(P["B"]);
std::cout << "C" << C << std::endl;
{
H5::H5File file( "ess.h5", H5F_ACC_TRUNC );
h5_write( file, "Parameters", P);
}
return 0;
}

View File

@ -1,7 +0,0 @@
A
[[1.3,0]
[0,-8.2]]
B[3,-8,0]
C[3,-8,0]
VC[3,-8,0]
C[6,-8,0]

View File

@ -2,13 +2,15 @@
#include <iostream>
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
using namespace triqs::utility;
using namespace triqs::params;
int main() {
parameters P;
P.add_field("a", 1, "?")
.add_field("d", 2.0, "")
.add_field("s", "", "");
P["a"] = long(1);
P["d"] = 2.7;
P["s"] = std::string("-14.3");

View File

@ -5,18 +5,36 @@ FOREACH(CPP ${ALLSOURCES})
ENDFOREACH(CPP ${ALLSOURCES})
get_property(ALLSOURCES GLOBAL PROPERTY TRIQS_LIB_CPP_SOURCES_LIST)
## The library also contains all the converters python <-> C++
## automatically generated for all wrapped modules.
## The lists are defined in subdirectory, in each module
## NB : pytriqs subdir is and must be called BEFORE triqs, or these lists are empty
get_property(all_py_converters_sources GLOBAL PROPERTY TRIQS_PY_CONVERTERS_CPP_LIST)
get_property(all_py_converters_targets GLOBAL PROPERTY TRIQS_PY_CONVERTERS_TARGETS)
# All files are generated, cmake should not worry not to see them at configuration time
foreach(CPP ${all_py_converters_sources})
set_source_files_properties(${CPP} PROPERTIES GENERATED TRUE)
endforeach()
# compile every subdirectory
add_all_subdirectories_with_cmakelist()
# The lib will be build from the sources
# The lib will be build from the sources and the converters generated sources
IF(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
SET( LINK_RT "")
else()
SET( LINK_RT "-lrt")
endif()
add_library(triqs ${ALLSOURCES})
add_library(triqs ${ALLSOURCES} ${all_py_converters_sources})
target_link_libraries (triqs ${LINK_RT} ${TRIQS_LINK_LIBS} )
# The TRIQS library depends on the generation of the .cpp wrapper and converters files
# which must be produced first.
foreach(T ${all_py_converters_targets})
add_dependencies(triqs ${T})
endforeach()
# Install library
install(TARGETS triqs DESTINATION lib)

View File

@ -0,0 +1,83 @@
#include "./_field.hpp"
#include <boost/lexical_cast.hpp>
namespace triqs {
namespace params {
std::map<std::type_index, std::string> _field::type_names;
std::string _field::type_name(std::type_index i) {
try {
return type_names.at(i);
}
catch (...) {
return i.name();
}
}
//-----------------------------------------------------------------------
void h5_write(h5::group g, std::string const &name, _field const &obj) {
obj.p->h5_write_(g, name);
};
//-----------------------------------------------------------------------
void h5_read(h5::group g, std::string const &name, _field &obj) {
obj.p->h5_read_(g, name);
obj.modified = true;
};
template <typename T> T lex_cast_from_string(_field const &obj) {
std::string s = extract<std::string>(obj);
try {
return boost::lexical_cast<T>(s);
}
catch (boost::bad_lexical_cast &) {
TRIQS_RUNTIME_ERROR << " extraction : can not read the string " << s << " into a " << typeid(T).name();
}
}
//-----------------------------------------------------
template <> // specialize for double since we can make int -> double conversion
double extract(_field const &obj) {
if (obj.has_type<double>()) return *static_cast<const double *>(obj.get());
if (obj.has_type<std::string>()) {
return lex_cast_from_string<double>(obj);
}
#define TRANSFORM_TYPE(T) \
if (obj.has_type<T>()) return extract<T>(obj)
TRANSFORM_TYPE(int);
// TRANSFORM_TYPE(unsigned int);
TRANSFORM_TYPE(long);
// TRANSFORM_TYPE(unsigned long);
TRANSFORM_TYPE(short);
// TRANSFORM_TYPE(unsigned short);
TRANSFORM_TYPE(long long);
// TRANSFORM_TYPE(unsigned long long);
// TRANSFORM_TYPE(float);
#undef TRANSFORM_TYPE
TRIQS_RUNTIME_ERROR << "extraction of " << obj.name() << " impossible : type mismatch. Got " << obj.type_name()
<< ", while I am supposed to extract a double";
}
//-----------------------------------------------------
template <> // specialize for double since we can make int -> double conversion
long extract(_field const &obj) {
if (obj.has_type<long>()) return *static_cast<const long *>(obj.get());
if (obj.has_type<std::string>()) {
return lex_cast_from_string<long>(obj);
}
TRIQS_RUNTIME_ERROR << "extraction of " << obj.name() << " impossible : type mismatch. Got " << obj.type_name()
<< ", while I am supposed to extract a double";
}
// --------------- _field cast op implementation ---------------------------------------
#define CAST_OPERATOR(r, data, T) \
_field::operator T() const { return extract<T>(*this); }
BOOST_PP_SEQ_FOR_EACH(CAST_OPERATOR, nil, TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
#undef CAST_OPERATOR
}
}

232
triqs/parameters/_field.hpp Normal file
View File

@ -0,0 +1,232 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2014 by H. Hafermann, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#pragma once
#include <triqs/utility/first_include.hpp>
#include <string>
#include <complex>
#include <memory>
#include <map>
#include <typeindex>
#include <boost/preprocessor/seq/for_each.hpp>
//#include <triqs/utility/serialization.hpp>
#include <triqs/arrays.hpp>
#include <triqs/python_tools/wrapper_tools.hpp>
namespace triqs {
namespace params {
using triqs::get_triqs_hdf5_data_scheme;
template <typename T> std::ostream &operator<<(std::ostream &out, std::vector<T> const &v) {
out << "[";
if (v.size() > 3)
out << v[0] << ", ..., " << v[v.size()-1];
else {
int c = 0;
for (auto const &x : v) out << (c++ ? ", " : "") << x;
}
return out << "]";
}
// All the predefined cast of _field
#define TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST \
(int)(long)(long long)(unsigned int)(unsigned long)(unsigned long long)(double)(bool)(std::string)
// a trait to compute the type actually stored in the opaque object.
// T except for integers, which are all stored as long
template <typename T, typename Enable = void> struct storage_t_impl {
using type = T;
};
template <typename T> using storage_t = typename storage_t_impl<std::c14::decay_t<T>>::type;
template <typename T> struct storage_t_impl<T, std::c14::enable_if_t<std::is_integral<T>::value>> {
using type = long;
};
// differentiate value and view ?
template <typename A> struct storage_t_impl<A, std::c14::enable_if_t<arrays::is_amv_value_or_view_class<A>::value>> {
using type = arrays::array<typename A::value_type, A::rank>;
};
template<> struct storage_t_impl<const char *> {using type = std::string;};
template<> struct storage_t_impl<char *> {using type = std::string;};
// --------------- the field object ---------------------------------------
class _field {
friend class parameters;
struct _data {
virtual const void *get() const = 0;
virtual _data *clone() const = 0;
virtual void h5_write_(h5::group, std::string const &) const = 0;
virtual void h5_read_(h5::group, std::string const &) = 0;
//virtual std::string serialize() const = 0;
//virtual void deserialize(std::string const &) = 0;
virtual std::ostream &print(std::ostream &out) const = 0;
virtual bool from_python_convertible(PyObject *) const = 0;
virtual void set_from_python(PyObject *) = 0;
virtual PyObject *to_python() const = 0;
};
template <typename T> struct _data_impl : _data {
T x;
_data_impl(T obj) : x(std::move(obj)) {}
_data_impl(_data_impl &&c) = default;
_data_impl(_data_impl const &) = default;
virtual const void *get() const override { return &x; }
virtual _data *clone() const override { return new _data_impl(*this); }
virtual void h5_write_(h5::group f, std::string const &name) const override { h5_write(f, name, x); }
virtual void h5_read_(h5::group f, std::string const &name) override { h5_read(f, name, x); }
/*
virtual std::string serialize() const override { return triqs::serialize(x); }
virtual void deserialize(std::string const &s) override {
x = triqs::deserialize<T>(s);
};
*/
virtual std::ostream &print(std::ostream &out) const override { return out << x; }
virtual bool from_python_convertible(PyObject *ob) const override {
return py_tools::py_converter<T>::is_convertible(ob, true);
}
virtual void set_from_python(PyObject *ob) override { x = py_tools::py_converter<T>::py2c(ob); }
virtual PyObject *to_python() const override { return py_tools::py_converter<T>::c2py(x); }
};
std::type_index index;
std::unique_ptr<_data> p; //invariant : is never null
static std::map<std::type_index, std::string> type_names;
std::string name_; // for_error_messages
bool modified = false;
// only parameters will construct _field
template <typename T>
_field(T obj, std::string n, bool modification_required)
: index(typeid(storage_t<T>)), p(new _data_impl<storage_t<T>>{std::move(obj)}), name_(n), modified(!modification_required) {
type_names.insert({index, get_triqs_hdf5_data_scheme(storage_t<T>{})});
}
public:
//_field() : index(typeid(void)) {} // BREAKS invariant : only used for BOOST serialization...
_field(_field &&c) = default;
_field(_field const &x) : index(x.index), p(x.p ? x.p->clone() : nullptr), name_(x.name_), modified(x.modified) {} // regular type
_field &operator=(_field &&c) = default;
_field &operator=(_field const &x) { return operator=(_field(x)); }
template <typename RHS> _field &operator=(RHS rhs) { // pass by value (sink)
modified = true;
using S_t = storage_t<RHS>;
if (index != typeid(S_t)) {
TRIQS_RUNTIME_ERROR << "Field "<< name_<<" is of type "<< type_name(index)<<". I can not put a " << type_name(typeid(S_t)) << " into it.";
}
p.reset(new _data_impl<S_t>{std::move(rhs)});
return *this;
}
// rewrite a few cases for convenience ...
_field &operator=(int rhs) { // a special case where we can correct : int -> double
if (index == typeid(double)) return operator=(double(rhs));
return operator=(long(rhs));// beware infinite loop!
}
// special treatment for const char *: fall back to string
_field &operator=(const char *rhs) { return operator=(std::string(rhs)); }
// for subgroups only : implemented after parameters. Check type at runtime
template <typename... T> _field &add_field(T &&... x);
_field &operator[](const char * key);
_field const &operator[](const char * key) const;
friend bool is_parameter(_field const & f);
_field& add_group(std::string const& key, std::string const& doc);
std::string type_name() const { return type_name(index); }
std::string const &name() const { return name_; }
bool is_modified() const { return modified; }
const void *get() const { return (p ? p->get() : nullptr); }
template <typename T> bool has_type() const { return index == typeid(T); }
static std::string type_name(std::type_index i);
bool from_python_convertible(PyObject *ob) const { return p->from_python_convertible(ob); }
void set_from_python(PyObject *ob) { p->set_from_python(ob); }
PyObject *to_python() const { return p->to_python(); }
// implemented later, since it needs the extract function ...
#define CAST_OPERATOR(r, data, T) operator T() const;
BOOST_PP_SEQ_FOR_EACH(CAST_OPERATOR, nil, TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
#undef CAST_OPERATOR
// ----- Boost serialisation
/*
template<class Archive>
void save(Archive & ar, const unsigned int version) const {
std::string s = p->serialize();
ar << TRIQS_MAKE_NVP("seria_str", s);
}
template<class Archive>
void load(Archive & ar, const unsigned int version) {
std::string s;
ar >> TRIQS_MAKE_NVP("seria_str", s);
p->deserialize(s);
}
BOOST_SERIALIZATION_SPLIT_MEMBER();
*/
friend std::ostream &operator<<(std::ostream &out, _field const &ob) { return ob.p->print(out); }
// --------------------- hdf5 ---------------------------------
friend std::string get_triqs_hdf5_data_scheme(_field const &) { return ""; }
friend void h5_write(h5::group F, std::string const &Name, _field const &);
friend void h5_read(h5::group F, std::string const &Name, _field &);
}; // object class
// --------------------- arithmetic operations are deleted for _field ---------------------------------
#define DELETE_OP(op) \
template <typename LHS, typename RHS> \
std::c14::enable_if_t<std::is_same<LHS, _field>::value || std::is_same<RHS, _field>::value> operator op(LHS const &, \
RHS const &) = delete;
DELETE_OP(+);
DELETE_OP(-);
DELETE_OP(*);
DELETE_OP(/ );
#undef DELETE_OP
// --------------------- extraction with type checking for C++ ---------------------------------
template <typename T> T extract(_field const &ob) {
if (!ob.has_type<storage_t<T>>())
TRIQS_RUNTIME_ERROR << "extraction of " << ob.name() << " impossible : type mismatch. I have received a " << ob.type_name()
<< ", while I am supposed to extract a " << _field::type_name(typeid(T));
return *static_cast<const storage_t<T> *>(ob.get());
}
template <> double extract(_field const &obj); // special treatment for basic types
template <> long extract(_field const &obj);
}
}

View File

@ -1,41 +0,0 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2013 by H. Hafermann, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "./defaults.hpp"
#include <triqs/utility/formatted_output.hpp>
namespace triqs { namespace utility {
std::vector<std::vector<std::string>> parameter_defaults:: generate_help() const{
std::vector<std::vector<std::string>> str;
str.push_back({"parameter:", "status:", "type", "default value:", "description:"});
for (auto const &s : object_map){
std::string key=s.first; std::ostringstream val; val << s.second;
if(is_required(key)) str.push_back({key, "required", s.second.type_name(), "-", doc(key)});
else str.push_back({key, "optional", s.second.type_name(), val.str(), doc(key)});
}
return str;
}
std::ostream & operator << (std::ostream & out, parameter_defaults const & p) {
out<< print_formatted(p.generate_help());
return out;
}
}}

View File

@ -1,106 +0,0 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2013 by H. Hafermann, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_UTILITY_PARAMS_DEFAULT_H
#define TRIQS_UTILITY_PARAMS_DEFAULT_H
#include "./opaque_object_h5.hpp"
namespace triqs { namespace utility {
/**
* Class to handle required and optional program parameters and default values for optional parameters.
* Required parameters need to be provided by the user. Parameters that are optional need not be provided
* by the user because sensible default values can be given. The former are inserted through the required
* method, the latter by the optional method. An object of type parameters can be updated from an object
* of type parameter_defaults (see parameters.hpp).
*/
class parameter_defaults {
public :
parameter_defaults() {};
parameter_defaults (parameter_defaults const & other) = default;
parameter_defaults (parameter_defaults && other) { swap(*this,other);}
parameter_defaults & operator = (parameter_defaults const & other) = default;
parameter_defaults & operator = (parameter_defaults && other) noexcept { swap(*this,other); return *this;}
friend void swap(parameter_defaults & a, parameter_defaults &b)
{ swap(a.object_map,b.object_map); swap(a.documentation, b.documentation);swap(a.is_optional, b.is_optional); }
private:
typedef std::map<std::string, _object> map_t;
map_t object_map;
std::map<std::string, std::string> documentation;
std::map<std::string, bool > is_optional;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) { ar & TRIQS_MAKE_NVP("object_map",object_map); }
template<typename T> parameter_defaults & insert(std::string const & key, T && def_val, std::string const & doc, bool opt) {
object_map[key] = std::forward<T>(def_val);
documentation[key] = doc;
is_optional[key] = opt;
return *this;
}
template<typename T> const T getter(std::map<std::string,T> const & m, std::string const & key) const {
auto it = m.find(key); assert(it !=m.end()); return it->second;
}
public:
typedef map_t::const_iterator const_iterator;
typedef map_t::iterator iterator;
const_iterator begin() const { return object_map.begin();}
const_iterator end() const { return object_map.end();}
iterator begin() { return object_map.begin();}
iterator end() { return object_map.end();}
bool has_key(std::string const & key) const { return object_map.find(key) != object_map.end();}
bool is_required(std::string const & key) const { return (has_key(key) && (! getter(this->is_optional,key)));}
std::string doc(std::string const & key) const { return (has_key(key) ? getter(this->documentation,key) : "");}
/// inserter for optional parameters;
/// calls can be chained for multiple parameters
template <typename T> parameter_defaults &optional(std::string const &key, T &&def_val, std::string const &doc) {
insert(key, std::forward<T>(def_val), doc, true);
return *this;
}
/// inserter for required parameters;
/// calls can be chained for multiple parameters
template <typename T> parameter_defaults &required(std::string const &key, T &&def_val, std::string const &doc) {
insert(key, std::forward<T>(def_val), doc, false);
return *this;
}
///parameters class-like element access
_object const & operator[](std::string const & key) const {
auto it = object_map.find(key);
if ( it== object_map.end()) TRIQS_RUNTIME_ERROR<<"Key : "<< key<< " not found";
return it->second;
}
///generate help in form of a table of strings containing a list of required and optional parameters
std::vector<std::vector<std::string>> generate_help() const;
///print a formatted table of required and optional parameters
friend std::ostream & operator << (std::ostream & out, parameter_defaults const & p);
};
}}
#endif

View File

@ -1,65 +0,0 @@
#include "./opaque_object_h5.hpp"
namespace triqs { namespace utility {
std::map<size_t, std::function<_object(std::string const &)>> _object::code_to_deserialization_fnts;
std::map<size_t, std::function<_object(h5::group const &, std::string const &)>> _object::code_to_h5_read_fnts;
std::map<hid_t, size_t > _object::h5_type_to_c_equivalence;
std::map<std::pair<size_t,int>, size_t > _object::code_element_rank_to_code_array;
std::map<std::string, size_t > _object::h5_scheme_to_code;
std::map<size_t, std::string > _object::type_code_to_type_name;
std::map<std::string, size_t > _object::type_name_to_type_code;
bool _object::initialized = false;
//-----------------------------------------------------------------------
void _object::_init() {
if (initialized) return;
#define REGISTER_UNSERIALIZE_FUN(r, data, T) _object::register_native_type<T>();
BOOST_PP_SEQ_FOR_EACH(REGISTER_UNSERIALIZE_FUN, nil , TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
#undef REGISTER_UNSERIALIZE_FUN
initialized = true;
}
//-----------------------------------------------------------------------
void h5_read ( h5::group g, std::string const & name, _object & obj){
//std::cerr << " read object "<< name << std::endl ;
using namespace H5;
if (!g.has_key(name)) TRIQS_RUNTIME_ERROR << "no such "<<name <<" in file ";
size_t type_hash;
// First if it is not a subgroup, it is a scalar or a an array
// TO BE CHECKED
try {
H5::DataSet ds = g.open_dataset( name.c_str() );
hid_t dtype = H5Dget_type(ds.getId());
hid_t native_type=H5Tget_native_type(dtype, H5T_DIR_DEFAULT);
if (H5Tget_class(dtype) == H5T_STRING ) { // it is a string
auto triqs_data_scheme = h5::read_string_attribute(&ds,"TRIQS_HDF5_data_scheme");
type_hash = (triqs_data_scheme == "") ? _object::type_code<std::string>() : _object::h5_scheme_to_code[triqs_data_scheme];
}
else if ((H5Tget_class(dtype) == H5T_INTEGER ) || ((H5Tget_class(dtype) == H5T_FLOAT ) )) {
int rank = ds.getSpace().getSimpleExtentNdims();
auto it = _object::h5_type_to_c_equivalence.begin();
for (;it != _object::h5_type_to_c_equivalence.end();++it) { if (H5Tequal(native_type, it->first)) break;}
if (it == _object::h5_type_to_c_equivalence.end()) TRIQS_RUNTIME_ERROR << " h5_type_to_c_equivalence : type not found";
type_hash = it->second;
if (rank>0) {
size_t type_hash_element = type_hash;
auto it2= _object::code_element_rank_to_code_array.find(std::make_pair(type_hash_element,rank));
if (it2 == _object::code_element_rank_to_code_array.end())
TRIQS_RUNTIME_ERROR << " code_element_rank_to_code_array : type not found : " << name << " " << type_hash_element << " "
<< rank;
type_hash = it2->second;
}
}
//else if (H5Tget_class(dtype)==H5T_ARRAY)
herr_t status = H5Tclose (native_type);
status = H5Tclose (dtype);
}
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
obj = _object::code_to_h5_read_fnts[type_hash](g,name);
}
}}

View File

@ -1,332 +0,0 @@
/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2013 by H. Hafermann, O. Parcollet
*
* TRIQS is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_UTILITY_OPAQUE_OBJECT_H5_H
#define TRIQS_UTILITY_OPAQUE_OBJECT_H5_H
#include <triqs/utility/first_include.hpp>
#include <string>
#include <complex>
#include <memory>
#include <map>
#include <boost/lexical_cast.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/serialization/map.hpp>
#include <triqs/utility/exceptions.hpp>
#include <triqs/utility/serialization.hpp>
#include <triqs/arrays.hpp>
#include <triqs/python_tools/array_interface.hpp>
#include <triqs/h5/make_h5_read_write.hpp>
namespace triqs { namespace utility {
template<typename T>
std::ostream & operator<<(std::ostream & out, std::vector<T> const & v) {
out << "["; int c = 0; for (auto const & x : v) out << ( c++==0 ? ", " :" ") << x;
return out << "]";
}
// All the predefined cast of _object
#define TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST (int)(long)(long long)(unsigned int)(unsigned long)(unsigned long long)(double)(bool)(std::string)
// a trait to compute the type actually stored in the opaque object.
// T except for integers, which are all stored as long
template<typename T> struct _object_collapse_type_impl : std::conditional<std::is_integral<T>::value, long, T > {};
// We store the array/matrix/vector as array_c (a view repackaged as a value) since :
// in python : it allows to extract a view
// in C++ : it allows to extract a value (array) with a copy, or a view (array_view) without a copy
template<class T, int R, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::array<T,R,Opt,To>> { typedef arrays::array_c<T,R,Opt,To> type;};
template<class T, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::matrix<T,Opt,To>> { typedef arrays::array_c<T,2,Opt,To> type;};
template<class T, ull_t Opt> struct _object_collapse_type_impl< arrays::vector<T,Opt>> { typedef arrays::array_c<T,1,Opt> type;};
//same thing for the view
template<class T, int R, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::array_view<T,R,Opt,To>> { typedef arrays::array_c<T,R,Opt,To> type;};
template<class T, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::matrix_view<T,Opt,To>> { typedef arrays::array_c<T,2,Opt,To> type;};
template<class T, ull_t Opt> struct _object_collapse_type_impl< arrays::vector_view<T,Opt>> { typedef arrays::array_c<T,1,Opt> type;};
// uncomment after merge qview branch
//template<class T, int R, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::array_qview<T,R,Opt,To>> { typedef arrays::array_c<T,R,Opt,To> type;};
//template<class T, ull_t Opt, ull_t To> struct _object_collapse_type_impl< arrays::matrix_qview<T,Opt,To>> { typedef arrays::array_c<T,2,Opt,To> type;};
//template<class T, ull_t Opt> struct _object_collapse_type_impl< arrays::vector_qview<T,Opt>> { typedef arrays::array_c<T,1,Opt> type;};
template<typename T> struct _object_collapse_type: _object_collapse_type_impl <typename std::decay<T>::type> {};
// Since I used array_c to store in the dict, I need to make it h5 read/writable.
// write is ok, because it is a view. Read : we can not use the view (no resize)
// so I first build the value (an array) and rebind the array_c to it.
template<class T, int R, ull_t Opt, ull_t To>
void h5_read(h5::group const &gr, std::string const &Name, arrays::array_c<T,R,Opt,To> & a) {
arrays::array<T,R,Opt,To> v; h5_read(gr,Name,v); a=v();// rebinds !
}
// --------------- the opaque object ---------------------------------------
// _object is a value : it makes deep copies in particular ...
class _object {
std::shared_ptr<void> p; // the object handled by the class
size_t type_code_; // id of the type, implementation dependent...
std::function<_object()> clone_; // clones the object : will be used to make copy of parameters
std::function<void(h5::group const &, std::string const &)> h5_w; // the function to write in h5
std::function<std::string()> serialize_; // for boost serialization ...
std::function<void(std::ostream&)> print_;
std::string name_;
public :
template<typename T> static constexpr size_t type_code () { return typeid(T).hash_code();}
template<typename T> static std::string make_type_name () { return get_triqs_hdf5_data_scheme(typename _object_collapse_type<T>::type());}
//template<typename T> static std::string make_type_name () { return demangle(typeid(T).name());}
_object() {_init(); };
// pass a const & or a && (in which case a move will be used, provided that T has a move constructor)
template<typename T>
_object ( T && obj, std::string const & name){ delegate_constructor( new typename std::remove_cv<typename std::remove_reference<T>::type>::type(std::forward<T>(obj)), name); }
private:
template<typename T> void delegate_constructor( T * obj, std::string const & name) {
p = std::shared_ptr<T> (obj);
type_code_ = type_code<T>();
name_ = name;
clone_ = [obj,name]() { return _object( *obj, name);} ;
//clone_ = [this,obj]() { return _object::factory( *obj);} ; //clone_ = [obj]() { return _object( *obj, "");} ;
//h5_w = [obj](h5::group const &F, std::string const &Name)->void { h5_write(F,Name, *obj);};
h5_w = h5::make_h5_write(obj);// either call h5_write or synthetize one into a string using boost serialization
//static_assert(h5::has_h5_write<T>::value, "oops");
serialize_ = [obj](){ return triqs::serialize(*obj);};
print_ = [obj](std::ostream & out ){out << *obj;};
// CHECK if std::bind would lead to less code bloat ??
_init();
}
public:
_object(_object const & x ) { *this = x; _init(); }
_object(_object && c) { *this= std::move(c); _init();}
friend void swap (_object & a, _object & b) {
#define SWAP(A) swap(a.A,b.A)
SWAP(p); std::SWAP(type_code_); SWAP(clone_); SWAP(h5_w); SWAP(serialize_); SWAP(print_); SWAP(name_);
#undef SWAP
}
_object & operator = (_object && c) { swap(*this, c); return *this; }
_object & operator = (_object const & x ) { if (x.p) *this = x.clone_(); else *this = _object(); return *this; }
_object & operator = (_object & x ) { if (x.p) *this = x.clone_(); else *this = _object(); return *this; }
// the last one is needed since otherwise the template for _object & is taken !
// alternatively disable the template for object ...
template <typename RHS> _object & operator=(RHS && rhs) {
typedef typename _object_collapse_type<RHS>::type storage_t;
*this = _object (storage_t(std::forward<RHS>(rhs)),this->name());
register_type<storage_t>::invoke();
//register_type<typename std::remove_reference<RHS>::type>::invoke();
return *this;
}
// special treatment for const char *: fall back to string
_object & operator=(const char * rhs) { *this = std::string(rhs); return *this;}
bool is_empty() const { return bool(p);}
std::string const & name() const { return name_;}
void set_name(std::string const & n) { name_ = n;}
friend bool have_same_type( _object const & a, _object const & b) { return a.type_code_ == b.type_code_;}
template<typename T> bool has_type() const { return type_code_ == type_code<T>();}
const void * get_void_ptr() const { return p.get();}
void * get_void_ptr() { return p.get();}
// implemented later, since it needs the extract function ...
#define CAST_OPERATOR(r, data, T) operator T () const;
BOOST_PP_SEQ_FOR_EACH(CAST_OPERATOR, nil , TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
#undef CAST_OPERATOR
friend std::ostream & operator << (std::ostream & out, _object const & p) { if (p.is_empty()) p.print_(out); else out<< "empty"; return out;}
friend void h5_write ( h5::group F, std::string const & Name, _object const & obj){ obj.h5_w(F,Name); };
friend void h5_read ( h5::group F, std::string const & Name, _object & obj);
friend std::string get_triqs_hdf5_data_scheme(_object const&) { return "";}
std::string type_name() const { return type_code_to_type_name[type_code_];}
// ----- Boost serialisation
template<class Archive>
void save(Archive & ar, const unsigned int version) const {
std::string s = serialize_();
ar << TRIQS_MAKE_NVP("type_name", type_code_to_type_name[type_code_]);
ar << TRIQS_MAKE_NVP("seria_str", s);
}
template<class Archive>
void load(Archive & ar, const unsigned int version) {
std::string s, tnn;
ar >> TRIQS_MAKE_NVP("type_name", tnn);
ar >> TRIQS_MAKE_NVP("seria_str", s);
auto it = type_name_to_type_code.find(tnn);
if (it== type_name_to_type_code.end())
TRIQS_RUNTIME_ERROR << " Can not deserialize the type "<< tnn<< "\n Did you forget to register it ?";
*this = code_to_deserialization_fnts[it->second](s);
}
BOOST_SERIALIZATION_SPLIT_MEMBER();
// ----- Deserialization (boost, h5) table : type_code -> deserialization function
// init will register the most common types.
static std::map<size_t, std::function<_object(std::string const &)>> code_to_deserialization_fnts;
static std::map<size_t, std::function<_object(h5::group const &, std::string const &)>> code_to_h5_read_fnts;
static std::map<hid_t, size_t > h5_type_to_c_equivalence;
static std::map<std::pair<size_t,int>, size_t > code_element_rank_to_code_array;
static std::map<std::string, size_t > h5_scheme_to_code;
static std::map<size_t, std::string > type_code_to_type_name;
static std::map<std::string, size_t > type_name_to_type_code;
static bool initialized;
static void _init();
static bool is_initialised(size_t code) { return type_code_to_type_name.find(code) != type_code_to_type_name.end();}
template <typename T> struct register_type;
private: // native type
template <typename T>
static void register_native_type() {
if (register_type<T>::invoke()) return;
h5_type_to_c_equivalence[h5::h5_type_from_C(T()).getId()] = type_code<T>();
}
};// object class
// --------------------- type registering ---------------------------------
template <typename T> struct _object::register_type<const T> : _object::register_type<T>{};
template <typename T> struct _object::register_type {
static bool invoke() { // returns true if already registered
size_t code = type_code<T>();
if (is_initialised(code)) return true;
type_code_to_type_name[code] = make_type_name<T>();
type_name_to_type_code[make_type_name<T>()]= code;
code_to_deserialization_fnts[code] = [](std::string const &s) { return _object( triqs::deserialize<T>(s),"");};
code_to_h5_read_fnts[code] = [](h5::group const &f,std::string const &s) ->_object { T n; h5::make_h5_read(&n)(f,s); return _object(std::move(n),"");};
//code_to_h5_read_fnts[code] = [](h5::group const &f,std::string const &s) ->_object { T n; h5_read(f,s,n); return _object(std::move(n),true);};
auto h5_scheme = get_triqs_hdf5_data_scheme(T());
if (h5_scheme != "") h5_scheme_to_code[h5_scheme] = code;
//std::cerr << " registering " << type_code_to_type_name[code] << "h5 scheme "<< h5_scheme<< std::endl ;
return false;
}
};
// special case for array, we need to fill one more table
template<typename T, int R> struct _object::register_type<arrays::array_c<T,R>>{
static bool invoke() {
typedef arrays::array_c<T,R> A;
typedef arrays::array<T,R> Aa;
if (is_initialised(type_code<A>())) return true;
type_code_to_type_name[type_code<A>()] = make_type_name<A>();
type_name_to_type_code[make_type_name<A>()]= type_code<A>();
code_to_deserialization_fnts[type_code<A>()] = [](std::string const &s) { return _object( triqs::deserialize<A>(s),"");};
//code_to_h5_read_fnts[type_code<A>()] = [](h5::group const &f,std::string const &s) ->_object { A n; h5_read(f,s,n); return _object(std::move(n),true);};
code_to_h5_read_fnts[type_code<A>()] = [](h5::group const &f,std::string const &s) ->_object { Aa a; h5::make_h5_read(&a)(f,s); return _object(A(a),"");};
code_element_rank_to_code_array[std::make_pair(type_code<T>(), R)] = type_code<A>();
auto h5_scheme = get_triqs_hdf5_data_scheme(Aa());
if (h5_scheme != "") h5_scheme_to_code[h5_scheme] = type_code<A>();
return false;
}
};
// --------------------- arithmetic operations are deleted for _object ---------------------------------
#define DELETE_OP(op)\
template <typename LHS, typename RHS> \
typename std::enable_if< std::is_same<LHS,_object>::value || std::is_same<RHS,_object>::value>::type\
operator op( LHS const &, RHS const &) = delete;
DELETE_OP(+); DELETE_OP(-); DELETE_OP(*); DELETE_OP(/);
#undef DELETE_OP
// --------------------- extraction with strict type checking for python ---------------------------------
template<typename T> struct extract_strict {
typedef typename _object_collapse_type<T>::type T_stored;
static bool is_possible (_object const &obj) { return obj.has_type<T_stored>(); }
static T invoke(_object const &obj) {
if (! is_possible(obj))
TRIQS_RUNTIME_ERROR<<"extraction of "<< obj.name() << "impossible : type mismatch. Got a "<<obj.type_name()<< " while I am supposed to extract a "<<_object::make_type_name<T>();
return T(* static_cast<const T_stored*>(obj.get_void_ptr()));
}
};
// --------------------- extraction with more relaxed type checking for C++ ---------------------------------
template<typename T> T extract(_object const &obj);
template<typename T> T lex_cast_from_string(_object const &obj) {
std::string s = extract<std::string>(obj);
try { return boost::lexical_cast<T>(s); }
catch(boost::bad_lexical_cast &) { TRIQS_RUNTIME_ERROR << " extraction : can not read the string "<<s <<" into a "<< _object::make_type_name<T>(); }
}
template<typename T> struct lexical_cast_make_sense : std::is_arithmetic<T>{};
//template<typename T> constexpr bool lexical_cast_make_sense() { return std::is_arithmetic<T>::value; }
template<typename T> T extract1(_object const &obj, std::false_type) {
typedef typename _object_collapse_type<T>::type coll_t;
if (! obj.has_type<coll_t>())
TRIQS_RUNTIME_ERROR<<"extraction of "<< obj.name() << " impossible : type mismatch. Got "<<obj.type_name()<< ", while I am supposed to extract a "<<_object::make_type_name<T>();
return * static_cast<const coll_t*>(obj.get_void_ptr());
}
template<typename T> T extract1(_object const &obj, std::true_type) {
// if T is not a string, and object contains a string, attempt lexical_cast
if ((!std::is_same<T,std::string>::value) && (obj.has_type<std::string>())) { return lex_cast_from_string<T>(obj); }
return extract1<T>(obj, std::false_type());
}
template<typename T> T extract(_object const &obj) {
return extract1<T>(obj, std::integral_constant<bool,lexical_cast_make_sense<T>::value>());
}
template<> // specialize for double since we can make int -> double conversion
inline double extract(_object const & obj) {
if (obj.has_type<double>()) return * static_cast<const double*>(obj.get_void_ptr());
if (obj.has_type<std::string>()) {return lex_cast_from_string<double>(obj); }
#define TRANSFORM_TYPE(T) if (obj.has_type<T>()) return extract<T>(obj)
TRANSFORM_TYPE(int);
//TRANSFORM_TYPE(unsigned int);
TRANSFORM_TYPE(long);
//TRANSFORM_TYPE(unsigned long);
TRANSFORM_TYPE(short);
//TRANSFORM_TYPE(unsigned short);
TRANSFORM_TYPE(long long);
//TRANSFORM_TYPE(unsigned long long);
//TRANSFORM_TYPE(float);
#undef TRANSFORM_TYPE
TRIQS_RUNTIME_ERROR<<"extraction of "<< obj.name() << " impossible : type mismatch. Got "<<obj.type_name()<< ", while I am supposed to extract a double";
}
// template<> // special case to size_t
// inline size_t extract(_object const & obj) { return extract<long>(obj);}
// --------------- _object cast op implementation ---------------------------------------
#define CAST_OPERATOR(r, data, T) inline _object::operator T () const{ return extract<T>(*this);}
BOOST_PP_SEQ_FOR_EACH(CAST_OPERATOR, nil , TRIQS_UTIL_OPAQUE_OBJECT_PREDEFINED_CAST);
#undef CAST_OPERATOR
}}
#endif

View File

@ -1,87 +1,154 @@
#include "./parameters.hpp"
#include <triqs/utility/first_include.hpp>
#include <triqs/utility/formatted_output.hpp>
#include <boost/serialization/string.hpp>
#include "./parameters.hpp"
#include <triqs/utility/serialization.hpp>
#include <algorithm>
#include <boost/algorithm/string.hpp>
namespace triqs { namespace utility {
namespace triqs {
namespace params {
void h5_read ( h5::group F, std::string const & subgroup_name, parameters & p){
parameters::parameters() {
using triqs::arrays::array;
using dcomplex = std::complex<double>;
if (_field::type_names.size() == 0) {
#define R(...) _field::type_names.insert({typeid(__VA_ARGS__), get_triqs_hdf5_data_scheme(storage_t<__VA_ARGS__>{})});
#define A(N) \
R(array<int, N>); \
R(array<long, N>); \
R(array<double, N>); \
R(array<dcomplex, N>);
R(long);
R(double);
R(int);
R(dcomplex);
A(1);
A(2);
A(3);
A(4);
}
}
parameters::_data_t::iterator parameters::find(std::string const& key) {
return std::find_if(_data.begin(), _data.end(), [&key](_data_elem const& x) { return x.key == key; });
}
parameters::_data_t::const_iterator parameters::find(std::string const& key) const {
return std::find_if(_data.begin(), _data.end(), [&key](_data_elem const& x) { return x.key == key; });
}
bool parameters::has_key(std::string const& k) const { return find(k) != _data.end();}
void parameters::sort_by_key() {
std::sort(_data.begin(), _data.end(), [](_data_elem const& x, _data_elem const& y) { return x.key < y.key; });
}
void parameters::insert(std::string const& key, _field&& f, std::string const& doc) {
if (has_key(key)) TRIQS_RUNTIME_ERROR << "Field " << key << " already defined";
_data.push_back({key, std::move(f),doc});
}
_field& parameters::operator[](const char * key) {
auto it = find(key);
if (it == _data.end()) TRIQS_RUNTIME_ERROR << "Parameters : the key : " << key << " does not exists";
return it->f;
}
_field const& parameters::operator[](const char * key) const {
auto it = find(key);
if (it == _data.end()) TRIQS_RUNTIME_ERROR << "Parameters : the key : " << key << " does not exists";
return it->f;
}
void h5_write(h5::group F, std::string const& subgroup_name, parameters const& p) {
auto gr = F.create_group(subgroup_name);
for (auto& pvp : p._data) h5_write(gr, pvp.key, pvp.f);
}
void h5_read(h5::group F, std::string const& subgroup_name, parameters& p) {
auto gr = F.open_group(subgroup_name);
std::vector<std::string> ds_name = F.get_all_dataset_names(subgroup_name), grp_name = F.get_all_subgroup_names(subgroup_name);
for (auto & x : grp_name) {
//std::cerr << " loading group : "<< x <<std::endl;
auto x_grp = gr.open_group(x);
auto triqs_data_scheme = x_grp.read_triqs_hdf5_data_scheme();
if (triqs_data_scheme != "") {
auto type_hash = _object::h5_scheme_to_code[triqs_data_scheme];
auto it = _object::code_to_h5_read_fnts.find(type_hash);
if (it == _object::code_to_h5_read_fnts.end()) TRIQS_RUNTIME_ERROR << "TRIQS_HDF5_data_scheme : ["<< triqs_data_scheme << "] is unknown. Did you register your object ?";
p[x] = it->second(gr,x);
}
else {
parameters p2;
h5_read (gr,x,p2);
p[x] = p2;
}
}
for (auto & x : ds_name) {
//std::cerr << " loading : "<< x <<std::endl;
try {
_object obj;
h5_read(gr,x,obj);
p[x] = obj;
}
catch(H5::Exception const & e) { TRIQS_RUNTIME_ERROR<< "Cannot load "<< x<<"\n H5 error is : \n "<< e.getCDetailMsg();}
}
for (auto& pvp : p._data) h5_read(gr, pvp.key, pvp.f);
}
//-----------------------------------------------------------------------
void parameters::update (parameters const & pdef){ for (auto const & pvp : pdef) (*this)[pvp.first] = pvp.second; }
void parameters::update (parameter_defaults const & pdef, ull_t flag ){
std::vector<std::vector<std::string>> missing;
std::vector<std::vector<std::string>> wrong_t;
std::vector<std::vector<std::string>> no_deft;
std::vector<std::string> desc{"key:", "description:"};
std::vector<std::string> tdesc{"key:", "expected type:", "actual type:"};
if ( (flag & reject_key_without_default) ) { // check that no extra parameters are present
for (auto const & pvp : *this) {
auto key = pvp.first;
if (!pdef.has_key(key)){
no_deft.push_back({key});
}
}
void parameters::update(parameters const& other) {
for (auto const& kfd : other._data) {
auto it = find(kfd.key);
if (it !=_data.end()) {
if (it->f.index != kfd.f.index) TRIQS_RUNTIME_ERROR << "Index mismatch in merging parameters";
if (kfd.doc.size()>0) it->doc = kfd.doc;
} else
_data.push_back(kfd);
}
for (auto const & pvp : pdef) {
auto key = pvp.first;
// check whether required parameters are present
if (pdef.is_required(key) && (!this->has_key(key))){
// delay exception until all parameters have been checked
if (!missing.size()) missing.push_back(desc);
missing.push_back({key, pdef.doc(key)});
}
if (this->has_key(key)) { // check whether the type is correct
if (! have_same_type(pvp.second, (*this)[key])){
// delay exception until all parameters have been checked
if (!wrong_t.size()) wrong_t.push_back(tdesc);
wrong_t.push_back({key, pvp.second.type_name(), (*this)[key].type_name()});
}
}
else {
(*this)[key] = pvp.second; // insert the default
}
}
// raise a runtime exception if errors occured
if(missing.size()) TRIQS_RUNTIME_ERROR << "update with defaults : the following parameters are required but absent: \n"<< print_formatted(missing);
if(wrong_t.size()) TRIQS_RUNTIME_ERROR << "update with defaults : the following parameters have incorrect type: \n"<< print_formatted(wrong_t);
if(no_deft.size()) TRIQS_RUNTIME_ERROR << "update with defaults : the following parameters are absent from the defaults and no_parameter_without_default is ON: \n"<< print_formatted(no_deft);
}
}}
//-----------------------------------------------------------------------
std::vector<std::vector<std::string>> parameters::generate_help() const {
std::vector<std::vector<std::string>> str;
str.push_back({"parameter:", "type:", "value:", "description:"});
for (auto const& s : _data)
if (!s.f.is_modified()) str.push_back({s.key, s.f.type_name(), "-", s.doc});
for (auto const& s : _data) {
if (is_parameter(s.f)) continue; // no subgroup
if (s.f.is_modified()) {
std::ostringstream val;
val << s.f;
auto sv = val.str();
boost::algorithm::trim(sv);
int size_max = 30;
if (sv.size()>size_max) {
auto s2 = std::string(size_max+5,'.');
std::copy(sv.begin(), sv.begin()+size_max/2, s2.begin());
std::copy(sv.end()-size_max/2, sv.end(), s2.end()-size_max/2);
sv = s2;
}
std::replace( sv.begin(), sv.end(), '\n', ','); // replace all 'x' to 'y'
str.push_back({s.key, s.f.type_name(), sv, s.doc});
}
}
// all sub groups after
for (auto const& s : _data) {
if (!is_parameter(s.f)) continue;
auto p = dynamic_cast<_field::_data_impl<parameters>*>(s.f.p.get());
auto str2 = p->x.generate_help();
for (auto & x : str2) x[0] = " " + x[0];
str2.insert(str2.begin(), {"Sub-group : ", s.key, " ", ""});
str.insert(str.end(), str2.begin(), str2.end());
}
return str;
}
std::ostream& operator<<(std::ostream& out, parameters const& p) {
out << utility::print_formatted(p.generate_help());
return out;
}
//-----------------------------------------------------------------------
_field& _field::operator[](const char* key) {
auto* pp = dynamic_cast<_data_impl<parameters>*>(p.get());
if (!pp) TRIQS_RUNTIME_ERROR << "Can only use [] on a subgroup, which " << name() << " is not !";
return pp->x.operator[](key);
}
_field const& _field::operator[](const char* key) const {
auto* pp = dynamic_cast<_data_impl<parameters>*>(p.get());
if (!pp) TRIQS_RUNTIME_ERROR << "Can only use [] on a subgroup, which " << name() << " is not !";
return pp->x.operator[](key);
}
bool is_parameter(_field const& f) { return dynamic_cast<_field::_data_impl<parameters>*>(f.p.get()); }
_field& _field::add_group(std::string const& key, std::string const& doc) {
auto* pp = dynamic_cast<_data_impl<parameters>*>(p.get());
if (!pp) TRIQS_RUNTIME_ERROR << "Can only use [] on a subgroup, which " << name() << " is not !";
pp->x.add_group(key, doc);
return *this;
}
}
}

View File

@ -18,15 +18,16 @@
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#ifndef TRIQS_UTILITY_PARAMS_H
#define TRIQS_UTILITY_PARAMS_H
#include "./opaque_object_h5.hpp"
#include "./defaults.hpp"
namespace triqs { namespace utility {
#pragma once
#include "./_field.hpp"
namespace triqs {
namespace params {
template<typename T> struct no_default {};
/**
* Class for storing program parameters.
* Parameters can be added to and extracted from the parameter object using the element access operator [].
* Each element is stored by means of an object of type _object, which also stores the original type (all
* Each element is stored by means of an object of type _field, which also stores the original type (all
* integral types are collapsed to long and char* is collapsed to std::string).
* When accessing elements, a typecheck is performed. Typecasts are allowed and are similar to the C++ rules
* for casts. If the lvalue has type double, a cast from any integral type is allowed. If the lvalue has
@ -34,94 +35,80 @@ namespace triqs { namespace utility {
* The class is boost-serializable and implements hdf5 I/O operations.
*/
class parameters {
public :
parameters() {};
parameters (parameters const & other) = default;
parameters (parameters && other) noexcept { swap(*this,other);}
parameters & operator = (parameters const & other) = default;
parameters & operator = (parameters && other) noexcept { swap(*this,other); return *this;}
friend void swap(parameters & a, parameters &b) noexcept { swap(a.object_map,b.object_map);}
struct _data_elem {
std::string key;
_field f;
std::string doc;
template <class Archive> void serialize(Archive& ar, const unsigned int version) {
ar& TRIQS_MAKE_NVP("key", key) & TRIQS_MAKE_NVP("f", f) & TRIQS_MAKE_NVP("doc", doc);
}
};
using _data_t = std::vector<_data_elem>;
_data_t _data;
void insert(std::string const& key, _field&& f, std::string const& doc);
_data_t::iterator find(std::string const& key);
_data_t::const_iterator find(std::string const& key) const;
private:
typedef std::map<std::string, _object> map_t;
map_t object_map;
std::map<std::string, std::string> documentation;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) { ar & TRIQS_MAKE_NVP("object_map",object_map); }
friend class boost::serialization::access;
template <class Archive> void serialize(Archive& ar, const unsigned int version) { ar& TRIQS_MAKE_NVP("_data", _data); }
public:
parameters();
typedef map_t::const_iterator const_iterator;
typedef map_t::iterator iterator;
const_iterator begin() const { return object_map.begin();}
const_iterator end() const { return object_map.end();}
iterator begin() { return object_map.begin();}
iterator end() { return object_map.end();}
/// calls can be chained for multiple parameters
template <typename T> parameters& add_field(std::string const& key, T&& x, std::string const& doc) {
insert(key, _field{std::forward<T>(x),key, false}, doc);
return *this;
}
bool has_key(std::string const & k) const { return object_map.find(k) != object_map.end();}
// add a field without a default value
template <typename T> parameters& add_field(std::string const& key, no_default<T>, std::string const& doc) {
insert(key, _field{T{}, key, true}, doc);
return *this;
}
///
_object & operator[](std::string const & key) {
//std::cout << key << std::endl << std::flush;
auto & r = object_map[key];
if (r.name()=="") r.set_name(key); // in case the object has just been created, set its name
return r;
}
parameters& add_group(std::string const& key, std::string const& doc) {
insert(key, _field{parameters{}, key, false}, doc);
return *this;
}
///
_object const & operator[](std::string const & key) const {
auto it = object_map.find(key);
if ( it== object_map.end()) TRIQS_RUNTIME_ERROR<<"Parameters : the key : "<< key<< " does not exists";
return it->second;
}
void sort_by_key();
friend std::string get_triqs_hdf5_data_scheme(parameters const&) { return "";}
///write contents to an hdf5 archive
friend void h5_write ( h5::group F, std::string const & subgroup_name, parameters const & p){
auto gr = F.create_group(subgroup_name);
for (auto & pvp : p.object_map) h5_write(gr, pvp.first, pvp.second);
}
bool has_key(std::string const& k) const;
///read from an hdf5 archive
friend void h5_read ( h5::group F, std::string const & subgroup_name, parameters & p);
/// Access the parameter key, which must be present (or it throws an exception).
_field& operator[](const char * key);
_field const& operator[](const char * key) const;
friend std::ostream & operator << (std::ostream & out, parameters const & p) {
out<< "{";
for (auto & pvp : p.object_map) out<< pvp.first << " : " << pvp.second<< ", ";
return out<<"}";
}
/// generate help in form of a table of strings containing a list of required and optional parameters
std::vector<std::vector<std::string>> generate_help() const;
/**
* Register a type for conversion, serialization and h5 read/write.
* Note : can be called multiple times (no effect for second and later call).
* Note : this is automatically called when putting an object in parameters
*/
template<typename T> static void register_type() { _object::register_type<T>::invoke();}
/**
* Update with another parameter set.
* If a key is present in other and not in this, add parameter to this.
* If a key is present in both, overwrite parameter in this without any check (Python-like behaviour).
*/
void update(parameters const & pdef);
/// Flags controlling the update_with_default function
//static constexpr ull_t strict_type_check = 1ull; // Type check is strict. Always true now
static constexpr ull_t reject_key_without_default = 1ull<<2;
/**
* Update with a default parameters set pdef.
* If a key is a default parameter in pdef and not in this, add the pdef parameter and value to this.
* If a key is a required parameter in pdef and not in this, then raise triqs::runtime_error exception.
* If a key is present in both, do no change it in this, but check that type are the same.
* If a key is present in this, and not in pdef, and reject_key_without_default is passed, then raise triqs::runtime_error exception.
*/
void update(parameter_defaults const & pdef, ull_t flag =0);
friend std::string get_triqs_hdf5_data_scheme(parameters) { return ""; }
friend void h5_write(h5::group F, std::string const& subgroup_name, parameters const& p);
friend void h5_read(h5::group F, std::string const& subgroup_name, parameters& p);
friend std::ostream& operator<<(std::ostream& out, parameters const& p);
/**
* Update with another parameter set.
* If a key is present in other and not in this, add parameter to this.
* If a key is present in both, overwrite parameter in this without any check (Python-like behaviour).
*/
void update(parameters const&);
};
}}
#endif
inline parameters operator+(parameters p1, parameters const& p2) {
p1.update(p2);
return p1;
}
// can only be implemented after complete declaration of parameters
template <typename... T> _field& _field::add_field(T&&... x) {
auto* pp = dynamic_cast<_data_impl<parameters>*>(p.get());
if (!pp) TRIQS_RUNTIME_ERROR << "Can only use add_field on a subgroup, which " << name() << " is not !";
pp->x.add_field(std::forward<T>(x)...);
return *this;
}
}
}

View File

@ -0,0 +1,18 @@
// REMOVE THIS
#include <triqs/arrays.hpp>
#include "./wrapper_tools.hpp"
namespace triqs { namespace py_tools {
template <> const char * make_format<0>::value = "";
template <> const char * make_format<1>::value = "O&";
template <> const char * make_format<2>::value = "O&O&";
template <> const char * make_format<3>::value = "O&O&O&";
template <> const char * make_format<4>::value = "O&O&O&O&";
template <> const char * make_format<5>::value = "O&O&O&O&O&";
pyref py_converter<triqs::h5::group>::group_type;
}}

View File

@ -1,6 +1,10 @@
#pragma once
#include <Python.h>
#include "structmember.h"
#include <string>
#include <complex>
#include <vector>
#include <triqs/utility/exceptions.hpp>
#pragma clang diagnostic ignored "-Wdeprecated-writable-strings"
#pragma GCC diagnostic ignored "-Wdeprecated-writable-strings"
@ -48,11 +52,12 @@ class pyref {
static pyref string(std::string const &s) { return PyString_FromString(s.c_str());}
};
pyref borrowed(PyObject * ob) { Py_XINCREF(ob); return {ob};}
inline pyref borrowed(PyObject * ob) { Py_XINCREF(ob); return {ob};}
//--------------------- py_converters -----------------------------
template<typename T> struct py_converter {
static void ** init();
static PyObject * c2py(T const & x);
static T py2c(PyObject * ob);
static bool is_convertible(PyObject * ob, bool raise_exception);
@ -60,12 +65,12 @@ template<typename T> struct py_converter {
// We only use these functions in the code, not converter
// TODO : Does c2py return NULL in failure ? Or is it undefined...
template <typename T> PyObject *convert_to_python(T &&x) {
template <typename T> static PyObject *convert_to_python(T &&x) {
return py_converter<typename std::decay<T>::type>::c2py(std::forward<T>(x));
}
// can convert_from_python raise a triqs exception ? NO
template<typename T> auto convert_from_python(PyObject * ob) DECL_AND_RETURN(py_converter<T>::py2c(ob));
template <typename T> bool convertible_from_python(PyObject *ob, bool raise_exception) {
template<typename T> static auto convert_from_python(PyObject * ob) -> decltype(py_converter<T>::py2c(ob)) { return py_converter<T>::py2c(ob);}
template <typename T> static bool convertible_from_python(PyObject *ob, bool raise_exception) {
return py_converter<T>::is_convertible(ob, raise_exception);
}
@ -134,7 +139,6 @@ template <typename T> static int converter_for_parser(PyObject *ob, T *p) {
static bool is_convertible(PyObject *ob, bool raise_exception) { return true;}
};
// -----------------------------------
// basic types
// -----------------------------------
@ -216,6 +220,16 @@ template <> struct py_converter<std::string> {
}
};
template <> struct py_converter<const char *> {
static PyObject *c2py(const char *x) { return PyString_FromString(x); }
static const char * py2c(PyObject *ob) { return PyString_AsString(ob); }
static bool is_convertible(PyObject *ob, bool raise_exception) {
if (PyString_Check(ob)) return true;
if (raise_exception) { PyErr_SetString(PyExc_TypeError, "Can not convert to string");}
return false;
}
};
// --- h5 group of h5py into a triqs::h5 group
template <> struct py_converter<triqs::h5::group> {
@ -282,9 +296,6 @@ template <typename T> struct py_converter<std::vector<T>> {
}
};
// in CPP file ?
pyref py_converter<triqs::h5::group>::group_type;
// --- mini_vector<T,N>---
// via std::vector
template <typename T, int N> struct py_converter<triqs::utility::mini_vector<T,N>> {
@ -305,7 +316,7 @@ template <typename T, int N> struct py_converter<triqs::utility::mini_vector<T,N
template <typename ArrayType> struct py_converter_array {
static PyObject *c2py(ArrayType const &x) { return x.to_python(); }
static ArrayType py2c(PyObject *ob) {
return ArrayType {ob};
return ArrayType (ob);
}
static bool is_convertible(PyObject *ob, bool raise_exception) {
try {
@ -400,12 +411,6 @@ template <> struct _make_index_seq<4> { using type = index_seq<0, 1, 2, 3>; };
template <> struct _make_index_seq<5> { using type = index_seq<0, 1, 2, 3, 4>; };
template <int N> struct make_format { static const char * value;};
template <> const char * make_format<0>::value = "";
template <> const char * make_format<1>::value = "O&";
template <> const char * make_format<2>::value = "O&O&";
template <> const char * make_format<3>::value = "O&O&O&";
template <> const char * make_format<4>::value = "O&O&O&O&";
template <> const char * make_format<5>::value = "O&O&O&O&O&";
template <typename R, typename... T> struct py_converter<std::function<R(T...)>> {