• Forums
• Posts
Latest Posts
Active Posts
Recently Visited
Search Results
• Page Extras
• Forum Themes
• AVR Freaks

### Hot!modulus and angle of fractcomplex variable

Author
Maple
PIC-fan
• Total Posts : 44
• Reward points : 0
• Joined: 2016/03/06 21:42:36
• Location: China
• Status: offline
0

# modulus and angle of fractcomplex variable

Hello everyone! how to get the modulus and angle of fractcomplex variable?
Is there any build-in library functions I can use? if not, would anyone can give me some example? Thx!

Aussie Susan
Super Member
• Total Posts : 3769
• Reward points : 0
• Joined: 2008/08/18 22:20:40
• Location: Melbourne, Australia
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/09/30 19:34:43 (permalink)
+2 (2)
Have a look at that the library code it refers to. You may need to look at some of the 'legacy' libraries on the Microchip web site.
Susan
Maple
PIC-fan
• Total Posts : 44
• Reward points : 0
• Joined: 2016/03/06 21:42:36
• Location: China
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/18 11:12:35 (permalink)
0
I did check the library, and write some code with it, but it takes a loooot of Tcy to get the reult. I just want to see if anyone has better solutions. :)

_Q15 FractCmplx_GetMag(fractcomplex* pX)
{
_Q15 q1, q2;
q1 = _Q15mpy(pX->real, pX->real);
q2 = _Q15mpy(pX->imag, pX->imag);
q2 = _Q15sqrt(q1);
return q2;
}

//range = [-45°, 45°]
_Q15 FractCmplx_GetPha(fractcomplex* pX)
{
_Q15 ret;
if(pX->real > 0)
{
if(pX->imag == 0) ret = 0;
else if(pX->real >= _Q15abs(pX->imag)) //range=[-45°, 45°]
ret = _Q15atanYByX(pX->real, pX->imag);
else ret = 0xffff;
}
else ret = 0xffff;
return ret;
}
vexorg
Senior Member
• Total Posts : 139
• Reward points : 0
• Joined: 2019/09/27 10:59:40
• Location: 0
• Status: online
Re: modulus and angle of fractcomplex variable 2020/10/18 11:23:26 (permalink)
0
Not sure what pic you have, some do have hardware multipliers or an fpu.

You could put a lookup table in for the arctan function to speed that up, depending on the accuracy you want.

Or depending on your range, mutliply everything by 1,000 or 1,000,000 so that you use int functions instead of float function. Again all compromises depending on what's acceptable.
1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/18 11:32:43 (permalink)
+1 (1)
vexorg
Not sure what pic you have, some do have hardware multipliers or an fpu.

OP is using a 16-bit PIC device, which has hardware multipliers and dividers.

You could put a lookup table in for the arctan function to speed that up, depending on the accuracy you want.

Or depending on your range, mutliply everything by 1,000 or 1,000,000 so that you use int functions instead of float function. Again all compromises depending on what's acceptable.

Q15 numbers are fixed point numbers; that is, they are stored and operated upon as regular binary signed integers. <edit> The ALU on these 16-bit devices are made to perform such calculations. </edit>
post edited by 1and0 - 2020/10/18 11:35:58
Maple
PIC-fan
• Total Posts : 44
• Reward points : 0
• Joined: 2016/03/06 21:42:36
• Location: China
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/18 20:05:07 (permalink)
0
vexorg
Not sure what pic you have, some do have hardware multipliers or an fpu.

You could put a lookup table in for the arctan function to speed that up, depending on the accuracy you want.

Or depending on your range, mutliply everything by 1,000 or 1,000,000 so that you use int functions instead of float function. Again all compromises depending on what's acceptable.

The MCU I am using is dsPIC33CK64MP506, it has hardware multiplier but no FPU.
1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/19 06:17:45 (permalink)
+1 (1)
grchy
I did check the library, and write some code with it, but it takes a loooot of Tcy to get the reult. I just want to see if anyone has better solutions. :)

As I said in your other thread, calling function within a function takes cycles. So replace this
`_Q15 FractCmplx_GetMag(fractcomplex* pX){_Q15 q1, q2;q1 = _Q15mpy(pX->real, pX->real);q2 = _Q15mpy(pX->imag, pX->imag);q1 = _Q15add(q1, q2);q2 = _Q15sqrt(q1);return q2;}`

