Repository: scipy/scipy

Issue:
Planck distribution is a geometric distribution
`stats.planck` is just a geometric distribution `stats.geom` with `p = 1 - exp(-lambda)`. I am not aware that Planck distribution is a known name for it.

Currently, `planck` is incorrectly defined for negative `lambda` as well (see #9358).

Should `planck` be deprecated?


Discussion:
In the scipy docs, geom.pmf(k) = (1 - p) ^ (k - 1) * p and planck.pmf(k) = (1 - exp(-lambda)) * exp(-lambda * k) = (1 - (1  - exp(-lambda)) ^ ( k - 1) * (exp(-lambda)) * (1 - exp(-lambda)), so it's just not simple as p = 1 - exp(-lambda), so I think we shouldn't deprecated stats.planck. Thanks!
OK, but `geom.pmf(k, 1-exp(-a)) == planck.pmf(k-1, a)`, so difference is a shift by one (which can be achieved with the parameter loc). Did i overlook sth?
Your second parameter is `(1 - exp(-a))`, but planck is more than geom with `exp(-a)`, so it can not solve by shift by one.
@LuckyPigeon 
>planck is more than geom with exp(-a), so it can not solve by shift by one.

This isn't clear to me, it does seem to me that Planck is same as geometric. 
Can you provide explanation for how planck is more than geom with exp(-a). 
Numerical "proof":
```
import numpy as np
from scipy.stats import planck, geom

a = 0.5
k = np.arange(20)
sum(abs(geom.pmf(k, 1-np.exp(-a)) - planck.pmf(k-1, a))) # 1.30e-18

# or using loc:
sum(abs(geom.pmf(k, 1-np.exp(-a), loc=-1) - planck.pmf(k, a))) # 1.30e-18
```

Resolving patch:
diff --git a/scipy/stats/_discrete_distns.py b/scipy/stats/_discrete_distns.py
--- a/scipy/stats/_discrete_distns.py
+++ b/scipy/stats/_discrete_distns.py
@@ -233,6 +233,10 @@ class geom_gen(rv_discrete):
 
     %(after_notes)s
 
+    See Also
+    --------
+    planck
+
     %(example)s
 
     """
@@ -243,7 +247,6 @@ def _argcheck(self, p):
         return (p <= 1) & (p >= 0)
 
     def _pmf(self, k, p):
-        # geom.pmf(k) = (1-p)**(k-1)*p
         return np.power(1-p, k-1) * p
 
     def _logpmf(self, k, p):
@@ -546,10 +549,16 @@ class planck_gen(rv_discrete):
 
     for :math:`k \ge 0` and :math:`\lambda > 0`.
 
-    `planck` takes :math:`\lambda` as shape parameter.
+    `planck` takes :math:`\lambda` as shape parameter. The Planck distribution
+    can be written as a geometric distribution (`geom`) with
+    :math:`p = 1 - \exp(-\lambda)` shifted by `loc = -1`.
 
     %(after_notes)s
 
+    See Also
+    --------
+    geom
+
     %(example)s
 
     """
@@ -557,14 +566,14 @@ def _argcheck(self, lambda_):
         return lambda_ > 0
 
     def _pmf(self, k, lambda_):
-        return (1-exp(-lambda_))*exp(-lambda_*k)
+        return -expm1(-lambda_)*exp(-lambda_*k)
 
     def _cdf(self, x, lambda_):
         k = floor(x)
-        return 1-exp(-lambda_*(k+1))
+        return -expm1(-lambda_*(k+1))
 
     def _sf(self, x, lambda_):
-        return np.exp(self._logsf(x, lambda_))
+        return exp(self._logsf(x, lambda_))
 
     def _logsf(self, x, lambda_):
         k = floor(x)
@@ -576,17 +585,21 @@ def _ppf(self, q, lambda_):
         temp = self._cdf(vals1, lambda_)
         return np.where(temp >= q, vals1, vals)
 
+    def _rvs(self, lambda_):
+        # use relation to geometric distribution for sampling
+        p = -expm1(-lambda_)
+        return self._random_state.geometric(p, size=self._size) - 1.0
+
     def _stats(self, lambda_):
-        mu = 1/(exp(lambda_)-1)
+        mu = 1/expm1(lambda_)
         var = exp(-lambda_)/(expm1(-lambda_))**2
         g1 = 2*cosh(lambda_/2.0)
         g2 = 4+2*cosh(lambda_)
         return mu, var, g1, g2
 
     def _entropy(self, lambda_):
-        l = lambda_
-        C = (1-exp(-l))
-        return l*exp(-l)/C - log(C)
+        C = -expm1(-lambda_)
+        return lambda_*exp(-lambda_)/C - log(C)
 
 
 planck = planck_gen(a=0, name='planck', longname='A discrete exponential ')


Test patch: