C++ calling single helper function with *this attributes - c++

Edit: I’m a beginner to C++, and I’d like to understand more about how to optimize my code.
I have created a Fraction object in C++ as well as overloaded +, - operations etc. When I came to the unary operators, however, I realized I didn't know how to reduce the fraction in the most efficient manner. So I have a function gcd that finds the greatest divisor:
int gcd (int n, int m) {
int newN = n < 0 ? -n : n;
int newM = m < 0 ? -m : m;
if (newM <= newN && newN % newM == 0) { return newM; }
else if (newN < newM) { return gcd(newM, newN); }
else { return gcd(newM, newN%newM); }
}
and then I have an overloaded operator, for example, incrementation:
Fraction& Fraction::operator++() {
num = num + denom;
//reduce fraction
int divisor = gcd(denom,num);
num = num/divisor;
denom = denom/divisor;
if (num < 0 && denom < 0) {num *= (-1);}
if (denom < 0) {denom *= (-1);}
return *this;
}
For efficiency, I would like to put the reduce fraction part of the code in a separate single helper function so the final function would look like this:
Fraction& Fraction::operator++() {
num = num + denom;
//reduce fraction
reduce(num, denom);
return *this;
}
That way I don't have to copy and paste whatever is in //reduce fraction everytime I overload a unary operator for example. However, I'm not sure how the reduce(Fraction num, Fraction& denom) function should look like. At most I can implement it like this:
void reduce(int& num, int& denom) {
int divisor = gcd(denom,num);
num = num/divisor;
denom = denom/divisor;
if (num < 0 && denom < 0) {num *= (-1);}
if (denom < 0) {denom *= (-1);}
}
I'm sure the code above will run into issues during compilation, so I was wondering if I could be suggested any pointers as to efficiently create the reduce fraction function. This is maybe being a bit nitpicky since my original code runs fine, but since I am new to C++, I'd like to learn more about how I can make my code more efficient. Thanks a lot! Let me know if more information is needed.
Edit: The above code does not work. Compiles correctly, but does not reduce fraction properly. So 1/2 + 1/4 results in 6/8, not 3/4.

Well on a high level your gcd function is too complicated and the last part of reduce is a bit wrong. If only denom is negative you invert it.
Nicely shows why it's always a good idea to put code into proper functions because they can also be separately tested. So I'd suggest writing some unit tests for your reduce and gcd functions.
Start with a simple solution like
static int gcd(int a, int b)
{
return b == 0 ? a : gcd(b, a % b);
}
and adapt if needed for negative numbers considering % semantics. Thinking about it the function should already be fine like that and you just need to call std::abs(gcd(n,d)) in reduce.
In general you should ask yourself if you really want to pay the renormalization cost at every single operation or if you let the user decide when to call reduce.
For lower-level optimizations here are some hints:
Always test/measure, e.g. by looking at what the compiler actually produces with godbolt.org.
The recursion in gcd is not a problem from a performance point of view in this case as it's tail recursive and the compiler will turn it into a loop for you.
The out parameters in reduce are bad for optimizations cause the compiler has to prove they don't point to the same object. Returning a std::pair and using C++11 std::tie or C++17 structured bindings at the callsite if possible is way more elegant.

Related

how could I use the power function in c/c++ without pow(), functions, or recursion

