Coverage for src / chebpy / onefun.py: 100%
4 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-22 21:33 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-22 21:33 +0000
1"""Abstract base class for functions defined on the standard interval [-1, 1].
3This module provides the Onefun abstract base class, which defines the interface for
4all function representations on the standard interval [-1, 1] in ChebPy. It specifies
5the methods and properties that concrete function classes must implement.
7The Onefun class serves as the foundation for representing functions on the standard
8interval, with concrete implementations like Chebtech inheriting from it. Functions
9defined on arbitrary intervals are typically mapped to this standard interval for
10internal representation and manipulation.
11"""
13from abc import ABC, abstractmethod
14from typing import Any
16import numpy as np
19class Onefun(ABC):
20 """Abstract base class for functions defined on the interval [-1, 1].
22 This class defines the interface for all function representations on the
23 standard interval [-1, 1]. It serves as the base class for specific
24 implementations like Chebtech.
26 Concrete subclasses must implement all the abstract methods defined here,
27 which include constructors, algebraic operations, calculus operations,
28 and utility functions.
29 """
31 # --------------------------
32 # alternative constructors
33 # --------------------------
34 @classmethod
35 @abstractmethod
36 def initconst(cls, c: float) -> "Onefun": # pragma: no cover
37 """Initialize a constant function.
39 This constructor creates a function that represents a constant value
40 on the interval [-1, 1].
42 Args:
43 c: The constant value.
45 Returns:
46 Onefun: A new instance representing the constant function f(x) = c.
47 """
48 raise NotImplementedError
50 @classmethod
51 @abstractmethod
52 def initempty(cls) -> "Onefun": # pragma: no cover
53 """Initialize an empty function.
55 This constructor creates an empty function representation, which is
56 useful as a placeholder or for special cases.
58 Returns:
59 Onefun: A new empty instance.
60 """
61 raise NotImplementedError
63 @classmethod
64 @abstractmethod
65 def initidentity(cls) -> "Onefun": # pragma: no cover
66 """Initialize the identity function f(x) = x.
68 This constructor creates a function that represents f(x) = x
69 on the interval [-1, 1].
71 Returns:
72 Onefun: A new instance representing the identity function.
73 """
74 raise NotImplementedError
76 @classmethod
77 @abstractmethod
78 def initfun(cls, f: Any, n: Any = None) -> "Onefun": # pragma: no cover
79 """Initialize from a callable function.
81 This is a general constructor that delegates to either initfun_adaptive
82 or initfun_fixedlen based on the provided parameters.
84 Args:
85 f (callable): The function to be approximated.
86 n (int, optional): If provided, specifies the number of points to use.
87 If None, determines the number adaptively.
89 Returns:
90 Onefun: A new instance representing the function f.
91 """
92 raise NotImplementedError
94 @classmethod
95 @abstractmethod
96 def initfun_adaptive(cls, f: Any) -> "Onefun": # pragma: no cover
97 """Initialize from a callable function using adaptive sampling.
99 This constructor determines the appropriate number of points needed to
100 represent the function to a specified tolerance using an adaptive algorithm.
102 Args:
103 f (callable): The function to be approximated.
105 Returns:
106 Onefun: A new instance representing the function f.
107 """
108 raise NotImplementedError
110 @classmethod
111 @abstractmethod
112 def initfun_fixedlen(cls, f: Any, n: int) -> "Onefun": # pragma: no cover
113 """Initialize from a callable function using a fixed number of points.
115 This constructor uses a specified number of points to represent the function,
116 rather than determining the number adaptively.
118 Args:
119 f (callable): The function to be approximated.
120 n (int): The number of points to use.
122 Returns:
123 Onefun: A new instance representing the function f.
124 """
125 raise NotImplementedError
127 @classmethod
128 @abstractmethod
129 def initvalues(cls, values: Any) -> "Onefun": # pragma: no cover
130 """Initialize from function values at Chebyshev points.
132 This constructor creates a function representation from values
133 at Chebyshev points.
135 Args:
136 values: Function values at Chebyshev points.
138 Returns:
139 Onefun: A new instance representing the function with the given values.
140 """
141 raise NotImplementedError
143 # -------------------
144 # "private" methods
145 # -------------------
146 @abstractmethod
147 def __call__(self, x: Any) -> Any: # pragma: no cover
148 """Evaluate the function at points x.
150 This method evaluates the function at the specified points.
152 Args:
153 x (float or array-like): Points at which to evaluate the function.
154 These should be in the interval [-1, 1].
156 Returns:
157 float or array-like: The value(s) of the function at the specified point(s).
158 Returns a scalar if x is a scalar, otherwise an array of the same size as x.
159 """
160 raise NotImplementedError
162 @abstractmethod
163 def __init__(self) -> None: # pragma: no cover
164 """Initialize a new Onefun instance.
166 This method initializes a new function representation on the interval [-1, 1].
167 The specific initialization depends on the concrete subclass implementation.
168 """
169 raise NotImplementedError
171 @abstractmethod
172 def __repr__(self) -> str: # pragma: no cover
173 """Return a string representation of the function.
175 This method returns a string representation of the function that includes
176 relevant information about its representation.
178 Returns:
179 str: A string representation of the function.
180 """
181 raise NotImplementedError
183 # ----------------
184 # algebra
185 # ----------------
186 @abstractmethod
187 def __add__(self, other: Any) -> "Onefun": # pragma: no cover
188 """Add this function with another function or a scalar.
190 This method implements the addition operation between this function
191 and another function or a scalar.
193 Args:
194 other (Onefun or scalar): The function or scalar to add to this function.
196 Returns:
197 Onefun: A new function representing the sum.
198 """
199 raise NotImplementedError
201 @abstractmethod
202 def __mul__(self, other: Any) -> "Onefun": # pragma: no cover
203 """Multiply this function with another function or a scalar.
205 This method implements the multiplication operation between this function
206 and another function or a scalar.
208 Args:
209 other (Onefun or scalar): The function or scalar to multiply with this function.
211 Returns:
212 Onefun: A new function representing the product.
213 """
214 raise NotImplementedError
216 @abstractmethod
217 def __neg__(self) -> "Onefun": # pragma: no cover
218 """Return the negative of this function.
220 This method implements the unary negation operation for this function.
222 Returns:
223 Onefun: A new function representing -f(x).
224 """
225 raise NotImplementedError
227 @abstractmethod
228 def __pos__(self) -> "Onefun": # pragma: no cover
229 """Return the positive of this function (which is the function itself).
231 This method implements the unary plus operation for this function.
233 Returns:
234 Onefun: This function object (unchanged).
235 """
236 raise NotImplementedError
238 @abstractmethod
239 def __pow__(self, power: Any) -> "Onefun": # pragma: no cover
240 """Raise this function to a power.
242 This method implements the power operation for this function.
244 Args:
245 power (int, float, or Onefun): The exponent to which this function is raised.
247 Returns:
248 Onefun: A new function representing f(x)^power.
249 """
250 raise NotImplementedError
252 @abstractmethod
253 def __radd__(self, other: Any) -> "Onefun": # pragma: no cover
254 """Add a scalar or another function to this function (from the right).
256 This method is called when a scalar or another function is added to this function,
257 i.e., other + self.
259 Args:
260 other (scalar or Onefun): The scalar or function to add to this function.
262 Returns:
263 Onefun: A new function representing the sum.
264 """
265 raise NotImplementedError
267 @abstractmethod
268 def __rmul__(self, other: Any) -> "Onefun": # pragma: no cover
269 """Multiply a scalar or another function with this function (from the right).
271 This method is called when a scalar or another function is multiplied with this function,
272 i.e., other * self.
274 Args:
275 other (scalar or Onefun): The scalar or function to multiply with this function.
277 Returns:
278 Onefun: A new function representing the product.
279 """
280 raise NotImplementedError
282 @abstractmethod
283 def __rsub__(self, other: Any) -> "Onefun": # pragma: no cover
284 """Subtract this function from a scalar or another function.
286 This method is called when this function is subtracted from a scalar or another function,
287 i.e., other - self.
289 Args:
290 other (scalar or Onefun): The scalar or function from which to subtract this function.
292 Returns:
293 Onefun: A new function representing the difference.
294 """
295 raise NotImplementedError
297 @abstractmethod
298 def __sub__(self, other: Any) -> "Onefun": # pragma: no cover
299 """Subtract another function or a scalar from this function.
301 This method implements the subtraction operation between this function
302 and another function or a scalar.
304 Args:
305 other (Onefun or scalar): The function or scalar to subtract from this function.
307 Returns:
308 Onefun: A new function representing the difference.
309 """
310 raise NotImplementedError
312 # ---------------
313 # properties
314 # ---------------
315 @property
316 @abstractmethod
317 def coeffs(self) -> np.ndarray: # pragma: no cover
318 """Get the coefficients of the function representation.
320 This property returns the coefficients used in the function representation,
321 such as Chebyshev coefficients for a Chebyshev series.
323 Returns:
324 array-like: The coefficients of the function representation.
325 """
326 raise NotImplementedError
328 @property
329 @abstractmethod
330 def isconst(self) -> bool: # pragma: no cover
331 """Check if this function represents a constant.
333 This property determines whether the function is constant (i.e., f(x) = c
334 for some constant c) over the interval [-1, 1].
336 Returns:
337 bool: True if the function is constant, False otherwise.
338 """
339 raise NotImplementedError
341 @property
342 @abstractmethod
343 def isempty(self) -> bool: # pragma: no cover
344 """Check if this function is empty.
346 This property determines whether the function is empty, which is a special
347 state used as a placeholder or for special cases.
349 Returns:
350 bool: True if the function is empty, False otherwise.
351 """
352 raise NotImplementedError
354 @property
355 @abstractmethod
356 def size(self) -> int: # pragma: no cover
357 """Get the size of the function representation.
359 This property returns the number of coefficients or other measure of the
360 complexity of the function representation.
362 Returns:
363 int: The size of the function representation.
364 """
365 raise NotImplementedError
367 @property
368 @abstractmethod
369 def vscale(self) -> float: # pragma: no cover
370 """Get the vertical scale of the function.
372 This property returns a measure of the range of function values, typically
373 the maximum absolute value of the function on the interval [-1, 1].
375 Returns:
376 float: The vertical scale of the function.
377 """
378 raise NotImplementedError
380 # ---------------
381 # utilities
382 # ---------------
383 @abstractmethod
384 def copy(self) -> "Onefun": # pragma: no cover
385 """Create a deep copy of this function.
387 This method creates a new function that is a deep copy of this function,
388 ensuring that modifications to the copy do not affect the original.
390 Returns:
391 Onefun: A new function that is a deep copy of this function.
392 """
393 raise NotImplementedError
395 @abstractmethod
396 def imag(self) -> "Onefun": # pragma: no cover
397 """Get the imaginary part of this function.
399 This method returns a new function representing the imaginary part of this function.
400 If this function is real-valued, returns a zero function.
402 Returns:
403 Onefun: A new function representing the imaginary part of this function.
404 """
405 raise NotImplementedError
407 @abstractmethod
408 def prolong(self, n: int) -> "Onefun": # pragma: no cover
409 """Extend the function representation to a larger size.
411 This method extends the function representation to use more coefficients
412 or a higher degree, which can be useful for certain operations.
414 Args:
415 n (int): The new size for the function representation.
417 Returns:
418 Onefun: A new function with an extended representation.
419 """
420 raise NotImplementedError
422 @abstractmethod
423 def real(self) -> "Onefun": # pragma: no cover
424 """Get the real part of this function.
426 This method returns a new function representing the real part of this function.
427 If this function is already real-valued, returns this function.
429 Returns:
430 Onefun: A new function representing the real part of this function.
431 """
432 raise NotImplementedError
434 @abstractmethod
435 def simplify(self) -> "Onefun": # pragma: no cover
436 """Simplify the function representation.
438 This method simplifies the function representation by removing unnecessary
439 coefficients or reducing the degree, while maintaining the specified accuracy.
441 Returns:
442 Onefun: A new function with a simplified representation.
443 """
444 raise NotImplementedError
446 @abstractmethod
447 def values(self) -> np.ndarray: # pragma: no cover
448 """Get the values of the function at Chebyshev points.
450 This method returns the values of the function at Chebyshev points,
451 which can be useful for certain operations or for visualization.
453 Returns:
454 array-like: The values of the function at Chebyshev points.
455 """
456 raise NotImplementedError
458 # --------------
459 # rootfinding
460 # --------------
461 @abstractmethod
462 def roots(self) -> np.ndarray: # pragma: no cover
463 """Find the roots (zeros) of the function on [-1, 1].
465 This method computes the points where the function equals zero
466 within the interval [-1, 1].
468 Returns:
469 array-like: An array of the roots of the function in the interval [-1, 1],
470 sorted in ascending order.
471 """
472 raise NotImplementedError
474 # -------------
475 # calculus
476 # -------------
477 @abstractmethod
478 def sum(self) -> float: # pragma: no cover
479 """Compute the definite integral of the function over [-1, 1].
481 This method calculates the definite integral of the function
482 over the interval [-1, 1].
484 Returns:
485 float or complex: The definite integral of the function over [-1, 1].
486 """
487 raise NotImplementedError
489 @abstractmethod
490 def cumsum(self) -> "Onefun": # pragma: no cover
491 """Compute the indefinite integral of the function.
493 This method calculates the indefinite integral (antiderivative) of the function,
494 with the constant of integration chosen so that the indefinite integral
495 evaluates to 0 at x = -1.
497 Returns:
498 Onefun: A new function representing the indefinite integral of this function.
499 """
500 raise NotImplementedError
502 @abstractmethod
503 def diff(self) -> "Onefun": # pragma: no cover
504 """Compute the derivative of the function.
506 This method calculates the derivative of the function with respect to x.
508 Returns:
509 Onefun: A new function representing the derivative of this function.
510 """
511 raise NotImplementedError