with this
`_Q15 FractCmplx_GetMag(fractcomplex* pX){    volatile register int result asm("A");     _Q15 mag;        result = __builtin_mpy(pX->real, pX->real, NULL, NULL, 0, NULL, NULL, 0);     result = __builtin_mac(result, pX->imag, pX->imag, NULL, NULL, 0, NULL, NULL, 0, 0, 0);     mag = __builtin_sacr(result, 0);    return _Q15sqrt(mag);}`

and replace this
`_Q15 FractCmplx_GetPha(fractcomplex* pX){_Q15 ret;if(pX->real > 0){if(pX->imag == 0) ret = 0;else if(pX->real >= _Q15abs(pX->imag)) //range=[-45°, 45°]ret = _Q15atanYByX(pX->real, pX->imag);else ret = 0xffff;}else ret = 0xffff;return ret;}`

with this
`_Q15 FractCmplx_GetPha(fractcomplex* pX){    _Q15 phase = 0xFFFF, imag;    if (pX->real > 0) {        imag = pX->imag;        if (imag < 0)            imag = -imag;        if (pX->real >= imag) //range=[-45°, 45°]            phase = _Q15atanYByX(pX->real, pX->imag);    }    return phase;}`

1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/19 10:27:53 (permalink)
0
Here's more efficient:
`#define X_AT_45_DEGREE  0x????    // value at 45 degree_Q15 FractCmplx_GetPha(fractcomplex* pX){    _Q15 phase = 0xFFFF;    if (pX->real >= X_AT_45_DEGREE) {  // range=[-45°, 45°]        phase = _Q15atanYByX(pX->real, pX->imag);    }    return phase;}`

Maple
PIC-fan
• Total Posts : 44
• Reward points : 0
• Joined: 2016/03/06 21:42:36
• Location: China
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/19 21:04:34 (permalink)
0
A Marco? I don't think it will work, 'cause  the value @45° is not a constant both for pX->real and pX->imag...
maybe like this ? :
if ((pX->real & 0x7fff) >= (pX->imag & 0x7fff)) {  // range=[-45°, 45°]
phase = _Q15atanYByX(pX->real, pX->imag);
}
1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/19 21:32:08 (permalink)
0
Arggg... I was thinking of a unity circle. What are the value ranges of pX->real and pX->imag? I presume it is 16-bit signed values, correct?

post edited by 1and0 - 2020/10/19 21:35:20
1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/19 21:40:09 (permalink)
0
grchy
A Marco? I don't think it will work, 'cause  the value @45° is not a constant both for pX->real and pX->imag...
maybe like this ? :
if ((pX->real & 0x7fff) >= (pX->imag & 0x7fff)) {  // range=[-45°, 45°]
phase = _Q15atanYByX(pX->real, pX->imag);
}

If pX->real is masked with 0x7FFF, then it can be outside the range of [-45°, 45°]. I'll assume bit 15 is the sign bit, so it should be this:
`    if (pX->real >= (px->imag & 0x7FFF) {  // range=[-45°, 45°]        phase = _Q15atanYByX(pX->real, pX->imag);    } `

On second thought, that will not work since it is not a negate. So go back to Post #7 with the absolute value.
post edited by 1and0 - 2020/10/19 22:04:57
Maple
PIC-fan
• Total Posts : 44
• Reward points : 0
• Joined: 2016/03/06 21:42:36
• Location: China
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/19 22:08:48 (permalink)
0
Actually X is the result of some DFT algorithm, not a unit circle.
since  pX->real is Q15 format data, I think pX->real & 0x7fff = abs(pX->real), isn't it?
As long as abs(pX->real) >= abs(pX->imag), the angle will fall into -45 ~ 45
1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/19 22:24:53 (permalink)
0
grchy
since  pX->real is Q15 format data, I think pX->real & 0x7fff = abs(pX->real), isn't it?
As long as abs(pX->real) >= abs(pX->imag), the angle will fall into -45 ~ 45

Don't think so.

+0.25 @ Q15 = 0x2000
-0.25 @ Q15 = 0xE000

<edit> In my Posts #10 and #11, I forgot for a moment it is Q15 format. ;)

