C/C++ code 2nd = sign in operation - c++

I'm not sure if this is C or C++ code, but I don't think it matters.
in this code:
x -= (t = u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x)))));
what does the t = u mean? It's not assigning t to u is it? Because it wouldn't make sense then since it's actually getting set to something else in the previous line:
t = exp(a1*log(x)+b1*log(1.-x) + afac);
u = err/t;
x -= (t = u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x)))));
if (x <= 0.) x = 0.5*(x + t);
if (x >= 1.) x = 0.5*(x + t + 1.);

what does the t = u mean?
It is part of a larger sub-expression,
t = u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x))))
It's not assigning t to u is it?
No, it is assigning the value of that complicated expression to t. The result of that assignment is then used in the complete expression:
x -= (t = <stuff> );
Conceptually, this is the same as:
t = <stuff>
x = x - t
Because it wouldn't make sense then since it's actually getting set to something else in the previous line
Frankly, the whole set of statements doesn't make sense to me. Regardless, t is set in line one, used in line 2, and set again in line 3.

Quite simply:
x -= (t = u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x)))));
| | \_____________________________________/|
| | Calculate this monstrosity |
| \_________________________________________/|
| Assign it to t |
\________________________________________________/
Subtract that from x
In C (and C-like languages) the "result" of an assignment can be used for other things. So, for example:
x = (a = a - 1); // decrements a and assigns that to x as well
x += (a = 1 - a); // toggles a between 1 and 0 and adds to x (x increases
// every second time).
The relevant bit of the C standard is C11, 6.5.16 Assignment operators, paras 2 and 3:
2/ An assignment operator shall have a modifiable lvalue as its left operand.
3/ An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type of the left operand unless the left operand has qualified type, in which case it is the unqualified version of the type of the left operand. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.

In both C and C++ an assignment returns a value, the value of the left hand side.
a = 1 + (b = 4);
is equivalent to:
b = 4;
a = 1 + b;
So:
x -= (t = u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x)))));
is the same as:
t = u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x))));
x -= t;

In your code:
x -= (t = u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x)))));
Let me assume
A=(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x))));
Then that code will become
x -= (t = u/A);
Then it can read as:
t = u/A;
x -= t;
If you have any questions,just feel free to ask.

Using = will indeed assign a value, and will return the value you are assigning. In your case, t is being assigned the result of u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x))).

The overall calculation : u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x)))) is assigned to t and what ever value of t is there ,this is performed.
x=x-t

The statement could be divided into two sub-statements, and for readibility, it probably should.
t = u/(1.-0.5*MIN(1.,u*(a1/x - b1/(1.-x))));
x -= t;
Essentially, the author assigned a sub-section of the entire formula to an intermediate variable (t) for later use.

Related

lazy-evaluation in Xtensor

In the following function using xtensor, I was expecting the compiler to express the computation graph to auto z = 3.0 * u + 100 * xt::cos(u); and evaluate the result at xt::xtensor_fixed<T, xt::xshape<nn>> out = z; when assigning the expression to an exact tensor.
template<typename T, size_t nn>
T func_cos(xt::xtensor_fixed<T, xt::xshape<nn>> &u) {
auto z = 3.0 * u;
for (auto k = 0; k < 100; ++k){
z += xt::cos(u);
}
xt::xtensor_fixed<T, xt::xshape<nn>> out = z;
return out(0);
}
However, I got an error
views_xtensor.cpp:76:11: error: no viable overloaded '+='
z += xt::cos(u);
[....]
Did I use auto in an wrong way? How could I use lazy evaluation in a for-loop?
Thank you for your help!
When you write
auto z = 3.0 * u
The type of z encodes the operation, it is something like
xfunction<multiplies, scalar<double>, xtensor_fixed>
This class does not hold any value, so it is not possible to assign it anything (even if it is a computed assignment). Now even if iw was possible, consider the following expression
auto y = z + xt::cos(u);
The type of this expression is something like
xfunction<plus, type(z), xfunction<cos, xtensor_fixed>>
So when you write
z += xt::cos(u); // equivalent to z = z + xt::cos(u);
You try to assign z something of a completely different type.
Lazy evaluation cannot be used in for loops for these reasons.

Which is the value of i in this "simple" initialization?

