Repository: scipy/scipy

Issue:
BUG: scipy.stats.linregress fails when x is an array of zeros
### Reproducing Code Example

```python
import numpy as np
from scipy.stats import linregress

x = np.full(10, 42)
y = np.random.rand(10)
regr = linregress(x, y)
```


### Error message

```shell
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/sergio/.local/lib/python3.8/site-packages/scipy/stats/_stats_mstats_common.py", line 170, in linregress
    slope = ssxym / ssxm
FloatingPointError: invalid value encountered in double_scalars
```

### Additional info
When input `x` is an array containing identical elements, `ssxm` is 0 and all divisions by `ssxm` fail:
- https://github.com/scipy/scipy/blob/5996b0b928956505fae60f27b6d0d527165e453e/scipy/stats/_stats_mstats_common.py#L171
- https://github.com/scipy/scipy/blob/5996b0b928956505fae60f27b6d0d527165e453e/scipy/stats/_stats_mstats_common.py#L188

I know that regression with such an `x` array doesn't really make sense, and that you can handle this from outside with a  check, but it would be nice to detect this condition inside `linregress` and provide meaningful output (i.e. absence of correlation, slope = Inf, intercept = NaN) in this scenario as well.


### SciPy/NumPy/Python version information

1.7.1 1.20.1 sys.version_info(major=3, minor=8, micro=10, releaselevel='final', serial=0)


Discussion:

Resolving patch:
diff --git a/scipy/stats/_stats_mstats_common.py b/scipy/stats/_stats_mstats_common.py
--- a/scipy/stats/_stats_mstats_common.py
+++ b/scipy/stats/_stats_mstats_common.py
@@ -146,6 +146,10 @@ def linregress(x, y=None, alternative='two-sided'):
     if x.size == 0 or y.size == 0:
         raise ValueError("Inputs must not be empty.")
 
+    if np.amax(x) == np.amin(x) and len(x) > 1:
+        raise ValueError("Cannot calculate a linear regression "
+                         "if all x values are identical")
+
     n = len(x)
     xmean = np.mean(x, None)
     ymean = np.mean(y, None)
diff --git a/scipy/stats/mstats_basic.py b/scipy/stats/mstats_basic.py
--- a/scipy/stats/mstats_basic.py
+++ b/scipy/stats/mstats_basic.py
@@ -998,6 +998,10 @@ def linregress(x, y=None):
     x = x.flatten()
     y = y.flatten()
 
+    if np.amax(x) == np.amin(x) and len(x) > 1:
+        raise ValueError("Cannot calculate a linear regression "
+                         "if all x values are identical")
+
     m = ma.mask_or(ma.getmask(x), ma.getmask(y), shrink=False)
     if m is not nomask:
         x = ma.array(x, mask=m)


Test patch:
diff --git a/scipy/stats/tests/test_mstats_basic.py b/scipy/stats/tests/test_mstats_basic.py
--- a/scipy/stats/tests/test_mstats_basic.py
+++ b/scipy/stats/tests/test_mstats_basic.py
@@ -869,6 +869,15 @@ def test_regress_simple():
     assert_almost_equal(result.stderr, 0.002395781449783862)
     assert_almost_equal(result.intercept_stderr, 0.13866936078570702)
 
+
+def test_linregress_identical_x():
+    x = np.zeros(10)
+    y = np.random.random(10)
+    msg = "Cannot calculate a linear regression if all x values are identical"
+    with assert_raises(ValueError, match=msg):
+        mstats.linregress(x, y)
+
+
 def test_theilslopes():
     # Test for basic slope and intercept.
     slope, intercept, lower, upper = mstats.theilslopes([0, 1, 1])
diff --git a/scipy/stats/tests/test_stats.py b/scipy/stats/tests/test_stats.py
--- a/scipy/stats/tests/test_stats.py
+++ b/scipy/stats/tests/test_stats.py
@@ -1862,6 +1862,12 @@ def test_nan_input(self):
         assert_array_equal(result, (np.nan,)*5)
         assert_equal(result.intercept_stderr, np.nan)
 
+    def test_identical_x(self):
+        x = np.zeros(10)
+        y = np.random.random(10)
+        msg = "Cannot calculate a linear regression"
+        with assert_raises(ValueError, match=msg):
+            stats.linregress(x, y)
 
 def test_theilslopes():
     # Basic slope test.