66
77from rocketpy .mathutils ._calc .polation_base import PolationBase
88
9+ _COMPLEX_ND_ERROR = (
10+ "Complex coordinates are not supported for N-D array-based Function interpolation."
11+ )
12+
913
1014class PolationEvaluator1D (PolationBase ):
11- """Route 1D evaluation to interpolation or extrapolation."""
15+ """Route 1-D evaluation to interpolation or extrapolation.
16+
17+ Complex queries are propagated only to support complex-step
18+ differentiation of a real 1-D sampled Function. Routing uses the real
19+ component so the imaginary perturbation cannot change the selected real
20+ interval. This does not define general interpolation over the complex
21+ plane.
22+ """
1223
1324 __slots__ = (
1425 "_interpolator" ,
@@ -38,6 +49,9 @@ def expose(self):
3849 """Flattens the evaluator into a fast closure for the
3950 simulation loop.
4051 """
52+ if hasattr (self , "_exposed_fn" ):
53+ return self ._exposed_fn
54+
4155 scalar_eval = self ._scalar_fn
4256 vector_eval = self ._vector_fn
4357
@@ -53,6 +67,9 @@ def _eval(x, _is_iterable=None):
5367
5468 def expose_scalar (self ):
5569 """Expose a scalar-only evaluator with no iterable checks."""
70+ if hasattr (self , "_scalar_fn" ):
71+ return self ._scalar_fn
72+
5673 x_min = self ._x_min
5774 x_max = self ._x_max
5875 interp_eval = self ._interpolator .evaluate
@@ -74,6 +91,9 @@ def _scalar(x):
7491
7592 def expose_vector (self ):
7693 """Expose a vector-only evaluator with no iterable checks."""
94+ if hasattr (self , "_vector_fn" ):
95+ return self ._vector_fn
96+
7797 x_min = self ._x_min
7898 x_max = self ._x_max
7999 interp_eval = self ._interpolator .evaluate
@@ -241,6 +261,9 @@ def evaluate(self, *args, _is_iterable=None):
241261 return self ._exposed_fn (* args , _is_iterable = _is_iterable )
242262
243263 def expose (self ):
264+ if hasattr (self , "_exposed_fn" ):
265+ return self ._exposed_fn
266+
244267 scalar_eval = self ._scalar_fn
245268 vector_eval = self ._vector_fn
246269
@@ -256,6 +279,9 @@ def _eval(*args, _is_iterable=None):
256279 return _eval
257280
258281 def expose_scalar (self ):
282+ if hasattr (self , "_scalar_fn" ):
283+ return self ._scalar_fn
284+
259285 min_domain = self ._min_domain
260286 max_domain = self ._max_domain
261287 extrapolation_mask = self ._extrapolation_mask
@@ -264,7 +290,10 @@ def expose_scalar(self):
264290 np_local = np
265291
266292 def _scalar (* args ):
267- points = np_local .array ([args ], dtype = float )
293+ points = np_local .array ([args ])
294+ if np_local .iscomplexobj (points ):
295+ raise TypeError (_COMPLEX_ND_ERROR )
296+ points = points .astype (float , copy = False )
268297 point = points [0 ]
269298 outside_bounds = ((point < min_domain ) | (point > max_domain )).any ()
270299 outside_hull = (
@@ -283,6 +312,9 @@ def _scalar(*args):
283312 return _scalar
284313
285314 def expose_vector (self ): # pylint: disable=too-many-statements
315+ if hasattr (self , "_vector_fn" ):
316+ return self ._vector_fn
317+
286318 min_domain = self ._min_domain
287319 max_domain = self ._max_domain
288320 extrapolation_mask = self ._extrapolation_mask
@@ -292,11 +324,11 @@ def expose_vector(self): # pylint: disable=too-many-statements
292324
293325 def _vector (* args ):
294326 points = np_local .column_stack (args )
295- out_dtype = complex if np_local .iscomplexobj (points ) else float
296- result = np_local . empty ( len ( points ), dtype = out_dtype )
297- points_real = points . real
298- lower = points_real < min_domain
299- upper = points_real > max_domain
327+ if np_local .iscomplexobj (points ):
328+ raise TypeError ( _COMPLEX_ND_ERROR )
329+ result = np_local . empty ( len ( points ), dtype = float )
330+ lower = points < min_domain
331+ upper = points > max_domain
300332 extrap_mask = lower .any (axis = 1 ) | upper .any (axis = 1 )
301333 if extrapolation_mask is not None :
302334 interp_candidates = ~ extrap_mask
@@ -352,6 +384,9 @@ def evaluate(self, *args, _is_iterable=None):
352384 return self ._exposed_fn (* args , _is_iterable = _is_iterable )
353385
354386 def expose (self ):
387+ if hasattr (self , "_exposed_fn" ):
388+ return self ._exposed_fn
389+
355390 scalar_eval = self ._scalar_fn
356391 vector_eval = self ._vector_fn
357392
@@ -367,6 +402,9 @@ def _eval(*args, _is_iterable=None):
367402 return _eval
368403
369404 def expose_scalar (self ):
405+ if hasattr (self , "_scalar_fn" ):
406+ return self ._scalar_fn
407+
370408 min_domain = self ._min_domain
371409 max_domain = self ._max_domain
372410 interp_eval = self ._interpolator .evaluate
@@ -376,14 +414,20 @@ def expose_scalar(self):
376414 if self ._interpolator is self ._extrapolator :
377415
378416 def _scalar_same (* args ):
379- points = np_local .array ([args ], dtype = float )
417+ points = np_local .array ([args ])
418+ if np_local .iscomplexobj (points ):
419+ raise TypeError (_COMPLEX_ND_ERROR )
420+ points = points .astype (float , copy = False )
380421 res = interp_eval (points )
381422 return float (res [0 ])
382423
383424 return _scalar_same
384425
385426 def _scalar (* args ):
386- points = np_local .array ([args ], dtype = float )
427+ points = np_local .array ([args ])
428+ if np_local .iscomplexobj (points ):
429+ raise TypeError (_COMPLEX_ND_ERROR )
430+ points = points .astype (float , copy = False )
387431 point = points [0 ]
388432 if ((point < min_domain ) | (point > max_domain )).any ():
389433 return float (extrap_eval (points )[0 ])
@@ -392,6 +436,9 @@ def _scalar(*args):
392436 return _scalar
393437
394438 def expose_vector (self ):
439+ if hasattr (self , "_vector_fn" ):
440+ return self ._vector_fn
441+
395442 min_domain = self ._min_domain
396443 max_domain = self ._max_domain
397444 interp_eval = self ._interpolator .evaluate
@@ -402,12 +449,16 @@ def expose_vector(self):
402449
403450 def _vector_same (* args ):
404451 points = np_local .column_stack (np_local .broadcast_arrays (* args ))
452+ if np_local .iscomplexobj (points ):
453+ raise TypeError (_COMPLEX_ND_ERROR )
405454 return interp_eval (points )
406455
407456 return _vector_same
408457
409458 def _vector (* args ):
410459 points = np_local .column_stack (np_local .broadcast_arrays (* args ))
460+ if np_local .iscomplexobj (points ):
461+ raise TypeError (_COMPLEX_ND_ERROR )
411462 result = np_local .empty (len (points ), dtype = float )
412463 lower = points < min_domain
413464 upper = points > max_domain
0 commit comments