I have a doubt about this code:
int i, x, z = 4, y = 1;
i = x = z += y++;
Which is the value of i? Can we know that value or not?
First of all, have you tested if this compiles at all?
If not, then why?
Unless you write some code that invokes UB, compiler, regarding basic syntax of the language, has most of the answers you'll ever need. Please test it yourself, and if it's still not clear, or behaves weirdly, then it's something worth asking.
In this case, it's valid, so let's go through it.
#include <iostream>
int main() {
int i, x, z = 4, y = 1;
i = x = z += y++;
std::cout << "i=" << i << std::endl;
}
I compiled, ran it, and here's the result:
$ g++ test.cpp -o test
$ ./test
i=5
So, what is actually going on in this line?
i = x = z += y++;
First of all, it's easier to understand when you add parentheses so it's perfectly obvious what is evaluated and when:
i = (x = (z += (y++)));
i is a result of assignment to x;
x is a result of addition assignment to z;
z is a result of z + (y post increment);
You can then work your way backwards through the list, and will arrive at the correct result:
y++ evaluates to simply y, because post increment affects only value of y, not the result of expression itself;
z is then z + y, which is 4 + 1, or 5;
intermediate expression becomes i = x = z; (or, form that's too obvious, i = (x = z);), and that means that i, just like x is 5.
Whatever you do, please don't actually write code like this, while it's easy to deconstruct, it's not something that is easy to understand at a first glance, and that, more often than not, causes confusion.
Can we know that value or not?
Yes.
Which is the value of i?
5
since you add y to i, where their values are 4 (since i gets assigned the value of z, which is 4) and 1 respectively.
y is incremented after z has been initialized. It's incremented in the following statement, as #john commented.
As #LightnessInOrbit commented, this is not good code. Forget about it and move on.
Yes the value of i is 5.
Just trace the code.
y++ post increement i,e first assign the value then increement so Y= 4. Next
z += y shorthand operation i,e.., z= z + y ,initially z=4 so 5 = 4+ 1 so Z=5
x = z i.e, x = 5 Next
i = x i.e, i = 5.

Difference between += and =+ in C++

While programming in C++, I often confuse both "+=" and "=+", the former being the operator I actually mean. Visual Studio seems to accept both, yet they behave differently and is a source for a lot of my bugs. I know that a += b is semantically equivalent to a = a+b, but what does "=+" do?
=+ is really = + (assignment and the unary + operators).
In order to help you remember +=, remember that it does addition first, then assignment. Of course that depends on the actual implementation, but it should be for the primitives.
a =+ b means a = +b means a = b
if you see = the first , it means you re-declare your variable value ,
but if you face + the first it means that you order the compiler to increment the value of the variable , keep it in you mind
int x=20 ;
x=+10 ;
cout<< x <<endl ; // x = 10
x+=10 ;
cout<< x<<endl ; // x= 10+10 = 20
I may be remembering this wrong, but I think that in C, C++, and even Java (which has similar syntax to C and C++), =+ and += actually behave very similarly. The statement that =+ is assignment (equivalent to plain = operator), while += increases a variable's value by a certain amount, is INCORRECT.
x += y as well as x =+ y will BOTH have the same effect (that is, both of these will cause the new value of x to be the old value of x + y). The difference comes in when you have a slightly more complex expression.
z = (x += y) and z = (x =+ y) will have DIFFERENT outputs for the variable z.
Let's look at each one of these:
z = (x += y) will add y to x, and then set z to be the NEW value of x.
z = (x =+ y) will set z to be the OLD value of x, and then add y to x.
It's possible I got those 2 backwards, but I do remember reading somewhere before that the differences I describe here are the ACTUAL differences between those 2.

Moving out before brackets with XOR

If I had the sum of products like z*a + z*b + z*c + ... + z*y, it would be possible to move the z factor, which is the same, out before brackets: z(a + b + c + ... y).
I'd like to know how it is possible (if it is) to do the same trick if bitwise XOR is used instead of multiplication.
z^a + z^b + ... z^y -> z^(a + b + ... + y)
Perhaps a, b, c ... should be preprocessed, such as logically negated or something else, before adding? z could change, so preprocessing, if it's needed, shouldn't depend on particular z value.
From Wikipedia:
Distributivity: with no binary function, not even with itself
So, no, unfortunately, you can't do anything like that with XOR.
To prove that a general formula does not hold you only need to prove a contradiction in a limited case.
We can reduce it to show that this does not hold:
(a^b) * c = (a^c) * (b^c)
It is trivial to show that one base case fails as such:
a = 3
b = 1
c = 1
(a^b) * c = (3^1) * 1 = 2
(a^c) * (b^c) = 2 * 0 = 0
Using the same case you can show that (a*b) ^ c = (a^c) * (b^c) and (a + b) ^ c = (a^c) + (b^c) do not hold either.
Hence, equality does not hold in a general case.
Equality can hold in special cases though, which is an entirely different subject.

Expression transformation problem

Let's say we have the following statement: s = 3 * a * b - 2 * c, where s, a, b and c are variables. Also, we used Shunting Yard algorithm to build RPN expression, so now we can assign values to variables a, b and c and calculate s value by using simple RPN evaluator.
But, the problem is that I should be able to calculate a value of any variable a, b or c when values of all other variables are set.
So, I need to transform existing expression somehow to get a set of expressions:
a = (s + 2 * c) / (3 * b)
b = (s + 2 * c) / (3 * a)
c = (3 * a * b - s) / 2
How can I generate such expressions on basis of one original statement? Is there any standard approaches for solving such problems?
Constraints:
A set of available operators: +, -, *, /, including unary + and -
operators *, / and = can't have the same variable on both sides (e.g. s = a * a, or s = a + s are not acceptable)
Thanks
See this first: Postfix notation to expression tree to convert your RPN into a tree.
Once you have the equation left expression = right expression change this to left expression - right expression = 0 and create a tree of left expression - right expression via Shunting Yard and the above answer. Thus when you evaluate the tree, you must get the answer as 0.
Now based on your restrictions, observe that if a variable (say x) is unknown, the resulting expression will always be of the form
(ax + b)/(cx + d) where a,b,c,d will depend on the other variables.
You can now recursively compute the expression as a tuple (a,b,c,d).
In the end, you will end up solving the linear equation
(ax + b)/(cx + d) = 0 giving x = -b/a
This way you don't have to compute separate expressions for each variable. One expression tree is enough. And given the other variables, you just recursively compute the tuple (a,b,c,d) and solve the linear equation in the end.
The (incomplete) pseudocode will be
TupleOrValue Eval (Tree t) {
if (!t.ContainsVariable) {
blah;
return value;
}
Tuple result;
if (t.Left.ContainsVariable) {
result = Eval(t.Left);
value = Eval(t.Right);
return Compose(t.Operator, result, value);
} else {
result = Eval(t.Right);
value = Eval(t.Left);
return Compose(t.Operator, result, value);
}
}
Tuple Compose(Operator op, Tuple t, Value v) {
switch (op) {
case 'PLUS': return new Tuple(t.a + v*t.c, t.b + v*t.d, t.c, t.d);
// (ax+b)/(cx+d) + v = ( (a + vc)x + b + dv)/(cx + d)
// blah
}
}
For an example, if the expression is x+y-z = 0. The tree will be
+
/ \
x -
/ \
y z
For y=5 and z=2.
Eval (t.Right) will return y-z = 3 as that subtree does not contain x.
Eval(t.Left) will return (1,0,0,1) which corresponds to (1x + 0)/(0x + 1). Note: the above pseudo-code is incomplete.
Now Compose of (1,0,0,1) with the value 3 will give (1 + 3*0, 0 + 3*1, 0, 1) = (1,3,0,1) which corresponds to (x + 3)/(0x + 1).
Now if you want to solve this you take x to be -b/a = -3/1 = -3
I will leave the original answer:
In general it will be impossible.
For instance consider the expression
x*x*x*x*x + a*x*x*x*x + b*x*x*x + c*x*x + d*x = e
Getting an expression for x basically corresponds to find the roots of the polynomial
x5 + ax4 + bx3 + cx2 + dx -e
which has been proven to be impossible in general, if you want to use +,-,/,* and nth roots. See Abel Ruffini Theorem.
Are there are some restrictions you forgot to mention, which might simplify the problem?
The basic answer is you have to apply algebra to the set of equations you have, to produce equations that you want.
In general, if you start with this symbolic equation:
s = 3 * a * b - 2 * c
and you add constraints for s, a, and c:
s = ...
a = ...
c = ...
you need to apply standard laws of algebra to rearrange the set of equations to produce what you want, in this case, a formula for b:
b = ...
If you add different constraints, you need the same laws of algebra, applied in different ways.
If your equations are all of the form (as your example is not) of
left_hand_side_variable_n = combination_of_variables
then you can use rules for solving simultaneous equations. For linear combinations, this is pretty straightforward (you learned how to do this high school). And you can even set up a standard matrix and solve using a standard solver package without doing algebra.
If the equations are not linear, then you may not be able to find a solution no matter how good your math is (see other answers for examples). To the extent it is possible to do so, you can use a computer algebra system (CAS) to manipulate formulas. They do so by representing the formulas essentially as [math] abstract syntax trees, not as RPN, and apply source-to-source transformation rules (you would call these "algebra rules" from high school). They usually have a pretty big set of built-in rules ("knowledge") already. Some CAS will attempt to solve such systems of equations for you using the built-in rules; others, you have to tell what sequence of algebraic laws to apply in what order.
You may also use a constraint solver, which is a special kind of computer algebra system focused only on answering the kind of question you've posed, e.g., "with this set of constraints, and specific values for variables, what is the value of other variables?". These are pretty good if your equations follows the forms they are designed to solve; otherwise no gaurantee but that's not surprising.
One can also use a program transformation system, which manipulate arbitrary "syntax trees", because algrebra trees are just a special case of syntax trees. To use such a system, you define the langauge to be manipulated (e.g., conventional algebra) and the rules by which it can be manipulated, and the order in which to apply the rules. [The teacher did exactly this for you in your intro algebra class, but not in such a formal way] Here's an example of a my program transformation system manipulating algebra. For equation solving, you want much the same rules, but a different order of application.
Finally, if you want to do this in a C++ program, either you have to simulate one of the above more general mechanisms (which is a huge amount of work), or you have narrow what you are willing to solve significantly (e.g., "linear combinations") so that you can take advantage of a much simpler algorithm.
There is a quite straight-forward one for very basic expressions (like in your example) where each variable occurs mostly once and every operator is binary. The algorithm is mostly what you would do by hand.
The variable we are looking for will be x in the following lines. Transform your expression into the form f(...,x,...) == g(...). Either variable x is already on the left hand side or you just switch both sides.
You now have two functions consisting of applications of binary operators to sub-expressions, i.e. f = o_1(e_1,e_2) where each e_i is either a variable, a number or another function e_i = o_i(e_j, e_k). Think of this as the binary tree representation where nodes are operators and leafs are variables or numbers. Same applies for g.
Yyou can apply the following algorithm (our goal is to transform the tree into one representing the expression x == h(...):
while f != x:
// note: f is not a variable but x is a subexpression of f
// and thus f has to be of the form binop(e_1, e_2)
if x is within e_1:
case f = e_1 + e_2: // i.e. e_1 + e_2 = g
g <- g - e_2
case f = e_1 - e_2: // i.e. e_1 - e_2 = g
g <- g + e_2
case f = e_1 * e_2: // i.e. e_1 * e_2 = g
g <- g / e_2
case f = e_1 / e_2: // i.e. e_1 / e_2 = g
g <- g * e_2
f <- e_1
else if x is within e_2:
case f = e_1 + e_2: // i.e. e_1 + e_2 = g
g <- g - e_2
case f = e_1 - e_2: // i.e. e_1 - e_2 = g
g <- g + e_2
case f = e_1 * e_2: // i.e. e_1 * e_2 = g
g <- g / e_2
case f = e_1 / e_2: // i.e. e_1 / e_2 = g
g <- g * e_2
f <- e_1
Now that f = x and f = g was saved during all steps we have x = g as solution.
In each step you ensure that x remains on the lhs and at the same time you reduce the depth of the lhs by one. Thus this algorithm will terminate after a finite amount of steps.
In your example (solve for b):
f = 3a*b*2c*- and g = s
f = 3a*b* and g = s2c*+
f = b and g = s2c*+3a*/
and thus b = (s + 2*c)/(3*a).
If you have more operators you can extend the algorithm but you might run into problems if they are not invertible.