summaryrefslogtreecommitdiff
path: root/numpy/lib
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/lib')
-rw-r--r--numpy/lib/__init__.py2
-rw-r--r--numpy/lib/financial.py967
-rw-r--r--numpy/lib/function_base.py45
-rw-r--r--numpy/lib/polynomial.py2
-rw-r--r--numpy/lib/tests/test_financial.py380
-rw-r--r--numpy/lib/tests/test_financial_expired.py12
-rw-r--r--numpy/lib/tests/test_function_base.py27
-rw-r--r--numpy/lib/tests/test_polynomial.py9
8 files changed, 70 insertions, 1374 deletions
diff --git a/numpy/lib/__init__.py b/numpy/lib/__init__.py
index cb0de0d15..ad88ba347 100644
--- a/numpy/lib/__init__.py
+++ b/numpy/lib/__init__.py
@@ -35,7 +35,6 @@ from .polynomial import *
from .utils import *
from .arraysetops import *
from .npyio import *
-from .financial import *
from .arrayterator import Arrayterator
from .arraypad import *
from ._version import *
@@ -54,7 +53,6 @@ __all__ += polynomial.__all__
__all__ += utils.__all__
__all__ += arraysetops.__all__
__all__ += npyio.__all__
-__all__ += financial.__all__
__all__ += nanfunctions.__all__
__all__ += histograms.__all__
diff --git a/numpy/lib/financial.py b/numpy/lib/financial.py
deleted file mode 100644
index 709a79dc0..000000000
--- a/numpy/lib/financial.py
+++ /dev/null
@@ -1,967 +0,0 @@
-"""Some simple financial calculations
-
-patterned after spreadsheet computations.
-
-There is some complexity in each function
-so that the functions behave like ufuncs with
-broadcasting and being able to be called with scalars
-or arrays (or other sequences).
-
-Functions support the :class:`decimal.Decimal` type unless
-otherwise stated.
-"""
-import warnings
-from decimal import Decimal
-import functools
-
-import numpy as np
-from numpy.core import overrides
-
-
-_depmsg = ("numpy.{name} is deprecated and will be removed from NumPy 1.20. "
- "Use numpy_financial.{name} instead "
- "(https://pypi.org/project/numpy-financial/).")
-
-array_function_dispatch = functools.partial(
- overrides.array_function_dispatch, module='numpy')
-
-
-__all__ = ['fv', 'pmt', 'nper', 'ipmt', 'ppmt', 'pv', 'rate',
- 'irr', 'npv', 'mirr']
-
-_when_to_num = {'end':0, 'begin':1,
- 'e':0, 'b':1,
- 0:0, 1:1,
- 'beginning':1,
- 'start':1,
- 'finish':0}
-
-def _convert_when(when):
- #Test to see if when has already been converted to ndarray
- #This will happen if one function calls another, for example ppmt
- if isinstance(when, np.ndarray):
- return when
- try:
- return _when_to_num[when]
- except (KeyError, TypeError):
- return [_when_to_num[x] for x in when]
-
-
-def _fv_dispatcher(rate, nper, pmt, pv, when=None):
- warnings.warn(_depmsg.format(name='fv'),
- DeprecationWarning, stacklevel=3)
- return (rate, nper, pmt, pv)
-
-
-@array_function_dispatch(_fv_dispatcher)
-def fv(rate, nper, pmt, pv, when='end'):
- """
- Compute the future value.
-
- .. deprecated:: 1.18
-
- `fv` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- Given:
- * a present value, `pv`
- * an interest `rate` compounded once per period, of which
- there are
- * `nper` total
- * a (fixed) payment, `pmt`, paid either
- * at the beginning (`when` = {'begin', 1}) or the end
- (`when` = {'end', 0}) of each period
-
- Return:
- the value at the end of the `nper` periods
-
- Parameters
- ----------
- rate : scalar or array_like of shape(M, )
- Rate of interest as decimal (not per cent) per period
- nper : scalar or array_like of shape(M, )
- Number of compounding periods
- pmt : scalar or array_like of shape(M, )
- Payment
- pv : scalar or array_like of shape(M, )
- Present value
- when : {{'begin', 1}, {'end', 0}}, {string, int}, optional
- When payments are due ('begin' (1) or 'end' (0)).
- Defaults to {'end', 0}.
-
- Returns
- -------
- out : ndarray
- Future values. If all input is scalar, returns a scalar float. If
- any input is array_like, returns future values for each input element.
- If multiple inputs are array_like, they all must have the same shape.
-
- Notes
- -----
- The future value is computed by solving the equation::
-
- fv +
- pv*(1+rate)**nper +
- pmt*(1 + rate*when)/rate*((1 + rate)**nper - 1) == 0
-
- or, when ``rate == 0``::
-
- fv + pv + pmt * nper == 0
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
- .. [2] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
- Open Document Format for Office Applications (OpenDocument)v1.2,
- Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
- Pre-Draft 12. Organization for the Advancement of Structured Information
- Standards (OASIS). Billerica, MA, USA. [ODT Document].
- Available:
- http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formula
- OpenDocument-formula-20090508.odt
-
-
- Examples
- --------
- What is the future value after 10 years of saving $100 now, with
- an additional monthly savings of $100. Assume the interest rate is
- 5% (annually) compounded monthly?
-
- >>> np.fv(0.05/12, 10*12, -100, -100)
- 15692.928894335748
-
- By convention, the negative sign represents cash flow out (i.e. money not
- available today). Thus, saving $100 a month at 5% annual interest leads
- to $15,692.93 available to spend in 10 years.
-
- If any input is array_like, returns an array of equal shape. Let's
- compare different interest rates from the example above.
-
- >>> a = np.array((0.05, 0.06, 0.07))/12
- >>> np.fv(a, 10*12, -100, -100)
- array([ 15692.92889434, 16569.87435405, 17509.44688102]) # may vary
-
- """
- when = _convert_when(when)
- (rate, nper, pmt, pv, when) = map(np.asarray, [rate, nper, pmt, pv, when])
- temp = (1+rate)**nper
- fact = np.where(rate == 0, nper,
- (1 + rate*when)*(temp - 1)/rate)
- return -(pv*temp + pmt*fact)
-
-
-def _pmt_dispatcher(rate, nper, pv, fv=None, when=None):
- warnings.warn(_depmsg.format(name='pmt'),
- DeprecationWarning, stacklevel=3)
- return (rate, nper, pv, fv)
-
-
-@array_function_dispatch(_pmt_dispatcher)
-def pmt(rate, nper, pv, fv=0, when='end'):
- """
- Compute the payment against loan principal plus interest.
-
- .. deprecated:: 1.18
-
- `pmt` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- Given:
- * a present value, `pv` (e.g., an amount borrowed)
- * a future value, `fv` (e.g., 0)
- * an interest `rate` compounded once per period, of which
- there are
- * `nper` total
- * and (optional) specification of whether payment is made
- at the beginning (`when` = {'begin', 1}) or the end
- (`when` = {'end', 0}) of each period
-
- Return:
- the (fixed) periodic payment.
-
- Parameters
- ----------
- rate : array_like
- Rate of interest (per period)
- nper : array_like
- Number of compounding periods
- pv : array_like
- Present value
- fv : array_like, optional
- Future value (default = 0)
- when : {{'begin', 1}, {'end', 0}}, {string, int}
- When payments are due ('begin' (1) or 'end' (0))
-
- Returns
- -------
- out : ndarray
- Payment against loan plus interest. If all input is scalar, returns a
- scalar float. If any input is array_like, returns payment for each
- input element. If multiple inputs are array_like, they all must have
- the same shape.
-
- Notes
- -----
- The payment is computed by solving the equation::
-
- fv +
- pv*(1 + rate)**nper +
- pmt*(1 + rate*when)/rate*((1 + rate)**nper - 1) == 0
-
- or, when ``rate == 0``::
-
- fv + pv + pmt * nper == 0
-
- for ``pmt``.
-
- Note that computing a monthly mortgage payment is only
- one use for this function. For example, pmt returns the
- periodic deposit one must make to achieve a specified
- future balance given an initial deposit, a fixed,
- periodically compounded interest rate, and the total
- number of periods.
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
- .. [2] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
- Open Document Format for Office Applications (OpenDocument)v1.2,
- Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
- Pre-Draft 12. Organization for the Advancement of Structured Information
- Standards (OASIS). Billerica, MA, USA. [ODT Document].
- Available:
- http://www.oasis-open.org/committees/documents.php
- ?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
-
- Examples
- --------
- What is the monthly payment needed to pay off a $200,000 loan in 15
- years at an annual interest rate of 7.5%?
-
- >>> np.pmt(0.075/12, 12*15, 200000)
- -1854.0247200054619
-
- In order to pay-off (i.e., have a future-value of 0) the $200,000 obtained
- today, a monthly payment of $1,854.02 would be required. Note that this
- example illustrates usage of `fv` having a default value of 0.
-
- """
- when = _convert_when(when)
- (rate, nper, pv, fv, when) = map(np.array, [rate, nper, pv, fv, when])
- temp = (1 + rate)**nper
- mask = (rate == 0)
- masked_rate = np.where(mask, 1, rate)
- fact = np.where(mask != 0, nper,
- (1 + masked_rate*when)*(temp - 1)/masked_rate)
- return -(fv + pv*temp) / fact
-
-
-def _nper_dispatcher(rate, pmt, pv, fv=None, when=None):
- warnings.warn(_depmsg.format(name='nper'),
- DeprecationWarning, stacklevel=3)
- return (rate, pmt, pv, fv)
-
-
-@array_function_dispatch(_nper_dispatcher)
-def nper(rate, pmt, pv, fv=0, when='end'):
- """
- Compute the number of periodic payments.
-
- .. deprecated:: 1.18
-
- `nper` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- :class:`decimal.Decimal` type is not supported.
-
- Parameters
- ----------
- rate : array_like
- Rate of interest (per period)
- pmt : array_like
- Payment
- pv : array_like
- Present value
- fv : array_like, optional
- Future value
- when : {{'begin', 1}, {'end', 0}}, {string, int}, optional
- When payments are due ('begin' (1) or 'end' (0))
-
- Notes
- -----
- The number of periods ``nper`` is computed by solving the equation::
-
- fv + pv*(1+rate)**nper + pmt*(1+rate*when)/rate*((1+rate)**nper-1) = 0
-
- but if ``rate = 0`` then::
-
- fv + pv + pmt*nper = 0
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
-
- Examples
- --------
- If you only had $150/month to pay towards the loan, how long would it take
- to pay-off a loan of $8,000 at 7% annual interest?
-
- >>> print(np.round(np.nper(0.07/12, -150, 8000), 5))
- 64.07335
-
- So, over 64 months would be required to pay off the loan.
-
- The same analysis could be done with several different interest rates
- and/or payments and/or total amounts to produce an entire table.
-
- >>> np.nper(*(np.ogrid[0.07/12: 0.08/12: 0.01/12,
- ... -150 : -99 : 50 ,
- ... 8000 : 9001 : 1000]))
- array([[[ 64.07334877, 74.06368256],
- [108.07548412, 127.99022654]],
- [[ 66.12443902, 76.87897353],
- [114.70165583, 137.90124779]]])
-
- """
- when = _convert_when(when)
- (rate, pmt, pv, fv, when) = map(np.asarray, [rate, pmt, pv, fv, when])
-
- use_zero_rate = False
- with np.errstate(divide="raise"):
- try:
- z = pmt*(1+rate*when)/rate
- except FloatingPointError:
- use_zero_rate = True
-
- if use_zero_rate:
- return (-fv + pv) / pmt
- else:
- A = -(fv + pv)/(pmt+0)
- B = np.log((-fv+z) / (pv+z))/np.log(1+rate)
- return np.where(rate == 0, A, B)
-
-
-def _ipmt_dispatcher(rate, per, nper, pv, fv=None, when=None):
- warnings.warn(_depmsg.format(name='ipmt'),
- DeprecationWarning, stacklevel=3)
- return (rate, per, nper, pv, fv)
-
-
-@array_function_dispatch(_ipmt_dispatcher)
-def ipmt(rate, per, nper, pv, fv=0, when='end'):
- """
- Compute the interest portion of a payment.
-
- .. deprecated:: 1.18
-
- `ipmt` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- Parameters
- ----------
- rate : scalar or array_like of shape(M, )
- Rate of interest as decimal (not per cent) per period
- per : scalar or array_like of shape(M, )
- Interest paid against the loan changes during the life or the loan.
- The `per` is the payment period to calculate the interest amount.
- nper : scalar or array_like of shape(M, )
- Number of compounding periods
- pv : scalar or array_like of shape(M, )
- Present value
- fv : scalar or array_like of shape(M, ), optional
- Future value
- when : {{'begin', 1}, {'end', 0}}, {string, int}, optional
- When payments are due ('begin' (1) or 'end' (0)).
- Defaults to {'end', 0}.
-
- Returns
- -------
- out : ndarray
- Interest portion of payment. If all input is scalar, returns a scalar
- float. If any input is array_like, returns interest payment for each
- input element. If multiple inputs are array_like, they all must have
- the same shape.
-
- See Also
- --------
- ppmt, pmt, pv
-
- Notes
- -----
- The total payment is made up of payment against principal plus interest.
-
- ``pmt = ppmt + ipmt``
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
-
- Examples
- --------
- What is the amortization schedule for a 1 year loan of $2500 at
- 8.24% interest per year compounded monthly?
-
- >>> principal = 2500.00
-
- The 'per' variable represents the periods of the loan. Remember that
- financial equations start the period count at 1!
-
- >>> per = np.arange(1*12) + 1
- >>> ipmt = np.ipmt(0.0824/12, per, 1*12, principal)
- >>> ppmt = np.ppmt(0.0824/12, per, 1*12, principal)
-
- Each element of the sum of the 'ipmt' and 'ppmt' arrays should equal
- 'pmt'.
-
- >>> pmt = np.pmt(0.0824/12, 1*12, principal)
- >>> np.allclose(ipmt + ppmt, pmt)
- True
-
- >>> fmt = '{0:2d} {1:8.2f} {2:8.2f} {3:8.2f}'
- >>> for payment in per:
- ... index = payment - 1
- ... principal = principal + ppmt[index]
- ... print(fmt.format(payment, ppmt[index], ipmt[index], principal))
- 1 -200.58 -17.17 2299.42
- 2 -201.96 -15.79 2097.46
- 3 -203.35 -14.40 1894.11
- 4 -204.74 -13.01 1689.37
- 5 -206.15 -11.60 1483.22
- 6 -207.56 -10.18 1275.66
- 7 -208.99 -8.76 1066.67
- 8 -210.42 -7.32 856.25
- 9 -211.87 -5.88 644.38
- 10 -213.32 -4.42 431.05
- 11 -214.79 -2.96 216.26
- 12 -216.26 -1.49 -0.00
-
- >>> interestpd = np.sum(ipmt)
- >>> np.round(interestpd, 2)
- -112.98
-
- """
- when = _convert_when(when)
- rate, per, nper, pv, fv, when = np.broadcast_arrays(rate, per, nper,
- pv, fv, when)
- total_pmt = pmt(rate, nper, pv, fv, when)
- ipmt = _rbl(rate, per, total_pmt, pv, when)*rate
- try:
- ipmt = np.where(when == 1, ipmt/(1 + rate), ipmt)
- ipmt = np.where(np.logical_and(when == 1, per == 1), 0, ipmt)
- except IndexError:
- pass
- return ipmt
-
-
-def _rbl(rate, per, pmt, pv, when):
- """
- This function is here to simply have a different name for the 'fv'
- function to not interfere with the 'fv' keyword argument within the 'ipmt'
- function. It is the 'remaining balance on loan' which might be useful as
- its own function, but is easily calculated with the 'fv' function.
- """
- return fv(rate, (per - 1), pmt, pv, when)
-
-
-def _ppmt_dispatcher(rate, per, nper, pv, fv=None, when=None):
- warnings.warn(_depmsg.format(name='ppmt'),
- DeprecationWarning, stacklevel=3)
- return (rate, per, nper, pv, fv)
-
-
-@array_function_dispatch(_ppmt_dispatcher)
-def ppmt(rate, per, nper, pv, fv=0, when='end'):
- """
- Compute the payment against loan principal.
-
- .. deprecated:: 1.18
-
- `ppmt` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- Parameters
- ----------
- rate : array_like
- Rate of interest (per period)
- per : array_like, int
- Amount paid against the loan changes. The `per` is the period of
- interest.
- nper : array_like
- Number of compounding periods
- pv : array_like
- Present value
- fv : array_like, optional
- Future value
- when : {{'begin', 1}, {'end', 0}}, {string, int}
- When payments are due ('begin' (1) or 'end' (0))
-
- See Also
- --------
- pmt, pv, ipmt
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
-
- """
- total = pmt(rate, nper, pv, fv, when)
- return total - ipmt(rate, per, nper, pv, fv, when)
-
-
-def _pv_dispatcher(rate, nper, pmt, fv=None, when=None):
- warnings.warn(_depmsg.format(name='pv'),
- DeprecationWarning, stacklevel=3)
- return (rate, nper, nper, pv, fv)
-
-
-@array_function_dispatch(_pv_dispatcher)
-def pv(rate, nper, pmt, fv=0, when='end'):
- """
- Compute the present value.
-
- .. deprecated:: 1.18
-
- `pv` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- Given:
- * a future value, `fv`
- * an interest `rate` compounded once per period, of which
- there are
- * `nper` total
- * a (fixed) payment, `pmt`, paid either
- * at the beginning (`when` = {'begin', 1}) or the end
- (`when` = {'end', 0}) of each period
-
- Return:
- the value now
-
- Parameters
- ----------
- rate : array_like
- Rate of interest (per period)
- nper : array_like
- Number of compounding periods
- pmt : array_like
- Payment
- fv : array_like, optional
- Future value
- when : {{'begin', 1}, {'end', 0}}, {string, int}, optional
- When payments are due ('begin' (1) or 'end' (0))
-
- Returns
- -------
- out : ndarray, float
- Present value of a series of payments or investments.
-
- Notes
- -----
- The present value is computed by solving the equation::
-
- fv +
- pv*(1 + rate)**nper +
- pmt*(1 + rate*when)/rate*((1 + rate)**nper - 1) = 0
-
- or, when ``rate = 0``::
-
- fv + pv + pmt * nper = 0
-
- for `pv`, which is then returned.
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
- .. [2] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
- Open Document Format for Office Applications (OpenDocument)v1.2,
- Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
- Pre-Draft 12. Organization for the Advancement of Structured Information
- Standards (OASIS). Billerica, MA, USA. [ODT Document].
- Available:
- http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formula
- OpenDocument-formula-20090508.odt
-
- Examples
- --------
- What is the present value (e.g., the initial investment)
- of an investment that needs to total $15692.93
- after 10 years of saving $100 every month? Assume the
- interest rate is 5% (annually) compounded monthly.
-
- >>> np.pv(0.05/12, 10*12, -100, 15692.93)
- -100.00067131625819
-
- By convention, the negative sign represents cash flow out
- (i.e., money not available today). Thus, to end up with
- $15,692.93 in 10 years saving $100 a month at 5% annual
- interest, one's initial deposit should also be $100.
-
- If any input is array_like, ``pv`` returns an array of equal shape.
- Let's compare different interest rates in the example above:
-
- >>> a = np.array((0.05, 0.04, 0.03))/12
- >>> np.pv(a, 10*12, -100, 15692.93)
- array([ -100.00067132, -649.26771385, -1273.78633713]) # may vary
-
- So, to end up with the same $15692.93 under the same $100 per month
- "savings plan," for annual interest rates of 4% and 3%, one would
- need initial investments of $649.27 and $1273.79, respectively.
-
- """
- when = _convert_when(when)
- (rate, nper, pmt, fv, when) = map(np.asarray, [rate, nper, pmt, fv, when])
- temp = (1+rate)**nper
- fact = np.where(rate == 0, nper, (1+rate*when)*(temp-1)/rate)
- return -(fv + pmt*fact)/temp
-
-# Computed with Sage
-# (y + (r + 1)^n*x + p*((r + 1)^n - 1)*(r*w + 1)/r)/(n*(r + 1)^(n - 1)*x -
-# p*((r + 1)^n - 1)*(r*w + 1)/r^2 + n*p*(r + 1)^(n - 1)*(r*w + 1)/r +
-# p*((r + 1)^n - 1)*w/r)
-
-def _g_div_gp(r, n, p, x, y, w):
- t1 = (r+1)**n
- t2 = (r+1)**(n-1)
- return ((y + t1*x + p*(t1 - 1)*(r*w + 1)/r) /
- (n*t2*x - p*(t1 - 1)*(r*w + 1)/(r**2) + n*p*t2*(r*w + 1)/r +
- p*(t1 - 1)*w/r))
-
-
-def _rate_dispatcher(nper, pmt, pv, fv, when=None, guess=None, tol=None,
- maxiter=None):
- warnings.warn(_depmsg.format(name='rate'),
- DeprecationWarning, stacklevel=3)
- return (nper, pmt, pv, fv)
-
-
-# Use Newton's iteration until the change is less than 1e-6
-# for all values or a maximum of 100 iterations is reached.
-# Newton's rule is
-# r_{n+1} = r_{n} - g(r_n)/g'(r_n)
-# where
-# g(r) is the formula
-# g'(r) is the derivative with respect to r.
-@array_function_dispatch(_rate_dispatcher)
-def rate(nper, pmt, pv, fv, when='end', guess=None, tol=None, maxiter=100):
- """
- Compute the rate of interest per period.
-
- .. deprecated:: 1.18
-
- `rate` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- Parameters
- ----------
- nper : array_like
- Number of compounding periods
- pmt : array_like
- Payment
- pv : array_like
- Present value
- fv : array_like
- Future value
- when : {{'begin', 1}, {'end', 0}}, {string, int}, optional
- When payments are due ('begin' (1) or 'end' (0))
- guess : Number, optional
- Starting guess for solving the rate of interest, default 0.1
- tol : Number, optional
- Required tolerance for the solution, default 1e-6
- maxiter : int, optional
- Maximum iterations in finding the solution
-
- Notes
- -----
- The rate of interest is computed by iteratively solving the
- (non-linear) equation::
-
- fv + pv*(1+rate)**nper + pmt*(1+rate*when)/rate * ((1+rate)**nper - 1) = 0
-
- for ``rate``.
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
- .. [2] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
- Open Document Format for Office Applications (OpenDocument)v1.2,
- Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
- Pre-Draft 12. Organization for the Advancement of Structured Information
- Standards (OASIS). Billerica, MA, USA. [ODT Document].
- Available:
- http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formula
- OpenDocument-formula-20090508.odt
-
- """
- when = _convert_when(when)
- default_type = Decimal if isinstance(pmt, Decimal) else float
-
- # Handle casting defaults to Decimal if/when pmt is a Decimal and
- # guess and/or tol are not given default values
- if guess is None:
- guess = default_type('0.1')
-
- if tol is None:
- tol = default_type('1e-6')
-
- (nper, pmt, pv, fv, when) = map(np.asarray, [nper, pmt, pv, fv, when])
-
- rn = guess
- iterator = 0
- close = False
- while (iterator < maxiter) and not close:
- rnp1 = rn - _g_div_gp(rn, nper, pmt, pv, fv, when)
- diff = abs(rnp1-rn)
- close = np.all(diff < tol)
- iterator += 1
- rn = rnp1
- if not close:
- # Return nan's in array of the same shape as rn
- return np.nan + rn
- else:
- return rn
-
-
-def _irr_dispatcher(values):
- warnings.warn(_depmsg.format(name='irr'),
- DeprecationWarning, stacklevel=3)
- return (values,)
-
-
-@array_function_dispatch(_irr_dispatcher)
-def irr(values):
- """
- Return the Internal Rate of Return (IRR).
-
- .. deprecated:: 1.18
-
- `irr` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- This is the "average" periodically compounded rate of return
- that gives a net present value of 0.0; for a more complete explanation,
- see Notes below.
-
- :class:`decimal.Decimal` type is not supported.
-
- Parameters
- ----------
- values : array_like, shape(N,)
- Input cash flows per time period. By convention, net "deposits"
- are negative and net "withdrawals" are positive. Thus, for
- example, at least the first element of `values`, which represents
- the initial investment, will typically be negative.
-
- Returns
- -------
- out : float
- Internal Rate of Return for periodic input values.
-
- Notes
- -----
- The IRR is perhaps best understood through an example (illustrated
- using np.irr in the Examples section below). Suppose one invests 100
- units and then makes the following withdrawals at regular (fixed)
- intervals: 39, 59, 55, 20. Assuming the ending value is 0, one's 100
- unit investment yields 173 units; however, due to the combination of
- compounding and the periodic withdrawals, the "average" rate of return
- is neither simply 0.73/4 nor (1.73)^0.25-1. Rather, it is the solution
- (for :math:`r`) of the equation:
-
- .. math:: -100 + \\frac{39}{1+r} + \\frac{59}{(1+r)^2}
- + \\frac{55}{(1+r)^3} + \\frac{20}{(1+r)^4} = 0
-
- In general, for `values` :math:`= [v_0, v_1, ... v_M]`,
- irr is the solution of the equation: [2]_
-
- .. math:: \\sum_{t=0}^M{\\frac{v_t}{(1+irr)^{t}}} = 0
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
- .. [2] L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed.,
- Addison-Wesley, 2003, pg. 348.
-
- Examples
- --------
- >>> round(np.irr([-100, 39, 59, 55, 20]), 5)
- 0.28095
- >>> round(np.irr([-100, 0, 0, 74]), 5)
- -0.0955
- >>> round(np.irr([-100, 100, 0, -7]), 5)
- -0.0833
- >>> round(np.irr([-100, 100, 0, 7]), 5)
- 0.06206
- >>> round(np.irr([-5, 10.5, 1, -8, 1]), 5)
- 0.0886
-
- """
- # `np.roots` call is why this function does not support Decimal type.
- #
- # Ultimately Decimal support needs to be added to np.roots, which has
- # greater implications on the entire linear algebra module and how it does
- # eigenvalue computations.
- res = np.roots(values[::-1])
- mask = (res.imag == 0) & (res.real > 0)
- if not mask.any():
- return np.nan
- res = res[mask].real
- # NPV(rate) = 0 can have more than one solution so we return
- # only the solution closest to zero.
- rate = 1/res - 1
- rate = rate.item(np.argmin(np.abs(rate)))
- return rate
-
-
-def _npv_dispatcher(rate, values):
- warnings.warn(_depmsg.format(name='npv'),
- DeprecationWarning, stacklevel=3)
- return (values,)
-
-
-@array_function_dispatch(_npv_dispatcher)
-def npv(rate, values):
- """
- Returns the NPV (Net Present Value) of a cash flow series.
-
- .. deprecated:: 1.18
-
- `npv` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- Parameters
- ----------
- rate : scalar
- The discount rate.
- values : array_like, shape(M, )
- The values of the time series of cash flows. The (fixed) time
- interval between cash flow "events" must be the same as that for
- which `rate` is given (i.e., if `rate` is per year, then precisely
- a year is understood to elapse between each cash flow event). By
- convention, investments or "deposits" are negative, income or
- "withdrawals" are positive; `values` must begin with the initial
- investment, thus `values[0]` will typically be negative.
-
- Returns
- -------
- out : float
- The NPV of the input cash flow series `values` at the discount
- `rate`.
-
- Warnings
- --------
- ``npv`` considers a series of cashflows starting in the present (t = 0).
- NPV can also be defined with a series of future cashflows, paid at the
- end, rather than the start, of each period. If future cashflows are used,
- the first cashflow `values[0]` must be zeroed and added to the net
- present value of the future cashflows. This is demonstrated in the
- examples.
-
- Notes
- -----
- Returns the result of: [2]_
-
- .. math :: \\sum_{t=0}^{M-1}{\\frac{values_t}{(1+rate)^{t}}}
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
- .. [2] L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed.,
- Addison-Wesley, 2003, pg. 346.
-
- Examples
- --------
- Consider a potential project with an initial investment of $40 000 and
- projected cashflows of $5 000, $8 000, $12 000 and $30 000 at the end of
- each period discounted at a rate of 8% per period. To find the project's
- net present value:
-
- >>> rate, cashflows = 0.08, [-40_000, 5_000, 8_000, 12_000, 30_000]
- >>> np.npv(rate, cashflows).round(5)
- 3065.22267
-
- It may be preferable to split the projected cashflow into an initial
- investment and expected future cashflows. In this case, the value of
- the initial cashflow is zero and the initial investment is later added
- to the future cashflows net present value:
-
- >>> initial_cashflow = cashflows[0]
- >>> cashflows[0] = 0
- >>> np.round(np.npv(rate, cashflows) + initial_cashflow, 5)
- 3065.22267
-
- """
- values = np.asarray(values)
- return (values / (1+rate)**np.arange(0, len(values))).sum(axis=0)
-
-
-def _mirr_dispatcher(values, finance_rate, reinvest_rate):
- warnings.warn(_depmsg.format(name='mirr'),
- DeprecationWarning, stacklevel=3)
- return (values,)
-
-
-@array_function_dispatch(_mirr_dispatcher)
-def mirr(values, finance_rate, reinvest_rate):
- """
- Modified internal rate of return.
-
- .. deprecated:: 1.18
-
- `mirr` is deprecated; for details, see NEP 32 [1]_.
- Use the corresponding function in the numpy-financial library,
- https://pypi.org/project/numpy-financial.
-
- Parameters
- ----------
- values : array_like
- Cash flows (must contain at least one positive and one negative
- value) or nan is returned. The first value is considered a sunk
- cost at time zero.
- finance_rate : scalar
- Interest rate paid on the cash flows
- reinvest_rate : scalar
- Interest rate received on the cash flows upon reinvestment
-
- Returns
- -------
- out : float
- Modified internal rate of return
-
- References
- ----------
- .. [1] NumPy Enhancement Proposal (NEP) 32,
- https://numpy.org/neps/nep-0032-remove-financial-functions.html
- """
- values = np.asarray(values)
- n = values.size
-
- # Without this explicit cast the 1/(n - 1) computation below
- # becomes a float, which causes TypeError when using Decimal
- # values.
- if isinstance(finance_rate, Decimal):
- n = Decimal(n)
-
- pos = values > 0
- neg = values < 0
- if not (pos.any() and neg.any()):
- return np.nan
- numer = np.abs(npv(reinvest_rate, values*pos))
- denom = np.abs(npv(finance_rate, values*neg))
- return (numer/denom)**(1/(n - 1))*(1 + reinvest_rate) - 1
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index cd8862c94..556227c0d 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -1631,21 +1631,27 @@ def trim_zeros(filt, trim='fb'):
# Numpy 1.20.0, 2020-07-31
warning = DeprecationWarning(
"in the future trim_zeros will require a 1-D array as input "
- "that is compatible with ndarray.astype(bool)"
+ "that supports elementwise comparisons with zero"
)
warning.__cause__ = ex
- warnings.warn(warning, stacklevel=3)
- # Fall back to the old implementation if an exception is encountered
- # Note that the same exception may or may not be raised here as well
- return _trim_zeros_old(filt, trim)
+ # Fall back to the old implementation if an exception is encountered
+ # Note that the same exception may or may not be raised here as well
+ ret = _trim_zeros_old(filt, trim)
+ warnings.warn(warning, stacklevel=3)
+ return ret
def _trim_zeros_new(filt, trim='fb'):
"""Newer optimized implementation of ``trim_zeros()``."""
- arr = np.asanyarray(filt).astype(bool, copy=False)
-
- if arr.ndim != 1:
+ arr_any = np.asanyarray(filt)
+ arr = arr_any != 0 if arr_any.dtype != bool else arr_any
+
+ if arr is False:
+ # not all dtypes support elementwise comparisons with `0` (e.g. str);
+ # they will return `False` instead
+ raise TypeError('elementwise comparison failed; unsupported data type')
+ elif arr.ndim != 1:
raise ValueError('trim_zeros requires an array of exactly one dimension')
elif not len(arr):
return filt
@@ -3193,25 +3199,18 @@ def i0(x):
"""
Modified Bessel function of the first kind, order 0.
- Usually denoted :math:`I_0`. This function does broadcast, but will *not*
- "up-cast" int dtype arguments unless accompanied by at least one float or
- complex dtype argument (see Raises below).
+ Usually denoted :math:`I_0`.
Parameters
----------
- x : array_like, dtype float or complex
+ x : array_like of float
Argument of the Bessel function.
Returns
-------
- out : ndarray, shape = x.shape, dtype = x.dtype
+ out : ndarray, shape = x.shape, dtype = float
The modified Bessel function evaluated at each of the elements of `x`.
- Raises
- ------
- TypeError: array cannot be safely cast to required type
- If argument consists exclusively of int dtypes.
-
See Also
--------
scipy.special.i0, scipy.special.iv, scipy.special.ive
@@ -3241,12 +3240,16 @@ def i0(x):
Examples
--------
>>> np.i0(0.)
- array(1.0) # may vary
- >>> np.i0([0., 1. + 2j])
- array([ 1.00000000+0.j , 0.18785373+0.64616944j]) # may vary
+ array(1.0)
+ >>> np.i0([0, 1, 2, 3])
+ array([1. , 1.26606588, 2.2795853 , 4.88079259])
"""
x = np.asanyarray(x)
+ if x.dtype.kind == 'c':
+ raise TypeError("i0 not supported for complex values")
+ if x.dtype.kind != 'f':
+ x = x.astype(float)
x = np.abs(x)
return piecewise(x, [x <= 8.0], [_i0_1, _i0_2])
diff --git a/numpy/lib/polynomial.py b/numpy/lib/polynomial.py
index 1c124cc0e..7b89eeb70 100644
--- a/numpy/lib/polynomial.py
+++ b/numpy/lib/polynomial.py
@@ -1017,7 +1017,7 @@ def polydiv(u, v):
(array([1.5 , 1.75]), array([0.25]))
"""
- truepoly = (isinstance(u, poly1d) or isinstance(u, poly1d))
+ truepoly = (isinstance(u, poly1d) or isinstance(v, poly1d))
u = atleast_1d(u) + 0.0
v = atleast_1d(v) + 0.0
# w has the common type
diff --git a/numpy/lib/tests/test_financial.py b/numpy/lib/tests/test_financial.py
deleted file mode 100644
index 26e79bc06..000000000
--- a/numpy/lib/tests/test_financial.py
+++ /dev/null
@@ -1,380 +0,0 @@
-import warnings
-from decimal import Decimal
-
-import numpy as np
-from numpy.testing import (
- assert_, assert_almost_equal, assert_allclose, assert_equal, assert_raises
- )
-
-
-def filter_deprecation(func):
- def newfunc(*args, **kwargs):
- with warnings.catch_warnings(record=True) as ws:
- warnings.filterwarnings('always', category=DeprecationWarning)
- func(*args, **kwargs)
- assert_(all(w.category is DeprecationWarning for w in ws))
- return newfunc
-
-
-class TestFinancial:
- @filter_deprecation
- def test_npv_irr_congruence(self):
- # IRR is defined as the rate required for the present value of a
- # a series of cashflows to be zero i.e. NPV(IRR(x), x) = 0
- cashflows = np.array([-40000, 5000, 8000, 12000, 30000])
- assert_allclose(np.npv(np.irr(cashflows), cashflows), 0, atol=1e-10, rtol=0)
-
- @filter_deprecation
- def test_rate(self):
- assert_almost_equal(
- np.rate(10, 0, -3500, 10000),
- 0.1107, 4)
-
- @filter_deprecation
- def test_rate_decimal(self):
- rate = np.rate(Decimal('10'), Decimal('0'), Decimal('-3500'), Decimal('10000'))
- assert_equal(Decimal('0.1106908537142689284704528100'), rate)
-
- @filter_deprecation
- def test_irr(self):
- v = [-150000, 15000, 25000, 35000, 45000, 60000]
- assert_almost_equal(np.irr(v), 0.0524, 2)
- v = [-100, 0, 0, 74]
- assert_almost_equal(np.irr(v), -0.0955, 2)
- v = [-100, 39, 59, 55, 20]
- assert_almost_equal(np.irr(v), 0.28095, 2)
- v = [-100, 100, 0, -7]
- assert_almost_equal(np.irr(v), -0.0833, 2)
- v = [-100, 100, 0, 7]
- assert_almost_equal(np.irr(v), 0.06206, 2)
- v = [-5, 10.5, 1, -8, 1]
- assert_almost_equal(np.irr(v), 0.0886, 2)
-
- # Test that if there is no solution then np.irr returns nan
- # Fixes gh-6744
- v = [-1, -2, -3]
- assert_equal(np.irr(v), np.nan)
-
- @filter_deprecation
- def test_pv(self):
- assert_almost_equal(np.pv(0.07, 20, 12000, 0), -127128.17, 2)
-
- @filter_deprecation
- def test_pv_decimal(self):
- assert_equal(np.pv(Decimal('0.07'), Decimal('20'), Decimal('12000'), Decimal('0')),
- Decimal('-127128.1709461939327295222005'))
-
- @filter_deprecation
- def test_fv(self):
- assert_equal(np.fv(0.075, 20, -2000, 0, 0), 86609.362673042924)
-
- @filter_deprecation
- def test_fv_decimal(self):
- assert_equal(np.fv(Decimal('0.075'), Decimal('20'), Decimal('-2000'), 0, 0),
- Decimal('86609.36267304300040536731624'))
-
- @filter_deprecation
- def test_pmt(self):
- res = np.pmt(0.08 / 12, 5 * 12, 15000)
- tgt = -304.145914
- assert_allclose(res, tgt)
- # Test the edge case where rate == 0.0
- res = np.pmt(0.0, 5 * 12, 15000)
- tgt = -250.0
- assert_allclose(res, tgt)
- # Test the case where we use broadcast and
- # the arguments passed in are arrays.
- res = np.pmt([[0.0, 0.8], [0.3, 0.8]], [12, 3], [2000, 20000])
- tgt = np.array([[-166.66667, -19311.258], [-626.90814, -19311.258]])
- assert_allclose(res, tgt)
-
- @filter_deprecation
- def test_pmt_decimal(self):
- res = np.pmt(Decimal('0.08') / Decimal('12'), 5 * 12, 15000)
- tgt = Decimal('-304.1459143262052370338701494')
- assert_equal(res, tgt)
- # Test the edge case where rate == 0.0
- res = np.pmt(Decimal('0'), Decimal('60'), Decimal('15000'))
- tgt = -250
- assert_equal(res, tgt)
- # Test the case where we use broadcast and
- # the arguments passed in are arrays.
- res = np.pmt([[Decimal('0'), Decimal('0.8')], [Decimal('0.3'), Decimal('0.8')]],
- [Decimal('12'), Decimal('3')], [Decimal('2000'), Decimal('20000')])
- tgt = np.array([[Decimal('-166.6666666666666666666666667'), Decimal('-19311.25827814569536423841060')],
- [Decimal('-626.9081401700757748402586600'), Decimal('-19311.25827814569536423841060')]])
-
- # Cannot use the `assert_allclose` because it uses isfinite under the covers
- # which does not support the Decimal type
- # See issue: https://github.com/numpy/numpy/issues/9954
- assert_equal(res[0][0], tgt[0][0])
- assert_equal(res[0][1], tgt[0][1])
- assert_equal(res[1][0], tgt[1][0])
- assert_equal(res[1][1], tgt[1][1])
-
- @filter_deprecation
- def test_ppmt(self):
- assert_equal(np.round(np.ppmt(0.1 / 12, 1, 60, 55000), 2), -710.25)
-
- @filter_deprecation
- def test_ppmt_decimal(self):
- assert_equal(np.ppmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('60'), Decimal('55000')),
- Decimal('-710.2541257864217612489830917'))
-
- # Two tests showing how Decimal is actually getting at a more exact result
- # .23 / 12 does not come out nicely as a float but does as a decimal
- @filter_deprecation
- def test_ppmt_special_rate(self):
- assert_equal(np.round(np.ppmt(0.23 / 12, 1, 60, 10000000000), 8), -90238044.232277036)
-
- @filter_deprecation
- def test_ppmt_special_rate_decimal(self):
- # When rounded out to 8 decimal places like the float based test, this should not equal the same value
- # as the float, substituted for the decimal
- def raise_error_because_not_equal():
- assert_equal(
- round(np.ppmt(Decimal('0.23') / Decimal('12'), 1, 60, Decimal('10000000000')), 8),
- Decimal('-90238044.232277036'))
-
- assert_raises(AssertionError, raise_error_because_not_equal)
- assert_equal(np.ppmt(Decimal('0.23') / Decimal('12'), 1, 60, Decimal('10000000000')),
- Decimal('-90238044.2322778884413969909'))
-
- @filter_deprecation
- def test_ipmt(self):
- assert_almost_equal(np.round(np.ipmt(0.1 / 12, 1, 24, 2000), 2), -16.67)
-
- @filter_deprecation
- def test_ipmt_decimal(self):
- result = np.ipmt(Decimal('0.1') / Decimal('12'), 1, 24, 2000)
- assert_equal(result.flat[0], Decimal('-16.66666666666666666666666667'))
-
- @filter_deprecation
- def test_nper(self):
- assert_almost_equal(np.nper(0.075, -2000, 0, 100000.),
- 21.54, 2)
-
- @filter_deprecation
- def test_nper2(self):
- assert_almost_equal(np.nper(0.0, -2000, 0, 100000.),
- 50.0, 1)
-
- @filter_deprecation
- def test_npv(self):
- assert_almost_equal(
- np.npv(0.05, [-15000, 1500, 2500, 3500, 4500, 6000]),
- 122.89, 2)
-
- @filter_deprecation
- def test_npv_decimal(self):
- assert_equal(
- np.npv(Decimal('0.05'), [-15000, 1500, 2500, 3500, 4500, 6000]),
- Decimal('122.894854950942692161628715'))
-
- @filter_deprecation
- def test_mirr(self):
- val = [-4500, -800, 800, 800, 600, 600, 800, 800, 700, 3000]
- assert_almost_equal(np.mirr(val, 0.08, 0.055), 0.0666, 4)
-
- val = [-120000, 39000, 30000, 21000, 37000, 46000]
- assert_almost_equal(np.mirr(val, 0.10, 0.12), 0.126094, 6)
-
- val = [100, 200, -50, 300, -200]
- assert_almost_equal(np.mirr(val, 0.05, 0.06), 0.3428, 4)
-
- val = [39000, 30000, 21000, 37000, 46000]
- assert_(np.isnan(np.mirr(val, 0.10, 0.12)))
-
- @filter_deprecation
- def test_mirr_decimal(self):
- val = [Decimal('-4500'), Decimal('-800'), Decimal('800'), Decimal('800'),
- Decimal('600'), Decimal('600'), Decimal('800'), Decimal('800'),
- Decimal('700'), Decimal('3000')]
- assert_equal(np.mirr(val, Decimal('0.08'), Decimal('0.055')),
- Decimal('0.066597175031553548874239618'))
-
- val = [Decimal('-120000'), Decimal('39000'), Decimal('30000'),
- Decimal('21000'), Decimal('37000'), Decimal('46000')]
- assert_equal(np.mirr(val, Decimal('0.10'), Decimal('0.12')), Decimal('0.126094130365905145828421880'))
-
- val = [Decimal('100'), Decimal('200'), Decimal('-50'),
- Decimal('300'), Decimal('-200')]
- assert_equal(np.mirr(val, Decimal('0.05'), Decimal('0.06')), Decimal('0.342823387842176663647819868'))
-
- val = [Decimal('39000'), Decimal('30000'), Decimal('21000'), Decimal('37000'), Decimal('46000')]
- assert_(np.isnan(np.mirr(val, Decimal('0.10'), Decimal('0.12'))))
-
- @filter_deprecation
- def test_when(self):
- # begin
- assert_equal(np.rate(10, 20, -3500, 10000, 1),
- np.rate(10, 20, -3500, 10000, 'begin'))
- # end
- assert_equal(np.rate(10, 20, -3500, 10000),
- np.rate(10, 20, -3500, 10000, 'end'))
- assert_equal(np.rate(10, 20, -3500, 10000, 0),
- np.rate(10, 20, -3500, 10000, 'end'))
-
- # begin
- assert_equal(np.pv(0.07, 20, 12000, 0, 1),
- np.pv(0.07, 20, 12000, 0, 'begin'))
- # end
- assert_equal(np.pv(0.07, 20, 12000, 0),
- np.pv(0.07, 20, 12000, 0, 'end'))
- assert_equal(np.pv(0.07, 20, 12000, 0, 0),
- np.pv(0.07, 20, 12000, 0, 'end'))
-
- # begin
- assert_equal(np.fv(0.075, 20, -2000, 0, 1),
- np.fv(0.075, 20, -2000, 0, 'begin'))
- # end
- assert_equal(np.fv(0.075, 20, -2000, 0),
- np.fv(0.075, 20, -2000, 0, 'end'))
- assert_equal(np.fv(0.075, 20, -2000, 0, 0),
- np.fv(0.075, 20, -2000, 0, 'end'))
-
- # begin
- assert_equal(np.pmt(0.08 / 12, 5 * 12, 15000., 0, 1),
- np.pmt(0.08 / 12, 5 * 12, 15000., 0, 'begin'))
- # end
- assert_equal(np.pmt(0.08 / 12, 5 * 12, 15000., 0),
- np.pmt(0.08 / 12, 5 * 12, 15000., 0, 'end'))
- assert_equal(np.pmt(0.08 / 12, 5 * 12, 15000., 0, 0),
- np.pmt(0.08 / 12, 5 * 12, 15000., 0, 'end'))
-
- # begin
- assert_equal(np.ppmt(0.1 / 12, 1, 60, 55000, 0, 1),
- np.ppmt(0.1 / 12, 1, 60, 55000, 0, 'begin'))
- # end
- assert_equal(np.ppmt(0.1 / 12, 1, 60, 55000, 0),
- np.ppmt(0.1 / 12, 1, 60, 55000, 0, 'end'))
- assert_equal(np.ppmt(0.1 / 12, 1, 60, 55000, 0, 0),
- np.ppmt(0.1 / 12, 1, 60, 55000, 0, 'end'))
-
- # begin
- assert_equal(np.ipmt(0.1 / 12, 1, 24, 2000, 0, 1),
- np.ipmt(0.1 / 12, 1, 24, 2000, 0, 'begin'))
- # end
- assert_equal(np.ipmt(0.1 / 12, 1, 24, 2000, 0),
- np.ipmt(0.1 / 12, 1, 24, 2000, 0, 'end'))
- assert_equal(np.ipmt(0.1 / 12, 1, 24, 2000, 0, 0),
- np.ipmt(0.1 / 12, 1, 24, 2000, 0, 'end'))
-
- # begin
- assert_equal(np.nper(0.075, -2000, 0, 100000., 1),
- np.nper(0.075, -2000, 0, 100000., 'begin'))
- # end
- assert_equal(np.nper(0.075, -2000, 0, 100000.),
- np.nper(0.075, -2000, 0, 100000., 'end'))
- assert_equal(np.nper(0.075, -2000, 0, 100000., 0),
- np.nper(0.075, -2000, 0, 100000., 'end'))
-
- @filter_deprecation
- def test_decimal_with_when(self):
- """Test that decimals are still supported if the when argument is passed"""
- # begin
- assert_equal(np.rate(Decimal('10'), Decimal('20'), Decimal('-3500'), Decimal('10000'), Decimal('1')),
- np.rate(Decimal('10'), Decimal('20'), Decimal('-3500'), Decimal('10000'), 'begin'))
- # end
- assert_equal(np.rate(Decimal('10'), Decimal('20'), Decimal('-3500'), Decimal('10000')),
- np.rate(Decimal('10'), Decimal('20'), Decimal('-3500'), Decimal('10000'), 'end'))
- assert_equal(np.rate(Decimal('10'), Decimal('20'), Decimal('-3500'), Decimal('10000'), Decimal('0')),
- np.rate(Decimal('10'), Decimal('20'), Decimal('-3500'), Decimal('10000'), 'end'))
-
- # begin
- assert_equal(np.pv(Decimal('0.07'), Decimal('20'), Decimal('12000'), Decimal('0'), Decimal('1')),
- np.pv(Decimal('0.07'), Decimal('20'), Decimal('12000'), Decimal('0'), 'begin'))
- # end
- assert_equal(np.pv(Decimal('0.07'), Decimal('20'), Decimal('12000'), Decimal('0')),
- np.pv(Decimal('0.07'), Decimal('20'), Decimal('12000'), Decimal('0'), 'end'))
- assert_equal(np.pv(Decimal('0.07'), Decimal('20'), Decimal('12000'), Decimal('0'), Decimal('0')),
- np.pv(Decimal('0.07'), Decimal('20'), Decimal('12000'), Decimal('0'), 'end'))
-
- # begin
- assert_equal(np.fv(Decimal('0.075'), Decimal('20'), Decimal('-2000'), Decimal('0'), Decimal('1')),
- np.fv(Decimal('0.075'), Decimal('20'), Decimal('-2000'), Decimal('0'), 'begin'))
- # end
- assert_equal(np.fv(Decimal('0.075'), Decimal('20'), Decimal('-2000'), Decimal('0')),
- np.fv(Decimal('0.075'), Decimal('20'), Decimal('-2000'), Decimal('0'), 'end'))
- assert_equal(np.fv(Decimal('0.075'), Decimal('20'), Decimal('-2000'), Decimal('0'), Decimal('0')),
- np.fv(Decimal('0.075'), Decimal('20'), Decimal('-2000'), Decimal('0'), 'end'))
-
- # begin
- assert_equal(np.pmt(Decimal('0.08') / Decimal('12'), Decimal('5') * Decimal('12'), Decimal('15000.'),
- Decimal('0'), Decimal('1')),
- np.pmt(Decimal('0.08') / Decimal('12'), Decimal('5') * Decimal('12'), Decimal('15000.'),
- Decimal('0'), 'begin'))
- # end
- assert_equal(np.pmt(Decimal('0.08') / Decimal('12'), Decimal('5') * Decimal('12'), Decimal('15000.'),
- Decimal('0')),
- np.pmt(Decimal('0.08') / Decimal('12'), Decimal('5') * Decimal('12'), Decimal('15000.'),
- Decimal('0'), 'end'))
- assert_equal(np.pmt(Decimal('0.08') / Decimal('12'), Decimal('5') * Decimal('12'), Decimal('15000.'),
- Decimal('0'), Decimal('0')),
- np.pmt(Decimal('0.08') / Decimal('12'), Decimal('5') * Decimal('12'), Decimal('15000.'),
- Decimal('0'), 'end'))
-
- # begin
- assert_equal(np.ppmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('60'), Decimal('55000'),
- Decimal('0'), Decimal('1')),
- np.ppmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('60'), Decimal('55000'),
- Decimal('0'), 'begin'))
- # end
- assert_equal(np.ppmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('60'), Decimal('55000'),
- Decimal('0')),
- np.ppmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('60'), Decimal('55000'),
- Decimal('0'), 'end'))
- assert_equal(np.ppmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('60'), Decimal('55000'),
- Decimal('0'), Decimal('0')),
- np.ppmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('60'), Decimal('55000'),
- Decimal('0'), 'end'))
-
- # begin
- assert_equal(np.ipmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('24'), Decimal('2000'),
- Decimal('0'), Decimal('1')).flat[0],
- np.ipmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('24'), Decimal('2000'),
- Decimal('0'), 'begin').flat[0])
- # end
- assert_equal(np.ipmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('24'), Decimal('2000'),
- Decimal('0')).flat[0],
- np.ipmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('24'), Decimal('2000'),
- Decimal('0'), 'end').flat[0])
- assert_equal(np.ipmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('24'), Decimal('2000'),
- Decimal('0'), Decimal('0')).flat[0],
- np.ipmt(Decimal('0.1') / Decimal('12'), Decimal('1'), Decimal('24'), Decimal('2000'),
- Decimal('0'), 'end').flat[0])
-
- @filter_deprecation
- def test_broadcast(self):
- assert_almost_equal(np.nper(0.075, -2000, 0, 100000., [0, 1]),
- [21.5449442, 20.76156441], 4)
-
- assert_almost_equal(np.ipmt(0.1 / 12, list(range(5)), 24, 2000),
- [-17.29165168, -16.66666667, -16.03647345,
- -15.40102862, -14.76028842], 4)
-
- assert_almost_equal(np.ppmt(0.1 / 12, list(range(5)), 24, 2000),
- [-74.998201, -75.62318601, -76.25337923,
- -76.88882405, -77.52956425], 4)
-
- assert_almost_equal(np.ppmt(0.1 / 12, list(range(5)), 24, 2000, 0,
- [0, 0, 1, 'end', 'begin']),
- [-74.998201, -75.62318601, -75.62318601,
- -76.88882405, -76.88882405], 4)
-
- @filter_deprecation
- def test_broadcast_decimal(self):
- # Use almost equal because precision is tested in the explicit tests, this test is to ensure
- # broadcast with Decimal is not broken.
- assert_almost_equal(np.ipmt(Decimal('0.1') / Decimal('12'), list(range(5)), Decimal('24'), Decimal('2000')),
- [Decimal('-17.29165168'), Decimal('-16.66666667'), Decimal('-16.03647345'),
- Decimal('-15.40102862'), Decimal('-14.76028842')], 4)
-
- assert_almost_equal(np.ppmt(Decimal('0.1') / Decimal('12'), list(range(5)), Decimal('24'), Decimal('2000')),
- [Decimal('-74.998201'), Decimal('-75.62318601'), Decimal('-76.25337923'),
- Decimal('-76.88882405'), Decimal('-77.52956425')], 4)
-
- assert_almost_equal(np.ppmt(Decimal('0.1') / Decimal('12'), list(range(5)), Decimal('24'), Decimal('2000'),
- Decimal('0'), [Decimal('0'), Decimal('0'), Decimal('1'), 'end', 'begin']),
- [Decimal('-74.998201'), Decimal('-75.62318601'), Decimal('-75.62318601'),
- Decimal('-76.88882405'), Decimal('-76.88882405')], 4)
diff --git a/numpy/lib/tests/test_financial_expired.py b/numpy/lib/tests/test_financial_expired.py
new file mode 100644
index 000000000..e1d05da0c
--- /dev/null
+++ b/numpy/lib/tests/test_financial_expired.py
@@ -0,0 +1,12 @@
+import sys
+import pytest
+import numpy as np
+
+
+def test_financial_expired():
+ if sys.version_info[:2] >= (3, 7):
+ match = 'NEP 32'
+ else:
+ match = None
+ with pytest.raises(AttributeError, match=match):
+ np.fv
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index 89c1a2d9b..34a395ee4 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -1169,7 +1169,7 @@ class TestTrimZeros:
a = np.array([0, 0, 1, 0, 2, 3, 4, 0])
b = a.astype(float)
c = a.astype(complex)
- d = np.array([None, [], 1, False, 'b', 3.0, range(4), b''], dtype=object)
+ d = a.astype(object)
def values(self):
attr_names = ('a', 'b', 'c', 'd')
@@ -1208,6 +1208,22 @@ class TestTrimZeros:
res = trim_zeros(arr)
assert_array_equal(arr, res)
+ @pytest.mark.parametrize(
+ 'arr',
+ [np.array([0, 2**62, 0]),
+ np.array([0, 2**63, 0]),
+ np.array([0, 2**64, 0])]
+ )
+ def test_overflow(self, arr):
+ slc = np.s_[1:2]
+ res = trim_zeros(arr)
+ assert_array_equal(res, arr[slc])
+
+ def test_no_trim(self):
+ arr = np.array([None, 1, None])
+ res = trim_zeros(arr)
+ assert_array_equal(arr, res)
+
class TestExtins:
@@ -2111,8 +2127,9 @@ class Test_I0:
i0(0.5),
np.array(1.0634833707413234))
- A = np.array([0.49842636, 0.6969809, 0.22011976, 0.0155549])
- expected = np.array([1.06307822, 1.12518299, 1.01214991, 1.00006049])
+ # need at least one test above 8, as the implementation is piecewise
+ A = np.array([0.49842636, 0.6969809, 0.22011976, 0.0155549, 10.0])
+ expected = np.array([1.06307822, 1.12518299, 1.01214991, 1.00006049, 2815.71662847])
assert_almost_equal(i0(A), expected)
assert_almost_equal(i0(-A), expected)
@@ -2149,6 +2166,10 @@ class Test_I0:
assert_array_equal(exp, res)
+ def test_complex(self):
+ a = np.array([0, 1 + 2j])
+ with pytest.raises(TypeError, match="i0 not supported for complex values"):
+ res = i0(a)
class TestKaiser:
diff --git a/numpy/lib/tests/test_polynomial.py b/numpy/lib/tests/test_polynomial.py
index cd0b90dc4..ab6691b43 100644
--- a/numpy/lib/tests/test_polynomial.py
+++ b/numpy/lib/tests/test_polynomial.py
@@ -243,6 +243,15 @@ class TestPolynomial:
assert_equal(q.coeffs.dtype, np.complex128)
assert_equal(r.coeffs.dtype, np.complex128)
assert_equal(q*a + r, b)
+
+ c = [1, 2, 3]
+ d = np.poly1d([1, 2, 3])
+ s, t = np.polydiv(c, d)
+ assert isinstance(s, np.poly1d)
+ assert isinstance(t, np.poly1d)
+ u, v = np.polydiv(d, c)
+ assert isinstance(u, np.poly1d)
+ assert isinstance(v, np.poly1d)
def test_poly_coeffs_mutable(self):
""" Coefficients should be modifiable """