# Calculate Y axis distance

D

#### David RF

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;
}

S

#### Stefan Ram

David RF said:
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.

B

#### Barry Schwarz

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
f = (n == 0.0 ? 0.0 : d/n);

I

#### Ian Collins

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.
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

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

D

#### David RF

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
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

B

#### BartC

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.