Skip to content

Commit

Permalink
version 0.4.3
Browse files Browse the repository at this point in the history
* Fxp adds `config` as optional init parameter (kwarg).
* Functions (operators) over one and two variables copy first operator configuration by default.
* Changes above fixed wrap overflowing bug after operation (issue #42 solved).
* Wrap function of utils fix bug when data has more than n_word_max (64 bits in the most of cases) (issue #41 soved).
* Config new methods: copy, deepcopy.
* Fix warning about internal complex check (issue #39).
* Add link implementation between `functions.truediv` with `numpy.divide`.
* Add `axes` parameter to `transpose` method.
  • Loading branch information
francof2a committed Sep 21, 2021
1 parent 59fc284 commit 7ed5cc0
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 10 deletions.
11 changes: 11 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
version 0.4.3
--------------------------------------------------
* Fxp adds `config` as optional init parameter (kwarg).
* Functions (operators) over one and two variables copy first operator configuration by default.
* Changes above fixed wrap overflowing bug after operation (issue #42 solved).
* Wrap function of utils fix bug when data has more than n_word_max (64 bits in the most of cases) (issue #41 soved).
* Config new methods: copy, deepcopy.
* Fix warning about internal complex check (issue #39).
* Add link implementation between `functions.truediv` with `numpy.divide`.
* Add `axes` parameter to `transpose` method.

version 0.4.2
--------------------------------------------------
* Add template to Config object.
Expand Down
2 changes: 1 addition & 1 deletion fxpmath/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '0.4.2'
__version__ = '0.4.3'

import sys
import os
Expand Down
19 changes: 16 additions & 3 deletions fxpmath/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ def _function_over_one_var(repr_func, raw_func, x, out=None, out_like=None, sizi
if not out.signed and signed:
raise ValueError('Signed addition can not be stored in unsigned `out` object!')
n_frac = out.n_frac
config = None

elif out_like is not None:
if not isinstance(out_like, Fxp):
raise TypeError('`out_like` must be a Fxp object!')
Expand All @@ -107,6 +109,10 @@ def _function_over_one_var(repr_func, raw_func, x, out=None, out_like=None, sizi
signed = None
n_frac = None
n_int = None
config = None

else:
config = x.config

if method == 'repr' or x.scaled or n_frac is None:
raw = False
Expand Down Expand Up @@ -141,6 +147,8 @@ def _function_over_two_vars(repr_func, raw_func, x, y, out=None, out_like=None,
if not out.signed and signed:
raise ValueError('Signed addition can not be stored in unsigned `out` object!')
n_frac = out.n_frac
config = None

elif out_like is not None:
if not isinstance(out_like, Fxp):
raise TypeError('`out_like` must be a Fxp object!')
Expand All @@ -149,6 +157,10 @@ def _function_over_two_vars(repr_func, raw_func, x, y, out=None, out_like=None,
signed = None
n_frac = None
n_int = None
config = None

else:
config = x.config

if method == 'repr' or x.scaled or n_frac is None:
raw = False
Expand All @@ -163,7 +175,7 @@ def _function_over_two_vars(repr_func, raw_func, x, y, out=None, out_like=None,
if out is not None:
z = out.set_val(val, raw=raw)
else:
z = Fxp(val, signed=signed, n_int=n_int, n_frac=n_frac, like=out_like, raw=raw)
z = Fxp(val, signed=signed, n_int=n_int, n_frac=n_frac, like=out_like, raw=raw, config=config)

return z

Expand Down Expand Up @@ -374,7 +386,7 @@ def _floordiv_raw(x, y, n_frac):

return _function_over_two_vars(repr_func=_floordiv_repr, raw_func=_floordiv_raw, x=x, y=y, out=out, out_like=out_like, sizing=sizing, method=method, optimal_size=optimal_size, **kwargs)

@implements(np.true_divide)
@implements(np.true_divide, np.divide)
def truediv(x, y, out=None, out_like=None, sizing='optimal', method='raw', **kwargs):
"""
"""
Expand Down Expand Up @@ -572,13 +584,14 @@ def _conjugate_raw(x, n_frac, **kwargs):
return _function_over_one_var(repr_func=np.conjugate, raw_func=_conjugate_raw, x=x, out=out, out_like=out_like, sizing=sizing, method=method, **kwargs)

@implements(np.transpose)
def transpose(x, out=None, out_like=None, sizing='optimal', method='raw', **kwargs):
def transpose(x, axes=None, out=None, out_like=None, sizing='optimal', method='raw', **kwargs):
"""
"""
def _transpose_raw(x, n_frac, **kwargs):
precision_cast = (lambda m: np.array(m, dtype=object)) if n_frac >= _n_word_max else (lambda m: m)
return (x.val.T) * precision_cast(2**(n_frac - x.n_frac))

kwargs['axes'] = axes
return _function_over_one_var(repr_func=np.transpose, raw_func=_transpose_raw, x=x, out=out, out_like=out_like, sizing=sizing, method=method, **kwargs)

@implements(np.clip)
Expand Down
19 changes: 16 additions & 3 deletions fxpmath/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ def __init__(self, val=None, signed=None, n_word=None, n_frac=None, n_int=None,
'inaccuracy': False,
'extended_prec': False}

# update config as argument
_config = kwargs.pop('config', None)
if _config is not None:
if isinstance(_config, Config):
self.config = _config.deepcopy()
else:
raise TypeError('config parameter must be Config class type!')

# update config from kwargs
self.config.update(**kwargs)

Expand Down Expand Up @@ -594,7 +602,7 @@ def set_val(self, val, raw=False, vdtype=None, index=None):
conv_factor = self._get_conv_factor(raw)

# round, saturate and store
if original_vdtype != complex and not np.issubdtype(original_vdtype, complex):
if original_vdtype != complex and not np.issubdtype(original_vdtype, np.complexfloating):
# val_dtype determination
_n_word_max_ = min(_n_word_max, 64)
if np.max(val) >= 2**_n_word_max_ or np.min(val) < -2**_n_word_max_ or self.n_word >= _n_word_max_:
Expand Down Expand Up @@ -1522,15 +1530,15 @@ def T(self):
x.val = x.val.T
return x

def transpose(self, **kwargs):
def transpose(self, axes=None, **kwargs):
from .functions import transpose

out = kwargs.pop('out', self.config.op_out)
out_like = kwargs.pop('out_like', self.config.op_out_like)
sizing = kwargs.pop('sizing', self.config.op_sizing)
method = kwargs.pop('method', self.config.op_method)

return transpose(self, out=out, out_like=out_like, sizing=sizing, method=method, **kwargs)
return transpose(self, axes=axes, out=out, out_like=out_like, sizing=sizing, method=method, **kwargs)

def item(self, *args):
if len(args) > 1:
Expand Down Expand Up @@ -1894,7 +1902,12 @@ def update(self, **kwargs):
if hasattr(self, k):
setattr(self, k, v)

# copy
def copy(self):
return copy.copy(self)

def deepcopy(self):
return copy.deepcopy(self)
# endregion

# ----------------------------------------------------------------------------------------
Expand Down
14 changes: 11 additions & 3 deletions fxpmath/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

#%%
import numpy as np
from . import _n_word_max

#%%
def array_support(func):
Expand Down Expand Up @@ -312,13 +313,20 @@ def int_clip(x, val_min, val_max):
x_clipped = np.array(max(val_min, min(val_max, int(x))))
return x_clipped

def wrap(x, signed, n_word):
def wrap(x, signed, n_word):
if n_word >= _n_word_max:
dtype = object
else:
dtype = int

m = (1 << n_word)
if signed:
x = np.array(x).astype(int) & (m - 1)
x = np.array(x).astype(dtype) & (m - 1)
x = np.asarray(x).astype(dtype)
x = np.where(x < (1 << (n_word-1)), x, x | (-m))
else:
x = np.array(x).astype(int) & (m - 1)
x = np.array(x).astype(dtype) & (m - 1)
x = np.asarray(x).astype(dtype)
return x

def get_sizes_from_dtype(dtype):
Expand Down
12 changes: 12 additions & 0 deletions tests/test_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,15 @@ def test_issue_31_v0_4_0():
q3 = t(0.125*2**3)
assert q3.val.dtype == object
assert q3() == 1.0

def test_issue_41_v0_4_2():
x = Fxp(2, False, 63, 0, overflow='wrap')
y = Fxp(2, False, 64, 0, overflow='wrap')

assert x() == 2
assert y() == 2

def test_issue_42_v0_4_2():
b = Fxp(2, True, 4, 0, overflow='wrap')
assert (b + 8)() == -6.0
assert (b - 8)() == -6.0

0 comments on commit 7ed5cc0

Please sign in to comment.