Template instantiation with Armadillo and boost::numeric::odeint - c++
I am trying to combine boost::numeric::odeint with an implementation of the System class of my own (see System.hpp).
A (template) System object is used within a BatchFilter class method, like so:
# BatchFilter.cpp
# template <typename state_type> BatchFilter class {...}
System<state_type> dynamics(this -> args,
N_true,
this -> true_dynamics_fun );
typedef boost::numeric::odeint::runge_kutta_cash_karp54< state_type > error_stepper_type;
auto stepper = boost::numeric::odeint::make_controlled<error_stepper_type>( 1.0e-13 , 1.0e-16 );
auto tbegin = T_obs.begin();
auto tend = T_obs.end();
boost::numeric::odeint::integrate_times(stepper, dynamics, X0_true_copy, tbegin, tend,0.1,
Observer::push_back_state(this -> true_state_history));
BatchFilter is a template derived class which I am explicitly instantiating at the bottom of BatchFilter.cpp. The two explicit instantiations are
template class BatchFilter< arma::vec >;
template class BatchFilter< arma::vec::fixed<2> >;
The Base class is also explicitly instantiated. I must use arma::vec::fixed<2> since using arma::vec within odeint causes a runtime crash as the state will not have the proper size.
What does not work?
The instantiation with arma::vec::fixed<2> fails while the one with arma::vec succeeds. The compiler complains about an illegal binding:
cannot bind non-const lvalue reference of type'arma::Col<double>::fixed<2>&' to an rvalue of type'arma::Col<double>::fixed<2>' sys( x , m_dxdt.m_v ,t );
What puzzles me is that everything works fine when the explicit instantiation of BatchFilter< arma::vec > succeeds while BatchFilter< arma::vec::fixed<2> > fails.
Any insight as to what is going on?
[ 3%] Building CXX object CMakeFiles/ASPEN.dir/source/BatchFilter.cpp.o
In file included from /usr/local/include/boost/numeric/odeint.hpp:35:0,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/include/Filter.hpp:5,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/include/BatchFilter.hpp:5,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/source/BatchFilter.cpp:1:
/usr/local/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp: In instantiation of 'boost::numeric::odeint::controlled_step_result boost::numeric::odeint::controlled_runge_kutta<ErrorStepper, ErrorChecker, StepAdjuster, Resizer, boost::numeric::odeint::explicit_error_stepper_tag>::try_step_v1(System, StateInOut&, boost::numeric::odeint::controlled_runge_kutta<ErrorStepper, ErrorChecker, StepAdjuster, Resizer, boost::numeric::odeint::explicit_error_stepper_tag>::time_type&, boost::numeric::odeint::controlled_runge_kutta<ErrorStepper, ErrorChecker, StepAdjuster, Resizer, boost::numeric::odeint::explicit_error_stepper_tag>::time_type&) [with System = System<arma::Col<double>::fixed<2>, arma::Mat<double> >; StateInOut = arma::Col<double>; ErrorStepper = boost::numeric::odeint::runge_kutta_cash_karp54<arma::Col<double> >; ErrorChecker = boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::range_algebra, boost::numeric::odeint::default_operations>; StepAdjuster = boost::numeric::odeint::default_step_adjuster<double, double>; Resizer = boost::numeric::odeint::initially_resizer; boost::numeric::odeint::controlled_runge_kutta<ErrorStepper, ErrorChecker, StepAdjuster, Resizer, boost::numeric::odeint::explicit_error_stepper_tag>::time_type = double]':
/usr/local/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:283:27: required from 'boost::numeric::odeint::controlled_step_result boost::numeric::odeint::controlled_runge_kutta<ErrorStepper, ErrorChecker, StepAdjuster, Resizer, boost::numeric::odeint::explicit_error_stepper_tag>::try_step(System, StateInOut&, boost::numeric::odeint::controlled_runge_kutta<ErrorStepper, ErrorChecker, StepAdjuster, Resizer, boost::numeric::odeint::explicit_error_stepper_tag>::time_type&, boost::numeric::odeint::controlled_runge_kutta<ErrorStepper, ErrorChecker, StepAdjuster, Resizer, boost::numeric::odeint::explicit_error_stepper_tag>::time_type&) [with System = System<arma::Col<double>::fixed<2>, arma::Mat<double> >; StateInOut = arma::Col<double>; ErrorStepper = boost::numeric::odeint::runge_kutta_cash_karp54<arma::Col<double> >; ErrorChecker = boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::range_algebra, boost::numeric::odeint::default_operations>; StepAdjuster = boost::numeric::odeint::default_step_adjuster<double, double>; Resizer = boost::numeric::odeint::initially_resizer; boost::numeric::odeint::controlled_runge_kutta<ErrorStepper, ErrorChecker, StepAdjuster, Resizer, boost::numeric::odeint::explicit_error_stepper_tag>::time_type = double]'
/usr/local/include/boost/numeric/odeint/integrate/detail/integrate_times.hpp:101:81: required from 'size_t boost::numeric::odeint::detail::integrate_times(Stepper, System, State&, TimeIterator, TimeIterator, Time, Observer, boost::numeric::odeint::controlled_stepper_tag) [with Stepper = boost::numeric::odeint::controlled_runge_kutta<boost::numeric::odeint::runge_kutta_cash_karp54<arma::Col<double> >, boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::range_algebra, boost::numeric::odeint::default_operations>, boost::numeric::odeint::default_step_adjuster<double, double>, boost::numeric::odeint::initially_resizer, boost::numeric::odeint::explicit_error_stepper_tag>; System = System<arma::Col<double>::fixed<2>, arma::Mat<double> >; State = arma::Col<double>; TimeIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double> >; Time = double; Observer = Observer::push_back_state<arma::Col<double> >; size_t = long unsigned int]'
/usr/local/include/boost/numeric/odeint/integrate/integrate_times.hpp:129:35: required from 'size_t boost::numeric::odeint::integrate_times(Stepper, System, State&, TimeIterator, TimeIterator, Time, Observer) [with Stepper = boost::numeric::odeint::controlled_runge_kutta<boost::numeric::odeint::runge_kutta_cash_karp54<arma::Col<double> >, boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::range_algebra, boost::numeric::odeint::default_operations>, boost::numeric::odeint::default_step_adjuster<double, double>, boost::numeric::odeint::initially_resizer, boost::numeric::odeint::explicit_error_stepper_tag>; System = System<arma::Col<double>::fixed<2>, arma::Mat<double> >; State = arma::Col<double>; TimeIterator = __gnu_cxx::__normal_iterator<const double*, std::vector<double> >; Time = double; Observer = Observer::push_back_state<arma::Col<double> >; size_t = long unsigned int]'
/Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/source/BatchFilter.cpp:231:42: required from void BatchFilter<state_type>::compute_reference_state_history(const std::vector<double>&, std::vector<_RealType>&, std::vector<arma::Mat<double> >&) [with state_type = arma::Col<double>::fixed<2>]'
/Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/source/BatchFilter.cpp:327:16: required from here
/usr/local/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:481:12: error: no match for call to '(boost::numeric::odeint::unwrap_reference<System<arma::Col<double>::fixed<2>, arma::Mat<double> > >::type {aka System<arma::Col<double>::fixed<2>, arma::Mat<double> >}) (arma::Col<double>&, arma::Col<double>&, boost::numeric::odeint::controlled_runge_kutta<boost::numeric::odeint::runge_kutta_cash_karp54<arma::Col<double> >, boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::range_algebra, boost::numeric::odeint::default_operations>, boost::numeric::odeint::default_step_adjuster<double, double>, boost::numeric::odeint::initially_resizer, boost::numeric::odeint::explicit_error_stepper_tag>::time_type&)'
sys( x , m_dxdt.m_v ,t );
~~~^~~~~~~~~~~~~~~~~~~~~
In file included from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/include/Filter.hpp:6:0,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/include/BatchFilter.hpp:5,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/source/BatchFilter.cpp:1:
/Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/include/System.hpp:32:7: note: candidate: void System<state_type, jacobian_type>::operator()(const state_type&, state_type&, double) [with state_type = arma::Col<double>::fixed<2>; jacobian_type = arma::Mat<double>] <near match>
void operator() (const state_type & x , state_type & dxdt , const double t ){
^~~~~~~~
/Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/include/System.hpp:32:7: note: conversion of argument 2 would be ill-formed:
In file included from /usr/local/include/boost/numeric/odeint.hpp:35:0,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/include/Filter.hpp:5,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/include/BatchFilter.hpp:5,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/source/BatchFilter.cpp:1:
/usr/local/include/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:481:25: error: cannot bind non-const lvalue reference of type 'arma::Col<double>::fixed<2>&' to an rvalue of type 'arma::Col<double>::fixed<2>'
sys( x , m_dxdt.m_v ,t );
~~~~~~~^~~
In file included from /usr/local/include/armadillo:568:0,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/include/BatchFilter.hpp:4,
from /Users/bbercovici/GDrive/CUBoulder/Research/code/ASPEN_gui_less/lib/source/BatchFilter.cpp:1:
/usr/local/include/armadillo_bits/Col_meat.hpp:1145:1: note: after user-defined conversion: arma::Col<eT>::fixed<fixed_n_elem>::fixed(const arma::Base<eT, T1>&) [with T1 = arma::Mat<double>; long long unsigned int fixed_n_elem = 2; eT = double]
Col<eT>::fixed<fixed_n_elem>::fixed(const Base<eT,T1>& A)
^~~~~~~
make[2]: *** [CMakeFiles/ASPEN.dir/source/BatchFilter.cpp.o] Error 1
make[1]: *** [CMakeFiles/ASPEN.dir/all] Error 2
make: *** [all] Error 2
For reference, System.hpp is down here:
# System.hpp
template <typename state_type,typename jacobian_type = arma::mat> class System {
public:
System(const Args & args,
unsigned int N_est,
state_type (*estimate_dynamics_fun)(double, const state_type & , const Args & args) ,
jacobian_type (*jacobian_estimate_dynamics_fun)(double, const state_type & , const Args & args),
unsigned int N_true = 0,
state_type (*true_dynamics_fun)(double, const state_type & , const Args & args) = nullptr)
: N_est(N_est), N_true(N_true){
this -> estimate_dynamics_fun = estimate_dynamics_fun;
this -> true_dynamics_fun = estimate_dynamics_fun;
this -> jacobian_estimate_dynamics_fun = jacobian_estimate_dynamics_fun;
this -> args = args;
}
System(const Args & args,
unsigned int N_true,
state_type (*true_dynamics_fun)(double, const state_type & , const Args & args))
: N_est(0), N_true(N_true){
this -> true_dynamics_fun = true_dynamics_fun;
this -> args = args;
}
void operator() (const state_type & x , state_type & dxdt , const double t ){
if (this -> true_dynamics_fun != nullptr){
dxdt.rows(this -> N_est + this -> N_est * this -> N_est,
this -> N_est + this -> N_est * this -> N_est + this -> N_true - 1) = this -> true_dynamics_fun(t,
x.rows(this -> N_est + this -> N_est * this -> N_est,
this -> N_est + this -> N_est * this -> N_est + this -> N_true - 1),args);
}
if (this -> estimate_dynamics_fun != nullptr){
arma::mat Phi = arma::reshape(x.rows(this -> N_est,
this -> N_est + this -> N_est * this -> N_est - 1), this -> N_est, this -> N_est );
arma::mat A = this -> jacobian_estimate_dynamics_fun(t,x.rows(0,this -> N_est - 1),this -> args);
dxdt.rows(0,this -> N_est - 1) = this -> estimate_dynamics_fun(t,x.rows(0,this -> N_est - 1),this -> args);
dxdt.rows(this -> N_est,
this -> N_est + this -> N_est * this -> N_est - 1) = arma::vectorise(A * Phi);
}
}
protected:
const unsigned int N_est;
const unsigned int N_true;
state_type (*estimate_dynamics_fun)(double, const state_type & , const Args & args) = nullptr;
state_type (*true_dynamics_fun)(double, const state_type & , const Args & args) = nullptr;
jacobian_type (*jacobian_estimate_dynamics_fun)(double, const state_type & , const Args & args) = nullptr;
Args args;
};
I found a way around the resizing issue here:
https://reformatcode.com/code/c/armadillo-conflicts-with-boost-odeint-odeint-resizes-the-state-vector-to-zero-during-integration
The solution consists in extending boost:numeric::odeint with the following adapters that handle automatic resizing of the arma::vec for safe use with odeint
#include <armadillo>
namespace boost { namespace numeric { namespace odeint {
template <>
struct is_resizeable<arma::vec>
{
typedef boost::true_type type;
const static bool value = type::value;
};
template <>
struct same_size_impl<arma::vec, arma::vec>
{
static bool same_size(const arma::vec & x, const arma::vec& y)
{
return x.n_rows == y.n_rows;
}
};
template<>
struct resize_impl<arma::vec, arma::vec>
{
static void resize(arma::vec &v1, const arma::vec & v2)
{
v1.resize(v2.n_rows,1);
}
};
} } } // namespace boost::numeric::odeint
Related
How to change a container elements in another 'temporary' container
I have a temporary list that needs to change its elements and erase() them from the list as a way of marking them as done. std::list<Vertex> temp {vertices.begin(), vertices.end()}; I've tried using Vertex& and Vertex* without success, and the second one makes the code very messy. What is the proper way to do this? Thanks in advance Edit: surrounding code int label = 1; // change elements without affecting temporary list std::list<Vertex*> unlabeledVertices {graph.vertices.begin(), graph.vertices.end()}; for (auto iter = unlabeledVertices.begin(); iter != unlabeledVertices.end(); ++label) { (*iter)->label = label; // temporary list std::list<Vertex*> currentLabelVertices; currentLabelVertices.push_back(*iter); // check if we can label any other vertex with the current color auto nestedIter = iter; for (nestedIter++; nestedIter != unlabeledVertices.end(); ) { // checking current vertex against any other colored vertex if (std::none_of(currentLabelVertices.begin(), currentLabelVertices.end(), [=](const Vertex* v){ return (*nestedIter)->isConnected(*v); })) { (*nestedIter)->label = label; currentLabelVertices.push_back(*nestedIter); nestedIter = unlabeledVertices.erase(nestedIter); } else { nestedIter++; } } iter = unlabeledVertices.erase(iter); } Error message: /usr/bin/g++ -fdiagnostics-color=always -g /home/etzl/projects/c-cpp/test/*.cc -o exec In file included from /usr/include/x86_64-linux-gnu/c++/10/bits/c++allocator.h:33, from /usr/include/c++/10/bits/allocator.h:46, from /usr/include/c++/10/string:41, from /usr/include/c++/10/bits/locale_classes.h:40, from /usr/include/c++/10/bits/ios_base.h:41, from /usr/include/c++/10/ios:42, from /usr/include/c++/10/ostream:38, from /usr/include/c++/10/iostream:39, from /home/etzl/projects/c-cpp/test/main.cc:1: /usr/include/c++/10/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = Vertex*; _Args = {Vertex&}; _Tp = std::_List_node<Vertex*>]’: /usr/include/c++/10/bits/alloc_traits.h:512:17: required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = Vertex*; _Args = {Vertex&}; _Tp = std::_List_node<Vertex*>; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::_List_node<Vertex*> >]’ /usr/include/c++/10/bits/stl_list.h:637:33: required from ‘std::__cxx11::list<_Tp, _Alloc>::_Node* std::__cxx11::list<_Tp, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {Vertex&}; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>; std::__cxx11::list<_Tp, _Alloc>::_Node = std::__cxx11::list<Vertex*>::_Node]’ /usr/include/c++/10/bits/stl_list.h:1911:32: required from ‘void std::__cxx11::list<_Tp, _Alloc>::_M_insert(std::__cxx11::list<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {Vertex&}; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>; std::__cxx11::list<_Tp, _Alloc>::iterator = std::__cxx11::list<Vertex*>::iterator]’ /usr/include/c++/10/bits/stl_list.h:1227:19: required from ‘void std::__cxx11::list<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {Vertex&}; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>]’ /usr/include/c++/10/bits/stl_list.h:1840:18: required from ‘void std::__cxx11::list<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = std::_List_iterator<Vertex>; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>]’ /usr/include/c++/10/bits/stl_list.h:806:26: required from ‘std::__cxx11::list<_Tp, _Alloc>::list(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = std::_List_iterator<Vertex>; <template-parameter-2-2> = void; _Tp = Vertex*; _Alloc = std::allocator<Vertex*>; std::__cxx11::list<_Tp, _Alloc>::allocator_type = std::allocator<Vertex*>]’ /home/etzl/projects/c-cpp/test/main.cc:58:87: required from here /usr/include/c++/10/ext/new_allocator.h:150:4: error: cannot convert ‘Vertex’ to ‘Vertex*’ in initialization 150 | { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Build finished with error(s)
You should use std::unordered_set<Vertex*> currentLabelVertices instead of a list. It gives O(1) lookup instead of the O(n) solution you have with std::none_of(). Your other problem is here: std::list<Vertex*> unlabeledVertices {graph.vertices.begin(), graph.vertices.end()}; It doesn't compile because graph.vertices contains Vertex instances, not pointers. The fix is simple: std::list<Vertex*> unlabeledVertices; for (auto& vertex : graph.vertices) unlabeledVertices.push_back(&vertex);
How can I make my stepper error controlled in boost odeint with complex matrices as state types?
I tried this way, but I got very long compiling error message. integrate_adaptive( make_controlled(1.E-12,1.E-12,stepper_type() ), matrix_ode() , x , 0.0 , 15. , 0.01 , write_ofsx ); where stepper_type is: typedef runge_kutta_dopri5< state_type > stepper_type; where state_type is: typedef matrix< complex< double > > state_type; Some details of the error message which might be interesting: boost_1_74_0/boost/numeric/odeint/stepper/controlled_runge_kutta.hpp:89:40: error: cannot convert 'boost::numeric::odeint::vector_space_norm_inf<boost::numeric::ublas::matrix<std::complex<double> >, void>::result_type' {aka 'std::complex<double>'} to 'boost::numeric::odeint::default_error_checker<double, boost::numeric::odeint::vector_space_algebra, boost::numeric::odeint::default_operations>::value_type' {aka 'double'} in return return algebra.norm_inf( x_err ); ^ and boost_1_74_0/boost/numeric/odeint/util/ublas_wrapper.hpp:60:55: error: could not convert 'boost::numeric::ublas::norm_inf(const boost::numeric::ublas::matrix_expression<E>&) [with E = boost::numeric::ublas::matrix<std::complex<double> >; typename boost::numeric::ublas::matrix_scalar_unary_traits<E, boost::numeric::ublas::matrix_norm_inf<E> >::result_type = boost::numeric::ublas::matrix_scalar_unary<boost::numeric::ublas::matrix<std::complex<double> >, boost::numeric::ublas::matrix_norm_inf<boost::numeric::ublas::matrix<std::complex<double> > > >]()' from 'boost::numeric::ublas::matrix_scalar_unary_traits<boost::numeric::ublas::matrix<std::complex<double> >, boost::numeric::ublas::matrix_norm_inf<boost::numeric::ublas::matrix<std::complex<double> > > >::result_type' {aka 'boost::numeric::ublas::matrix_scalar_unary<boost::numeric::ublas::matrix<std::complex<double> >, boost::numeric::ublas::matrix_norm_inf<boost::numeric::ublas::matrix<std::complex<double> > > >'} to 'boost::numeric::odeint::vector_space_norm_inf<boost::numeric::ublas::matrix<std::complex<double> >, void>::result_type' {aka 'std::complex<double>'} return boost::numeric::ublas::norm_inf( x ); ^
Result reshuffling during instruction selection
In an LLVM backend, during instruction selection, my input looks something like this: t17: i16,ch = load t16:1, t2, undef:i16 I'd like to select an opcode that has some extra result as well, i.e. replace the above with something like t17: i16, _: i16, ch = LDW t2, undef:i16 Of course, if I just try to replace the load with this LDW, it fails because the return types are not the same: llc: lib/CodeGen/SelectionDAG/SelectionDAG.cpp:6525: void llvm::SelectionDAG::ReplaceAllUsesWith(llvm::SDNode*, llvm::SDNode*): Assertion `(!From->hasAnyUseOfValue(i) || From->getValueType(i) == To->getValueType(i)) && "Cannot use this version of ReplaceAllUsesWith!"' failed. That's because for i == 1, From->getValueType(i) is ch, and To->getValueType(i) is i16. My question is, how do I re-shuffle the tuple (x: i16, y: i16, ch) into (x : i16, ch) during instruction selection? I.e. how would I do something like t17 : i16, ch = project [0, 2] (LDW t2, undef:i16) where project [0, 2] would be some magic tuple-reshuffling pseudo-instruction that just takes care of dropping coordinate 1? EDIT: Found what seemed like a possible solution, but still doesn't work I found that there's a MERGE_VALUES node type which should make what I'm trying to do possible, since it allows taking some inputs and packing them into a multi-value output. So I tried SDNode* LDW = CurDAG->getMachineNode( AVR::LDWRdPtr, SDLoc(N), VT, PtrVT, MVT::Other, LD->getBasePtr(), LD->getChain()); SDValue Unpack[] = { SDValue(LDW, 0), SDValue(LDW, 2) }; SDNode* NN = CurDAG->getMergeValues(Unpack, SDLoc(N)).getNode(); ReplaceNode(N, NN); If I run instruction selection with --debug, this looks very promising, since it turns this: SelectionDAG has 16 nodes: t0: ch = EntryToken t2: i16,ch = CopyFromReg t0, Register:i16 %vreg0 t5: i16,ch = load<LD2[%v25](align=1)(dereferenceable)> t0, t2, undef:i16 t9: ch,glue = callseq_start t5:1, TargetConstant:i16<0> t11: ch,glue = CopyToReg t9, Register:i16 %R25R24, t5 t13: ch,glue = CALL t11, TargetGlobalAddress:i16<i8 (i16)* #read_ram> 0, Register:i16 %R25R24, RegisterMask:Untyped, t11:1 t14: ch,glue = callseq_end t13, TargetConstant:i16<0>, TargetConstant:i16<0>, t13:1 t16: i8,ch,glue = CopyFromReg t14, Register:i8 %R24, t14:1 t17: ch = RET_FLAG t16:1 into this: SelectionDAG has 16 nodes: t0: ch = EntryToken t9: i16,ch,glue = ADJCALLSTACKDOWN TargetConstant:i16<0>, t19:1 t11: ch,glue = CopyToReg t9:1, Register:i16 %R25R24, t19 t13: ch,glue = CALLk TargetGlobalAddress:i16<i8 (i16)* #read_ram> 0, Register:i16 %R25R24, RegisterMask:Untyped, t11, t11:1 t14: i16,ch,glue = ADJCALLSTACKUP TargetConstant:i16<0>, TargetConstant:i16<0>, t13, t13:1 t2: i16,ch = CopyFromReg t0, Register:i16 %vreg0 t18: i16,i16,ch = LDWRdPtr t2, t0 t19: i16,ch = merge_values t18, t18:2 t16: i8,ch,glue = CopyFromReg t14:1, Register:i8 %R24, t14:2 t17: ch = RET t16:1 which looks fine to me: t18,_,ch is where we store the result of LDW, then t19,ch unpacks it. However, this later trips up instruction scheduling: llc: CodeGen/SelectionDAG/InstrEmitter.cpp:305: unsigned int llvm::InstrEmitter::getVR(llvm::SDValue, llvm::DenseMap<llvm::SDValue, unsigned int>&): Assertion `I != VRBaseMap.end() && "Node emitted out of order - late"' failed. #9 0x0000000001a7eae8 llvm::InstrEmitter::getVR(llvm::SDValue, llvm::DenseMap<llvm::SDValue, unsigned int, llvm::DenseMapInfo<llvm::SDValue>, llvm::detail::DenseMapPair<llvm::SDValue, unsigned int> >&) CodeGen/SelectionDAG/InstrEmitter.cpp:305:0 #10 0x0000000001a819c2 llvm::InstrEmitter::EmitSpecialNode(llvm::SDNode*, bool, bool, llvm::DenseMap<llvm::SDValue, unsigned int, llvm::DenseMapInfo<llvm::SDValue>, llvm::detail::DenseMapPair<llvm::SDValue, unsigned int> >&) CodeGen/SelectionDAG/InstrEmitter.cpp:928:0 #11 0x0000000001971c9c llvm::InstrEmitter::EmitNode(llvm::SDNode*, bool, bool, llvm::DenseMap<llvm::SDValue, unsigned int, llvm::DenseMapInfo<llvm::SDValue>, llvm::detail::DenseMapPair<llvm::SDValue, unsigned int> >&) CodeGen/SelectionDAG/InstrEmitter.h:124:0 #12 0x0000000001988bdb llvm::ScheduleDAGSDNodes::EmitSchedule(llvm::MachineInstrBundleIterator<llvm::MachineInstr, false>&) CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp:841:0 #13 0x0000000001a33cdc llvm::SelectionDAGISel::CodeGenAndEmitDAG() CodeGen/SelectionDAG/SelectionDAGISel.cpp:890:0
llvm createCall Calling a function with a bad signature
I want to make a function in LLVM which is an adapter with only a function call foo(idx, mn). The function prototype of foo is void foo(unsigned char, const char*). // adapter Function with only a function call foo(idx, mn) llvm::Function* createCallFun(llvm::Module* M, llvm::Function* exit_f) { llvm::LLVMContext& Ctx = M->getContext(); llvm::Function* foo_f = foo_prototype(Ctx, M); llvm::Constant* c = M->getOrInsertFunction("__call_fun", FunctionType::getVoidTy(Ctx), llvm::Type::getInt32Ty(Ctx), llvm::Type::getInt32Ty(Ctx), NULL); llvm::Function* call_fun_f = llvm::cast<llvm::Function>(c); llvm::BasicBlock* entry = llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", call_fun_f); llvm::IRBuilder<> builder(entry); llvm::Function::arg_iterator args = call_fun_f->arg_begin(); llvm::Value* idx = &*args++; idx->setName("idx"); llvm::Value* mn = &*args++; mn->setName("mn"); llvm::Value* greater = builder.CreateICmpSGE(idx, mn, "tmp"); std::vector<llvm::Value*> fun_args; fun_args.push_back(greater); fun_args.push_back(err_msg); builder.CreateCall(foo_f, fun_args); return call_fun_f; } Then I got this error: lib/IR/Instructions.cpp:245: void llvm::CallInst::init(llvm::FunctionType*, llvm::Value*, llvm::ArrayRef, llvm::ArrayRef >, const llvm::Twine&): Assertion `(i >= FTy->getNumParams() || FTy->getParamType(i) == Args[i]->getType()) && "Calling a function with a bad signature!"' failed. It seems the first argument of foo has a type mismatch. How can I cast the Value greater to unsigned char type?
I fixed this error by cast greater with CreateZExt. llvm::Value *castuchar = builder.CreateZExt(greater, llvm::Type::getInt8Ty(Ctx), "tmp1");
multi_index template compiling error
2 Questions: 1. Do i really need to pass parameter to modify/modify_key via member? 2. Why do i have this compilation error To see the entire code with the error, you can look at http://coliru.stacked-crooked.com/a/d6241361318e1925 the error is MultiIndex4.h: In member function 'uint32_t CrMultiParameterMultiIndex::ModifyKeyBy(SearchingKey&, ModifyKeyType&) [with SearchingTagType = IMEI_tag, ModifyingTagType = IMEI_tag, SearchingKey = uint32_t, ModifyKeyType = uint32_t]': MultiIndex4.h:183: instantiated from here MultiIndex4.h:119: error: no matching function for call to 'boost::multi_index::multi_index_container<UsersKey, UsersKey_indices, std::allocator<UsersKey> >::modify_key(boost::multi_index::detail::bidir_node_iterator<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::index_node_base<UsersKey, std::allocator<UsersKey> > > >&, boost::function<void ()(uint32_t&)>&)' *** Errors occurred during this build *** I have a class CrMultiParameterMultiIndex that hold a multi-index that have 2 indexes. I tried to create a template function that search only according a part of the key and modify only a part of the key. This class have a helper function template <typename TagType,typename SearchingKey> typename GlobalHash::index<TagType>::type::iterator GetIteratorBy(SearchingKey & key){ return m_pGlobalHash->get<TagType>().find(key) ; } and modify function that use it template <typename SearchingTagType,typename ModifyingTagType,typename SearchingKey,typename ModifyKeyType> uint32_t ModifyKeyBy(SearchingKey & key,ModifyKeyType & pi_Modifykey) { uint32_t hRes = 1; //search for entry by TagType typedef typename GlobalHash::index<SearchingTagType>::type IndexType; typename IndexType::iterator it = GetIteratorBy<SearchingTagType>(key); //entry found if( it != m_pGlobalHash->get<SearchingTagType>().end() ) { //Set parameter to modify hRes = SetParameterKeys<ModifyingTagType>(pi_Modifykey); if(hRes == 1) { //get iteraror to modify typedef typename GlobalHash::index<ModifyingTagType>::type ModifyIndexType; typename ModifyIndexType::iterator itToModify = m_pGlobalHash->get<ModifyingTagType>().iterator_to(*it); boost::function<void( ModifyKeyType &)> f = boost::bind(&CrMultiParameterMultiIndex::ModifyKey<ModifyingTagType, ModifyKeyType >, this, _1); //modify key failed if(m_pGlobalHash->modify_key(itToModify , f)==false) hRes = 0; } } //entry not found else hRes = 0; return hRes; } this compile uint64_t nFromImsi = 1; uint64_t nToImsi = 1; m_multiParam.ModifyKeyBy<IMSI_tag,IMSI_tag>( nFromImsi,nToImsi) but not this uint32_t nFromImsi = 1; uint32_t nToImsi = 1; m_multiParam.ModifyKeyBy<IMEI_tag,IMEI_tag>( nFromImsi,nToImsi) Why? and how can it compile and here are the modifiers template <> inline void CrMultiParameterMultiIndex::ModifyKey<IMEI_tag>( uint32_t & po_Key){po_Key = m_ParameterKeys.IMEI;} template <> inline void CrMultiParameterMultiIndex::ModifyKey<IMSI_tag>(uint64_t & po_Key){po_Key = m_ParameterKeys.IMSI;}
David, The problem with if(m_pGlobalHash->modify_key(itToModify , f)==false) lies in the fact that m_pGlobalHashis a view to index #0 (order_by_IMSI) and does not accept iterators to view #1 (order_by_IMEI). You can either project iterators or select the appropriate index: if(m_pGlobalHash->get<ModifyingTagType>().modify_key(itToModify , f)==false)