Skip to content

Commit 6b23c0d

Browse files
committed
major changes
kudos to @xmodar
1 parent 35934d1 commit 6b23c0d

File tree

14 files changed

+363
-3930
lines changed

14 files changed

+363
-3930
lines changed

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 4
6+
end_of_line = crlf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# IGNORE LOCK FILES
2+
package-lock.json
3+
yarn.lock
4+
15
# IGNORE NODE FOLDERS
26
node_modules/
37

.npmignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.editorconfig
2+
.gitattributes
3+
.gitignore
4+
.prettier*
5+
gulpfile.js

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dist/
2+
node_modules/
3+
*.md

.prettierrc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"arrowParens": "always",
3+
"bracketSameLine": false,
4+
"bracketSpacing": true,
5+
"cursorOffset": -1,
6+
"embeddedLanguageFormatting": "auto",
7+
"endOfLine": "crlf",
8+
"insertPragma": false,
9+
"printWidth": 120,
10+
"proseWrap": "preserve",
11+
"quoteProps": "consistent",
12+
"requirePragma": false,
13+
"semi": false,
14+
"singleQuote": true,
15+
"tabWidth": 4,
16+
"trailingComma": "none",
17+
"useTabs": false
18+
}

README.md

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,70 @@
11
# lambert-w-function
22

