qnty 0.0.9__py3-none-any.whl → 0.1.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.
Files changed (92) hide show
  1. qnty/__init__.py +2 -3
  2. qnty/constants/__init__.py +10 -0
  3. qnty/constants/numerical.py +18 -0
  4. qnty/constants/solvers.py +6 -0
  5. qnty/constants/tests.py +6 -0
  6. qnty/dimensions/__init__.py +23 -0
  7. qnty/dimensions/base.py +97 -0
  8. qnty/dimensions/field_dims.py +126 -0
  9. qnty/dimensions/field_dims.pyi +128 -0
  10. qnty/dimensions/signature.py +111 -0
  11. qnty/equations/__init__.py +1 -1
  12. qnty/equations/equation.py +118 -155
  13. qnty/equations/system.py +68 -65
  14. qnty/expressions/__init__.py +25 -46
  15. qnty/expressions/formatter.py +188 -0
  16. qnty/expressions/functions.py +46 -68
  17. qnty/expressions/nodes.py +539 -384
  18. qnty/expressions/types.py +70 -0
  19. qnty/problems/__init__.py +145 -0
  20. qnty/problems/composition.py +1031 -0
  21. qnty/problems/problem.py +695 -0
  22. qnty/problems/rules.py +145 -0
  23. qnty/problems/solving.py +1216 -0
  24. qnty/problems/validation.py +127 -0
  25. qnty/quantities/__init__.py +28 -5
  26. qnty/quantities/base_qnty.py +677 -0
  27. qnty/quantities/field_converters.py +24004 -0
  28. qnty/quantities/field_qnty.py +1012 -0
  29. qnty/{generated/setters.py → quantities/field_setter.py} +3071 -2961
  30. qnty/{generated/quantities.py → quantities/field_vars.py} +754 -432
  31. qnty/{generated/quantities.pyi → quantities/field_vars.pyi} +1289 -1290
  32. qnty/solving/manager.py +50 -44
  33. qnty/solving/order.py +181 -133
  34. qnty/solving/solvers/__init__.py +2 -9
  35. qnty/solving/solvers/base.py +27 -37
  36. qnty/solving/solvers/iterative.py +115 -135
  37. qnty/solving/solvers/simultaneous.py +93 -165
  38. qnty/units/__init__.py +1 -0
  39. qnty/{generated/units.py → units/field_units.py} +1700 -991
  40. qnty/units/field_units.pyi +2461 -0
  41. qnty/units/prefixes.py +58 -105
  42. qnty/units/registry.py +76 -89
  43. qnty/utils/__init__.py +16 -0
  44. qnty/utils/caching/__init__.py +23 -0
  45. qnty/utils/caching/manager.py +401 -0
  46. qnty/utils/error_handling/__init__.py +66 -0
  47. qnty/utils/error_handling/context.py +39 -0
  48. qnty/utils/error_handling/exceptions.py +96 -0
  49. qnty/utils/error_handling/handlers.py +171 -0
  50. qnty/utils/logging.py +4 -4
  51. qnty/utils/protocols.py +164 -0
  52. qnty/utils/scope_discovery.py +420 -0
  53. {qnty-0.0.9.dist-info → qnty-0.1.0.dist-info}/METADATA +1 -1
  54. qnty-0.1.0.dist-info/RECORD +60 -0
  55. qnty/_backup/problem_original.py +0 -1251
  56. qnty/_backup/quantity.py +0 -63
  57. qnty/codegen/cli.py +0 -125
  58. qnty/codegen/generators/data/unit_data.json +0 -8807
  59. qnty/codegen/generators/data_processor.py +0 -345
  60. qnty/codegen/generators/dimensions_gen.py +0 -434
  61. qnty/codegen/generators/doc_generator.py +0 -141
  62. qnty/codegen/generators/out/dimension_mapping.json +0 -974
  63. qnty/codegen/generators/out/dimension_metadata.json +0 -123
  64. qnty/codegen/generators/out/units_metadata.json +0 -223
  65. qnty/codegen/generators/quantities_gen.py +0 -159
  66. qnty/codegen/generators/setters_gen.py +0 -178
  67. qnty/codegen/generators/stubs_gen.py +0 -167
  68. qnty/codegen/generators/units_gen.py +0 -295
  69. qnty/expressions/cache.py +0 -94
  70. qnty/generated/dimensions.py +0 -514
  71. qnty/problem/__init__.py +0 -91
  72. qnty/problem/base.py +0 -142
  73. qnty/problem/composition.py +0 -385
  74. qnty/problem/composition_mixin.py +0 -382
  75. qnty/problem/equations.py +0 -413
  76. qnty/problem/metaclass.py +0 -302
  77. qnty/problem/reconstruction.py +0 -1016
  78. qnty/problem/solving.py +0 -180
  79. qnty/problem/validation.py +0 -64
  80. qnty/problem/variables.py +0 -239
  81. qnty/quantities/expression_quantity.py +0 -314
  82. qnty/quantities/quantity.py +0 -428
  83. qnty/quantities/typed_quantity.py +0 -215
  84. qnty/validation/__init__.py +0 -0
  85. qnty/validation/registry.py +0 -0
  86. qnty/validation/rules.py +0 -167
  87. qnty-0.0.9.dist-info/RECORD +0 -63
  88. /qnty/{codegen → extensions}/__init__.py +0 -0
  89. /qnty/{codegen/generators → extensions/integration}/__init__.py +0 -0
  90. /qnty/{codegen/generators/utils → extensions/plotting}/__init__.py +0 -0
  91. /qnty/{generated → extensions/reporting}/__init__.py +0 -0
  92. {qnty-0.0.9.dist-info → qnty-0.1.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,677 @@
1
+ """
2
+ High-Performance Quantity and Variables
3
+ ========================================
4
+
5
+ FastQuantity class and type-safe variables optimized for engineering calculations
6
+ with dimensional safety.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import TypeVar
12
+
13
+ from ..constants import FLOAT_EQUALITY_TOLERANCE
14
+ from ..dimensions.field_dims import (
15
+ AREA,
16
+ DIMENSIONLESS,
17
+ ENERGY_PER_UNIT_AREA,
18
+ FORCE,
19
+ LENGTH,
20
+ PRESSURE,
21
+ SURFACE_TENSION,
22
+ VOLUME,
23
+ DimensionSignature,
24
+ )
25
+ from ..dimensions.field_dims import (
26
+ ENERGY_HEAT_WORK as ENERGY,
27
+ )
28
+ from ..units.field_units import AreaUnits, DimensionlessUnits, LengthUnits, PressureUnits, VolumeUnits
29
+ from ..units.registry import UnitConstant, UnitDefinition, registry
30
+
31
+ # TypeVar for generic dimensional types
32
+ DimensionType = TypeVar("DimensionType", bound="Quantity")
33
+
34
+
35
+ # Performance optimization data structures
36
+ class ResultTemplate:
37
+ """Pre-computed result template to bypass Quantity creation overhead."""
38
+
39
+ __slots__ = ("unit", "combined_si_factor")
40
+
41
+ def __init__(self, unit: UnitConstant, combined_si_factor: float):
42
+ self.unit = unit
43
+ self.combined_si_factor = combined_si_factor
44
+
45
+
46
+ class ObjectPool:
47
+ """Object pool for common quantity types to reduce allocations."""
48
+
49
+ __slots__ = ("_area_pool", "_volume_pool", "_force_pool", "_energy_pool", "_pool_index", "_initialized")
50
+
51
+ def __init__(self):
52
+ # Initialize empty pools - delay creation until first use
53
+ self._area_pool: list[Quantity] = []
54
+ self._volume_pool: list[Quantity] = []
55
+ self._force_pool: list[Quantity] = []
56
+ self._energy_pool: list[Quantity] = []
57
+ self._pool_index = 0
58
+ self._initialized = False
59
+
60
+ def _initialize_pools_lazy(self):
61
+ """Lazily create pooled objects to avoid circular imports."""
62
+ if self._initialized:
63
+ return
64
+
65
+ area_unit = AreaUnits.square_millimeter
66
+ volume_unit = VolumeUnits.cubic_millimeter
67
+ force_unit = UnitConstant(UnitDefinition("newton", "N", FORCE, 1.0))
68
+ energy_unit = UnitConstant(UnitDefinition("joule", "J", ENERGY, 1.0))
69
+
70
+ # Pre-allocate 10 of each common type
71
+ for _ in range(10):
72
+ self._area_pool.append(Quantity(0.0, area_unit))
73
+ self._volume_pool.append(Quantity(0.0, volume_unit))
74
+ self._force_pool.append(Quantity(0.0, force_unit))
75
+ self._energy_pool.append(Quantity(0.0, energy_unit))
76
+
77
+ self._initialized = True
78
+
79
+ def get_area_quantity(self, value: float, unit: UnitConstant) -> Quantity:
80
+ """Get pooled area quantity or create new if pool empty."""
81
+ self._initialize_pools_lazy()
82
+ if self._area_pool:
83
+ qty = self._area_pool.pop()
84
+ qty.value = value
85
+ qty.unit = unit
86
+ qty._si_factor = unit.si_factor
87
+ qty._dimension_sig = unit.dimension._signature
88
+ return qty
89
+ return Quantity(value, unit)
90
+
91
+ def get_volume_quantity(self, value: float, unit: UnitConstant) -> Quantity:
92
+ """Get pooled volume quantity or create new if pool empty."""
93
+ self._initialize_pools_lazy()
94
+ if self._volume_pool:
95
+ qty = self._volume_pool.pop()
96
+ qty.value = value
97
+ qty.unit = unit
98
+ qty._si_factor = unit.si_factor
99
+ qty._dimension_sig = unit.dimension._signature
100
+ return qty
101
+ return Quantity(value, unit)
102
+
103
+ def get_force_quantity(self, value: float, unit: UnitConstant) -> Quantity:
104
+ """Get pooled force quantity or create new if pool empty."""
105
+ self._initialize_pools_lazy()
106
+ if self._force_pool:
107
+ qty = self._force_pool.pop()
108
+ qty.value = value
109
+ qty.unit = unit
110
+ qty._si_factor = unit.si_factor
111
+ qty._dimension_sig = unit.dimension._signature
112
+ return qty
113
+ return Quantity(value, unit)
114
+
115
+
116
+ # Global state management and caching system
117
+ class CacheManager:
118
+ """Centralized cache management for better encapsulation and control."""
119
+
120
+ def __init__(self):
121
+ self.small_integer_cache: dict[tuple[int, str], Quantity] = {}
122
+ self.multiplication_cache: dict[tuple[int | float, int | float], UnitConstant] = {}
123
+ # NEW: Result templates with pre-computed SI factors
124
+ self.multiplication_templates: dict[tuple[int | float, int | float], ResultTemplate] = {}
125
+ self.division_cache: dict[tuple[int | float, int | float], UnitConstant] = {}
126
+ self.max_cache_size = 100
127
+ # Object pool for common types
128
+ self.object_pool = ObjectPool()
129
+
130
+ def get_cached_quantity(self, value: int | float, unit: UnitConstant) -> Quantity | None:
131
+ """Get cached quantity for small integers."""
132
+ if isinstance(value, int | float) and -10 <= value <= 10 and value == int(value):
133
+ cache_key = (int(value), unit.name)
134
+ return self.small_integer_cache.get(cache_key)
135
+ return None
136
+
137
+ def cache_quantity(self, value: int | float, unit: UnitConstant, quantity: Quantity) -> None:
138
+ """Cache quantity if under size limit."""
139
+ if len(self.small_integer_cache) < self.max_cache_size:
140
+ cache_key = (int(value), unit.name)
141
+ self.small_integer_cache[cache_key] = quantity
142
+
143
+ def get_multiplication_result(self, left_sig: int | float, right_sig: int | float) -> UnitConstant | None:
144
+ """Get cached multiplication result."""
145
+ return self.multiplication_cache.get((left_sig, right_sig))
146
+
147
+ def cache_multiplication_result(self, left_sig: int | float, right_sig: int | float, result_unit: UnitConstant) -> None:
148
+ """Cache multiplication result if under size limit."""
149
+ if len(self.multiplication_cache) < self.max_cache_size:
150
+ self.multiplication_cache[(left_sig, right_sig)] = result_unit
151
+
152
+ def get_division_result(self, left_sig: int | float, right_sig: int | float) -> UnitConstant | None:
153
+ """Get cached division result."""
154
+ return self.division_cache.get((left_sig, right_sig))
155
+
156
+ def cache_division_result(self, left_sig: int | float, right_sig: int | float, result_unit: UnitConstant) -> None:
157
+ """Cache division result if under size limit."""
158
+ if len(self.division_cache) < self.max_cache_size:
159
+ self.division_cache[(left_sig, right_sig)] = result_unit
160
+
161
+ def initialize_common_operations(self) -> None:
162
+ """Initialize common dimensional operations cache."""
163
+ if not registry._dimension_cache:
164
+ registry._dimension_cache = {
165
+ DIMENSIONLESS._signature: DimensionlessUnits.dimensionless,
166
+ LENGTH._signature: LengthUnits.millimeter,
167
+ PRESSURE._signature: PressureUnits.Pa,
168
+ AREA._signature: AreaUnits.square_millimeter,
169
+ VOLUME._signature: VolumeUnits.cubic_millimeter,
170
+ FORCE._signature: UnitConstant(UnitDefinition("newton", "N", FORCE, 1.0)),
171
+ ENERGY._signature: UnitConstant(UnitDefinition("joule", "J", ENERGY, 1.0)),
172
+ SURFACE_TENSION._signature: UnitConstant(UnitDefinition("newton_per_meter", "N/m", SURFACE_TENSION, 1.0)),
173
+ ENERGY_PER_UNIT_AREA._signature: UnitConstant(UnitDefinition("joule_per_square_meter", "J/m²", ENERGY_PER_UNIT_AREA, 1.0)),
174
+ }
175
+
176
+ # Pre-populate common engineering combinations with extensive coverage
177
+ force_unit = UnitConstant(UnitDefinition("newton", "N", FORCE, 1.0))
178
+ energy_unit = UnitConstant(UnitDefinition("joule", "J", ENERGY, 1.0))
179
+ # _surface_tension_unit = UnitConstant(UnitDefinition("newton_per_meter", "N/m", SURFACE_TENSION, 1.0)) # Unused
180
+ energy_per_area_unit = UnitConstant(UnitDefinition("joule_per_square_meter", "J/m²", ENERGY_PER_UNIT_AREA, 1.0))
181
+
182
+ # NEW APPROACH: Create result templates with pre-computed combined SI factors
183
+ # This eliminates the need for SI factor division during multiplication
184
+
185
+ # Helper function to create template with pre-computed factors
186
+ def create_template(unit: UnitConstant) -> ResultTemplate:
187
+ """Create result template with pre-computed combined SI factor.
188
+
189
+ For typical case where left and right operands use the cached base units,
190
+ the combined factor is just 1.0 / result_unit.si_factor since the SI
191
+ conversion will be handled by the quantity's own _si_factor attributes.
192
+ """
193
+ # The template assumes SI values will be multiplied in, so we just need
194
+ # the reciprocal of the result unit's SI factor for final conversion
195
+ combined_factor = 1.0 / unit.si_factor
196
+ return ResultTemplate(unit, combined_factor)
197
+
198
+ # Get common unit SI factors for template pre-computation (unused in current implementation)
199
+ # _mm_si = LengthUnits.millimeter.si_factor # 0.001
200
+ # _pa_si = PressureUnits.Pa.si_factor # 1.0
201
+ # _mm2_si = AreaUnits.square_millimeter.si_factor # 1e-6
202
+ # _mm3_si = VolumeUnits.cubic_millimeter.si_factor # 1e-9
203
+
204
+ # ULTRA-OPTIMIZED TEMPLATES: Most common engineering operations
205
+ self.multiplication_templates.update(
206
+ {
207
+ # TOP 5 ENGINEERING COMBINATIONS (hardcoded for maximum speed)
208
+ # 1. Length × Length = Area (most common geometric operation)
209
+ (LENGTH._signature, LENGTH._signature): create_template(AreaUnits.square_millimeter),
210
+ # 2. Pressure × Area = Force (ASME pressure vessel calculations)
211
+ (PRESSURE._signature, AREA._signature): create_template(force_unit),
212
+ (AREA._signature, PRESSURE._signature): create_template(force_unit),
213
+ # 3. Length × Area = Volume (geometric calculations)
214
+ (LENGTH._signature, AREA._signature): create_template(VolumeUnits.cubic_millimeter),
215
+ (AREA._signature, LENGTH._signature): create_template(VolumeUnits.cubic_millimeter),
216
+ # 4. Force × Length = Energy (work calculations)
217
+ (FORCE._signature, LENGTH._signature): create_template(energy_unit),
218
+ (LENGTH._signature, FORCE._signature): create_template(energy_unit),
219
+ # 5. Dimensionless scaling (extremely common - factors of safety, ratios)
220
+ (PRESSURE._signature, DIMENSIONLESS._signature): create_template(PressureUnits.Pa),
221
+ (DIMENSIONLESS._signature, PRESSURE._signature): create_template(PressureUnits.Pa),
222
+ (LENGTH._signature, DIMENSIONLESS._signature): create_template(LengthUnits.millimeter),
223
+ (DIMENSIONLESS._signature, LENGTH._signature): create_template(LengthUnits.millimeter),
224
+ (AREA._signature, DIMENSIONLESS._signature): create_template(AreaUnits.square_millimeter),
225
+ (DIMENSIONLESS._signature, AREA._signature): create_template(AreaUnits.square_millimeter),
226
+ (VOLUME._signature, DIMENSIONLESS._signature): create_template(VolumeUnits.cubic_millimeter),
227
+ (DIMENSIONLESS._signature, VOLUME._signature): create_template(VolumeUnits.cubic_millimeter),
228
+ (FORCE._signature, DIMENSIONLESS._signature): create_template(force_unit),
229
+ (DIMENSIONLESS._signature, FORCE._signature): create_template(force_unit),
230
+ (ENERGY._signature, DIMENSIONLESS._signature): create_template(energy_unit),
231
+ (DIMENSIONLESS._signature, ENERGY._signature): create_template(energy_unit),
232
+ (DIMENSIONLESS._signature, DIMENSIONLESS._signature): create_template(DimensionlessUnits.dimensionless),
233
+ }
234
+ )
235
+
236
+ # Keep legacy multiplication cache for compatibility with less common operations
237
+ multiplication_patterns = {
238
+ # Less common but still cached operations
239
+ (AREA._signature, AREA._signature): UnitConstant(UnitDefinition("m4", "m⁴", AREA * AREA, 1e-12)), # mm⁴
240
+ (FORCE._signature, FORCE._signature): UnitConstant(UnitDefinition("N2", "N²", FORCE * FORCE, 1.0)),
241
+ (PRESSURE._signature, LENGTH._signature): force_unit,
242
+ (LENGTH._signature, PRESSURE._signature): force_unit,
243
+ (PRESSURE._signature, PRESSURE._signature): UnitConstant(UnitDefinition("Pa2", "Pa²", PRESSURE * PRESSURE, 1.0)),
244
+ (PRESSURE._signature, VOLUME._signature): energy_unit, # PV work
245
+ (VOLUME._signature, PRESSURE._signature): energy_unit,
246
+ (FORCE._signature, AREA._signature): energy_unit, # Force × Area = Energy
247
+ (AREA._signature, FORCE._signature): energy_unit,
248
+ (ENERGY._signature, LENGTH._signature): force_unit, # Energy/Length = Force
249
+ (LENGTH._signature, ENERGY._signature): force_unit,
250
+ (ENERGY._signature, AREA._signature): energy_per_area_unit,
251
+ (AREA._signature, ENERGY._signature): energy_per_area_unit,
252
+ (SURFACE_TENSION._signature, LENGTH._signature): force_unit,
253
+ (LENGTH._signature, SURFACE_TENSION._signature): force_unit,
254
+ }
255
+
256
+ self.multiplication_cache.update(multiplication_patterns)
257
+
258
+ self.division_cache.update(
259
+ {
260
+ # Basic geometric divisions
261
+ (AREA._signature, LENGTH._signature): LengthUnits.millimeter,
262
+ (VOLUME._signature, AREA._signature): LengthUnits.millimeter,
263
+ (VOLUME._signature, LENGTH._signature): AreaUnits.square_millimeter,
264
+ # Force and pressure divisions
265
+ (FORCE._signature, AREA._signature): PressureUnits.Pa,
266
+ (ENERGY._signature, FORCE._signature): LengthUnits.meter,
267
+ (ENERGY._signature, LENGTH._signature): force_unit,
268
+ # ASME-specific: Force ÷ Length = Pressure (common in final result)
269
+ (FORCE._signature, LENGTH._signature): PressureUnits.Pa,
270
+ # Dimensionless divisions (maintain original units)
271
+ (PRESSURE._signature, DIMENSIONLESS._signature): PressureUnits.Pa,
272
+ (LENGTH._signature, DIMENSIONLESS._signature): LengthUnits.millimeter,
273
+ (FORCE._signature, DIMENSIONLESS._signature): force_unit,
274
+ # Combined unit divisions (P×D ÷ P = D pattern in ASME)
275
+ (force_unit.dimension._signature, PRESSURE._signature): LengthUnits.millimeter,
276
+ }
277
+ )
278
+
279
+
280
+ # Pre-cached units for ultra-fast paths (avoid repeated creation/import overhead)
281
+ _CACHED_AREA_UNIT = AreaUnits.square_millimeter
282
+ _CACHED_VOLUME_UNIT = VolumeUnits.cubic_millimeter
283
+ _CACHED_FORCE_UNIT = UnitConstant(UnitDefinition("newton", "N", FORCE, 1.0))
284
+ # _CACHED_ENERGY_UNIT = UnitConstant(UnitDefinition("joule", "J", ENERGY, 1.0)) # Unused
285
+
286
+ # Pre-computed reciprocals for division (eliminate division operations)
287
+ _AREA_SI_RECIPROCAL = 1.0 / _CACHED_AREA_UNIT.si_factor # 1.0 / 1e-6 = 1e6
288
+ _VOLUME_SI_RECIPROCAL = 1.0 / _CACHED_VOLUME_UNIT.si_factor # 1.0 / 1e-9 = 1e9
289
+ # _FORCE_SI_RECIPROCAL = 1.0 / _CACHED_FORCE_UNIT.si_factor # 1.0 / 1.0 = 1.0 # Unused
290
+
291
+ # Global cache manager instance
292
+ _cache_manager = CacheManager()
293
+
294
+
295
+ # Error message constants for better maintainability
296
+ class ErrorMessages:
297
+ """Centralized error message templates."""
298
+
299
+ INCOMPATIBLE_ADD = "Cannot add {} and {}"
300
+ INCOMPATIBLE_SUBTRACT = "Cannot subtract {} from {}"
301
+ INCOMPATIBLE_DIMENSION = "Unit {} incompatible with expected dimension"
302
+ UNIT_NOT_FOUND = "Unit '{}' not found for {}. Available units: {}"
303
+ UNKNOWN_FUNCTION = "Unknown function: {}"
304
+ INCOMPATIBLE_COMPARISON = "Cannot compare incompatible dimensions"
305
+
306
+
307
+ # Component classes for separation of concerns
308
+ class ArithmeticOperations:
309
+ """Handles arithmetic operations for quantities."""
310
+
311
+ @staticmethod
312
+ def add(quantity, other):
313
+ """Add two quantities with dimensional checking."""
314
+ if quantity._dimension_sig != other._dimension_sig:
315
+ raise ValueError(ErrorMessages.INCOMPATIBLE_ADD.format(quantity.unit.name, other.unit.name))
316
+
317
+ # Fast path for same units
318
+ if quantity.unit.name == other.unit.name:
319
+ return Quantity(quantity.value + other.value, quantity.unit)
320
+
321
+ # Convert using cached SI factors
322
+ converted_value = other.value * other._si_factor / quantity._si_factor
323
+ return Quantity(quantity.value + converted_value, quantity.unit)
324
+
325
+ @staticmethod
326
+ def subtract(quantity, other):
327
+ """Subtract two quantities with dimensional checking."""
328
+ if quantity._dimension_sig != other._dimension_sig:
329
+ raise ValueError(ErrorMessages.INCOMPATIBLE_SUBTRACT.format(other.unit.name, quantity.unit.name))
330
+
331
+ # Fast path for same units
332
+ if quantity.unit.name == other.unit.name:
333
+ return Quantity(quantity.value - other.value, quantity.unit)
334
+
335
+ # Convert using cached SI factors
336
+ converted_value = other.value * other._si_factor / quantity._si_factor
337
+ return Quantity(quantity.value - converted_value, quantity.unit)
338
+
339
+ @staticmethod
340
+ def multiply(quantity, other):
341
+ """Ultra-aggressive multiplication optimizations targeting <0.400μs performance."""
342
+ # FASTEST PATH: Use type() check for numbers (faster than isinstance)
343
+ other_type = type(other)
344
+ if other_type in (int, float):
345
+ return Quantity(quantity.value * other, quantity.unit)
346
+
347
+ # DUCK TYPING: Extract quantity without hasattr overhead
348
+ other_qty = getattr(other, "quantity", None)
349
+ if other_qty is not None:
350
+ other = other_qty
351
+
352
+ # ULTRA-FAST ATTRIBUTE ACCESS: Direct access with getattr fallback for robustness
353
+ q_val = quantity.value
354
+ q_dim = quantity._dimension_sig
355
+ o_val = getattr(other, "value", None)
356
+ o_dim = getattr(other, "_dimension_sig", None)
357
+
358
+ # Quick validation
359
+ if o_val is None or o_dim is None:
360
+ raise TypeError(f"Expected Quantity-like object, got {type(other)}")
361
+
362
+ # SPECIAL VALUE FAST PATHS: Most performance-critical optimizations first
363
+ if o_val == 1.0 and o_dim == 1: # Multiply by 1.0 dimensionless
364
+ return Quantity(q_val * other._si_factor, quantity.unit)
365
+ if q_val == 1.0 and q_dim == 1: # 1.0 dimensionless * something
366
+ return Quantity(o_val * quantity._si_factor, other.unit)
367
+ if q_val == 0.0 or o_val == 0.0: # Zero multiplication
368
+ return Quantity(0.0, quantity.unit if q_val == 0.0 else other.unit)
369
+
370
+ # DIMENSIONLESS FAST PATHS: Treat as scaling to avoid template lookup
371
+ if o_dim == 1: # Right dimensionless
372
+ return Quantity(q_val * o_val * other._si_factor, quantity.unit)
373
+ if q_dim == 1: # Left dimensionless
374
+ return Quantity(q_val * quantity._si_factor * o_val, other.unit)
375
+
376
+ # ULTRA-OPTIMIZED HARDCODED PATHS: Use multiplication instead of division
377
+ # Length × Length = Area (most common geometric operation)
378
+ if q_dim == LENGTH._signature and o_dim == LENGTH._signature:
379
+ # Eliminate division: (q_val * q_si) * (o_val * o_si) * (1/result_si)
380
+ result_val = q_val * quantity._si_factor * o_val * other._si_factor * _AREA_SI_RECIPROCAL
381
+ return Quantity(result_val, _CACHED_AREA_UNIT)
382
+
383
+ # Pressure × Area = Force (ASME pressure vessel calculations)
384
+ elif (q_dim == PRESSURE._signature and o_dim == AREA._signature) or (q_dim == AREA._signature and o_dim == PRESSURE._signature):
385
+ # Force SI factor is 1.0, so no reciprocal multiplication needed
386
+ result_val = q_val * quantity._si_factor * o_val * other._si_factor
387
+ return Quantity(result_val, _CACHED_FORCE_UNIT)
388
+
389
+ # Length × Area = Volume (geometric calculations)
390
+ elif (q_dim == LENGTH._signature and o_dim == AREA._signature) or (q_dim == AREA._signature and o_dim == LENGTH._signature):
391
+ result_val = q_val * quantity._si_factor * o_val * other._si_factor * _VOLUME_SI_RECIPROCAL
392
+ return Quantity(result_val, _CACHED_VOLUME_UNIT)
393
+
394
+ # TEMPLATE LOOKUP for remaining optimized cases
395
+ cache_key = (q_dim, o_dim)
396
+ template = _cache_manager.multiplication_templates.get(cache_key)
397
+ if template is not None:
398
+ # Single combined operation
399
+ result_value = q_val * o_val * (quantity._si_factor * other._si_factor * template.combined_si_factor)
400
+ # Skip object pooling overhead - just create directly
401
+ return Quantity(result_value, template.unit)
402
+
403
+ # LEGACY CACHE LOOKUP: For operations not in optimized templates
404
+ cached_unit = _cache_manager.multiplication_cache.get(cache_key)
405
+ if cached_unit is not None:
406
+ # INLINE SI CALCULATION: Single combined expression
407
+ result_si_value = (q_val * quantity._si_factor) * (o_val * other._si_factor)
408
+ return Quantity(result_si_value / cached_unit.si_factor, cached_unit)
409
+
410
+ # FALLBACK PATH: General case for uncached operations
411
+ result_dimension_sig = q_dim * o_dim
412
+ result_si_value = (q_val * quantity._si_factor) * (o_val * other._si_factor)
413
+
414
+ # Fast unit resolution
415
+ result_unit = UnitResolution.find_result_unit_fast(quantity, result_dimension_sig)
416
+ result_value = result_si_value / result_unit.si_factor
417
+
418
+ # Direct cache assignment for future use
419
+ if len(_cache_manager.multiplication_cache) < _cache_manager.max_cache_size:
420
+ _cache_manager.multiplication_cache[cache_key] = result_unit
421
+
422
+ return Quantity(result_value, result_unit)
423
+
424
+ @staticmethod
425
+ def divide(quantity, other):
426
+ """Divide quantity by another quantity or scalar."""
427
+ # Fast path for numeric types - use type() for speed
428
+ if isinstance(other, int | float):
429
+ return Quantity(quantity.value / other, quantity.unit)
430
+
431
+ # Handle UnifiedVariable objects by using their quantity
432
+ if hasattr(other, "quantity") and getattr(other, "quantity", None) is not None:
433
+ other = other.quantity # type: ignore
434
+
435
+ # Type narrowing: at this point other should be Quantity
436
+ if not isinstance(other, Quantity):
437
+ raise TypeError(f"Expected Quantity, got {type(other)}")
438
+
439
+ # OPTIMIZATION: Fast path for dimensionless divisor (signature = 1)
440
+ # Treat dimensionless quantities more like scalars to reduce overhead
441
+ if other._dimension_sig == 1: # DIMENSIONLESS divisor
442
+ # Division by dimensionless: just scale the value, keep original unit
443
+ divisor = other.value * other._si_factor
444
+ return Quantity(quantity.value / divisor, quantity.unit)
445
+
446
+ # Check division cache first
447
+ cached_unit = _cache_manager.get_division_result(quantity._dimension_sig, other._dimension_sig)
448
+ if cached_unit:
449
+ result_si_value = (quantity.value * quantity._si_factor) / (other.value * other._si_factor)
450
+ return Quantity(result_si_value / cached_unit.si_factor, cached_unit)
451
+
452
+ # Calculate result dimension and value
453
+ result_dimension_sig = quantity._dimension_sig / other._dimension_sig
454
+ result_si_value = (quantity.value * quantity._si_factor) / (other.value * other._si_factor)
455
+
456
+ # Find appropriate result unit
457
+ result_unit = UnitResolution.find_result_unit_fast(quantity, result_dimension_sig)
458
+ result_value = result_si_value / result_unit.si_factor
459
+
460
+ # Cache the result for future use
461
+ _cache_manager.cache_division_result(quantity._dimension_sig, other._dimension_sig, result_unit)
462
+ return Quantity(result_value, result_unit)
463
+
464
+
465
+ class ComparisonOperations:
466
+ """Handles comparison operations for quantities."""
467
+
468
+ @staticmethod
469
+ def less_than(quantity, other):
470
+ """Compare if this quantity is less than another."""
471
+ # Optimized comparison with bulk operations
472
+ if quantity._dimension_sig != other._dimension_sig:
473
+ raise ValueError(ErrorMessages.INCOMPATIBLE_COMPARISON)
474
+
475
+ # Fast path for same units (use name comparison for speed)
476
+ if quantity.unit.name == other.unit.name:
477
+ return quantity.value < other.value
478
+
479
+ # Convert using cached SI factors (bulk assignment)
480
+ self_si, other_si = quantity._si_factor, other._si_factor
481
+ return quantity.value < (other.value * other_si / self_si)
482
+
483
+ @staticmethod
484
+ def equals(quantity, other):
485
+ """Check equality between quantities."""
486
+ if not isinstance(other, Quantity):
487
+ return False
488
+ if quantity._dimension_sig != other._dimension_sig:
489
+ return False
490
+
491
+ # Fast path for same units (use name comparison)
492
+ if quantity.unit.name == other.unit.name:
493
+ return abs(quantity.value - other.value) < FLOAT_EQUALITY_TOLERANCE
494
+
495
+ # Convert using cached SI factors (bulk assignment)
496
+ self_si, other_si = quantity._si_factor, other._si_factor
497
+ return abs(quantity.value - (other.value * other_si / self_si)) < FLOAT_EQUALITY_TOLERANCE
498
+
499
+
500
+ class UnitConversions:
501
+ """Handles unit conversion operations."""
502
+
503
+ @staticmethod
504
+ def to(quantity, target_unit):
505
+ """Convert quantity to target unit."""
506
+ # Ultra-fast same unit check using name comparison
507
+ if quantity.unit.name == target_unit.name:
508
+ return Quantity(quantity.value, target_unit)
509
+
510
+ # Direct SI factor conversion - avoid registry lookup
511
+ converted_value = quantity.value * quantity._si_factor / target_unit.si_factor
512
+ return Quantity(converted_value, target_unit)
513
+
514
+
515
+ class QuantityFormatting:
516
+ """Handles string formatting for quantities."""
517
+
518
+ @staticmethod
519
+ def to_string(quantity):
520
+ """String representation of the quantity."""
521
+ # Optimized string representation (caching removed for simplicity)
522
+ return f"{quantity.value} {quantity.unit.symbol}"
523
+
524
+ @staticmethod
525
+ def to_repr(quantity):
526
+ """Detailed representation of the quantity."""
527
+ return f"Quantity({quantity.value}, {quantity.unit.name})"
528
+
529
+
530
+ class UnitResolution:
531
+ """Handles unit resolution for dimensional operations."""
532
+
533
+ @staticmethod
534
+ def find_result_unit_fast(_quantity, result_dimension_sig: int | float) -> UnitConstant:
535
+ """Ultra-fast unit finding using pre-cached dimension signatures."""
536
+ # CRITICAL OPTIMIZATION: Direct dictionary access (O(1)) for common dimensions
537
+ dimension_cache = registry._dimension_cache
538
+ if result_dimension_sig in dimension_cache:
539
+ return dimension_cache[result_dimension_sig]
540
+
541
+ # OPTIMIZED PATH: For rare combined dimensions, create SI base unit efficiently
542
+ # Create new dimension signature from the computed value
543
+ result_dimension = DimensionSignature(result_dimension_sig) # type: ignore[misc]
544
+
545
+ # FAST CREATION: Minimize string operations for performance
546
+ sig_hash = abs(hash(result_dimension_sig)) % 10000
547
+ si_name = f"si_derived_{sig_hash}"
548
+ si_symbol = f"SI_{sig_hash % 1000}"
549
+
550
+ # STREAMLINED CREATION: Avoid unnecessary method calls
551
+ temp_unit = UnitDefinition(name=si_name, symbol=si_symbol, dimension=result_dimension, si_factor=1.0)
552
+ result_unit = UnitConstant(temp_unit)
553
+
554
+ # DIRECT CACHE ASSIGNMENT: Bypass cache size checks for dimension cache
555
+ dimension_cache[result_dimension_sig] = result_unit
556
+ return result_unit
557
+
558
+ @staticmethod
559
+ def create_si_unit_name(_quantity, dimension: DimensionSignature) -> str:
560
+ """Create descriptive SI unit name based on dimensional analysis."""
561
+ # For now, return a generic SI unit name. In the future, this could be enhanced
562
+ # to parse the dimension signature and create descriptive names like "newton_per_meter"
563
+ return f"si_derived_unit_{abs(hash(dimension._signature)) % 10000}"
564
+
565
+ @staticmethod
566
+ def create_si_unit_symbol(_quantity, dimension: DimensionSignature) -> str:
567
+ """Create SI unit symbol based on dimensional analysis."""
568
+ # For complex units, return descriptive symbol based on common engineering units
569
+ # Use dimension signature for unique symbol generation
570
+ return f"SI_{abs(hash(dimension._signature)) % 1000}"
571
+
572
+ @staticmethod
573
+ def find_result_unit(quantity, result_dimension: DimensionSignature) -> UnitConstant:
574
+ """Legacy method - kept for compatibility."""
575
+ return UnitResolution.find_result_unit_fast(quantity, result_dimension._signature)
576
+
577
+
578
+ class TypeSafeSetter:
579
+ """Basic type-safe setter that accepts compatible units."""
580
+
581
+ def __init__(self, variable, value: float):
582
+ self.variable = variable
583
+ self.value = value
584
+
585
+ def with_unit(self, unit: UnitConstant):
586
+ """Set with type-safe unit constant."""
587
+ if not self.variable.expected_dimension.is_compatible(unit.dimension):
588
+ raise TypeError(ErrorMessages.INCOMPATIBLE_DIMENSION.format(unit.name))
589
+
590
+ self.variable.quantity = Quantity(self.value, unit)
591
+ return self.variable
592
+
593
+
594
+ class Quantity:
595
+ """High-performance quantity optimized for engineering calculations."""
596
+
597
+ __slots__ = ("value", "unit", "dimension", "_si_factor", "_dimension_sig")
598
+
599
+ def __init__(self, value: float, unit: UnitConstant):
600
+ # Optimized initialization with cached values for performance
601
+ self.value = value if isinstance(value, float) else float(value)
602
+ self.unit = unit
603
+ self.dimension = unit.dimension
604
+ # Cache commonly used values to avoid repeated attribute access
605
+ self._si_factor = unit.si_factor
606
+ self._dimension_sig = unit.dimension._signature
607
+
608
+ @classmethod
609
+ def get_cached(cls, value: int | float, unit: UnitConstant):
610
+ """Get cached instance for small integers, otherwise create new."""
611
+ # Check cache for small integers
612
+ cached = _cache_manager.get_cached_quantity(value, unit)
613
+ if cached:
614
+ return cached
615
+
616
+ # Create new quantity
617
+ obj = cls(value, unit)
618
+
619
+ # Cache if it qualifies
620
+ _cache_manager.cache_quantity(value, unit, obj)
621
+ return obj
622
+
623
+ def __str__(self) -> str:
624
+ return QuantityFormatting.to_string(self)
625
+
626
+ def __repr__(self) -> str:
627
+ return QuantityFormatting.to_repr(self)
628
+
629
+ # Ultra-fast arithmetic with dimensional checking
630
+ def __add__(self, other: Quantity) -> Quantity:
631
+ return ArithmeticOperations.add(self, other)
632
+
633
+ def __sub__(self, other: Quantity) -> Quantity:
634
+ return ArithmeticOperations.subtract(self, other)
635
+
636
+ def __mul__(self, other: Quantity | float | int) -> Quantity:
637
+ return ArithmeticOperations.multiply(self, other)
638
+
639
+ def __rmul__(self, other: float | int) -> Quantity:
640
+ """Reverse multiplication for cases like 2 * quantity."""
641
+ if isinstance(other, int | float):
642
+ return Quantity(other * self.value, self.unit)
643
+ return NotImplemented
644
+
645
+ def __truediv__(self, other: Quantity | float | int) -> Quantity:
646
+ return ArithmeticOperations.divide(self, other)
647
+
648
+ def _find_result_unit_fast(self, result_dimension_sig: int | float) -> UnitConstant:
649
+ """Delegate to unit resolution component."""
650
+ return UnitResolution.find_result_unit_fast(self, result_dimension_sig)
651
+
652
+ def _create_si_unit_name(self, dimension: DimensionSignature) -> str:
653
+ """Delegate to unit resolution component."""
654
+ return UnitResolution.create_si_unit_name(self, dimension)
655
+
656
+ def _create_si_unit_symbol(self, dimension: DimensionSignature) -> str:
657
+ """Delegate to unit resolution component."""
658
+ return UnitResolution.create_si_unit_symbol(self, dimension)
659
+
660
+ def _find_result_unit(self, result_dimension: DimensionSignature) -> UnitConstant:
661
+ """Legacy method - kept for compatibility."""
662
+ return UnitResolution.find_result_unit(self, result_dimension)
663
+
664
+ # Ultra-fast comparisons
665
+ def __lt__(self, other: Quantity) -> bool:
666
+ return ComparisonOperations.less_than(self, other)
667
+
668
+ def __eq__(self, other) -> bool:
669
+ return ComparisonOperations.equals(self, other)
670
+
671
+ def to(self, target_unit: UnitConstant) -> Quantity:
672
+ """Ultra-fast unit conversion with optimized same-unit check."""
673
+ return UnitConversions.to(self, target_unit)
674
+
675
+
676
+ # Initialize cache manager at module load
677
+ _cache_manager.initialize_common_operations()