npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

double-double

v2.1.0

Published

Pure double-double precision functions *with strict error bounds*.

Downloads

21,093

Readme

Pure double & double-double floating point arithmetic functions with strict error bounds

This library is only possible through the research of Mioara Joldes, Jean-Michel Muller, Valentina Popescu, Tight and rigourous error bounds for basic building blocks of double-word arithmetic

New! ★★★

functions

ddToStr and strToDd
ddSin and ddCos
ddEq, ddGt, ddGte, ddLt, ddLte
ddDiffDouble

constants

PIDd    //=> [1.2246467991473535e-16, 3.141592653589793]
eDd     //=> [1.4456468917292502e-16, 2.718281828459045]
ln2Dd   //=> [2.3190468138463e-17, 0.6931471805599453];
eulerDd //=> [-4.942915152430649e-18, 0.5772156649015329];

Examples

strToDd('3.1415926535897932384626433832795');  //=> [1.2246467991473535e-16, 3.141592653589793]
strToDd('6.0221408e+23');  //=> [-2097152, 6.0221408e+23]

ddToStr([1.2246467991473535e-16, 3.141592653589793]);  //=> '3.1415926535897932384626433832795_30530870267274333'

dDsin(ddDivDouble(PIDd,6));  //=> [0,0.5]
ddCos(ddDivDouble(PIDd,6));  //=> [5.017542110902477e-17, 0.8660254037844386]

ddGt([0,1],[0,2]);  //=> false

Documentation

Overview

  • Double-double precision floating point operators (similar to quad precision)
  • Each function documents a strict error bound (see research [1] below)
  • Optimized for speed (see benchmark below)
  • Operators include: +, -, *, /, √, abs, <, >, ===, min, max, etc.
  • Operators mixing double and double-doubles are also included, e.g. ddAddDouble (for adding a double to a double-double)
  • Error free double precision operators also included, e.g. twoProduct (for calculating the exact result of multiplying two doubles)
  • No classes ⇒ a double-double is simply a length 2 Number array, e.g.
import { twoSum } from 'double-double';
// Specified directly (low order double first)
const a = [-4.357806199228875e-10, 11_638_607.274152497];
// ...or more usually from an earlier calculation
const b = twoSum(213.456, 111.111);  // => [-1.4210854715202004e-14, 324.567] (completely error-free)
  • All functions are pure, e.g.
// using `a` and `b` as defined above (ddAddDd => double-double + double-double)
const c = ddAddDd(a,b);  // => [-2.42072459299969e-10, 11638931.841152497]
  • No dependencies

Installation

npm install double-double

This package is ESM only and can be used in Node.js (or in a browser when bundled using e.g. Webpack).

Additionally, self-contained ECMAScript Module (ESM) files index.module.js and index.module.min.js in the ./browser folder is provided.

Or, if you need a legacy browser script there is also index.js and index.min.js in the ./browser folder. Either script exposes a global variable called doubleDouble.

See full examples below.

A Practical example (Node.js)

Let's say you want to calculate the determinant of the following 2x2 matrix:
┌─ ─┐
│ A B │
│ C D │
└─ ─┘

In other words, let's say you want to calculate (A*D - B*C).

Let's further assume:

const A = 11.13;               // A is double precision ieee754 floating point number
const B = 8.664;               // ...
const C = 3.6329224376731304;  // ...
const D = 2.828;               // ...

In double precision the calculation is easy:

const d = A*D - B*C  // => 0

but gives the completely wrong answer of 0 due to round-off combined with catastrophic cancellation.

Using double-double precision gives:

import { twoProduct, ddDiffDd } from 'double-double';

// dd = A*D - B*C
const dd = ddDiffDd(twoProduct(A,D), twoProduct(B,C)); // => [0, -9.743145041148111e-17]

// The final answer can easily be rounded to the 'nearest' double:
const d1 = dd[0] + dd[1];  // => -9.743145041148111e-17
// or, alternatively truncated
const d2 = dd[1];  // => -9.743145041148111e-17

So the final result (after rounding back to double precision) is -9.743145041148111e-17 which is the exact result (i.e. no error) in this case.

As another example, if we take:

const A = 0.13331;
const B = 8.668;
const C = 3.609;
const D = 2.885;

we get the result (again after rounding to double precision) to be:

const d2 = -30.898212649999998;

Let us calculate an absolute error bound of the above? (This may or may not be important depending on the application.)

