Skip to content

Commit 32dc4c8

Browse files
committed
Update documentation for native precision support
This commit updates all project documentation to reflect the v0.7.0 architectural changes: 1. **README.md**: - Updated precision section to describe native float32/float64 support - Added documentation for new precision control methods - Documented auto-detection behavior for both construction and loading - Updated version history with v0.7.0 changes 2. **CHANGES.md**: - Added comprehensive v0.7.0 release notes - Documented native precision architecture changes - Listed all new precision control methods - Described bug fixes related to precision handling - Updated test count (991/991 tests passing) 3. **docs/ARCHITECTURE.md**: - Updated PRTree template signature to include Real parameter - Documented 6 exposed C++ classes (float32/float64 variants) - Updated data flow diagrams for precision selection - Added design decision section for native precision support - Explained trade-offs and benefits of new architecture The documentation now accurately reflects: - Template signature: PRTree<T, B, D, Real> - Automatic precision selection based on numpy dtype - Auto-detection when loading from files - Precision settings preservation across operations - Elimination of idx2exact refinement approach
1 parent 0c9c90b commit 32dc4c8

File tree

3 files changed

+160
-26
lines changed

3 files changed

+160
-26
lines changed

CHANGES.md

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,105 @@
11
# PRTree Improvements
22

3-
## Critical Fixes
3+
## v0.7.0 - Native Precision Support (2025-01-XX)
44

5-
### 1. Windows Crash Fixed
5+
### Major Architectural Changes
6+
7+
#### 1. Native Float32/Float64 Precision
8+
- **Previous**: Float32 tree + idx2exact map + double precision refinement
9+
- **New**: Native float32 and float64 tree implementations
10+
- **Benefit**: Simpler code, better performance, true precision throughout
11+
- **Impact**: ~72 lines of code removed, no conversion overhead
12+
13+
**Implementation Details:**
14+
- Templated `PRTree<T, B, D, Real>` with `Real` type parameter (float or double)
15+
- Propagated `Real` parameter through entire class hierarchy:
16+
- `BB<D, Real>`: Bounding boxes
17+
- `DataType<T, D, Real>`: Data storage
18+
- `PRTreeNode<T, B, D, Real>`: Tree nodes
19+
- `PRTreeLeaf<T, B, D, Real>`: Leaf nodes
20+
- `PseudoPRTree<T, B, D, Real>`: Builder helper
21+
- Exposed 6 C++ classes via pybind11: `_PRTree{2D,3D,4D}_{float32,float64}`
22+
- Python wrapper auto-selects precision based on numpy dtype
23+
24+
**Breaking Change:**
25+
- Previous files saved with float64 input must be loaded with the correct precision
26+
- Solution: Auto-detection when loading from files (tries float32, then float64)
27+
28+
#### 2. Advanced Precision Control
29+
- **Adaptive epsilon**: Automatically scales epsilon based on bounding box sizes
30+
- **Configurable epsilon**: Set relative and absolute epsilon for edge cases
31+
- **Subnormal detection**: Correctly handles denormalized floating-point numbers
32+
- **Methods added**:
33+
```python
34+
tree.set_adaptive_epsilon(bool)
35+
tree.set_relative_epsilon(float)
36+
tree.set_absolute_epsilon(float)
37+
tree.set_subnormal_detection(bool)
38+
tree.get_adaptive_epsilon() -> bool
39+
tree.get_relative_epsilon() -> float
40+
tree.get_absolute_epsilon() -> float
41+
tree.get_subnormal_detection() -> bool
42+
```
43+
44+
#### 3. Query Precision Fixes
45+
- **Issue**: Query methods (`find_one`, `find_all`) used hardcoded `float` type
46+
- **Fix**: Templated with `Real` to match tree precision
47+
- **Impact**: Float64 trees now maintain full precision in queries
48+
49+
#### 4. Python Wrapper Enhancements
50+
- **Auto-detection on load**: Automatically tries both precisions when loading from file
51+
- **Preserve settings on insert**: First insert on empty tree now preserves precision settings
52+
- **Subnormal workaround**: Handles edge case of inserting with subnormal detection disabled
53+
54+
### Testing
55+
56+
**991/991 tests pass** (including 14 new adaptive epsilon tests)
57+
58+
New test coverage:
59+
- `test_adaptive_epsilon.py`: 14 tests covering edge cases
60+
- `test_save_load_float32_no_regression`: Precision preservation across save/load
61+
- Float32 vs float64 precision validation tests
62+
63+
### Performance
64+
65+
- **No regression**: Construction and query performance unchanged
66+
- **Memory reduction**: Eliminated idx2exact map overhead
67+
- **Code simplification**: ~72 lines removed, improved maintainability
68+
69+
### Bug Fixes
70+
71+
1. **Float64 precision loss in queries** (critical)
72+
- Query methods forced float32, losing precision
73+
- Fixed: Template query methods with Real parameter
74+
75+
2. **Precision settings lost on first insert**
76+
- Python wrapper recreated tree without preserving settings
77+
- Fixed: Preserve all precision settings when recreating
78+
79+
3. **File load precision mismatch**
80+
- Loading float32 file with float64 class caused std::bad_alloc
81+
- Fixed: Auto-detect precision by trying both classes
82+
83+
## Previous Releases
84+
85+
### Critical Fixes
86+
87+
#### 1. Windows Crash Fixed
688
- **Issue**: Fatal crash with `std::mutex` (not copyable, caused deadlocks)
789
- **Fix**: Use `std::unique_ptr<std::recursive_mutex>`
890
- **Result**: Thread-safe, no crashes, pybind11 compatible
991

