Skip to content

Commit

Permalink
feat: Add logit and cumulativeStdLogisticProbability methods
Browse files Browse the repository at this point in the history
* Add logistic distribution utilities

* Split out logit test and test boundary condition

Co-authored-by: Daniel Saxton <dsaxton@pm.me>
  • Loading branch information
tmcw and Daniel Saxton committed Feb 24, 2021
1 parent 182f3fe commit 7279632
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 0 deletions.
2 changes: 2 additions & 0 deletions index.js
Expand Up @@ -109,10 +109,12 @@ export {
// Normal distribution
export { default as zScore } from "./src/z_score";
export { default as cumulativeStdNormalProbability } from "./src/cumulative_std_normal_probability";
export { default as cumulativeStdLogisticProbability } from "./src/cumulative_std_logistic_probability";
export { default as standardNormalTable } from "./src/standard_normal_table";
export { default as errorFunction, default as erf } from "./src/error_function";
export { default as inverseErrorFunction } from "./src/inverse_error_function";
export { default as probit } from "./src/probit";
export { default as logit } from "./src/logit";

// Non-parametric Methods
export { default as permutationTest } from "./src/permutation_test";
Expand Down
6 changes: 6 additions & 0 deletions src/cumulative_std_logistic_probability.d.ts
@@ -0,0 +1,6 @@
/**
* https://simplestatistics.org/docs/#cumulativestdlogisticprobability
*/
declare function cumulativeStdLogisticProbability(x: number): number;

export default cumulativeStdLogisticProbability;
11 changes: 11 additions & 0 deletions src/cumulative_std_logistic_probability.js
@@ -0,0 +1,11 @@
/**
* **[Logistic Cumulative Distribution Function](https://en.wikipedia.org/wiki/Logistic_distribution)**
*
* @param {number} x
* @returns {number} cumulative standard logistic probability
*/
function cumulativeStdLogisticProbability(x) {
return 1 / (Math.exp(-x) + 1);
}

export default cumulativeStdLogisticProbability;
6 changes: 6 additions & 0 deletions src/logit.d.ts
@@ -0,0 +1,6 @@
/**
* https://simplestatistics.org/docs/#logit
*/
declare function logit(p: number): number;

export default logit;
16 changes: 16 additions & 0 deletions src/logit.js
@@ -0,0 +1,16 @@
/**
* The [Logit](https://en.wikipedia.org/wiki/Logit)
* is the inverse of cumulativeStdLogisticProbability,
* and is also known as the logistic quantile function.
*
* @param {number} p
* @returns {number} logit
*/
function logit(p) {
if (p <= 0 || p >= 1) {
throw new Error("p must be strictly between zero and one");
}
return Math.log(p / (1 - p));
}

export default logit;
32 changes: 32 additions & 0 deletions test/cumulative.test.js
Expand Up @@ -58,3 +58,35 @@ test("cumulativeStdNormalProbability", function (t) {
});
t.end();
});

test("cumulativeStdLogisticProbability", function (t) {
t.test("median is zero", function (t) {
t.equal(ss.cumulativeStdLogisticProbability(0), 0.5);
t.end();
});
t.test("increasing", function (t) {
for (let i = -3; i <= 3; i += 0.01) {
if (
ss.cumulativeStdLogisticProbability(i + ss.epsilon) <=
ss.cumulativeStdLogisticProbability(i)
) {
t.fail("increasing failure at " + i);
}
}
t.end();
});
t.test("symmetry", function (t) {
for (let i = 0; i <= 3; i += 0.01) {
if (
Math.abs(
ss.cumulativeStdLogisticProbability(i) -
(1 - ss.cumulativeStdLogisticProbability(-i))
) > ss.epsilon
) {
t.fail("not symmetric about zero");
}
}
t.end();
});
t.end();
});
27 changes: 27 additions & 0 deletions test/logit.test.js
@@ -0,0 +1,27 @@
/* eslint no-shadow: 0 */

const test = require("tap").test;
const ss = require("../");

test("logit", function (t) {
t.test("inverse", function (t) {
for (let i = -3; i <= 3; i += 0.01) {
if (
Math.abs(ss.logit(ss.cumulativeStdLogisticProbability(i)) - i) >
ss.epsilon
) {
t.fail("not an inverse of logit at " + i);
}
}
t.end();
});

t.test("out-of-bounds input", function (t) {
t.throws(function () {
ss.logit(2);
});
t.end();
});

t.end();
});

0 comments on commit 7279632

Please sign in to comment.