version bump 1.0.5: adjusting tolerance

This commit is contained in:
SheetJS 2016-09-23 01:43:23 -04:00
parent 63e6cf4bb3
commit 93ff7f307a
16 changed files with 161 additions and 89 deletions

@ -1,13 +1,14 @@
language: node_js
node_js:
- "5.0"
- "6"
- "5"
- "4.2"
- "0.12"
- "0.10"
- "0.8"
before_install:
- "npm install -g npm@next"
- "npm install -g mocha"
- "npm install -g mocha voc"
- "npm install blanket"
- "npm install coveralls mocha-lcov-reporter"
after_success:

@ -2,56 +2,57 @@ LIB=frac
REQS=
ADDONS=
AUXTARGETS=
HTMLLINT=index.html
ULIB=$(shell echo $(LIB) | tr a-z A-Z)
DEPS=$(LIB).md
TARGET=$(LIB).js
FLOWTARGET=$(LIB).flow.js
## Main Targets
.PHONY: all
all: $(TARGET) $(AUXTARGETS)
all: $(TARGET) $(AUXTARGETS) ## Build library and auxiliary scripts
$(TARGET) $(AUXTARGETS): %.js : %.flow.js
node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^\s*\/\*:[^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*:[^*]*\*\//gm,""))' > $@
node -e 'process.stdout.write(require("fs").readFileSync("$<","utf8").replace(/^[ \t]*\/\*[:#][^*]*\*\/\s*(\n)?/gm,"").replace(/\/\*[:#][^*]*\*\//gm,""))' > $@
$(LIB).flow.js: $(DEPS)
$(FLOWTARGET): $(DEPS)
voc $^
.PHONY: clean
clean:
rm -f $(TARGET)
clean: ## Remove targets and build artifacts
rm -f $(TARGET) $(FLOWTARGET)
## JavaScript
.PHONY: test mocha
test mocha: test.js
test mocha: test.js $(TARGET) ## Run JS test suite
mocha -R spec -t 20000
.PHONY: lint
lint: $(TARGET) $(AUXTARGETS)
jshint --show-non-errors $(TARGET) $(AUXTARGETS)
jshint --show-non-errors package.json
jscs $(TARGET) $(AUXTARGETS)
lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
@jshint --show-non-errors $(TARGET) $(AUXTARGETS)
@jshint --show-non-errors package.json
@jshint --show-non-errors --extract=always $(HTMLLINT)
@jscs $(TARGET) $(AUXTARGETS)
.PHONY: flow
flow: lint
flow check --all --show-all-errors
flow: lint ## Run flow checker
@flow check --all --show-all-errors
.PHONY: cov cov-spin
cov: misc/coverage.html
cov-spin:
make cov & bash misc/spin.sh $$!
.PHONY: cov
cov: misc/coverage.html ## Run coverage test
misc/coverage.html: $(TARGET) test.js
mocha --require blanket -R html-cov -t 20000 > $@
.PHONY: coveralls coveralls-spin
coveralls:
mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | ./node_modules/coveralls/bin/coveralls.js
coveralls-spin:
make coveralls & bash misc/spin.sh $$!
.PHONY: coveralls
coveralls: ## Coverage Test + Send to coveralls.io
mocha --require blanket --reporter mocha-lcov-reporter -t 20000 | node ./node_modules/coveralls/bin/coveralls.js
.PHONY: dist
dist: dist-deps $(TARGET)
dist: dist-deps $(TARGET) ## Prepare JS files for distribution
cp $(TARGET) dist/
cp LICENSE dist/
uglifyjs $(TARGET) -o dist/$(LIB).min.js --source-map dist/$(LIB).min.map --preamble "$$(head -n 1 frac.js)"
@ -65,16 +66,24 @@ dist-deps:
## Python
.PHONY: pylint
pylint: frac.py $(wildcard test_*.py)
pylint: frac.py $(wildcard test_*.py) ## Run pep8 check
pep8 $^
.PHONY: pypi
pypi: frac.py
pydist: frac.py ## Upload Python module to PyPI
python setup.py sdist upload
.PHONY: pytest pypytest
pytest: pylint
pytest: pylint ## Run Python test suite
py.test -v --durations=5
pypytest: pylint
pypytest: pylint ## Run Python test suite in pypy
pypy $$(which py.test) -v --durations=5
.PHONY: help
help:
@grep -hE '(^[a-zA-Z_-][ a-zA-Z_-]*:.*?|^#[#*])' $(MAKEFILE_LIST) | bash misc/help.sh
#* To show a spinner, append "-spin" to any target e.g. cov-spin
%-spin:
@make $* & bash misc/spin.sh $$!

@ -7,17 +7,22 @@ Uses the [Mediant Method](https://en.wikipedia.org/wiki/Mediant_method).
This module also provides an implementation of the continued fraction method as
described by Aberth in "A method for exact computation with rational numbers".
## Installation
### JS
With [npm](https://www.npmjs.org/package/frac):
$ npm install frac
```bash
$ npm install frac
```
In the browser:
<script src="frac.js"></script>
```html
<script src="frac.js"></script>
```
The script will manipulate `module.exports` if available (e.g. in a CommonJS
`require` context). This is not always desirable. To prevent the behavior,
@ -27,7 +32,9 @@ define `DO_NOT_EXPORT_FRAC`
From [PyPI](https://pypi.python.org/pypi/frac):
$ pip install frac
```bash
$ pip install frac
```
## Usage
@ -67,33 +74,37 @@ For example:
`frac.med` implements Mediant method.
`frac.cont` implements Aberth algorithm
`frac.cont` implements Aberth algorithm.
For example:
```py
>>> import frac
>>> frac.med(1.3, 9) # [ 0, 9, 7 ]
>>> frac.med(1.3, 9, True) # [ 1, 2, 7 ]
>>> frac.med(-1.3, 9) # [ 0, -9, 7 ]
>>> frac.med(-1.3, 9, True) # [ -2, 5, 7 ]
>>> frac.med(1.3, 9) ## [ 0, 9, 7 ] ## 1.3 ~ 9/7
>>> frac.med(1.3, 9, True) ## [ 1, 2, 7 ] ## 1.3 ~ 1 + 2/7
>>> frac.med(-1.3, 9) ## [ 0, -9, 7 ] ## -1.3 ~ -9/7
>>> frac.med(-1.3, 9, True) ## [ -2, 5, 7 ] ## -1.3 ~ -2 + 5/7
>>> frac.cont(1.3, 9) # [ 0, 4, 3 ]
>>> frac.cont(1.3, 9, True) # [ 1, 1, 3 ]
>>> frac.cont(-1.3, 9) # [ 0, -4, 3 ]
>>> frac.cont(-1.3, 9, True) # [ -2, 2, 3 ]
>>> frac.cont(1.3, 9) ## [ 0, 4, 3 ] ## 1.3 ~ 4/3
>>> frac.cont(1.3, 9, True) ## [ 1, 1, 3 ] ## 1.3 ~ 1 + 1/3
>>> frac.cont(-1.3, 9) ## [ 0, -4, 3 ] ## -1.3 ~ -4/3
>>> frac.cont(-1.3, 9, True) ## [ -2, 2, 3 ] ## -1.3 ~ -2 + 2/3
```
## Testing
`make test` will run the node-based tests.
Tests generated from Excel have 4 columns. To produce a similar test:
The test TSV baselines in the `test_files` directory have four columns:
- 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)"
- Column B format "Up to one digit (1/4)" (`denominator = 9`)
- Column C format "Up to two digits (21/25)" (`denominator = 99`)
- Column D format "Up to three digits (312/943)" (`denominator = 999`)
`make test` will run the node-based tests.
`make pytest` will run the python tests against the system Python version.
`make pypytest` will run the python tests against `pypy` if installed
## License

4
dist/frac.js vendored

@ -1,5 +1,5 @@
/* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */
var frac = function(x, D, mixed) {
var frac = function frac(x, D, mixed) {
var n1 = Math.floor(x), d1 = 1;
var n2 = n1+1, d2 = 1;
if(x !== n1) while(d1 <= D && d2 <= D) {
@ -28,7 +28,7 @@ frac.cont = function cont(x, D, mixed) {
A = Math.floor(B);
P = A * P_1 + P_2;
Q = A * Q_1 + Q_2;
if((B - A) < 0.000000005) break;
if((B - A) < 0.00000005) break;
B = 1 / (B - A);
P_2 = P_1; P_1 = P;
Q_2 = Q_1; Q_1 = Q;

3
dist/frac.min.js vendored

@ -1 +1,2 @@
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}}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=Math.floor(B);while(Q_1<D){A=Math.floor(B);P=A*P_1+P_2;Q=A*Q_1+Q_2;if(B-A<5e-9)break;B=1/(B-A);P_2=P_1;P_1=P;Q_2=Q_1;Q_1=Q}if(Q>D){if(Q_1>D){Q=Q_2;P=P_2}else{Q=Q_1;P=P_1}}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"&&typeof DO_NOT_EXPORT_FRAC==="undefined")module.exports=frac;
/* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */
var frac=function frac(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}}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=Math.floor(B);while(Q_1<D){A=Math.floor(B);P=A*P_1+P_2;Q=A*Q_1+Q_2;if(B-A<5e-8)break;B=1/(B-A);P_2=P_1;P_1=P;Q_2=Q_1;Q_1=Q}if(Q>D){if(Q_1>D){Q=Q_2;P=P_2}else{Q=Q_1;P=P_1}}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"&&typeof DO_NOT_EXPORT_FRAC==="undefined")module.exports=frac;

2
dist/frac.min.map vendored

@ -1 +1 @@
{"version":3,"file":"dist/frac.min.js","sources":["frac.js"],"names":["frac","x","D","mixed","n1","Math","floor","d1","n2","d2","m","q","cont","sgn","B","P_2","P_1","P","Q_2","Q_1","Q","A","module","DO_NOT_EXPORT_FRAC","exports"],"mappings":"AACA,GAAIA,MAAO,SAASC,EAAGC,EAAGC,OACxB,GAAIC,IAAKC,KAAKC,MAAML,GAAIM,GAAK,CAC7B,IAAIC,IAAKJ,GAAG,EAAGK,GAAK,CACpB,IAAGR,IAAMG,GAAI,MAAMG,IAAML,GAAKO,IAAMP,EAAG,CACrC,GAAIQ,IAAKN,GAAKI,KAAOD,GAAKE,GAC1B,IAAGR,IAAMS,EAAG,CACV,GAAGH,GAAKE,IAAMP,EAAG,CAAEK,IAAIE,EAAIL,KAAII,EAAIC,IAAGP,EAAE,MACnC,IAAGK,GAAKE,GAAIA,GAAGP,EAAE,MACjBK,IAAGL,EAAE,CACV,WAEG,IAAGD,EAAIS,EAAG,CAAEF,GAAKJ,GAAGI,EAAIC,IAAKF,GAAGE,OAChC,CAAEL,GAAKA,GAAGI,EAAID,IAAKA,GAAGE,IAE7B,GAAGF,GAAKL,EAAG,CAAEK,GAAKE,EAAIL,IAAKI,GAC3B,IAAIL,MAAO,OAAQ,EAAGC,GAAIG,GAC1B,IAAII,GAAIN,KAAKC,MAAMF,GAAGG,GACtB,QAAQI,EAAGP,GAAKO,EAAEJ,GAAIA,IAExBP,MAAKY,KAAO,QAASA,MAAKX,EAAGC,EAAGC,OAC9B,GAAIU,KAAMZ,EAAI,GAAK,EAAI,CACvB,IAAIa,GAAIb,EAAIY,GACZ,IAAIE,KAAM,EAAGC,IAAM,EAAGC,EAAI,CAC1B,IAAIC,KAAM,EAAGC,IAAM,EAAGC,EAAI,CAC1B,IAAIC,GAAIhB,KAAKC,MAAMQ,EACnB,OAAMK,IAAMjB,EAAG,CACbmB,EAAIhB,KAAKC,MAAMQ,EACfG,GAAII,EAAIL,IAAMD,GACdK,GAAIC,EAAIF,IAAMD,GACd,IAAIJ,EAAIO,EAAK,KAAa,KAC1BP,GAAI,GAAKA,EAAIO,EACbN,KAAMC,GAAKA,KAAMC,CACjBC,KAAMC,GAAKA,KAAMC,EAEnB,GAAGA,EAAIlB,EAAG,CAAE,GAAGiB,IAAMjB,EAAG,CAAEkB,EAAIF,GAAKD,GAAIF,QAAY,CAAEK,EAAID,GAAKF,GAAID,KAClE,IAAIb,MAAO,OAAQ,EAAGU,IAAMI,EAAGG,EAC/B,IAAIT,GAAIN,KAAKC,MAAMO,IAAMI,EAAEG,EAC3B,QAAQT,EAAGE,IAAII,EAAIN,EAAES,EAAGA,GAE1B,UAAUE,UAAW,mBAAsBC,sBAAuB,YAAaD,OAAOE,QAAUxB"}
{"version":3,"sources":["frac.js"],"names":["frac","x","D","mixed","n1","Math","floor","d1","n2","d2","m","q","cont","sgn","B","P_2","P_1","P","Q_2","Q_1","Q","A","module","DO_NOT_EXPORT_FRAC","exports"],"mappings":";AACA,GAAIA,MAAO,QAASA,MAAKC,EAAGC,EAAGC,OAC7B,GAAIC,IAAKC,KAAKC,MAAML,GAAIM,GAAK,CAC7B,IAAIC,IAAKJ,GAAG,EAAGK,GAAK,CACpB,IAAGR,IAAMG,GAAI,MAAMG,IAAML,GAAKO,IAAMP,EAAG,CACrC,GAAIQ,IAAKN,GAAKI,KAAOD,GAAKE,GAC1B,IAAGR,IAAMS,EAAG,CACV,GAAGH,GAAKE,IAAMP,EAAG,CAAEK,IAAIE,EAAIL,KAAII,EAAIC,IAAGP,EAAE,MACnC,IAAGK,GAAKE,GAAIA,GAAGP,EAAE,MACjBK,IAAGL,EAAE,CACV,WAEG,IAAGD,EAAIS,EAAG,CAAEF,GAAKJ,GAAGI,EAAIC,IAAKF,GAAGE,OAChC,CAAEL,GAAKA,GAAGI,EAAID,IAAKA,GAAGE,IAE7B,GAAGF,GAAKL,EAAG,CAAEK,GAAKE,EAAIL,IAAKI,GAC3B,IAAIL,MAAO,OAAQ,EAAGC,GAAIG,GAC1B,IAAII,GAAIN,KAAKC,MAAMF,GAAGG,GACtB,QAAQI,EAAGP,GAAKO,EAAEJ,GAAIA,IAExBP,MAAKY,KAAO,QAASA,MAAKX,EAAGC,EAAGC,OAC9B,GAAIU,KAAMZ,EAAI,GAAK,EAAI,CACvB,IAAIa,GAAIb,EAAIY,GACZ,IAAIE,KAAM,EAAGC,IAAM,EAAGC,EAAI,CAC1B,IAAIC,KAAM,EAAGC,IAAM,EAAGC,EAAI,CAC1B,IAAIC,GAAIhB,KAAKC,MAAMQ,EACnB,OAAMK,IAAMjB,EAAG,CACbmB,EAAIhB,KAAKC,MAAMQ,EACfG,GAAII,EAAIL,IAAMD,GACdK,GAAIC,EAAIF,IAAMD,GACd,IAAIJ,EAAIO,EAAK,KAAY,KACzBP,GAAI,GAAKA,EAAIO,EACbN,KAAMC,GAAKA,KAAMC,CACjBC,KAAMC,GAAKA,KAAMC,EAEnB,GAAGA,EAAIlB,EAAG,CAAE,GAAGiB,IAAMjB,EAAG,CAAEkB,EAAIF,GAAKD,GAAIF,QAAY,CAAEK,EAAID,GAAKF,GAAID,KAClE,IAAIb,MAAO,OAAQ,EAAGU,IAAMI,EAAGG,EAC/B,IAAIT,GAAIN,KAAKC,MAAMO,IAAMI,EAAEG,EAC3B,QAAQT,EAAGE,IAAII,EAAIN,EAAES,EAAGA,GAE1B,UAAUE,UAAW,mBAAsBC,sBAAuB,YAAaD,OAAOE,QAAUxB","file":"dist/frac.min.js"}

@ -1,5 +1,5 @@
/* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */
var frac = function(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
var frac = function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
var n1 = Math.floor(x), d1 = 1;
var n2 = n1+1, d2 = 1;
if(x !== n1) while(d1 <= D && d2 <= D) {
@ -28,7 +28,7 @@ frac.cont = function cont(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Arra
A = Math.floor(B);
P = A * P_1 + P_2;
Q = A * Q_1 + Q_2;
if((B - A) < 0.000000005) break;
if((B - A) < 0.00000005) break;
B = 1 / (B - A);
P_2 = P_1; P_1 = P;
Q_2 = Q_1; Q_1 = Q;

@ -1,5 +1,5 @@
/* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */
var frac = function(x, D, mixed) {
var frac = function frac(x, D, mixed) {
var n1 = Math.floor(x), d1 = 1;
var n2 = n1+1, d2 = 1;
if(x !== n1) while(d1 <= D && d2 <= D) {
@ -28,7 +28,7 @@ frac.cont = function cont(x, D, mixed) {
A = Math.floor(B);
P = A * P_1 + P_2;
Q = A * Q_1 + Q_2;
if((B - A) < 0.000000005) break;
if((B - A) < 0.00000005) break;
B = 1 / (B - A);
P_2 = P_1; P_1 = P;
Q_2 = Q_1; Q_1 = Q;

46
frac.md

@ -23,7 +23,7 @@ that behavior, pass the absolute value to frac and prepend a "-" if negative.
```js>frac.flow.js
/* frac.js (C) 2012-present SheetJS -- http://sheetjs.com */
var frac = function(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
var frac = function frac(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
```
The goal is to maintain a feasible fraction (with bounded denominator) below
@ -91,7 +91,7 @@ to the desired goal of most accurately approximating the floating point number)
frac.cont = function cont(x/*:number*/, D/*:number*/, mixed/*:?boolean*/)/*:Array<number>*/ {
```
> Record the sign of x, take b0=|x|, p_{-2}=0, p_{-1}=1, q_{-2}=1, q_{-1}=0
> Record the sign of x, take `b0=|x|, p_{-2}=0, p_{-1}=1, q_{-2}=1, q_{-1}=0`
Note that the variables are implicitly indexed at `k` (so `B` refers to `b_k`):
@ -102,8 +102,8 @@ Note that the variables are implicitly indexed at `k` (so `B` refers to `b_k`):
var Q_2 = 1, Q_1 = 0, Q = 0;
```
`A` should be the floor of `B`. Originally the bit-or trick was used, but this is not correct
for the range `B>=2**32`.
`A` should be the floor of `B`. Originally the bit-or trick was used, but this
is not correct for the range `B>=2**32`.
```
var A = Math.floor(B);
@ -111,31 +111,31 @@ for the range `B>=2**32`.
> Iterate
> ... 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).
> ... 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) {
```
> a_k = [b_k], i.e., the greatest integer <= b_k
> `a_k = [b_k]`, i.e., the greatest integer `<= b_k`
```
A = Math.floor(B);
```
> p_k = a_k p_{k-1} + p_{k-2}
> q_k = a_k q_{k-1} + q_{k-2}
> `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;
```
> b_{k+1} = (b_{k} - a_{k})^{-1}
> `b_{k+1} = (b_{k} - a_{k})^{-1}`
```
if((B - A) < 0.000000005) break;
if((B - A) < 0.00000005) break;
```
At the end of each iteration, advance `k` by one step:
@ -184,21 +184,25 @@ var xltestfiles=[
];
function xlline(o,j,m,w) {
it(j, function() {
var d, q, qq;
it(j.toString(), function() {
var d, q, qq, f = 0.1;
var q0 = 0, q1 = 0, q2 = 0
for(var i = j*w; i < m-3 && i < (j+1)*w; ++i) {
d = o[i].split("\t");
if(d.length < 3) continue;
f = parseFloat(d[0]);
q = frac.cont(Number(d[0]), 9, true);
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? q[1] + "/" + q[2] : " ") : "0 ";
q = frac.cont(f, 9, true);
q0 = q[0]; q1 = q[1]; q2 = q[2];
qq = (q0!=0||q1!=0) ? (q0!=0 ? q0.toString() : "") + " " + (q1!=0 ? q1.toString() + "/" + q2.toString() : " ") : "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 ";
q = frac.cont(f, 99, true);
qq = (q[0]!=0||q[1]!=0) ? (q[0]!=0 ? q[0].toString() : "") + " " + (q[1]!=0 ? (q[1] < 10 ? " " : "") + q[1].toString() + "/" + q[2].toString() + (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 ";
q = frac.cont(f, 999, true);
qq = (q[0]!=0||q[1]!=0) ? (q[0]!=0 ? q[0].toString() : "") + " " + (q[1]!=0 ? (q[1] < 100 ? " " : "") + (q[1] < 10 ? " " : "") + q[1].toString() + "/" + q[2].toString() + (q[2]<10?" ":"") + (q[2]<100?" ":""): " ") : "0 ";
assert.equal(qq, d[3], d[3] + " 3");
}
});
@ -239,7 +243,7 @@ xltestfiles.forEach(function(x) {
```json>package.json
{
"name": "frac",
"version": "1.0.4",
"version": "1.0.5",
"author": "SheetJS",
"description": "Rational approximation with bounded denominator",
"keywords": [ "math", "fraction", "rational", "approximation" ],
@ -252,7 +256,7 @@ xltestfiles.forEach(function(x) {
},
"repository": { "type":"git", "url":"git://github.com/SheetJS/frac.git" },
"scripts": {
"test": "mocha -R spec"
"test": "make test"
},
"config": {
"blanket": {

@ -55,7 +55,7 @@ def cont(x, D, mixed=False):
A = I(B)
P = A * P_1 + P_2
Q = A * Q_1 + Q_2
if (B - A) < 0.0000000005:
if (B - A) < 0.00000005:
break
B = 1. / (B-A)
P_2, P_1 = P_1, P

@ -21,6 +21,7 @@
</table>
</body>
<script>
/*jshint browser:true */
var V = document.getElementById('val');
var F = document.getElementById('fmt');
var X = document.getElementById('mix');

42
misc/help.sh Executable file

@ -0,0 +1,42 @@
#!/bin/bash
# make_help.sh -- process listing of targets and special items in Makefile
# Copyright (C) 2016-present SheetJS
#
# usage in makefile: pipe the output of the following command:
# @grep -hE '(^[a-zA-Z_-][ a-zA-Z_-]*:.*?|^#[#*])' $(MAKEFILE_LIST)
#
# lines starting with "## " are treated as subtitles
# lines starting with "#* " are treated as plaintext comments
# multiple targets with "## " after the ":" are rendered as separate targets
# if the presumed default target is labeled, it will be assigned a unique color
awk '
BEGIN{recipes=0;}
!/#[#*] .*$/ {next;}
{multi=0; isrecipe=0;}
/^[^#]*:/ {isrecipe=1; ++recipes;}
/^[^ :]* .*:/ {multi=1}
multi==0 && isrecipe>0 { if(recipes > 1) print; else print $0, "[default]"; next}
isrecipe == 0 {print; next}
multi>0 {
k=split($0, msg, "##"); m=split($0, a, ":"); n=split(a[1], b, " ");
for(i=1; i<=n; ++i) print b[i] ":", "##" msg[2], (recipes==1 && i==1 ? "[default]" : "")
}
END {}
' | if [[ -t 1 ]]; then
awk '
BEGIN {FS = ":.*?## "}
{color=36}
/\[default\]/ {color=35}
NF==1 && /^##/ {color=34}
NF==1 && /^#\*/ {color=20; $1 = substr($1, 4)}
{printf "\033[" color "m%-20s\033[0m %s\n", $1, $2;}
END{}' -
else
awk '
BEGIN {FS = ":.*?## "}
/^#\* / {$1 = substr($1, 4)}
{printf "%-20s %s\n", $1, $2;}
END{}' -
fi

@ -1,6 +1,6 @@
{
"name": "frac",
"version": "1.0.4",
"version": "1.0.5",
"author": "SheetJS",
"description": "Rational approximation with bounded denominator",
"keywords": [ "math", "fraction", "rational", "approximation" ],
@ -13,7 +13,7 @@
},
"repository": { "type":"git", "url":"git://github.com/SheetJS/frac.git" },
"scripts": {
"test": "mocha -R spec"
"test": "make test"
},
"config": {
"blanket": {

@ -1,7 +1,7 @@
from distutils.core import setup
setup(
name='frac',
version='1.0.2',
version='1.0.5',
author='SheetJS',
author_email='dev@sheetjs.com',
url='http://oss.sheetjs.com/frac',

20
test.js

@ -10,21 +10,25 @@ var xltestfiles=[
];
function xlline(o,j,m,w) {
it(j, function() {
var d, q, qq;
it(j.toString(), function() {
var d, q, qq, f = 0.1;
var q0 = 0, q1 = 0, q2 = 0
for(var i = j*w; i < m-3 && i < (j+1)*w; ++i) {
d = o[i].split("\t");
if(d.length < 3) continue;
f = parseFloat(d[0]);
q = frac.cont(Number(d[0]), 9, true);
qq = (q[0]||q[1]) ? (q[0] || "") + " " + (q[1] ? q[1] + "/" + q[2] : " ") : "0 ";
q = frac.cont(f, 9, true);
q0 = q[0]; q1 = q[1]; q2 = q[2];
qq = (q0!=0||q1!=0) ? (q0!=0 ? q0.toString() : "") + " " + (q1!=0 ? q1.toString() + "/" + q2.toString() : " ") : "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 ";
q = frac.cont(f, 99, true);
qq = (q[0]!=0||q[1]!=0) ? (q[0]!=0 ? q[0].toString() : "") + " " + (q[1]!=0 ? (q[1] < 10 ? " " : "") + q[1].toString() + "/" + q[2].toString() + (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 ";
q = frac.cont(f, 999, true);
qq = (q[0]!=0||q[1]!=0) ? (q[0]!=0 ? q[0].toString() : "") + " " + (q[1]!=0 ? (q[1] < 100 ? " " : "") + (q[1] < 10 ? " " : "") + q[1].toString() + "/" + q[2].toString() + (q[2]<10?" ":"") + (q[2]<100?" ":""): " ") : "0 ";
assert.equal(qq, d[3], d[3] + " 3");
}
});

@ -123,4 +123,3 @@
1234567892.2 1234567892 1/5 1234567892 1/5 1234567892 1/5
1234567892.3 1234567892 2/7 1234567892 3/10 1234567892 3/10
1234567892.4 1234567892 2/5 1234567892 2/5 1234567892 2/5

1 12345678900000 12345678900000 12345678900000 12345678900000
123 1234567892.2 1234567892 1/5 1234567892 1/5 1234567892 1/5
124 1234567892.3 1234567892 2/7 1234567892 3/10 1234567892 3/10
125 1234567892.4 1234567892 2/5 1234567892 2/5 1234567892 2/5