CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Faster computations

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
evsource



Joined: 21 Nov 2006
Posts: 129

View user's profile Send private message

Faster computations
PostPosted: Tue Nov 10, 2009 11:46 pm     Reply with quote

Hi,

I recently posted about faster computations. I have another question. With divide operations being so expensive, is there a better way to do the following:

x (a constant)
y (a constant)
z (obtained value that varies)

The equation: (x * y) / z

I can calculate ahead of time x * y, since these are constants. But with z being the variable, I can't see any way around the division.

Thanks in advance!
Guest








PostPosted: Wed Nov 11, 2009 6:41 am     Reply with quote

Scott Edwards' Stamp application #9 has an article about using fast integer math which might help, but you'll have to compare with fp package.
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Wed Nov 11, 2009 10:55 am     Reply with quote

But if X and Y are constants, how can Z be anything but constant?

I tried adding this to a program I already had:

Code:


#define X (float)1.234
#define Y (float)5.678

#define Z (float)(X/Y)

//Then later on, in the actual code:

   float zz;

   zz = Z;


This all compiled properly, and the "zz = Z" line generated some plausible looking assembly code. Have I misunderstood the problem?
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Wed Nov 11, 2009 11:28 am     Reply with quote

This issue involves basic math. In a world of numbers multiplication is exact and division is inexact unless the numerator is exactly divisible by the denominator. Now the PIC represents numbers in base 2 so if the divisor is a power of 2 then division reduces to shifting. Most often this isn't the case and can't be arranged by scaling the numerator in which case division becomes a highly optimized subtraction loop with variable timing depending on the relation between the numerator and the denominator. It's the way numbers are we all know from school that division was more laborious than multiplication.
Ken Johnson



Joined: 23 Mar 2006
Posts: 197
Location: Lewisburg, WV

View user's profile Send private message

PostPosted: Wed Nov 11, 2009 3:04 pm     Reply with quote

Your are right, you must divide (somehow).

However, the compiler will compute (x * y) for you - you don't have to explicitly do that.

Ken
Ttelmah
Guest







PostPosted: Wed Nov 11, 2009 4:06 pm     Reply with quote

Let me give you a 'for instance' type example, that shows a way of saving time.

Imagine that you are getting a value from an ADC. Because if comes from a voltage source, that is 0 to 2.5v (say), you decide to scale to value as a floating point number 0-2.5, nd use a floating point division to do so. Then this value actually represents something else (perhaps a flow), so there is a scale factor that has to be applied to this final result. The flow (say) is actually 500l/min, for 1v, and you want to display an output representng the time needed for 1000l to pass. The maths then becomes:
1000/(500*v)
You want to output this in minutes, with two decimal places, so print this float out, with %5.2f

Now, at several points in this, you are making decisions. The initial conversion to a 'voltage' value, and then scaling everything to suit the 'thinking', and final result, rather than the processor.
If you start instead from the other end. You want only 2 decimal places.
v itself started as an integer, 0 to 1023. If you step 'back' from the problem, and look at only the two 'endpoint' numbers, you have:

1023 -> should display 0.8

1 -> 819.2

0 -> impossible

If you multiply by 81920, and perform just an integer division, from the original number, you get:

81920/1023 = 80

81920/1 = 81920

So, if you instead of doing the original conversion to 'volts', and then the scaling, and finally the floating point print:


if (adc_val==0) printf("No flow");
else printf("%6.2Lw",(int32)81920/adc_val);

You get the required result, using int32 divison, rather than float. Typically about 2/3rd the time, and remember this is also saved on the output of every digit to the display, as well as in the original calculation...

Now, this type of 'arithmetic re-thinking', is vital on anything involving speed. Going yet further, if you could work with only one decimal, the same operation could be repeated using int16, with the times improving by a futher factor of four.....

I'd suspect you may well be able to save a lot of time in your application, but it can only be done by knowing what the numbers represent, the likely ranges, and what final accuracy is required.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group