I have code where I do a lot things like
a = 1/((1/b)+(1/c))
I can't help it, I cringe at the use of so many divisions, when I could do it like this
oneOverA = oneOverB + oneOverC
In fact i can do pretty much everything with reciprocals. For instance with comparisons
A < B iff oneOverB < oneOverA
again without need to divide. And so on.
However, this would be extremely error-prone. Imagine if I pass the reversed version to a function which expects the "straight" one, or forget to reverse the order while comparing, etc.
But, C++ exists to make magic happen, right?
And if I implenent a very simple class header-only, pretty much everything should be optimized away; leaving it just as I would write it if I was as infallible as the compiler.
So I tried a class like
template<typename T = float> //T must be a type for which 1/T is representable as another T such that 1(1/T)) = T. es. float
class ReversibleNum{
private:
const T reverse;
public:
ReversibleNum(T orig): reverse(1/orig) {}
operator T () { return 1/reverse; }
bool operator < (const ReversibleNum<T>& oth) { return oth.reverse < reverse; }
friend T operator / (const T one, const ReversibleNum<T>& two);
}
inline T operator / (const T one, const ReversibleNum<T>& two) { return one * two.reverse; }
However, when I try
ReversibleNum<float> a(5);
1.0/a
it uses "operator float" to convert and then divide, rather than "operator /" which is what I want.
I could probably make "operator T" explicit. However I like the idea of being able to use it seamlessy and have the conversion just happen; but only when there really is no alternative.
Is there something I can do to make my code work?
Or maybe some different, more advanced magic I coud use to achieve my aim?
II would like to use Eigen for linear algebra in a geometry project I am currently working on. It is a great library relatively small and easy to use and popular enough.
However, I would also like to use a custom defined "Double" class to be able to compare two floating point values in computer precision (something like the difference between the two must be smaller than a given precision). For my custom type, I have implemented most of the std::math c++11 functions and all operators (including unary -, conj, imag, abs2...). I did everything listed in these links :
http://eigen.tuxfamily.org/dox-devel/TopicCustomizingEigen.html
https://forum.kde.org/viewtopic.php?f=74&t=26631
However, I still get compilation errors in Eigen Jacobi.h file, more specifically at line 340,341 which are :
x[i] = c * xi + numext::conj(s) * yi;
y[i] = -s * xi + numext::conj(c) * yi;
I get the following error from the compiler (Vs 2012, Win32, Release and Debug Configuration)
eigen\src/Jacobi/Jacobi.h(341): error C3767: '*': candidate function(s) not accessible
operator* is define in my custom type for the following cases :
CustomType operator*(CustomType const &_other);
CustomType operator*(double const &_other);
double operator*(CustomType const &_other);
I tried to define conj in the following manners :
CustomType conj(CustomType const &_type){return _type;}
double conj(customType const &_type){return _type.get();}
I tried defining conj in Eigen::numext namespace as well as in my CustomType namespace with no success.
Anyone has a hint, link, suggestion or know something Eigen needs I might have forgotten ?
Most likely because your code isn't const correct.
Your operator overloads should be:
CustomType operator*(CustomType const &_other) **const**;
CustomType operator*(double const &_other) **const**;
double operator*(CustomType const &_other) **const**;
If eigen has a const reference to an object of type CustomType it cannot call your operators because they are not const declared.
I.e.
void foo(const CustomType& x, const CustomType& y){
x * y; // Compile error, cannot call non-const operator * on const object.
}
Not sure if this is the problem here, but you have to specialize Eigen::NumTraits<T>. See this manpage.
Also I don't understand how you can have two conj functions with the same arguments which return different types.
OK, I've been googling around for too long, I'm just not sure what to call this technique, so I figured it's better to just ask here on SO. Please point me in the right direction if this has an obvious name and/or solution I've overlooked.
For the laymen: a tensor is the logical extension of the matrix, in the same way a matrix is the logical extension of the vector. A vector is a rank-1 tensor (in programming terms, a 1D array of numbers), a matrix is a rank-2 tensor (a 2D array of numbers), and a rank-N tensor is then simply an N-D array of numbers.
Now, suppose I have something like this Tensor class:
template<typename T = double> // possibly also with size parameters
class Tensor
{
private:
T *M; // Tensor data (C-array)
// alternatively, std::vector<T> *M
// or std::array<T> *M
// etc., or possibly their constant-sized versions
// using Tensor<>'s template parameters
public:
... // insert trivial fluffy stuff here
// read elements
const T & operator() (size_t a, size_t b) const {
... // error checks etc.
return M[a + rows*b];
}
// write elements
T & operator() (size_t a, size_t b) {
... // error checks etc.
return M[a + rows*b];
}
...
};
With these definitions of operator()(...), indexing/assign individual elements then has the same call signature:
Tensor<> B(5,5);
double a = B(3,4); // operator() (size_t,size_t) used to both GET elements
B(3,4) = 5.5; // and SET elements
It is fairly trivial to extend this up to arbitrary tensor rank. But what I'd like to be able to implement is a more high-level way of indexing/assigning elements:
Tensor<> B(5,5);
Tensor<> C = B( Slice(0,4,2), 2 ); // operator() (Slice(),size_t) used to GET elements
B( Slice(0,4,2), 2 ) = C; // and SET elements
// (C is another tensor of the correct dimensions)
I am aware that std::valarray (and many others for that matter) does a very similar thing already, but it's not my objective to just accomplish the behavior; my objective here is to learn how to elegantly, efficiently and safely add the following functionality to my Tensor<> class:
// Indexing/assigning with Tensor<bool>
B( B>0 ) += 1.0;
// Indexing/assigning arbitrary amount of dimensions, each dimension indexed
// with either Tensor<bool>, size_t, Tensor<size_t>, or Slice()
B( Slice(0,2,FINAL), 3, Slice(0,3,FINAL), 4 ) = C;
// double indexing/assignment operation
B(3, Slice(0,4,FINAL))(mask) = C; // [mask] == Tensor<bool>
.. etc.
Note that it's my intention to use operator[] for non-checked versions of operator(). Alternatively, I'll stick more to the std::vector<> approach of using .at() methods for checked versions of operator[]. Anyway, this is a design choice and besides the issue right now.
I've conjured up the following incomplete "solution". This method is only really manageable for vectors/matrices (rank-1 or rank-2 tensors), and has many undesirable side-effects:
// define a simple slice class
Slice ()
{
private:
size_t
start, stride, end;
public:
Slice(size_t s, size_t e) : start(s), stride(1), end(e) {}
Slice(size_t s, size_t S, size_t e) : start(s), stride(S), end(e) {}
...
};
template<typename T = double>
class Tensor
{
... // same as before
public:
// define two operators() for use with slices:
// version for retrieving data
const Tensor<T> & operator() (Slice r, size_t c) const {
// use slicing logic to construct return tensor
...
return M;
{
// version for assigning data
Sass operator() (Slice r, size_t c) {
// returns Sass object, defined below
return Sass(*this, r,c);
}
protected:
class Sass
{
friend class Tensor<T>;
private:
Tensor<T>& M;
const Slice &R;
const size_t c;
public:
Sass(Tensor<T> &M, const Slice &R, const size_t c)
: M(M)
, R(R)
, c(c)
{}
operator Tensor<T>() const { return M; }
Tensor<T> & operator= (const Tensor<T> &M2) {
// use R/c to copy contents of M2 into M using the same
// Slice-logic as in "Tensor<T>::operator()(...) const" above
...
return M;
}
};
But this just feels wrong...
For each of the indexing/assignment methods outlined above, I'd have to define a separate Tensor<T>::Sass::Sass(...) constructor, a new Tensor<T>::Sass::operator=(...), and a new Tensor<T>::operator()(...) for each and every such operation. Moreover, the Tensor<T>::Sass::operators=(...) would need to contain much of the same stuff that's already in the corresponding Tensor<T>::operator()(...), and making everything suitable for a Tensor<> of arbitrary rank makes this approach quite ugly, way too verbose and more importantly, completely unmanageable.
So, I'm under the impression there is a much more effective approach to all this.
Any suggestions?
First of all I'd like to point out some design issues:
T & operator() (size_t a, size_t b) const;
suggests you can't alter the matrix through this method, because it's const. But you are giving back a nonconst reference to a matrix element, so in fact you can alter it. This only compiles because of the raw pointer you are using. I suggest to use std::vector instead, which does the memory management for you and will give you an error because vector's const version of operator[] gives a const reference like it should.
Regarding your actual question, I am not sure what the parameters of the Slice constructor should do, nor what a Sass object is meant to be (I am no native speaker, and "Sass" gives me only one translation in the dictionary, meaning sth. like "impudence", "impertinence").
However, I suppose with a slice you want to create an object that gives access to a subset of a matrix, defined by the slice's parameters.
I would advice against using operator() for every way to access the matrix. op() with two indices to access a given element seems natural. Using a similar operator to get a whole matrix to me seems less intuitive.
Here's an idea: make a Slice class that holds a reference to a Matrix and the necessary parameters that define which part of the Matrix is represented by the Slice. That way a Slice would be something like a proxy to the Matrix subset it defines, similar to a pair of iterators which can be seen as a proxy to a subrange of the container they are pointing to. Give your Matrix a pair of slice() methods (const and nonconst) that give back a Slice/ConstSlice, referencing the Matrix you call the method on. That way, you can even put checks into the method to see if the Slice's parameters make sense for the Matrix it refers to. If it makes sense and is necessary, you can also add a conversion operator, to convert a Slice into a Matrix of its own.
Overloading operator() again and again and using the parameters as a mask, as linear indices and other stuff is more confusing than helping imo. operator() is slick if it does something natural which everybody expects from it. It only obfuscates the code if it is used everywhere. Use named methods instead.
Not an answer, just a note to follow up my comment:
Tensor<bool> T(false);
// T (whatever its rank) contains all false
auto lazy = T(Slice(0,4,2));
// if I use lazy here, it will be all false
T = true;
// now T contains all true
// if I use lazy here, it will be all true
This may be what you want, or it might be unexpected.
In general, this can work cleanly with immutable tensors, but allowing mutation gives the same class of problem as COW strings.
If you allow for your Tensor to implicitly be a double you can return only Tensors from your operator() overload.
operator double() {
return M.size() == 1 ? M[0] : std::numeric_limits<double>::quiet_NaN();
};
That should allow for
double a = B(3,4);
Tensor<> a = B(Slice(1,2,3),4);
To get the operator() to work with multiple overloads with Slice and integer is another issue. I'd probably just use Slice and create another implicit conversion so integers can be Slice's, then maybe using the variable argument elipses.
const Tensor<T> & operator() (int numOfDimensions, ...)
Although the variable argument route is kind of a kludge best to just have 8 specializations for 1-8 parameters of Slice.
I was implementing a small dense matrix class and instead of plan get/set operators I wanted to use operator overloading to make the API more usable and coherent.
What I want to achieve is pretty simple:
template<typename T>
class Matrix
{
public:
/* ... Leaving out CTOR and Memory Management for Simplicity */
T operator() (unsigned x, unsigned y){/* ... */ }
};
Matrix<int> m(10,10);
int value = m(5,3); // get the value at index 5,3
m(5,3) = 99; // set the value at index 5,3
While getting the value is straight forward by overloading operator(), I can't get my head around defining the setter. From what I understood the operator precedence would call operator() before the assignment, however it is not possible to overload operator() to return a correct lvalue.
What is the best approach to solve this problem?
I dispute that "it's not possible" to do the correct thing:
struct Matrix
{
int & operator()(size_t i, size_t j) { return data[i * Cols + j]; }
const int & operator()(size_t i, size_t j) const { return data[i * Cols + j]; }
/* ... */
private:
const size_t Rows, Cols;
int data[Rows * Cols]; // not real code!
};
Now you can say, m(2,3) = m(3,2) = -1; etc.
The answer to your question is what Kerrek already stated: you can provide an overload by changing the signature of the operator, which in this case can be achieved by modifying the const-ness of the function.
But I would recommend that you at least consider providing a separate setter for the values. The reason is that once you return references to your internal data structures you loose control of what external code does with your data. It might be ok in this case, but consider that if you decided to add range validation to the implementation (i.e. verify that no value in the matrix is above X or below Y), or wished to optimize some calculation on the matrix (say the sum of all of the elements in the matrix is an often checked value, and you want to optimize away the calculation by pre-caching the value and updating it on each field change) it is much easier to control with a method that receives the value to set.
I am trying to make a dimensioned vector class with boost-units like so,
//vector will be constructed vec<si::length> v(10, 1.0*si::metre);
template<typename dimension>
class vec
{
public:
//constructor setting all values to q.
vec(const size_t, const boost::units::quantity<dimension> q)
//etc
}
It all works fine except for the operator*= and operator/= that do element wise multiplication and division. Since these do not change the dimension, they only make sense when multiplying/dividing by a dimensionless quantity: I am struggling to find an arbitrary dimensionless quantity that is not locked into a specific system (e.g. si or cgs units).
I want something like,
/** Multiply a dimensionless vector. */
vec<dimension>&
operator*=(const vec<boost::units::dimensionless_type>& b);
or perhaps some metaprogramming magic (I notice boost::units::is_dimensionless exists, but I have no idea how to use it as I am not versed in general metaprogramming techniques)
template<typename dimension>
template<typename a_dimensionless_type>
vec<dimension>&
vec<dimension>::operator*=(const vec<a_dimensionless_type>& b){
//some compile time check to make sure that a_dimensionless_type is actually dimensionless?
//the rest of the function
}
I want following examples to compile
vec<si::dimensionless> d(10, 2.0);
vec<si::length> l(10, 2.0*si::metre);
l*=d;
vec<cgs::dimensionless> d2(10, 2.0);
vec<cgs::length> l2(10, 2.0*cgs::centimetre);
l2*=d2;
Okay, after examining the library details (and learning about BOOST_MPL_ASSERT) it turned out to be very easy. My compliments to the library designer.
template<typename a_dimensionless_type>
vec<dimension>&
operator*=(const vec< a_dimensionless_type >& b)
{
BOOST_MPL_ASSERT(( boost::units::is_dimensionless<boost::units::quantity<a_dimensionless_type> > ));
//the rest of the function
};
I might be mistaken about Boost details, but conventionally double is the dimensionless type.