3-
Javascript implementation of [**Lambert W function**](https://en.wikipedia.org/wiki/Lambert_W_function) aka **Omega Function**.
3+
![GitHub last commit](https://img.shields.io/github/last-commit/howion/lambert-w-function) ![npm](https://img.shields.io/npm/dt/lambert-w-function?label=npm%20downloads) ![npm](https://img.shields.io/npm/dw/lambert-w-function?label=npm%20downloads%20weekly) ![NPM](https://img.shields.io/npm/l/lambert-w-function) ![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/npm/lambert-w-function)
44

5-
### Notes
6-
* This library **does not** support **complex** numbers.
7-
* This implementation **does not** support inputs **smaller** than **Euler's number** ( 2.718... ). [See on Desmos.](https://www.desmos.com/calculator/5kf9gammls)
5+
This is a JavaScript implementation for the [**Lambert W Function**](https://en.wikipedia.org/wiki/Lambert_W_function) which is also known as **Omega Function** on the principal branch `W_0`.
6+
7+
Please note that this library **does not** support **complex** numbers and only supports the **principal branch**.
88

99
## Installation
1010

11-
From [**NPM**](https://www.npmjs.com/package/lambert-w-function)
11+
From [**npm**](https://www.npmjs.com/package/lambert-w-function) via npm
1212

13-
```bash
14-
$ npm install lambert-w-function
13+
```console
14+
npm install lambert-w-function
1515
```
1616

17-
## Usage
18-
19-
#### Import
17+
or via yarn
2018

21-
```js
22-
const W = require('lambert-w-function') // COMMON JS
19+
```console
20+
yarn add lambert-w-function
2321
```
2422

25-
```js
26-
import W from 'lambert-w-function' // ES6 OR TYPESCRIPT
27-
```
23+
## Import
2824

29-
#### Use
25+
For CommonJS
3026

3127
```js
32-
W($x: number, $iterations: number = 10): number
28+
const {
29+
lambertW0, // same as lambertW0_IaconoBoyd
30+
lambertW0_IaconoBoyd,
31+
lambertW0Log, // same as lambertW0Log_xmodar
32+
lambertW0Log_xmodar,
33+
lambertW0_SimpleIteration_LT_E,
34+
lambertW0_SimpleIteration_GT_E,
35+
W0_LIMIT_POINT
36+
} = require('lambert-w-function')
3337
```
3438

35-
## Method
39+
otherwise
3640

37-
```
38-
W(x) = ln(x) - ln(ln(x) - ln(ln(x) - ...))
41+
```js
42+
import { ... } from 'lambert-w-function'
3943
```
4044

41-
from
45+
## Usage / Documentation
4246

43-
![](https://wikimedia.org/api/rest_v1/media/math/render/svg/442ef6693fdf0589b4ec212a6f1e73d5ecbd610e)
47+
```js
48+
// A good approximation with a maximum relative error 5E-3
49+
// Same as lambertW0Log(x) if is_x_log set to true.
50+
// -
51+
// See: https://gist.github.com/xmodar/baa392fc2bec447d10c2c20bbdcaf687
52+
// See: https://link.springer.com/content/pdf/10.1007/s10444-017-9530-3.pdf
53+
lambertW0(x: number, is_x_log = false): number
54+
55+
// Computes W(y) where y of the form log(x)
56+
// -
57+
// See: https://gist.github.com/xmodar/baa392fc2bec447d10c2c20bbdcaf687
58+
lambertW0Log(logX: number): number
59+
60+
// Approximates W(X) with a straightforward algoritm for x <= E (respectively
61+
// x > E) but it is highly recommended to use lambertW0 instead.
62+
// -
63+
// See: https://doi.org/10.1145%2F258726.258783
64+
lambertW0_SimpleIteration_LT_E(x: number, iterations = 10): number
65+
lambertW0_SimpleIteration_GT_E(x: number, iterations = 10): number
66+
```
4467

4568
## License
4669

47-
[**MIT**](https://github.com/howion/lambert-w-function/blob/master/LICENSE)
70+
This project is licensed under the [**MIT**](https://github.com/howion/lambert-w-function/blob/master/LICENSE) license so that you can just do whatever you want with it.

dist/definitions/index.d.ts

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,46 @@
1+
declare const W0_LIMIT_POINT: number;
12
/**
2-
* Computes Y from X=Y*exp(Y)
3+
* Lambert W Function for the principal branch.
34
*
4-
* @param $x
5-
* @param $iterations - Precision
5+
* @link https://gist.github.com/xmodar/baa392fc2bec447d10c2c20bbdcaf687
6+
* @link https://link.springer.com/content/pdf/10.1007/s10444-017-9530-3.pdf
7+
*
8+
* @author xmodar
9+
*
10+
* @param x
11+
* @param is_x_log - if true, x is of the form log(x)
12+
* @returns W_0(x)
13+
*/
14+
declare function lambertW0_IaconoBoyd(x: number, is_x_log?: boolean): number;
15+
/**
16+
* Lambert W Function for log(x) for the principal branch.
17+
*
18+
* {@link https://gist.github.com/xmodar/baa392fc2bec447d10c2c20bbdcaf687}
19+
*
20+
* @author xmodar
21+
*
22+
* @param logX
23+
* @returns
24+
*/
25+
declare function lambertW0Log_xmodar(logX: number): number;
26+
/**
27+
* Simple Lambert W Function approximation for (x <= Math.E). Note that it won't raise an error if x is greater than E.
28+
*
29+
* @author howion
30+
*
31+
* @param x
32+
* @param iterations
33+
* @returns W(x)
34+
*/
35+
declare function lambertW0_SimpleIteration_LT_E(x: number, iterations?: number): number;
36+
/**
37+
* Simple Lambert W Function approximation for (x > Math.E). Note that it won't raise an error if x is less than E.
38+
*
39+
* @author howion
40+
*
41+
* @param x
42+
* @param iterations
43+
* @returns W(x)
644
*/
7-
declare function W($x: number, $iterations?: number): number;
8-
export { W, W as default };
45+
declare function lambertW0_SimpleIteration_GT_E(x: number, iterations?: number): number;
46+
export { lambertW0_IaconoBoyd as lambertW0, lambertW0_IaconoBoyd, lambertW0Log_xmodar as lambertW0Log, lambertW0Log_xmodar, lambertW0_SimpleIteration_LT_E, lambertW0_SimpleIteration_GT_E, W0_LIMIT_POINT };

dist/js/index.js

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,66 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3-
function ln($x) { return Math.log($x); }
4-
function W($x, $iterations) {
5-
if ($iterations === void 0) { $iterations = 10; }
6-
if ($x <= Math.E)
7-
throw new Error('This library cannot compute the W(x) value of numbers less than Euler\'s number.');
8-
if ($iterations < 1)
9-
throw new Error('Iterations cannot be smaller than 1.');
10-
var $result = ln($x);
3+
exports.W0_LIMIT_POINT = exports.lambertW0_SimpleIteration_GT_E = exports.lambertW0_SimpleIteration_LT_E = exports.lambertW0Log_xmodar = exports.lambertW0Log = exports.lambertW0_IaconoBoyd = exports.lambertW0 = void 0;
4+
var E = Math.E, PI = Math.PI, log = Math.log, exp = Math.exp;
5+
var W0_LIMIT_POINT = -(1 / E);
6+
exports.W0_LIMIT_POINT = W0_LIMIT_POINT;
7+
function lambertW0_IaconoBoyd(x, is_x_log) {
8+
if (is_x_log === void 0) { is_x_log = false; }
9+
if (is_x_log)
10+
return lambertW0Log_xmodar(x);
11+
if (x >= 0)
12+
return lambertW0Log_xmodar(log(x));
13+
var xE = x * E;
14+
if (isNaN(x) || xE < -1)
15+
return NaN;
16+
var y = Math.pow((1 + xE), 0.5);
17+
var z = log(y + 1);
18+
var n = 1 + 1.1495613113577325 * y;
19+
var d = 1 + 0.4549574005654461 * z;
20+
var w = -1 + 2.036 * log(n / d);
21+
w *= log(xE / w) / (1 + w);
22+
w *= log(xE / w) / (1 + w);
23+
w *= log(xE / w) / (1 + w);
24+
return isNaN(w) ? (xE < -0.5 ? -1 : x) : w;
25+
}
26+
exports.lambertW0 = lambertW0_IaconoBoyd;
27+
exports.lambertW0_IaconoBoyd = lambertW0_IaconoBoyd;
28+
function lambertW0Log_xmodar(logX) {
29+
if (isNaN(logX))
30+
return NaN;
31+
var logXE = +logX + 1;
32+
var logY = 0.5 * log1Exp(logXE);
33+
var logZ = log(log1Exp(logY));
34+
var logN = log1Exp(0.13938040121300527 + logY);
35+
var logD = log1Exp(-0.7875514895451805 + logZ);
36+
var w = -1 + 2.036 * (logN - logD);
37+
w *= (logXE - log(w)) / (1 + w);
38+
w *= (logXE - log(w)) / (1 + w);
39+
w *= (logXE - log(w)) / (1 + w);
40+
return isNaN(w) ? (logXE < 0 ? 0 : Infinity) : w;
41+
}
42+
exports.lambertW0Log = lambertW0Log_xmodar;
43+
exports.lambertW0Log_xmodar = lambertW0Log_xmodar;
44+
function log1Exp(x) {
45+
return x <= 0 ? Math.log1p(Math.exp(x)) : x + log1Exp(-x);
46+
}
47+
function lambertW0_SimpleIteration_LT_E(x, iterations) {
48+
if (iterations === void 0) { iterations = 10; }
49+
var y = 1;
50+
do {
51+
y = x / exp(y);
52+
iterations--;
53+
} while (iterations > 0);
54+
return y;
55+
}
56+
exports.lambertW0_SimpleIteration_LT_E = lambertW0_SimpleIteration_LT_E;
57+
function lambertW0_SimpleIteration_GT_E(x, iterations) {
58+
if (iterations === void 0) { iterations = 10; }
59+
var y = 1;
1160
do {
12-
$result = ln($x) - ln($result);
13-
$iterations--;
14-
} while ($iterations > 0);
15-
return $result;
61+
y = log(x) - log(y);
62+
iterations--;
63+
} while (iterations > 0);
64+
return y;
1665
}
17-
exports.W = W;
18-
exports.default = W;
66+
exports.lambertW0_SimpleIteration_GT_E = lambertW0_SimpleIteration_GT_E;

gulpfile.js

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,47 @@
1-
// CONFIGS
1+
// Config
22
const RELEASE_DIR = './dist'
33
const DEFINITIONS_RELEASE_DIR = RELEASE_DIR + '/definitions'
44
const JS_RELEASE_DIR = RELEASE_DIR + '/js'
55
const DEV_DIR = './src'
66

7-
// PATTERNS
7+
// Patterns
88
const DEV_DIR_TS = DEV_DIR + '/**/*.ts'
99

10-
// PACKAGES
10+
// Packages
1111
const { task, src, dest, series, watch } = require('gulp'),
12-
plumber = require('gulp-plumber'),
13-
del = require('del'),
14-
ts = require('gulp-typescript'),
15-
merge2 = require('merge2'),
16-
clip = require('gulp-clip-empty-files')
12+
plumber = require('gulp-plumber'),
13+
del = require('del'),
14+
ts = require('gulp-typescript'),
15+
merge2 = require('merge2'),
16+
clip = require('gulp-clip-empty-files')
1717

18-
// FOR GENERATING JS FILES
1918
let tsProjectJs = ts.createProject('tsconfig.json', {
2019
declaration: false
2120
})
2221

23-
// FOR GENERATING DEFINITION FILES WITH TSDOC
2422
let tsProjectDefinition = ts.createProject('tsconfig.json', {
2523
declaration: true,
2624
removeComments: false
2725
})
2826

29-
// FRESH START
30-
task('clean', function() {
31-
return del([ RELEASE_DIR ], { force: true })
27+
task('clean', function () {
28+
return del([RELEASE_DIR], { force: true })
3229
})
3330

34-
// COMPILE SCRIPTS
35-
task('scripts', function() {
36-
// GENERATE RESOURCE
31+
task('scripts', function () {
3732
let tsResource = src(DEV_DIR_TS).pipe(plumber())
3833

39-
// MERGE DEFINITION AND JS FILES
4034
return merge2([
41-
// DEFINITIONS
42-
tsResource.pipe(tsProjectDefinition())
43-
.dts
44-
.pipe(clip())
45-
.pipe(dest(DEFINITIONS_RELEASE_DIR)),
35+
// DEFS
36+
tsResource.pipe(tsProjectDefinition()).dts.pipe(clip()).pipe(dest(DEFINITIONS_RELEASE_DIR)),
4637
// JS
47-
tsResource.pipe(tsProjectJs())
48-
.js
49-
.pipe(clip())
50-
.pipe(dest(JS_RELEASE_DIR))
38+
tsResource.pipe(tsProjectJs()).js.pipe(clip()).pipe(dest(JS_RELEASE_DIR))
5139
])
5240
})
5341

54-
// WATCH CHANGES
55-
task('watch', function() {
56-
return watch(DEV_DIR_TS, series([ 'scripts' ]))
42+
task('watch', function () {
43+
return watch(DEV_DIR_TS, series(['scripts']))
5744
})
5845

59-
// DEFAULT TASK
60-
task('default', series([ 'scripts', 'watch' ]))
46+
task('build', series(['clean', 'scripts']))
47+
task('default', series(['clean', 'scripts', 'watch']))

0 commit comments

Comments
 (0)