post edited by 1and0 - 2020/10/19 22:50:34
Maple
PIC-fan
• Total Posts : 44
• Reward points : 0
• Joined: 2016/03/06 21:42:36
• Location: China
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/20 00:33:42 (permalink)
0
Ah!!! You are right, I should use the built-in function "_Q15 _Q15abs(_Q15);" not "&0x7FFF"
1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/20 01:18:02 (permalink)
+1 (1)
grchy
Ah!!! You are right, I should use the built-in function "_Q15 _Q15abs(_Q15);" not "&0x7FFF"

Like I said, since you complainted of speed, avoid calling function since RCALL and RETURN take lot of cycles on a dsPIC33C, which the code in my Post #7 does.

Here's the disassembly for _Q15abs():
`000002fe <__Q15abs>: 2fe:    00 f0 a7        btsc.w    w0, #0xf 300:    00 00 ea        neg.w     w0, w0 302:    00 f0 a7        btsc.w    w0, #0xf 304:    00 80 ea        com.w     w0, w0 306:    00 00 06        return`

What are the BTSC/COM instructions for? Am I miss something?
du00000001
Just Some Member
• Total Posts : 3974
• Reward points : 0
• Joined: 2016/05/03 13:52:42
• Location: Germany
• Status: online
Re: modulus and angle of fractcomplex variable 2020/10/20 01:48:42 (permalink)
0
1and0
<...snipped…>

Here's the disassembly for _Q15abs():
`000002fe <__Q15abs>: 2fe:    00 f0 a7        btsc.w    w0, #0xf 300:    00 00 ea        neg.w     w0, w0 302:    00 f0 a7        btsc.w    w0, #0xf 304:    00 80 ea        com.w     w0, w0 306:    00 00 06        return`

What are the BTSC/COM instructions for? Am I miss something?

@ 1and0
Welcome to the club !
What is abx(x) basically ?
x   if x is positive
-x  if x is negative

btxc  tests for the sign bit, skipping the negation if x is w is already positive.

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/20 04:58:56 (permalink)
0
`000002fe <__Q15abs>: 2fe:    00 f0 a7        btsc.w    w0, #0xf  ; if x is positive, skip and skip 300:    00 00 ea        neg.w     w0, w0    ; negate -x to a positive x 302:    00 f0 a7        btsc.w    w0, #0xf  ; this will always skip ! 304:    00 80 ea        com.w     w0, w0    ; WTF is this doing ? 306:    00 00 06        return`

du00000001
Just Some Member
• Total Posts : 3974
• Reward points : 0
• Joined: 2016/05/03 13:52:42
• Location: Germany
• Status: online
Re: modulus and angle of fractcomplex variable 2020/10/20 13:34:25 (permalink)
0
@ 1and0
Seems the last 2 lines provide an opportunity for speed optimizations.
That is: provided there's not another library call to   __Q15abs + 4   (= 302)
In this case the tradeoff between space and speed might have been decided in favor of space (sparing one return).

I'm not that familiar with dsPIC33 assembly: is "com" to be understood as "complement" ?

PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/20 16:49:16 (permalink)
0
du00000001
Seems the last 2 lines provide an opportunity for speed optimizations.
That is: provided there's not another library call to   __Q15abs + 4   (= 302)
In this case the tradeoff between space and speed might have been decided in favor of space (sparing one return).

You choose kinder words for the writer of this Q15 library than I would have. ;) A saving of one program memory word for a RETURN in this function will cost lot more program memory words for the epilogue and prologue of calling this function. Seriously, I very much doubt that is the case. A sensible approach would be to inline this function of only two instructions.

I'm not that familiar with dsPIC33 assembly: is "com" to be understood as "complement" ?

The COM instruction is one's complement. How many uses are there for such snippet function? ;)
`int fubar(int foo){  if (foo < 0)    foo = ~foo;  return foo;}`

post edited by 1and0 - 2020/10/20 16:55:57
1and0
Access is Denied
• Total Posts : 11320
• Reward points : 0
• Joined: 2007/05/06 12:03:20
• Location: Harry's Gray Matter
• Status: offline
Re: modulus and angle of fractcomplex variable 2020/10/21 06:23:02 (permalink)
0
For the assembly challenged readers, here's it in C:
`_Q15 _Q15abs(_Q15 foo){  if (foo < 0)    foo = -foo;  if (foo < 0)    foo = ~foo;  return foo;}`

post edited by 1and0 - 2020/10/21 07:10:50