Repository: facebookresearch/NeuralCompression (language: python)

Issue:
log_cdf op
Logarithm of the distribution’s cumulative distribution function (CDF).

```Python
log_cdf(x: torch.Tensor, distribution: torch.distributions.Distribution) -> torch.Tensor
```

Prerequisites

- [x] #79 


Discussion / hints:

Fix patch:
diff --git a/docs/source/functional.rst b/docs/source/functional.rst
index d1a3383e..6096785f 100644
--- a/docs/source/functional.rst
+++ b/docs/source/functional.rst
@@ -13,3 +13,4 @@ neuralcompression.functional
 .. autofunction:: quantization_offset
 .. autofunction:: ndtr
 .. autofunction:: log_ndtr
+.. autofunction:: log_cdf
diff --git a/neuralcompression/functional/__init__.py b/neuralcompression/functional/__init__.py
index 70f87751..ccb93328 100644
--- a/neuralcompression/functional/__init__.py
+++ b/neuralcompression/functional/__init__.py
@@ -6,6 +6,7 @@
 """
 
 from ._estimate_tails import estimate_tails
+from ._log_cdf import log_cdf
 from ._log_ndtr import log_ndtr
 from ._ndtr import ndtr
 from ._quantization_offset import quantization_offset
diff --git a/neuralcompression/functional/_log_cdf.py b/neuralcompression/functional/_log_cdf.py
new file mode 100644
index 00000000..d49c2399
--- /dev/null
+++ b/neuralcompression/functional/_log_cdf.py
@@ -0,0 +1,37 @@
+"""
+Copyright (c) Facebook, Inc. and its affiliates.
+This source code is licensed under the MIT license found in the
+LICENSE file in the root directory of this source tree.
+"""
+
+import torch
+from torch import Tensor
+from torch.distributions import Distribution, Normal, Uniform
+
+from ._log_ndtr import log_ndtr
+
+
+def log_cdf(
+    x: Tensor,
+    distribution: Distribution,
+):
+    """Logarithm of the distribution’s cumulative distribution function (CDF).
+
+    Args:
+        x: the input tensor.
+        distribution: an object representing a continuous-valued random
+        variable.
+
+    Returns:
+        the log of the area under the distribution’s probability density
+        function (PDF), integrated from minus infinity to ``x``.
+    """
+    if isinstance(distribution, Normal):
+        standardized = (x - distribution.loc) / distribution.scale
+
+        return log_ndtr(standardized)
+
+    if isinstance(distribution, Uniform):
+        return torch.log(x)
+
+    return torch.log(distribution.cdf(x))


Test patch:
diff --git a/tests/functional/test_log_cdf.py b/tests/functional/test_log_cdf.py
new file mode 100644
index 00000000..858e1d14
--- /dev/null
+++ b/tests/functional/test_log_cdf.py
@@ -0,0 +1,38 @@
+"""
+Copyright (c) Facebook, Inc. and its affiliates.
+This source code is licensed under the MIT license found in the
+LICENSE file in the root directory of this source tree.
+"""
+
+import numpy.random
+import scipy.special
+import scipy.stats
+import torch
+import torch.testing
+from torch.distributions import Normal, Uniform
+
+from neuralcompression.functional import log_cdf
+
+
+def test_log_cdf():
+    rng = numpy.random.default_rng(0xFEEEFEEE)
+
+    x = rng.random((32,), dtype=numpy.float)
+
+    actual = log_cdf(torch.tensor(x, dtype=torch.float), Normal(0.0, 1.0))
+
+    assert torch.isfinite(actual).all()
+
+    torch.testing.assert_close(
+        actual,
+        torch.tensor(scipy.special.log_ndtr(x), dtype=torch.float),
+    )
+
+    actual = log_cdf(torch.tensor(x, dtype=torch.float), Uniform(0.0, 1.0))
+
+    assert torch.isfinite(actual).all()
+
+    torch.testing.assert_close(
+        actual,
+        torch.tensor(scipy.stats.uniform.logcdf(x), dtype=torch.float),
+    )