boost::odeint not working as intended (pass arguments of system function by reference!) - boost

I'm trying to use boost::odeint inside one of my class's member functions in a .cpp file. My class is called OdeDriver and the member is :
ublas::matrix\<double\> OdeDriver::RungeKuttaStep(
const ublas::vector\<double\> &U,
const ublas::vector\<double\> &alphas,
const int &step){...}
I'm doing the following inside this member function inside a for loop:
state_type x0 = {0.1, 0.1, 0.1, 0.1};
auto lambda = \[\](const state_type x, state_type dxdt, const time_type t)
{
dxdt = {1, 1, 1, 1};
};
stepper_type rk;
rk.do_step(lambda, x0,0.0, 0.1);
where I have defined the above types in a separate .hpp file as:
typedef std::vector\<double\> state_type;
typedef odeint::runge_kutta4\<state_type\> stepper_type;
The problem is that x0 is not updating, it should be x0 = {0.2,0.2,0.2,0.2}. I have noticed that inside the do_step function, after calling sys( x , m_dxdt.m_v ,t ), the class property m_dxdt.m_v is not updated to the value {0.1,0.1,0.1,0.1} even though the system function is working as intended. Somehow, the system function output is not being copied to m_dxdt.m_v.
If i run this same code on the main function, everything works as intended (I haven't tried running the exact code above, but I can use boost::odeint in the main() with no problems).
Can you tell me what's wrong?

While I was writing my question I realized what I was doing wrong, so I decided to post my question and answer it myself since I spent a long time trying to figure this out.
For some reason, I thought that passing a std::vector<double> to a function was always passed by reference. That is,
void foo(std::vector<double> v){...}
would pass v by reference to foo.
The fix is I have to pass the arguments to my lambda function by reference using &.
But am I wrong in assuming that passing a std::vector<double> to a function without using the & passes the vector by reference?

Related

Eigen generic function to handle different data types

I am trying to write a generic function that receives a DenseBase<Derived> parameter like this:
template<class Derived>
MatrixXd Math::gradient(const DenseBase<Derived> &y, const Dimension dimension)
{
...
Derived v = dimension == COLUMNS ? y.derived() : y.derived().transpose();
...
}
I'm having an error when I call the function in this manner:
const VectorXd g = Math::gradient(curve/ peak);
The curve/ peak expression returns a CwiseBinaryOp type, which becomes the Derived type of the Math::gradient templated function.
However, the y.derived().transpose() expression returns a Transpose<MatrixType> which yields a compilation error due to the different data type with respect to the CwiseBinaryOp
I know I can call the Math::gradient function previously storing the curve/ peak in a VectorXd to solve the problem, however, how can I write the function to handle this different datatypes?
Thank you very much.
I think I have found a solution to my own question (sorry for the poor explanation of the problem).
By using the eval() method of the DenseBase<Derived> variable y, Eigen resolves the "intermediate" expression types, such as the CwiseBinaryOp or the Transpose<MatrixType> in my particular case, to a PlainObject variable type.
So a possible solution could be:
template<class Derived>
MatrixXd Math::gradient(const DenseBase<Derived> &y, const Dimension dimension)
{
...
typename Derived::PlainObject v = dimension == COLUMNS ? y.derived().eval() : y.derived().transpose().eval();
...
}
Thank you very much for your attention

Eigen Library: Compiler error when passing Block reference to templated function

I am getting a compilation error when trying to call templated functions with arguments that are Eigen references.
For example, consider the following simplified example:
template <typename derived>
inline void fcn(Eigen::MatrixBase<derived> &M){
// ...
M.template block<3,3>(0,0) = something here
// ...
}
// I get compiler errors when trying to call this function as follows:
Eigen::MatrixXd A(100,100);
// call the above function with a Block as an argument
fcn(A.block<9,6>(10,10));
The compiler complains that I am trying to instantiate a non-const reference with an object passed by value (if my undersdanding of the following is correct):
error: invalid initialization of non-const reference of type ‘Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1>, 9, 6, false> >&’ from an rvalue of type ‘Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1>, 9, 6, false> >’
If I try to declare the argument of fcn as const then I am getting an error when I try to modify it inside the function.
The only solution I've found to work to fix this issue is to declare the arument of the function to be a const &, and then to use const_cast to "remove the const qualifier" when accessing M inside the function.
But this is hacky and I makes the code extremely messy. Am I missing some obvious solution to this problem? Any help would be appreciated.
Thanks!
T
This is because in c++ you cannot bind a temporary object (here the proxy object returned by .block()) to a non-const reference. The solution is to name it:
auto A_block = A.block<9,6>(10,10);
fcn(A_block);

Why would const-ness of a local variable inhibit move semantics for the returned value?

struct STest : public boost::noncopyable {
STest(STest && test) : m_n( std::move(test.m_n) ) {}
explicit STest(int n) : m_n(n) {}
int m_n;
};
STest FuncUsingConst(int n) {
STest const a(n);
return a;
}
STest FuncWithoutConst(int n) {
STest a(n);
return a;
}
void Caller() {
// 1. compiles just fine and uses move ctor
STest s1( FuncWithoutConst(17) );
// 2. does not compile (cannot use move ctor, tries to use copy ctor)
STest s2( FuncUsingConst(17) );
}
The above example illustrates how in C++11, as implemented in Microsoft Visual C++ 2012, the internal details of a function can modify its return type. Up until today, it was my understanding that the declaration of the return type is all a programmer needs to know to understand how the return value will be treated, e.g., when passed as a parameter to a subsequent function call. Not so.
I like making local variables const where appropriate. It helps me clean up my train of thought and clearly structure an algorithm. But beware of returning a variable that was declared const! Even though the variable will no longer be accessed (a return statement was executed, after all), and even though the variable that was declared const has long gone out of scope (evaluation of the parameter expression is complete), it cannot be moved and thus will be copied (or fail to compile if copying is not possible).
This question is related to another question, Move semantics & returning const values. The difference is that in the latter, the function is declared to return a const value. In my example, FuncUsingConst is declared to return a volatile temporary. Yet, the implementational details of the function body affect the type of the return value, and determine whether or not the returned value can be used as a parameter to other functions.
Is this behavior intended by the standard?
How can this be regarded useful?
Bonus question: How can the compiler know the difference at compile time, given that the call and the implementation may be in different translation units?
EDIT: An attempt to rephrase the question.
How is it possible that there is more to the result of a function than the declared return type? How does it even seem acceptable at all that the function declaration is not sufficient to determine the behavior of the function's returned value? To me that seems to be a case of FUBAR and I'm just not sure whether to blame the standard or Microsoft's implementation thereof.
As the implementer of the called function, I cannot be expected to even know all callers, let alone monitor every little change in the calling code. On the other hand, as the implementer of the calling function, I cannot rely on the called function to not return a variable that happens to be declared const within the scope of the function implementation.
A function declaration is a contract. What is it worth now? We are not talking about a semantically equivalent compiler optimization here, like copy elision, which is nice to have but does not change the meaning of code. Whether or not the copy ctor is called does change the meaning of code (and can even break the code to a degree that it cannot be compiled, as illustrated above). To appreciate the awkwardness of what I am discussing here, consider the "bonus question" above.
I like making local variables const where appropriate. It helps me clean up my train of thought and clearly structure an algorithm.
That is indeed a good practice. Use const wherever you can. Here, however, you cannot (if you expect your const object to be moved from).
The fact that you declare a const object inside your function is a promise that your object's state won't ever be altered as long as the object is alive - in other words, never before its destructor is invoked. Not even immediately before its destructor is invoked. As long as it is alive, the state of a const object shall not change.
However, here you are somehow expecting this object to be moved from right before it gets destroyed by falling out of scope, and moving is altering state. You cannot move from a const object - not even if you are not going to use that object anymore.
What you can do, however, is to create a non-const object and access it in your function only through a reference to const bound to that object:
STest FuncUsingConst(int n) {
STest object_not_to_be_touched_if_not_through_reference(n);
STest const& a = object_not_to_be_touched_if_not_through_reference;
// Now work only with a
return object_not_to_be_touched_if_not_through_reference;
}
With a bit of discipline, you can easily enforce the semantics that the function should not modify that object after its creation - except for being allowed to move from it when returning.
UPDATE:
As suggested by balki in the comments, another possibility would be to bind a constant reference to a non-const temporary object (whose lifetime would be prolonged as per § 12.2/5), and perform a const_cast when returning it:
STest FuncUsingConst(int n) {
STest const& a = STest();
// Now work only with a
return const_cast<STest&&>(std::move(a));
}
A program is ill-formed if the copy/move constructor [...] for an object is implicitly odr-used and the special member function is not accessible
-- n3485 C++ draft standard [class.copy]/30
I suspect your problem is with MSVC 2012, and not with C++11.
This code, even without calling it, is not legal C++11:
struct STest {
STest(STest const&) = delete
STest(STest && test) : m_n( std::move(test.m_n) ) {}
explicit STest(int n) : m_n(n) {}
int m_n;
};
STest FuncUsingConst(int n) {
STest const a(n);
return a;
}
because there is no legal way to turn a into a return value. While the return can be elided, eliding the return value does not remove the requirement that the copy constructor exist.
If MSVC2012 is allowing FuncUsingConst to compile, it is doing so in violation of the C++11 standard.

Passing a boost::bimap between functions

I'm new to the bimap functionality of the Boost libraries, and I'm having trouble passing a bimap into another function. My bimap looks like this:
typedef boost::bimap< int, int > bimap_type;
bimap_type bm;
I have an add_values() function that adds a set of values to the bimap:
add_values(int a, int b)
{
bm.insert(bimap_type::value_type(a, b));
}
I then have a function that is meant to set the values of the bimap by getting them from a Singleton Class:
void set_values()
{
MyClass::instance()->get_values(bm);
}
And, in MyClass, get_values() looks like this:
void get_values(bimap_type myBimap)
{
myBimap.add_values(3, 5);
}
However, MyClass does not recognise 'bimap_type'. I try putting the typedef in a separate header file and including that in MyClass, but I get the error message:
'class bimap_type' has no member named 'add_values'
How can I successfully pass the bimap to this Singleton Class in order to fill it with values from the Class? Does anyone know?
Thanks a lot.
Er, boost::bimap itself doesn't have an add_values method and it's hard to tell from these code fragments why you're suddenly expecting one to appear.
Consider renaming your functions: set_values() that calls get_values() that calls add_values() is one confusing call chain...
When you need to modify an object in a function, you have to take it by reference (or a pointer). The idea is that you must work with the same object inside and outside of the function. If you pass by value, function will see a copy, so anything it does with it does not reflect on original object.
// formerly known as add_values()
void initialize(bimap_type& bm, int a, int b)
{
bm.insert(bimap_type::value_type(a, b));
}
And this is how you will call it:
initialize(myBitmap, 3, 5);
Make sure to update your whole call chain to pass by reference where appropriate, because currently your get_values() works with a copy too.

System.AccessViolationException storing a variable with reflectio.emit

I'm building a compiler with reflection.emit in my spare time, and i've come to a problem that i'm not understanding.
A little context, I've a runtime with a couple of types and one of them is Float2, a simpler vector struct with two float values (X and Y). I've made a couple of properties that allow me to swizzle the values (a la hlsl). For example if i have a new Float2(1.0f, 2.0f), if i make something like (new Float2(1.0f, 2.0f)).YX i'm going to get a Float2(2.0f, 1.0f)
I'm using this type in my language and currently testing this case (minor details of the language omitted):
float2 a = float2(1.0, 2.0).yx;
return a;
I'm transforming float2(1.0, 2.0) in a new call and accessing the property YX of my Float2 type in .yx.
The problem is I'm getting a "System.AccessViolationException : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.". I don't understand why because if I make something like this:
float2 a = float2(1.0, 2.0);
return a;
Everything goes well.
The IL code that i'm generating is the following (I think the problem occurs in "L_0014: stloc.0", I don't know why it happens though) :
.method public virtual final instance valuetype
[Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 Main() cil managed
{
.maxstack 3
.locals init (
[0] valuetype [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 num)
L_0000: ldc.r4 1
L_0005: ldc.r4 2
L_000a: newobj instance void [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2::.ctor(float32, float32)
L_000f: call instance valuetype [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2 [Bifrost.Psl]Bifrost.Psl.Compiler.Runtime.Float2::get_XY()
L_0014: stloc.0
L_0015: ldloc.0
L_0016: ret
}
Result of peverify:
[IL]: Error: [offset 0x0000000F]
[found value 'Bifrost.Psl.Compiler.Runtime.Float2'][expected address of value 'Bifrost.Psl.Compiler.Runtime.Float2'] Unexpected type on the stack.
The IL looks OK, although I don't know what your Float2 looks like.
I found the best way to debug this is to save the assembly to disk, then run peverify. Any code that generates an AccessViolationException will cause an error in peverify.
Edit: The newobj doc on MSDN talks about pushing an object reference onto the stack, which I took to be a pointer to a value type. If you're getting this error from peverify then I think you need to
newobj
stloc to a temporary variable
ldloca to get the address of the value type stored in the temporary variable
call
Now that I think about it, this is what the C# compiler does if you do a direct call on a value type like 4.ToString();.

Resources