awips2/pythonPackages/scientific/Scientific/Functions/Rational.py
root e2ecdcfe33 Initial revision of AWIPS2 11.9.0-7p5
Former-commit-id: a02aeb236c [formerly 9f19e3f712] [formerly a02aeb236c [formerly 9f19e3f712] [formerly 06a8b51d6d [formerly 64fa9254b946eae7e61bbc3f513b7c3696c4f54f]]]
Former-commit-id: 06a8b51d6d
Former-commit-id: 8e80217e59 [formerly 3360eb6c5f]
Former-commit-id: 377dcd10b9
2012-01-06 08:55:05 -06:00

179 lines
5.9 KiB
Python
Executable file

# This module defines a univariate rational function class
#
# Written by Konrad Hinsen <hinsen@cnrs-orleans.fr>
# last revision: 2006-6-12
#
"""
Rational functions in one variable
"""
from Polynomial import Polynomial
from Scientific import N; Numeric = N
class RationalFunction:
"""Rational Function
Instances of this class represent rational functions
in a single variable. They can be evaluated like functions.
Rational functions support addition, subtraction, multiplication,
and division.
"""
def __init__(self, numerator, denominator=[1.]):
"""
@param numerator: polynomial in one variable, or a list
of polynomial coefficients
@type numerator: L{Scientific.Functions.Polynomial.Polynomial}
or C{list} of numbers
@param denominator: polynomial in one variable, or a list
of polynomial coefficients
@type denominator: L{Scientific.Functions.Polynomial.Polynomial}
or C{list} of numbers
"""
if hasattr(numerator, 'is_polynomial'):
self.numerator = numerator
else:
self.numerator = Polynomial(numerator)
if hasattr(denominator, 'is_polynomial'):
self.denominator = denominator
else:
self.denominator = Polynomial(denominator)
self._normalize()
is_rational_function = 1
def __call__(self, value):
return self.numerator(value)/self.denominator(value)
def __repr__(self):
return "RationalFunction(%s,%s)" % (repr(list(self.numerator.coeff)),
repr(list(self.denominator.coeff)))
def _normalize(self):
self.numerator = self._truncate(self.numerator)
self.denominator = self._truncate(self.denominator)
n = 0
while 1:
if self.numerator.coeff[n] != 0:
break
if self.denominator.coeff[n] != 0:
break
n = n + 1
if n == len(self.numerator.coeff):
break
if n > 0:
self.numerator = Polynomial(self.numerator.coeff[n:])
self.denominator = Polynomial(self.denominator.coeff[n:])
factor = self.denominator.coeff[-1]
if factor != 1.:
self.numerator = self.numerator/factor
self.denominator = self.denominator/factor
def _truncate(self, poly):
if poly.coeff[-1] != 0.:
return poly
coeff = poly.coeff
while len(coeff) > 1 and coeff[-1] == 0.:
coeff = coeff[:-1]
return Polynomial(coeff)
def __coerce__(self, other):
if hasattr(other, 'is_rational_function'):
return (self, other)
elif hasattr(other, 'is_polynomial'):
return (self, RationalFunction(other, [1.]))
else:
return (self, RationalFunction([other], [1.]))
def __mul__(self, other):
return RationalFunction(self.numerator*other.numerator,
self.denominator*other.denominator)
__rmul__ = __mul__
def __div__(self, other):
return RationalFunction(self.numerator*other.denominator,
self.denominator*other.numerator)
def __rdiv__(self, other):
return RationalFunction(other.numerator*self.denominator,
other.denominator*self.numerator)
def __add__(self, other):
return RationalFunction(self.numerator*other.denominator+
self.denominator*other.numerator,
self.denominator*other.denominator)
__radd__ = __add__
def __sub__(self, other):
return RationalFunction(self.numerator*other.denominator-
self.denominator*other.numerator,
self.denominator*other.denominator)
def __rsub__(self, other):
return RationalFunction(other.numerator*self.denominator-
other.denominator*self.numerator,
self.denominator*other.denominator)
def divide(self, shift=0):
"""
@param shift: the power of the independent variable by which
the numerator is multiplied prior to division
@type shift: C{int} (non-negative)
@return: a polynomial and a rational function such that the
sum of the two is equal to the original rational function. The
returned rational function's numerator is of lower order than
its denominator.
@rtype: (L{Scientific.Functions.Polynomial.Polynomial},
L{RationalFunction})
"""
num = Numeric.array(self.numerator.coeff, copy=1)
if shift > 0:
num = Numeric.concatenate((shift*[0.], num))
den = self.denominator.coeff
den_order = len(den)
coeff = []
while len(num) >= den_order:
q = num[-1]/den[-1]
coeff.append(q)
num[-den_order:] = num[-den_order:]-q*den
num = num[:-1]
if not coeff:
coeff = [0]
coeff.reverse()
if len(num) == 0:
num = [0]
return Polynomial(coeff), RationalFunction(num, den)
def zeros(self):
"""
Find the X{zeros} (X{roots}) of the numerator by diagonalization
of the associated Frobenius matrix.
@returns: an array containing the zeros
@rtype: C{Numeric.array}
"""
return self.numerator.zeros()
def poles(self):
"""
Find the X{poles} (zeros of the denominator) by diagonalization
of the associated Frobenius matrix.
@returns: an array containing the poles
@rtype: C{Numeric.array}
"""
return self.denominator.zeros()
# Test code
if __name__ == '__main__':
p = Polynomial([1., 1.])
invp = 1./p
pr = RationalFunction(p)
print pr+invp