francof2a / fxpmath

A python library for fractional fixed-point (base 2) arithmetic and binary manipulation with Numpy compatibility.
MIT License
183 stars 21 forks source link

`.like()` seems to fail on complex numbers #58

Closed mousecat98 closed 2 years ago

mousecat98 commented 2 years ago

Hi all, I am facing an issue with fxpmath's .like() functionality. In my case, I perform some fixed-point signal processing using numpy's convolve()-method. Using ordinary datatype definitions, the result is a complex number which is correct. However, using ahead datatype definitions and the .like()-function the resulting number is real-valued.

import numpy as np
from fxpmath import Fxp

# datatype definition
TAP = Fxp(None, dtype='fxp-s32/24-complex')
SIGNAL = Fxp(None, dtype='fxp-s32/24-complex')

# signal
signal = np.array([(1 + 1j), (1 - 1j), (-1 + 1j), (-1 - 1j)], dtype=complex)
signal_fxp = Fxp(signal).like(SIGNAL)
signal_fxp1 = Fxp(signal, dtype='fxp-s32/24-complex')

# generate filter
filt = np.arange(0.1, 0.5, 0.1)
filt_fxp = Fxp(filt).like(TAP)
filt_fxp1 = Fxp(filt, dtype='fxp-s32/24')

# convolve signal and filter
out = np.convolve(signal_fxp, filt_fxp, 'same')
out1 = np.convolve(signal_fxp1, filt_fxp1, 'same')

# debug output
print("Signal FXP")
signal_fxp.info(verbose=3)
signal_fxp1.info(verbose=3)
print(100 * "-")
print("Filter FXP")
filt_fxp.info(verbose=3)
filt_fxp1.info(verbose=3)
print(100 * "-")
print("Output FXP")
out.info(verbose=3)
out1.info(verbose=3)

This code results in the following console output:

Signal FXP
    dtype       =   fxp-s32/24-complex
    Value       =   [ 1.  1. -1. -1.]
    extended_prec   =   True

    Signed      =   True
    Word bits   =   32
    Fract bits  =   24
    Int bits    =   7
    Val data type   =   <class 'float'>

    Upper       =   127.99999994039536
    Lower       =   -128.0
    Precision   =   5.960464477539063e-08
    Overflow    =   saturate
    Rounding    =   trunc
    Shifting    =   expand

    dtype       =   fxp-s32/24-complex
    Value       =   [ 1.+1.j  1.-1.j -1.+1.j -1.-1.j]
    extended_prec   =   True

    Signed      =   True
    Word bits   =   32
    Fract bits  =   24
    Int bits    =   7
    Val data type   =   <class 'complex'>

    Upper       =   127.99999994039536
    Lower       =   -128.0
    Precision   =   5.960464477539063e-08
    Overflow    =   saturate
    Rounding    =   trunc
    Shifting    =   expand

----------------------------------------------------------------------------------------------------
Filter FXP
    dtype       =   fxp-s32/24
    Value       =   [0.09999996 0.19999999 0.29999995 0.39999998]
    inaccuracy  =   True
    extended_prec   =   True

    Signed      =   True
    Word bits   =   32
    Fract bits  =   24
    Int bits    =   7
    Val data type   =   <class 'float'>

    Upper       =   127.99999994039536
    Lower       =   -128.0
    Precision   =   5.960464477539063e-08
    Overflow    =   saturate
    Rounding    =   trunc
    Shifting    =   expand

    dtype       =   fxp-s32/24
    Value       =   [0.09999996 0.19999999 0.29999995 0.39999998]
    inaccuracy  =   True
    extended_prec   =   True

    Signed      =   True
    Word bits   =   32
    Fract bits  =   24
    Int bits    =   7
    Val data type   =   <class 'float'>

    Upper       =   127.99999994039536
    Lower       =   -128.0
    Precision   =   5.960464477539063e-08
    Overflow    =   saturate
    Rounding    =   trunc
    Shifting    =   expand

----------------------------------------------------------------------------------------------------
Output FXP
    dtype       =   fxp-s25/24
    Value       =   [ 0.29999995  0.39999998  0.39999998 -0.09999996]

    Signed      =   True
    Word bits   =   25
    Fract bits  =   24
    Int bits    =   0
    Val data type   =   <class 'float'>

    Upper       =   0.9999999403953552
    Lower       =   -1.0
    Precision   =   5.960464477539063e-08
    Overflow    =   saturate
    Rounding    =   trunc
    Shifting    =   expand

    dtype       =   fxp-s25/24-complex
    Value       =   [ 0.29999995+0.10000002j  0.39999998+0.19999993j  0.39999998+0.20000005j
 -0.09999996-0.30000001j]

    Signed      =   True
    Word bits   =   25
    Fract bits  =   24
    Int bits    =   0
    Val data type   =   <class 'complex'>

    Upper       =   0.9999999403953552
    Lower       =   -1.0
    Precision   =   5.960464477539063e-08
    Overflow    =   saturate
    Rounding    =   trunc
    Shifting    =   expand

Thanks for your help!

francof2a commented 2 years ago

Hello @mousecat98 I can reproduce the error. Thanks for the issue, I'll try to find a solution for that.

I will have news soon.

francof2a commented 2 years ago

I've fix the problem. It was not about like method but using None to initialize the template. As workaround you might try replace None by complex(0) (or even any complex number).

By the way, this is gonna to be fixed in the next release (0.4.6).

Thank you!

francof2a commented 2 years ago

Issue solved in v0.4.6