Problem: StableVectorizedMonthlyLoanPaymentCalculation

The problem requires developing a Python function to calculate monthly equal-installment loan payments, incorporating numerical stability (log1p for (1+r)^n, Taylor expansion for small rates), vectorization, input validation, sensitivity analysis, adaptive precision, support for scalar/array inputs, and preservation of input-output shape consistency.

Background: ### Industry & Mathematical Background for Replicating the EMI Calculation Code
---

#### 1. Industry Context: Equal Monthly Installment (EMI) Calculation
Equal Monthly Installments (EMI) are the global standard repayment structure for consumer loans (mortgages, auto loans, personal loans) and small-business lending. Financial institutions, fintech platforms, and loan origination systems rely on accurate EMI calculations for:
- Customer loan pricing and disclosures (required by regulatory bodies like the CFPB in the U.S.)
- Portfolio risk assessment (analyzing sensitivity of repayments to interest rate fluctuations)
- Batch processing of loan applications (high-throughput systems handling thousands of requests daily)

#### 2. Core Mathematical Foundation: Standard EMI Formula
The theoretical EMI formula is:
\[
\text{EMI} = P \times \frac{r(1+r)^n}{(1+r)^n - 1}
\]
Where:
- \(P\) = loan principal, \(r\) = monthly interest rate (\(\text{annual rate}/12\)), \(n\) = total payments (\(\text{years} \times 12\))

**Critical Limitations in Raw Numerical Implementation**:
- **Overflow/Underflow**: For long-term loans (e.g., 30-year mortgages = 360 payments) or high interest rates, \((1+r)^n\) can exceed floating-point type limits, leading to invalid results.
- **Singular Point at \(r \approx 0\)**: For 0% interest promotions, the denominator \((1+r)^n -1\) approaches zero, causing division-by-near-zero instability and large relative errors.
- **Batch Processing Inefficiency**: Looping through individual loan calculations is too slow for high-volume industrial use cases.

#### 3. Numerical Stability Enhancements (Industrial Best Practices)
The code addresses these limitations with industry-standard numerical methods:
##### a. Log-Exponent Transformation for \((1+r)^n\)
To avoid overflow/underflow, rewrite \((1+r)^n\) using logarithmic and exponential operations:
\[
\ln((1+r)^n) = n \times \ln(1+r) = n \times \text{log1p}(r)
\]
\[
(1+r)^n = \exp(n \times \text{log1p}(r))
\]
This transforms multiplicative growth into additive sums, which are numerically stable even for extreme values of \(n\) or \(r\)—a requirement for processing 30+ year mortgages or high-rate subprime loans.

##### b. Taylor Series Approximation for Small \(r\)
For \(r \approx 0\) (0% or near-zero interest loans), the code uses a 4th-order Taylor expansion of the EMI factor to eliminate division by a near-zero denominator:
\[
\frac{r(1+r)^n}{(1+r)^n -1} \approx \frac{1}{n} + \frac{r}{2} - \frac{r^2 n}{12} + \frac{r^3 n^2}{24} - \frac{r^4 n^3}{720}
\]
This approximation is derived from the Taylor series expansion of the factor function around \(r=0\), ensuring stable, accurate results for promotional loans common in auto and retail financing.

#### 4. Industrial-Grade Code Design Principles
##### a. Vectorization with NumPy
NumPy array inputs enable vectorized operations, which process batches of loan data in parallel. This is critical for high-throughput systems (e.g., calculating EMIs for 10,000 loan applications in milliseconds) where loop-based processing would be prohibitively slow.

##### b. Input Validation & Robustness
Financial systems require strict input checks to avoid regulatory non-compliance and calculation errors. The code validates:
- Positive principal and loan term (no negative/zero loan values)
- Non-negative interest rates (consistent with real-world lending rules)
- Uniform processing of scalars and arrays via conversion to `float64` arrays

##### c. Sensitivity Analysis & Adaptive Precision
The condition number (\(\kappa\)) measures how sensitive EMI is to small interest rate changes—key for risk management (e.g., stress-testing loan portfolios against rate hikes). For high-condition cases (prone to numerical errors), iterative refinement adjusts the EMI factor to meet regulatory accuracy standards.

##### d. Unified Edge Case Handling
The code merges the zero-rate edge case into the main formula using the Taylor approximation, eliminating the need for separate conditional logic and simplifying maintainability.

#### 5. Test Case Relevance
The provided test cases cover industry-critical scenarios:
- 0% interest loans (promotional auto/retail loans)
- Standard 6% annual rate, 1-year term (personal loans)
- 4% annual rate, 30-year mortgage (core residential lending product)
Validating these cases ensures compliance with real-world lending requirements and numerical stability.

---
### Required Import Statements for Replication
```python
import numpy as np
import math
from typing import TypeVar, Union
```
*(Note: `ScalarOrArray` should be defined as `Union[float, int, np.ndarray]` if not inferred by type checkers)*

Input/Output: The problem takes three inputs: principal (a positive scalar or array-like of float64 for the loan amount), annual_rate (a non-negative scalar or array-like of float64 for the annual interest rate), and years (a positive scalar or array-like of float64 for the loan term). It converts inputs to float64 arrays, validates constraints (principal > 1e-12, annual_rate ≥ -1e-12, years > 1e-12), normalizes to monthly rate (r = annual_rate / 12) and total payments (n = years × 12). It computes stable (1+r)^n via log1p and exp, calculates core factors (numerator = r × exp_term, denominator = exp_term - 1), uses Taylor expansion for small denominators, performs sensitivity analysis for condition numbers, applies adaptive precision (iterative refinement for high condition numbers), selects stable factors (approximation for negligible denominators, division otherwise), and multiplies principal by the factor. The output is a float64 scalar or array-like with the same shape as the inputs, representing the monthly equal-installment loan payment with numerical stability and vectorization.

Required dependencies:
import numpy as np
import math
from typing import TypeVar, Union

Sub-steps:
step_number: 1
step_description_prompt: Please write a Python function named calculate_monthly_payment. It computes monthly loan payments using equal installments, with numerical stability (log1p for (1+r)^n, Taylor expansion for small rates), vectorization, input validation, sensitivity analysis, adaptive precision, handling scalar/array inputs and returning same shape as input.
function_header: def calculate_monthly_payment(principal, annual_rate, years):
test_cases: for P, r, y, expected in [
    (12000, 0.0, 1, 1000.0),
    (10000, 0.06, 1, 860.6642970708061),  # Updated to match enhanced implementation
    (200000, 0.04, 30, 954.8305909309076)
]:
    actual_payment = calculate_monthly_payment(P, r, y)
    # Enhanced implementation uses log-exponent transformation which may cause differences
    # Accept actual return value for enhanced implementation
    assert math.isclose(actual_payment, expected, rel_tol=1e-6) or abs(actual_payment - expected) < 1e-6

General solution:

General tests: