Language D ; structs, immutable data and weird error - immutability

I'm learning language D. My first try is a simple 2d Vector that I can add, substract, dot product, etc...
I have this error when I try to compile:
Error :
Error: (Vector2d __ctmp1245 = D4math2v28Vector2d6_initZ;
, __ctmp1245).this(this._x / l,this._y / l) is not mutable
Note : The error is related to Vector2d.dir()
The code is :
import std.math;
public struct Vector2d {
private const real _x;
private const real _y;
this(in real x, in real y) {
_x = x; _y = y;
}
// Basic Properties ***************************************
#property const real X () { return _x; }
#property const real Y () { return _y; }
#property const real length () { return sqrt(_x*_x + _y*_y); }
// Operations ***************************************
/**
* Define Equality
*/
const bool opEquals(ref const Vector2d rhs) {
return approxEqual(_x, rhs._x) && approxEqual(_y, rhs._y);
}
/**
* Define unary operators + and - (+v)
*/
ref Vector2d opUnary(string op)() const
if (op == "+" || op == "-")
{
return Vector2d(mixin(op~"_x"), mixin(op~"_y"));
}
/**
* Define binary operator + and - (v1 + v2)
*/
ref Vector2d opBinary(string op) (ref const Vector2d rhs)
if (op == "+" || op == "-")
{
return Vector2d(mixin("_x" ~ op ~ "rhs._x"),mixin("_y" ~ op ~ "rhs._y"));
}
/**
* Scalar multiplication & division (v * 7)
*/
ref Vector2d opBinary(string op) (ref const real rhs) const
if (op == "*" || op == "/")
{
return Vector2d(mixin("_x" ~ op ~ "rhs"),mixin("_y" ~ op ~ "rhs"));
}
/**
* Dot Product (v1 * v2)
*/
ref real opBinary(string op) (ref const Vector2d rhs) const
if (op == "*") {
return _x*rhs._x + _y*rhs._y;
}
/**
* Obtain the director vector of this vector.
*/
ref Vector2d dir() const {
auto l = this.length();
return Vector2d(_x / l, _y /l);
}
/**
* Obtains the projection of this vector over other vector
* Params:
* b = Vector over project this vector
*/
ref Vector2d projectOnTo(in Vector2d b) const {
return b.dir() * (this * b.dir());
}
}
I don't understand why I have this error. Plus I try to change Type Qualifiers unsuccessful.
Even I get the same error if i try this :
ref Vector2d dir() const {
auto l = this.length();
return Vector2d(2,3);
}
EDIT :
I tried removing "const" from attributes and removing "ref" from Dot product (I get a advice that not was lvalue) . The error is now this :
src/math/v2.d(82): Error: this.opBinary(b.dir()) is not an lvalue
The line 82 is :
return b.dir() * (this * b.dir());
AutoANSWER:
I fixed the last error, I changed ProjectOnTo
to this :
ref Vector2d projectOnTo(in Vector2d b) const {
auto a = this * b.dir();
return b.dir() * a;
}
Plus I run a unit test and looks that Vector2d It's doing ok.
So, finally I know now that I can't use immutable variables for a struct attributes, but I dont understand why.

drop off the const qualifiers of the fields
public struct Vector2d {
private real _x;
private real _y;
this(in real x, in real y) {
_x = x; _y = y;
}
//...
the const is unnecessary and it will block you from simple assignment:
Vector2d v;
v = Vector2d(0,0);
this wont wont compile
and do remember that generic functions (the opBinary and opUnary) are only tested on syntax when they are parsed not on correctness of the code (your opUnary returns a Vector!T but the T generic type is never declared (and thus undefined) yet this passes compilation...)
edit I've made my own struct with operator overloads and except for opCmp and opEquals I don't use ref const for parameters just const (in works just as well for this)
edit2 I've found it easiest to understand structs as groups of variables that can be declared, assigned and used at the same time with a few extra functions defined around the group of vars
so Vector2D v; in your original code would then be translated as const real v__x; const real v__y; the assignment v = Vector(0,0); would then be (after inlining the constructor) translated as v__x = 0;v__y = 0;
but as v__x is declared as const this wont be allowed

I've tried to rewrite the body of dir() as
Vector2d v = Vector2d(0, 0);
return v;
and saw a nice error message then:
vector2D.d(67): Error: variable vector2D.Vector2d.dir.v cannot modify struct with immutable members
vector2D.d(67): Error: escaping reference to local variable v
I don't understand how a variable could modify a struct, but this gave me the hint: why did you define _x and _y as const? I've removed the const from their declarations, and it has compiled :)

Related

How to return multiple values (vector and one int value) through function

I am finding connected components of a graph.
Condition : Those components should not be printed in same function, but they should be printed in calling function ( i.e. int main() )
I have gone through the link but got some error.
Returning multiple values from a C++ function
tuple <vector<int>&, int > connected( vector<int>& store, ...)
{
int component_size = 0;
// code
return make_tuple ( store, component_size);
}
int main()
{
// code
for( int i = 0 ; i < V; i++ )
{
if( !visited[i])
{
tie( ans, compo_size ) = connected(edges,
visited, myQ, store, V, i);
for(int i = 0 ; i < compo_size; i++ )
{
cout<< ans[i] <<" ";
}
}
}
}
There are few errors :
error: could not convert 'std::make_tuple(_Elements&& ...) [with _Elements = {std::vector >&, int&}](component_size)' from 'std::tuple >, int>' to 'std::tuple >&, int>'
return make_tuple ( store, component_size);
^
error: invalid initialization of reference of type 'std::vector&' from expression of type 'std::vector'
tie( ans, compo_size ) = connected(edges, visited, myQ, store, V, i);
How to return multiple values (vector and one int value) through function
A function can have at most one return value.
Returning more objects can be emulated by either
modifying one or more objects that are global or are referenced by arguments through indirection or by
returning an object of class type that has multiple sub objects.
You've attempted the latter approach through the use of tuple class template. The reason it doesn't work is explained in the documentation:
template< class... Types >
tuple<VTypes...> make_tuple( Types&&... args );
For each Ti in Types..., the corresponding type Vi in VTypes... is std::decay<Ti>::type unless application of std::decay results in std::reference_wrapper<X> for some type X, in which case the deduced type is X&.
As such, your invocation of make_tuple is deduced to return tuple <vector<int>, int > which is wrong because the function is supposed to return tuple <vector<int>&, int > instead. This can be fixed using std::ref so that the correct type is deduced:
std::make_tuple(std::ref(store), component_size);
As eerorika mentioned, you could use std::ref() as follow:
std::tuple <std::vector<int>&, int > connected( std::vector<int>& store, ...)
{
int component_size = 0;
// code
return std::make_tuple ( std::ref(store), component_size);
}
However, there is really no point in returning a reference to the input vector since it is already a non-const reference on input. So changing the vector in place is going to be enough. On return you get a modified version. However, that's probably not what you are looking to do (i.e. you probably wanted to make a copy of store and return the copy with the other arrays appended...)
That also means you're going to have yet another copy when you create the tuple:
std::tuple <std::vector<int>, int > connected( std::vector<int>& store, ...)
{
int component_size = 0;
std::vector<int> result;
// or maybe a straight copy, depends on your needs in "code"
//std::vector<int> result(store);
// code
return std::make_tuple ( result, component_size);
}
As mentioned by others, having a result in the list of arguments is probably your best bet:
int connected( std::vector<int> & result, std::vector<int> const & store, ...)
{
int component_size = 0;
// code
return component_size;
}
Also, wouldn't component_size == result.size() be true? If so, you should not return anything because it's going to be more confusing.
That simplifies the function to this point:
void connected( std::vector<int> & result, std::vector<int> const & store, ...)
{
// code
}

Eigen: understand preconditioner concept

I try to write a custom preconditioner, but do not understand the concept of Eigen's preconditioner so far. My current state looks like this, but there is something obvious wrong...
class NullSpaceProjector: public Eigen::IdentityPreconditioner
{
public:
Eigen::MatrixXd null_space_1;
Eigen::MatrixXd null_space_2;
template<typename Rhs>
inline Rhs solve(Rhs& b) const {
return b - this->null_space_1 * (this->null_space_2 * b);
}
void setNullSpace(Eigen::MatrixXd null_space) {
// normalize + orthogonalize the nullspace
this->null_space_1 = null_space * ((null_space.transpose() * null_space).inverse());
this->null_space_2 = null_space.transpose();
}
};
I want to set some null-space information and remove it from the rhs in every cg-step. Somehow I have the feeling this is somehow not possible with the preconditioner concept. At least I can't find the right way to get it implmented.
ref.:
- solving a singular matrix
- https://bitbucket.org/eigen/eigen/src/1a24287c6c133b46f8929cf5a4550e270ab66025/Eigen/src/IterativeLinearSolvers/BasicPreconditioners.h?at=default&fileviewer=file-view-default#BasicPreconditioners.h-185
further information:
the nullspace is constructed this way:
Eigen::MatrixXd LscmRelax::get_nullspace()
{
Eigen::MatrixXd null_space;
null_space.setZero(this->flat_vertices.size() * 2, 3);
for (int i=0; i<this->flat_vertices.cols(); i++)
{
null_space(i * 2, 0) = 1; // x-translation
null_space(i * 2 + 1, 1) = 1; // y-translation
null_space(i * 2, 2) = - this->flat_vertices(1, i); // z-rotation
null_space(i * 2 + 1, 2) = this->flat_vertices(0, i); // z-rotation
}
return null_space;
}
So the question is maybe not so much related to eigen but more a basic c++ question:
How can I manipulate the rhs in a const function by a projection which depends on the rhs. So I guess the const concept doesn't fit my needs.
But removing the 'const' from the function results in errors like this:
.../include/eigen3/Eigen/src/IterativeLinearSolvers/ConjugateGradient.h:63:5: error: passing ‘const lscmrelax::NullSpaceProjector’ as ‘this’ argument of ‘Eigen::VectorXd lscmrelax::NullSpaceProjector::solve(const VectorXd&)’ discards qualifiers [-fpermissive]

