0

Is there a way to overcome a nested loop recursion in C++11? My program has a slow runtime. Or rather, is there a more efficient way to solve for the following formula z=|a-b|*|x-y|,with a, b, x and y being elements in a 10000 integer array?

Here is the code:

#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

ifstream in("int.in");

int main()
{
    long long n, n1, z, x, y, in2=0;
    in>>n
    long long l[n], p[n];
    for(x=0;x!=n;x++)
        in>>l[x]>>p[x];
    for(x=0;x!=n;x++)
    {
        for(y=x+1;y<n;y++)
        {
            ineq+=(abs(l[x]-l[y])*abs(p[x]-p[y]))); //executes slow
            /*n1=l[x]-l[y]; //Alternative algorithm
            if(n1<0)
                n1*=-1;
            z=p[x]-p[y];
            if(z<0)
                z*=-1;
            in2+=n1*z;*/
        }
    }
    cout<<in2<<"\n";
}

I tried to change the data types to short int, long, long long and unsigned, but it either dumps garbage values or executes ``Segmentation Core Fault` errors.

For the absolute value formula, I originally tried using a hard-coded approach (commented out), but it seemingly outputs garbage values. I've also tried to optimize the abs solution with the abs() function ineq+=abs(l[x]-l[y])*abs(p[x]-p[y]));, but it seems to execute slower. I do not know of any other optimizations I can implement, so please do recommend some.

Linux-friendly solution preferred. Thank you.

Side Note: the values of a, b, x and y are all within the range 1<=a,b,x,y<=10000.

Side Note: this program reads from a file "int.in", takes the first integer (the number of items) and reads each new line by pair (l[x] and p[x] are pairs).

Side Note: I also tried using only a multidimensional array, but I read somewhere that a one dimension array is in the CPU cache, while multidimensions are scattered in the memory and is slower.

  • 3
    Can you explain why you are computing this? Then it might be easier to suggest an alternative algorithm. – cfh May 06 '15 at 08:42
  • Related, what are you trying to accomplish in the big picture? For example, I think Fourier Transforms run in `n log n`, so if you can move it to the FFT domain, you will get your speedup. – jww May 06 '15 at 08:42
  • And z can be whatever? You want to have **all** the solutions or just one? – Thomas Ayoub May 06 '15 at 08:42
  • `|a-b|*|x-y|` is exactly the same to `z=|(a-b)(x-y)|`. That saves you an absolute call – phuclv May 06 '15 at 10:52
  • your alternative way is no better than the other one because `n1*=-1;` will be costlier than `n1 = -n1;` if the compiler is not smart enough, and the `if` may incur a branch while `abs` will use the most eifficient way to take absolute – phuclv May 06 '15 at 10:56
  • @LưuVĩnhPhúc I know I'm stepping boundaries here, but readability is not a necessity in this program, as a separate program will simply redirect the compiled .exe's stdin and stdout to a file (which is not the point of this program; its just to automate things) and thus I only require the fastest possible code with the smallest possible space on memory. in both cases, abs() failed. – Zuayo Beta May 06 '15 at 13:13
  • I didn't talk about readability here but performance. A multiplication is obviously much slower than a negation. And 2 `abs` calls obviously are slower than a single call. – phuclv May 07 '15 at 09:01

1 Answers1

1

The problem can be drawn in another way: you're looking for c and d (both positive) in the equation z=c*d (of course c is |a-b| and d is |x-y|).

So first order your arrays. Then look for solution of z=c*d then find which a and b make c == a - b true and x and y that make d == x - y true.

Once it's done you've got all the values that makes your equation true since abs(a-b) is the same as abs(b-a)

Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142