cancel
Showing results for
Show  only  | Search instead for
Did you mean:
Visitor
720 Views
Registered: ‎06-03-2019

## Time taken for execution of trigonometric functions

Hello everyone,

I have a few Interrupt service routines in my C program. Each of these uses math functions, sqrt() and asin(), both a couple of times. I faced some glitches in my code operation but couldn't find the reason until the I measured the total execution time of the ISR. It was 5 us each which is HUGE. I tried to reduce the calculations as much as possible but couldn't reduce this execution time significantly.

Is there a way to optmize the math functions to save time? Or is there any other solution to this issue?

Thank you.

Best regards,

Pramod

Tags (3)
1 Solution

Accepted Solutions
Scholar
597 Views
Registered: ‎04-13-2015

To use loook-up tables you have to remap your input between 0 and N-1 (N being the size of the table, idealy a power of 2).  For asin(), it is the simplest because the input is bounded between -1.0 and +1.0 and asin(-x) == -asin(x). If the input is negative, memo it is and use -x.  The input value is multiplied by N-1, giving you the index in the table.  The larger the table, the more resolution/precision your result will have; you can also interpolate between Idx & Idx+1 using the remainder, i.e. input * (N-1) % 1. Then use - table value if the inpur was -ve.

For sqrt(), the idea is alike, except sqrt(4n) == 2*sqrt(n). By bringing the input between 0. and 4.0-epsilon (memorizing the scaling factor used, divided by 2) you read the table with the index (ScaledInput * N-1) and then apply the scaling factor / 2.

I assume your input and output are integers, if so, then all these manipulations can done with int meaning almost no CPU as they involve shfts and mutiplfy (for sqrt) if you play a bit with the size of the table, or index remapping or special handling when the index would be N. As for how to create the tables, look at what the indexes are vs the value used to determine the index and generate the tables accordingly.

6 Replies
Teacher
707 Views
Registered: ‎07-09-2009
Id suggest that you re look at your interrupt.
For a real time type system one would expect that all the ISR does is makes a note of the interrupt, along with any time stamp or such like,
Doing slow functions such as sqrt or sin, is generally not done in the interrupt, but the main loop.

You are lucky, this sort of interrupt problem is inherent, "whilst your interrupted, you can be missing interrupts", you need to design the system such that this doe snot affect how the system runs, you can not rely upon the interrupt being fast. No matter how fast, with random interrupt,s at some point you are going to have a situation where your in an interrupt and another happens,

Scholar
660 Views
Registered: ‎04-13-2015

I agree with @drjohnsmith for using trigonometrics in an interrupt.. As for your question(s): "Is there a way to optmize the math functions to save time? Or is there any other solution to this issue?". Likely, but more details should be provided.

The ubiquitous solution, if a high precision is not required, is to use look-up tables for these functions. Else, if a high precision is required, then you'll have to get your hands dirty by writing your own, either using low order polynomial approximation or with Cordic iterations using just a few iterations.

Visitor
620 Views
Registered: ‎06-03-2019

Hello @drjohnsmith ,

Thank you for your answer. ISRs in my code are used for control and modulation of a converter as I need to update variables synchronous to all the ISRs. My main loop has bare minimum calculations. There is no way around for me but to make these calculations in these interrupts. I had read that these PL-PS interrupts are queued up until they are executed. Also, I am not worried if I lose a lower priority interrupt but my higher priority interrupt gets executed.

Hello @ericv ,

Could you tell me what more details are needed? I did think of using look-up tables but I had no idea how much faster they are compared to the math functions.

Scholar
598 Views
Registered: ‎04-13-2015

To use loook-up tables you have to remap your input between 0 and N-1 (N being the size of the table, idealy a power of 2).  For asin(), it is the simplest because the input is bounded between -1.0 and +1.0 and asin(-x) == -asin(x). If the input is negative, memo it is and use -x.  The input value is multiplied by N-1, giving you the index in the table.  The larger the table, the more resolution/precision your result will have; you can also interpolate between Idx & Idx+1 using the remainder, i.e. input * (N-1) % 1. Then use - table value if the inpur was -ve.

For sqrt(), the idea is alike, except sqrt(4n) == 2*sqrt(n). By bringing the input between 0. and 4.0-epsilon (memorizing the scaling factor used, divided by 2) you read the table with the index (ScaledInput * N-1) and then apply the scaling factor / 2.

I assume your input and output are integers, if so, then all these manipulations can done with int meaning almost no CPU as they involve shfts and mutiplfy (for sqrt) if you play a bit with the size of the table, or index remapping or special handling when the index would be N. As for how to create the tables, look at what the indexes are vs the value used to determine the index and generate the tables accordingly.

Scholar
585 Views
Registered: ‎04-13-2015

2 corrections for sqrt():

- the scaling factor to apply is sqrt(scaling) and not divided by 2.  sqrt(scaling) is easy to calclated using int because for every >>4 f te input, the scaling factor is incremented by 1 (starting at 1.0).

- the index is scaledinput *(N-1)/4 and not scaldeinput*(N-1) because the entry at N-1 is 4.0.

Visitor
511 Views
Registered: ‎06-03-2019

Thank you Eric. I will try and see if the implementation of look-up tables helps/is necessary.