fixedpoint 1.0.1 Package Documentation¶
Release 1.0.1
The fixedpoint package offers several features that are widely used in DSP applications:
Generate fixed point numbers from string literals, integers, or floating point numbers.
Specify bit widths and signedness, or allow it to be deduced
Various rounding methods
Various overflow handling methods
Configurable alerts for overflow, property mismatches, and implicit casting errors
Arithmetic operations such as addition, subtraction, multiplication, exponentiation
Bitwise operations AND, OR, XOR, and inversion.
Built-in string formatting (f-strings or
str.format()
)Comparisons with other
FixedPoint
,int
, orfloat
objects
The fixedpoint package is unit-tested against MATLAB stimulus (with the fixed
point toolbox), making the fixedpoint
package a viable, accurate, and
cost-free alternative to MATLAB.
Installation¶
The fixedpoint
package is available on PyPI. You can install with pip:
pip install -U fixedpoint
The -U
will install and/or update to the latest version.
Useful Links¶
Table of Contents¶
Fixed Point Basics¶
A FixedPoint
object consists of:
A distinct number of bits
A distinct binary point position within those bits
to the left of the binary point are integer bits
to the right of the binary point are fractional bits
Properties that govern interactions with other built-in and
FixedPoint
objects
Q Format¶
The fixedpoint
module utilizes the
“Q-format notation”
to describe the word length and binary point position:
Qm.n represents a signed fixed point number with m integer bits and n fractional bits (that is, m + n total bits). The most significant bit has a negative weight.
UQm.n represents an unsigned fixed point number with m integer bits and n fractional bits (that is, m + n total bits). The most significant bit has a positive weight.
Furthermore:
Negative m or n is not allowed.
Total word length (m + n) must be positive.
Signed numbers must have m greater than 0, while unsigned numbers can have m equal to 0, as long as total word length is positive.
n can be 0 as long as total word length is positive.
Any deviation from the above specifications constitutes an invalid Q format.
Warning
Some notations reverse m and n. Some notations use A and U to represent signed and unsinged numbers, respectively. Some notations do not include the sign bit in the integer bits.
It is important to understand the Q format utilized by fixedpoint
because there are various formats in use throughout the industry.
The FixedPoint Class¶
Examples are just a click away
Boxes like this link to example code.
Jump to Section
-
class
fixedpoint.
FixedPoint
(init, /, signed=None, m=None, n=None, *, overflow='clamp', rounding='auto', overflow_alert='error', implicit_cast_alert='warning', mismatch_alert='warning', str_base=16)¶ - Parameters
init (float or int or str or FixedPoint) – Initial value. This argument is required and positional, meaning it cannot be keyworded and must come first in the list of arguments.
signed (bool) – Signedness, part of the Q format specification. When left unspecified,
sign()
is used to deduce signedness. This argument can be keyworded.m (int) – Number of integer bits, part of the Q format specification. When left unspecified,
min_m()
is used to deduce initial integer bit width, after whichtrim()
is used after rounding to minimize integer bits. This argument can be keyworded.n (int) – Number of fractional bits, part of the Q format specification. When left unspecified,
min_n()
is used to deduce fractional bit width. This argument can be keyworded.overflow (str) –
Specifies what shall happen when the value overflows its integer bit width. Valid options are:
'clamp'
(default when left unspecified)'wrap'
rounding (str) –
Specifies how superfluous fractional bits are rounded away. Valid options are:
'convergent'
(default for signed when left unspecified)'nearest'
(default for unsigned when left unspecified)'in'
'out'
'up'
'down'
overflow_alert (str) –
Specifies the notification scheme when overflow occurs. Valid options are:
'error'
(default when left unspecified)'warning'
'ignore'
mismatch_alert (str) –
Specifies the notification scheme when 2 FixedPoints with non-matching properties undergo arithmetic. Valid options are:
'error'
'warning'
(default when left unspecified)'ignore'
implicit_cast_alert (str) –
Specifies the notification scheme when implicit casting is performed and the resultant FixedPoint is not valued the same as the original number. Valid options are:
'error'
'warning'
(default when left unspecified)'ignore'
str_base (int) –
Casting a FixedPoint to a str generates a bit string in the base specified by str_base. Valid options are:
16
(default when left unspecified)10
8
2
- Raises
if init is a str and any of signed, m, or n are not specified.
if more than m + n bits are present in init (when init is a str).
if an invalid Q format is specified.
TypeError – if init is not an int, float, str, or FixedPoint and cannot be cast to a float.
FixedPointOverflowError – if overflow_alert is
'error'
and m is too small to represent init.
Jump to Examples
-
from_int
(val)¶ - Parameters
val (int) – Value to set the
FixedPoint
to.
Set the value of the
FixedPoint
from an integer value. Affects only integer bits (since integer require no fractional bits). Must fit into the Q format already designated by the object, otherwise overflow will occur.Jump to Examples
-
from_float
(val)¶ - Parameters
val (float) – Value to set the
FixedPoint
to.
Set the value of the
FixedPoint
. Must fit into the Q format already designated by the object, otherwise rounding and/or overflow will occur.Jump to Examples
-
from_string
(val)¶ -
from_str
(val)¶ - Parameters
val (str) – Value to set the
FixedPoint
bits to.
Directly set the bits of the
FixedPoint
, using the Q format already designated by the object. May be a decimal, binary, octal, or hexadecimal string, the latter three of which require a'0b'
,'0o'
, or'0x'
radix, respectively.Jump to Examples
FixedPoint Properties
-
signed
¶ - Type
- Getter
True for signed, False for unsigned.
- Setter
Set signedness.
- Raises
FixedPointOverflowError – Fixed point value changes from negative to positive or positive to negative (raised only when
overflow_alert
is'error'
).FixedPointError – Changing to True with 0 integer bits.
Change signedness of number. Note that if the MSb is 0, the value of the number will not change. Overflow occurs if the MSb is 1.
-
m
¶ - Type
- Getter
Number of integer bits in the
FixedPoint
number.- Setter
Set the number of integer bits in the
FixedPoint
number.- Raises
FixedPointOverflowError – New value for m is smaller than needed to represent the current
FixedPoint
value (raised only whenoverflow_alert
is'error'
).ValueError – Invalid Q format
When the number of integer bits increases, sign extension occurs for signed numbers, and 0-padding occurs for unsigned numbers. When then number of integer bits decreases, overflow handling may occur (per the
overflow
property) if theFixedPoint
value is too large for the new integer bit width.
-
n
¶ - Type
- Getter
Number of fractional bits in the
FixedPoint
number.- Setter
Set the number of fractional bits in the
FixedPoint
number.- Raises
FixedPointOverflowError – Number of fractional bits causes rounding (per the
rounding
property) which induces overflow (raised only whenoverflow_alert
is'error'
).
When the number of fractional bits increases, 0s are appended to the fixed point number. When the number of fractional bits decreases, rounding may occur (per the
rounding
property), which in turn may cause overflow (per theoverflow
property) if the integer portion of the rounded result is too large to fit within the current integer bit width.
-
str_base
¶ - Type
- Getter
Base of the string generated by
str
.- Setter
Set the base of the string generated by
str
.
Using the builtin python
str
function on aFixedPoint
casts the object to a string. The string is the bits of theFixedPoint
number in the base specified bystr_base
, but without the radix. Must be one of:16
10
8
2
Jump to Examples
-
overflow
¶ -
Overflow occurs when the number of bits required to represent a value exceeds the number of integer bits available (
m
). Theoverflow
property of aFixedPoint
specifies how to handle overflow. Must be one of:'clamp'
'wrap'
Jump to Examples
-
rounding
¶ -
Rounding occurs when fractional bits must be removed from the object. Some rounding schemes can cause overflow in certain circumstances. Must be one of:
'convergent'
'nearest'
'in'
'out'
'up'
'down'
Jump to Examples
-
overflow_alert
¶ - Type
- Getter
The current
overflow_alert
scheme.- Setter
Set the
overflow_alert
scheme.
When overflow occurs, the
overflow_alert
property indicates how you are notified. Must be one of:'error'
'warning'
'ignore'
Jump to Examples
-
mismatch_alert
¶ - Type
- Getter
The current
mismatch_alert
scheme.- Setter
Set the
mismatch_alert
scheme.
When 2
FixedPoint
s interact to create anotherFixedPoint
, the properties assigned to the new object must be resolved from the 2 original objects. Whenever properties between these 2 objects do not match, themismatch_alert
property indicates how you are notified. Must be one of:'warning'
'error'
'ignore'
Jump to Examples
-
implicit_cast_alert
¶ - Type
- Getter
The current
implicit_cast_alert
scheme.- Setter
Set the
implicit_cast_alert
scheme.
Some operations allow a
FixedPoint
to interact with another object that is not aFixedPoint
. Typically, the other object will need to be cast to aFixedPoint
, and is done so internally in the class method. If error exists after the cast toFixedPoint
, theimplicit_cast_alert
property indicates how you are notified. Must be one of:'warning'
'error'
'ignore'
Jump to Examples
-
bits
¶ - Type
- Getter
Bits of the fixed point number.
This is the read-only bits of the
FixedPoint
, stored as an integer.Indexing, slicing, and mapping is available with the
FixedPointBits
class.Jump to Examples
-
bitmask
¶ - Type
- Getter
Bitmask of the
FixedPoint
number.
Integer bitmask, equivalent to \(2^{m + n} - 1\).
-
clamped
¶ - Type
- Getter
True if the value of the
FixedPoint
number is equal to it minimum or maximum value. False otherwise.
-
qformat
¶ - Type
- Getter
Q format of the
FixedPoint
number.
The string takes the form UQm.n, where:
U is only present for unsigned numbers
m is the number of integer bits
n is the number of fractional bits
Arithmetic Operators
-
__add__
(augend)¶ -
__iadd__
(augned)¶ -
__radd__
(addend)¶ Note
These are the
+
and+=
operators.- Parameters
addend (FixedPoint or int or float) – addition term
augend (FixedPoint or int or float) – addition term
- Returns
Sum of addend and augend
- Return type
- Raises
ImplicitCastError – if the addend or augend argument cannot be cast to a
FixedPoint
without error.MismatchError – if any addend or augend properties do not match, and either of their
mismatch_alert
properties is'error'
.
Note
\(\it{sum} = \it{addend} + \it{augend}\)
Addition using the
+
and+=
operators are full precision; bit growth will occur:If both augend or addend are unsigned, the result is unsigned, otherwise the result will be signed.
Jump to Examples
-
__sub__
(subtrahend)¶ -
__isub__
(subtrahend)¶ -
__rsub__
(minuend)¶ Note
These are the
-
and-=
operators.- Parameters
minuend (FixedPoint or int or float) – subtraction term
subtrahend (FixedPoint or int or float) – subtraction term
- Returns
Difference of minuend and subtrahend
- Return type
- Raises
ImplicitCastError – if the minuend or subtrahend argument cannot be cast to a
FixedPoint
without error.FixedPointOverflowError – Subtrahend > minuend and both terms are unsigned.
MismatchError – if any minuend or subtrahend properties do not match, and either of their
mismatch_alert
properties is'error'
.
Note
\(\it{difference} = \it{minuend} - \it{subtrahend}\)
Subtraction using the
-
and-=
operators are full precision; bit growth will occur.If both minuend or subtrahend are unsigned, the result is unsigned, otherwise the result will be signed.
Overflow can occur for unsigned subtraction.
Jump to Examples
-
__mul__
(multiplier)¶ -
__imul__
(multiplier)¶ -
__rmul__
(multiplicand)¶ Note
These are the
*
and*=
operators.- Parameters
multiplier (FixedPoint or int or float) – multiplication term
multiplicand (FixedPoint or int or float) – multiplication term
- Returns
Product of multiplicand and multiplier
- Return type
- Raises
ImplicitCastError – if the addend or augend argument cannot be cast to a
FixedPoint
without error.MismatchError – if any multiplicand or multiplier properties do not match, and either of their
mismatch_alert
properties is'error'
.
Note
\(\it{product} = \it{multiplicand} \times \it{multiplier}\)
Multiplication using the
*
and*=
operators are full precision; bit growth will occur.If both multiplicand or multiplier are unsigned, the result is unsigned, otherwise the result will be signed.
Jump to Examples
-
__pow__
(exponent)¶ -
__ipow__
(exponent)¶ Note
These are the
**
and**=
operators.- Parameters
exponent (int) – The exponent to the
FixedPoint
base. Must be positive.- Returns
Result of the base raised to the exponent power.
- Return type
Note
\(\it{result} = \it{base}^{\it{exponent}}\)
Exponentiation using the
**
and**=
operators are full precision; bit growth will occur.The result has the same signedness as the base.
Only positive integers are supported as the exponent.
Jump to Examples
Comparison Operators
-
__lt__
(other)¶ -
__le__
(other)¶ -
__gt__
(other)¶ -
__ge__
(other)¶ -
__eq__
(other)¶ -
__ne__
(other)¶ Note
These are the
<
,<=
,>
,>=
,==
and!=
operators.- Parameters
other (FixedPoint or int or float) – Numeric object to compare to
- Returns
True if the comparison is true, False otherwise
- Return type
-
__cmp__
(other)¶ - Parameters
other (FixedPoint or int or float) – Numeric object to compare to
- Returns
a negative number if the object is < other
0 if the object == other
a positive number if the object is > other
- Return type
Generic comparison object. Not used for comparisons in python 3 but used internally by all other comparisons.
Bitwise Operators
-
__lshift__
(nbits)¶ -
__ilshift__
(nbits)¶ Note
These are the
<<
and<<=
operators.- Parameters
nbits (int) – Number of bits to shift left.
- Return type
Bit shifting does not change the
FixedPoint
’s Q format. The nbits leftmost bits are discarded.To keep bits after shifting, multiply the object by \(2^{nbits}\) instead of using the
<<
or<<=
operator.If nbits < 0, bits are shifted right using
>>
or>>=
byabs(nbits)
instead.Jump to Examples
-
__rshift__
(nbits)¶ -
__irshift__
(nbits)¶ Note
These are the
>>
and>>=
operators.- Parameters
nbits (int) – Number of bits to shift right.
- Returns
Original
FixedPoint
with bits shifted right.- Return type
Bit shifting does not change the
FixedPoint
’s Q format. The nbits rightmost bits are discarded.To keep bits after shifting, multiply the object by \(2^{-nbits}\) instead of using the
>>
or>>=
operator.For signed numbers, sign extension occurs.
If nbits < 0, bits are shifted right using
<<
or<<=
byabs(nbits)
instead.Jump to Examples
-
__and__
(other)¶ -
__iand__
(other)¶ -
__rand__
(other)¶ Note
These are the
&
and&=
operators.- Parameters
other (int or FixedPoint) – Object to bitwise AND with
- Returns
Original object’s bits bitwise ANDed with other’s bits.
- Return type
When ANDing 2
FixedPoint
s, the binary point is not aligned.After ANDing, the result is masked with the leftmost
FixedPoint.bitmask
and assigned to thebits
of the return value.Jump to Examples
-
__or__
(other)¶ -
__ior__
(other)¶ -
__ror__
(other)¶ Note
These are the
|
and|=
operators.- Parameters
other (int or FixedPoint) – Object to bitwise OR with
- Returns
Original object’s bits bitwise ORed with other’s bits.
- Return type
When ORing 2
FixedPoint
s, the binary point is not aligned.After ORing, the result is masked with the leftmost
FixedPoint.bitmask
and assigned to thebits
of the return value.Jump to Examples
-
__xor__
(other)¶ -
__ixor__
(other)¶ -
__rxor__
(other)¶ Note
These are the
^
and^=
operators.- Parameters
other (int or FixedPoint) – Object to bitwise XOR with
- Returns
Original object’s bits bitwise XORed with other’s bits.
- Return type
When XORing 2
FixedPoint
s, the binary point is not aligned.After XORing, the result is masked with the leftmost
FixedPoint.bitmask
and assigned to thebits
of the return value.Jump to Examples
Unary Operators
-
__invert__
()¶ Note
This is the unary
~
operator.- Returns
Copy of original object with bits inverted.
- Return type
Jump to Examples
-
__pos__
()¶ Note
This is the unary
+
operator.- Returns
Copy of original object.
- Return type
-
__neg__
()¶ Note
This is the unary
-
operator.- Returns
Negated copy of original object negated.
- Return type
- Raises
FixedPointError – if unsigned number is negated.
FixedPointOverflowError – if the negative value is larger than the Q format allows (raised only if
overflow_alert
is'error'
).
In an attempt to minimize user error, unsigned numbers cannot be negated. The idea is that you should be doing this very intentionally.
Jump to Examples
Built-in Function Support
-
__abs__
()¶ Note
This is the built-in
abs()
function.- Returns
Absolute value.
- Return type
- Raises
FixedPointOverflowError – if the absolute value of a negative-valued number is larger than the Q format allows (raised only if
overflow_alert
is'error'
).
Signedness does not change.
Jump to Examples
-
__int__
()¶ Note
This is the built-in
int
function.- Returns
Only the integer bits of the
FixedPoint
number.- Return type
Fractional bits are ignored, which is the same as rounding down.
-
__float__
()¶ Note
This is the built-in
float
function.- Returns
Floating point cast of the
FixedPoint
number.- Return type
When casting to a float would result in an
OverflowError
,float('inf')
orfloat('-inf')
is returned instead.Warning
A typical Python
float
follows IEEE 754 double-precision format, which means there’s 52 mantissa bits and a sign bit (you can verify this by examiningsys.float_info
). Thus forFixedPoint
word lengths beyond 52 bits, thefloat
cast may lose precision or resolution.
-
__bool__
()¶ Note
This is the built-in
bool
function.- Returns
False if
FixedPoint.bits
are non-zero, True otherwise.- Return type
-
__index__
()¶ -
- Returns
Bits of the
FixedPoint
number.- Return type
Calling
hex()
,oct()
, orbin()
on aFixedPoint
generates astr
with theFixedPoint.bits
represented as a hexadecimal, octal, or binary string. The radix prepends thebits
, which do not contain any left-padded zeros.
-
__str__
()¶ Note
This is the built-in
str
function.- Returns
Bits of the
FixedPoint
number, left padded to the number of bits in the number, in the base specified by thestr_base
property.- Return type
Calling
str()
will generate a hexadecimal, octal, or binary string (according to thestr_base
property setting) without the radix, and 0-padded to the actual bit width of theFixedPoint
number. Decimal strings are not 0-padded.This string represents the bits of the number, thus will always be non-negative.
Signedness does not change.
Jump to Examples
-
__format__
()¶ Note
This is the built-in
str.format()
andformat()
function, and also applies to f-strings.- Returns
Formatted string, various formats available.
- Return type
A
FixedPoint
can be formatted as astr
,float
, orint
would, depending on the format string syntax.Standard Format Specifier Parsing Summary¶ format_spec
type
Formatted Type
Formatted Value(givenx = FixedPoint(...)
)'s'
str(x)
(depends onx.str_base
)'q'
x.qformat
'b'
(binary)x.bits
'd'
(decimal)'o'
(octal)'x'
(lowercasehexadecimal)'X'
(uppercasehexadecimal)'...m'
1x.bits['int']
(integer bits only)'...n'
1x.bits['frac']
(fractional bits only)'e'
float(x)
'E'
'f'
'F'
'g'
'G'
'%'
1 Append to the specifier of another formatted
int
. E.g.,'bn'
would format the fractional bits ofx
in binary.Jump to Examples
-
__len__
()¶ Note
This is the built-in
len()
function..- Returns
Number of bits in the
FixedPoint
.- Return type
-
__repr__
()¶ Note
This is the built-in
repr()
function, which is also the output shown when aFixedPoint
is not assigned to a variable.This generates a code string that will exactly reproduce the
FixedPoint
’s value and properties.
Bit Resizing Methods
-
resize
(m, n, /, rounding=None, overflow=None, alert=None)¶ - Parameters
m (int) – Number of integer bits to resize to.
n (int) – Number of fractional bits to resize to
rounding (str) – Temporary
rounding
scheme to use. Can be keyworded.overflow (str) – Temporary
overflow
scheme to use. Can be keyworded.alert (str) – Temporary
overflow_alert
scheme to use. Can be keyworded.
- Raises
FixedPointOverflowError – if resizing causes overflow (raised only if alert - or
overflow_alert
if alert is not specified - is'error'
).
Fractional bits are resized first, them integer bits. Bit sizes can grow or shrink from their current value.
Rounding, overflow handling, and overflow alert notification severity can be temporarily modified within the scope of this method. I.e., specifying the rounding, overflow, or alert arguments will only take effect within this method; it will not permanently change the property settings of the object. If left unspecified, the current property setting is used.
Jump to Examples
-
trim
(ints=None, fracs=None)¶ - Parameters
Trims off excess bits, including:
Resultant Q format is always valid. For the
FixedPoint
value of 0, resulting Q format is [U]Q1.0.Opt to trim off only fractional bits or only integer bits by setting fracs or ints, respectively, to True. When left unspecified, both integer and fractional bits are trimmed.
Jump to Examples
Rounding Methods
-
__round__
(n)¶ Note
This is the built-in
round()
function.- Parameters
n (int) – Number of bits remaining after round
- Returns
A copy of the
FixedPoint
rounded to n bits.- Return type
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if the
overflow_alert
property setting is'error'
).
Rounds a copy of the
FixedPoint
using the rounding scheme specified by therounding
property setting.Refer to
FixedPoint.resize()
for more details.Jump to Examples
-
__floor__
()¶ Note
This is the built-in
math.floor()
function. It does not modify the object given to it, but creates a copy and operates on it instead.- Return type
Rounds to the integer closest to \(-\infty\), but does not modify the fractional bit width.
Jump to Examples
-
__ceil__
()¶ Note
This is the built-in
math.ceil()
function. It does not modify the object given to it, but creates a copy and operates on it instead.- Return type
- RaisesFixedPointOverflowError
if the integer value of the
FixedPoint
is already at its maximum possible value (raised only ifoverflow_alert
is'error'
)
Rounds to the integer closest to \(+\infty\), leaving 0 fractional bits. For values other than 0, this requires
m
to be non-zero.Jump to Examples
-
__trunc__
()¶ Note
This is the built-in
math.trunc()
function. It does not modify the object given to it, but creates a copy and operates on it instead.- Return type
Rounds to the integer closest to \(-\infty\), leaving 0 fractional bits. If
m
is 0, it is changed to 1, otherwisem
is not modified.Jump to Examples
-
round
(n)¶ - Parameters
n (int) – Number of fractional bits remaining after rounding
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if
overflow_alert
is'error'
)
Rounds the
FixedPoint
using the rounding scheme specified by therounding
property setting.
-
convergent
(n)¶ -
round_convergent
(n)¶ - Parameters
n (int) – Number of fractional bits remaining after rounding
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if
overflow_alert
is'error'
)
Rounds to n fractional bits, biased toward the nearest value with ties rounding to the nearest even value.
Jump to Examples
-
round_nearest
(n)¶ - Parameters
n (int) – Number of fractional bits remaining after rounding
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if
overflow_alert
is'error'
)
Rounds the
FixedPoint
to n fractional bits, biased toward the nearest value with ties rounding to \(+\infty\).Jump to Examples
-
round_in
(n)¶ - Parameters
n (int) – Number of fractional bits remaining after rounding
Rounds the
FixedPoint
to n fractional bits toward 0.Jump to Examples
-
round_out
(n)¶ - Parameters
n (int) – Number of fractional bits remaining after rounding
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if
overflow_alert
is'error'
)
Rounds the
FixedPoint
to n fractional bits, biased toward the nearest value with ties rounding away from 0.Jump to Examples
-
round_down
(n)¶ - Parameters
n (int) – Number of fractional bits remaining after rounding
Rounds the
FixedPoint
to n fractional bits toward \(-\infty\).Jump to Examples
-
round_up
(n)¶ - Parameters
n (int) – Number of fractional bits remaining after rounding
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if
overflow_alert
is'error'
)
Rounds the
FixedPoint
to n fractional bits toward \(+\infty\).Jump to Examples
-
keep_msbs
(m, n, /, rounding=None, overflow=None, alert=None)¶ - Parameters
m (int) – Number of integer bits in the result
n (int) – Number of fractional bits in the result
rounding (str) – Temporary
rounding
scheme to use. Can be keyworded.overflow (str) – Temporary
overflow
scheme to use. Can be keyworded.alert (str) – Temporary
overflow_alert
scheme to use. Can be keyworded.
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if alert - or
overflow_alert
if alert is not specified - is'error'
)
Rounds away LSb(s), leaving m + n bit(s), using the rounding scheme specified, then interprets the result with m integer bits and n fractional bits.
The rounding, overflow handling, and overflow alert notification schemes can be temporarily modified within the scope of this method. I.e., specifying the rounding, overflow, or alert arguments will only take effect within this method; it will not permanently change the property settings of the object. The current property setting for any of these unspecified arguments is used.
While other rounding functions cannot round beyond the fractional bits in a
FixedPoint
,keep_msbs()
will keep an arbitrary number of theFixedPoint
’s most significant bits, regardless of its current Q format. The resulting Q format must be valid.Jump to Examples
Overflow Handling
-
clamp
(m, /, alert=None)¶ - Parameters
m (int) – Number of integer bits remaining after clamping
alart (str) – Temporary
overflow_alert
scheme to use. Can be keyworded.
- Raises
FixedPointOverflowError – if new integer bit width is too small to represent the
FixedPoint
object value (raised only if alert - oroverflow_alert
if alert is not specified - is'error'
)
Reduces the number of integer bits in the
FixedPoint
to m, clamping to the minimum or maximum value on overflow.The overflow alert notification scheme can be temporarily modified within the scope of the method by using the alert argument. When left unspecified, the
overflow_alert
property setting is used.Jump to Examples
-
wrap
(m, /, alert=None)¶ - Parameters
m (int) – Number of integer bits remaining after wrapping
alart (str) – Temporary
overflow_alert
scheme to use. Can be keyworded.
- Raises
FixedPointOverflowError – if new integer bit width is too small to represent the
FixedPoint
object value (raised only if alert - oroverflow_alert
if alert is not specified - is'error'
)
Reduces the number of integer bits in the
FixedPoint
to m, masking away the removed integer bits.The overflow alert notification scheme can be temporarily modified within the scope of the method by using the alert argument. When left unspecified, the
overflow_alert
property setting is used.Jump to Examples
-
keep_lsbs
(m, n, /, overflow=None, alert=None)¶ - Parameters
- Raises
FixedPointOverflowError – if new m + n bits is too small to represent the
FixedPoint
value (raised only if alert - oroverflow_alert
if alert is not specified - is'error'
)
Removes MSb(s), leaving m + n bit(s), using the overflow scheme specified, then interprets the result with m integer bits and n fractional bits.
The overflow handling and overflow alert notification schemes can be temporarily modified within the scope of this method. I.e., specifying the overflow or alert arguments will only take effect within this method; it will not permanently change the property settings of the object. The current property setting for any of these unspecified arguments is used.
While other overflow handling functions cannot remove MSbs beyond their integer bits in a
FixedPoint
,keep_lsbs()
will keep an arbitrary number of theFixedPoint
’s least significant bits, regardless of its current Q format. The resulting Q format must be valid.Jump to Examples
Context Management
-
__enter__
()¶ -
__exit__
(exc_type, *args)¶ -
__call__
(*, safe_retain=False, **props)¶ Note
This is the built-in with statement in conjunction with the
()
operator.- Parameters
safe_retain (bool) – Set to True to retain the changes made within the context as long as no exceptions were raised. Set to False (or leave unspecified) if the the changes made within the context are to be undone when the context exits.
props –
Any keyword-able argument from the
FixedPoint
constructor, including:signed (bool)
m (int)
n (int)
overflow (str)
rounding (str)
overflow_alert (str)
mismatch_alert (str)
implicit_cast_alert (str)
str_base (int)
- Raises
AttributeError – if invalid keyword is specified
PermissionError – if a private or read-only
FixedPoint
property/attribute is specified
While the
__call__
method is not typically associated with the context manager, theFixedPoint
class uses this method to assign attributes temporarily (or permanently, with appropriate use of the safe_retain keyword) to theFixedPoint
called, within the context of the with statement.Using the
__call__
method is optional when safe_retain does not need to be True.Jump to Examples
-
static
enable_logging
()¶ Enables logging to fixedpoint.log, located in the root directory of the
fixedpoint
module.On initial import, logging is disabled.
Any time this method is called, fixedpoint.log is erased.
-
static
disable_logging
()¶ Disables logging to fixedpoint.log.
-
classmethod
sign
(val)¶ - Parameters
val (FixedPoint or int or float) – Value from which to discern the sign.
- Returns
-1 if val < 0
+1 if val > 0
0 if val == 0
- Return type
Determine the sign of a number.
-
classmethod
min_m
(val, /, signed=None)¶ - Parameters
- Returns
Minimum value for
FixedPoint.m
for which val can be represented without overflow.- Return type
Calculate the minimum value for
FixedPoint.m
for which va can be represented without overflow. If signed is not specified, it is deduced from the value of val. When val < 0, signed is ignored.Worst case rounding is assumed (e.g.,
min_m(3.25)
returns 3, in case 3.25 needs to be rounded up to 4).
-
classmethod
min_n
(val)¶ - Parameters
val (float) – Value to analyze
- Returns
Minimum value for
FixedPoint.n
for which val can be represented exactly.- Return type
The FixedPointBits Class¶
Examples are just a click away
Boxes like this link to example code.
-
class
fixedpoint.
FixedPointBits
¶ FixedPointBits
inherits fromint
and adds item access. You should not need to instantiate this, but this allows for theFixedPoint.bits
attribute to be indexed, sliced, and mapped.-
__getitem__
(key)¶ Note
This is the built-in square bracket
[]
operator.- Parameters
- Return type
- Raises
KeyError – Unsupported mapping string
IndexError – Invalid slice step or index out of range
The square brackets allow access to one or more bits at a time. No matter the access scheme (indexing, slicing, or mapping, described below), the return value is always shifted to be no more than N bits, where N is the number of bits accessed. E.g., accessing 3 bits will return an integer in the range [0, 23), regardless of where the are located in the
FixedPointBits
.Indexing
When key is an
int
, a single bit is accessed inFixedPoint.bits
. Index 0 is the LSb and index \(m + n - 1\) is the MSb.Jump to Examples
Slicing
When key is a
slice
(either an explicit slice object, or generated by using one or more:
s), one or more bits can be accessed. With bits asFixedPointBits
and integers A, B, and C such that A > B:bits[A:B:C]
returns bits A down to B (inclusive) with index 0 being the LSb and \(m + n - 1\) being the MSb. C can be omitted, but must be -1 if specified.bits[B:A:C]
returns bits A up to B (inclusive) with index 0 being the MSb and \(m + n - 1\) being the LSb. C can be omitted, but must be 1 if specified.bits[A:A:C]
with C == -1 returns bit A within index 0 being the LSb and \(m + n - 1\) being the MSb.bits[B:B:C]
with C == 1 returns bit B within index 0 being the MSb and \(m + n - 1\) being the LSb.
Any slicing format not specified above treats the
FixedPointBits
as a binary digitstr
(indexed from 0 to \(m + n - 1\)).Jump to Examples
Mapping
Common bit slices are mapped to string keywords:
Key String
Bit Slice
Assumptions
'm'
integer bits only
FixedPointBits.m
> 0'int'
'n'
fractional bits only
FixedPointBits.n
> 0'frac'
's'
most significant bit
is True'sign'
'msb'
–
'lsb'
least significant bit
If the mapping is accessed and the assumption(s) for that mapping are not satisfied, a
KeyError
is raised.When the key string is UPPERCASED, the return value is a
str
of binary bits.Jump to Examples
-
The PropertyResolver Class¶
Examples are just a click away
Boxes like this link to example code.
-
class
fixedpoint.properties.
PropertyResolver
¶ Resolves properties between two
FixedPoint
s.This is used internally by the
FixedPoint
class for property resolution. You should not need to instantiate this class, but it is documented here to show how properties are resolved.-
mismatch_alert
(*args)¶ - Parameters
args (FixedPoint) – An variable number of
FixedPoint
s whosemismatch_alert
properties are to be resolved.- Returns
Resolved
mismatch_alert
property.- Return type
- Raises
MismatchError – if
mismatch_alert
properties of all args do not match, and any args’mismatch_alert
property setting is'error'
.
When all args have equivalent
mismatch_alert
properties, that value is returned. Otherwise, the priority of resolution order is:'warning'
'error'
'ignore'
If there are mismatches in the
mismatch_alert
properties, then an alert is issued according to the highest priority mismatch_alert setting in args.
-
overflow
(*args)¶ - Parameters
args (FixedPoint) – An variable number of
FixedPoint
s whoseoverflow
properties are to be resolved.- Returns
Resolved
overflow
property.- Return type
- Raises
MismatchError – if
overflow
ormismatch_alert
properties of all args do not match, and any args’mismatch_alert
property setting is'error'
.
When all args have equivalent
overflow
properties, that value is returned. Otherwise, the priority of resolution order is:'clamp'
'wrap'
If there are mismatches in the
mismatch_alert
properties, then an alert is issued according to the highest priority mismatch_alert setting in args.
-
rounding
(*args)¶ - Parameters
args (FixedPoint) – An variable number of
FixedPoint
s whoserounding
properties are to be resolved.- Returns
Resolved
rounding
property.- Return type
- Raises
MismatchError – if
rounding
ormismatch_alert
properties of all args do not match, and any args’mismatch_alert
property setting is'error'
.
When all args have equivalent
rounding
properties, that value is returned. Otherwise, the priority of resolution order is:'convergent'
(if any args are signed, otherwise'nearest'
)'nearest'
(if no args are signed, otherwise'convergent'
)'down'
'in'
'out'
'up'
If there are mismatches in the
mismatch_alert
properties, then an alert is issued according to the highest priority mismatch_alert setting in args.
-
overflow_alert
(*args)¶ - Parameters
args (FixedPoint) – An variable number of
FixedPoint
s whoseoverflow_alert
properties are to be resolved.- Returns
Resolved
overflow_alert
property.- Return type
- Raises
MismatchError – if
mismatch_alert
oroverflow_alert
properties of all args do not match.
When all args have equivalent
overflow_alert
properties, that value is returned. Otherwise, the priority of resolution order is:'error'
'warning'
'ignore'
If there are mismatches in the
overflow_alert
properties, then an alert is issued according to the highest priority mismatch_alert setting in args.
-
implicit_cast_alert
(*args)¶ - Parameters
args (FixedPoint) – An variable number of
FixedPoint
s whoseimplicit_cast_alert
properties are to be resolved.- Returns
Resolved
implicit_cast_alert
property.- Return type
- Raises
MismatchError – if
mismatch_alert
orimplicit_cast_alert
properties of all args do not match.
When all args have equivalent
implicit_cast_alert
properties, that value is returned. Otherwise, the priority of resolution order is:'warning'
'error'
'ignore'
If there are mismatches in the
implicit_cast_alert
properties, then an alert is issued according to the highest priority mismatch_alert setting in args.
-
str_base
(*args)¶ - Parameters
args (FixedPoint) – An variable number of
FixedPoint
s whosestr_base
properties are to be resolved.- Returns
Resolved
str_base
property.- Return type
When all args have equivalent
str_base
properties, thatstr_base
is returned. Otherwise the resolution is 16.Note
str_base
mismatches do not raiseMismatchError
s.
-
all
(*args)¶ - Parameters
args (FixedPoint) – An variable number of
FixedPoint
s whose property settings are to be resolved.- Returns
dict
of resolved properties.- Return type
- Raises
MismatchError – if any properties are not equivalent for all args and any args’
mismatch_alert
property setting is'error'
.
Resolves all properties for each
FixedPoint
in args.Return value is a
dict
, with the format'property name': 'property setting'
. This can be used directly in theFixedPoint
constructor as its property keyword arguments.A mismatch alert is issued for each property mismatch.
Property Resolution Order
The order in which properties are resolved (and thus the order in which alerts may be issued) is:
-
Functions¶
The fixedpoint
module functions provide the same functionality as the
FixedPoint
methods of the same name, but make a copy of the
FixedPoint
object and operate on it, instead of modifying the object
itself.
Examples are just a click away
Boxes like this link to example code.
-
fixedpoint.
resize
(fp, m, n, /, rounding=None, overflow=None, alert=None)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
m (int) – Number of integer bits to resize to.
n (int) – Number of fractional bits to resize to
rounding (str) – Temporary
rounding
scheme to use. Can be keyworded.overflow (str) – Temporary
overflow
scheme to use. Can be keyworded.alert (str) – Temporary
overflow_alert
scheme to use. Can be keyworded.
- Return type
- Raises
FixedPointOverflowError – if resizing causes overflow (raised only if alert - or
overflow_alert
if alert is not specified - is'error'
).
Refer to
FixedPoint.resize()
for more details.Jump to Examples
-
fixedpoint.
trim
(fp, /, ints=None, fracs=None)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
ints (bool) – Set to True to trim off superfluous integer bits
fracs (bool) – Set to True to trim off superfluous fractional bits
- Return type
Refer to
FixedPoint.trim()
for more details.Jump to Examples
-
fixedpoint.
convergent
(fp, n, /)¶ -
fixedpoint.
round_convergent
(fp, n, /)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
n (int) – Number of fractional bits remaining after rounding
- Return type
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if
overflow_alert
is'error'
)
Refer to
FixedPoint.convergent()
for more details.Jump to Examples
-
fixedpoint.
round_nearest
(fp, n, /)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
n (int) – Number of fractional bits remaining after rounding
- Return type
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if
overflow_alert
is'error'
)
Refer to
FixedPoint.round_nearest()
for more details.Jump to Examples
-
fixedpoint.
round_in
(fp, n, /)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
n (int) – Number of fractional bits remaining after rounding
- Return type
Refer to
FixedPoint.round_in()
for more details.Jump to Examples
-
fixedpoint.
round_out
(fp, n, /)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
n (int) – Number of fractional bits remaining after rounding
- Return type
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if
overflow_alert
is'error'
)
Refer to
FixedPoint.round_out()
for more details.Jump to Examples
-
fixedpoint.
round_up
(fp, n, /)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
n (int) – Number of fractional bits remaining after rounding
- Return type
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if
overflow_alert
is'error'
)
Refer to
FixedPoint.round_up()
for more details.Jump to Examples
-
fixedpoint.
round_down
(fp, n, /)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
n (int) – Number of fractional bits remaining after rounding
- Return type
Refer to
FixedPoint.round_down()
for more details.Jump to Examples
-
fixedpoint.
keep_msbs
(fp, m, n, /, rounding=None, overflow=None, alert=None)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
m (int) – Number of integer bits in the result
n (int) – Number of fractional bits in the result
rounding (str) – Temporary
rounding
scheme to use. Can be keyworded.overflow (str) – Temporary
overflow
scheme to use. Can be keyworded.alert (str) – Temporary
overflow_alert
scheme touse. Can be keyworded.
- Return type
- Raises
FixedPointOverflowError – if rounding causes overflow (raised only if alert - or
overflow_alert
if alert is not specified - is'error'
)
Refer to
FixedPoint.keep_msbs()
for more details.Jump to Examples
-
fixedpoint.
clamp
(fp, m, /, alert=None)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
m (int) – Number of integer bits remaining after clamping
alart (str) – Temporary
overflow_alert
scheme to use. Can be keyworded.
- Return type
- Raises
FixedPointOverflowError – if reducing integer bit width causes overflow (raised only if alert - or
overflow_alert
if alert is not specified - is'error'
)
Refer to
FixedPoint.clamp()
for more details.Jump to Examples
-
fixedpoint.
wrap
(fp, m, /, alert=None)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
m (int) – Number of integer bits remaining after wrapping
alart (str) – Temporary
overflow_alert
scheme to use. Can be keyworded.
- Return type
- Raises
FixedPointOverflowError – if reducing integer bit width causes overflow (raised only if alert - or
overflow_alert
if alert is not specified - is'error'
)
Refer to
FixedPoint.wrap()
for more details.Jump to Examples
-
fixedpoint.
keep_lsbs
(fp, m, n, /, overflow=None, alert=None)¶ - Parameters
fp (FixedPoint) – Object to copy and operate on
m (int) – Number of integer bits in the result
n (int) – Number of fractional bits in the result
overflow (str) – Temporary
overflow
scheme to use. Can be keyworded.alert (str) – Temporary
overflow_alert
scheme to use. Can be keyworded.
- Return type
- Raises
FixedPointOverflowError – if reducing integer bit width causes overflow (raised only if alert - or
overflow_alert
if alert is not specified - is'error'
)
Refer to
FixedPoint.keep_lsbs()
for more details.Jump to Examples
Exceptions¶
-
exception
fixedpoint.
FixedPointError
¶ Base class for other fixedpoint exceptions.
-
exception
fixedpoint.
FixedPointOverflowError
¶ Signals that overflow has occurred. Raised only when
overflow_alert
is'error'
.Inherits from
FixedPointError
andOverflowError
.
-
exception
fixedpoint.
MismatchError
¶ Signals that the properties of 2
FixedPoint
s do not match. Raised only whenmismatch_alert
is'error'
.Inherits from
FixedPointError
.
-
exception
fixedpoint.
ImplicitCastError
¶ Signals that an object required implicit casting to a
FixedPoint
, and the cast was not exact. Raised only whenimplicit_cast_alert
is'error'
.Inherits from
FixedPointError
andFloatingPointError
.
Initialization¶
Initializing from a float¶
When initializing a FixedPoint
from a float
, signed, m, and n
are all optional. Thus the following object instantiations are all valid:
>>> from fixedpoint import FixedPoint
>>> from math import pi
>>> a = FixedPoint(pi) # No signed, m, or n argument
>>> float(a), a.qformat
(3.141592653589793, 'UQ2.48')
>>> b = FixedPoint(pi, True) # No m or n argument
>>> float(b), b.qformat
(3.141592653589793, 'Q3.48')
>>> c = FixedPoint(2**-80, m=10, n=80) # No signed argument
>>> float(c), c.qformat
(8.271806125530277e-25, 'UQ10.80')
Warning
Python’s float
type is typically implemented with 64-bit doubles,
specified by IEEE 754. This means that there’s only 53 significant
binary bits in a float
(you can verify this by examining
sys.float_info
), and thus precision and resolution may be compromised in
certain circumstances. See The Python Tutorial on the Issues and Limitations of Floating Point Arithmetic.
>>> print(format(pi, '.60f'))
3.141592653589793115997963468544185161590576171875000000000000
>>> a = FixedPoint(pi, n=60, str_base=2)
>>> print(str(a))
11001001000011111101101010100010001000010110100011000000000000
In the example above, \(\pi\) is only representable by 52 floating point
mantissa bits. Thus extending the decimal representation out to 60 places, the
bits eventually stabilize to 0 (even though \(\pi\) is irrational and never
stabilizes). While the FixedPoint
representation of the float is accurate,
this method of representing \(\pi\) suffers from inaccuracy.
Initializing from an int¶
When initializing a FixedPoint
from an int
, signed, m, and n are all
optional. When n is left unspecified, it is guaranteed to be 0 (since integers
never require fractional bits). When m is left unspecified,
FixedPoint.min_m()
is used to deduce the number of integer bits needed to
represent init, and after rounding occurs, trim()
is used
to remove superfluous leading 0s or sign-extended 1s.
>>> a = FixedPoint(-2**1000, n=42) # No signed or m argument
>>> a.qformat
'Q1001.42'
>>> b = FixedPoint(14, True, 10) # No n argument
>>> b.qformat, float(b)
('Q10.0', 14.0)
>>> c = FixedPoint(0, 0, 19, 88) # Signed, m, and n arguments are present
>>> str(c)
'000000000000000000000000000'
Tip
Python’s int
type has unlimited precision, meaning it can be as large
as you need it to be! In fact, the FixedPoint bits
are
stored internally as an int.
Initializing from a str¶
When initializing a FixedPoint
from a str
, signed, m, and n are
required:
>>> a = FixedPoint('1') # no Q format
Traceback (most recent call last):
...
ValueError: String literal initialization Q format must be fully constrained.
The string is converted to an int and this value is stored internally as the
FixedPoint bits
. This means that leading 0s are ignored
and not included in the total number of bits:
>>> a = FixedPoint('0x00000000000000001', signed=0, m=1, n=0) # Leading 0s
>>> a.bits
1
Rounding and overflow handling are not performed. If the bits of the string
exceed the specified Q format, a ValueError
is raised.
>>> a = FixedPoint('0xFF', 0, 1, 1) # A whole bunch of extra bits
Traceback (most recent call last):
...
ValueError: Superfluous bits detected in string literal '0xFF' for UQ1.1 format.
int(init, 0)
is used to internally convert the str to int, thus the
0b
, 0o
, or 0x
radix is required for binary, octal, or hexadecimal
strings, respectively. If the radix is not present, it is considered a decimal
number. This means if you have an integer that represents some known/desired
Q format, you can simply call bin()
, oct()
,
str
or hex()
to convert it to a str, then to a
FixedPoint
. This method of initialization may be super useful in
generating random stimulus:
>>> import random
>>> random.seed(42)
>>> signed, m, n = 1, 12, 13
>>> bits = random.getrandbits(m + n)
>>> x = FixedPoint(hex(bits), signed, m, n)
>>> float(x), x.qformat
(-1476.9078369140625, 'Q12.13')
Warning
Converting a negative integer to a string is not allowed; the bits of interest should be masked before converting to a string.
>>> x = FixedPoint('-1', signed=1, m=2, n=0)
Traceback (most recent call last):
...
ValueError: Superfluous bits detected in string literal '-1' for Q2.0 format.
>>> m, n = 2, 0
>>> mask = 2**(m + n) - 1
>>> x = FixedPoint(str(-1 & mask), 1, m, n)
>>> float(x), x.qformat
(-1.0, 'Q2.0')
Initializing from another FixedPoint¶
When initializing a FixedPoint
from another FixedPoint
, only init is
required; all other arguments are ignored.
>>> x = FixedPoint(2**-5)
>>> x.qformat
'UQ0.5'
>>> y = FixedPoint(x, n=492) # n is ignored
>>> y.qformat
'UQ0.5'
Initializing from other types¶
When init is not a(n) float
, int
, str
, or FixedPoint
, the object
is cast to a float.
>>> from decimal import Decimal
>>> x = Decimal(1) / Decimal(10)
>>> y = FixedPoint(x)
>>> z = FixedPoint(0.1)
>>> y == z
True
If this fails, a TypeError
is raised.
>>> file = open('some_file', 'a')
>>> FixedPoint(file)
Traceback (most recent call last):
...
TypeError: Unsupported type <class '_io.TextIOWrapper'>; cannot convert to float.
Initializers¶
When the Q format of a FixedPoint
should stay the same, but
a different value is needed, it is quicker to use one of the following
initializers than generating a new FixedPoint
object:
It’s quicker because the Q format and properties need not be validated.
from timeit import timeit
test_constructor = {
'stmt': 'FixedPoint(hex(random.getrandbits(100)), 1, 42, 58)',
'setup': 'from fixedpoint import FixedPoint; import random',
'number': 100000,
}
test_initializer = {
'stmt': 'x.from_string(hex(random.getrandbits(100)))',
'setup': 'import fixedpoint, random; x = fixedpoint.FixedPoint(0, 1, 42, 58)',
'number': 100000,
}
print("Constructor:", timeit(**test_constructor))
print("Initializer:", timeit(**test_initializer))
The code block above tests the difference between creating 100,000 FixedPoint
instances and 100,000 initializer calls. There is a significant time improvement
by using the initializer from_string()
instead of the
FixedPoint
constructor:
Constructor: 1.6910291
Initializer: 0.18432009999999988
The results are similar with from_int()
:
Constructor: 1.8801342
Initializer: 0.4326542
and from_float()
(using random.random()
with 50
fractional bits):
Constructor: 2.4381994
Initializer: 0.7997059000000002
One example is when stimulus is being created that uses a single FixedPoint
at a time, or when the processing of that FixedPoint
does not change its
properties. Create a single instance, and then just use the initializer in
each loop iteration:
from fixedpoint import FixedPoint
import random
# Q1.24
qformat = {'signed': True, 'm': 1, 'n': 24}
# A single instance
x = FixedPoint(0, **qformat)
for i in range(10000):
x.from_string(hex(random.getrandbits(25)))
# Do stuff with x that doesn't change the Q format. If the Q format
# is changed, you could use the context manager to restore the original
# values once the processing in this iteration is done.
overflow
¶
Overflow occurs when a number is greater than the minimum or maximum value that the fixed point number can represent (underflow is also generalized here to overflow). This is determined by the Q format.
The FixedPoint class offers two forms of overflow handling:
'clamp'
(default if not specified)'wrap'
'clamp'
¶
Clamping limits the number to the most maximum or minimum value
representable by the available Q format. The
overflow_alert
property may need to be changed from the
default 'error'
to allow processing to continue.
>>> x = FixedPoint(999, 0, 4, 1, overflow='clamp')
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN1] Integer 999 overflows in UQ4.1 format.
>>> try:
... x
... except NameError:
... print('x was not assigned because of the FixedPointOverflowError')
x was not assigned because of the FixedPointOverflowError
>>> x = FixedPoint(999, 0, 4, 1, overflow='clamp', overflow_alert='ignore')
>>> x.clamped, x.qformat, bin(x), float(x)
(True, 'UQ4.1', '0b11111', 15.5)
>>> x = FixedPoint(999, 1, 4, 1, overflow='clamp', overflow_alert='warning')
WARNING [SN3]: Integer 999 overflows in Q4.1 format.
WARNING [SN3]: Clamped to maximum.
>>> x.qformat, hex(x), float(x)
('Q4.1', '0xf', 7.5)
>>> x = FixedPoint(-999, 0, 4, 1, overflow='clamp', overflow_alert='warning')
WARNING [SN4]: Integer -999 overflows in UQ4.1 format.
WARNING [SN4]: Clamped to minimum.
>>> x.qformat, hex(x), float(x)
('UQ4.1', '0x0', 0.0)
>>> x = FixedPoint(-999, 1, 4, 1, overflow='clamp', overflow_alert='ignore')
>>> x.qformat, bin(x), float(x)
('Q4.1', '0b10000', -8.0)
'wrap'
¶
Wrapping will compute the full-length value and then mask away unspecified MSbs.
This is also called 2’s complement overflow. The
overflow_alert
property may need to be changed from the
default 'error'
to allow processing to continue.
>>> big = 0b11000 # Needs 5 (unsigned) integer bits to represent
>>> big
24
>>> x = FixedPoint(big, 0, 4, 1, overflow='wrap')
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN1] Integer 24 overflows in UQ4.1 format.
>>> try:
... x
... except NameError:
... print('x was not assigned because of the FixedPointOverflowError')
x was not assigned because of the FixedPointOverflowError
>>> x = FixedPoint(big, 0, 4, 1, overflow='wrap', overflow_alert='ignore')
>>> x.clamped, x.qformat, bin(x), float(x)
(False, 'UQ4.1', '0b10000', 8.0)
>>> x = FixedPoint(big, 1, 4, 1, overflow='wrap', overflow_alert='warning')
WARNING [SN3]: Integer 24 overflows in Q4.1 format.
WARNING [SN3]: Wrapped maximum.
>>> x.qformat, hex(x), float(x)
('Q4.1', '0x10', -8.0)
>>> x = FixedPoint(-1, 0, 4, 1, overflow='wrap', overflow_alert='warning')
WARNING [SN4]: Integer -1 overflows in UQ4.1 format.
WARNING [SN4]: Wrapped minimum.
>>> x.qformat, bin(x), 15.0
('UQ4.1', '0b11110', 15.0)
>>> -big & 0b11111
8
>>> x = FixedPoint(-big, 1, 4, 1, overflow='wrap', overflow_alert='ignore')
>>> x.qformat, bin(x), float(x)
('Q4.1', '0b10000', -8.0)
rounding
¶
Rounding occurs when non-zero fractional bits must be removed from the number.
The FixedPoint
class offers several forms of rounding:
'convergent'
(default for signed numbers if not specified)'nearest'
(default for unsigned numbers if not specified)'out'
'in'
'up'
'down'
The table below summarizes the behavior of all supported rounding schemes. When the number in the first column is rounded to 0 fractional bits using the rounding scheme in the first row, the result is shown.
convergent |
nearest |
down |
in |
out |
up |
|
---|---|---|---|---|---|---|
-3.49 |
-3 |
-3 |
-4 |
-3 |
-3 |
-3 |
-3.50 |
-4 |
-3 |
-4 |
-3 |
-4 |
-3 |
-3.51 |
-4 |
-4 |
-4 |
-3 |
-4 |
-3 |
+3.49 |
+3 |
+3 |
+3 |
+3 |
+3 |
+4 |
+3.50 |
+4 |
+4 |
+3 |
+3 |
+4 |
+4 |
+3.51 |
+4 |
+4 |
+3 |
+3 |
+4 |
+4 |
'convergent'
¶
Rounds toward the nearest even value in the case of a tie, otherwise rounds to the nearest value. Wikipedia outlines the pros and cons of convergent rounding.
>>> x = FixedPoint(0, signed=1, m=4, n=0, rounding='convergent')
>>> for sign in [+1, -1]:
... for mag in [3.49, 3.5, 3.51, 4.49, 4.5, 4.51]:
... x.from_float(init := mag * sign)
... print(f"{init: .2f} rounds to {x: .0f}")
3.49 rounds to 3
3.50 rounds to 4
3.51 rounds to 4
4.49 rounds to 4
4.50 rounds to 4
4.51 rounds to 5
-3.49 rounds to -3
-3.50 rounds to -4
-3.51 rounds to -4
-4.49 rounds to -4
-4.50 rounds to -4
-4.51 rounds to -5
The example above shows easy-to-understand values and rounding off fractional bits completely. However, the same principal applies to round to a non-zero number of fractional bits:
>>> x = FixedPoint('0b100110', 1, 2, 4, rounding='convergent')
>>> float(x), x.qformat
(-1.625, 'Q2.4')
>>> y = FixedPoint(float(x), n=2, rounding='convergent') # round to 2 frac bits
>>> float(y), bin(y)
(-1.5, '0b1010')
Because convergent rounding can cause the value of the number to increase, it can cause overflow.
>>> x = FixedPoint(3.5)
>>> x.qformat # Can be represented with 2 integer bits
'UQ2.1'
>>> y = FixedPoint(3.5, m=2, n=0, rounding='convergent')
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN2] 3.500000e+00 overflows in UQ2.0 format.
>>> z = FixedPoint(3.5, n=0, rounding='convergent') # Requires 4 integer bits
>>> float(z), z.qformat
(4.0, 'UQ3.0')
'nearest'
¶
Rounds toward \(+\infty\) in the case of a tie, otherwise rounds to the nearest value. Wikipedia describes this widely used rounding method.
>>> x = FixedPoint(0, signed=1, m=4, n=0, rounding='nearest')
>>> for sign in [+1, -1]:
... for mag in [3.49, 3.5, 3.51, 4.49, 4.5, 4.51]:
... x.from_float(init := mag * sign)
... print(f"{init: .2f} rounds to {x: .0f}")
3.49 rounds to 3
3.50 rounds to 4
3.51 rounds to 4
4.49 rounds to 4
4.50 rounds to 5
4.51 rounds to 5
-3.49 rounds to -3
-3.50 rounds to -3
-3.51 rounds to -4
-4.49 rounds to -4
-4.50 rounds to -4
-4.51 rounds to -5
The example above shows easy-to-understand values and rounding off fractional bits completely. However, the same principal applies to round to a non-zero number of fractional bits:
>>> x = FixedPoint('0b100110', 1, 2, 4, rounding='nearest')
>>> x.qformat, float(x)
('Q2.4', -1.625)
>>> y = FixedPoint(float(x), n=2, rounding='nearest') # round to 2 frac bits
>>> bin(y), float(y)
('0b1010', -1.5)
Because rounding to nearest can cause the value of the number to increase, it can cause overflow.
>>> FixedPoint(15.5).qformat # Can be represented with 4 integer bits
'UQ4.1'
>>> x = FixedPoint(15.5, m=4, n=0, rounding='nearest')
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN2] 1.550000e+01 overflows in UQ4.0 format.
>>> z = FixedPoint(15.5, n=0, rounding='nearest') # Requires 5 integer bits
>>> float(z), z.qformat
(16.0, 'UQ5.0')
'out'
¶
Rounds away from 0 in the case of a tie, otherwise rounds to the nearest value. Wikipedia outlines the pros and cons of rounding away from 0.
>>> x = FixedPoint(0, signed=1, m=4, n=0, rounding='out')
>>> for sign in [+1, -1]:
... for mag in [3.49, 3.5, 3.51, 4.49, 4.5, 4.51]:
... x.from_float(init := mag * sign)
... print(f"{init: .2f} rounds to {x: .0f}")
3.49 rounds to 3
3.50 rounds to 4
3.51 rounds to 4
4.49 rounds to 4
4.50 rounds to 5
4.51 rounds to 5
-3.49 rounds to -3
-3.50 rounds to -4
-3.51 rounds to -4
-4.49 rounds to -4
-4.50 rounds to -5
-4.51 rounds to -5
The example above shows easy-to-understand values and rounding off fractional bits completely. However, the same principal applies to round to a non-zero number of fractional bits:
>>> x = FixedPoint('0b100110', 1, 2, 4, rounding='out')
>>> x.qformat, float(x)
('Q2.4', -1.625)
>>> y = FixedPoint(float(x), n=2, rounding='out') # round to 2 fractional bits
>>> bin(y), float(y)
('0b1001', -1.75)
Because rounding away from 0 causes the magnitude of the number to increase, it can cause overflow.
>>> FixedPoint(15.5).qformat # Can be represented with 4 integer bits
'UQ4.1'
>>> x = FixedPoint(15.5, m=4, n=0, rounding='out')
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN2] 1.550000e+01 overflows in UQ4.0 format.
>>> z = FixedPoint(15.5, n=0, rounding='out') # Requires 5 integer bits
>>> float(z), z.qformat
(16.0, 'UQ5.0')
'in'
¶
Rounds unconditionally toward 0.
Note
This has the same effect as truncating decimal digits.
Warning
This is not the same as truncating bits; use the down rounding scheme for bit truncation.
>>> x = FixedPoint(0, signed=1, m=4, n=0, rounding='in')
>>> for sign in [+1, -1]:
... for mag in [3.49, 3.5, 3.51, 4.49, 4.5, 4.51]:
... x.from_float(init := mag * sign)
... print(f"{init: .2f} rounds to {x: .0f}")
3.49 rounds to 3
3.50 rounds to 3
3.51 rounds to 3
4.49 rounds to 4
4.50 rounds to 4
4.51 rounds to 4
-3.49 rounds to -3
-3.50 rounds to -3
-3.51 rounds to -3
-4.49 rounds to -4
-4.50 rounds to -4
-4.51 rounds to -4
The example above shows easy-to-understand values and rounding off fractional bits completely. However, the same principal applies to round to a non-zero number of fractional bits:
>>> x = FixedPoint('0b100110', 0, 2, 4, rounding='in')
>>> x.qformat, float(x)
('UQ2.4', 2.375)
>>> y = FixedPoint(float(x), n=2, rounding='in') # round to 2 fractional bits
>>> bin(y), float(y)
('0b1001', 2.25)
Because rounding in will always decrease the number’s magnitude, it cannot cause overflow.
'up'
¶
Rounds unconditionally toward \(+\infty\).
>>> x = FixedPoint(0, signed=1, m=4, n=0, rounding='up')
>>> for sign in [+1, -1]:
... for mag in [3.49, 3.5, 3.51, 4.49, 4.5, 4.51]:
... x.from_float(init := mag * sign)
... print(f"{init: .2f} rounds to {x: .0f}")
3.49 rounds to 4
3.50 rounds to 4
3.51 rounds to 4
4.49 rounds to 5
4.50 rounds to 5
4.51 rounds to 5
-3.49 rounds to -3
-3.50 rounds to -3
-3.51 rounds to -3
-4.49 rounds to -4
-4.50 rounds to -4
-4.51 rounds to -4
The example above shows easy-to-understand values and rounding off fractional bits completely. However, the same principal applies to round to a non-zero number of fractional bits:
>>> x = FixedPoint('0b100110', 0, 2, 4, rounding='up')
>>> x.qformat, float(x)
('UQ2.4', 2.375)
>>> y = FixedPoint(float(x), n=2, rounding='up') # round to 2 fractional bits
>>> bin(y), float(y)
('0b1010', 2.5)
Because rounding up can cause the number’s magnitude to increase, it can cause overflow.
>>> FixedPoint(15.5).qformat # Can be represented with 4 integer bits
'UQ4.1'
>>> x = FixedPoint(15.5, m=4, n=0, rounding='up')
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN2] 1.550000e+01 overflows in UQ4.0 format.
>>> z = FixedPoint(15.5, n=0, rounding='up') # Requires 5 integer bits
>>> float(z), z.qformat
(16.0, 'UQ5.0')
'down'
¶
Rounds unconditionally toward \(-\infty\).
Note
This is the same as truncating bits, since fractional bits cannot have negative weight.
Warning
This is not the same as truncating decimal digits; use the in rounding scheme to achieve decimal digit truncation.
>>> x = FixedPoint(0, signed=1, m=4, n=0, rounding='down')
>>> for sign in [+1, -1]:
... for mag in [3.49, 3.5, 3.51, 4.49, 4.5, 4.51]:
... x.from_float(init := mag * sign)
... print(f"{init: .2f} rounds to {x: .0f}")
3.49 rounds to 3
3.50 rounds to 3
3.51 rounds to 3
4.49 rounds to 4
4.50 rounds to 4
4.51 rounds to 4
-3.49 rounds to -4
-3.50 rounds to -4
-3.51 rounds to -4
-4.49 rounds to -5
-4.50 rounds to -5
-4.51 rounds to -5
The example above shows easy-to-understand values and rounding off fractional bits completely. However, the same principal applies to round to a non-zero number of fractional bits:
>>> x = FixedPoint('0b100110', 0, 2, 4, rounding='down')
>>> x.qformat, float(x)
('UQ2.4', 2.375)
>>> y = FixedPoint(float(x), n=2, rounding='down')
>>> bin(y), float(y)
('0b1001', 2.25)
Because rounding down will always make the value of the number smaller in magnitude, it cannot cause overflow.
overflow_alert
¶
The overflow_alert
property indicates how you will be notified and if
operation should be halted when overflow occurs. You can choose from:
'error'
(default if not specified)'warning'
'ignore'
Overflow can occur in the following scenarios:
initialization
changing the
signed
attributenegation (the unary
__neg__()
operator)reducing the number of integer bits
changing the
m
attribute
unsigned subtraction (see
__sub__()
)rounding with the following schemes/methods
'convergent' (or using
round_convergent()
)'nearest' (or using
round_nearest()
)'out' (or using
round_out()
)'up' (or using
round_up()
)
Some methods that can cause overflow have an alert argument which can change the notification scheme for the scope of the method. This can be used if overflow is expected.
'error'
¶
In this notification scheme, overflow causes execution to halt and a
FixedPointOverflowError
is raised.
>>> x = FixedPoint(999, 0, 1, 0, overflow_alert='error')
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN1] Integer 999 overflows in UQ1.0 format.
>>> x # Does not exist because of the exception!
Traceback (most recent call last):
...
NameError: name 'x' is not defined
'warning'
¶
In this notification scheme, overflow will emit two warnings, and execution will continue. The first warning informs you of the overflow cause, the second warning informs you of the action taken.
>>> x = FixedPoint(999, 0, 1, 0, overflow='clamp', overflow_alert='warning')
WARNING [SN1]: Integer 999 overflows in UQ1.0 format.
WARNING [SN1]: Clamped to maximum.
>>> float(x), x.clamped
(1.0, True)
>>> y = FixedPoint(3, 1, 2, 0, overflow='wrap', overflow_alert='warning')
WARNING [SN2]: Integer 3 overflows in Q2.0 format.
WARNING [SN2]: Wrapped maximum.
>>> float(y), y.clamped
(-1.0, False)
'ignore'
¶
In this notification scheme, overflow is handled silently.
>>> x = FixedPoint(3.75, 0, 2, 1, overflow_alert='ignore')
>>> float(x), x.clamped
(3.5, True)
>>> y = FixedPoint(-3, 1, 2, 10, overflow='wrap', overflow_alert='ignore')
>>> float(y), bin(y)
(1.0, '0b10000000000')
mismatch_alert
¶
The mismatch_alert
property indicates how you will be notified and if
operation should be halted when any property of 2 combining FixedPoint
s do
not match. You can choose from:
'error'
'warning'
(default if not specified)'ignore'
For instance, what are the properties of c
below?
a = FixedPoint(1,
overflow='wrap',
rounding='in',
overflow_alert='error',
mismatch_alert='warning',
implicit_cast_alert='ignore',
str_base=8,
)
b = FixedPoint(3.12345,
overflow='clamp',
rounding='convergent',
overflow_alert='warning',
mismatch_alert='ignore',
implicit_cast_alert='error',
str_base=2,
)
c = a + b
FixedPoint uses the PropertyResolver
class to
resolve property mismatches for the following operations:
addition (see
FixedPoint.__add__()
)subtraction (see
FixedPoint.__sub__()
)multiplication (see
FixedPoint.__mul__()
)
(in case you’re curious, the example above produces the following):
WARNING [SN1]: Non-matching mismatch_alert behaviors ['ignore', 'warning'].
WARNING [SN1]: Using 'warning'.
WARNING [SN1]: Non-matching overflow behaviors ['clamp', 'wrap'].
WARNING [SN1]: Using 'clamp'.
WARNING [SN1]: Non-matching rounding behaviors ['convergent', 'in'].
WARNING [SN1]: Using 'convergent'.
WARNING [SN1]: Non-matching overflow_alert behaviors ['error', 'warning'].
WARNING [SN1]: Using 'error'.
WARNING [SN1]: Non-matching implicit_cast_alert behaviors ['error', 'ignore'].
WARNING [SN1]: Using 'error'.
Tip
You may consider starting out with mismatch_alert
set
to 'error'
, just to make sure you understand the nuances of the
FixedPoint
class.
'error'
¶
In this notification scheme, the first property mismatch encountered will raise
a MismatchError
exception.
>>> a = FixedPoint(-1, rounding='convergent', mismatch_alert='error')
>>> b = FixedPoint(+1, rounding='nearest', mismatch_alert='error')
>>> c = a + b
Traceback (most recent call last):
...
fixedpoint.MismatchError: [SN1] Non-matching rounding behaviors ['convergent', 'nearest'].
>>> c # Does not exist because of the exception!
Traceback (most recent call last):
...
NameError: name 'c' is not defined
If either FixedPoint
’s mismatch_alert
is 'error'
,
then an exception is thrown. This is even the case if one of the settings is
'ignore'
(see the example below). When there are multiple mismatched
properties the first mismatch encountered in the
resolution order is the culprit.
>>> a.mismatch_alert = 'ignore' # Now mismatch_alert and rounding don't match
>>> d = a + b
Traceback (most recent call last):
...
MismatchError: Non-matching mismatch_alert behaviors ['error', 'ignore'].
>>> d # Does not exist because of the exception!
Traceback (most recent call last):
...
NameError: name 'd' is not defined
'warning'
¶
In this notification scheme, two warnings are emitted for each mismatch, but execution will continue. The first warning informs you of the non-matching properties, the second informs you of the resolution.
>>> x = FixedPoint(1492)
>>> y = FixedPoint(x)
>>> y.rounding = 'down'
>>> z = x - y
WARNING [SN1]: Non-matching rounding behaviors ['down', 'nearest'].
WARNING [SN1]: Using 'nearest'.
>>> z.rounding
'nearest'
Warnings are emitted in the property resolution order.
>>> y.overflow = 'wrap'
>>> zz = x + y # Overflow is resolved before rounding
WARNING [SN1]: Non-matching overflow behaviors ['clamp', 'wrap'].
WARNING [SN1]: Using 'clamp'.
WARNING [SN1]: Non-matching rounding behaviors ['down', 'nearest'].
WARNING [SN1]: Using 'nearest'.
>>> zz.rounding, zz.overflow
('nearest', 'clamp')
For augmented arithmetic operations (e.g. +=
), mismatches are ignored
because a new FixedPoint
is not being created.
>>> import sys, io
>>> sys.stderr = io.StringIO() # redirect stderr to a string buffer
>>> x -= y
>>> y *= x
>>> sys.stderr.flush()
>>> sys.stderr.getvalue() # Nothing written to stderr
''
>>> sys.stderr = sys.__stderr__ # Restore stderr
'ignore'
¶
In this notification scheme, property mismatches are resolved silently. The same examples from above are used.
>>> x = FixedPoint(1492, mismatch_alert='ignore')
>>> y = FixedPoint(x)
>>> y.rounding = 'down'
>>> z = x - y
>>> z.rounding
'nearest'
>>> y.overflow = 'wrap'
>>> zz = x + y # Overflow is resolved before rounding
>>> zz.rounding, zz.overflow
('nearest', 'clamp')
implicit_cast_alert
¶
Arithmetic operations allow non-FixedPoint
s as operands, and in such
cases, are cast to a FixedPoint
(see the Initializing from other types
section) prior to operation. When a value is cast, its value is compared to the
previous object, and if it doesn’t exactly match, FixedPoint
emits an alert.
The implicit_cast_alert
property indicates how you will be notified and if
operation should be halted when implicit casting introduces error. You can
choose from:
'error'
'warning'
(default if not specified)'ignore'
Note
Finding stimulus to actually cause this alert naturally has not been achieved. This notification scheme was unit tested using a patcher. The examples in this section employ the same technique to illustrate functionality.
Imiplicit cast alerts can conceivably be issued for the following operations:
addition (see
FixedPoint.__add__()
)subtraction (see
FixedPoint.__sub__()
)multiplication (see
FixedPoint.__mul__()
)
'error'
¶
In this notification scheme, numerical error introduced by implicit casting will
raise an ImplicitCastError
exception and operation is halted.
>>> a = FixedPoint(3, implicit_cast_alert='error')
>>> x = a + 0.2
Traceback (most recent call last):
...
fixedpoint.ImplicitCastError: [SN1] Casting 0.2 to UQ0.53 introduces an error of 5.551115e-17
>>> x # Does not exist because of the exception!
Traceback (most recent call last):
...
NameError: name 'x' is not defined
'warning'
¶
In this notification scheme, numerical error introduced by implicit casting will emit a warning, but the operation is still carried out.
>>> a = FixedPoint(1969, implicit_cast_alert='warning')
>>> a -= 0.3
WARNING [SN1]: Casting 0.3 to UQ0.52 introduces an error of 5.551115e-17
>>> print(f"{a:.60f}")
1968.700000000000045474735088646411895751953125000000000000000000
'ignore'
¶
In this notification scheme, numerical error introduced by implicit casting is ignored.
>>> a = FixedPoint(-10.5, implicit_cast_alert='ignore')
>>> x = 0.2 * a
>>> print(f"{x:.60f}")
-2.100000000000000088817841970012523233890533447265625000000000
str_base
¶
When casting a FixedPoint
to a str
, the bits of the
FixedPoint
are displayed. Since the bits
are stored
internally as an int
, they are simply converted using bin()
,
oct()
, str
, or hex()
from the __str__()
method. The str_base
property indicates the base of the generated string.
You can choose from:
16
(default if not specified)10
8
2
16
¶
Generates a hexadecimal string representative of FixedPoint.bits
. The
string is sign extended (or 0-padded) to the bit width of the object, and does
not include the radix.
>>> x = FixedPoint(0xdeadbeef, 1, 64, 8) # str_base=16 by default
>>> str(x)
'00000000deadbeef00'
>>> str(-x)
'ffffffff2152411100'
10
¶
Generates a decimal string representative of FixedPoint.bits
. The
string is not sign extended to the bit width of the object, and does not
include a radix. This is equivalent to str(FixedPoint(...).bits)
.
>>> x = FixedPoint(2, 1, 8, str_base=10)
>>> str(x) # no zero-padding occurs
'2'
>>> x.n += 1 # Effectively multiplies the bits by 2
>>> str(x)
'4'
>>> x.n = 0
>>> str(-x) # Never negative
'254'
8
¶
Generates an octal string representative of FixedPoint.bits
. The
string is sign extended (or 0-padded) to the bit width of the object, and does
not include the radix.
>>> x = FixedPoint(1/3, 1, 1, str_base=8)
>>> x.qformat, str(x)
('Q1.54', '0252525252525252525')
>>> str(-x)
'1525252525252525253'
2
¶
Generates a binary string representative of FixedPoint.bits
. The
string is sign extended (or 0-padded) to the bit width of the object, and does
not include the radix.
>>> x = FixedPoint(-1 + 2**-40, str_base=2)
>>> x.qformat, str(x)
('Q1.40', '10000000000000000000000000000000000000001')
>>> str(-x)
'01111111111111111111111111111111111111111'
Arithmetic¶
Addition¶
FixedPoint
addition using the +
or +=
operator is always
full-precision; that is, there is always bit growth.
Augend |
Addend |
Sum |
---|---|---|
\(UQm_1.n_1\)
(unsigned)
|
\(UQm_2.n_2\)
(unsigned)
|
\(UQx.y\), where
\(x = 1 + max\{m_1, m_2\}\)
\(y = max\{n_1, n_2\}\)
|
\(Qm_1.n_1\)
(signed)
|
\(Qm_2.n_2\)
(signed)
|
\(Qx.y\), where
\(x = 1 + max\{m_1, m_2\}\)
\(y = max\{n_1, n_2\}\)
|
\(Qm_1.n_1\)
(signed)
|
\(UQm_2.n_2\)
(unsigned)
|
|
\(UQm_1.n_1\)
(unsigned)
|
\(Qm_2.n_2\)
(signed)
|
As indicated in the table, any combination of signed and unsigned numbers can be added together. The sum is only unsigned when both augend and added are unsigned.
Overflow is not possible using the addition operators.
Unsigned¶
>>> x = FixedPoint(14, signed=0, m=8, n=4)
>>> y = FixedPoint(6, signed=0, m=3, n=5)
>>> z = x + y
>>> print(f' {x:q}\n+ {y:q}\n-------\n {z:q}')
UQ8.4
+ UQ3.5
-------
UQ9.5
Signed¶
>>> x = FixedPoint(-4, signed=1, m=4, n=4)
>>> y = FixedPoint(3, signed=1, m=3, n=5)
>>> z = x + y
>>> print(f' {x:q}\n+ {y:q}\n------\n {z:q}')
Q4.4
+ Q3.5
------
Q5.5
Mixed Signedness¶
>>> s = FixedPoint(-4.375, signed=1, m=4, n=4)
>>> u = FixedPoint(3 + 2**-5, signed=0, m=3, n=5)
>>> z = s + u
WARNING [SN1]: Non-matching rounding behaviors ['convergent', 'nearest'].
WARNING [SN1]: Using 'convergent'.
>>> print(f' {s:q}\n+ {u:q}\n-------\n {z:q}')
Q4.4
+ UQ3.5
-------
Q5.5
Additional Examples¶
This behavior guarantees that addition will never cause overflow. However, it does mean that an accumulator may grow larger than intended.
For example, summing 64 Q18.0 numbers will grow at maximum \(log_2(64) = 6\) bits, thus the accumulator should be sized to 24 integer bits.
from fixedpoint import FixedPoint
accum = FixedPoint(0, 1, 24, 0, overflow_alert='error', str_base=2)
max_neg = FixedPoint(-2**17, 1, 18, 0)
assert max_neg.clamped
for _ in range(64):
accum += max_neg
accum.clamp(24)
print(f"{int(accum)} in {accum:q} is\n0b{accum:_b}")
Summing the maximum negative Q18.0 number 64 times produces a Q24.0 that is
clamped to the maximum negative value. Note that accum.overflow_alert
was
set to 'error'
, thus we would have been informed had overflow occurred.
-8388608 in Q24.0 is
0b1000_0000_0000_0000_0000_0000
Subtraction¶
FixedPoint
subtraction using the -
or -=
operator is always
full-precision; that is, there is always bit growth.
Minuend |
Subtrahend |
Difference |
---|---|---|
\(UQm_1.n_1\)
(unsigned)
|
\(UQm_2.n_2\)
(unsigned)
|
\(UQx.y\), where
\(x = 1 + max\{m_1, m_2\}\)
\(y = max\{n_1, n_2\}\)
Overflow occurs if
subtrahend > minuend.
|
\(Qm_1.n_1\)
(signed)
|
\(Qm_2.n_2\)
(signed)
|
\(Qx.y\), where
\(x = 1 + max\{m_1, m_2\}\)
\(y = max\{n_1, n_2\}\)
|
\(Qm_1.n_1\)
(signed)
|
\(UQm_2.n_2\)
(unsigned)
|
\(Qx.y\), where
\(x = 2 + max\{m_1, m_2\}\)
\(y = max\{n_1, n_2\}\)
|
\(UQm_1.n_1\)
(unsigned)
|
\(Qm_2.n_2\)
(signed)
|
As indicated in the table, any combination of signed and unsigned numbers can be subtracted from each other. The difference is only unsigned when both augend and added are unsigned.
When signedness between minuend and subtrahend does not match, an extra integer bit is added to the unsigned term so it can be signed without overflowing.
Unsigned¶
>>> x = FixedPoint(14, signed=0, m=8, n=4)
>>> y = FixedPoint(6, signed=0, m=3, n=5)
>>> z = x - y
>>> print(f' {x:q}\n- {y:q}\n-------\n {z:q}')
UQ8.4
- UQ3.5
-------
UQ9.5
>>> float(z)
8.0
Overflow occurs when subtrahend > minuend.
>>> q_presub = y.qformat
>>> y.overflow_alert = 'warning'
>>> y -= x
WARNING [SN2]: Unsigned subtraction causes overflow.
WARNING [SN2]: Clamped to minimum.
>>> print(f' {q_presub}\n- {x:q}\n-------\n {y:q}')
UQ3.5
- UQ8.4
-------
UQ9.5
>>> float(y)
0.0
Signed¶
>>> x = FixedPoint(250 + 2**-6, signed=1)
>>> y = FixedPoint(-13 - 2**-8, signed=1)
>>> a = x - y
>>> print(f' {x:q}\n- {y:q}\n------\n {a:q}')
Q9.6
- Q5.8
------
Q10.8
>>> float(a)
263.01953125
>>> b = y - x
>>> print(f' {y:q}\n- {x:q}\n------\n {b:q}')
Q5.8
- Q9.6
------
Q10.8
>>> float(b)
-263.01953125
>>> a == -b
True
Overflow is not possible with signed subtraction.
Mixed Signedness¶
>>> s = FixedPoint(1, 1, 2)
>>> u = FixedPoint(1, 0, 2)
>>> x = u - s
WARNING [SN2]: Non-matching rounding behaviors ['convergent', 'nearest'].
WARNING [SN2]: Using 'convergent'.
>>> print(f' {u:q}\n- {s:q}\n------\n {x:q}')
UQ2.0
- Q2.0
------
Q4.0
>>> float(x)
0.0
Note that even though u and s can be represented without overflow in both
UQ2.0 and Q2.0 formats (their difference can too), 2 bits are still added
to the maximum integer bit width for the result. This makes for deterministic
bit growth. Use clamp()
or wrap()
to
revert back to the original Q format if needed.
>>> y = s - u
WARNING [SN1]: Non-matching rounding behaviors ['convergent', 'nearest'].
WARNING [SN1]: Using 'convergent'.
>>> print(f' {s:q}\n- {u:q}\n-------\n {y:q}')
Q2.0
- UQ2.0
-------
Q4.0
>>> float(y), clamp(y, s.m).qformat
(0.0, 'Q2.0')
Overflow is not possible with mixed signedness subtraction.
Multiplication¶
FixedPoint
multiplication using the *
or *=
operator is always
full-precision; that is, there is always bit growth.
Multiplicand |
Multiplier |
Product |
---|---|---|
\(UQm_1.n_1\)
(unsigned)
|
\(UQm_2.n_2\)
(unsigned)
|
\(UQx.y\), where
\(x = m_1 + m_2\)
\(y = n_1 + n_2\)
|
\(Qm_1.n_1\)
(signed)
|
\(Qm_2.n_2\)
(signed)
|
\(Qx.y\), where
\(x = m_1 + m_2\)
\(y = n_1 + n_2\)
|
\(Qm_1.n_1\)
(signed)
|
\(UQm_2.n_2\)
(unsigned)
|
|
\(UQm_1.n_1\)
(unsigned)
|
\(Qm_2.n_2\)
(signed)
|
Overflow is not possible using the multiplication operator.
Unsigned¶
>>> x = FixedPoint(10, n=2)
>>> y = FixedPoint(29, n=7)
>>> z = x * y
>>> print(f' {x:q}\n* {y:q}\n-------\n {z:q}')
UQ4.2
* UQ5.7
-------
UQ9.9
Signed¶
>>> x = FixedPoint(-4, signed=1, n=8)
>>> y = FixedPoint(2.5, signed=1)
>>> q = y.qformat
>>> y *= x
>>> print(f' {q}\n* {x:q}\n------\n {y:q}')
Q3.1
* Q3.8
------
Q6.9
>>> float(y)
-10.0
Mixed Signedness¶
>>> s = FixedPoint("0b1000", signed=1, m=3, n=1, rounding='nearest')
>>> u = FixedPoint("0b11", signed=0, m=2, n=0)
>>> z = u * s
>>> print(f"{u:.1f} * {s:.1f} = {z:.1f}")
3.0 * -4.0 = -12.0
>>> print(f' {u:q}\n* {s:q}\n------\n {z:q}')
UQ2.0
* Q3.1
------
Q5.1
Exponentiation¶
FixedPoint
exponentiation using the **
or **=
operator is always
full-precision; that is, there is always bit growth. Only positive integer
exponents are supported.
Base |
Exponent |
Result |
|
---|---|---|---|
\(UQm.n\)
(unsigned)
|
\(p \in \mathbb{Z}^+\)
(
int > 0) |
\(UQx.y\) |
where
\(x = p \times m\)
\(y = p \times n\)
|
\(Qm.n\)
(signed)
|
\(Qx.y\) |
>>> x = FixedPoint(1.5)
>>> y = FixedPoint(-1.5)
>>> x**y # not allowed
Traceback (most recent call last):
...
TypeError: Only positive integers are supported for exponentiation.
>>> x **= -2 # not allowed
Traceback (most recent call last):
...
TypeError: Only positive integers are supported for exponentiation.
>>> 2**x # not allowed
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'FixedPoint'
>>> a = x**4
>>> x.qformat, float(a), a.qformat
('UQ1.1', 5.0625, 'UQ4.4')
>>> b = y**3
>>> y.qformat, float(b), b.qformat
('Q2.1', -3.375, 'Q6.3')
Overflow is not possible using the power operators.
Negation & Absolute Value¶
Negation is achieved using the unary negation operator -
(see
FixedPoint.__neg__()
). Absolute value (see FixedPoint.__abs__()
)
is achieved using the negation operator on negative numbers, thus the same
behavior applies to unary negation and absolute value.
>>> x = FixedPoint(-4, m=10, overflow_alert='warning', str_base=2)
>>> float(y := -x)
4.0
>>> float(abs(x))
4.0
If the Q format can be maintained without overflow it will,
(as in the example above) otherwise an overflow alert is
issued, and the Q format of the result has an integer bit width one more than
the original FixedPoint
(as long as overflow_alert
is not 'error'
).
>>> y.qformat
'Q10.0'
>>> x.trim(ints=True) # remove unneeded leading bits
>>> x.qformat, float(x)
('Q3.0', -4.0)
>>> yy = -x
WARNING [SN1]: Negating 0b100 (Q3.0) causes overflow.
WARNING [SN1]: Adjusting Q format to Q4.0 to allow negation.
>>> x.qformat, y.qformat, yy.qformat, float(yy)
('Q3.0', 'Q10.0', 'Q4.0', 4.0)
>>> zz = abs(x)
WARNING [SN1]: Negating 0b100 (Q3.0) causes overflow.
WARNING [SN1]: Adjusting Q format to Q4.0 to allow negation.
>>> x.qformat, y.qformat, zz.qformat, float(zz)
('Q3.0', 'Q10.0', 'Q4.0', 4.0)
Unsigned numbers cannot be negated; this behavior is intended to minimize user error. Negating an unsigned number should be intentional. The preferred method is by use of the context manager:
>>> x = FixedPoint(3, signed=0)
>>> xx = abs(x)
>>> float(xx)
3.0
>>> -x
Traceback (most recent call last):
...
fixedpoint.FixedPointError: Unsigned numbers cannot be negated.
>>> with x(m=x.m + 1, signed=1): # Increase integer bit width for sign
... y = -x
>>> x.qformat, y.qformat, float(y)
('UQ2.0', 'Q3.0', -3.0)
Bitwise Operations¶
Bitwise operations do not cause overflow, nor do they modify the Q format.
Left Shift¶
Shifting bits left will cause MSbs to be lost. 0s are shifted into the LSb.
>>> x = FixedPoint('0b111000', 0, 3, 3, str_base=2)
>>> str(x << 2)
'100000'
To shift bits left and not lose bits, instead multiply the number by 2n, where n is the number of bits to shift.
>>> float(x) * 2**4
112.0
>>> y = x << 4
>>> float(y), y.qformat
(0.0, 'UQ3.3')
>>> z = x * 2**4
>>> float(z), z.qformat
(112.0, 'UQ8.3')
If the number of bits to shift is negative, a right shift is performed instead. For signed numbers, the value of the bits shifted in is the MSb. For unsigned numbers, 0s are shifted into the MSb.
>>> str(x << -2) # unsigned shift
'001110'
>>> with x(overflow_alert='ignore', overflow='wrap', signed=1): # signed shift
... str(x << -2)
'111110'
Right Shift¶
Shifting bits right will cause LSbs to be lost. 0s are shifted into the MSb for unsigned numbers. Sign bits are shifted into the MSb for signed numbers.
>>> notsigned = FixedPoint('0b111000', 0, 3, 3, str_base=2)
>>> signedneg = FixedPoint('0b111000', 1, 3, 3, str_base=2)
>>> signedpos = FixedPoint('0b011000', 1, 3, 3, str_base=2)
>>> print(f"{notsigned >> 2!s}\n{signedpos >> 2!s}\n{signedneg >> 2!s}")
001110
000110
111110
To shift bits left and not lose bits, instead multiply the number by 2-n, where n is the number of bits to shift.
If the number of bits to shift is negative, a left shift is performed instead. 0s are shifted into the LSb.
>>> print(f"{notsigned >> -2!s}\n{signedpos >> -2!s}\n{signedneg >> -2!s}")
100000
100000
100000
>>> x = FixedPoint(1, m=3)
>>> 2**-3 # Desired numerical value
0.125
>>> y = x >> 3
>>> float(y), y.qformat
(0.0, 'UQ3.0')
>>> z = x * 2**-3
>>> float(z), z.qformat
(0.125, 'UQ3.3')
AND, OR, XOR¶
The &
, &=
, |
, |=
, ^
, and ^=
operators perform bitwise
operations. A FixedPoint
is inter operable with an int
or
another FixedPoint
. In the latter case, the operand on the left will
be the Q format of the returned value.
>>> from operator import and_, or_, xor
>>> def operate(left, op, right):
... """Pretty display of using `op` with `left` and `right` operands"""
... r = {'&': and_, '|': or_, '^': xor}[op](left, right)
... l = max(len(left), len(right))
... return (f" {left:>{l}s} ({left:q})\n"
... f"{op} {right:>{l}s} ({right:q})\n"
... f"----------{'-' * l}\n"
... f" {r:>{l}s} ({r:q})")
>>> L = FixedPoint('0b100011', 0, 3, 3, str_base=2)
>>> R = FixedPoint(0b10, str_base=2)
>>> print(f" L & R\n{operate(L, '&', R)}")
L & R
100011 (UQ3.3)
& 10 (UQ2.0)
----------------
000010 (UQ3.3)
>>> print(f" R | L\n{operate(R, '|', L)}")
R | L
10 (UQ2.0)
| 100011 (UQ3.3)
----------------
11 (UQ2.0)
>>> print(f" L ^ R\n{operate(L, '^', R)}")
L ^ R
100011 (UQ3.3)
^ 10 (UQ2.0)
----------------
100001 (UQ3.3)
When using an int
as an operand, the operation is performed on the
FixedPoint.bits
attribute, and not the numerical value.
>>> x = FixedPoint('0b100011', 1, 3, 3, str_base=2)
>>> str(a := 7 & x)
'000011'
>>> float(a)
0.375
The order of the operands is irrelevant.
>>> str(b1 := x ^ 0b110000)
'010011'
>>> str(b2 := 0b110000 ^ x)
'010011'
>>> float(b1), float(b2)
(2.375, 2.375)
The integer is masked to the the number of bits in the FixedPoint
before
performing the operation.
>>> b1 |= 0b11111111111111111111101100 # (only the left len(b1) bits are used)
>>> str(b1), float(b1)
('111111', -0.125)
Inversion¶
Use the unary inversion operator ~
(see FixedPoint.__invert__()
) to
perform bitwise inversion.
>>> x = FixedPoint(0xAAAA)
>>> hex(~x)
'0x5555'
>>> ~x == (x ^ x.bitmask)
True
Bit Resizing¶
Attention
The code examples on this page change betwee the function version and the method version of the resizing operation. For example, y1, and y2 in the following example are equivalent, and x remains unchanged:
>>> (x := FixedPoint(-1.5)).qformat
'Q2.1'
>>> y1 = FixedPoint(x)
>>> y1.resize(10, 10)
>>> y2 = resize(x, 10, 10)
>>> print(f'{x.qformat=}\n{y1.qformat=}\n{y2.qformat=}')
x.qformat='Q2.1'
y1.qformat='Q10.10'
y2.qformat='Q10.10'
The function will operate on a copy of the given object, so the original object is not modified.
resize¶
Using FixedPoint.resize()
or resize()
, the fractional and integer
bit width can grow or shrink. The bit widths are modified based on the position
of the binary point, so as long as overflow or rounding does not occur, the
value does not change.
>>> from fixedpoint import FixedPoint
>>> def show(A):
... print(f"{A: <+5.2f} ", end="") # float
... print(f"{A:>5q} ", end="") # Q format
... print(f"{A:0{A.m+(A.m-1)//4}_bm}." if A.m else ".", end="")
... print(f"{A:0{A.n}_bn}" if A.n else "") # Show binary point
>>> neg_signed = FixedPoint(-2, 1, 4, 2)
>>> pos_signed = FixedPoint(+2, 1, 4, 2)
>>> pos_unsigned = FixedPoint(+2, 0, 4, 2)
>>> show(neg_signed)
-2.00 Q4.2 1110.00
>>> show(pos_signed)
+2.00 Q4.2 0010.00
>>> show(pos_unsigned)
+2.00 UQ4.2 0010.00
Increasing the integer bit width of a negative FixedPoint
will
sign-extend:
>>> x = resize(neg_signed, 7, 2)
>>> show(x)
-2.00 Q7.2 111_1110.00
Increasing the integer bit width of a positive FixedPoint
(sign or
unsigned) will pad with zeros:
>>> x = resize(pos_signed, 7, 2)
>>> show(x)
+2.00 Q7.2 000_0010.00
>>> y = resize(pos_unsigned, 7, 2)
>>> show(y)
+2.00 UQ7.2 000_0010.00
Since fractional bits always have a positive weight (by virtue of the fact that
the Q format does not allow for a non-positive integer bit
width for signed numbers), increasing the fractional bit width of any (signed
or unsigned) FixedPoint
will pad with zeros:
>>> show(resize(neg_signed, 4, 5))
-2.00 Q4.5 1110.0_0000
>>> show(resize(pos_signed, 4, 5))
+2.00 Q4.5 0010.0_0000
>>> show(resize(pos_unsigned, 4, 5))
+2.00 UQ4.5 0010.0_0000
Decreasing the integer bit width below the minimum number of bits required to represent it will result in overflow:
>>> neg_signed.resize(1, 5)
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN1] Overflow in format Q4.5.
Override the overflow_alert
property by setting the alert
argument to the desired alert level. Override the overflow
property by setting the overflow argument. These overrides only take effect
inside the function/method; the original property setting is restored after
resizing.
>>> show(resize(neg_signed, 1, 5, alert='warning', overflow='wrap'))
WARNING [SN10]: Overflow in format Q4.5.
WARNING [SN10]: Wrapped minimum.
+0.00 Q1.5 0.0_0000
>>> show(resize(pos_signed, 1, 2, alert='warning'))
WARNING [SN11]: Overflow in format Q4.2.
WARNING [SN11]: Clamped to maximum.
+0.75 Q1.2 0.11
>>> show(resize(pos_unsigned, 1, 0, alert='ignore'))
+1.00 UQ1.0 1.
Decreasing the fractional bit width below the minimum number of bits required
to represent it will result in rounding. Override the
rounding
property by setting the rounding argument.
This override only takes effect inside the function/method; the original
property setting is restored after resizing.
>>> neg_signed.rounding
'convergent'
>>> show(resize(neg_signed | 0b11, 3, 1))
-1.00 Q3.1 111.0
>>> show(resize(pos_signed | 0b11, 4, 1, rounding='down'))
+2.50 Q4.1 0010.1
>>> pos_signed.rounding
'convergent'
>>> show(resize(pos_unsigned | 0b11, 2, 0, 'out'))
+3.00 UQ2.0 11.
>>> pos_unsigned.rounding
'nearest'
Rounding can potentially cause overflow if the integer portion of the
FixedPoint
is already at its maximum. Only
certain rounding schemes can cause this.
>>> signed_maxed = FixedPoint('0xF', 1, 3, 2) # convergent rounding
>>> show(signed_maxed)
+3.75 Q3.2 011.11
>>> show(resize(signed_maxed, 3, 0, alert='warning', overflow='wrap'))
WARNING [SN20]: Convergent round to Q3.0 causes overflow.
WARNING [SN20]: Wrapped maximum.
-4.00 Q3.0 100.
When resizing, fractional bits are resized first, followed by integer bits. This could cause issues if (for example) the number being resized originally has 0 integer bits, and you are resizing to 0 fractional bits:
>>> orig = FixedPoint(0.25, rounding='up')
>>> show(orig)
+0.25 UQ0.2 .01
>>> orig.resize(4, 0) # resize to Q4.0
Traceback (most recent call last):
...
ValueError: Word size (integer and fractional) must be positive.
In this case, you’ll need to manually resize the integer bit width first, then the fractional:
>>> orig.m = 4
>>> orig.n = 0
>>> show(orig)
+1.00 UQ4.0 0001.
trim¶
Using FixedPoint.trim()
or trim()
will remove superfluous/insignificant bits.
>>> neg_signed = FixedPoint(-2, 1, 4, 2)
>>> pos_signed = FixedPoint(+2, 1, 4, 2)
>>> pos_unsigned = FixedPoint(+2, 0, 4, 2)
>>> show(neg_signed)
-2.00 Q4.2 1110.00
>>> show(trim(neg_signed))
-2.00 Q2.0 10.
>>> show(pos_signed)
+2.00 Q4.2 0010.00
>>> show(trim(pos_signed))
+2.00 Q3.0 010.
>>> show(pos_unsigned)
+2.00 UQ4.2 0010.00
>>> show(trim(pos_unsigned))
+2.00 UQ2.0 10.
You can opt to trim off only fractional or integer bits by setting fracs or int, respectively, to True.
>>> neg_signed.trim(ints=True)
>>> show(neg_signed)
-2.00 Q2.2 10.00
>>> pos_signed.trim(fracs=True)
>>> show(pos_signed)
+2.00 Q4.0 0010.
>>> pos_unsigned.trim(True, True) # same as pos_unsigned.trim()
>>> show(pos_unsigned)
+2.00 UQ2.0 10.
Zero is always trimmed to 1 integer bit and 0 fractional bits.
>>> signed = FixedPoint(0, 1, 4, 4)
>>> signed_no_frac = FixedPoint(0, 1, 4, 0)
>>> unsigned_no_int = FixedPoint(0, 0, 0, 4)
>>> show(signed)
+0.00 Q4.4 0000.0000
>>> show(trim(signed))
+0.00 Q1.0 0.
>>> show(signed_no_frac)
+0.00 Q4.0 0000.
>>> show(trim(signed_no_frac))
+0.00 Q1.0 0.
>>> show(unsigned_no_int)
+0.00 UQ0.4 .0000
>>> show(trim(unsigned_no_int))
+0.00 UQ1.0 0.
Rounding¶
See the Initialization page for numerical examples on various rounding schemes. The items described here warrant more information than what those examples show.
Default rounding¶
When a FixedPoint
is instantiated, a rounding scheme (whether
defaulted or explicitly specified) is determined.
The FixedPoint.round()
method and built-in round()
function use
the inherent rounding scheme.
>>> x = FixedPoint(1/3, n=24)
>>> x.rounding
'nearest'
>>> show(x)
+0.33 UQ0.24 .0101_0101_0101_0101_0101_0101
>>> show(round(x, 4))
+0.31 UQ0.4 .0101
>>> x.rounding = 'up'
>>> x.round(7)
>>> show(x)
+0.34 UQ0.7 .010_1011
Additionally, when shrinking the fractional bit width (via
FixedPoint.n
), the default rounding scheme is used.
>>> x.rounding = 'in'
>>> x.n = 3
>>> show(x)
+0.25 UQ0.3 .010
math.floor()
¶
When given a float
, math.floor()
will round towards
\(-\infty\) and return an int
type.
>>> import math
>>> x = math.floor(1/3)
>>> x, type(x)
(0, <class 'int'>)
>>> y = math.floor(-1/2)
>>> y, type(y)
(-1, <class 'int'>)
Using math.floor()
on a FixedPoint
will produce the same result,
but will not modify the fractional bit width. It simply sets all fractional
bits to 0.
>>> x = FixedPoint(-2**-5)
>>> y = math.floor(x)
>>> show(x); show(y)
-0.03 Q1.5 1.1_1111
-1.00 Q1.5 1.0_0000
The FixedPoint.round_down()
method is similar to math.floor()
, but
instead will change the fractional bit width. A bit mask can accomplish
the same thing as math.floor()
if importing math
is not desired.
>>> show(x); show(x & ~(2**x.n - 1))
-0.03 Q1.5 1.1_1111
-1.00 Q1.5 1.0_0000
math.ceil()
¶
When given a float
, math.ceil()
will round towards
\(+\infty\) and return an int
type.
>>> import math
>>> x = math.ceil(1/3)
>>> x, type(x)
(1, <class 'int'>)
>>> y = math.ceil(-1/2)
>>> y, type(y)
(0, <class 'int'>)
Using math.ceil()
on a FixedPoint
produces the same result.
Note that this can cause overflow.
>>> x = FixedPoint(2**-5, signed=True, overflow_alert='warning')
>>> y = math.ceil(x)
WARNING [SN2]: Rounding up to Q1.0 causes overflow.
WARNING [SN2]: Clamped to maximum.
>>> show(x); show(y)
+0.03 Q1.5 0.0_0001
+0.00 Q1.0 0.
Because the fractional bit width is changed to 0, unsigned numbers with no no integer bits will raise an exception.
>>> x = FixedPoint(2**-5)
>>> show(x)
+0.03 UQ0.5 .0_0001
>>> math.ceil(x)
Traceback (most recent call last):
...
ValueError: Word size (integer and fractional) must be positive.
math.trunc()
¶
When given a float
, math.trunc()
will round towards 0
(truncating decimal digits) and return an int
type.
>>> import math
>>> x = math.trunc(0.333333333333333333)
>>> x, type(x)
(0, <class 'int'>)
>>> y = math.trunc(-0.5)
>>> y, type(y)
(0, <class 'int'>)
The truncation that math.trunc()
performs on float
s is the
truncation of decimal digits. For FixedPoint
s, binary digits
are truncated, effectively flooring the number. Thus the only difference
between math.floor()
and math.trunc()
is that the latter leaves no
fractional bits in the return value.
Attention
Function |
Argument Type |
Truncated Digits |
Rounds Towards |
---|---|---|---|
binary |
\(-\infty\) |
||
decimal |
\(-\infty\) |
||
binary |
\(-\infty\) |
||
decimal |
0 |
>>> x = FixedPoint(-2**-5, signed=1)
>>> y = math.trunc(x)
>>> show(x); show(y)
-0.03 Q1.5 1.1_1111
-1.00 Q1.0 1.
Because the fractional bit width is changed to 0, unsigned numbers with no no integer bits will have the integer bit width set to 1.
>>> x = FixedPoint(2**-5)
>>> show(x)
+0.03 UQ0.5 .0_0001
>>> show(math.trunc(x))
+0.00 UQ1.0 0.
Rounding-induced overflow¶
The following rounding schemes can cause overflow under the right circumstances:
This is because each of these schemes can increase the value of a number toward
\(+\infty\) which can overflow into the integer bits. One possible
workaround (if clamping/wrapping is not desired) is to manually change the
integer bit width via FixedPoint.m
before rounding:
>>> x = FixedPoint("0b1111", 0, 2, 2)
>>> x.round_out(1)
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN1] Rounding out to UQ2.1 causes overflow.
>>> x.m += 1
>>> x.round_out(1)
>>> x.qformat, bin(x)
('UQ3.1', '0b1000')
Rounding beyond the fractional bit width¶
There may be times when you want to round away bits beyond the fractional bit
width (e.g., keep the most significant 18 bits of a Q24.18 number and round off
the rest). This can be done with FixedPoint.keep_msbs()
or
keep_msbs()
.
>>> x = FixedPoint('0x15555555555', 1, 24, 18, rounding='up')
>>> y = keep_msbs(x, 18, 0)
>>> print(f'{x: <6q} {x:_b}\n{y: <6q} {y:_b}')
Q24.18 1_0101_0101_0101_0101_0101_0101_0101_0101_0101_0101
Q18.0 1_0101_0101_0101_0110
Bit widths are calculated with respect to the MSb. This is not the same as
y = resize(x, 18, 0)
where the bit widths are calculated with respect to
the current binary point position.
Overflow Handling¶
See the Initialization page for numerical examples on various overflow handling schemes. The items described here warrant more information than what those examples show.
Clamping/wrapping below 0 integer bits¶
There may be times when you want to remove MSbs and still perform clamping (
e.g. keep the least significant 18 bits of a Q18.24 number but clamp/wrap the
entire value). This can be done with the FixedPoint.keep_lsbs()
or
keep_lsbs()
.
>>> x = FixedPoint('0x15555555555', 1, 18, 24)
>>> y = keep_lsbs(x, 18, 0, overflow='clamp', alert='ignore')
>>> print(f'{x: <6q} {x:_b}\n{y: <6q} {y:_b}')
Q18.24 1_0101_0101_0101_0101_0101_0101_0101_0101_0101_0101
Q18.0 1_1111_1111_1111_1111
Bit widths are calculated with respect to the LSb. This is not the same as
y = resize(x, 18, 0)
where the bit widths are calculated with respect to
the current binary point position.
Context Management¶
The FixedPoint
class offers richly-featured context management (see
PEP 343) that allows for some unique approaches to programatic arithmetic.
Three functions are utilized:
FixedPoint.__call__()
allows properties to be assigned in the
with statement at the start of the context;
this is called context initialization.
FixedPoint.__enter__()
save off the current state of the
FixedPoint
and assigns the properties specified by
__call__()
in the new context.
FixedPoint.__exit__()
restores the original context unless the
safe_retain
keyword was specified in __call__()
.
Basic Usage¶
Use the with statement to generate a scope in which changes to the original object can be undone:
>>> from fixedpoint import FixedPoint
>>> x = FixedPoint(1/9, signed=1)
>>> x.qformat
'Q1.54'
>>> with x: # save off the current state of x
... x.signed = 0
... x.m = 42
... x.qformat # show the changes that were made within the context
'UQ42.54'
>>> x.qformat # outisde of the with context, original x is restored
'Q1.54'
Any property or attribute of the original FixedPoint
can be changed within
the context. All changes made to FixedPoint
properties are restored at
context exit. These properties include:
Even the value can be changed with Arithmetic or Initializers.
>>> float(x)
0.1111111111111111
>>> with x:
... x.from_string("0x7FFFFFAAAA5555")
... float(x)
-7.947407237862691e-08
>>> float(x)
0.1111111111111111
New FixedPoint
s generated inside the context manager are valid and available
outside of the context. This is useful for temporarily overriding properties.
You can also rename a variable if desired.
>>> x = FixedPoint(0.2)
>>> y = FixedPoint(0.7)
>>> x.qformat, y.qformat
('UQ0.54', 'UQ0.52')
>>> z = x - y
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN3] Unsigned subtraction causes overflow.
>>> with x as xtmp, y as ytmp:
... xtmp.m, ytmp.m = 1, 1
... xtmp.signed, ytmp.signed = 1, 1
... z = x - y
... xtmp.qformat, ytmp.qformat, z.qformat
('Q1.54', 'Q1.52', 'Q2.54')
>>> x.qformat, y.qformat, z.qformat, float(round(z, 1))
('UQ0.54', 'UQ0.52', 'Q2.54', -0.5)
Context managers can be nested:
>>> def nest(x):
... print(f'0) {x.rounding=}')
... with x as y:
... print(f'1) {x.rounding=}')
... x.rounding = 'in'
... print(f'2) {x.rounding=}')
... with y as z:
... print(f'3) {x.rounding=}')
... z.rounding = 'convergent'
... print(f'4) {x.rounding=}')
... print(f'5) {x.rounding=}')
... print(f'6) {x.rounding=}')
>>> nest(FixedPoint(31))
0) x.rounding='nearest'
1) x.rounding='nearest'
2) x.rounding='in'
3) x.rounding='in'
4) x.rounding='convergent'
5) x.rounding='in'
6) x.rounding='nearest'
Context Initialization¶
In addition to saving off the current context of FixedPoint
objects, the
with statement can also initialize the new
context for you. Given x
, y
, and z
below,
>>> x = FixedPoint(-1)
>>> y = FixedPoint(1, mismatch_alert='error')
>>> z = x + y
Traceback (most recent call last):
...
fixedpoint.MismatchError: [SN2] Non-matching mismatch_alert behaviors ['warning', 'error'].
the following two code blocks accomplish the same goal:
>>> with x, y:
... x.rounding = 'nearest'
... x.mismatch_alert = 'error'
... z = x + y
>>> float(z)
0.0
>>> with x(rounding='nearest', mismatch_alert='error'):
... z = x + y
>>> float(z)
0.0
Any keywordable argument from the FixedPoint
constructor can be used in
the context manager. All initilization arguments must be keyworded. The
__call__()
keywords can be specified in a dict
if
preferred.
>>> xprop = {'rounding': 'nearest', 'mismatch_alert': 'warning'}
>>> yprop = {'mismatch_alert': 'warning'}
>>> with x(**xprop), y(**yprop):
... z = x + y
>>> x.rounding, x.mismatch_alert, y.rounding, y.mismatch_alert
('convergent', 'warning', 'nearest', 'error')
Retaining the Context¶
Context initialization also supports a safe_retain
keyword that, when
True
, will not restore the original FixedPoint
context as long as
no exceptions occur.
>>> x = FixedPoint(3, str_base=10)
>>> x.qformat
'UQ2.0'
>>> with x(safe_retain=True):
... x.signed = True
Traceback (most recent call last):
...
fixedpoint.FixedPointOverflowError: [SN1] Changing signedness on 3 causes overflow.
>>> x.signed, x.qformat # Changes were not retained because of exception
(False, 'UQ2.0')
>>> with x(m=3, safe_retain=True):
... x.signed = True
>>> x.signed, x.qformat # Changes were retained
(True, 'Q3.0')
This is useful when several properties/attributes might change, and if all
changes are made successfully, the properties should be retained. In fact,
this is exactly how FixedPoint.resize()
is implemented:
def resize(self: FixedPointType, m: int, n: int, /, rounding: str = None,
overflow: str = None, alert: str = None) -> None:
"""Resize integer and fractional bit widths.
Overflow handling, sign-extension, and rounding are employed.
Override rounding, overflow, and overflow_alert settings for the
scope of this method by specifying the appropriate arguments.
"""
old = self._overflow, self._rounding, self._overflow_alert
try:
with self(safe_retain=True,
overflow=overflow or self.overflow,
rounding=rounding or self.rounding,
overflow_alert=alert or self.overflow_alert):
self.n = n
self.m = m
except Exception:
raise
else:
self._overflow, self._rounding, self._overflow_alert = old
The magic here is that if self.m = m
raises an exception, then the
assignment on the line just before it is undone by the context manager. However,
if no exception occurs, then the assignments to the m
and n
attributes
are kept and the number is resized.
Bit Slicing¶
Sometimes you want to access only certain bits of a FixedPoint
number.
The FixedPoint.bits
attribute returns a FixedPointBits
object,
which is an int
that support square bracket access.
Bit Random Access¶
One or more contiguous bits in the FixedPointBits
can be accessed
with an int
or slice
key.
Single-Bit Random Access¶
To access a single bit use an integer key. Bits are indexed with the MSb being
index m+n-1
and the LSb being index 0.
>>> x = FixedPoint('0b001001', signed=0, m=3, n=3, str_base=2)
>>> bin(x.bits), x.bits[3]
('0b1001', 1)
You can also access a single bit using a slice
when start and stop
values are equal. The slice step must be either
-1 (indicating a descending range with the MSb as index
m+n-1
and the LSb as index 0)+1 (indicating an ascending range with the MSb as index 0 and the LSb as index
m+n-1
)
>>> x = FixedPoint('0b001000', signed=0, m=3, n=3)
>>> x.bits[3:3:-1] # the middle '1' with a descending range
1
>>> x.bits[2:2:1] # the middle '1' with an ascending range
1
Attempting to access a single bit in this fashion (the slice start and stop are equal) without specifying a step results in an error.
>>> x.bits[3:3]
Traceback (most recent call last):
...
IndexError: Step must be 1 or -1 for equivalent start and stop bound 3.
Multi-Bit Random Access¶
To access multiple bits at a time, slice
s are employed. Both
ascending and descending ranges are supported.
>>> x = FixedPoint(0b0001100, m=7)
>>> x.bits[3:2] # Access the middle two 1s using a descending range
3
>>> x.bits[3:2:-1] # The step can be -1 for clarity but is unnecessary
3
>>> x.bits[3:4] # Access the middle two 1s using an ascending range
3
>>> x.bits[3:4:1] # The step can be +1 for clarity but is unnecessary
3
When a step is used that is not 1 or -1, or when the start/stop index is
negative, the slice accesses the bits as if they were a str
.
>>> x = FixedPoint(0b100_100_100_100)
>>> x.bits[::3] # Get every 3rd bit starting from the first
15
>>> bin(x.bits[:-6]) # Get the last 6 bits
'0b100100'
Bit Mappings¶
Common parts of the FixedPoint
bit string are mapped to keys, specified as
strings (like a dict
).
These include:
integer bits (
'm'
or'int'
)fractional bits (
'n'
or'frac'
)sign bit (
's'
or'sign'
)most significant bit (
'msb'
)least significant bit (
'lsb'
)
If the portion of the FixedPoint
bits does not exist (e.g., the sign bit of
an unsigned number), a KeyError
is raised.
>>> intonly = signed = FixedPoint("0b1110", 1, 4, 0)
>>> fraconly = unsigned = FixedPoint("0b0001", 0, 0, 4)
>>> intonly.bits['m']
14
>>> fraconly.bits['int']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'int' for UQ0.4 format."
>>> intonly.bits['n']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'n' for Q4.0 format."
>>> signed.bits['sign']
1
>>> (-signed).bits['s']
0
>>> unsigned.bits['sign']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'sign' for UQ0.4 format."
>>> intonly.bits['msb'], intonly.bits['lsb']
(1, 0)
>>> fraconly.bits['msb'], fraconly.bits['lsb']
(0, 1)
When the mappings are uppercased, a str
type is returned corresponding
to the binary bits.
>>> intonly = signed = FixedPoint("0b1110", 1, 4, 0)
>>> fraconly = unsigned = FixedPoint("0b0001", 0, 0, 4)
>>> intonly.bits['M']
'1110'
>>> fraconly.bits['INT']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'INT' for UQ0.4 format."
>>> intonly.bits['N']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'N' for Q4.0 format."
>>> signed.bits['SIGN']
'1'
>>> (-signed).bits['S']
'0'
>>> unsigned.bits['SIGN']
Traceback (most recent call last):
...
KeyError: "Invalid bit specification 'SIGN' for UQ0.4 format."
>>> intonly.bits['MSB'], intonly.bits['LSB']
('1', '0')
>>> fraconly.bits['MSB'], fraconly.bits['LSB']
('0', '1')
String Conversion and Formatting¶
When you need to generate a string representation of a FixedPoint
number (such as stimulus generation for a test), you can use standard string
conversion (via str()
) or a more advanced string formatting using a
standard format specifier
with str.format()
, format()
, or
f-strings. These methods are
described below.
String Conversion¶
Calling str()
on a FixedPoint
generates a decimal, binary, octal,
or hexadecimal string based on the FixedPoint.bits
. The latter 3 of
which are 0-padded (if necessary) to the bit length of the FixedPoint
number. No radix is included.
>>> init = '0b11001'
>>> b = FixedPoint(init, 1, 3, 2, str_base=2)
>>> str(b)
'11001'
>>> o = FixedPoint(init, 1, 3, 2, str_base=8)
>>> str(o)
'31'
>>> d = FixedPoint(init, 1, 3, 2, str_base=10)
>>> str(d)
'25'
>>> h = FixedPoint(init, 1, 3, 2, str_base=16)
>>> str(h)
'19'
String Formatting¶
A
FixedPoint
can be formatted as astr
,float
, orint
would, depending on the format string syntax.
Standard Format Specifier Parsing Summary¶ format_spec
type
Formatted Type
Formatted Value(givenx = FixedPoint(...)
)
's'
str(x)
(depends onx.str_base
)
'q'
x.qformat
'b'
(binary)
x.bits
'd'
(decimal)'o'
(octal)'x'
(lowercasehexadecimal)'X'
(uppercasehexadecimal)
'...m'
1x.bits['int']
(integer bits only)
'...n'
1x.bits['frac']
(fractional bits only)
'e'
float(x)
'E'
'f'
'F'
'g'
'G'
'%'
1 Append to the specifier of another formatted
int
. E.g.,'bn'
would format the fractional bits ofx
in binary.
str() Output¶
As described above, str()
generates a str
from the FixedPoint.bits
in the base specified by
FixedPoint.str_base
. This can be further formatted with the
format specification mini language using the format_spec
type
's'
.
The example below uses a formatted string literal (or f-string) to further format the output of str()
.
>>> x = FixedPoint(0b1010_0101_1111, str_base=2)
>>> str(x) # This is the str() output
'101001011111'
>>> f"{x:_^16s}" # Center str(x) in a field of underscores 16 characters wide
'__101001011111__'
>>> x.str_base = 16
>>> f"{x:_^16s}" # Same thing but uses hex instead of binary due to str_base
'______a5f_______'
The same thing can be done using str.format()
:
>>> x.str_base = 8 # octal
>>> '{:-^16s}'.format(x)
'------5137------'
or format()
:
>>> x.str_base = 10
>>> format(x, '~>6s')
'~~2655'
The remaining examples will be done using f-strings, but the same syntax applies to
str.format()
and format()
.
Q Format¶
Using the format_spec
type
'q'
allows you to format the
FixedPoint.qformat
output as a string.
>>> a = FixedPoint(-12345.678)
>>> f"{a:q}"
'Q15.36'
>>> f"{a: ^10q}"
' Q15.36 '
FixedPoint.bits¶
Using the format_spec
type
'b'
, 'o'
, 'd'
,
'x'
, or 'X'
allow you to format the FixedPoint.bits
as an
int
.
>>> a = FixedPoint(0b1111_0000_1011, m=14)
>>> f"{a:#0{2 + len(a) // 4 + len(a)}_b}" # add 2 for radix, // 4 for seperators
'0b00_1111_0000_1011'
>>> f"{a:010,d}"
'00,003,851'
>>> f"{a:=^+#10X}"
'==+0XF0B=='
Integer and Fractional Bits¶
Using the format_spec
type
'm'
or 'n'
allows you
to format the integer and fractional bits as an int
. Precede these
type
s with other standard types like 'b'
, 'o'
, 'd'
,
'n'
, 'x'
, or 'X'
.
>>> a = FixedPoint('0b11001100', signed=0, m=4, n=5)
>>> f"{a:#0{a.m+2}bm}.{a:0{a.n}bn}" # Show the binary point
'0b0110.01100'
Float Equivalent¶
Using the format_spec
type
'e'
, 'E'
, 'f'
,
'F'
, 'g'
, 'G'
, or '%'
allow you to format the
FixedPoint
as a float
.
>>> a = FixedPoint(1.125, rounding='up')
>>> f"{a:#0{2+a.m}bm}.{a:0{a.n}bn} ==> {a:.3f}"
'0b1.001 ==> 1.125'
>>> f"{a:.2f}" # Show 2 decimal points
'1.12'
Attention
Convergent rounding is used for rounding float
s in the example
above, which is the default rounding method specified by IEEE 754. This
will be the case regardless of the FixedPoint.rounding
property
specified.
>>> f"{a:.3%}"
'112.500%'
>>> f"{a - 1:.2%}"
'12.50%'
>>> import sys
>>> b = FixedPoint(2**sys.float_info.min_exp)
>>> f"{b:+e}"
'+4.450148e-308'
Miscellaneous¶
Logging Integration¶
The fixedpoint
package uses standard logging constructs to generate
warnings and debug logs. The following specifications allow you to customize
the logging schemes, handlers, formats, etc. to your liking.
Warnings¶
fixedpoint
warnings are generated using the logging
package.
-
fixedpoint.logging.
WARNER_CONSOLE_HANDLER
¶ - Type
- Value
stream is set to
sys.stderr
level is set to logging.DEBUG.
-
fixedpoint.logging.
WARNER
¶ - Type
- Value
name is FP.CONSOLE
level defaults to logging.WARNING
You can retrieve this logger with
logging.getLogger("FP.CONSOLE")
.
The WARNER_CONSOLE_HANDLER
is added to WARNER
.
Additionally, each FixedPoint
object has a unique
serial number associated with it that is available in the
LogRecord
instance as the key sn. This is described in
more detail here as the extra
keyword.
Debug Logging¶
Logging is also used for debug purposes.
-
fixedpoint.logging.
LOGGER
¶ - Type
- Value
name is FP
level defaults to logging.CRITICAL
-
fixedpoint.logging.
DEFAULT_FILE_HANDLER
¶ - Type
- Value
filename is set to fixedpoint.log located in the same directory as the source code
mode is set to ‘w’
delay is set to True, thus no file is generated (or overwritten) until logging is enabled with
fixedpoint.FixedPoint.enable_logging()
level defaults to logging.DEBUG
The DEFAULT_FILE_HANDLER
is added to the LOGGER
.
On initial import, LOGGER
’s level is set to logging.CRITICAL. Since
no critical level logs are made within fixedpoint
, it essentially
disables debug logging.
When FixedPoint.enable_logging()
is called,
LOGGER
’s level is set to logging.DEBUG.
When FixedPoint.disable_logging()
is called,
LOGGER
’s level is set back to logging.CRITICAL.
Typing¶
The fixedpoint
package is typed (see PEP 484) and supported by
mypy,
PyCharm, etc.
Subclassing FixedPoint
is also supported.
Numpy Integration¶
While not specifically tested, integration with numpy
should be possible as
long as unsupported operators (like @
, /
, //
, %
, etc.) are not
used.
Examples taken from the numpy.convolve
documentation:
>>> import numpy as np
>>> a = [FixedPoint(1), FixedPoint(2), FixedPoint(3)]
>>> b = [FixedPoint(0), FixedPoint(1), FixedPoint(0.5)]
>>> x = np.convolve(a, b)
>>> [float(fp) for fp in x]
[0.0, 1.0, 2.5, 4.0, 1.5]
>>> y = np.convolve(a, b, 'same')
>>> [float(fp) for fp in y]
[1.0, 2.5, 4.0]
>>> z = np.convolve(a, b, 'valid')
>>> [float(fp) for fp in z]
[2.5]
Serialization¶
JSON¶
-
class
fixedpoint.json.
JSONEncoder
¶
-
class
fixedpoint.json.
JSONDecoder
¶
>>> from fixedpoint.json import FixedPointEncoder, FixedPointDecoder
>>> import random, json
>>> L = 52
>>> signed = random.randrange(2)
>>> m = random.randrange(L)
>>> n = L - m
>>> original = FixedPoint(hex(random.getrandbits(L)), signed, m, n)
>>> serialized = json.dumps(original, cls=FixedPointEncoder)
>>> deserialized = json.loads(serialized, cls=FixedPointDecoder)
>>> original == deserialized
True
Pickle¶
The pickle
scheme works out of the box:
>>> import random, pickle
>>> L = 52
>>> signed = random.randrange(2)
>>> m = random.randrange(signed, L)
>>> n = L - m
>>> original = FixedPoint(hex(random.getrandbits(L)), signed, m, n)
>>> pickled = pickle.dumps(original)
>>> unpickled = pickle.loads(pickled)
>>> original == unpickled
True
Indices and tables¶
License¶
The fixedpoint package is released under the BSD license.
Copyright (c) 2019-2020, Schweitzer Engineering Laboratories, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.