version bump 0.3.0: tolerance adjustment
Note: The Aberth algorithm is sensitive to input errors New tests trigger an infinite loop under old tolerance, work fine with new.
This commit is contained in:
parent
804bc32c2c
commit
e0b3a1e75c
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (C) 2013 SheetJS
|
||||
Copyright (C) 2013-2014 SheetJS
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
2
Makefile
2
Makefile
@ -2,5 +2,5 @@ frac.js: frac.md
|
||||
voc frac.md
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
test:
|
||||
mocha -R spec
|
||||
|
12
README.md
12
README.md
@ -37,3 +37,15 @@ For example:
|
||||
|
||||
`frac.cont` implements the Aberth algorithm (input and output specifications
|
||||
match the original `frac` function)
|
||||
|
||||
## Tests
|
||||
|
||||
Tests generated from Excel have 4 columns. To produce a similar test:
|
||||
|
||||
- Column A contains the raw values
|
||||
- Column B format "Up to one digit (1/4)"
|
||||
- Column C format "Up to two digits (21/25)"
|
||||
- Column D format "Up to three digits (312/943)"
|
||||
|
||||
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/731e31b3a26382ccd5d213b9e74ea552 "githalytics.com")](http://githalytics.com/SheetJS/frac)
|
||||
|
||||
|
72
frac.js
72
frac.js
@ -1,42 +1,42 @@
|
||||
/* frac.js (C) 2013 SheetJS -- http://sheetjs.com */
|
||||
/* frac.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
var frac = function(x, D, mixed) {
|
||||
var n1 = Math.floor(x), d1 = 1;
|
||||
var n2 = n1+1, d2 = 1;
|
||||
if(x !== n1) while(d1 <= D && d2 <= D) {
|
||||
var m = (n1 + n2) / (d1 + d2);
|
||||
if(x === m) {
|
||||
if(d1 + d2 <= D) { d1+=d2; n1+=n2; d2=D+1; }
|
||||
else if(d1 > d2) d2=D+1;
|
||||
else d1=D+1;
|
||||
break;
|
||||
}
|
||||
else if(x < m) { n2 = n1+n2; d2 = d1+d2; }
|
||||
else { n1 = n1+n2; d1 = d1+d2; }
|
||||
var n1 = Math.floor(x), d1 = 1;
|
||||
var n2 = n1+1, d2 = 1;
|
||||
if(x !== n1) while(d1 <= D && d2 <= D) {
|
||||
var m = (n1 + n2) / (d1 + d2);
|
||||
if(x === m) {
|
||||
if(d1 + d2 <= D) { d1+=d2; n1+=n2; d2=D+1; }
|
||||
else if(d1 > d2) d2=D+1;
|
||||
else d1=D+1;
|
||||
break;
|
||||
}
|
||||
if(d1 > D) { d1 = d2; n1 = n2; }
|
||||
if(!mixed) return [0, n1, d1];
|
||||
var q = Math.floor(n1/d1);
|
||||
return [q, n1 - q*d1, d1];
|
||||
else if(x < m) { n2 = n1+n2; d2 = d1+d2; }
|
||||
else { n1 = n1+n2; d1 = d1+d2; }
|
||||
}
|
||||
if(d1 > D) { d1 = d2; n1 = n2; }
|
||||
if(!mixed) return [0, n1, d1];
|
||||
var q = Math.floor(n1/d1);
|
||||
return [q, n1 - q*d1, d1];
|
||||
};
|
||||
frac.cont = function cont(x, D, mixed) {
|
||||
var sgn = x < 0 ? -1 : 1;
|
||||
var B = x * sgn;
|
||||
var P_2 = 0, P_1 = 1, P = 0;
|
||||
var Q_2 = 1, Q_1 = 0, Q = 0;
|
||||
var A = B|0;
|
||||
while(Q_1 < D) {
|
||||
A = B|0;
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
if((B - A) < 0.0000000001) break;
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
}
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
var sgn = x < 0 ? -1 : 1;
|
||||
var B = x * sgn;
|
||||
var P_2 = 0, P_1 = 1, P = 0;
|
||||
var Q_2 = 1, Q_1 = 0, Q = 0;
|
||||
var A = B|0;
|
||||
while(Q_1 < D) {
|
||||
A = B|0;
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
}
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
};
|
||||
if(typeof module !== 'undefined') module.exports = frac;
|
||||
|
190
frac.md
190
frac.md
@ -10,74 +10,74 @@ The JS implementation walks through the algorithm.
|
||||
|
||||
# JS Implementation
|
||||
|
||||
In this version, the return value is `[quotient, numerator, denominator]`,
|
||||
where `quotient == 0` for improper fractions. The interpretation is
|
||||
In this version, the return value is `[quotient, numerator, denominator]`,
|
||||
where `quotient == 0` for improper fractions. The interpretation is
|
||||
`x ~ quotient + numerator / denominator` where `0 <= numerator < denominator`
|
||||
and `quotient <= x` for negative `x`.
|
||||
|
||||
```js>frac.js
|
||||
/* frac.js (C) 2013 SheetJS -- http://sheetjs.com */
|
||||
/* frac.js (C) 2013-2014 SheetJS -- http://sheetjs.com */
|
||||
var frac = function(x, D, mixed) {
|
||||
```
|
||||
|
||||
The goal is to maintain a feasible fraction (with bounded denominator) below
|
||||
the target and another fraction above the target. The lower bound is
|
||||
the target and another fraction above the target. The lower bound is
|
||||
`floor(x) / 1` and the upper bound is `(floor(x) + 1) / 1`. We keep track of
|
||||
the numerators and denominators separately:
|
||||
|
||||
```
|
||||
var n1 = Math.floor(x), d1 = 1;
|
||||
var n2 = n1+1, d2 = 1;
|
||||
var n1 = Math.floor(x), d1 = 1;
|
||||
var n2 = n1+1, d2 = 1;
|
||||
```
|
||||
|
||||
If `x` is not integral, we bisect using mediants until a denominator exceeds
|
||||
our target:
|
||||
|
||||
```
|
||||
if(x !== n1) while(d1 <= D && d2 <= D) {
|
||||
if(x !== n1) while(d1 <= D && d2 <= D) {
|
||||
```
|
||||
|
||||
The mediant is the sum of the numerators divided by the sum of demoninators:
|
||||
|
||||
```
|
||||
var m = (n1 + n2) / (d1 + d2);
|
||||
var m = (n1 + n2) / (d1 + d2);
|
||||
```
|
||||
|
||||
If we happened to stumble upon the exact value, then we choose the closer one
|
||||
(the mediant if the denominator is within bounds, or the bound with the larger
|
||||
denominator)
|
||||
denominator)
|
||||
|
||||
```
|
||||
if(x === m) {
|
||||
if(d1 + d2 <= D) { d1+=d2; n1+=n2; d2=D+1; }
|
||||
else if(d1 > d2) d2=D+1;
|
||||
else d1=D+1;
|
||||
break;
|
||||
}
|
||||
if(x === m) {
|
||||
if(d1 + d2 <= D) { d1+=d2; n1+=n2; d2=D+1; }
|
||||
else if(d1 > d2) d2=D+1;
|
||||
else d1=D+1;
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
Otherwise shrink the range:
|
||||
|
||||
```
|
||||
else if(x < m) { n2 = n1+n2; d2 = d1+d2; }
|
||||
else { n1 = n1+n2; d1 = d1+d2; }
|
||||
}
|
||||
else if(x < m) { n2 = n1+n2; d2 = d1+d2; }
|
||||
else { n1 = n1+n2; d1 = d1+d2; }
|
||||
}
|
||||
```
|
||||
|
||||
At this point, `d1 > D` or `d2 > D` (but not both -- keep track of how `d1` and
|
||||
`d2` change). So we merely return the desired values:
|
||||
|
||||
```
|
||||
if(d1 > D) { d1 = d2; n1 = n2; }
|
||||
if(!mixed) return [0, n1, d1];
|
||||
var q = Math.floor(n1/d1);
|
||||
return [q, n1 - q*d1, d1];
|
||||
if(d1 > D) { d1 = d2; n1 = n2; }
|
||||
if(!mixed) return [0, n1, d1];
|
||||
var q = Math.floor(n1/d1);
|
||||
return [q, n1 - q*d1, d1];
|
||||
};
|
||||
```
|
||||
|
||||
## Continued Fraction Method
|
||||
|
||||
The continued fraction technique is employed by various spreadsheet programs.
|
||||
The continued fraction technique is employed by various spreadsheet programs.
|
||||
Note that this technique is inferior to the mediant method (at least, according
|
||||
to the desired goal of most accurately approximating the floating point number)
|
||||
|
||||
@ -90,64 +90,64 @@ frac.cont = function cont(x, D, mixed) {
|
||||
Note that the variables are implicitly indexed at `k` (so `B` refers to `b_k`):
|
||||
|
||||
```
|
||||
var sgn = x < 0 ? -1 : 1;
|
||||
var B = x * sgn;
|
||||
var P_2 = 0, P_1 = 1, P = 0;
|
||||
var Q_2 = 1, Q_1 = 0, Q = 0;
|
||||
var A = B|0;
|
||||
var sgn = x < 0 ? -1 : 1;
|
||||
var B = x * sgn;
|
||||
var P_2 = 0, P_1 = 1, P = 0;
|
||||
var Q_2 = 1, Q_1 = 0, Q = 0;
|
||||
var A = B|0;
|
||||
```
|
||||
|
||||
> Iterate
|
||||
|
||||
> ... for k = 0,1,...,K, where K is the first instance of k where
|
||||
> ... for k = 0,1,...,K, where K is the first instance of k where
|
||||
> either q_{k+1} > Q or b_{k+1} is undefined (b_k = a_k).
|
||||
|
||||
```
|
||||
while(Q_1 < D) {
|
||||
while(Q_1 < D) {
|
||||
```
|
||||
|
||||
> a_k = [b_k], i.e., the greatest integer <= b_k
|
||||
|
||||
```
|
||||
A = B|0;
|
||||
A = B|0;
|
||||
```
|
||||
|
||||
> p_k = a_k p_{k-1} + p_{k-2}
|
||||
> q_k = a_k q_{k-1} + q_{k-2}
|
||||
|
||||
```
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
P = A * P_1 + P_2;
|
||||
Q = A * Q_1 + Q_2;
|
||||
```
|
||||
|
||||
> b_{k+1} = (b_{k} - a_{k})^{-1}
|
||||
> b_{k+1} = (b_{k} - a_{k})^{-1}
|
||||
|
||||
```
|
||||
if((B - A) < 0.0000000001) break;
|
||||
if((B - A) < 0.0000000005) break;
|
||||
```
|
||||
|
||||
At the end of each iteration, advance `k` by one step:
|
||||
|
||||
```
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
}
|
||||
```
|
||||
B = 1 / (B - A);
|
||||
P_2 = P_1; P_1 = P;
|
||||
Q_2 = Q_1; Q_1 = Q;
|
||||
}
|
||||
```
|
||||
|
||||
In case we end up overstepping, walk back an iteration or two:
|
||||
In case we end up overstepping, walk back an iteration or two:
|
||||
|
||||
```
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
if(Q > D) { Q = Q_1; P = P_1; }
|
||||
if(Q > D) { Q = Q_2; P = P_2; }
|
||||
```
|
||||
|
||||
The final result is `r = (sgn x)p_k / q_k`:
|
||||
|
||||
```
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
if(!mixed) return [0, sgn * P, Q];
|
||||
var q = Math.floor(sgn * P/Q);
|
||||
return [q, sgn*P - q*Q, Q];
|
||||
};
|
||||
```
|
||||
|
||||
@ -163,34 +163,44 @@ if(typeof module !== 'undefined') module.exports = frac;
|
||||
var fs = require('fs'), assert = require('assert');
|
||||
var frac;
|
||||
describe('source', function() { it('should load', function() { frac = require('./'); }); });
|
||||
var xltestfiles=[
|
||||
['xl.00001.tsv', 10000],
|
||||
['xl.0001.tsv', 10000],
|
||||
['xl.001.tsv', 10000],
|
||||
['xl.01.tsv', 10000]
|
||||
];
|
||||
|
||||
function line(o,j,m) {
|
||||
it(j, function(done) {
|
||||
var d, q, qq;
|
||||
for(var i = j*100; i < m-3 && i < (j+1)*100; ++i) {
|
||||
d = o[i].split("\t");
|
||||
function xlline(o,j,m,w) {
|
||||
it(j, function(done) {
|
||||
var d, q, qq;
|
||||
for(var i = j*w; i < m-3 && i < (j+1)*w; ++i) {
|
||||
d = o[i].split("\t");
|
||||
|
||||
q = frac.cont(Number(d[0]), 9, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? q[1] + "/" + q[2] : " ") : "0 ";
|
||||
assert.equal(qq, d[1], d[1] + " 1");
|
||||
q = frac.cont(Number(d[0]), 9, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? q[1] + "/" + q[2] : " ") : "0 ";
|
||||
assert.equal(qq, d[1], d[1] + " 1");
|
||||
|
||||
q = frac.cont(Number(d[0]), 99, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") : " ") : "0 ";
|
||||
assert.equal(qq, d[2], d[2] + " 2");
|
||||
q = frac.cont(Number(d[0]), 99, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") : " ") : "0 ";
|
||||
assert.equal(qq, d[2], d[2] + " 2");
|
||||
|
||||
q = frac.cont(Number(d[0]), 999, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 100 ? " " : "") + (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") + (q[2]<100?" ":""): " ") : "0 ";
|
||||
assert.equal(qq, d[3], d[3] + " 3");
|
||||
}
|
||||
done();
|
||||
});
|
||||
q = frac.cont(Number(d[0]), 999, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 100 ? " " : "") + (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") + (q[2]<100?" ":""): " ") : "0 ";
|
||||
assert.equal(qq, d[3], d[3] + " 3");
|
||||
}
|
||||
done();
|
||||
});
|
||||
}
|
||||
function parsetest(o) {
|
||||
for(var j = 0, m = o.length-3; j < m/100; ++j) line(o,j,m);
|
||||
function parsexl(f,w) {
|
||||
if(!fs.existsSync(f)) return;
|
||||
var o = fs.readFileSync(f, 'utf-8').split("\n");
|
||||
for(var j = 0, m = o.length-3; j < m/w; ++j) xlline(o,j,m,w);
|
||||
}
|
||||
describe('xl.00001.tsv', function() {
|
||||
var o = fs.readFileSync('./test_files/xl.00001.tsv', 'utf-8').split("\n");
|
||||
parsetest(o);
|
||||
xltestfiles.forEach(function(x) {
|
||||
var f = './test_files/' + x[0];
|
||||
describe(x[0], function() {
|
||||
parsexl(f,x[1]);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
@ -201,7 +211,7 @@ frac.js: frac.md
|
||||
voc frac.md
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
test:
|
||||
mocha -R spec
|
||||
```
|
||||
|
||||
@ -209,24 +219,32 @@ test:
|
||||
|
||||
```json>package.json
|
||||
{
|
||||
"name": "frac",
|
||||
"version": "0.2.1",
|
||||
"author": "SheetJS",
|
||||
"description": "Rational approximation with bounded denominator",
|
||||
"keywords": [ "math", "fraction", "rational", "approximation" ],
|
||||
"main": "./frac.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {"mocha":""},
|
||||
"repository": {
|
||||
"type":"git",
|
||||
"url": "git://github.com/SheetJS/frac.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test"
|
||||
},
|
||||
"bugs": { "url": "https://github.com/SheetJS/frac/issues" },
|
||||
"engines": { "node": ">=0.8" }
|
||||
"name": "frac",
|
||||
"version": "0.3.0",
|
||||
"author": "SheetJS",
|
||||
"description": "Rational approximation with bounded denominator",
|
||||
"keywords": [ "math", "fraction", "rational", "approximation" ],
|
||||
"main": "./frac.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {"mocha":"","voc":""},
|
||||
"repository": {
|
||||
"type":"git",
|
||||
"url": "git://github.com/SheetJS/frac.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test"
|
||||
},
|
||||
"bugs": { "url": "https://github.com/SheetJS/frac/issues" },
|
||||
"engines": { "node": ">=0.8" }
|
||||
}
|
||||
```
|
||||
|
||||
And to make sure that test files are not included in npm:
|
||||
```>.npmignore
|
||||
./test_files
|
||||
```
|
||||
|
||||
```>.gitignore
|
||||
.gitignore
|
||||
.npmignore
|
||||
```
|
||||
|
34
package.json
34
package.json
@ -1,19 +1,19 @@
|
||||
{
|
||||
"name": "frac",
|
||||
"version": "0.2.1",
|
||||
"author": "SheetJS",
|
||||
"description": "Rational approximation with bounded denominator",
|
||||
"keywords": [ "math", "fraction", "rational", "approximation" ],
|
||||
"main": "./frac.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {"mocha":""},
|
||||
"repository": {
|
||||
"type":"git",
|
||||
"url": "git://github.com/SheetJS/frac.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test"
|
||||
},
|
||||
"bugs": { "url": "https://github.com/SheetJS/frac/issues" },
|
||||
"engines": { "node": ">=0.8" }
|
||||
"name": "frac",
|
||||
"version": "0.3.0",
|
||||
"author": "SheetJS",
|
||||
"description": "Rational approximation with bounded denominator",
|
||||
"keywords": [ "math", "fraction", "rational", "approximation" ],
|
||||
"main": "./frac.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {"mocha":"","voc":""},
|
||||
"repository": {
|
||||
"type":"git",
|
||||
"url": "git://github.com/SheetJS/frac.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "make test"
|
||||
},
|
||||
"bugs": { "url": "https://github.com/SheetJS/frac/issues" },
|
||||
"engines": { "node": ">=0.8" }
|
||||
}
|
||||
|
54
test.js
54
test.js
@ -1,32 +1,42 @@
|
||||
var fs = require('fs'), assert = require('assert');
|
||||
var frac;
|
||||
describe('source', function() { it('should load', function() { frac = require('./'); }); });
|
||||
var xltestfiles=[
|
||||
['xl.00001.tsv', 10000],
|
||||
['xl.0001.tsv', 10000],
|
||||
['xl.001.tsv', 10000],
|
||||
['xl.01.tsv', 10000]
|
||||
];
|
||||
|
||||
function line(o,j,m) {
|
||||
it(j, function(done) {
|
||||
var d, q, qq;
|
||||
for(var i = j*100; i < m-3 && i < (j+1)*100; ++i) {
|
||||
d = o[i].split("\t");
|
||||
function xlline(o,j,m,w) {
|
||||
it(j, function(done) {
|
||||
var d, q, qq;
|
||||
for(var i = j*w; i < m-3 && i < (j+1)*w; ++i) {
|
||||
d = o[i].split("\t");
|
||||
|
||||
q = frac.cont(Number(d[0]), 9, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? q[1] + "/" + q[2] : " ") : "0 ";
|
||||
assert.equal(qq, d[1], d[1] + " 1");
|
||||
q = frac.cont(Number(d[0]), 9, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? q[1] + "/" + q[2] : " ") : "0 ";
|
||||
assert.equal(qq, d[1], d[1] + " 1");
|
||||
|
||||
q = frac.cont(Number(d[0]), 99, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") : " ") : "0 ";
|
||||
assert.equal(qq, d[2], d[2] + " 2");
|
||||
q = frac.cont(Number(d[0]), 99, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") : " ") : "0 ";
|
||||
assert.equal(qq, d[2], d[2] + " 2");
|
||||
|
||||
q = frac.cont(Number(d[0]), 999, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 100 ? " " : "") + (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") + (q[2]<100?" ":""): " ") : "0 ";
|
||||
assert.equal(qq, d[3], d[3] + " 3");
|
||||
}
|
||||
done();
|
||||
});
|
||||
q = frac.cont(Number(d[0]), 999, true);
|
||||
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? (q[1] < 100 ? " " : "") + (q[1] < 10 ? " " : "") + q[1] + "/" + q[2] + (q[2]<10?" ":"") + (q[2]<100?" ":""): " ") : "0 ";
|
||||
assert.equal(qq, d[3], d[3] + " 3");
|
||||
}
|
||||
done();
|
||||
});
|
||||
}
|
||||
function parsetest(o) {
|
||||
for(var j = 0, m = o.length-3; j < m/100; ++j) line(o,j,m);
|
||||
function parsexl(f,w) {
|
||||
if(!fs.existsSync(f)) return;
|
||||
var o = fs.readFileSync(f, 'utf-8').split("\n");
|
||||
for(var j = 0, m = o.length-3; j < m/w; ++j) xlline(o,j,m,w);
|
||||
}
|
||||
describe('xl.00001.tsv', function() {
|
||||
var o = fs.readFileSync('./test_files/xl.00001.tsv', 'utf-8').split("\n");
|
||||
parsetest(o);
|
||||
xltestfiles.forEach(function(x) {
|
||||
var f = './test_files/' + x[0];
|
||||
describe(x[0], function() {
|
||||
parsexl(f,x[1]);
|
||||
});
|
||||
});
|
||||
|
848576
test_files/xl.00001.tsv
848576
test_files/xl.00001.tsv
File diff suppressed because it is too large
Load Diff
1048576
test_files/xl.0001.tsv
Normal file
1048576
test_files/xl.0001.tsv
Normal file
File diff suppressed because it is too large
Load Diff
1048576
test_files/xl.001.tsv
Normal file
1048576
test_files/xl.001.tsv
Normal file
File diff suppressed because it is too large
Load Diff
1048576
test_files/xl.01.tsv
Normal file
1048576
test_files/xl.01.tsv
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user