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

1"""Abstract base class for functions defined on the standard interval [-1, 1]. 

2 

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. 

6 

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""" 

12 

13from abc import ABC, abstractmethod 

14 

15 

16class Onefun(ABC): 

17 """Abstract base class for functions defined on the interval [-1, 1]. 

18 

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. 

22 

23 Concrete subclasses must implement all the abstract methods defined here, 

24 which include constructors, algebraic operations, calculus operations, 

25 and utility functions. 

26 """ 

27 

28 # -------------------------- 

29 # alternative constructors 

30 # -------------------------- 

31 @classmethod 

32 @abstractmethod 

33 def initconst(cls): # pragma: no cover 

34 """Initialize a constant function. 

35 

36 This constructor creates a function that represents a constant value 

37 on the interval [-1, 1]. 

38 

39 Args: 

40 c: The constant value. 

41 

42 Returns: 

43 Onefun: A new instance representing the constant function f(x) = c. 

44 """ 

45 raise NotImplementedError 

46 

47 @classmethod 

48 @abstractmethod 

49 def initempty(cls): # pragma: no cover 

50 """Initialize an empty function. 

51 

52 This constructor creates an empty function representation, which is 

53 useful as a placeholder or for special cases. 

54 

55 Returns: 

56 Onefun: A new empty instance. 

57 """ 

58 raise NotImplementedError 

59 

60 @classmethod 

61 @abstractmethod 

62 def initidentity(cls): # pragma: no cover 

63 """Initialize the identity function f(x) = x. 

64 

65 This constructor creates a function that represents f(x) = x 

66 on the interval [-1, 1]. 

67 

68 Returns: 

69 Onefun: A new instance representing the identity function. 

70 """ 

71 raise NotImplementedError 

72 

73 @classmethod 

74 @abstractmethod 

75 def initfun(cls): # pragma: no cover 

76 """Initialize from a callable function. 

77 

78 This is a general constructor that delegates to either initfun_adaptive 

79 or initfun_fixedlen based on the provided parameters. 

80 

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. 

85 

86 Returns: 

87 Onefun: A new instance representing the function f. 

88 """ 

89 raise NotImplementedError 

90 

91 @classmethod 

92 @abstractmethod 

93 def initfun_adaptive(cls): # pragma: no cover 

94 """Initialize from a callable function using adaptive sampling. 

95 

96 This constructor determines the appropriate number of points needed to 

97 represent the function to a specified tolerance using an adaptive algorithm. 

98 

99 Args: 

100 f (callable): The function to be approximated. 

101 

102 Returns: 

103 Onefun: A new instance representing the function f. 

104 """ 

105 raise NotImplementedError 

106 

107 @classmethod 

108 @abstractmethod 

109 def initfun_fixedlen(cls): # pragma: no cover 

110 """Initialize from a callable function using a fixed number of points. 

111 

112 This constructor uses a specified number of points to represent the function, 

113 rather than determining the number adaptively. 

114 

115 Args: 

116 f (callable): The function to be approximated. 

117 n (int): The number of points to use. 

118 

119 Returns: 

120 Onefun: A new instance representing the function f. 

121 """ 

122 raise NotImplementedError 

123 

124 @classmethod 

125 @abstractmethod 

126 def initvalues(cls): # pragma: no cover 

127 """Initialize from function values at Chebyshev points. 

128 

129 This constructor creates a function representation from values 

130 at Chebyshev points. 

131 

132 Args: 

133 values: Function values at Chebyshev points. 

134 

135 Returns: 

136 Onefun: A new instance representing the function with the given values. 

137 """ 

138 raise NotImplementedError 

139 

140 # ------------------- 

141 # "private" methods 

142 # ------------------- 

143 @abstractmethod 

144 def __call__(self, x): # pragma: no cover 

145 """Evaluate the function at points x. 

146 

147 This method evaluates the function at the specified points. 

148 

149 Args: 

150 x (float or array-like): Points at which to evaluate the function. 

151 These should be in the interval [-1, 1]. 

152 

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 

158 

159 @abstractmethod 

160 def __init__(self): # pragma: no cover 

161 """Initialize a new Onefun instance. 

162 

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 

167 

168 @abstractmethod 

169 def __repr__(self): # pragma: no cover 

170 """Return a string representation of the function. 

171 

172 This method returns a string representation of the function that includes 

173 relevant information about its representation. 

174 

175 Returns: 

176 str: A string representation of the function. 

177 """ 

178 raise NotImplementedError 

179 

180 # ---------------- 

