flexfloat 0.1.3__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flexfloat/__init__.py +21 -17
- flexfloat/bitarray/__init__.py +21 -80
- flexfloat/bitarray/bitarray.py +154 -54
- flexfloat/bitarray/bitarray_bigint.py +305 -0
- flexfloat/bitarray/bitarray_bool.py +202 -0
- flexfloat/bitarray/bitarray_int64.py +174 -149
- flexfloat/bitarray/bitarray_mixins.py +110 -47
- flexfloat/core.py +215 -113
- flexfloat/types.py +7 -1
- {flexfloat-0.1.3.dist-info → flexfloat-0.3.0.dist-info}/METADATA +48 -25
- flexfloat-0.3.0.dist-info/RECORD +15 -0
- flexfloat/bitarray/bitarray_list.py +0 -187
- flexfloat-0.1.3.dist-info/RECORD +0 -14
- {flexfloat-0.1.3.dist-info → flexfloat-0.3.0.dist-info}/WHEEL +0 -0
- {flexfloat-0.1.3.dist-info → flexfloat-0.3.0.dist-info}/licenses/LICENSE +0 -0
- {flexfloat-0.1.3.dist-info → flexfloat-0.3.0.dist-info}/top_level.txt +0 -0
flexfloat/types.py
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
"""Type definitions for the flexfloat package.
|
1
|
+
"""Type definitions for the flexfloat package.
|
2
|
+
|
3
|
+
This module provides type aliases used throughout the flexfloat package.
|
4
|
+
|
5
|
+
Type Aliases:
|
6
|
+
Number: Alias for int | float, used for numeric arguments.
|
7
|
+
"""
|
2
8
|
|
3
9
|
from typing import TypeAlias
|
4
10
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: flexfloat
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.3.0
|
4
4
|
Summary: A library for arbitrary precision floating point arithmetic
|
5
5
|
Author: Ferran Sanchez Llado
|
6
6
|
License: MIT
|
@@ -45,7 +45,7 @@ A high-precision Python library for arbitrary precision floating-point arithmeti
|
|
45
45
|
- **🔢 Growable Exponents**: Dynamically expand exponent size to handle extremely large (>10^308) or small (<10^-308) numbers
|
46
46
|
- **🎯 Fixed-Size Fractions**: Maintain IEEE 754-compatible 52-bit fraction precision for consistent accuracy
|
47
47
|
- **⚡ Full Arithmetic Support**: Addition, subtraction, multiplication, division, and power operations
|
48
|
-
- **🔧 Multiple BitArray Backends**: Choose between list-
|
48
|
+
- **🔧 Multiple BitArray Backends**: Choose between bool-list, int64-list, and big-integer implementations for optimal performance
|
49
49
|
- **🌟 Special Value Handling**: Complete support for NaN, ±infinity, and zero values
|
50
50
|
- **🛡️ Overflow Protection**: Automatic exponent growth prevents overflow/underflow errors
|
51
51
|
- **📊 IEEE 754 Baseline**: Fully compatible with standard double-precision format as the starting point
|
@@ -81,12 +81,15 @@ print(f"Exponent bits: {len(large_result.exponent)}") # > 11 (grown beyond IEEE
|
|
81
81
|
print(f"Can represent: {large_result}") # No overflow!
|
82
82
|
```
|
83
83
|
|
84
|
-
### Advanced
|
84
|
+
### Advanced Features
|
85
85
|
|
86
86
|
```python
|
87
|
-
from flexfloat import FlexFloat
|
87
|
+
from flexfloat import FlexFloat, BigIntBitArray
|
88
|
+
|
89
|
+
# Use different BitArray implementations for specific needs
|
90
|
+
FlexFloat.set_bitarray_implementation(BigIntBitArray)
|
88
91
|
|
89
|
-
# Mathematical operations
|
92
|
+
# Mathematical operations with unlimited precision
|
90
93
|
x = FlexFloat.from_float(2.0)
|
91
94
|
y = FlexFloat.from_float(3.0)
|
92
95
|
|
@@ -98,10 +101,13 @@ print(power_result.to_float()) # 8.0
|
|
98
101
|
e_result = FlexFloat.e ** x # e^2
|
99
102
|
print(f"e^2 ≈ {e_result.to_float()}")
|
100
103
|
|
104
|
+
# Absolute value operations
|
105
|
+
abs_result = abs(FlexFloat.from_float(-42.0))
|
106
|
+
print(f"|-42| = {abs_result.to_float()}") # 42.0
|
107
|
+
|
101
108
|
# Working with extreme values
|
102
|
-
tiny = FlexFloat.from_float(1e-300)
|
103
109
|
huge = FlexFloat.from_float(1e300)
|
104
|
-
extreme_product =
|
110
|
+
extreme_product = huge * huge
|
105
111
|
print(f"Product: {extreme_product.to_float()}") # Still computable!
|
106
112
|
|
107
113
|
# Precision demonstration
|
@@ -111,35 +117,40 @@ print(f"1/3 with 52-bit precision: {precise_calc}")
|
|
111
117
|
|
112
118
|
## 🔧 BitArray Backends
|
113
119
|
|
114
|
-
FlexFloat supports multiple BitArray implementations for different performance characteristics:
|
120
|
+
FlexFloat supports multiple BitArray implementations for different performance characteristics. You can use them directly or configure FlexFloat to use a specific implementation:
|
115
121
|
|
116
122
|
```python
|
117
123
|
from flexfloat import (
|
118
124
|
FlexFloat,
|
119
|
-
|
120
|
-
|
125
|
+
ListBoolBitArray,
|
126
|
+
ListInt64BitArray,
|
127
|
+
BigIntBitArray
|
121
128
|
)
|
122
129
|
|
123
|
-
#
|
124
|
-
|
125
|
-
|
126
|
-
# Use list-based implementation (default, more flexible)
|
127
|
-
set_default_implementation('list')
|
128
|
-
flex_list = FlexFloat.from_float(42.0)
|
130
|
+
# Configure FlexFloat to use a specific BitArray implementation
|
131
|
+
FlexFloat.set_bitarray_implementation(ListBoolBitArray) # Default
|
132
|
+
flex_bool = FlexFloat.from_float(42.0)
|
129
133
|
|
130
|
-
#
|
131
|
-
set_default_implementation('int64')
|
134
|
+
FlexFloat.set_bitarray_implementation(ListInt64BitArray) # For performance
|
132
135
|
flex_int64 = FlexFloat.from_float(42.0)
|
133
136
|
|
134
|
-
#
|
137
|
+
FlexFloat.set_bitarray_implementation(BigIntBitArray) # For very large arrays
|
138
|
+
flex_bigint = FlexFloat.from_float(42.0)
|
139
|
+
|
140
|
+
# Use BitArray implementations directly
|
141
|
+
bits = [True, False, True, False]
|
142
|
+
bool_array = ListBoolBitArray.from_bits(bits)
|
143
|
+
int64_array = ListInt64BitArray.from_bits(bits)
|
144
|
+
bigint_array = BigIntBitArray.from_bits(bits)
|
135
145
|
```
|
136
146
|
|
137
147
|
### Implementation Comparison
|
138
148
|
|
139
149
|
| Implementation | Best For | Pros | Cons |
|
140
150
|
|---------------|----------|------|------|
|
141
|
-
| `
|
142
|
-
| `
|
151
|
+
| `ListBoolBitArray` | Testing and development | Simple, flexible, easy to debug | Slower for large operations |
|
152
|
+
| `ListInt64BitArray` | Standard operations | Fast for medium-sized arrays, memory efficient | Some overhead for very small arrays |
|
153
|
+
| `BigIntBitArray` | Any usescases | Python already optimizes it | Overhead for small arrays |
|
143
154
|
|
144
155
|
## 📚 API Reference
|
145
156
|
|
@@ -159,6 +170,11 @@ abs(a), -a
|
|
159
170
|
|
160
171
|
# Mathematical functions
|
161
172
|
FlexFloat.e ** x # Exponential function
|
173
|
+
flexfloat.exp() # Natural exponential
|
174
|
+
flexfloat.abs() # Absolute value
|
175
|
+
|
176
|
+
# BitArray configuration
|
177
|
+
FlexFloat.set_bitarray_implementation(implementation: Type[BitArray])
|
162
178
|
```
|
163
179
|
|
164
180
|
### Special Values
|
@@ -269,8 +285,9 @@ flexfloat/
|
|
269
285
|
├── types.py # Type definitions
|
270
286
|
├── bitarray/ # BitArray implementations
|
271
287
|
│ ├── bitarray.py # Abstract base class
|
272
|
-
│ ├──
|
273
|
-
│ ├── bitarray_int64.py #
|
288
|
+
│ ├── bitarray_bool.py # List[bool] implementation
|
289
|
+
│ ├── bitarray_int64.py # List[int64] implementation
|
290
|
+
│ ├── bitarray_bigint.py # Python int implementation
|
274
291
|
│ └── bitarray_mixins.py # Common functionality
|
275
292
|
└── __init__.py # Public API exports
|
276
293
|
```
|
@@ -301,8 +318,14 @@ flexfloat/
|
|
301
318
|
### Optimization Tips
|
302
319
|
|
303
320
|
```python
|
304
|
-
|
305
|
-
|
321
|
+
from flexfloat import FlexFloat, ListInt64BitArray, BigIntBitArray
|
322
|
+
|
323
|
+
# Choose the right BitArray implementation for your use case
|
324
|
+
# For standard operations with moderate precision
|
325
|
+
FlexFloat.set_bitarray_implementation(ListInt64BitArray)
|
326
|
+
|
327
|
+
# For most use cases, Python's int is already optimized
|
328
|
+
FlexFloat.set_bitarray_implementation(BigIntBitArray)
|
306
329
|
|
307
330
|
# Batch operations when possible
|
308
331
|
values = [FlexFloat.from_float(x) for x in range(1000)]
|
@@ -0,0 +1,15 @@
|
|
1
|
+
flexfloat/__init__.py,sha256=Y7oR-CRyfDv_ImzcS4jkVveMzaXc2BHvAyzItgUaF3E,933
|
2
|
+
flexfloat/core.py,sha256=EQiBMmUtDreWFLjVeuaEiEj-PyNNcOV9BmRtOCs4neU,42821
|
3
|
+
flexfloat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
+
flexfloat/types.py,sha256=Enm4-oyGnvxGI-7MOK6eEIH2IzWafk0wQBsPaTqFYrE,266
|
5
|
+
flexfloat/bitarray/__init__.py,sha256=aFnw7HSlFwWnFwmLhmjvRwt6qOakbUochHwT8di0v14,979
|
6
|
+
flexfloat/bitarray/bitarray.py,sha256=L8CYFSxyMgfV-CpvtrKJ_kO3nexsHK2E2pNN9BfnNyI,8428
|
7
|
+
flexfloat/bitarray/bitarray_bigint.py,sha256=yLfAreZ9hhP2f2dIS7ptYSuAFlUTXJiv-LtHhRWN5dc,9986
|
8
|
+
flexfloat/bitarray/bitarray_bool.py,sha256=naTUcTycvP9BfU1_CJRgajgvsJoQz9jvi5aI224pphE,6429
|
9
|
+
flexfloat/bitarray/bitarray_int64.py,sha256=FLfbg2gk_Ia-9_4UjoiWYZNK3CbD4teAYU5SGSV3WF0,10856
|
10
|
+
flexfloat/bitarray/bitarray_mixins.py,sha256=HJkyseP_yat0tE3_XElFEqBgKk8oWEiHEKjzqIRwUnw,5026
|
11
|
+
flexfloat-0.3.0.dist-info/licenses/LICENSE,sha256=uwwkK--SUYUV3lbrv9kXJ_vDiYfHVb-t732g6c4qg7Q,1077
|
12
|
+
flexfloat-0.3.0.dist-info/METADATA,sha256=l9sXHmygreTApX2unPPQny_I8vVekmGUl-A0SLcbXSU,11510
|
13
|
+
flexfloat-0.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
14
|
+
flexfloat-0.3.0.dist-info/top_level.txt,sha256=82S8dY2UoNZh-9pwg7tUvbwB3uw2s3mfEoyUW6vCMdU,10
|
15
|
+
flexfloat-0.3.0.dist-info/RECORD,,
|
@@ -1,187 +0,0 @@
|
|
1
|
-
"""List-based BitArray implementation for the flexfloat package."""
|
2
|
-
|
3
|
-
from __future__ import annotations
|
4
|
-
|
5
|
-
import struct
|
6
|
-
from typing import Iterator, overload
|
7
|
-
|
8
|
-
from .bitarray import BitArray
|
9
|
-
from .bitarray_mixins import BitArrayCommonMixin
|
10
|
-
|
11
|
-
|
12
|
-
class ListBitArray(BitArrayCommonMixin):
|
13
|
-
"""A bit array class that encapsulates a list of booleans with utility methods.
|
14
|
-
|
15
|
-
This class provides all the functionality previously available through utility
|
16
|
-
functions, now encapsulated as methods for better object-oriented design.
|
17
|
-
"""
|
18
|
-
|
19
|
-
def __init__(self, bits: list[bool] | None = None):
|
20
|
-
"""Initialize a BitArray.
|
21
|
-
|
22
|
-
Args:
|
23
|
-
bits: Initial list of boolean values. Defaults to empty list.
|
24
|
-
"""
|
25
|
-
self._bits = bits if bits is not None else []
|
26
|
-
|
27
|
-
@classmethod
|
28
|
-
def zeros(cls, length: int) -> ListBitArray:
|
29
|
-
"""Create a BitArray filled with zeros.
|
30
|
-
|
31
|
-
Args:
|
32
|
-
length: The length of the bit array.
|
33
|
-
Returns:
|
34
|
-
ListBitArray: A BitArray filled with False values.
|
35
|
-
"""
|
36
|
-
return cls([False] * length)
|
37
|
-
|
38
|
-
@classmethod
|
39
|
-
def ones(cls, length: int) -> ListBitArray:
|
40
|
-
"""Create a BitArray filled with ones.
|
41
|
-
|
42
|
-
Args:
|
43
|
-
length: The length of the bit array.
|
44
|
-
Returns:
|
45
|
-
ListBitArray: A BitArray filled with True values.
|
46
|
-
"""
|
47
|
-
return cls([True] * length)
|
48
|
-
|
49
|
-
@staticmethod
|
50
|
-
def parse_bitarray(bitstring: str) -> ListBitArray:
|
51
|
-
"""Parse a string of bits (with optional spaces) into a BitArray instance."""
|
52
|
-
bits = [c == "1" for c in bitstring if c in "01"]
|
53
|
-
return ListBitArray(bits)
|
54
|
-
|
55
|
-
def to_float(self) -> float:
|
56
|
-
"""Convert a 64-bit array to a floating-point number.
|
57
|
-
|
58
|
-
Returns:
|
59
|
-
float: The floating-point number represented by the bit array.
|
60
|
-
Raises:
|
61
|
-
AssertionError: If the bit array is not 64 bits long.
|
62
|
-
"""
|
63
|
-
assert len(self._bits) == 64, "Bit array must be 64 bits long."
|
64
|
-
|
65
|
-
byte_values = bytearray()
|
66
|
-
for i in range(0, 64, 8):
|
67
|
-
byte = 0
|
68
|
-
for j in range(8):
|
69
|
-
if self._bits[i + j]:
|
70
|
-
byte |= 1 << (7 - j)
|
71
|
-
byte_values.append(byte)
|
72
|
-
# Unpack as double precision (64 bits)
|
73
|
-
return struct.unpack("!d", bytes(byte_values))[0] # type: ignore
|
74
|
-
|
75
|
-
def to_int(self) -> int:
|
76
|
-
"""Convert the bit array to an unsigned integer.
|
77
|
-
|
78
|
-
Returns:
|
79
|
-
int: The integer represented by the bit array.
|
80
|
-
"""
|
81
|
-
return sum((1 << i) for i, bit in enumerate(reversed(self._bits)) if bit)
|
82
|
-
|
83
|
-
def to_signed_int(self) -> int:
|
84
|
-
"""Convert a bit array into a signed integer using off-set binary
|
85
|
-
representation.
|
86
|
-
|
87
|
-
Returns:
|
88
|
-
int: The signed integer represented by the bit array.
|
89
|
-
Raises:
|
90
|
-
AssertionError: If the bit array is empty.
|
91
|
-
"""
|
92
|
-
assert len(self._bits) > 0, "Bit array must not be empty."
|
93
|
-
|
94
|
-
int_value = self.to_int()
|
95
|
-
# Half of the maximum value
|
96
|
-
bias = 1 << (len(self._bits) - 1)
|
97
|
-
# If the sign bit is set, subtract the bias
|
98
|
-
return int_value - bias
|
99
|
-
|
100
|
-
def shift(self, shift_amount: int, fill: bool = False) -> ListBitArray:
|
101
|
-
"""Shift the bit array left or right by a specified number of bits.
|
102
|
-
|
103
|
-
This function shifts the bits in the array, filling in new bits with the
|
104
|
-
specified fill value.
|
105
|
-
If the value is positive, it shifts left; if negative, it shifts right.
|
106
|
-
Fills the new bits with the specified fill value (default is False).
|
107
|
-
|
108
|
-
Args:
|
109
|
-
shift_amount (int): The number of bits to shift. Positive for left shift,
|
110
|
-
negative for right shift.
|
111
|
-
fill (bool): The value to fill in the new bits created by the shift.
|
112
|
-
Defaults to False.
|
113
|
-
Returns:
|
114
|
-
ListBitArray: A new BitArray with the bits shifted and filled.
|
115
|
-
"""
|
116
|
-
if shift_amount == 0:
|
117
|
-
return self.copy()
|
118
|
-
if abs(shift_amount) > len(self._bits):
|
119
|
-
new_bits = [fill] * len(self._bits)
|
120
|
-
elif shift_amount > 0:
|
121
|
-
new_bits = [fill] * shift_amount + self._bits[:-shift_amount]
|
122
|
-
else:
|
123
|
-
new_bits = self._bits[-shift_amount:] + [fill] * (-shift_amount)
|
124
|
-
return ListBitArray(new_bits)
|
125
|
-
|
126
|
-
def copy(self) -> ListBitArray:
|
127
|
-
"""Create a copy of the bit array.
|
128
|
-
|
129
|
-
Returns:
|
130
|
-
ListBitArray: A new BitArray with the same bits.
|
131
|
-
"""
|
132
|
-
return ListBitArray(self._bits.copy())
|
133
|
-
|
134
|
-
def __len__(self) -> int:
|
135
|
-
"""Return the length of the bit array."""
|
136
|
-
return len(self._bits)
|
137
|
-
|
138
|
-
@overload
|
139
|
-
def __getitem__(self, index: int) -> bool: ...
|
140
|
-
@overload
|
141
|
-
def __getitem__(self, index: slice) -> ListBitArray: ...
|
142
|
-
|
143
|
-
def __getitem__(self, index: int | slice) -> bool | ListBitArray:
|
144
|
-
"""Get an item or slice from the bit array."""
|
145
|
-
if isinstance(index, slice):
|
146
|
-
return ListBitArray(self._bits[index])
|
147
|
-
return self._bits[index]
|
148
|
-
|
149
|
-
@overload
|
150
|
-
def __setitem__(self, index: int, value: bool) -> None: ...
|
151
|
-
@overload
|
152
|
-
def __setitem__(self, index: slice, value: BitArray | list[bool]) -> None: ...
|
153
|
-
|
154
|
-
def __setitem__(
|
155
|
-
self, index: int | slice, value: bool | list[bool] | BitArray
|
156
|
-
) -> None:
|
157
|
-
"""Set an item or slice in the bit array."""
|
158
|
-
if isinstance(index, slice):
|
159
|
-
if isinstance(value, BitArray):
|
160
|
-
self._bits[index] = list(value)
|
161
|
-
elif isinstance(value, list):
|
162
|
-
self._bits[index] = value
|
163
|
-
else:
|
164
|
-
raise TypeError("Cannot assign a single bool to a slice")
|
165
|
-
return
|
166
|
-
if isinstance(value, bool):
|
167
|
-
self._bits[index] = value
|
168
|
-
else:
|
169
|
-
raise TypeError("Cannot assign a list or BitArray to a single index")
|
170
|
-
|
171
|
-
def __iter__(self) -> Iterator[bool]:
|
172
|
-
"""Iterate over the bits in the array."""
|
173
|
-
return iter(self._bits)
|
174
|
-
|
175
|
-
def __add__(self, other: BitArray | list[bool]) -> ListBitArray:
|
176
|
-
"""Concatenate two bit arrays."""
|
177
|
-
if isinstance(other, BitArray):
|
178
|
-
return ListBitArray(self._bits + list(other))
|
179
|
-
return ListBitArray(self._bits + other)
|
180
|
-
|
181
|
-
def __radd__(self, other: list[bool]) -> ListBitArray:
|
182
|
-
"""Reverse concatenation with a list."""
|
183
|
-
return ListBitArray(other + self._bits)
|
184
|
-
|
185
|
-
def __repr__(self) -> str:
|
186
|
-
"""Return a string representation of the BitArray."""
|
187
|
-
return f"ListBitArray({self._bits})"
|
flexfloat-0.1.3.dist-info/RECORD
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
flexfloat/__init__.py,sha256=QynzrIicNr9asICyJbity5QdrFop7xEDlKkrS7rZfKk,725
|
2
|
-
flexfloat/core.py,sha256=u5TVNxGxsb0_H4vc9p6PvjeBYRJrYBABhZxOTcS5sAg,39658
|
3
|
-
flexfloat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
flexfloat/types.py,sha256=_vRC7gQl5ua76QfKco4L3jQ4uPtEPUxPNGy4zWBFbns,113
|
5
|
-
flexfloat/bitarray/__init__.py,sha256=nyHA70JnEuDVOYWfHjhNNu0zm4xVLWADkuMo0kqsJ7c,2512
|
6
|
-
flexfloat/bitarray/bitarray.py,sha256=ASq8L1Ky84H41AzhLlZjY1u1k6zOtyf2czuD-ixGsJA,5912
|
7
|
-
flexfloat/bitarray/bitarray_int64.py,sha256=kq-vULiA0lk8GaSDUf9U41q12qCREdn83ywKxiNjv_M,10585
|
8
|
-
flexfloat/bitarray/bitarray_list.py,sha256=OTH6MjA1kBHPZP2Mi2mIViN2aOdxHVVrCybV-9ko99c,6586
|
9
|
-
flexfloat/bitarray/bitarray_mixins.py,sha256=Cfm0dt1gRIG5kNb9wPPH62Tzd5B0Ck6YZupHia1jKmo,3302
|
10
|
-
flexfloat-0.1.3.dist-info/licenses/LICENSE,sha256=uwwkK--SUYUV3lbrv9kXJ_vDiYfHVb-t732g6c4qg7Q,1077
|
11
|
-
flexfloat-0.1.3.dist-info/METADATA,sha256=Iea-nvdjZCsfvrhfNQTEHnCozLgPLRotRG8RqskwjXs,10375
|
12
|
-
flexfloat-0.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
13
|
-
flexfloat-0.1.3.dist-info/top_level.txt,sha256=82S8dY2UoNZh-9pwg7tUvbwB3uw2s3mfEoyUW6vCMdU,10
|
14
|
-
flexfloat-0.1.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|