double-double
Version:
Pure double-double precision functions *with strict error bounds*.
99 lines (75 loc) • 2.77 kB
text/typescript
import { expect } from 'chai';
import { describe } from 'mocha';
import { squares } from 'squares-rng';
import { ddToStr, strToDd } from '../../src/index.js';
import { getDiffInUlpsDd } from '../../src/str-to-dd/get-diff-in-ulps-dd.js';
import { getDiffInUlps } from '../../src/dd-to-str/get-diff-in-ulps.js';
import { extractExp } from '../../src/str-to-dd/extract-exp.js';
import { multStrByPowOf10 } from '../../src/str-to-dd/mult-str-by-pow-of-10.js';
const { abs } = Math;
describe('ddToStr', function() {
it('should correctly convert a double-double to a string',
function() {
// Some double-doubles
const PI = [1.2246467991473532e-16, 3.141592653589793]; // correctly rounded
const PIStr = ddToStr(PI);
expect(
PIStr.slice(0,34),
`PI not converted correctly, got ${PIStr}`
).to.eql('3.14159265358979323846264338327950');
let ddStrs = [
'0',
'1',
'1.0',
'-0',
'-1',
'-1.0',
'2.12122321e-31'
];
const randomStrs = makeRandomStrs(50);
ddStrs = [...ddStrs, ...randomStrs];
for (const ddStr of ddStrs) {
test(ddStr);
}
});
});
function makeRandomStrs(count: number) {
const strs: string[] = [];
let rng = 0;
for (let i=0; i<count; i++) {
const exp = squares(rng++)%100 - 50;
const l = squares(rng++)%50 + 1;
let s: string = '';
for (let j=0; j<l; j++) {
const n = squares(rng++)%10;
s += n.toString();
}
const zeros = new Array(abs(exp)).join('0');
const negStr = squares(rng++)%2 === 0 ? '' : '-1';
if (exp === 0) {
strs.push(negStr + s);
} else if (exp > 0) {
strs.push(negStr + s + zeros);
} else {
strs.push(negStr + '0.' + zeros + s);
}
}
return strs;
}
function test(str: string) {
const dd = strToDd(str);
const ddStr = ddToStr(dd);
const { s: s_, exp: exp_ } = extractExp(str);
str = multStrByPowOf10(s_,exp_);
const diffInUlpsDd = abs(getDiffInUlpsDd(str,ddStr));
expect(
diffInUlpsDd,
`Failed to convert ${str}. Expected a dd (quarter) ulp error of less than or equal to 1 but found ${diffInUlpsDd}`
).to.be.lessThanOrEqual(1);
const d = Number(str);
const diffInUlps = abs(getDiffInUlps(d,dd[0] + dd[1]));
expect(
diffInUlps,
`Failed to convert ${str}. Expected an ulp error of less than or equal to 1 but found ${diffInUlpsDd}`
).to.be.lessThanOrEqual(1);
}