News:

Let's find out together what makes a PIC Tick!

Main Menu

Exponentiation???

Started by dr-zin, Apr 05, 2021, 09:04 PM

Previous topic - Next topic

dr-zin

Greetings.  A quick question:  I just noticed (after 12+ years of using this compiler) that there doesn't seem to be a way to raise numbers to a power (e.g. 3^^4 = 81).  Am I missing something or daft (or both)?  I see the "^" symbol is used for a bit-wise operation, but is there a command, routine or tip to do integer exponentiation without using iterative loops?  Any pointers would be appreciated.  Thanks!

top204

#1
Take a look at the compiler's Exp function and its Pow function, or create a procedure that will do it with the range of variables that will be used in it. Below is an integer "Power Of" procedure that uses 32-bit Dword variables, but if smaller "Powers Of" are required these can be converted to 24-bit Long variables or 16-bit Word variables etc... The problem with all "Power Of" routines  is that even using 32-bit variables, they can run out of room as the variable being multiplied by itself many times will overflow rather quickly. If larger values are to be used, switch to a PIC24 or dsPIC33 device and use 64-bit floating point and dPow or dExp.

'-------------------------------------------------------------
' 32-bit Integer Power Of
' Input     : pBase holds the value to calculate the power of
'           : pExp holds the power of value
' Output    : Returns the result of pBase to the power of pExp
' Notes     : None
'
Proc iPow(pBase As Dword, pExp As Dword), Dword
    Result = 1
    Do
        If pExp.0 = 1 Then
            Result = Result * pBase
        EndIf
        pExp = pExp >> 1
        If pExp = 0 Then
            Break
        EndIf
        pBase = pBase * pBase
    Loop
EndProc
   
'---------------------------------------------------------------------------------
Main:
    Wordout = iPow(9, 3)

If using smaller values for the parameters, reduce the size of the varables used within the procedure, and this will make it both smaller and faster.

That's the flexability of the compilers. :-)

dr-zin

Thank you so much for the quick reply and advice.  I was looking into this 3-4 weeks ago (when the old site was in the twilight zone).  I did research the function section, but both the Pow and Exp commands were not precisely what I could use (I'm using a 14-bit device, so Pow is out).  I am aware that I can compute these values as needed using loop structures, and your example would work perfectly BTW, but I thought there might be some overlooked tweek that everyone else knows but me for computing these "on the fly" with one line.  With a subroutine/procedure, I suppose I can, and shouldn't get too greedy for easy answers...

I was trying to compute the sequence 1, 3, 7, 15, etc. up to 255, and 2^^x-1, where x is an integer from 1 to 8 would work nicely.  I can solve it iteratively, or with so few predefined values, I can (and did) just store these values to be used as needed.  Now that I "rediscovered" the forum, I was just fishing around for the brilliant generalized solution for this problem.  I guess it is to get a 16-bit chip and use the Pow function.

Thanks again for the swift and helpful reply.  Cheers

top204

#3
The only way to perform a fast "Power Of" procedure without loop iterations is to store fixed values in a flash memory table, then use the pExp value as the index to the table. However, that will only suffice for known values.

top204

#4
Here's another "Power Of" procedure, but this one does not use multiplication. On a 14-bit core device it may be a little faster because they do not have hardware multiply within them.

'---------------------------------------------------------------------------------
' 32-bit Integer Power Of using additions only
' Input     : pBase holds the value to calculate the power of
'           : pExp holds the power of value
' Output    : Returns the result of pBase to the power of pExp
' Notes     : pBase and and pExp must be values greater than 0
'
Proc iPow32(pBase As Dword, pExp As Word), Dword
    Dim wLoop1 As Word
    Dim dLoop2 As Dword
    Dim dTemp As Dword

    If pExp = 0 Then
        Result = 1
    Else   
        dTemp = pBase
        Result = pBase
        For wLoop1 = 1 To pExp - 1
            For dLoop2 = 1 To pBase - 1
                Result = Result + dTemp
            Next
            dTemp = Result
        Next
    EndIf
EndProc

If using smaller values for the parameters and the result of the procedure, reduce the size of the varables used within the procedure, and this will make it both smaller and faster.

dr-zin

Cool!  The good info. just keeps flowing in.  Yes, I think the lookup/lookdown table structures of Proton Basic are some of its most powerful and overlooked features.  I use them for storing nonlinear conversion data for sensors to determine approximate values, then interpolate to home in on "exact" values.  They provide a compact way to store hundreds of data points and code much easier than Select...Case structures.  Data tables also avoid ugly, resource draining 3rd order calculations that lighter featured PICs can't do anyway.  Any time I can use them is a win in my book!