I'm using a C++ compiler but writing code in C (if that helps)
There's a series of numbers
(-1^(a-1)/2a-1)B^(2a-1)
A and X are user defined... A must be positive, but X can be anything (+,-)...
to decode this sequence... I need use exponents/powers, but was given some restrictions... I can't make another function, use recursion, or pow() (among other advanced math functions that come with cmath or math.h).
There were plenty of similar questions, but many answers have used functions and recursion which aren't directly relevant to this question.
This is the code that works perfectly with pow(), I spent a lot of time trying to modify it to replace pow() with my own code, but nothing seems to be working... mainly getting wrong results. X and J are user inputted variables
for (int i = 1; i < j; i++)
sum += (pow(-1, i - 1)) / (5 * i - 1) * (pow(x, 5 * i - 1));
}
You can use macros to get away with no function calls restriction as macros will generate inline code which is technically not a function call
however in case of more complex operations macro can not have return value so you need to use some local variable for the result (in case of more than single expression) like:
int ret;
#define my_pow_notemp(a,b) (b==0)?1:(b==1)?a:(b==2)?a*a:(b==3)?a*a*a:0
#define my_pow(a,b)\
{\
ret=1;\
if (int(b& 1)) ret*=a;\
if (int(b& 2)) ret*=a*a;\
if (int(b& 4)) ret*=a*a*a*a;\
if (int(b& 8)) ret*=a*a*a*a*a*a*a*a;\
if (int(b&16)) ret*=a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a;\
if (int(b&32)) ret*=a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a;\
}
void main()
{
int a=2,b=3,c;
c=my_pow_notemp(a,b); // c = a^b
my_pow(a,b); c = ret; // c = a^b
}
as you can see you can use my_pow_notemp directly but the code is hardcoded so only up to a^3 if you want more you have to add it to code. The my_pow is accepting exponents up to a^63 and its also an example on how to return value in case of more complex code inside macro. Here are some (normal) ways on how to compute powers in case you need non integer or negative exponents (but to convert it to unrolled code will be insanely hard without loops/recursion):
Power by squaring for negative exponents
In case you want to get away with recursion and function calls you can use templates instead of macros but that is limited to C++.
template<class T> T my_pow(T a,T b)
{
if (b==0) return 1;
if (b==1) return a;
return a*my_pow(a,b-1);
}
void main()
{
int a=2,b=3,c;
c=my_pow(a,b);
}
As you can see templates have return value so no problem even with more complex code (more than single expression).
To avoid loops you can use LUT tables
int my_pow[4][4]=
{
{1,0,0,0}, // 0^
{1,1,1,1}, // 1^
{1,2,4,8}, // 2^
{1,3,9,27}, // 3^
};
void main()
{
int a=2,b=3,c;
c=my_pow[a][b];
}
If you have access to FPU or advanced math assembly you can use that as asm instruction is not a function call. FPU usually have log,exp,pow functions natively. This however limits the code to specific instruction set !!!
Here some examples:
How to: pow(real, real) in x86
So when I consider your limitation I think the best way is:
#define my_pow(a,b) (b==0)?1:(b==1)?a:(b==2)?a*a:(b==3)?a*a*a:0
void main()
{
int a=2,b=3,c;
c=my_pow(a,b); // c = a^b
}
Which will work on int exponents b up to 3 (if you want more just add (b==4)?a*a*a*a: ... :0) and both int and float bases a. If you need much bigger exponent use the complicated version with local temp variable for returning result.
[Edit1] ultimative single expression macro with power by squaring up to a^15
#define my_pow(a,b) (1* (int(b&1))?a:1* (int(b&2))?a*a:1* (int(b&4))?a*a*a*a:1* (int(b&8))?a*a*a*a*a*a*a*a:1)
void main()
{
int a=2,b=3,c;
c=my_pow(a,b); // c = a^b
}
In case you want more than a^15 just add sub term (int(b&16))?a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a:1 and so on for each bit of exponent.
It is a series. Replace pow() based on the previous iteration. #Bathsheba
Code does not need to call pow(). It can form pow(x, 5 * i - 1) and pow(-1, i - 1), since both have an int exponent based on the iterator i, from the prior loop iteration.
Example:
Let f(x, i) = pow(x, 5 * i - 1)
Then f(x, 1) = x*x*x*x
and f(x, i > 1) = f(x, i-1) * x*x*x*x*x
double power_n1 = 1.0;
double power_x5 = x*x*x*x;
for (int i = 1; i < j + 1; i++)
// sum += (pow(-1, i - 1)) / (5 * i - 1) * (pow(x, 5 * i - 1));
sum += power_n1 / (5 * i - 1) * power_x5;
power_n1 = -power_n1;
power_x5 *= x*x*x*x*x;
}

What is the need of the statement of (num+mod)%mod?

What is the need of the statement ans = (ans + mod) % mod in this program ?
Assume that mod = 10^9+7. This function is computing a to the power of b under mod operation in O(log(n)) complexity:
long long power(long long a, long long b)
{
if (b == 0)
return 1ll;
long long ans = power(a, b/2);
ans = (ans * ans) % mod;
ans = (ans + mod) % mod;
if(b % 2 == 1)
ans = (ans * a) % mod;
ans = (ans + mod) % mod;
return ans;
}
The most common usage of such a construct is to make sure the result is non-negative. The standard operator% behaves differently for positive and negative arguments: for example, 4%3==1, but (-2)%3==-2, while you might expect (-2)%3==1 and (-2)/3==-1, which is mathematically more correct.
This behavior can often cause problems when modular arithmetic is used, and this trick of adding mod is often employed to obtain the mathematically more correct non-negative result. Instead of simply writing a%b, if a can be negative, one writes (a%b+b)%b.
However, its usage in the code in your question is strange. In that case, it is easier to assume that a is positive before calling the power function from the main code (for example, by making the main call like power((a%mod+mod)%mod, b)). Probably the author just wanted to get additional assurance of correctness, although it was not needed.

How can I check if std::pow will overflow double