181 # algebra 

182 # ---------------- 

183 @abstractmethod 

184 def __add__(self, other): # pragma: no cover 

185 """Add this function with another function or a scalar. 

186 

187 This method implements the addition operation between this function 

188 and another function or a scalar. 

189 

190 Args: 

191 other (Onefun or scalar): The function or scalar to add to this function. 

192 

193 Returns: 

194 Onefun: A new function representing the sum. 

195 """ 

196 raise NotImplementedError 

197 

198 @abstractmethod 

199 def __mul__(self, other): # pragma: no cover 

200 """Multiply this function with another function or a scalar. 

201 

202 This method implements the multiplication operation between this function 

203 and another function or a scalar. 

204 

205 Args: 

206 other (Onefun or scalar): The function or scalar to multiply with this function. 

207 

208 Returns: 

209 Onefun: A new function representing the product. 

210 """ 

211 raise NotImplementedError 

212 

213 @abstractmethod 

214 def __neg__(self): # pragma: no cover 

215 """Return the negative of this function. 

216 

217 This method implements the unary negation operation for this function. 

218 

219 Returns: 

220 Onefun: A new function representing -f(x). 

221 """ 

222 raise NotImplementedError 

223 

224 @abstractmethod 

225 def __pos__(self): # pragma: no cover 

226 """Return the positive of this function (which is the function itself). 

227 

228 This method implements the unary plus operation for this function. 

229 

230 Returns: 

231 Onefun: This function object (unchanged). 

232 """ 

233 raise NotImplementedError 

234 

235 @abstractmethod 

236 def __pow__(self, power): # pragma: no cover 

237 """Raise this function to a power. 

238 

239 This method implements the power operation for this function. 

240 

241 Args: 

242 power (int, float, or Onefun): The exponent to which this function is raised. 

243 

244 Returns: 

245 Onefun: A new function representing f(x)^power. 

246 """ 

247 raise NotImplementedError 

248 

249 @abstractmethod 

250 def __radd__(self, other): # pragma: no cover 

251 """Add a scalar or another function to this function (from the right). 

252 

253 This method is called when a scalar or another function is added to this function, 

254 i.e., other + self. 

255 

256 Args: 

257 other (scalar or Onefun): The scalar or function to add to this function. 

258 

259 Returns: 

260 Onefun: A new function representing the sum. 

261 """ 

262 raise NotImplementedError 

263 

264 @abstractmethod 

265 def __rmul__(self, other): # pragma: no cover 

266 """Multiply a scalar or another function with this function (from the right). 

267 

268 This method is called when a scalar or another function is multiplied with this function, 

269 i.e., other * self. 

270 

271 Args: 

272 other (scalar or Onefun): The scalar or function to multiply with this function. 

273 

274 Returns: 

275 Onefun: A new function representing the product. 

276 """ 

277 raise NotImplementedError 

278 

279 @abstractmethod 

280 def __rsub__(self, other): # pragma: no cover 

281 """Subtract this function from a scalar or another function. 

282 

283 This method is called when this function is subtracted from a scalar or another function, 

284 i.e., other - self. 

285 

286 Args: 

287 other (scalar or Onefun): The scalar or function from which to subtract this function. 

288 

289 Returns: 

290 Onefun: A new function representing the difference. 

291 """ 

292 raise NotImplementedError 

293 

294 @abstractmethod 

295 def __sub__(self, other): # pragma: no cover 

296 """Subtract another function or a scalar from this function. 

297 

298 This method implements the subtraction operation between this function 

299 and another function or a scalar. 

300 

301 Args: 

302 other (Onefun or scalar): The function or scalar to subtract from this function. 

303 

304 Returns: 

305 Onefun: A new function representing the difference. 

306 """ 

307 raise NotImplementedError 

308 

309 # --------------- 

310 # properties 

311 # --------------- 

312 @property 

313 @abstractmethod 

314 def coeffs(self): # pragma: no cover 

315 """Get the coefficients of the function representation. 

316 

317 This property returns the coefficients used in the function representation, 

318 such as Chebyshev coefficients for a Chebyshev series. 

319 

320 Returns: 

321 array-like: The coefficients of the function representation. 

322 """ 

323 raise NotImplementedError 

324 

325 @property 

326 @abstractmethod 

327 def isconst(self): # pragma: no cover 

328 """Check if this function represents a constant. 

329 

330 This property determines whether the function is constant (i.e., f(x) = c 

331 for some constant c) over the interval [-1, 1]. 

332 

333 Returns: 

334 bool: True if the function is constant, False otherwise. 

335 """ 