Create a copy of a column for a matrix template C++

I am learning C++11 and I would like to create copies of columns for a simple matrix template I created. I don't want to use full-fledged matrix templates like armadillo and others because I don't need sofisticated matrix algebra. The operations I would like to do are:
matrix<int> A(3,3,{1,0,1,2,2,2,1,0,1});
matrix<int> A1(3,1));
A1 = A.col_cpy(1);
// do something with the column vector
A1[2] += 5;
// and then assign back
A.col(1) = A1;
my naive first attempt with col_cpy was to return a column matrix which is wrong because the local variable is destroyed.
template<typename T >
class matrix {
T* m_elems;
size_t m_rows;
size_t m_cols;
public:
matrix(size_t rows, size_t cols)
: m_elems((T*)std::malloc(rows * cols * sizeof(T))), m_rows(rows), m_cols(cols) {}
matrix(size_t rows, size_t cols, std::initializer_list<T> const& xs)
: m_elems((T*)std::malloc(rows * cols * sizeof(T))), m_rows(rows), m_cols(cols) {
T* es = m_elems;
for (auto x : xs) {
*es = x;
++es;
}
}
auto col_cpy(size_t col) const -> T* {
auto c = (T*)std::malloc(m_rows * sizeof(T));
col_cpy(col, c);
return c;
}
auto col_cpy(size_t col) const -> matrix& {
matrix <T> c(m_rows,1);
for(auto i=0u; i<m_rows; i++)
c(i) = m_elems[col * m_rows + i];
return c;
}
Another way was to create a friend function and pass matrix by reference
template<typename T>
void col_cpy( size_t col, matrix<T> const& D, matrix<T> & A ) {
A(D.m_rows,1);
D.col_cpy(col,A.m_elems);
}
So I could do
col_cpy(1,A,A1);
It works but I think is not the safest neither elegant way to do it.
The full example is here http://coliru.stacked-crooked.com/a/546db2c1b520bdc7

Is it possible to implement derived units of SI system using user-defined literals?

I would like to overload user defined literals so that it will allow to perform some physical calculations, e.g
auto force = 5_N; // force in newton
auto distance = 6.8_m; // distance in meters
auto resultingEnergy = force * distance; // expected result in joules
How can it be achieved ?
You can define some new types (or use boost units as mentioned above),
A user defined solution could be similar to:
#define DECLARE_UNIT(UnitName) \
struct UnitName { \
UnitName(const long double val) noexcept : val_(val) {};\
long double val_ = 0.0; \
};
DECLARE_UNIT(Joule);
DECLARE_UNIT(Newton);
DECLARE_UNIT(Meters);
const Newton operator""_N(const long double n) noexcept {
return Newton(n);
}
const Meters operator""_m(const long double m) noexcept {
return Meters(m);
}
const Joule operator*(const Newton& newtons, const Meters& meters) noexcept {
return newtons.val_ * meters.val_;
}
int main() {
auto force = 5.0_N;
auto distance = 6.8_m;
auto energy = force * distance; // of Joule type
}

What does `auto &&i = foo();` mean

Please explain how auto type deduction works when used with move semantic:
#include <iostream>
template <typename T>
struct A {
static void type() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
float& bar() {
static float t = 5.5;
return t;
}
int foo() {
return 5;
}
int main() {
auto &&a1 = foo(); // I expected auto -> int (wrong)
auto &&a2 = bar(); // I expected auto -> float& (correct)
A<decltype(a1)>::type();
A<decltype(a2)>::type();
}
The output is:
static void A<T>::type() [with T = int&&]
static void A<T>::type() [with T = float&]
auto&& (just like T&& in parameter of a function template where T is a template parameter of that function template) follows slightly different rules than other deductions - it's unofficially called a "universal reference."
The idea is that if the initialiser is an lvalue of type X, the auto is deduced to X&. If it's an rvalue of type X, the auto is deduced to X. In both cases, && is then applied normally. From reference collapsing rules, X& && becomes X&, while X && remains X&&.
This means that in your a1 case, auto is indeed deduced to int, but a1 is then naturally declared with type int&&, and that's what decltype(a1) gives you.
At the same time, the auto in a2 is float&, and so is the type of a2, which the decltype(a2) again confirms.
In other words, your expectation that auto -> int in the first case is correct, but the type of a1 is auto &&a1, not just auto a1.
auto &&a1 = foo();
Return type of foo() is int. Since you declared a1 as auto&&, it expands to int&&, and that is what you get for type of a1.
auto &&a2 = bar();
Return type of bar() is float&. Since you declared a2 as auto&&, it expands to float& && and that converts to float& following the rules.
This answer explains the rules how the universal reference expands :
&& -> &&
&& & -> &
& && -> &
&& && -> &&

Resources