I have a function that deals with arbitrarily large grids. I need to compute if a grid to the power of another number will fit into a double due to using std::pow. If it cannot, I want to take a different branch and use gnu multiprecision library instead of normal.
Is there a quick way to see if:
int a = 1024;
int b = 0-10;
if(checkPowFitsDouble(a, b)) {
long c = static_cast<long>(std::pow(a, b)); //this will only work if b < 6
} else {
mpz_t c; //yada yada gmp
}
I am completely stumped on checkPowFitsDouble; perhaps there is some math trick I don't know of.
A common trick to check whether exponentiations will overflow uses logarithms. The idea is based on these relationships:
a^b <= m <=> log(a^b) <= log(m) <=> b * log(a) <= log(m) <=> b <= log(m) / log(a)
For instance,
int a = 1024;
for (int b = 0; b < 10; ++b) {
if (b * std::log(a) < std::log(std::numeric_limits<long>::max())) {
long c = std::pow(a, b);
std::cout << c << '\n';
}
else
std::cout << "overflow\n";
}
This gives the idea. I hope this helps.
Unless it's particularly performance-critical, the suggestion would be to try it and see. If it overflows a double, std::pow will return HUGE_VAL. Hence something like:
double val = std::pow(a, b);
if(val != HUGE_VAL) {
...
} else {
mpz_t c;
//...
}
You can easily use the reverse functions in the test:
if ( std::log( DBL_MAX ) / std::log( a ) < b ) {
// std::pow( a, b ) will not overflow...
} else {
}
It might be just as good to just do the pow, and see if it
succeeds:
errno = 0;
double powab = std::pow( a, b );
if ( errno == 0 ) {
// std::pow succeeded (without overflow)
} else {
// some error (probably overflow) with std::pow.
}
You won't gain much time by just calculating std::log( a ).
(std::log( DBL_MAX ) is, of course, a constant, so only needs
to be calculated once.)
With a logarithm base 10, you can deduce that std:pow(a, b) has log(a^b) = b log a digits. You can then trivially see if it fits a double, which can fit values up to DBL_MAX.
However, this method performs additional computation than just computing a^b once. Measure a version with GMP first and see if checking for overflow actually provides any measurable and reproducible benefits.
EDIT: Ignore this, std::pow already returns an appropriate value in case an overflow occurs, so use that.

Simplify this expression

