Calculate Y axis distance

Discussion in 'C Programming' started by David RF, May 5, 2012.

  1. David RF

    David RF Guest

    Hi folks, first of all excuse my poor english, I have build this
    function for calulate Y axis distance, I wan't to know if there is a
    way to increase performance or improve the algorithm (dgra is called
    many many times) Thanks.

    #include <stdio.h>

    double ddiv(double a, double b)
    {
    return b == 0.0 ? 0.0 : a / b;
    }

    double dgra(double d, int *n)
    {
    const double a[] = {1.25, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0,
    7.5, 8.0, 10.0, 12.5};
    const double *pa = a;
    double sign, product;

    if (d == 0.0) {
    if (n) *n = 0;
    return 0.0;
    }
    d *= sign = (d > 0.0) ? 1.0 : -1.0; /* Store sign */
    /* Trunc to most significant (by example 15678 turns into
    1.5678) */
    if (d < 1.0) {
    for (product = 1.0; d < 1.00; product *= 0.10, d *=
    10.0);
    } else {
    for (product = 1.0; d > 10.0; product *= 10.0, d *=
    0.10);
    }
    d *= 1.1; /* Increase number 10% */
    while (*pa < d) pa++; /* Search optimal value */
    /* Must be divide by n numbers */
    if (n) {
    if (*pa == 1.5 || *pa == 3.0 || *pa == 6.0)
    *n = 3; else
    if (*pa == 2.0 || *pa == 4.0 || *pa == 8.0)
    *n = 4; else
    *n = 5;
    }
    return *pa * sign * product;
    }

    int main(void)
    {
    /* Test */
    const double a[] = {112.8, -13.245, 121.5, 27894.0, 0.22452,
    463.20, 7094.230, 235.20, 1420.04, 992312.52, 0.0};
    const double *pa = a;
    double d, f;
    int n;

    while (*pa) {
    d = dgra(*pa, &n);
    f = ddiv(d, n);
    printf("%f = %f\n", *pa, d);
    while (n >= 0) {
    printf("\t%f\n", f * n);
    n--;
    }
    pa++;
    }
    return 0;
    }

    --
    David
     
    David RF, May 5, 2012
    #1
    1. Advertising

  2. David RF

    Stefan Ram Guest

    David RF <> writes:
    >I wan't to know if there is a
    >way to increase performance


    Yes: to measure the run-time of the application under the
    target environment (of the customer) and then trying the
    optimization techniques like: replacing double by float,
    trying compiler-options (like -O3), using a
    profiler/valgrind to analyze behavior (like cache misses,
    KCacheGrind), loop unroling, cache-friendliness, inline
    functions, strength reduction, reduction of register
    pressure, writing in assembly, using »const«/»restrict« to
    allow more optimizations.
     
    Stefan Ram, May 5, 2012
    #2
    1. Advertising

  3. On Sat, 5 May 2012 10:36:28 -0700 (PDT), David RF
    <> wrote:

    >Hi folks, first of all excuse my poor english, I have build this
    >function for calulate Y axis distance, I wan't to know if there is a
    >way to increase performance or improve the algorithm (dgra is called
    >many many times) Thanks.


    In the code you show, dgra is called only 10 times. Unless this is
    only an example and you actually call it several thousand times, no
    improvement is likely to have a noticeable affect.

    >
    >#include <stdio.h>
    >
    >double ddiv(double a, double b)
    >{
    > return b == 0.0 ? 0.0 : a / b;
    >}


    This function is unnecessary. See comment in main.

    >
    >double dgra(double d, int *n)
    >{
    > const double a[] = {1.25, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0,
    >7.5, 8.0, 10.0, 12.5};


    If you make a static, it will not get reinitialized each time you call
    dgra which will save some time.

    > const double *pa = a;


    Suggestion: If you change pa to an int (not const) and initialize it
    to 0, you can save some time at the end of dgra. To do this, also add
    an integer array parallel to a
    static const int b[] = {5, 3, 4, 5, 3, 4, 5, 3, 5, 4, 5,5};

    > double sign, product;
    >
    > if (d == 0.0) {
    > if (n) *n = 0;
    > return 0.0;
    > }
    > d *= sign = (d > 0.0) ? 1.0 : -1.0; /* Store sign */


    Multiplication of doubles can be time consuming. The following may be
    faster.
    if (d > 0.0)
    sign = 1.0;
    else
    {
    sign = -1.0;
    d = -d;
    }

    > /* Trunc to most significant (by example 15678 turns into
    >1.5678) */


    You should be aware that if d is 11.5, it will be represented exactly
    but -

    > if (d < 1.0) {
    > for (product = 1.0; d < 1.00; product *= 0.10, d *=
    >10.0);
    > } else {
    > for (product = 1.0; d > 10.0; product *= 10.0, d *=
    >0.10);


    after multiplying by .1, d will not equal 1.15 because that number
    cannot be represented exactly.

    > }
    > d *= 1.1; /* Increase number 10% */
    > while (*pa < d) pa++; /* Search optimal value */


    Suggestion continued: All expressions in dgra of the form *pa need to
    be changed to a[pa].

    > /* Must be divide by n numbers */
    > if (n) {
    > if (*pa == 1.5 || *pa == 3.0 || *pa == 6.0)
    > *n = 3; else
    > if (*pa == 2.0 || *pa == 4.0 || *pa == 8.0)
    > *n = 4; else
    > *n = 5;
    > }


    Suggestion completed: This entire sequence can then be replace by
    if (n)
    *n = b[pa];

    > return *pa * sign * product;
    >}
    >
    >int main(void)
    >{
    > /* Test */
    > const double a[] = {112.8, -13.245, 121.5, 27894.0, 0.22452,
    >463.20, 7094.230, 235.20, 1420.04, 992312.52, 0.0};
    > const double *pa = a;
    > double d, f;
    > int n;
    >
    > while (*pa) {
    > d = dgra(*pa, &n);
    > f = ddiv(d, n);


    You could replace the call to ddiv with the same one statement that
    ddiv contains, just change the variable names. This will eliminate
    the overhead calling the function.
    f = (n == 0.0 ? 0.0 : d/n);

    > printf("%f = %f\n", *pa, d);
    > while (n >= 0) {
    > printf("\t%f\n", f * n);
    > n--;
    > }
    > pa++;
    > }
    > return 0;
    >}


    --
    Remove del for email
     
    Barry Schwarz, May 5, 2012
    #3
  4. David RF

    Ian Collins Guest

    On 05/ 6/12 07:51 AM, Barry Schwarz wrote:
    > On Sat, 5 May 2012 10:36:28 -0700 (PDT), David RF
    > <> wrote:
    >
    >> Hi folks, first of all excuse my poor english, I have build this
    >> function for calulate Y axis distance, I wan't to know if there is a
    >> way to increase performance or improve the algorithm (dgra is called
    >> many many times) Thanks.
    >>
    >> #include<stdio.h>
    >>
    >> double ddiv(double a, double b)
    >> {
    >> return b == 0.0 ? 0.0 : a / b;
    >> }

    >
    > This function is unnecessary. See comment in main.


    <snip>

    >> int main(void)
    >> {
    >> /* Test */
    >> const double a[] = {112.8, -13.245, 121.5, 27894.0, 0.22452,
    >> 463.20, 7094.230, 235.20, 1420.04, 992312.52, 0.0};
    >> const double *pa = a;
    >> double d, f;
    >> int n;
    >>
    >> while (*pa) {
    >> d = dgra(*pa,&n);
    >> f = ddiv(d, n);

    >
    > You could replace the call to ddiv with the same one statement that
    > ddiv contains, just change the variable names. This will eliminate
    > the overhead calling the function.


    Any compiler worth using will do that for you. All you loose by
    removing the function is clarity - assuming the function name is meaningful!

    --
    Ian Collins
     
    Ian Collins, May 6, 2012
    #4
  5. David RF

    David RF Guest

    On 5 mayo, 21:51, Barry Schwarz <> wrote:
    > On Sat, 5 May 2012 10:36:28 -0700 (PDT), David RF
    >
    > <> wrote:
    > >Hi folks, first of all excuse my poor english, I have build this
    > >function for calulate Y axis distance, I wan't to know if there is a
    > >way to increase performance or improve the algorithm (dgra is called
    > >many many times) Thanks.

    >
    > In the code you show, dgra is called only 10 times.  Unless this is
    > only an example and you actually call it several thousand times, no
    > improvement is likely to have a noticeable affect.
    >
    >
    >
    > >#include <stdio.h>

    >
    > >double ddiv(double a, double b)
    > >{
    > >        return b == 0.0 ? 0.0 : a / b;
    > >}

    >
    > This function is unnecessary.  See comment in main.
    >
    >
    >
    > >double dgra(double d, int *n)
    > >{
    > >        const double a[] = {1.25, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0,
    > >7.5, 8.0, 10.0, 12.5};

    >
    > If you make a static, it will not get reinitialized each time you call
    > dgra which will save some time.
    >
    > >        const double *pa = a;

    >
    > Suggestion: If you change pa to an int (not const) and initialize it
    > to 0, you can save some time at the end of dgra.  To do this, also add
    > an integer array parallel to a
    >     static const int b[] = {5, 3, 4, 5, 3, 4, 5, 3, 5, 4, 5,5};
    >
    > >        double sign, product;

    >
    > >        if (d == 0.0) {
    > >                if (n) *n = 0;
    > >                return 0.0;
    > >        }
    > >        d *= sign = (d > 0.0) ? 1.0 : -1.0; /* Store sign */

    >
    > Multiplication of doubles can be time consuming.  The following may be
    > faster.
    >      if (d > 0.0)
    >           sign = 1.0;
    >      else
    >           {
    >           sign = -1.0;
    >           d = -d;
    >           }
    >
    > >        /* Trunc to most significant (by example 15678 turns into
    > >1.5678) */

    >
    > You should be aware that if d is 11.5, it will be represented exactly
    > but -
    >
    > >        if (d < 1.0) {
    > >                for (product = 1.0; d < 1.00; product *= 0.10, d *=
    > >10.0);
    > >        } else {
    > >                for (product = 1.0; d > 10.0; product *= 10.0, d *=
    > >0.10);

    >
    > after multiplying by .1, d will not equal 1.15 because that number
    > cannot be represented exactly.
    >
    > >        }
    > >        d *= 1.1; /* Increase number 10% */
    > >        while (*pa < d) pa++; /* Search optimal value */

    >
    > Suggestion continued: All expressions in dgra of the form *pa need to
    > be changed to a[pa].
    >
    > >        /* Must be divide by n numbers */
    > >        if (n) {
    > >                if (*pa == 1.5 || *pa == 3.0 || *pa == 6.0)
    > >                        *n = 3; else
    > >                if (*pa == 2.0 || *pa == 4.0 || *pa == 8.0)
    > >                        *n = 4; else
    > >                        *n = 5;
    > >        }

    >
    > Suggestion completed: This entire sequence can then be replace by
    >      if (n)
    >          *n = b[pa];
    >
    > >        return *pa * sign * product;
    > >}

    >
    > >int main(void)
    > >{
    > >        /* Test */
    > >        const double a[] = {112.8, -13.245, 121.5, 27894.0, 0.22452,
    > >463.20, 7094.230, 235.20, 1420.04, 992312.52, 0.0};
    > >        const double *pa = a;
    > >        double d, f;
    > >        int n;

    >
    > >        while (*pa) {
    > >                d = dgra(*pa, &n);
    > >                f = ddiv(d, n);

    >
    > You could replace the call to ddiv with the same one statement that
    > ddiv contains, just change the variable names.  This will eliminate
    > the overhead calling the function.
    >                f = (n == 0.0 ? 0.0 : d/n);
    >
    > >                printf("%f = %f\n", *pa, d);
    > >                while (n >= 0) {
    > >                        printf("\t%f\n", f * n);
    > >                        n--;
    > >                }
    > >                pa++;
    > >        }
    > >        return 0;
    > >}

    >


    Thanks Barry
     
    David RF, May 6, 2012
    #5
  6. David RF

    BartC Guest

    "David RF" <> wrote in message
    news:...

    > const double a[] = {1.25, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0,
    > 7.5, 8.0, 10.0, 12.5};


    > if (*pa == 1.5 || *pa == 3.0 || *pa == 6.0)
    > *n = 3; else
    > if (*pa == 2.0 || *pa == 4.0 || *pa == 8.0)
    > *n = 4; else
    > *n = 5;


    pa always points into the a[] array, and the contents of a[] are fixed? Then
    it might be better to use an index into the array, and use tests such as:

    if (index==1 || index==4 || index==6)

    etc.

    > while (*pa) {
    > d = dgra(*pa, &n);
    > f = ddiv(d, n);
    > printf("%f = %f\n", *pa, d);
    > while (n >= 0) {
    > printf("\t%f\n", f * n);
    > n--;
    > }
    > pa++;
    > }


    Comment out the printf() statements, wrap a loop around it to execute it at
    least a million times (remember to re-initialise pa each time), and find
    some way of timing the code. Then it will be easy to try different things
    and see if they make a difference. Reinstate the printf() statements every
    so often (and disable the outer loop) to check the output is still right.

    --
    Bartc
     
    BartC, May 6, 2012
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?bWFoc2E=?=

    calculate distance

    =?Utf-8?B?bWFoc2E=?=, May 13, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    470
    Dan Brussee
    May 13, 2004
  2. Joey Vendetta
    Replies:
    0
    Views:
    3,508
    Joey Vendetta
    Apr 1, 2004
  3. Stefan
    Replies:
    0
    Views:
    772
    Stefan
    May 6, 2004
  4. Replies:
    0
    Views:
    989
  5. sarah.kidd
    Replies:
    2
    Views:
    167
    Bart Van der Donck
    Apr 14, 2008
Loading...

Share This Page