The documentation of ddDiffDd states:

  • Relative error bound: 3u^2 + 13u^3, i.e. fl(a-b) = (a-b)(1+ϵ), where ϵ <= 3u^2 + 13u^3, u = 0.5 * Number.EPSILON

For simplicity we incorporate the 3rd order term of 13u^3 in the 2nd order term, i.e. 3u^2 becomes 4u^2 === 4.930380657631324e-32 < 5e-32. (Note that the fl() function above is not the usual one in double precision, but instead represents a double-double precision calculation. Also, fl(a - b) is often denoted by a ⊖ b as for example in What Every Computer Scientist Should Know About Floating-Point Arithmetic.)

The maximum absolute error bound is then |a - b||ϵ| = |0.13331*2.885 - 8.668*3.609||5e-32| = 1.5449106325000001e-30 where A, B, C and D is as given previously. (The actual error is 4.930380657631324e-32)

In other words the calculation of dd above as a double-double represented as the length 2 array [6.3219416368554e-16, -30.898212649999998] with exact value 6.3219416368554e-16 + -30.898212649999998 is accurate up to roughly the 30th digit. (Typically the calculations will be more complex such as when the matrix is, say, 3x3 and the final result is often truncated to double precision.)

Usage

Node.js

// @filename: `test.mjs` (or `test.js` if { "type": "module" } is specified in your package.json)
import { ddAddDd } from 'double-double';  // `ddAddDd` returns the sum of two double-doubles 

const dd1 = [-4.357806199228875e-10, 11638607.274152497];  // some double-double
const dd2 = [4.511949494578893e-11, -2797357.2918064594];  // another double-double

const r1 = ddAddDd(dd1,dd2);  // sum the two double-doubles
const r2 = [-3.906611249770986e-10, 8841249.982346037];  // the correct result

if (r1[0] === r2[0] && r1[1] === r2[1]) {
    console.log('success! 😁');  // we should get to here!
} else {
    console.log('failure! 😥');  // ...and not here
}

Browsers - directly, without a bundler, using the pre-bundled minified .js file

Please note that no tree shaking will take place in this case.

<!doctype html>

<html lang="en">
<head>
    <script type="module">
        import { ddAddDd } from "./node_modules/double-double/browser/index.min.js";

        const dd1 = [-4.357806199228875e-10, 11638607.274152497];  // some double-double
        const dd2 = [4.511949494578893e-11, -2797357.2918064594];  // another double-double

        const r1 = ddAddDd(dd1,dd2);  // sum the two double-doubles
        const r2 = [-3.906611249770986e-10, 8841249.982346037];  // the correct result

        if (r1[0] === r2[0] && r1[1] === r2[1]) {
            console.log('success! 😁');  // we should get to here!
        } else {
            console.log('failure! 😥');  // ...and not here
        }
    </script>
</head>

<body>Check the console.</body>

</html>

Bundlers (Webpack, Rollup, ...)

Tree shaking will take place if supported by your bundler.

Webpack will be taken as an example here.

Since your webpack config file might still use CommonJS you must rename webpack.config.js to webpack.config.cjs.

If you are using TypeScript:

Since this is an ESM only library you must use resolve-typescript-plugin (at least until webpack catches up with ESM?) in your webpack.config.cjs file.

npm install --save-dev resolve-typescript-plugin

and follow the instructions given at resolve-typescript-plugin.

Additionally, follow this guide.

❗Important❗

When using bundlers:

import { operators } from 'double-double'

and then later in the code get the functions you need, e.g.:

const { ddAddDd as add, twoProduct, /* etc. */ } = operators;

as opposed to importing the operators directly.

This will increase performance roughly 5 times!

Why? Because Webpack (and Rollup) exports functions using getters that gets invoked on every function call adding a big overhead and slowing down each function. This is not an issue if the code is not bundled, e.g. when using Node.js.

Research

The following research / books / lectures have been used or are directly relevant to this library (especially the first two):

  1. Mioara Joldes, Jean-Michel Muller, Valentina Popescu, Tight and rigourous error bounds for basic building blocks of double-word arithmetic
  2. T. J. Dekker, A Floating-Point Technique for Extending the Available Precision
  3. Yozo Hida, Xiaoye S. Li, David H. Bailey, Library for Double-Double and Quad-Double Arithmetic
  4. Nicholas J. Higham, Accuracy and Stability of Numerical Algorithms

Benchmark

benchmark

Similar libraries in Javascript / TypeScript

License

MIT