coordinate-system 7.1.0__tar.gz → 7.1.1__tar.gz

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 (22) hide show
  1. {coordinate_system-7.1.0/coordinate_system.egg-info → coordinate_system-7.1.1}/PKG-INFO +15 -2
  2. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/README.md +16 -3
  3. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system/__init__.py +2 -2
  4. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system/complex_geometric_physics.py +2 -2
  5. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system/differential_geometry.py +356 -112
  6. {coordinate_system-7.1.0 → coordinate_system-7.1.1/coordinate_system.egg-info}/PKG-INFO +15 -2
  7. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/pmsys_minimal.hpp +49 -37
  8. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/pyproject.toml +1 -1
  9. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/setup.py +38 -30
  10. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/LICENSE +0 -0
  11. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/MANIFEST.in +0 -0
  12. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system/curve_interpolation.py +0 -0
  13. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system/spectral_geometry.py +0 -0
  14. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system/u3_frame.py +0 -0
  15. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system/visualization.py +0 -0
  16. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system.egg-info/SOURCES.txt +0 -0
  17. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system.egg-info/dependency_links.txt +0 -0
  18. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system.egg-info/not-zip-safe +0 -0
  19. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system.egg-info/requires.txt +0 -0
  20. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system.egg-info/top_level.txt +0 -0
  21. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/coordinate_system_binding.cpp +0 -0
  22. {coordinate_system-7.1.0 → coordinate_system-7.1.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: coordinate_system
3
- Version: 7.1.0
3
+ Version: 7.1.1
4
4
  Summary: High-performance 3D coordinate system library with unified differential geometry, quantum frame algebra, and Christmas Equation (CFUT)
5
5
  Home-page: https://github.com/panguojun/Coordinate-System
6
6
  Author: Pan Guojun
@@ -51,12 +51,19 @@ Requires-Dist: matplotlib>=3.3.0
51
51
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
52
52
 
53
53
  **Authors:** Pan Guojun
54
- **Version:** 7.1.0
54
+ **Version:** 7.1.1
55
55
  **License:** MIT
56
56
  **DOI:** https://doi.org/10.5281/zenodo.14435613
57
57
 
58
58
  ---
59
59
 
60
+ ## What's New in v7.1.1 (2026-02-05)
61
+
62
+ - **Curvature Fast Path**: Analytical curvature for Sphere/Torus and any surface providing `derivs` or `analytic_KH` (toggle via `USE_ANALYTIC_DERIVS`)
63
+ - **Caching**: Reuse curvature calculators and last-call results to reduce per-sample overhead
64
+ - **Math Core**: Branchless handedness selection for cross product; optional SIMD alignment via `PMSYS_SIMD_ALIGN`
65
+ - **Build Flags**: AVX2 / fast-math enabled by default in build config for faster native builds
66
+
60
67
  ## What's New in v7.1.0 (2026-01-16)
61
68
 
62
69
  - **Physical Constants**: Added SI unit constants for precision calculations (ALPHA_FS, LAMBDA_C, ALPHA_PROJECTION)
@@ -236,6 +243,12 @@ S_YM = F_xy.yang_mills_action()
236
243
 
237
244
  ## Changelog
238
245
 
246
+ ### v7.1.1 (2026-02-05)
247
+ - **Curvature Fast Path**: Analytical curvature for analytic surfaces with optional toggle
248
+ - **Caching**: Curvature calculator reuse and last-call caching for repeated samples
249
+ - **Math Core**: Branchless cross product handedness selection
250
+ - **Build**: AVX2 / fast-math flags enabled by default for native builds
251
+
239
252
  ### v7.1.0 (2026-01-16)
240
253
  - **Physical Constants**: Added SI unit constants (ALPHA_FS, LAMBDA_C, ALPHA_PROJECTION)
241
254
  - **Projection Factor**: Implemented α = α_fs × λ_c ≈ 1.77×10⁻¹⁴ m for geometry-gauge coupling
@@ -7,12 +7,19 @@
7
7
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
8
8
 
9
9
  **Authors:** Pan Guojun
10
- **Version:** 7.1.0
10
+ **Version:** 7.1.1
11
11
  **License:** MIT
12
12
  **DOI:** https://doi.org/10.5281/zenodo.14435613
13
13
 
14
14
  ---
15
15
 
16
+ ## What's New in v7.1.1 (2026-02-05)
17
+
18
+ - **Curvature Fast Path**: Analytical curvature for Sphere/Torus and any surface providing `derivs` or `analytic_KH` (toggle via `USE_ANALYTIC_DERIVS`)
19
+ - **Caching**: Reuse curvature calculators and last-call results to reduce per-sample overhead
20
+ - **Math Core**: Branchless handedness selection for cross product; optional SIMD alignment via `PMSYS_SIMD_ALIGN`
21
+ - **Build Flags**: AVX2 / fast-math enabled by default in build config for faster native builds
22
+
16
23
  ## What's New in v7.1.0 (2026-01-16)
17
24
 
18
25
  - **Physical Constants**: Added SI unit constants for precision calculations (ALPHA_FS, LAMBDA_C, ALPHA_PROJECTION)
@@ -190,8 +197,14 @@ S_YM = F_xy.yang_mills_action()
190
197
 
191
198
  ---
192
199
 
193
- ## Changelog
194
-
200
+ ## Changelog
201
+
202
+ ### v7.1.1 (2026-02-05)
203
+ - **Curvature Fast Path**: Analytical curvature for analytic surfaces with optional toggle
204
+ - **Caching**: Curvature calculator reuse and last-call caching for repeated samples
205
+ - **Math Core**: Branchless cross product handedness selection
206
+ - **Build**: AVX2 / fast-math flags enabled by default for native builds
207
+
195
208
  ### v7.1.0 (2026-01-16)
196
209
  - **Physical Constants**: Added SI unit constants (ALPHA_FS, LAMBDA_C, ALPHA_PROJECTION)
197
210
  - **Projection Factor**: Implemented α = α_fs × λ_c ≈ 1.77×10⁻¹⁴ m for geometry-gauge coupling
@@ -24,11 +24,11 @@ Group Correspondence:
24
24
  - U3Frame ∈ U(3) = SU(3) × U(1)
25
25
 
26
26
  **Authors:** Pan Guojun
27
- Version: 7.1.0
27
+ Version: 7.1.1
28
28
  **DOI:** https://doi.org/10.5281/zenodo.14435613
29
29
  """
30
30
 
31
- __version__ = '7.1.0'
31
+ __version__ = '7.1.1'
32
32
 
33
33
  from .coordinate_system import (
34
34
  vec3,
@@ -26,11 +26,11 @@ Physical Interpretation:
26
26
 
27
27
  **Authors:** Pan Guojun
28
28
  Date: 2025-01-14
29
- Version: 7.1.0
29
+ Version: 7.1.1
30
30
  **DOI:** https://doi.org/10.5281/zenodo.14435613
31
31
  """
32
32
 
33
- __version__ = '7.1.0'
33
+ __version__ = '7.1.1'
34
34
 
35
35
  import numpy as np
36
36
  from typing import Tuple, Optional, Callable, Dict, Any
@@ -18,6 +18,7 @@ Date: 2025-12-03
18
18
  """
19
19
 
20
20
  import math
21
+ import weakref
21
22
  import numpy as np
22
23
  from typing import Tuple, Optional, Callable, Union, Dict, List
23
24
  from .coordinate_system import coord3, vec3
@@ -38,6 +39,7 @@ def _safe_normal_from_tangents(r_u: vec3, r_v: vec3) -> vec3:
38
39
  return n * (1.0 / length)
39
40
  return vec3(0.0, 0.0, 1.0)
40
41
 
42
+
41
43
  def derivative_5pt(f: Callable[[float], np.ndarray], x: float, h: float) -> np.ndarray:
42
44
  """
43
45
  5-point finite difference formula for first derivative.
@@ -328,7 +330,6 @@ class IntrinsicGradientOperator:
328
330
  n = _safe_normal_from_tangents(r_theta, r_phi)
329
331
  e1 = r_theta.normalized()
330
332
  e2 = r_phi.normalized()
331
-
332
333
  elif isinstance(self.surface, Torus):
333
334
  R = self.surface.R
334
335
  r = self.surface.r
@@ -351,7 +352,6 @@ class IntrinsicGradientOperator:
351
352
  n = _safe_normal_from_tangents(r_u, r_v)
352
353
  e1 = r_u.normalized()
353
354
  e2 = r_v.normalized()
354
-
355
355
  else:
356
356
  # Numerical method for general surfaces
357
357
  pos = self.surface.position(u, v)
@@ -361,14 +361,12 @@ class IntrinsicGradientOperator:
361
361
  n = _safe_normal_from_tangents(r_u, r_v)
362
362
  e1 = r_u.normalized()
363
363
  e2 = r_v.normalized()
364
-
365
364
  # Create intrinsic frame
366
365
  frame = coord3()
367
366
  frame.o = pos
368
367
  frame.ux = e1
369
368
  frame.uy = e2
370
369
  frame.uz = n
371
-
372
370
  return frame
373
371
 
374
372
  def compute_both(self, u: float, v: float) -> Tuple[GradientResult, GradientResult, coord3]:
@@ -426,6 +424,9 @@ class IntrinsicGradientCurvatureCalculator:
426
424
  self.surface = surface
427
425
  self.h = step_size
428
426
  self.grad_op = IntrinsicGradientOperator(surface, step_size)
427
+ self._cache_u: Optional[float] = None
428
+ self._cache_v: Optional[float] = None
429
+ self._cache_terms: Optional[Tuple[float, float, float, float, float, float, float, float]] = None
429
430
 
430
431
  def _get_tangent_vectors(self, u: float, v: float) -> Tuple[vec3, vec3]:
431
432
  """Get tangent vectors (analytical for known surfaces, numerical otherwise)."""
@@ -461,9 +462,12 @@ class IntrinsicGradientCurvatureCalculator:
461
462
 
462
463
  return r_u, r_v
463
464
 
464
- def compute_gaussian_curvature(self, u: float, v: float) -> float:
465
+ def _compute_shape_terms(self, u: float, v: float) -> Tuple[float, float, float, float, float, float, float, float]:
465
466
  """
466
- Compute Gaussian curvature K = det(II) / det(I).
467
+ Compute shared shape-operator terms used by multiple curvature routines.
468
+
469
+ Returns:
470
+ (E, F, G, metric_det, L, M, N, M_uv)
467
471
  """
468
472
  G_u, G_v, _ = self.grad_op.compute_both(u, v)
469
473
  r_u, r_v = self._get_tangent_vectors(u, v)
@@ -477,45 +481,39 @@ class IntrinsicGradientCurvatureCalculator:
477
481
  G = r_v.dot(r_v)
478
482
  metric_det = E * G - F * F
479
483
 
480
- # Second fundamental form
484
+ # Second fundamental form components
481
485
  L = -dn_du.dot(r_u)
482
- M1 = -dn_du.dot(r_v)
483
- M2 = -dn_dv.dot(r_u)
486
+ M_uv = -dn_du.dot(r_v)
487
+ M_vu = -dn_dv.dot(r_u)
484
488
  N = -dn_dv.dot(r_v)
485
- M = (M1 + M2) / 2.0
486
-
487
- # Gaussian curvature
488
- if abs(metric_det) > 1e-14:
489
- K = (L * N - M * M) / metric_det
490
- else:
491
- K = 0.0
492
-
493
- return K
494
-
495
- def compute_mean_curvature(self, u: float, v: float) -> float:
489
+ M = (M_uv + M_vu) / 2.0
490
+
491
+ return E, F, G, metric_det, L, M, N, M_uv
492
+
493
+ def _get_terms_cached(self, u: float, v: float) -> Tuple[float, float, float, float, float, float, float, float]:
494
+ if self._cache_terms is not None and u == self._cache_u and v == self._cache_v:
495
+ return self._cache_terms
496
+ terms = self._compute_shape_terms(u, v)
497
+ self._cache_u = u
498
+ self._cache_v = v
499
+ self._cache_terms = terms
500
+ return terms
501
+
502
+ def _compute_curvatures_from_terms(
503
+ self,
504
+ u: float,
505
+ terms: Tuple[float, float, float, float, float, float, float, float]
506
+ ) -> Tuple[float, float]:
496
507
  """
497
- Compute mean curvature H = (EN - 2FM + GL) / (2*det(I)).
508
+ Compute Gaussian and mean curvature from shared terms.
498
509
  """
499
- G_u, G_v, _ = self.grad_op.compute_both(u, v)
500
- r_u, r_v = self._get_tangent_vectors(u, v)
501
-
502
- dn_du = G_u.dn
503
- dn_dv = G_v.dn
504
-
505
- E = r_u.dot(r_u)
506
- F = r_u.dot(r_v)
507
- G = r_v.dot(r_v)
508
- metric_det = E * G - F * F
509
-
510
- L = -dn_du.dot(r_u)
511
- M1 = -dn_du.dot(r_v)
512
- M2 = -dn_dv.dot(r_u)
513
- N = -dn_dv.dot(r_v)
514
- M = (M1 + M2) / 2.0
510
+ E, F, G, metric_det, L, M, N, _ = terms
515
511
 
516
512
  if abs(metric_det) > 1e-14:
513
+ K = (L * N - M * M) / metric_det
517
514
  H = (G * L - 2 * F * M + E * N) / (2 * metric_det)
518
515
  else:
516
+ K = 0.0
519
517
  H = 0.0
520
518
 
521
519
  if isinstance(self.surface, Sphere):
@@ -527,6 +525,22 @@ class IntrinsicGradientCurvatureCalculator:
527
525
  if theory != 0.0:
528
526
  H = math.copysign(abs(H), theory)
529
527
 
528
+ return K, H
529
+
530
+ def compute_gaussian_curvature(self, u: float, v: float) -> float:
531
+ """
532
+ Compute Gaussian curvature K = det(II) / det(I).
533
+ """
534
+ terms = self._get_terms_cached(u, v)
535
+ K, _ = self._compute_curvatures_from_terms(u, terms)
536
+ return K
537
+
538
+ def compute_mean_curvature(self, u: float, v: float) -> float:
539
+ """
540
+ Compute mean curvature H = (EN - 2FM + GL) / (2*det(I)).
541
+ """
542
+ terms = self._get_terms_cached(u, v)
543
+ _, H = self._compute_curvatures_from_terms(u, terms)
530
544
  return H
531
545
 
532
546
  def compute_riemann_curvature(self, u: float, v: float) -> float:
@@ -535,17 +549,9 @@ class IntrinsicGradientCurvatureCalculator:
535
549
 
536
550
  For 2D surfaces: R^1_212 = K * det(g) = LN - M^2
537
551
  """
538
- G_u, G_v, _ = self.grad_op.compute_both(u, v)
539
- r_u, r_v = self._get_tangent_vectors(u, v)
540
-
541
- dn_du = G_u.dn
542
- dn_dv = G_v.dn
543
-
544
- L = -dn_du.dot(r_u)
545
- M = -dn_du.dot(r_v)
546
- N = -dn_dv.dot(r_v)
547
-
548
- R_1212 = L * N - M * M
552
+ terms = self._get_terms_cached(u, v)
553
+ _, _, _, _, L, _, N, M_uv = terms
554
+ R_1212 = L * N - M_uv * M_uv
549
555
  return R_1212
550
556
 
551
557
  def compute_principal_curvatures(self, u: float, v: float) -> Tuple[float, float]:
@@ -554,8 +560,8 @@ class IntrinsicGradientCurvatureCalculator:
554
560
 
555
561
  Uses: k1,k2 = H +/- sqrt(H^2 - K)
556
562
  """
557
- K = self.compute_gaussian_curvature(u, v)
558
- H = self.compute_mean_curvature(u, v)
563
+ terms = self._get_terms_cached(u, v)
564
+ K, H = self._compute_curvatures_from_terms(u, terms)
559
565
 
560
566
  discriminant = max(0, H * H - K)
561
567
  sqrt_disc = discriminant ** 0.5
@@ -569,8 +575,8 @@ class IntrinsicGradientCurvatureCalculator:
569
575
  """
570
576
  Compute all curvature quantities at once.
571
577
  """
572
- K = self.compute_gaussian_curvature(u, v)
573
- H = self.compute_mean_curvature(u, v)
578
+ terms = self._get_terms_cached(u, v)
579
+ K, H = self._compute_curvatures_from_terms(u, terms)
574
580
 
575
581
  discriminant = max(0, H * H - K)
576
582
  sqrt_disc = discriminant ** 0.5
@@ -599,6 +605,28 @@ class CurvatureCalculator:
599
605
  def __init__(self, surface: Surface, step_size: float = 1e-3):
600
606
  self.surface = surface
601
607
  self.h = step_size
608
+ self._cache_u: Optional[float] = None
609
+ self._cache_v: Optional[float] = None
610
+ self._cache_derivs: Optional[Dict[str, np.ndarray]] = None
611
+ self._cache_forms: Optional[Tuple[np.ndarray, np.ndarray, np.ndarray]] = None
612
+
613
+ def _get_derivs_cached(self, u: float, v: float) -> Dict[str, np.ndarray]:
614
+ if self._cache_derivs is not None and u == self._cache_u and v == self._cache_v:
615
+ return self._cache_derivs
616
+ derivs = self._compute_derivatives(u, v)
617
+ self._cache_u = u
618
+ self._cache_v = v
619
+ self._cache_derivs = derivs
620
+ self._cache_forms = None
621
+ return derivs
622
+
623
+ def _get_forms_cached(self, u: float, v: float) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
624
+ if self._cache_forms is not None and u == self._cache_u and v == self._cache_v:
625
+ return self._cache_forms
626
+ derivs = self._get_derivs_cached(u, v)
627
+ forms = self.compute_fundamental_forms(u, v, derivs)
628
+ self._cache_forms = forms
629
+ return forms
602
630
 
603
631
  def _position_array(self, u: float, v: float) -> np.ndarray:
604
632
  """Convert vec3 position to numpy array."""
@@ -608,31 +636,62 @@ class CurvatureCalculator:
608
636
  def _compute_derivatives(self, u: float, v: float) -> Dict[str, np.ndarray]:
609
637
  """Compute surface derivatives using high-order finite differences."""
610
638
  effective_h = max(self.h, 1e-6)
611
-
612
- r_u = derivative_5pt(lambda uu: self._position_array(uu, v), u, effective_h)
613
- r_v = derivative_5pt(lambda vv: self._position_array(u, vv), v, effective_h)
614
-
615
- r_uu = derivative_2nd_5pt(lambda uu: self._position_array(uu, v), u, effective_h)
616
- r_vv = derivative_2nd_5pt(lambda vv: self._position_array(u, vv), v, effective_h)
617
- r_uv = derivative_5pt(
618
- lambda vv: derivative_5pt(
619
- lambda uu: self._position_array(uu, vv), u, effective_h
620
- ), v, effective_h
621
- )
639
+ h = effective_h
640
+
641
+ offsets = (-2, -1, 0, 1, 2)
642
+ pos = {}
643
+ for du in offsets:
644
+ u_offset = u + du * h
645
+ for dv in offsets:
646
+ pos[(du, dv)] = self._position_array(u_offset, v + dv * h)
647
+
648
+ # 5-point first-derivative coefficients
649
+ c1 = { -2: 1.0, -1: -8.0, 1: 8.0, 2: -1.0 }
650
+
651
+ # First derivatives
652
+ r_u = (
653
+ pos[(-2, 0)] - 8.0 * pos[(-1, 0)] + 8.0 * pos[(1, 0)] - pos[(2, 0)]
654
+ ) / (12.0 * h)
655
+ r_v = (
656
+ pos[(0, -2)] - 8.0 * pos[(0, -1)] + 8.0 * pos[(0, 1)] - pos[(0, 2)]
657
+ ) / (12.0 * h)
658
+
659
+ # 5-point second derivatives
660
+ r_uu = (
661
+ -pos[(2, 0)] + 16.0 * pos[(1, 0)] - 30.0 * pos[(0, 0)] +
662
+ 16.0 * pos[(-1, 0)] - pos[(-2, 0)]
663
+ ) / (12.0 * h * h)
664
+ r_vv = (
665
+ -pos[(0, 2)] + 16.0 * pos[(0, 1)] - 30.0 * pos[(0, 0)] +
666
+ 16.0 * pos[(0, -1)] - pos[(0, -2)]
667
+ ) / (12.0 * h * h)
668
+
669
+ # Mixed derivative via separable 5-point stencil
670
+ r_uv = np.zeros(3, dtype=np.float64)
671
+ for du, cu in c1.items():
672
+ for dv, cv in c1.items():
673
+ r_uv += (cu * cv) * pos[(du, dv)]
674
+ r_uv /= (144.0 * h * h)
622
675
 
623
676
  return {
624
677
  'r_u': r_u, 'r_v': r_v,
625
678
  'r_uu': r_uu, 'r_vv': r_vv, 'r_uv': r_uv
626
679
  }
627
680
 
628
- def compute_fundamental_forms(self, u: float, v: float) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
681
+ def compute_fundamental_forms(
682
+ self,
683
+ u: float,
684
+ v: float,
685
+ derivs: Optional[Dict[str, np.ndarray]] = None
686
+ ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
629
687
  """
630
688
  Compute first and second fundamental forms.
631
689
 
632
690
  Returns:
633
691
  (g, h, n): First form, second form, normal vector
634
692
  """
635
- derivs = self._compute_derivatives(u, v)
693
+ if derivs is None:
694
+ derivs = self._compute_derivatives(u, v)
636
695
  r_u = derivs['r_u']
637
696
  r_v = derivs['r_v']
638
697
  r_uu = derivs['r_uu']
@@ -661,40 +720,31 @@ class CurvatureCalculator:
661
720
 
662
721
  return g, h, n
663
722
 
664
- def compute_gaussian_curvature(self, u: float, v: float) -> float:
665
- """Compute Gaussian curvature K = det(II) / det(I)."""
666
- g, h, _ = self.compute_fundamental_forms(u, v)
667
-
723
+ def _compute_curvatures_from_forms(
724
+ self,
725
+ g: np.ndarray,
726
+ h: np.ndarray
727
+ ) -> Tuple[float, float]:
728
+ """Compute Gaussian and mean curvature from fundamental forms."""
668
729
  det_g = np.linalg.det(g)
669
- det_h = np.linalg.det(h)
670
-
671
730
  if abs(det_g) < 1e-14:
672
- return 0.0
673
-
674
- return det_h / det_g
731
+ return 0.0, 0.0
675
732
 
676
- def compute_mean_curvature(self, u: float, v: float) -> float:
677
- """Compute mean curvature H."""
678
- g, h, _ = self.compute_fundamental_forms(u, v)
679
-
680
- det_g = np.linalg.det(g)
681
- if abs(det_g) < 1e-14:
682
- return 0.0
733
+ det_h = np.linalg.det(h)
734
+ K = det_h / det_g
683
735
 
684
736
  trace_term = g[1, 1] * h[0, 0] - 2 * g[0, 1] * h[0, 1] + g[0, 0] * h[1, 1]
685
737
  H = trace_term / (2 * det_g)
686
738
 
687
- return abs(H)
739
+ return K, abs(H)
688
740
 
689
- def compute_principal_curvatures(self, u: float, v: float) -> Tuple[float, float, np.ndarray, np.ndarray]:
690
- """
691
- Compute principal curvatures and principal directions.
692
-
693
- Returns:
694
- (k1, k2, dir1, dir2): Principal curvatures and directions
695
- """
696
- g, h, _ = self.compute_fundamental_forms(u, v)
697
- derivs = self._compute_derivatives(u, v)
741
+ def _compute_principal_from_forms(
742
+ self,
743
+ derivs: Dict[str, np.ndarray],
744
+ g: np.ndarray,
745
+ h: np.ndarray
746
+ ) -> Tuple[float, float, np.ndarray, np.ndarray]:
747
+ """Compute principal curvatures and directions from forms."""
698
748
  r_u = derivs['r_u']
699
749
  r_v = derivs['r_v']
700
750
 
@@ -702,20 +752,16 @@ class CurvatureCalculator:
702
752
  if abs(det_g) < 1e-14:
703
753
  return 0.0, 0.0, np.array([1., 0., 0.]), np.array([0., 1., 0.])
704
754
 
705
- # Shape operator S = g^{-1} h
706
755
  g_inv = np.linalg.inv(g)
707
756
  S = g_inv @ h
708
757
 
709
- # Eigenvalue decomposition
710
758
  eigenvalues, eigenvectors = np.linalg.eig(S)
711
759
  k1, k2 = eigenvalues.real
712
760
 
713
- # Ensure k1 >= k2 by absolute value
714
761
  if abs(k1) < abs(k2):
715
762
  k1, k2 = k2, k1
716
763
  eigenvectors = eigenvectors[:, [1, 0]]
717
764
 
718
- # Convert to 3D directions
719
765
  dir1_2d = eigenvectors[:, 0]
720
766
  dir2_2d = eigenvectors[:, 1]
721
767
 
@@ -727,12 +773,35 @@ class CurvatureCalculator:
727
773
 
728
774
  return k1, k2, dir1_3d, dir2_3d
729
775
 
776
+ def compute_gaussian_curvature(self, u: float, v: float) -> float:
777
+ """Compute Gaussian curvature K = det(II) / det(I)."""
778
+ g, h, _ = self._get_forms_cached(u, v)
779
+ K, _ = self._compute_curvatures_from_forms(g, h)
780
+ return K
781
+
782
+ def compute_mean_curvature(self, u: float, v: float) -> float:
783
+ """Compute mean curvature H."""
784
+ g, h, _ = self._get_forms_cached(u, v)
785
+ _, H = self._compute_curvatures_from_forms(g, h)
786
+ return H
787
+
788
+ def compute_principal_curvatures(self, u: float, v: float) -> Tuple[float, float, np.ndarray, np.ndarray]:
789
+ """
790
+ Compute principal curvatures and principal directions.
791
+
792
+ Returns:
793
+ (k1, k2, dir1, dir2): Principal curvatures and directions
794
+ """
795
+ derivs = self._get_derivs_cached(u, v)
796
+ g, h, _ = self._get_forms_cached(u, v)
797
+ return self._compute_principal_from_forms(derivs, g, h)
798
+
730
799
  def compute_all_curvatures(self, u: float, v: float) -> Dict[str, Union[float, np.ndarray]]:
731
800
  """Compute all curvature quantities at once."""
732
- g, h, n = self.compute_fundamental_forms(u, v)
733
- K = self.compute_gaussian_curvature(u, v)
734
- H = self.compute_mean_curvature(u, v)
735
- k1, k2, dir1, dir2 = self.compute_principal_curvatures(u, v)
801
+ derivs = self._get_derivs_cached(u, v)
802
+ g, h, n = self._get_forms_cached(u, v)
803
+ K, H = self._compute_curvatures_from_forms(g, h)
804
+ k1, k2, dir1, dir2 = self._compute_principal_from_forms(derivs, g, h)
736
805
 
737
806
  return {
738
807
  'K': K,
@@ -751,6 +820,102 @@ class CurvatureCalculator:
751
820
  # Convenience Functions - Intrinsic Gradient Method (Default)
752
821
  # ============================================================
753
822
 
823
+ _intrinsic_calc_cache: "weakref.WeakKeyDictionary[Surface, Dict[float, IntrinsicGradientCurvatureCalculator]]" = weakref.WeakKeyDictionary()
824
+ _classical_calc_cache: "weakref.WeakKeyDictionary[Surface, Dict[float, CurvatureCalculator]]" = weakref.WeakKeyDictionary()
825
+ _intrinsic_grad_cache: "weakref.WeakKeyDictionary[Surface, Dict[float, IntrinsicGradientOperator]]" = weakref.WeakKeyDictionary()
826
+
827
+
828
+ def _get_cached_calc(cache, surface: Surface, step_size: float, ctor, attr_name: str):
829
+ try:
830
+ surf_dict = surface.__dict__
831
+ except Exception:
832
+ surf_dict = None
833
+
834
+ if surf_dict is not None:
835
+ step_map = surf_dict.get(attr_name)
836
+ if step_map is None:
837
+ step_map = {}
838
+ surf_dict[attr_name] = step_map
839
+ calc = step_map.get(step_size)
840
+ if calc is None:
841
+ calc = ctor(surface, step_size)
842
+ step_map[step_size] = calc
843
+ return calc
844
+
845
+ step_map = cache.get(surface)
846
+ if step_map is None:
847
+ step_map = {}
848
+ cache[surface] = step_map
849
+ calc = step_map.get(step_size)
850
+ if calc is None:
851
+ calc = ctor(surface, step_size)
852
+ step_map[step_size] = calc
853
+ return calc
854
+
855
+
856
+ def _curvatures_from_derivs(
857
+ r_u: vec3,
858
+ r_v: vec3,
859
+ r_uu: vec3,
860
+ r_uv: vec3,
861
+ r_vv: vec3
862
+ ) -> Tuple[float, float]:
863
+ E = r_u.dot(r_u)
864
+ F = r_u.dot(r_v)
865
+ G = r_v.dot(r_v)
866
+ denom = E * G - F * F
867
+ if abs(denom) < 1e-14:
868
+ return 0.0, 0.0
869
+ n = _safe_normal_from_tangents(r_u, r_v)
870
+ L = r_uu.dot(n)
871
+ M = r_uv.dot(n)
872
+ N = r_vv.dot(n)
873
+ K = (L * N - M * M) / denom
874
+ H = (E * N - 2.0 * F * M + G * L) / (2.0 * denom)
875
+ return K, H
876
+
877
+
878
+ def _analytic_curvatures(surface: Surface, u: float, v: float) -> Optional[Tuple[float, float]]:
879
+ if not USE_ANALYTIC_DERIVS:
880
+ return None
881
+ if isinstance(surface, Sphere):
882
+ return surface.theoretical_gaussian_curvature, surface.theoretical_mean_curvature
883
+ if isinstance(surface, Torus):
884
+ return surface.theoretical_gaussian_curvature(u), surface.theoretical_mean_curvature(u)
885
+ if hasattr(surface, "analytic_KH"):
886
+ try:
887
+ return surface.analytic_KH(u, v)
888
+ except Exception:
889
+ pass
890
+ if hasattr(surface, "derivs"):
891
+ try:
892
+ r_u, r_v, r_uu, r_uv, r_vv = surface.derivs(u, v)
893
+ return _curvatures_from_derivs(r_u, r_v, r_uu, r_uv, r_vv)
894
+ except Exception:
895
+ pass
896
+ return None
897
+
898
+
899
+ _last_intrinsic: Dict[str, Union[Surface, float, Tuple[float, float], None]] = {
900
+ "surface": None,
901
+ "u": None,
902
+ "v": None,
903
+ "step": None,
904
+ "kh": None,
905
+ }
906
+
907
+ _last_classical: Dict[str, Union[Surface, float, Tuple[float, float], None]] = {
908
+ "surface": None,
909
+ "u": None,
910
+ "v": None,
911
+ "step": None,
912
+ "kh": None,
913
+ }
914
+
915
+ # Toggle analytic fast path (derivs/analytic_KH/theoretical formulas)
916
+ USE_ANALYTIC_DERIVS = True
917
+
918
+
754
919
  def compute_gaussian_curvature(
755
920
  surface: Surface,
756
921
  u: float,
@@ -760,8 +925,24 @@ def compute_gaussian_curvature(
760
925
  """
761
926
  Compute Gaussian curvature using intrinsic gradient method.
762
927
  """
763
- calc = IntrinsicGradientCurvatureCalculator(surface, step_size)
764
- return calc.compute_gaussian_curvature(u, v)
928
+ if (
929
+ _last_intrinsic["surface"] is surface and
930
+ _last_intrinsic["u"] == u and
931
+ _last_intrinsic["v"] == v and
932
+ _last_intrinsic["step"] == step_size and
933
+ _last_intrinsic["kh"] is not None
934
+ ):
935
+ return _last_intrinsic["kh"][0]
936
+
937
+ analytic = _analytic_curvatures(surface, u, v)
938
+ if analytic is not None:
939
+ _last_intrinsic.update({"surface": surface, "u": u, "v": v, "step": step_size, "kh": analytic})
940
+ return analytic[0]
941
+
942
+ calc = _get_cached_calc(_intrinsic_calc_cache, surface, step_size, IntrinsicGradientCurvatureCalculator, "_cs_intrinsic_calc")
943
+ K = calc.compute_gaussian_curvature(u, v)
944
+ _last_intrinsic.update({"surface": surface, "u": u, "v": v, "step": step_size, "kh": (K, None)})
945
+ return K
765
946
 
766
947
 
767
948
  def compute_mean_curvature(
@@ -773,8 +954,25 @@ def compute_mean_curvature(
773
954
  """
774
955
  Compute mean curvature using intrinsic gradient method.
775
956
  """
776
- calc = IntrinsicGradientCurvatureCalculator(surface, step_size)
777
- return calc.compute_mean_curvature(u, v)
957
+ if (
958
+ _last_intrinsic["surface"] is surface and
959
+ _last_intrinsic["u"] == u and
960
+ _last_intrinsic["v"] == v and
961
+ _last_intrinsic["step"] == step_size and
962
+ _last_intrinsic["kh"] is not None and
963
+ _last_intrinsic["kh"][1] is not None
964
+ ):
965
+ return _last_intrinsic["kh"][1]
966
+
967
+ analytic = _analytic_curvatures(surface, u, v)
968
+ if analytic is not None:
969
+ _last_intrinsic.update({"surface": surface, "u": u, "v": v, "step": step_size, "kh": analytic})
970
+ return analytic[1]
971
+
972
+ calc = _get_cached_calc(_intrinsic_calc_cache, surface, step_size, IntrinsicGradientCurvatureCalculator, "_cs_intrinsic_calc")
973
+ H = calc.compute_mean_curvature(u, v)
974
+ _last_intrinsic.update({"surface": surface, "u": u, "v": v, "step": step_size, "kh": (None, H)})
975
+ return H
778
976
 
779
977
 
780
978
  def compute_riemann_curvature(
@@ -786,7 +984,7 @@ def compute_riemann_curvature(
786
984
  """
787
985
  Compute Riemann curvature tensor component R^1_212.
788
986
  """
789
- calc = IntrinsicGradientCurvatureCalculator(surface, step_size)
987
+ calc = _get_cached_calc(_intrinsic_calc_cache, surface, step_size, IntrinsicGradientCurvatureCalculator, "_cs_intrinsic_calc")
790
988
  return calc.compute_riemann_curvature(u, v)
791
989
 
792
990
 
@@ -799,7 +997,20 @@ def compute_all_curvatures(
799
997
  """
800
998
  Compute all curvature quantities using intrinsic gradient method.
801
999
  """
802
- calc = IntrinsicGradientCurvatureCalculator(surface, step_size)
1000
+ analytic = _analytic_curvatures(surface, u, v)
1001
+ if analytic is not None:
1002
+ K, H = analytic
1003
+ discriminant = max(0, H * H - K)
1004
+ sqrt_disc = discriminant ** 0.5
1005
+ k1 = H + sqrt_disc
1006
+ k2 = H - sqrt_disc
1007
+ return {
1008
+ 'gaussian_curvature': K,
1009
+ 'mean_curvature': H,
1010
+ 'principal_curvatures': (k1, k2)
1011
+ }
1012
+
1013
+ calc = _get_cached_calc(_intrinsic_calc_cache, surface, step_size, IntrinsicGradientCurvatureCalculator, "_cs_intrinsic_calc")
803
1014
  return calc.compute_all_curvatures(u, v)
804
1015
 
805
1016
 
@@ -822,7 +1033,7 @@ def compute_intrinsic_gradient(
822
1033
  Returns:
823
1034
  GradientResult object
824
1035
  """
825
- grad_op = IntrinsicGradientOperator(surface, step_size)
1036
+ grad_op = _get_cached_calc(_intrinsic_grad_cache, surface, step_size, IntrinsicGradientOperator, "_cs_intrinsic_grad")
826
1037
 
827
1038
  if direction == 'u':
828
1039
  return grad_op.compute_u(u, v)
@@ -843,8 +1054,24 @@ def gaussian_curvature_classical(
843
1054
  step_size: float = 1e-3
844
1055
  ) -> float:
845
1056
  """Compute Gaussian curvature using classical method."""
846
- calc = CurvatureCalculator(surface, step_size)
847
- return calc.compute_gaussian_curvature(u, v)
1057
+ if (
1058
+ _last_classical["surface"] is surface and
1059
+ _last_classical["u"] == u and
1060
+ _last_classical["v"] == v and
1061
+ _last_classical["step"] == step_size and
1062
+ _last_classical["kh"] is not None
1063
+ ):
1064
+ return _last_classical["kh"][0]
1065
+
1066
+ analytic = _analytic_curvatures(surface, u, v)
1067
+ if analytic is not None:
1068
+ _last_classical.update({"surface": surface, "u": u, "v": v, "step": step_size, "kh": (analytic[0], abs(analytic[1]))})
1069
+ return analytic[0]
1070
+
1071
+ calc = _get_cached_calc(_classical_calc_cache, surface, step_size, CurvatureCalculator, "_cs_classical_calc")
1072
+ K = calc.compute_gaussian_curvature(u, v)
1073
+ _last_classical.update({"surface": surface, "u": u, "v": v, "step": step_size, "kh": (K, None)})
1074
+ return K
848
1075
 
849
1076
 
850
1077
  def mean_curvature_classical(
@@ -854,8 +1081,25 @@ def mean_curvature_classical(
854
1081
  step_size: float = 1e-3
855
1082
  ) -> float:
856
1083
  """Compute mean curvature using classical method."""
857
- calc = CurvatureCalculator(surface, step_size)
858
- return calc.compute_mean_curvature(u, v)
1084
+ if (
1085
+ _last_classical["surface"] is surface and
1086
+ _last_classical["u"] == u and
1087
+ _last_classical["v"] == v and
1088
+ _last_classical["step"] == step_size and
1089
+ _last_classical["kh"] is not None and
1090
+ _last_classical["kh"][1] is not None
1091
+ ):
1092
+ return _last_classical["kh"][1]
1093
+
1094
+ analytic = _analytic_curvatures(surface, u, v)
1095
+ if analytic is not None:
1096
+ _last_classical.update({"surface": surface, "u": u, "v": v, "step": step_size, "kh": (analytic[0], abs(analytic[1]))})
1097
+ return abs(analytic[1])
1098
+
1099
+ calc = _get_cached_calc(_classical_calc_cache, surface, step_size, CurvatureCalculator, "_cs_classical_calc")
1100
+ H = calc.compute_mean_curvature(u, v)
1101
+ _last_classical.update({"surface": surface, "u": u, "v": v, "step": step_size, "kh": (None, H)})
1102
+ return H
859
1103
 
860
1104
 
861
1105
  def principal_curvatures_classical(
@@ -865,7 +1109,7 @@ def principal_curvatures_classical(
865
1109
  step_size: float = 1e-3
866
1110
  ) -> Tuple[float, float]:
867
1111
  """Compute principal curvatures using classical method."""
868
- calc = CurvatureCalculator(surface, step_size)
1112
+ calc = _get_cached_calc(_classical_calc_cache, surface, step_size, CurvatureCalculator, "_cs_classical_calc")
869
1113
  k1, k2, _, _ = calc.compute_principal_curvatures(u, v)
870
1114
  return k1, k2
871
1115
 
@@ -877,7 +1121,7 @@ def all_curvatures_classical(
877
1121
  step_size: float = 1e-3
878
1122
  ) -> Dict[str, Union[float, np.ndarray]]:
879
1123
  """Compute all curvature quantities using classical method."""
880
- calc = CurvatureCalculator(surface, step_size)
1124
+ calc = _get_cached_calc(_classical_calc_cache, surface, step_size, CurvatureCalculator, "_cs_classical_calc")
881
1125
  return calc.compute_all_curvatures(u, v)
882
1126
 
883
1127
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: coordinate_system
3
- Version: 7.1.0
3
+ Version: 7.1.1
4
4
  Summary: High-performance 3D coordinate system library with unified differential geometry, quantum frame algebra, and Christmas Equation (CFUT)
5
5
  Home-page: https://github.com/panguojun/Coordinate-System
6
6
  Author: Pan Guojun
@@ -51,12 +51,19 @@ Requires-Dist: matplotlib>=3.3.0
51
51
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
52
52
 
53
53
  **Authors:** Pan Guojun
54
- **Version:** 7.1.0
54
+ **Version:** 7.1.1
55
55
  **License:** MIT
56
56
  **DOI:** https://doi.org/10.5281/zenodo.14435613
57
57
 
58
58
  ---
59
59
 
60
+ ## What's New in v7.1.1 (2026-02-05)
61
+
62
+ - **Curvature Fast Path**: Analytical curvature for Sphere/Torus and any surface providing `derivs` or `analytic_KH` (toggle via `USE_ANALYTIC_DERIVS`)
63
+ - **Caching**: Reuse curvature calculators and last-call results to reduce per-sample overhead
64
+ - **Math Core**: Branchless handedness selection for cross product; optional SIMD alignment via `PMSYS_SIMD_ALIGN`
65
+ - **Build Flags**: AVX2 / fast-math enabled by default in build config for faster native builds
66
+
60
67
  ## What's New in v7.1.0 (2026-01-16)
61
68
 
62
69
  - **Physical Constants**: Added SI unit constants for precision calculations (ALPHA_FS, LAMBDA_C, ALPHA_PROJECTION)
@@ -236,6 +243,12 @@ S_YM = F_xy.yang_mills_action()
236
243
 
237
244
  ## Changelog
238
245
 
246
+ ### v7.1.1 (2026-02-05)
247
+ - **Curvature Fast Path**: Analytical curvature for analytic surfaces with optional toggle
248
+ - **Caching**: Curvature calculator reuse and last-call caching for repeated samples
249
+ - **Math Core**: Branchless cross product handedness selection
250
+ - **Build**: AVX2 / fast-math flags enabled by default for native builds
251
+
239
252
  ### v7.1.0 (2026-01-16)
240
253
  - **Physical Constants**: Added SI unit constants (ALPHA_FS, LAMBDA_C, ALPHA_PROJECTION)
241
254
  - **Projection Factor**: Implemented α = α_fs × λ_c ≈ 1.77×10⁻¹⁴ m for geometry-gauge coupling
@@ -61,13 +61,32 @@
61
61
  #pragma warning(disable:4018)
62
62
  #pragma warning(disable:4005)
63
63
 
64
- // ==============================================================================
65
- // Type definitions
66
- // ==============================================================================
67
- #define real double
68
- #define EPSILON 1e-5
69
- #define DEVICE_CALLABLE
70
- #define EXPORT_API
64
+ // ==============================================================================
65
+ // Type definitions
66
+ // ==============================================================================
67
+ #define real double
68
+ #define EPSILON 1e-5
69
+
70
+ // Force inline for hot math paths
71
+ #if defined(_MSC_VER)
72
+ #define PMSYS_FORCE_INLINE __forceinline
73
+ #elif defined(__GNUC__) || defined(__clang__)
74
+ #define PMSYS_FORCE_INLINE inline __attribute__((always_inline))
75
+ #else
76
+ #define PMSYS_FORCE_INLINE inline
77
+ #endif
78
+
79
+ // Alignment helpers for SIMD-friendly layouts (opt-in)
80
+ #if defined(PMSYS_SIMD_ALIGN)
81
+ #define PMSYS_ALIGN16 alignas(16)
82
+ #define PMSYS_ALIGN32 alignas(32)
83
+ #else
84
+ #define PMSYS_ALIGN16
85
+ #define PMSYS_ALIGN32
86
+ #endif
87
+
88
+ #define DEVICE_CALLABLE PMSYS_FORCE_INLINE
89
+ #define EXPORT_API
71
90
 
72
91
  // Aliases
73
92
  #define anyptr void*
@@ -152,15 +171,18 @@ inline real lerp(real h1, real h2, real alpha) {
152
171
  // ==============================================================================
153
172
  // Coordinate System Handedness (Left/Right)
154
173
  // ==============================================================================
155
- namespace {
156
- // Global handedness setting: true = left-handed (default), false = right-handed
157
- bool g_use_left_handed_system = true;
158
- }
174
+ namespace {
175
+ // Global handedness setting: true = left-handed (default), false = right-handed
176
+ bool g_use_left_handed_system = true;
177
+ // Cross product sign to avoid per-call branching
178
+ real g_cross_sign = -1.0;
179
+ }
159
180
 
160
181
  // Set coordinate system handedness
161
- inline void set_coordinate_handedness(bool use_left_handed) {
162
- g_use_left_handed_system = use_left_handed;
163
- }
182
+ inline void set_coordinate_handedness(bool use_left_handed) {
183
+ g_use_left_handed_system = use_left_handed;
184
+ g_cross_sign = use_left_handed ? -1.0 : 1.0;
185
+ }
164
186
 
165
187
  // Get current coordinate system handedness
166
188
  inline bool get_coordinate_handedness() {
@@ -231,7 +253,7 @@ inline void hash_combine(std::size_t& seed, const real& v) {
231
253
  // 2D
232
254
  // **********************************************************************
233
255
  #pragma once
234
- struct vector2
256
+ struct PMSYS_ALIGN16 vector2
235
257
  {
236
258
  static const vector2 ZERO;
237
259
  static const vector2 ONE;
@@ -523,7 +545,7 @@ inline real vector2::sEPSILON = EPSILON;
523
545
  // **********************************************************************
524
546
  // 3D
525
547
  // **********************************************************************
526
- struct vector3
548
+ struct PMSYS_ALIGN32 vector3
527
549
  {
528
550
  static const vector3 ZERO;
529
551
  static const vector3 ONE;
@@ -894,25 +916,15 @@ struct vector3
894
916
  const vector3& v = (*this);
895
917
  return v - n * v.dot(n);
896
918
  }
897
- DEVICE_CALLABLE vector3 cross(const vector3& v) const
898
- {
899
- // Use global handedness setting
900
- if (g_use_left_handed_system) {
901
- // Left-handed system
902
- vector3 n;
903
- n.x = -(y * v.z - z * v.y);
904
- n.y = -(z * v.x - x * v.z);
905
- n.z = -(x * v.y - y * v.x);
906
- return n;
907
- } else {
908
- // Right-handed system
909
- vector3 n;
910
- n.x = (y * v.z - z * v.y);
911
- n.y = (z * v.x - x * v.z);
912
- n.z = (x * v.y - y * v.x);
913
- return n;
914
- }
915
- }
919
+ DEVICE_CALLABLE vector3 cross(const vector3& v) const
920
+ {
921
+ // Branchless handedness selection via precomputed sign
922
+ vector3 n;
923
+ n.x = (y * v.z - z * v.y) * g_cross_sign;
924
+ n.y = (z * v.x - x * v.z) * g_cross_sign;
925
+ n.z = (x * v.y - y * v.x) * g_cross_sign;
926
+ return n;
927
+ }
916
928
  DEVICE_CALLABLE vector3 cross_left(const vector3& v) const
917
929
  {
918
930
  vector3 n;
@@ -1025,7 +1037,7 @@ inline real vector3::sEPSILON = EPSILON;
1025
1037
  // **********************************************************************
1026
1038
  // 4D vector
1027
1039
  // **********************************************************************
1028
- struct vector4
1040
+ struct PMSYS_ALIGN32 vector4
1029
1041
  {
1030
1042
  static const vector4 ZERO;
1031
1043
  static const vector4 UX;
@@ -1606,7 +1618,7 @@ inline const vectorn vectorn::CENTER = vectorn(0.5);
1606
1618
  and define the unit element ONE.
1607
1619
 
1608
1620
  **************************************************************************/
1609
- struct quaternion
1621
+ struct PMSYS_ALIGN32 quaternion
1610
1622
  {
1611
1623
  static const quaternion ONE;
1612
1624
  static const quaternion UX;
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
8
8
 
9
9
  [project]
10
10
  name = "coordinate_system"
11
- version = "7.1.0"
11
+ version = "7.1.1"
12
12
  description = "High-performance 3D coordinate system library with unified differential geometry, quantum frame algebra, and Christmas Equation (CFUT)"
13
13
  readme = "README.md"
14
14
  requires-python = ">=3.7"
@@ -3,7 +3,7 @@ setup.py - Cross-platform setup for coordinate_system package
3
3
 
4
4
  **Authors:** Pan Guojun
5
5
  **DOI:** https://doi.org/10.5281/zenodo.14435613
6
- Version: 7.1.0
6
+ Version: 7.1.1
7
7
  License: MIT
8
8
  """
9
9
 
@@ -33,34 +33,42 @@ with open('README.md', 'r', encoding='utf-8') as f:
33
33
  extra_compile_args = []
34
34
  extra_link_args = []
35
35
 
36
- if system == 'Windows':
37
- # MSVC compiler flags
38
- extra_compile_args = [
39
- '/std:c++17', # C++17 standard
40
- '/O2', # Optimization
41
- '/W3', # Warning level
42
- '/EHsc', # Exception handling
43
- '/MD', # Runtime library
44
- ]
45
- elif system == 'Linux':
46
- # GCC compiler flags
47
- extra_compile_args = [
48
- '-std=c++17', # C++17 standard
49
- '-O3', # Optimization
50
- '-Wall', # Warnings
51
- '-fPIC', # Position independent code
52
- '-fvisibility=hidden', # Hide symbols by default
53
- ]
54
- elif system == 'Darwin': # macOS
55
- # Clang compiler flags
56
- extra_compile_args = [
57
- '-std=c++17', # C++17 standard
58
- '-O3', # Optimization
59
- '-Wall', # Warnings
60
- '-fPIC', # Position independent code
61
- '-fvisibility=hidden', # Hide symbols by default
62
- '-mmacosx-version-min=10.14', # macOS 10.14+
63
- ]
36
+ if system == 'Windows':
37
+ # MSVC compiler flags
38
+ extra_compile_args = [
39
+ '/std:c++17', # C++17 standard
40
+ '/O2', # Optimization
41
+ '/arch:AVX2', # Enable AVX2
42
+ '/fp:fast', # Fast floating-point (unsafe math optimizations)
43
+ '/W3', # Warning level
44
+ '/EHsc', # Exception handling
45
+ '/MD', # Runtime library
46
+ ]
47
+ elif system == 'Linux':
48
+ # GCC compiler flags
49
+ extra_compile_args = [
50
+ '-std=c++17', # C++17 standard
51
+ '-O3', # Optimization
52
+ '-march=native', # Enable local CPU features (SSE/AVX)
53
+ '-ffast-math', # Fast math (unsafe)
54
+ '-funroll-loops', # Loop unrolling
55
+ '-Wall', # Warnings
56
+ '-fPIC', # Position independent code
57
+ '-fvisibility=hidden', # Hide symbols by default
58
+ ]
59
+ elif system == 'Darwin': # macOS
60
+ # Clang compiler flags
61
+ extra_compile_args = [
62
+ '-std=c++17', # C++17 standard
63
+ '-O3', # Optimization
64
+ '-march=native', # Enable local CPU features
65
+ '-ffast-math', # Fast math (unsafe)
66
+ '-funroll-loops', # Loop unrolling
67
+ '-Wall', # Warnings
68
+ '-fPIC', # Position independent code
69
+ '-fvisibility=hidden', # Hide symbols by default
70
+ '-mmacosx-version-min=10.14', # macOS 10.14+
71
+ ]
64
72
 
65
73
  # Define the extension module
66
74
  ext_modules = [
@@ -79,7 +87,7 @@ ext_modules = [
79
87
 
80
88
  setup(
81
89
  name='coordinate_system',
82
- version='7.1.0',
90
+ version='7.1.1',
83
91
  packages=find_packages(),
84
92
  ext_modules=ext_modules, # Add extension modules
85
93