Coverage for chebpy/core/onefun.py: 100%
2 statements
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-07 10:30 +0000
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-07 10:30 +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
16class Onefun(ABC):
17 """Abstract base class for functions defined on the interval [-1, 1].
19 This class defines the interface for all function representations on the
20 standard interval [-1, 1]. It serves as the base class for specific
21 implementations like Chebtech.
23 Concrete subclasses must implement all the abstract methods defined here,
24 which include constructors, algebraic operations, calculus operations,
25 and utility functions.
26 """
28 # --------------------------
29 # alternative constructors
30 # --------------------------
31 @classmethod
32 @abstractmethod
33 def initconst(cls): # pragma: no cover
34 """Initialize a constant function.
36 This constructor creates a function that represents a constant value
37 on the interval [-1, 1].
39 Args:
40 c: The constant value.
42 Returns:
43 Onefun: A new instance representing the constant function f(x) = c.
44 """
45 raise NotImplementedError
47 @classmethod
48 @abstractmethod
49 def initempty(cls): # pragma: no cover
50 """Initialize an empty function.
52 This constructor creates an empty function representation, which is
53 useful as a placeholder or for special cases.
55 Returns:
56 Onefun: A new empty instance.
57 """
58 raise NotImplementedError
60 @classmethod
61 @abstractmethod
62 def initidentity(cls): # pragma: no cover
63 """Initialize the identity function f(x) = x.
65 This constructor creates a function that represents f(x) = x
66 on the interval [-1, 1].
68 Returns:
69 Onefun: A new instance representing the identity function.
70 """
71 raise NotImplementedError
73 @classmethod
74 @abstractmethod
75 def initfun(cls): # pragma: no cover
76 """Initialize from a callable function.
78 This is a general constructor that delegates to either initfun_adaptive
79 or initfun_fixedlen based on the provided parameters.
81 Args:
82 f (callable): The function to be approximated.
83 n (int, optional): If provided, specifies the number of points to use.
84 If None, determines the number adaptively.
86 Returns:
87 Onefun: A new instance representing the function f.
88 """
89 raise NotImplementedError
91 @classmethod
92 @abstractmethod
93 def initfun_adaptive(cls): # pragma: no cover
94 """Initialize from a callable function using adaptive sampling.
96 This constructor determines the appropriate number of points needed to
97 represent the function to a specified tolerance using an adaptive algorithm.
99 Args:
100 f (callable): The function to be approximated.
102 Returns:
103 Onefun: A new instance representing the function f.
104 """
105 raise NotImplementedError
107 @classmethod
108 @abstractmethod
109 def initfun_fixedlen(cls): # pragma: no cover
110 """Initialize from a callable function using a fixed number of points.
112 This constructor uses a specified number of points to represent the function,
113 rather than determining the number adaptively.
115 Args:
116 f (callable): The function to be approximated.
117 n (int): The number of points to use.
119 Returns:
120 Onefun: A new instance representing the function f.
121 """
122 raise NotImplementedError
124 @classmethod
125 @abstractmethod
126 def initvalues(cls): # pragma: no cover
127 """Initialize from function values at Chebyshev points.
129 This constructor creates a function representation from values
130 at Chebyshev points.
132 Args:
133 values: Function values at Chebyshev points.
135 Returns:
136 Onefun: A new instance representing the function with the given values.
137 """
138 raise NotImplementedError
140 # -------------------
141 # "private" methods
142 # -------------------
143 @abstractmethod
144 def __call__(self, x): # pragma: no cover
145 """Evaluate the function at points x.
147 This method evaluates the function at the specified points.
149 Args:
150 x (float or array-like): Points at which to evaluate the function.
151 These should be in the interval [-1, 1].
153 Returns:
154 float or array-like: The value(s) of the function at the specified point(s).
155 Returns a scalar if x is a scalar, otherwise an array of the same size as x.
156 """
157 raise NotImplementedError
159 @abstractmethod
160 def __init__(self): # pragma: no cover
161 """Initialize a new Onefun instance.
163 This method initializes a new function representation on the interval [-1, 1].
164 The specific initialization depends on the concrete subclass implementation.
165 """
166 raise NotImplementedError
168 @abstractmethod
169 def __repr__(self): # pragma: no cover
170 """Return a string representation of the function.
172 This method returns a string representation of the function that includes
173 relevant information about its representation.
175 Returns:
176 str: A string representation of the function.
177 """
178 raise NotImplementedError
180 # ----------------
181 # algebra
182 # ----------------
183 @abstractmethod
184 def __add__(self, other): # pragma: no cover
185 """Add this function with another function or a scalar.
187 This method implements the addition operation between this function
188 and another function or a scalar.
190 Args:
191 other (Onefun or scalar): The function or scalar to add to this function.
193 Returns:
194 Onefun: A new function representing the sum.
195 """
196 raise NotImplementedError
198 @abstractmethod
199 def __mul__(self, other): # pragma: no cover
200 """Multiply this function with another function or a scalar.
202 This method implements the multiplication operation between this function
203 and another function or a scalar.
205 Args:
206 other (Onefun or scalar): The function or scalar to multiply with this function.
208 Returns:
209 Onefun: A new function representing the product.
210 """
211 raise NotImplementedError
213 @abstractmethod
214 def __neg__(self): # pragma: no cover
215 """Return the negative of this function.
217 This method implements the unary negation operation for this function.
219 Returns:
220 Onefun: A new function representing -f(x).
221 """
222 raise NotImplementedError
224 @abstractmethod
225 def __pos__(self): # pragma: no cover
226 """Return the positive of this function (which is the function itself).
228 This method implements the unary plus operation for this function.
230 Returns:
231 Onefun: This function object (unchanged).
232 """
233 raise NotImplementedError
235 @abstractmethod
236 def __pow__(self, power): # pragma: no cover
237 """Raise this function to a power.
239 This method implements the power operation for this function.
241 Args:
242 power (int, float, or Onefun): The exponent to which this function is raised.
244 Returns:
245 Onefun: A new function representing f(x)^power.
246 """
247 raise NotImplementedError
249 @abstractmethod
250 def __radd__(self, other): # pragma: no cover
251 """Add a scalar or another function to this function (from the right).
253 This method is called when a scalar or another function is added to this function,
254 i.e., other + self.
256 Args:
257 other (scalar or Onefun): The scalar or function to add to this function.
259 Returns:
260 Onefun: A new function representing the sum.
261 """
262 raise NotImplementedError
264 @abstractmethod
265 def __rmul__(self, other): # pragma: no cover
266 """Multiply a scalar or another function with this function (from the right).
268 This method is called when a scalar or another function is multiplied with this function,
269 i.e., other * self.
271 Args:
272 other (scalar or Onefun): The scalar or function to multiply with this function.
274 Returns:
275 Onefun: A new function representing the product.
276 """
277 raise NotImplementedError
279 @abstractmethod
280 def __rsub__(self, other): # pragma: no cover
281 """Subtract this function from a scalar or another function.
283 This method is called when this function is subtracted from a scalar or another function,
284 i.e., other - self.
286 Args:
287 other (scalar or Onefun): The scalar or function from which to subtract this function.
289 Returns:
290 Onefun: A new function representing the difference.
291 """
292 raise NotImplementedError
294 @abstractmethod
295 def __sub__(self, other): # pragma: no cover
296 """Subtract another function or a scalar from this function.
298 This method implements the subtraction operation between this function
299 and another function or a scalar.
301 Args:
302 other (Onefun or scalar): The function or scalar to subtract from this function.
304 Returns:
305 Onefun: A new function representing the difference.
306 """
307 raise NotImplementedError
309 # ---------------
310 # properties
311 # ---------------
312 @property
313 @abstractmethod
314 def coeffs(self): # pragma: no cover
315 """Get the coefficients of the function representation.
317 This property returns the coefficients used in the function representation,
318 such as Chebyshev coefficients for a Chebyshev series.
320 Returns:
321 array-like: The coefficients of the function representation.
322 """
323 raise NotImplementedError
325 @property
326 @abstractmethod
327 def isconst(self): # pragma: no cover
328 """Check if this function represents a constant.
330 This property determines whether the function is constant (i.e., f(x) = c
331 for some constant c) over the interval [-1, 1].
333 Returns:
334 bool: True if the function is constant, False otherwise.
335 """
336 raise NotImplementedError
338 @property
339 @abstractmethod
340 def isempty(self): # pragma: no cover
341 """Check if this function is empty.
343 This property determines whether the function is empty, which is a special
344 state used as a placeholder or for special cases.
346 Returns:
347 bool: True if the function is empty, False otherwise.
348 """
349 raise NotImplementedError
351 @property
352 @abstractmethod
353 def size(self): # pragma: no cover
354 """Get the size of the function representation.
356 This property returns the number of coefficients or other measure of the
357 complexity of the function representation.
359 Returns:
360 int: The size of the function representation.
361 """
362 raise NotImplementedError
364 @property
365 @abstractmethod
366 def vscale(self): # pragma: no cover
367 """Get the vertical scale of the function.
369 This property returns a measure of the range of function values, typically
370 the maximum absolute value of the function on the interval [-1, 1].
372 Returns:
373 float: The vertical scale of the function.
374 """
375 raise NotImplementedError
377 # ---------------
378 # utilities
379 # ---------------
380 @abstractmethod
381 def copy(self): # pragma: no cover
382 """Create a deep copy of this function.
384 This method creates a new function that is a deep copy of this function,
385 ensuring that modifications to the copy do not affect the original.
387 Returns:
388 Onefun: A new function that is a deep copy of this function.
389 """
390 raise NotImplementedError
392 @abstractmethod
393 def imag(self): # pragma: no cover
394 """Get the imaginary part of this function.
396 This method returns a new function representing the imaginary part of this function.
397 If this function is real-valued, returns a zero function.
399 Returns:
400 Onefun: A new function representing the imaginary part of this function.
401 """
402 raise NotImplementedError
404 @abstractmethod
405 def prolong(self, n): # pragma: no cover
406 """Extend the function representation to a larger size.
408 This method extends the function representation to use more coefficients
409 or a higher degree, which can be useful for certain operations.
411 Args:
412 n (int): The new size for the function representation.
414 Returns:
415 Onefun: A new function with an extended representation.
416 """
417 raise NotImplementedError
419 @abstractmethod
420 def real(self): # pragma: no cover
421 """Get the real part of this function.
423 This method returns a new function representing the real part of this function.
424 If this function is already real-valued, returns this function.
426 Returns:
427 Onefun: A new function representing the real part of this function.
428 """
429 raise NotImplementedError
431 @abstractmethod
432 def simplify(self): # pragma: no cover
433 """Simplify the function representation.
435 This method simplifies the function representation by removing unnecessary
436 coefficients or reducing the degree, while maintaining the specified accuracy.
438 Returns:
439 Onefun: A new function with a simplified representation.
440 """
441 raise NotImplementedError
443 @abstractmethod
444 def values(self): # pragma: no cover
445 """Get the values of the function at Chebyshev points.
447 This method returns the values of the function at Chebyshev points,
448 which can be useful for certain operations or for visualization.
450 Returns:
451 array-like: The values of the function at Chebyshev points.
452 """
453 raise NotImplementedError
455 # --------------
456 # rootfinding
457 # --------------
458 @abstractmethod
459 def roots(self): # pragma: no cover
460 """Find the roots (zeros) of the function on [-1, 1].
462 This method computes the points where the function equals zero
463 within the interval [-1, 1].
465 Returns:
466 array-like: An array of the roots of the function in the interval [-1, 1],
467 sorted in ascending order.
468 """
469 raise NotImplementedError
471 # -------------
472 # calculus
473 # -------------
474 @abstractmethod
475 def sum(self): # pragma: no cover
476 """Compute the definite integral of the function over [-1, 1].
478 This method calculates the definite integral of the function
479 over the interval [-1, 1].
481 Returns:
482 float or complex: The definite integral of the function over [-1, 1].
483 """
484 raise NotImplementedError
486 @abstractmethod
487 def cumsum(self): # pragma: no cover
488 """Compute the indefinite integral of the function.
490 This method calculates the indefinite integral (antiderivative) of the function,
491 with the constant of integration chosen so that the indefinite integral
492 evaluates to 0 at x = -1.
494 Returns:
495 Onefun: A new function representing the indefinite integral of this function.
496 """
497 raise NotImplementedError
499 @abstractmethod
500 def diff(self): # pragma: no cover
501 """Compute the derivative of the function.
503 This method calculates the derivative of the function with respect to x.
505 Returns:
506 Onefun: A new function representing the derivative of this function.
507 """
508 raise NotImplementedError