Rationale for Eigen API for Matrix with Scalar operations - c++

Consider the following code:
#include <Eigen/Core>
using Matrix = Eigen::Matrix<float, 2, 2>;
Matrix func1(const Matrix& mat) { return mat + 0.5; }
Matrix func2(const Matrix& mat) { return mat / 0.5; }
func1() does not compile; you need to replace mat with mat.array() in the function body to fix it ([1]). However, func2() does compile as-is.
My question has to do with why the API is designed this way. Why is addition-with-scalar and division-by-scalar treated differently? What problems would arise if the following method is added to the Matrix class, and why haven't those problems arisen already for the operator/ method?:
auto operator+(Scalar s) const { return this->array() + s; }

From a mathematics perspective, a scalar added to a matrix "should" be the same as adding the scalar only to the diagonal. That is, a math text would usually use M + 0.5 to mean M + 0.5I, for I the identity matrix. There are many ways to justify this. For example, you can appeal to the analogy I = 1, or you can appeal to the desire to say Mx + 0.5x = (M + 0.5)x whenever x is a vector, etc.
Alternatively, you could take M + 0.5 to add 0.5 to every element. This is what you think is right if you don't think of matrices from a "linear algebra mindset" and treat them as just collections (arrays) of numbers, where it is natural to just "broadcast" scalar operations.
Since there are multiple "obvious" ways to handle + between a scalar and a matrix, where someone expecting one may be blindsided by the other, it is a good idea to do as Eigen does and ban such expressions. You are then forced to signify what you want in a less ambiguous way.
The natural definition of / from an algebra perspective coincides with the array perspective, so no reason to ban it.

Related

How can I divide the Eigen::matrix by Eigen::vector?

following is my code.
Eigen::Matrix3d first_rotation = firstPoint.q.matrix();
Eigen::Vector3d first_trans= firstPoint.t;
for(auto &iter:in_points )
{
iter.second.t= first_rotation / (iter.second.t-first_trans).array();
}
However,the vscode says"no operator / matches the operands" for division."
How can I division a matrix by a vector?
In Matlab, the line was t2 = R1 \ (R2 - t1);
Matlab defined the / and \ operators, when applied to matrices, as solving linear equation systems, as you can read up on in their operator documentation. In particular
x = A\B solves the system of linear equations A*x = B
Eigen doesn't do this. And I don't think most other languages or libraries do it either. The main point is that there are multiple ways to decompose a matrix for solving. Each with their own pros and cons. You can read up on it in their documentation.
In your case, you can save time by reusing the decomposition multiple times. Something like this:
Eigen::PartialPivLU<Eigen::Matrix3d> first_rotation =
firstPoint.q.matrix().partialPivLu();
for(auto &iter: in_points)
iter.second.t = first_rotation.solve(
(iter.second.t-first_trans).eval());
Note: I picked LU over e.g. householderQr because that is what Matlab does for general square matrices. If you know more about your input matrix, e.g. that it is symmetrical, or not invertible, try something else.
Note 2: I'm not sure it is necessary in this case but I added a call to eval so that the left side of the assignment is not an alias of anything on the right side. With dynamically sized vectors, this would introduce extra memory allocations but here it is fine.

Function to invert Eigen matrix without branching statements for auto differentiation

I need to invert an Eigen matrix (9x9 in my particular case) as a part of code that I want to automatically differentiate using CppAD. For this to succeed the code executing the inversion can not contain any branching like for example if or switch statements. Unfortunately, the inverse function of Eigen contains branching with makes the algorithmic differentiation of CppAD fail.
Mathematically it should be possible to come up with a formulation that does not need branching for a fixed matrix size that is guaranteed to be invertible. Is that correct?
Do you know of any library that implements such an inverse without branching?
There is a mechanical conversion from branch to no-branch for arithmetic functions.
Duplicate all the variables you use in each branch, and calculate both halves. At the end of the block, multiply the if branch by condition, and the else branch by !condition, then sum them.
Similarly for a switch, calculate all the cases, and multiply by value == case.
E.g.
Mat frob_branch(Mat a, Mat b) {
if (a.baz()) {
return a * b;
} else {
return b * a;
}
}
becomes
Mat frob_no_branch(Mat a, Mat b) {
auto if_true = a * b;
auto if_false = b * a;
bool condition = a.baz();
return (if_true * condition) + (if_false * !condition);
}
In general, it is possible to invert arbitrary large (invertible) matrices without branching, but this gets inefficient for bigger matrices. Eigen only does this for matrices up to size 4x4.
If you want the derivation of the inverse, just use the identity
deriv (inv(A)) = - inv(A) * deriv(A) * inv(A)
i.e., compute the inverse of the plain matrix, then compute the expression above.

C++: How to compute an integral with interval bounds?

I am both tired, new to C++ and real bad at dealing with polynomials. That's a bad combo for my assignment. Nevertheless I am trying to solve it. Please note that I might have misunderstood certain parts both mathematically and language-wise. Maybe even terminology.
The first task of my assignment was to create a class for storing polynomials. I figured the important parts were coefficiants and the degree of the polynomial. As such I have a polynomial class that (partly) looks like this:
class Polynomial {
private:
double* Coefficients; //Array of coefficients in order of ascending power
int Degree; //The degree of the polynomial
...
The class should have a method for finding the integral of the polynomial within a lower and upper bound. But I really do not know how to work with it.
Since it's bad practise not to show what I've done, this is what I currently have, and it probably does not make a lot of sense, but please, if you can, point me in the right direction?
Polynomial Polynomial::ComputeIntegral(double lower, double upper) {
//Values needed to create new polynomial
//degree will be one more than the original polynomial
int degree = Degree + 1;
double* coefficients = new double[degree + 1];
coefficients[0] = 0;
for (int i = 0; i < degree +1; i++) {
coefficients[i + 1] = Coefficients[i] / (double)(i + 1);
}
Polynomial integral(degree, coefficients);
return integral;
}
That I can see myself, it is messed up because a) I do not use the bounds, and b) I am pretty sure per the assignment description I should end up with a value rather than a new polynomial.
Google tells me there are algorithms to deal with finding integrals (Trapezoid for example), but I can not wrap my head around matching that with my representation of a polynomial.
A few pointers:
Use std::vectors instead of pointers and new. (If you are new to C++, there are very few circumstances when you actually need to use new.)
ComputeIntegral(double, double) will need to return a double, since it is obviously computing a definite integral. (The function you have at the moment would be something like GetPrimitive(), as it returns the primitive of the polynomial, which is another poly.
The definite integral is the difference of the primitive evaluated at the bounds (First Fundamental theorem of calculus).
There are a number of ways you could represent the polynomial as a data structure, but I would suggest a single std::vector<double> coeffs that represents all of the coefficients up to the degree of the poly, then the degree can be calculated at coeffs.size(). In some cases there may be zeroes in that coeffs though.
In the general case, it is possible to use the boost library to compute integrals: https://www.boost.org/doc/libs/1_77_0/libs/math/doc/html/quadrature.html
There is also the library ALGLIB that I have used to compute integrals. Here is an example to compute integrals with ALGLIB: Integrate a public but non static member function with ALGLIB

Implementing complex-valued matrix equation in OpenCV

I am attempting to implement a complex-valued matrix equation in OpenCV. I've prototyped in MATLAB which works fine. Starting off with the equation (exact MATLAB implementation):
kernel = exp(1i .* k .* Circ3D) .* z ./ (1i .* lambda .* Circ3D .* Circ3D)
In which
1i = complex number
k = constant (float)
Circ3D = real-valued matrix of known size
lambda = constant (float)
.* = element-wise multiplication
./ = element-wise division
The result is a complex-valued matrix. I succeeded in generating the necessary Circ3D matrix as a CV_32F, however the multiplication by the complex number i is giving me trouble. From the OpenCV documentation I understand that a complex matrix is simply a two-channel matrix (CV_32FC2).
The real trouble comes from how to define i. I've tried several options, among which defining i as
cv::Vec2d complex = cv::Vec2d(0,1);
and then multiplying by the matrix
kernel = complex * Circ3D
But this doesn't work (although I didn't expect it to). I suspect I need to do something with std::complex but I have no idea what (http://docs.opencv.org/modules/core/doc/basic_structures.html).
Thanks in advance for any help.
Edit: Just after writing this post I did make some progress, by defining i as follows:
std::complex<float> complex(0,1)
I am then able to assign complex values as follows:
kernel.at<std::complex<float>>(i,j) = cv::exp(complex * k * Circ3D.at<float>(i,j)) * ...
z / (complex * lambda * pow(Circ3D.at<float>(i,j),2));
However, this works in a loop, which makes the procedure incredibly slow. Any way to do it in one go?
OpenCV treats std::complex just like the simple pair of numbers (see example in the documentation). No special rules on arithmetic operations are applied. You overcome this by multiplying std::complex directly. So basically, this is simple: you either chose automatic complex arithmetic (as you are doing now), or automatic vectorization (when using OpenCV functions on matrices).
I think, in your case you should carry all the complex arithmetic by yourself. Store matrix of complex values C{ai + b} as two matrices A{a} and B{b}. Implement exponentiation by yourself. Multiplication on scalars and addition shouldn't be a problem.
There is also the function mulSpectrums, which lets you do element wise multiplication of complex matrices. So if K is your kernel matrix and I is some complex matrix, that is, CV_32FC2 (float two channel) you can do the following to compute the element wise multiplication,
// Make K a complex matrix
cv::Mat Ktmp[] = {cv::Mat_<float>(K), cv::Mat::zeros(K.size(), CV_32FC1)};
cv::Mat Kc;
cv::merge(Ktmp,2,Kc);
// Do matrix multiplication
cv::mulSpectrums(Kc,I,I,0);

Maths in Programing Video Games

I've just finished second year at Uni doing a games course, this is always been bugging me how math and game programming are related. Up until now I've been using Vectors, Matrices, and Quaternions in games, I can under stand how these fit into games.
This is a General Question about the relationship between Maths and Programming for Real Time Graphics, I'm curious on how dynamic the maths is. Is it a case where all the formulas and derivatives are predefined(semi defined)?
Is it even feasible to calculate derivatives/integrals in realtime?
These are some of things I don't see how they fit inside programming/maths As an example.
MacLaurin/Talor Series I can see this is useful, but is it the case that you must pass your function and its derivatives, or can you pass it a single function and have it work out the derivatives for you?
MacLaurin(sin(X)); or MacLaurin(sin(x), cos(x), -sin(x));
Derivatives /Integrals This is related to the first point. Calculating the y' of a function done dynamically at run time or is this something that is statically done perhaps with variables inside a set function.
f = derive(x); or f = derivedX;
Bilnear Patches We learned this as a way to possible generate landscapes in small chunks that could be 'sewen' together, is this something that happens in games? I've never heard of this (granted my knowlages is very limited) being used with procedural methods or otherwise. What I've done so far involves arrays for vertex information being processesed.
Sorry if this is off topic, but the community here seems spot on, on this kinda thing.
Thanks.
Skizz's answer is true when taken literally, but only a small change is required to make it possible to compute the derivative of a C++ function. We modify skizz's function f to
template<class Float> f (Float x)
{
return x * x + Float(4.0f) * x + Float(6.0f); // f(x) = x^2 + 4x + 6
}
It is now possible to write a C++ function to compute the derivative of f with respect to x. Here is a complete self-contained program to compute the derivative of f. It is exact (to machine precision) as it's not using an inaccurate method like finite differences. I explain how it works in a paper I wrote. It generalises to higher derivatives. Note that much of the work is done statically by the compiler. If you turn up optimization, and your compiler inlines decently, it should be as fast as anything you could write by hand for simple functions. (Sometimes faster! In particular, it's quite good at amortising the cost of computing f and f' simultaneously because it makes common subexpression elimination easier for the compiler to spot than if you write separate functions for f and f'.)
using namespace std;
template<class Float>
Float f(Float x)
{
return x * x + Float(4.0f) * x + Float(6.0f);
}
struct D
{
D(float x0, float dx0 = 0) : x(x0), dx(dx0) { }
float x, dx;
};
D operator+(const D &a, const D &b)
{
// The rule for the sum of two functions.
return D(a.x+b.x, a.dx+b.dx);
}
D operator*(const D &a, const D &b)
{
// The usual Leibniz product rule.
return D(a.x*b.x, a.x*b.dx+a.dx*b.x);
}
// Here's the function skizz said you couldn't write.
float d(D (*f)(D), float x) {
return f(D(x, 1.0f)).dx;
}
int main()
{
cout << f(0) << endl;
// We can't just take the address of f. We need to say which instance of the
// template we need. In this case, f<D>.
cout << d(&f<D>, 0.0f) << endl;
}
It prints the results 6 and 4 as you should expect. Try other functions f. A nice exercise is to try working out the rules to allow subtraction, division, trig functions etc.
2) Derivatives and integrals are usually not computed on large data sets in real time, its too expensive. Instead they are precomputed. For example (at the top of my head) to render a single scatter media Bo Sun et al. use their "airlight model" which consists of a lot of algebraic shortcuts to get a precomputed lookup table.
3) Streaming large data sets is a big topic, especially in terrain.
A lot of the maths you will encounter in games is to solve very specific problems, and is usually kept simple. Linear algebra is used far more than any calculus. In Graphics (I like this the most) a lot of the algorithms come from research done in academia, and then they are modified for speed by game programmers: although even academic research makes speed their goal these days.
I recommend the two books Real time collision detection and Real time rendering, which contain the guts of most of the maths and concepts used in game engine programming.
I think there's a fundamental problem with your understanding of the C++ language itself. Functions in C++ are not the same as mathmatical functions. So, in C++, you could define a function (which I will now call methods to avoid confusion) to implement a mathmatical function:
float f (float x)
{
return x * x + 4.0f * x + 6.0f; // f(x) = x^2 + 4x + 6
}
In C++, there is no way to do anything with the method f other than to get the value of f(x) for a given x. The mathmatical function f(x) can be transformed quite easily, f'(x) for example, which in the example above is f'(x) = 2x + 4. To do this in C++ you'd need to define a method df (x):
float df (float x)
{
return 2.0f * x + 4.0f; // f'(x) = 2x + 4
}
you can't do this:
get_derivative (f(x));
and have the method get_derivative transform the method f(x) for you.
Also, you would have to ensure that when you wanted the derivative of f that you call the method df. If you called the method for the derivative of g by accident, your results would be wrong.
We can, however, approximate the derivative of f(x) for a given x:
float d (float (*f) (float x), x) // pass a pointer to the method f and the value x
{
const float epsilon = a small value;
float dy = f(x+epsilon/2.0f) - f(x-epsilon/2.0f);
return epsilon / dy;
}
but this is very unstable and quite inaccurate.
Now, in C++ you can create a class to help here:
class Function
{
public:
virtual float f (float x) = 0; // f(x)
virtual float df (float x) = 0; // f'(x)
virtual float ddf (float x) = 0; // f''(x)
// if you wanted further transformations you'd need to add methods for them
};
and create our specific mathmatical function:
class ExampleFunction : Function
{
float f (float x) { return x * x + 4.0f * x + 6.0f; } // f(x) = x^2 + 4x + 6
float df (float x) { return 2.0f * x + 4.0f; } // f'(x) = 2x + 4
float ddf (float x) { return 2.0f; } // f''(x) = 2
};
and pass an instance of this class to a series expansion routine:
float Series (Function &f, float x)
{
return f.f (x) + f.df (x) + f.ddf (x); // series = f(x) + f'(x) + f''(x)
}
but, we're still having to create a method for the function's derivative ourselves, but at least we're not going to accidentally call the wrong one.
Now, as others have stated, games tend to favour speed, so a lot of the maths is simplified: interpolation, pre-computed tables, etc.
Most of the maths in games is designed to to as cheap to calculate as possible, trading speed over accuracy. For example, much of the number crunching uses integers or single-precision floats rather than doubles.
Not sure about your specific examples, but if you can define a cheap (to calculate) formula for a derivative beforehand, then that is preferable to calculating things on the fly.
In games, performance is paramount. You won't find anything that's done dynamically when it could be done statically, unless it leads to a notable increase in visual fidelity.
You might be interested in compile time symbolic differentiation. This can (in principle) be done with c++ templates. No idea as to whether games do this in practice (symbolic differentiation might be too expensive to program right and such extensive template use might be too expensive in compile time, I have no idea).
However, I thought that you might find the discussion of this topic interesting. Googling "c++ template symbolic derivative" gives a few articles.
There's many great answers if you are interested in symbolic calculation and computation of derivatives.
However, just as a sanity check, this kind of symbolic (analytical) calculus isn't practical to do at real time in the context of games.
In my experience (which is more 3D geometry in computer vision than games), most of the calculus and math in 3D geometry comes in by way of computing things offline ahead of time and then coding to implement this math. It's very seldom that you'll need to symbolically compute things on the fly and then get on-the-fly analytical formulae this way.
Can any game programmers verify?
1), 2)
MacLaurin/Taylor series (1) are constructed from derivatives (2) in any case.
Yes, you are unlikely to need to symbolically compute any of these at run-time - but for sure user207442's answer is great if you need it.
What you do find is that you need to perform a mathematical calculation and that you need to do it in reasonable time, or sometimes very fast. To do this, even if you re-use other's solutions, you will need to understand basic analysis.
If you do have to solve the problem yourself, the upside is that you often only need an approximate answer. This means that, for example, a series type expansion may well allow you to reduce a complex function to a simple linear or quadratic, which will be very fast.
For integrals, the you can often compute the result numerically, but it will always be much slower than an analytic solution. The difference may well be the difference between being practical or not.
In short: Yes, you need to learn the maths, but in order to write the program rather than have the program do it for you.