Let a, b be positive integers with different values. Is there any way to simplify these expressions:
bool foo(unsigned a, unsigned b)
{
if (a % 2 == 0)
return (b % 2) ^ (a < b); // Should I write "!=" instead of "^" ?
else
return ! ( (b % 2) ^ (a < b) ); // Should I write "(b % 2) == (a < b)"?
}
I am interpreting the returned value as a boolean.
How is it different from
(a%2)^(b%2)^(a<b)
which in turn is
((a^b)&1)^(a<b)
or, indeed
((a ^ b) & 1) != (a < b)
Edited to add: Thinking about it some more, this is just the xor of the first and last bits of (a-b) (if you use 2's complement), so there is probably a machine-specific ASM sequence which is faster, involving a rotate instruction.
As a rule of thumb, don't mix operators of different operator families. You are mixing relational/boolean operators with bitwise operators, and regular arithmetic.
This is what I think you are trying to do, I'm not sure, since I don't understand the purpose of your code: it is neither readable nor self-explaining.
bool result;
bool a_is_even = (a % 2) == 0;
bool b_is_even = (b % 2) == 0;
if (a_is_even == b_is_even) // both even or both odd
result = a < b;
else
result = a >= b;
return result;
I program in C# but I'd think about something like this:
return (a % 2 == 0) && ((b % 2) ^ (a < b))
Considering from you comments that '^' is equivalent to '=='
If you are returning a truth value, a boolean, then your proposed changes do not change the semantics of the code. That's because bitwise XOR, when used in a truth context, is the same as !=.
In my view your proposed changes make the code much easier to understand. Quite why the author thought bitwise XOR would be appropriate eludes me. I guess some people think that sort of coding is clever. I don't.
If you want to know the relative performance of the two versions, write a program and time the difference. I'd be surprised if you could measure any difference between them. And I'd be equally surprised if these lines of code were your performance bottleneck.
Since there is not much information around this issue, try this:
int temp = (b % 2) ^ (a < b);
if (a % 2 == 0)
return temp;
else
return !temp;
This should be less code if the compiler hasn't optimized it already.

Efficient Exponentiation For HUGE Numbers (I'm Talking Googols)

I am in the midst of solving a simple combination problem whose solution is 2^(n-1).
The only problem is 1 <= n <= 2^31 -1 (max value for signed 32 bit integer)
I tried using Java's BigInteger class but It times out for numbers 2^31/10^4 and greater, so that clearly doesn't work out.
Furthermore, I am limited to using only built-in classes for Java or C++.
Knowing I require speed, I chose to build a class in C++ which does arithmetic on strings.
Now, when I do multiplication, my program multiplies similarly to how we multiply on paper for efficiency (as opposed to repeatedly adding the strings).
But even with that in place, I can't multiply 2 by itself 2^31 - 1 times, it is just not efficient enough.
So I started reading texts on the problem and I came to the solution of...
2^n = 2^(n/2) * 2^(n/2) * 2^(n%2) (where / denotes integer division and % denotes modulus)
This means I can solve exponentiation in a logarithmic number of multiplications. But to me, I can't get around how to apply this method to my code? How do I choose a lower bound and what is the most efficient way to keep track of the various numbers that I need for my final multiplication?
If anyone has any knowledge on how to solve this problem, please elaborate (example code is appreciated).
UPDATE
Thanks to everyone for all your help! Clearly this problem is meant to be solved in a realistic way, but I did manage to outperform java.math.BigInteger with a power function that only performs ceil(log2(n)) iterations.
If anyone is interested in the code I've produced, here it is...
using namespace std;
bool m_greater_or_equal (string & a, string & b){ //is a greater than or equal to b?
if (a.length()!=b.length()){
return a.length()>b.length();
}
for (int i = 0;i<a.length();i++){
if (a[i]!=b[i]){
return a[i]>b[i];
}
}
return true;
}
string add (string& a, string& b){
if (!m_greater_or_equal(a,b)) return add(b,a);
string x = string(a.rbegin(),a.rend());
string y = string(b.rbegin(),b.rend());
string result = "";
for (int i = 0;i<x.length()-y.length()+1;i++){
y.push_back('0');
}
int carry = 0;
for (int i =0;i<x.length();i++){
char c = x[i]+y[i]+carry-'0'-'0';
carry = c/10;
c%=10;
result.push_back(c+'0');
}
if (carry==1) result.push_back('1');
return string(result.rbegin(),result.rend());
}
string multiply (string&a, string&b){
string row = b, tmp;
string result = "0";
for (int i = a.length()-1;i>=0;i--){
for (int j= 0;j<(a[i]-'0');j++){
tmp = add(result,row);
result = tmp;
}
row.push_back('0');
}
return result;
}
int counter = 0;
string m_pow (string&a, int exp){
counter++;
if(exp==1){
return a;
}
if (exp==0){
return "1";
}
string p = m_pow(a,exp/2);
string res;
if (exp%2==0){
res = "1"; //a^exp%2 is a^0 = 1
} else {
res = a; //a^exp%2 is a^1 = a
}
string x = multiply(p,p);
return multiply(x,res);
//return multiply(multiply(p,p),res); Doesn't work because multiply(p,p) is not const
}
int main(){
string x ="2";
cout<<m_pow(x,5000)<<endl<<endl;
cout<<counter<<endl;
return 0;
}
As mentioned by #Oli's answer, this is not a question of computing 2^n as that's trivially just a 1 followed by 0s in binary.
But since you want to print them out in decimal, this becomes a question of how to convert from binary to decimal for very large numbers.
My answer to that is that it's not realistic. (I hope this question just stems from curiosity.)
You mention trying to compute 2^(2^31 - 1) and printing that out in decimal. That number is 646,456,993 digits long.
Java BigInteger can't do it. It's meant for small numbers and uses O(n^2) algorithms.
As mentioned in the comments, there are no built-in BigNum libraries in C++.
Even Mathematica can't handle it: General::ovfl : Overflow occurred in computation.
Your best bet is to use the GMP library.
If you're just interested in seeing part of the answer:
2^(2^31 - 1) = 2^2147483647 =
880806525841981676603746574895920 ... 7925005662562914027527972323328
(total: 646,456,993 digits)
This was done using a close-sourced library and took roughly 37 seconds and 3.2 GB of memory on a Core i7 2600K # 4.4 GHz including the time needed to write all 646 million digits to a massive text file.
(It took notepad longer to open the file than needed to compute it.)
Now to answer your question of how to actually compute such a power in the general case, #dasblinkenlight has the answer to that which is a variant of Exponentiation by Squaring.
Converting from binary to decimal for large numbers is a much harder task. The standard algorithm here is Divide-and-Conquer conversion.
I do not recommend you try to implement the latter - as it's far beyond the scope of starting programmers. (and is also somewhat math-intensive)
You don't need to do any multiplication at all. 2^(n-1) is just 1 << (n-1), i.e. 1 followed by (n-1) zeros (in binary).
The easiest way to apply this method in your code is to apply it the most direct way - recursively. It works for any number a, not only for 2, so I wrote code that takes a as a parameter to make it more interesting:
MyBigInt pow(MyBigInt a, int p) {
if (!p) return MyBigInt.One;
MyBigInt halfPower = pow(a, p/2);
MyBigInt res = (p%2 == 0) ? MyBigInt.One : a;
return res * halfPower * halfPower;
}