336 raise NotImplementedError 

337 

338 @property 

339 @abstractmethod 

340 def isempty(self): # pragma: no cover 

341 """Check if this function is empty. 

342 

343 This property determines whether the function is empty, which is a special 

344 state used as a placeholder or for special cases. 

345 

346 Returns: 

347 bool: True if the function is empty, False otherwise. 

348 """ 

349 raise NotImplementedError 

350 

351 @property 

352 @abstractmethod 

353 def size(self): # pragma: no cover 

354 """Get the size of the function representation. 

355 

356 This property returns the number of coefficients or other measure of the 

357 complexity of the function representation. 

358 

359 Returns: 

360 int: The size of the function representation. 

361 """ 

362 raise NotImplementedError 

363 

364 @property 

365 @abstractmethod 

366 def vscale(self): # pragma: no cover 

367 """Get the vertical scale of the function. 

368 

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]. 

371 

372 Returns: 

373 float: The vertical scale of the function. 

374 """ 

375 raise NotImplementedError 

376 

377 # --------------- 

378 # utilities 

379 # --------------- 

380 @abstractmethod 

381 def copy(self): # pragma: no cover 

382 """Create a deep copy of this function. 

383 

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. 

386 

387 Returns: 

388 Onefun: A new function that is a deep copy of this function. 

389 """ 

390 raise NotImplementedError 

391 

392 @abstractmethod 

393 def imag(self): # pragma: no cover 

394 """Get the imaginary part of this function. 

395 

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. 

398 

399 Returns: 

400 Onefun: A new function representing the imaginary part of this function. 

401 """ 

402 raise NotImplementedError 

403 

404 @abstractmethod 

405 def prolong(self, n): # pragma: no cover 

406 """Extend the function representation to a larger size. 

407 

408 This method extends the function representation to use more coefficients 

409 or a higher degree, which can be useful for certain operations. 

410 

411 Args: 

412 n (int): The new size for the function representation. 

413 

414 Returns: 

415 Onefun: A new function with an extended representation. 

416 """ 

417 raise NotImplementedError 

418 

419 @abstractmethod 

420 def real(self): # pragma: no cover 

421 """Get the real part of this function. 

422 

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. 

425 

426 Returns: 

427 Onefun: A new function representing the real part of this function. 

428 """ 

429 raise NotImplementedError 

430 

431 @abstractmethod 

432 def simplify(self): # pragma: no cover 

433 """Simplify the function representation. 

434 

435 This method simplifies the function representation by removing unnecessary 

436 coefficients or reducing the degree, while maintaining the specified accuracy. 

437 

438 Returns: 

439 Onefun: A new function with a simplified representation. 

440 """ 

441 raise NotImplementedError 

442 

443 @abstractmethod 

444 def values(self): # pragma: no cover 

445 """Get the values of the function at Chebyshev points. 

446 

447 This method returns the values of the function at Chebyshev points, 

448 which can be useful for certain operations or for visualization. 

449 

450 Returns: 

451 array-like: The values of the function at Chebyshev points. 

452 """ 

453 raise NotImplementedError 

454 

455 # -------------- 

456 # rootfinding 

457 # -------------- 

458 @abstractmethod 

459 def roots(self): # pragma: no cover 

460 """Find the roots (zeros) of the function on [-1, 1]. 

461 

462 This method computes the points where the function equals zero 

463 within the interval [-1, 1]. 

464 

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 

470 

471 # ------------- 

472 # calculus 

473 # ------------- 

474 @abstractmethod 

475 def sum(self): # pragma: no cover 

476 """Compute the definite integral of the function over [-1, 1]. 

477 

478 This method calculates the definite integral of the function 

479 over the interval [-1, 1]. 

480 

481 Returns: 

482 float or complex: The definite integral of the function over [-1, 1]. 

483 """ 

484 raise NotImplementedError 

485 

486 @abstractmethod 

487 def cumsum(self): # pragma: no cover 

488 """Compute the indefinite integral of the function. 

489 

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. 

493 

494 Returns: 

495 Onefun: A new function representing the indefinite integral of this function. 

496 """ 

497 raise NotImplementedError 

498 

499 @abstractmethod 

500 def diff(self): # pragma: no cover 

501 """Compute the derivative of the function. 

502 

503 This method calculates the derivative of the function with respect to x. 

504 

505 Returns: 

506 Onefun: A new function representing the derivative of this function. 

507 """ 

508 raise NotImplementedError