From 91f2bad828e5e5a25e48c948ab4b008cf910617b Mon Sep 17 00:00:00 2001 From: Chad Young Date: Mon, 21 Mar 2022 13:32:32 -0700 Subject: [PATCH 1/3] documentation update --- .../scala/com/fulcrumgenomics/util/NumericTypes.scala | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala b/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala index f636bf325..327051daf 100644 --- a/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala +++ b/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala @@ -146,7 +146,7 @@ object NumericTypes { } /** - * Precise computation of log(1-exp(x)) for use in the `aOrNotB` method. + * Precise computation of log(1-exp(-x)) for use in the `aOrNotB` method. * See Equation (7) in https://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf */ private def log1mexp(value: Double): Double = { @@ -155,7 +155,7 @@ object NumericTypes { else log1p(-exp(-value)) // value > LnTwo } - /** Computes the probability of a or b, where a and b are independent events: Pr(A or B) = Pr(A) + Pr(B). */ + /** Computes the probability of a or b, where a and b are mutually exclusive events: Pr(A or B) = Pr(A) + Pr(B). */ def or(a: LogProbability, b: LogProbability): LogProbability = { if (a.isNegInfinity) b else if (b.isNegInfinity) a @@ -163,7 +163,7 @@ object NumericTypes { else a + log1pexp(b - a) // for precision we use log1pexp, which is equivalent to log(1+exp(x)) } - /** Computes the probability of any of the given independent events occurring: Pr(AB..N) = Pr(A)+Pr(B)+...+Pr(N). */ + /** Computes the probability of any of the given mutually exclusive events occurring: Pr(AB..N) = Pr(A)+Pr(B)+...+Pr(N). */ def or(values: Array[LogProbability]): LogProbability = { if (values.forall(_.isNegInfinity)) Double.NegativeInfinity else { @@ -184,10 +184,7 @@ object NumericTypes { /** Computes the probability of the given independent events co-occurring: Pr(AB..N) = Pr(A)*Pr(B)*...*Pr(N). */ def and(values: Array[Double]): LogProbability = values.sum - /** - * Computes the probability Pr(A OR not B) = Pr(A) - Pr(B). While this could be computed using - * or(a, not(b)), this form is more efficient and more precise. - */ + /** Computes the probability Pr(A AND not B) = Pr(A) - Pr(B), where B is a subset of A. */ def aOrNotB(a: LogProbability, b: LogProbability): LogProbability = { if (b.isNegInfinity) a else if (a == b) Double.NegativeInfinity From 5ae19f1b24b1d47d69dace262bea1fbdc53adc63 Mon Sep 17 00:00:00 2001 From: Chad Young Date: Mon, 21 Mar 2022 13:33:25 -0700 Subject: [PATCH 2/3] notation update --- src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala b/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala index 327051daf..393f0c95f 100644 --- a/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala +++ b/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala @@ -163,7 +163,7 @@ object NumericTypes { else a + log1pexp(b - a) // for precision we use log1pexp, which is equivalent to log(1+exp(x)) } - /** Computes the probability of any of the given mutually exclusive events occurring: Pr(AB..N) = Pr(A)+Pr(B)+...+Pr(N). */ + /** Computes the probability of any of the given mutually exclusive events occurring: Pr(A,B,..N) = Pr(A)+Pr(B)+...+Pr(N). */ def or(values: Array[LogProbability]): LogProbability = { if (values.forall(_.isNegInfinity)) Double.NegativeInfinity else { @@ -178,10 +178,10 @@ object NumericTypes { } } - /** Computes the probability of a and b, where a and b are independent events: Pr(AB) = Pr(A)*Pr(B). */ + /** Computes the probability of a and b, where a and b are independent events: Pr(A,B) = Pr(A)*Pr(B). */ def and(a: LogProbability, b: LogProbability): LogProbability = a + b - /** Computes the probability of the given independent events co-occurring: Pr(AB..N) = Pr(A)*Pr(B)*...*Pr(N). */ + /** Computes the probability of the given independent events co-occurring: Pr(A,B,..N) = Pr(A)*Pr(B)*...*Pr(N). */ def and(values: Array[Double]): LogProbability = values.sum /** Computes the probability Pr(A AND not B) = Pr(A) - Pr(B), where B is a subset of A. */ From 92d078f1b579027d1978519b9d30c560deec6d1d Mon Sep 17 00:00:00 2001 From: Chad Young Date: Mon, 21 Mar 2022 14:28:42 -0700 Subject: [PATCH 3/3] Update log1mexp --- src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala b/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala index 393f0c95f..dfd499676 100644 --- a/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala +++ b/src/main/scala/com/fulcrumgenomics/util/NumericTypes.scala @@ -150,7 +150,7 @@ object NumericTypes { * See Equation (7) in https://cran.r-project.org/web/packages/Rmpfr/vignettes/log1mexp-note.pdf */ private def log1mexp(value: Double): Double = { - if (value < 0) throw new IllegalArgumentException("value was less than zero: " + value) + if (value <= 0) throw new IllegalArgumentException("value was less than or equal to zero: " + value) else if (value <= LnTwo) log(-expm1(-value)) else log1p(-exp(-value)) // value > LnTwo }