10-
### 2. Error Messages
92+
#### 2. Error Messages
1193
- Improved with context while maintaining backward compatibility
1294
- Example: `"Given index is not found. (Index: 999, tree size: 2)"`
1395

14-
## Improvements Applied
96+
### Improvements Applied
1597

1698
- **C++20**: Migrated standard, added concepts for type safety
1799
- **Exception Safety**: noexcept + RAII (no memory leaks)
18100
- **Thread Safety**: Recursive mutex protects all mutable operations
19101

20-
## Test Results
21-
22-
**674/674 unit tests pass**
23-
24-
## Performance
102+
### Performance Baseline
25103

26104
- Construction: 9-11M ops/sec (single-threaded)
27105
- Memory: 23 bytes/element
@@ -30,3 +108,5 @@
30108
## Future Work
31109

32110
- Parallel partitioning algorithm for better thread scaling (2-3x expected)
111+
- Split large prtree.h into modular components
112+
- Additional precision validation modes

README.md

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,25 @@ results = tree.batch_query(queries) # Returns [[], [], ...]
171171

172172
### Precision
173173

174-
- **Float32 input**: Pure float32 for maximum speed
175-
- **Float64 input**: Float32 tree + double-precision refinement for accuracy
176-
- Handles boxes with very small gaps correctly (< 1e-5)
174+
The library supports native float32 and float64 precision with automatic selection:
175+
176+
- **Float32 input**: Creates native float32 tree for maximum speed
177+
- **Float64 input**: Creates native float64 tree for full double precision
178+
- **Auto-detection**: Precision automatically selected based on numpy array dtype
179+
- **Save/Load**: Precision automatically detected when loading from file
180+
181+
Advanced precision control available:
182+
```python
183+
# Configure precision parameters for challenging cases
184+
tree = PRTree2D(indices, boxes)
185+
tree.set_adaptive_epsilon(True) # Adaptive epsilon based on box sizes
186+
tree.set_relative_epsilon(1e-6) # Relative epsilon for intersection tests
187+
tree.set_absolute_epsilon(1e-12) # Absolute epsilon for near-zero cases
188+
tree.set_subnormal_detection(True) # Handle subnormal numbers correctly
189+
```
190+
191+
The new architecture eliminates the previous float32 tree + refinement approach,
192+
providing true native precision at each level for better performance and accuracy.
177193

178194
### Thread Safety
179195

@@ -220,10 +236,13 @@ PRTree2D(filename) # Load from file
220236
## Version History
221237

222238
### v0.7.0 (Latest)
239+
- **Native precision support**: True float32/float64 precision throughout the entire stack
240+
- **Architectural refactoring**: Eliminated idx2exact complexity for simpler, faster code
241+
- **Auto-detection**: Precision automatically selected based on input dtype and when loading files
242+
- **Advanced precision control**: Adaptive epsilon, configurable relative/absolute epsilon, subnormal detection
223243
- **Fixed critical bug**: Boxes with small gaps (<1e-5) incorrectly reported as intersecting
224244
- **Breaking**: Minimum Python 3.8, serialization format changed
225245
- Added input validation (NaN/Inf rejection)
226-
- Improved precision handling
227246

228247
### v0.5.x
229248
- Added 4D support

docs/ARCHITECTURE.md

Lines changed: 48 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,17 @@ python_prtree/
8383
**Purpose**: Implements the Priority R-Tree algorithm
8484

8585
**Key Components**:
86-
- `prtree.h`: Main template class `PRTree<T, B, D>`
86+
- `prtree.h`: Main template class `PRTree<T, B, D, Real>`
8787
- `T`: Index type (typically `int64_t`)
8888
- `B`: Branching factor (default: 8)
8989
- `D`: Dimensions (2, 3, or 4)
90+
- `Real`: Floating-point type (float or double) - **new in v0.7.0**
9091

9192
**Design Principles**:
9293
- Header-only template library for performance
9394
- No Python dependencies at this layer
9495
- Pure C++ with C++20 features
96+
- Native precision support through Real template parameter
9597

9698
### 2. Utilities Layer (`include/prtree/utils/`)
9799

@@ -116,11 +118,18 @@ python_prtree/
116118
- Handle numpy array conversions
117119
- Expose methods with Python-friendly signatures
118120
- Provide module-level documentation
121+
- Expose both float32 and float64 variants
122+
123+
**Exposed Classes** (v0.7.0):
124+
- `_PRTree2D_float32`, `_PRTree2D_float64`
125+
- `_PRTree3D_float32`, `_PRTree3D_float64`
126+
- `_PRTree4D_float32`, `_PRTree4D_float64`
119127

120128
**Design Principles**:
121129
- Thin binding layer (minimal logic)
122130
- Direct mapping to C++ API
123131
- Efficient numpy integration
132+
- Separate classes for each precision level
124133

125134
### 4. Python Wrapper Layer (`src/python_prtree/`)
126135

@@ -135,37 +144,42 @@ python_prtree/
135144
- Python object storage (pickle serialization)
136145
- Convenient APIs (auto-indexing, return_obj parameter)
137146
- Type hints and documentation
147+
- **Automatic precision selection** (v0.7.0): Detects numpy dtype and selects float32/float64
148+
- **Precision auto-detection on load** (v0.7.0): Tries both precisions when loading files
149+
- **Precision settings preservation** (v0.7.0): Maintains epsilon settings across operations
138150

139151
**Design Principles**:
140152
- Safety over raw performance
141153
- Pythonic API design
142154
- Backwards compatibility considerations
155+
- Zero-overhead precision selection
143156

144157
## Data Flow
145158

146-
### Construction
159+
### Construction (v0.7.0)
147160
```
148161
User Code
149-
↓ (numpy arrays)
162+
↓ (numpy arrays with dtype)
150163
PRTree2D/3D/4D (Python)
151-
↓ (arrays + validation)
152-
_PRTree2D/3D/4D (pybind11)
164+
↓ (dtype detection: float32 or float64?)
165+
↓ (select _PRTree{2D,3D,4D}_{float32,float64})
166+
_PRTree2D_float32 OR _PRTree2D_float64 (pybind11)
153167
↓ (type conversion)
154-
PRTree<int64_t, 8, D> (C++)
155-
↓ (algorithm)
156-
Optimized R-Tree Structure
168+
PRTree<int64_t, 8, D, float> OR PRTree<int64_t, 8, D, double> (C++)
169+
↓ (algorithm with native precision)
170+
Optimized R-Tree Structure (float32 or float64)
157171
```
158172

159-
### Query
173+
### Query (v0.7.0)
160174
```
161175
User Code
162176
↓ (query box)
163177
PRTree2D.query() (Python)
164178
↓ (empty tree check)
165-
_PRTree2D.query() (pybind11)
166-
↓ (type conversion)
167-
PRTree::find_one() (C++)
168-
↓ (tree traversal)
179+
_PRTree2D_float32.query() OR _PRTree2D_float64.query() (pybind11)
180+
↓ (type conversion with matching precision)
181+
PRTree<T,B,D,Real>::find_one(vec<Real>) (C++)
182+
↓ (tree traversal with native Real precision)
169183
Result Indices
170184
↓ (optional: object retrieval)
171185
User Code
@@ -249,6 +263,26 @@ Extension installed in src/python_prtree/
249263

250264
## Design Decisions
251265

266+
### Native Precision Support (v0.7.0)
267+
268+
**Decision**: Template PRTree with Real type parameter instead of using idx2exact refinement
269+
270+
**Rationale**:
271+
- Simpler architecture: Eliminated ~72 lines of refinement code
272+
- Better performance: No conversion overhead, no idx2exact map
273+
- True precision: Float64 maintains double precision throughout
274+
- Type safety: Compiler ensures precision consistency
275+
276+
**Implementation**:
277+
- Added `Real` template parameter to PRTree and all detail classes
278+
- Exposed 6 separate C++ classes via pybind11
279+
- Python wrapper auto-selects based on numpy dtype
280+
281+
**Trade-offs**:
282+
- Larger binary size (6 classes instead of 3)
283+
- Longer compilation time (more template instantiations)
284+
- Benefit: Cleaner code, better maintainability, true native precision
285+
252286
### Header-Only Core
253287

254288
**Decision**: Keep core PRTree as header-only template library
@@ -257,6 +291,7 @@ Extension installed in src/python_prtree/
257291
- Enables full compiler optimization
258292
- Simplifies distribution
259293
- No need for .cc files at core layer
294+
- Required for Real template parameter
260295

261296
**Trade-offs**:
262297
- Longer compilation times

0 commit comments

Comments
 (0)