From 6ba3097766e39ab68cb3d04e4c8b81b6f51a29c5 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Sat, 21 May 2011 12:56:06 -0700 Subject: [PATCH] Add d3.bisect. This is similar to pv.search, but more closely modeled after Python's bisect methods to provide the desired flexibility in searching slices of arrays. This includes good tests for bisect, and better tests for polylinear and quantile scales (both of which now use bisect). --- Makefile | 3 + d3.js | 78 ++++++++++------ d3.layout.js | 44 ++++----- d3.layout.min.js | 2 +- d3.min.js | 4 +- examples/histogram/histogram.html | 69 ++++++++++----- src/core/bisect.js | 38 ++++++++ src/layout/histogram.js | 44 ++++----- src/scale/polylinear.js | 13 +-- src/scale/quantile.js | 27 +++--- tests/test-bisect.js | 66 ++++++++++++++ tests/test-bisect.out | 53 +++++++++++ tests/test-scale-polylinear.js | 30 +++++-- tests/test-scale-polylinear.out | 26 ++++-- tests/test-scale-quantile.js | 142 ++++++++++++++++++++++++++++++ tests/test-scale-quantile.out | 105 ++++++++++++++++++++++ 16 files changed, 595 insertions(+), 149 deletions(-) create mode 100644 src/core/bisect.js create mode 100644 tests/test-bisect.js create mode 100644 tests/test-bisect.out create mode 100644 tests/test-scale-quantile.js create mode 100644 tests/test-scale-quantile.out diff --git a/Makefile b/Makefile index 72358052..e22ce354 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,7 @@ d3.core.js: \ src/core/call.js \ src/core/range.js \ src/core/requote.js \ + src/core/bisect.js \ src/core/xhr.js \ src/core/text.js \ src/core/json.js \ @@ -176,6 +177,8 @@ tests: \ tests/test-scale-log.test \ tests/test-scale-sqrt.test \ tests/test-scale-pow.test \ + tests/test-scale-quantile.test \ + tests/test-bisect.test \ tests/test-svg-arc.test \ tests/test-svg-area.test \ tests/test-svg-line.test \ diff --git a/d3.js b/d3.js index f8083233..83146b3d 100644 --- a/d3.js +++ b/d3.js @@ -236,6 +236,44 @@ d3.requote = function(s) { }; var d3_requote_re = /[\\\^\$\*\+\?\[\]\(\)\.\{\}]/g; +// Locate the insertion point for x in a to maintain sorted order. The +// arguments lo and hi may be used to specify a subset of the array which should +// be considered; by default the entire array is used. If x is already present +// in a, the insertion point will be before (to the left of) any existing +// entries. The return value is suitable for use as the first argument to +// `array.splice` assuming that a is already sorted. +// +// The returned insertion point i partitions the array a into two halves so that +// all v < x for v in a[lo:i] for the left side and all v >= x for v in a[i:hi] +// for the right side. +d3.bisectLeft = function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = (lo + hi) >> 1; + if (a[mid] < x) lo = mid + 1; + else hi = mid; + } + return lo; +}; + +// Similar to bisectLeft, but returns an insertion point which comes after (to +// the right of) any existing entries of x in a. +// +// The returned insertion point i partitions the array into two halves so that +// all v <= x for v in a[lo:i] for the left side and all v > x for v in a[i:hi] +// for the right side. +d3.bisect = +d3.bisectRight = function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = (lo + hi) >> 1; + if (x < a[mid]) hi = mid; + else lo = mid + 1; + } + return lo; +}; d3.xhr = function(url, mime, callback) { var req = new XMLHttpRequest(); if (arguments.length < 3) callback = mime; @@ -2147,19 +2185,8 @@ function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { i.push(interpolate(range[j - 1], range[j])); } - function search(x) { - var low = 1, high = domain.length - 2; - while (low <= high) { - var mid = (low + high) >> 1, midValue = domain[mid]; - if (midValue < x) low = mid + 1; - else if (midValue > x) high = mid - 1; - else return mid; - } - return low - 1; - } - return function(x) { - var j = search(x); + var j = d3.bisect(domain, x, 1, domain.length - 1) - 1; return i[j](u[j](x)); }; } @@ -2417,26 +2444,21 @@ d3.scale.quantile = function() { thresholds = []; function rescale() { - var i = -1, - n = thresholds.length = range.length, - k = domain.length / n; - while (++i < n) thresholds[i] = domain[~~(i * k)]; - } - - function quantile(value) { - if (isNaN(value = +value)) return NaN; - var low = 0, high = thresholds.length - 1; - while (low <= high) { - var mid = (low + high) >> 1, midValue = thresholds[mid]; - if (midValue < value) low = mid + 1; - else if (midValue > value) high = mid - 1; - else return mid; + var k = 0, + n = domain.length, + q = range.length, + i; + thresholds.length = Math.max(0, q - 1); + while (++k < q) { + i = n * k / q; + if (i % 1) thresholds[k - 1] = domain[~~i]; + else thresholds[k - 1] = (domain[i = ~~i] + domain[i - 1]) / 2; } - return high < 0 ? 0 : high; } function scale(x) { - return range[quantile(x)]; + if (isNaN(x = +x)) return NaN; + return range[d3.bisect(thresholds, x)]; } scale.domain = function(x) { diff --git a/d3.layout.js b/d3.layout.js index 6cfbd22b..82884181 100644 --- a/d3.layout.js +++ b/d3.layout.js @@ -878,37 +878,35 @@ d3.layout.histogram = function() { ticksFunction = d3_layout_histogramTicks; function histogram(data, i) { - var x = data.map(value), bins = []; - - // Initialize default ticks. - var ticks = ticksFunction.call(this, data, i); + var x = data.map(value), + bins = [], + bin, + ticks = ticksFunction.call(this, data, i), + i = -1, + n = x.length, + m = ticks.length - 1, + k = frequency ? 1 / n : 1; // Initialize the bins. - for (var i = 0; i < ticks.length - 1; i++) { - var bin = bins[i] = []; - bin.x = ticks[i]; - bin.dx = ticks[i + 1] - ticks[i]; + while (++i < m) { + bin = bins[i] = []; + bin.dx = ticks[i + 1] - (bin.x = ticks[i]); bin.y = 0; } // Count the number of samples per bin. - for (var i = 0; i < x.length; i++) { - var bin = bins[d3_layout_histogramSearch(ticks, x[i])]; - bin.y++; + i = -1; while(++i < n) { + bin = bins[d3.bisect(ticks, x[i], 0, m - 1)]; + bin.y += k; bin.push(data[i]); } - // Convert frequencies to probabilities. - if (!frequency) for (var i = 0; i < bins.length; i++) { - bins[i].y /= x.length; - } - return bins; } histogram.frequency = function(x) { if (!arguments.length) return frequency; - frequency = Boolean(x); + frequency = !!x; return histogram; }; @@ -927,18 +925,6 @@ d3.layout.histogram = function() { return histogram; }; -// Performs a binary search on a sorted array. -function d3_layout_histogramSearch(array, value) { - var low = 1, high = array.length - 2; - while (low <= high) { - var mid = (low + high) >> 1, midValue = array[mid]; - if (midValue < value) low = mid + 1; - else if (midValue > value) high = mid - 1; - else return mid; - } - return low - 1; -} - function d3_layout_histogramTicks(x) { return d3.scale.linear().domain(x).ticks(10); } diff --git a/d3.layout.min.js b/d3.layout.min.js index dc9b8219..4fca6527 100644 --- a/d3.layout.min.js +++ b/d3.layout.min.js @@ -1 +1 @@ -(function(){function X(a,b,c){return a._tree.ancestor.parent==b.parent?a._tree.ancestor:c}function W(a,b,c){a=a._tree,b=b._tree;var d=c/(b.number-a.number);a.change+=d,b.change-=d,b.shift+=c,b.prelim+=c,b.mod+=c}function V(a){var b=0,c=0,d=a.children,e=d.length,f;while(--e>=0)f=d[e]._tree,f.prelim+=b,f.mod+=b,b+=f.shift+(c+=f.change)}function U(a,b){function c(a,d){var e=a.children;if(e){var f,g=null,h=-1,i=e.length;while(++h0&&(a=d)}return a}function P(a){return a.children?a.children[a.children.length-1]:a._tree.thread}function O(a){return a.children?a.children[0]:a._tree.thread}function N(a,b){return a.parent==b.parent?1:2}function M(a){return d3.merge(a.map(function(a){return(a.children||[]).map(function(b){return{source:a,target:b}})}))}function L(a){var b=a.children;return b?L(b[b.length-1]):a}function K(a){var b=a.children;return b?K(b[0]):a}function J(a){return a.reduce(function(a,b){return a+b.x},0)/a.length}function I(a){return 1+d3.max(a,function(a){return a.y})}function H(a,b,c){var d=b.r+c.r,e=a.r+c.r,f=b.x-a.x,g=b.y-a.y,h=Math.sqrt(f*f+g*g),i=(e*e+h*h-d*d)/(2*e*h),j=Math.acos(i),k=i*e,l=Math.sin(j)*e;f/=h,g/=h,c.x=a.x+k*f+l*g,c.y=a.y+k*g-l*f}function G(a,b,c,d){var e=a.children;a.x=b+=d*a.x,a.y=c+=d*a.y,a.r*=d;if(e){var f=-1,g=e.length;while(++f1){h=a[1],h.x=h.r,h.y=0,l(h);if(f>2){i=a[2],H(g,h,i),l(i),z(g,i),g._pack_prev=i,z(i,h),h=g._pack_next;for(var m=3;m0?(A(g,j),h=j,m--):(A(j,h),g=j,m--)}}}var q=(b+c)/2,r=(d+e)/2,s=0;for(var m=0;m.001}function A(a,b){a._pack_next=b,b._pack_prev=a}function z(a,b){var c=a._pack_next;a._pack_next=b,b._pack_prev=a,b._pack_next=c,c._pack_prev=b}function y(a,b){return a.value-b.value}function x(a,b){return b.value-a.value}function w(a){return a.value}function v(a){return a.children}function u(a){return d3.scale.linear().domain(a).ticks(10)}function t(a,b){var c=1,d=a.length-2;while(c<=d){var e=c+d>>1,f=a[e];if(fb)d=e-1;else return e}return c-1}function s(a,b){return a+b[1]}function r(a){return a.reduce(s,0)}function q(a){var b=1,c=0,d=a[0][1],e,f=a.length;for(;bd&&(c=b,d=e);return c}function n(a,b,c){a.y0=b,a.y=c}function m(a){return a.y}function l(a){return a.x}function k(a){var b=0,c=0;a.count=0,a.leaf||a.nodes.forEach(function(d){k(d),a.count+=d.count,b+=d.count*d.cx,c+=d.count*d.cy}),a.point&&(a.leaf||(a.point.x+=Math.random()-.5,a.point.y+=Math.random()-.5),a.count++,b+=a.point.x,c+=a.point.y),a.cx=b/a.count,a.cy=c/a.count}function j(){d3.event.stopPropagation(),d3.event.preventDefault()}function i(){c&&(j(),c=!1)}function h(c,d){(a=c).fixed=!0,b=!1,e=this,j()}function g(b){b!==a&&(b.fixed=!1)}function f(a){a.fixed=!0}d3.layout={},d3.layout.chord=function(){function k(){b.sort(function(a,b){a=Math.min(a.source.value,a.target.value),b=Math.min(b.source.value,b.target.value);return i(a,b)})}function j(){var a={},j=[],l=d3.range(e),m=[],n,o,p,q,r;b=[],c=[],n=0,q=-1;while(++qe&&(e=h),d.push(h)}for(g=0;g0&&(W(X(g,a,d),a,m),i+=m,j+=m),k+=g._tree.mod,i+=e._tree.mod,l+=h._tree.mod,j+=f._tree.mod;g&&!P(f)&&(f._tree.thread=g,f._tree.mod+=k-j),e&&!O(h)&&(h._tree.thread=e,h._tree.mod+=i-l,d=a)}return d}function i(a,b){a.x=a._tree.prelim+b;var c=a.children;if(c){var d=-1,e=c.length;b+=a._tree.mod;while(++dd.dy)j=d.dy;while(++fd.dx)j=d.dx;while(++fe&&(e=d);c*=c,b*=b;return Math.max(b*e/c,c/(b*f))}function h(a){if(!!a.children){var b={x:a.x,y:a.y,dx:a.dx,dy:a.dy},c=a.children.slice(),d,e=[];e.area=0;while(d=c.pop())e.push(d),e.area+=d.area,d.z!=null&&(j(e,d.z?b.dx:b.dy,b,!c.length),e.length=e.area=0);a.children.forEach(h)}}function g(a){if(!!a.children){var b={x:a.x,y:a.y,dx:a.dx,dy:a.dy},c=[],d=a.children.slice(),e,f=Infinity,h,k=Math.min(b.dx,b.dy),l;c.area=0;while((l=d.length)>0)c.push(e=d[l-1]),c.area+=e.area,(h=i(c,k))<=f?(d.pop(),f=h):(c.area-=c.pop().area,j(c,k,b,!1),k=Math.min(b.dx,b.dy),c.length=c.area=0,f=Infinity);c.length&&(j(c,k,b,!0),c.length=c.area=0),a.children.forEach(g)}}function f(a,b){var c=a.children;a.area=a.value*b;if(c){var d=-1,e=c.length;while(++d=0)f=d[e]._tree,f.prelim+=b,f.mod+=b,b+=f.shift+(c+=f.change)}function T(a,b){function c(a,d){var e=a.children;if(e){var f,g=null,h=-1,i=e.length;while(++h0&&(a=d)}return a}function O(a){return a.children?a.children[a.children.length-1]:a._tree.thread}function N(a){return a.children?a.children[0]:a._tree.thread}function M(a,b){return a.parent==b.parent?1:2}function L(a){return d3.merge(a.map(function(a){return(a.children||[]).map(function(b){return{source:a,target:b}})}))}function K(a){var b=a.children;return b?K(b[b.length-1]):a}function J(a){var b=a.children;return b?J(b[0]):a}function I(a){return a.reduce(function(a,b){return a+b.x},0)/a.length}function H(a){return 1+d3.max(a,function(a){return a.y})}function G(a,b,c){var d=b.r+c.r,e=a.r+c.r,f=b.x-a.x,g=b.y-a.y,h=Math.sqrt(f*f+g*g),i=(e*e+h*h-d*d)/(2*e*h),j=Math.acos(i),k=i*e,l=Math.sin(j)*e;f/=h,g/=h,c.x=a.x+k*f+l*g,c.y=a.y+k*g-l*f}function F(a,b,c,d){var e=a.children;a.x=b+=d*a.x,a.y=c+=d*a.y,a.r*=d;if(e){var f=-1,g=e.length;while(++f1){h=a[1],h.x=h.r,h.y=0,l(h);if(f>2){i=a[2],G(g,h,i),l(i),y(g,i),g._pack_prev=i,y(i,h),h=g._pack_next;for(var m=3;m0?(z(g,j),h=j,m--):(z(j,h),g=j,m--)}}}var q=(b+c)/2,r=(d+e)/2,s=0;for(var m=0;m.001}function z(a,b){a._pack_next=b,b._pack_prev=a}function y(a,b){var c=a._pack_next;a._pack_next=b,b._pack_prev=a,b._pack_next=c,c._pack_prev=b}function x(a,b){return a.value-b.value}function w(a,b){return b.value-a.value}function v(a){return a.value}function u(a){return a.children}function t(a){return d3.scale.linear().domain(a).ticks(10)}function s(a,b){return a+b[1]}function r(a){return a.reduce(s,0)}function q(a){var b=1,c=0,d=a[0][1],e,f=a.length;for(;bd&&(c=b,d=e);return c}function n(a,b,c){a.y0=b,a.y=c}function m(a){return a.y}function l(a){return a.x}function k(a){var b=0,c=0;a.count=0,a.leaf||a.nodes.forEach(function(d){k(d),a.count+=d.count,b+=d.count*d.cx,c+=d.count*d.cy}),a.point&&(a.leaf||(a.point.x+=Math.random()-.5,a.point.y+=Math.random()-.5),a.count++,b+=a.point.x,c+=a.point.y),a.cx=b/a.count,a.cy=c/a.count}function j(){d3.event.stopPropagation(),d3.event.preventDefault()}function i(){c&&(j(),c=!1)}function h(c,d){(a=c).fixed=!0,b=!1,e=this,j()}function g(b){b!==a&&(b.fixed=!1)}function f(a){a.fixed=!0}d3.layout={},d3.layout.chord=function(){function k(){b.sort(function(a,b){a=Math.min(a.source.value,a.target.value),b=Math.min(b.source.value,b.target.value);return i(a,b)})}function j(){var a={},j=[],l=d3.range(e),m=[],n,o,p,q,r;b=[],c=[],n=0,q=-1;while(++qe&&(e=h),d.push(h)}for(g=0;g0&&(V(W(g,a,d),a,m),i+=m,j+=m),k+=g._tree.mod,i+=e._tree.mod,l+=h._tree.mod,j+=f._tree.mod;g&&!O(f)&&(f._tree.thread=g,f._tree.mod+=k-j),e&&!N(h)&&(h._tree.thread=e,h._tree.mod+=i-l,d=a)}return d}function i(a,b){a.x=a._tree.prelim+b;var c=a.children;if(c){var d=-1,e=c.length;b+=a._tree.mod;while(++dd.dy)j=d.dy;while(++fd.dx)j=d.dx;while(++fe&&(e=d);c*=c,b*=b;return Math.max(b*e/c,c/(b*f))}function h(a){if(!!a.children){var b={x:a.x,y:a.y,dx:a.dx,dy:a.dy},c=a.children.slice(),d,e=[];e.area=0;while(d=c.pop())e.push(d),e.area+=d.area,d.z!=null&&(j(e,d.z?b.dx:b.dy,b,!c.length),e.length=e.area=0);a.children.forEach(h)}}function g(a){if(!!a.children){var b={x:a.x,y:a.y,dx:a.dx,dy:a.dy},c=[],d=a.children.slice(),e,f=Infinity,h,k=Math.min(b.dx,b.dy),l;c.area=0;while((l=d.length)>0)c.push(e=d[l-1]),c.area+=e.area,(h=i(c,k))<=f?(d.pop(),f=h):(c.area-=c.pop().area,j(c,k,b,!1),k=Math.min(b.dx,b.dy),c.length=c.area=0,f=Infinity);c.length&&(j(c,k,b,!0),c.length=c.area=0),a.children.forEach(g)}}function f(a,b){var c=a.children;a.area=a.value*b;if(c){var d=-1,e=c.length;while(++d9&&(f=c*3/Math.sqrt(f),g[h]=f*d,g[h+1]=f*e));h=-1;while(++h<=i)f=(a[Math.min(i,h+1)][0]-a[Math.max(0,h-1)][0])/(6*(1+g[h]*g[h])),b.push([f||0,g[h]*f||0]);return b}function bQ(a){var b=0,c=a.length-1,d=[],e=a[0],f=a[1],g=d[0]=bP(e,f);while(++b1){h=b[1],f=a[i],i++,d+="C"+(e[0]+g[0])+","+(e[1]+g[1])+","+(f[0]-h[0])+","+(f[1]-h[1])+","+f[0]+","+f[1];for(var j=2;j>1,f=a[e];if(fb)d=e-1;else return e}return c-1}var e=[],f=[],g=0,h=a.length;while(++gc.delay&&(c.flush=c.callback(a)),c=c.next;var d=bd()-b;d>24?(isFinite(d)&&(clearTimeout(ba),ba=setTimeout(bc,d)),_=0):(_=1,be(bc))}function bb(a,b){var c=Date.now(),d=!1,e,f=$;if(!!isFinite(b)){while(f){if(f.callback===a){f.then=c,f.delay=b,d=!0;break}e=f,f=f.next}d||($={callback:a,then:c,delay:b,next:$}),_||(ba=clearTimeout(ba),_=1,be(bc))}}function Z(a){return typeof a=="function"?function(b,c,d){return d3.interpolate(d,String(a.call(this,b,c)))}:(a=String(a),function(b,c,d){return d3.interpolate(d,a)})}function Y(a){function n(b){var g=!0,l=-1;a.each(function(){if(i[++l]!==2){var a=(b-j[l])/k[l],n=this.__transition__,o,p,q=e[l];if(a<1){g=!1;if(a<0)return}else a=1;if(i[l]){if(!n||n.active!==c){i[l]=2;return}}else{if(!n||n.active>c){i[l]=2;return}i[l]=1,h.start.dispatch.apply(this,arguments),q=e[l]={},n.active=c;for(p in d)if(o=d[p].apply(this,arguments))q[p]=o}o=m(a);for(p in q)q[p].call(this,o);if(a===1){i[l]=2;if(n.active===c){var r=n.owner;r===c&&(delete this.__transition__,f&&this.parentNode.removeChild(this)),X=c,h.end.dispatch.apply(this,arguments),X=0,n.owner=r}}}});return g}var b={},c=X||++W,d={},e=[],f=!1,h=d3.dispatch("start","end"),i=[],j=[],k=[],l,m=d3.ease("cubic-in-out");a.each(function(){(this.__transition__||(this.__transition__={})).owner=c}),b.delay=function(c){var d=Infinity,e=-1;typeof c=="function"?a.each(function(a,b){var f=j[++e]=+c.apply(this,arguments);fl&&(l=e)})):(l=+c,a.each(function(a,b){k[++d]=l}));return b},b.ease=function(a){m=typeof a=="function"?a:d3.ease.apply(d3,arguments);return b},b.attrTween=function(a,c){function f(b,d){var e=c.call(this,b,d,this.getAttributeNS(a.space,a.local));return function(b){this.setAttributeNS(a.space,a.local,e(b))}}function e(b,d){var e=c.call(this,b,d,this.getAttribute(a));return function(b){this.setAttribute(a,e(b))}}d["attr."+a]=a.local?f:e;return b},b.attr=function(a,c){return b.attrTween(a,Z(c))},b.styleTween=function(a,c,e){function f(b,d){var f=c.call(this,b,d,window.getComputedStyle(this,null).getPropertyValue(a));return function(b){this.style.setProperty(a,f(b),e)}}arguments.length<3&&(e=null),d["style."+a]=f;return b},b.style=function(a,c,d){arguments.length<3&&(d=null);return b.styleTween(a,Z(c),d)},b.text=function(a){d.text=function(b,c){this.textContent=typeof a=="function"?a.call(this,b,c):a};return b},b.select=function(b){var c,d=Y(a.select(b)).ease(m);c=-1,d.delay(function(a,b){return j[++c]}),c=-1,d.duration(function(a,b){return k[++c]});return d},b.selectAll=function(b){var c,d=Y(a.selectAll(b)).ease(m);c=-1,d.delay(function(a,b){return j[b?c:++c]}),c=-1,d.duration(function(a,b){return k[b?c:++c]});return d},b.remove=function(){f=!0;return b},b.each=function(a,c){h[a].add(c);return b},b.call=g;return b.delay(0).duration(250)}function V(a){return{__data__:a}}function U(a){arguments.length||(a=d3.ascending);return function(b,c){return a(b&&b.__data__,c&&c.__data__)}}function T(a){function b(b){var c=[],d,e,f,g;for(var h=0,i=a.length;h360?a-=360:a<0&&(a+=360);if(a<60)return d+(e-d)*a/60;if(a<180)return e;if(a<240)return d+(e-d)*(240-a)/60;return d}var d,e;a=a%360,a<0&&(a+=360),b=b<0?0:b>1?1:b,c=c<0?0:c>1?1:c,e=c<=.5?c*(1+b):c+b-c*b,d=2*c-e;return E(g(a+120),g(a),g(a-120))}function N(a,b,c){this.h=a,this.s=b,this.l=c}function M(a,b,c){return new N(a,b,c)}function J(a){var b=parseFloat(a);return a.charAt(a.length-1)==="%"?Math.round(b*2.55):b}function I(a,b,c){var d=Math.min(a/=255,b/=255,c/=255),e=Math.max(a,b,c),f=e-d,g,h,i=(e+d)/2;f?(h=i<.5?f/(e+d):f/(2-e-d),a==e?g=(b-c)/f+(b=0?a.substring(b):(b=a.length,""),d=[];while(b>0)d.push(a.substring(b-=3,b+3));return d.reverse().join(",")+c}function i(a){var b={},c=[];b.add=function(a){for(var d=0;db?1:0},d3.descending=function(a,b){return ba?1:0},d3.min=function(a,b){var c=0,d=a.length,e=a[0],f;if(arguments.length===1)while(++c(f=a[c])&&(e=f);else{e=b(a[0]);while(++c(f=b(a[c]))&&(e=f)}return e},d3.max=function(a,b){var c=0,d=a.length,e=a[0],f;if(arguments.length===1)while(++c=b.length)return a;var e=[],f=c[d++],h;for(h in a)e.push({key:h,values:g(a[h],d)});f&&e.sort(function(a,b){return f(a.key,b.key)});return e}function f(c,g){if(g>=b.length)return e?e.call(a,c):d?c.sort(d):c;var h=-1,i=c.length,j=b[g++],k,l,m={};while(++hb)d.push(f);else while((f=a+c*++e)=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,l=s(2),m=s(3),n={linear:function(){return r},poly:s,quad:function(){return l},cubic:function(){return m},sin:function(){return t},exp:function(){return u},circle:function(){return v},elastic:w,back:x,bounce:function(){return y}},o={"in":function(a){return a},out:p,"in-out":q,"out-in":function(a){return q(p(a))}};d3.ease=function(a){var b=a.indexOf("-"),c=b>=0?a.substring(0,b):a,d=b>=0?a.substring(b+1):"in";return o[d](n[c].apply(null,Array.prototype.slice.call(arguments,1)))},d3.event=null,d3.interpolate=function(a,b){if(typeof b=="number")return d3.interpolateNumber(+a,b);if(typeof b=="string")return b in K||/^(#|rgb\(|hsl\()/.test(b)?d3.interpolateRgb(String(a),b):d3.interpolateString(String(a),b);if(b instanceof Array)return d3.interpolateArray(a,b);return d3.interpolateObject(a,b)},d3.interpolateNumber=function(a,b){b-=a;return function(c){return a+b*c}},d3.interpolateRound=function(a,b){b-=a;return function(c){return Math.round(a+b*c)}},d3.interpolateString=function(a,b){var c,d,e,f=0,g=0,h=[],i=[],j,k;z.lastIndex=0;for(d=0;c=z.exec(b);++d)c.index&&h.push(b.substring(f,g=c.index)),i.push({i:h.length,x:c[0]}),h.push(null),f=z.lastIndex;f0;j--)e.push(c(f)*j)}else{for(;fi;g--);e=e.slice(f,g)}return e},d.tickFormat=function(){return function(a){return a.toPrecision(1)}};return d},bh.pow=function(a){return Math.pow(10,a)},bi.pow=function(a){return-Math.pow(10,-a)},d3.scale.pow=function(){function f(b){return a(d(b))}var a=d3.scale.linear(),b=d3.scale.linear(),c=1,d=Number,e=d;f.invert=function(b){return e(a.invert(b))},f.domain=function(g){if(!arguments.length)return a.domain().map(e);var h=(g[0]||g[1])<0?bk:bj;d=h(c),e=h(1/c),a.domain(g.map(d)),b.domain(g);return f},f.range=d3.rebind(f,a.range),f.rangeRound=d3.rebind(f,a.rangeRound),f.interpolate=d3.rebind(f,a.interpolate),f.clamp=d3.rebind(f,a.clamp),f.ticks=b.ticks,f.tickFormat=b.tickFormat,f.exponent=function(a){if(!arguments.length)return c;var b=f.domain();c=a;return f.domain(b)};return f},d3.scale.sqrt=function(){return d3.scale.pow().exponent(.5)},d3.scale.ordinal=function(){function e(d){var e=d in b?b[d]:b[d]=a.push(d)-1;return c[e%c.length]}var a=[],b={},c=[],d=0;e.domain=function(c){if(!arguments.length)return a;a=c,b={};var d=-1,f=-1,g=a.length;while(++d>1,f=c[e];if(fa)d=e-1;else return e}return d<0?0:d}function d(){var d=-1,e=c.length=b.length,f=a.length/e;while(++d=bq?e?"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"M0,"+e+"A"+e+","+e+" 0 1,1 0,"+ -e+"A"+e+","+e+" 0 1,1 0,"+e+"Z":"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"Z":e?"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L"+e*m+","+e*n+"A"+e+","+e+" 0 "+j+",0 "+e*k+","+e*l+"Z":"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L0,0"+"Z"}var a=br,b=bs,c=bt,d=bu;e.innerRadius=function(b){if(!arguments.length)return a;a=d3.functor(b);return e},e.outerRadius=function(a){if(!arguments.length)return b;b=d3.functor(a);return e},e.startAngle=function(a){if(!arguments.length)return c;c=d3.functor(a);return e},e.endAngle=function(a){if(!arguments.length)return d;d=d3.functor(a);return e},e.centroid=function(){var e=(a.apply(this,arguments)+b.apply(this,arguments))/2,f=(c.apply(this,arguments)+d.apply(this,arguments))/2+bp;return[Math.cos(f)*e,Math.sin(f)*e]};return e};var bp=-Math.PI/2,bq=2*Math.PI-1e-6;d3.svg.line=function(){function f(c){return c.length<1?null:"M"+d(bv(this,c,a,b),e)}var a=bw,b=bx,c="linear",d=by[c],e=.7;f.x=function(b){if(!arguments.length)return a;a=b;return f},f.y=function(a){if(!arguments.length)return b;b=a;return f},f.interpolate=function(a){if(!arguments.length)return c;d=by[c=a];return f},f.tension=function(a){if(!arguments.length)return e;e=a;return f};return f};var by={linear:bz,"step-before":bA,"step-after":bB,basis:bH,"basis-open":bI,"basis-closed":bJ,cardinal:bE,"cardinal-open":bC,"cardinal-closed":bD,monotone:bS},bL=[0,2/3,1/3,0],bM=[0,1/3,2/3,0],bN=[0,1/6,2/3,1/6];d3.svg.area=function(){function g(d){return d.length<1?null:"M"+e(bv(this,d,a,c),f)+"L"+e(bv(this,d,a,b).reverse(),f)+"Z"}var a=bw,b=bT,c=bx,d="linear",e=by[d],f=.7;g.x=function(b){if(!arguments.length)return a;a=b;return g},g.y0=function(a){if(!arguments.length)return b;b=a;return g},g.y1=function(a){if(!arguments.length)return c;c=a;return g},g.interpolate=function(a){if(!arguments.length)return d;e=by[d=a];return g},g.tension=function(a){if(!arguments.length)return f;f=a;return g};return g},d3.svg.chord=function(){function j(a,b,c,d){return"Q 0,0 "+d}function i(a,b){return"A"+a+","+a+" 0 0,1 "+b}function h(a,b){return a.a0==b.a0&&a.a1==b.a1}function g(a,b,f,g){var h=b.call(a,f,g),i=c.call(a,h,g),j=d.call(a,h,g)+bp,k=e.call(a,h,g)+bp;return{r:i,a0:j,a1:k,p0:[i*Math.cos(j),i*Math.sin(j)],p1:[i*Math.cos(k),i*Math.sin(k)]}}function f(c,d){var e=g(this,a,c,d),f=g(this,b,c,d);return"M"+e.p0+i(e.r,e.p1)+(h(e,f)?j(e.r,e.p1,e.r,e.p0):j(e.r,e.p1,f.r,f.p0)+i(f.r,f.p1)+j(f.r,f.p1,e.r,e.p0))+"Z"}var a=bU,b=bV,c=bW,d=bt,e=bu;f.radius=function(a){if(!arguments.length)return c;c=d3.functor(a);return f},f.source=function(b){if(!arguments.length)return a;a=d3.functor(b);return f},f.target=function(a){if(!arguments.length)return b;b=d3.functor(a);return f},f.startAngle=function(a){if(!arguments.length)return d;d=d3.functor(a);return f},f.endAngle=function(a){if(!arguments.length)return e;e=d3.functor(a);return f};return f},d3.svg.diagonal=function(){function d(d,e){var f=a.call(this,d,e),g=b.call(this,d,e),h=(f.y+g.y)/2,i=[f,{x:f.x,y:h},{x:g.x,y:h},g];i=i.map(c);return"M"+i[0]+"C"+i[1]+" "+i[2]+" "+i[3]}var a=bU,b=bV,c=bZ;d.source=function(b){if(!arguments.length)return a;a=d3.functor(b);return d},d.target=function(a){if(!arguments.length)return b;b=d3.functor(a);return d},d.projection=function(a){if(!arguments.length)return c;c=a;return d};return d},d3.svg.mouse=function(a){return b_(a,d3.event)};var b$=/WebKit/.test(navigator.userAgent)?-1:0;d3.svg.touches=function(b){var c=d3.event.touches;return c?a(c).map(function(a){var c=b_(b,a);c.identifier=a.identifier;return c}):[]},d3.svg.symbol=function(){function c(c,d){return(cc[a.call(this,c,d)]||cc.circle)(b.call(this,c,d))}var a=cb,b=ca;c.type=function(b){if(!arguments.length)return a;a=d3.functor(b);return c},c.size=function(a){if(!arguments.length)return b;b=d3.functor(a);return c};return c},d3.svg.symbolTypes=["circle","cross","diamond","square","triangle-down","triangle-up"];var cc={circle:function(a){var b=Math.sqrt(a/Math.PI);return"M0,"+b+"A"+b+","+b+" 0 1,1 0,"+ -b+"A"+b+","+b+" 0 1,1 0,"+b+"Z"},cross:function(a){var b=Math.sqrt(a/5)/2;return"M"+ -3*b+","+ -b+"H"+ -b+"V"+ -3*b+"H"+b+"V"+ -b+"H"+3*b+"V"+b+"H"+b+"V"+3*b+"H"+ -b+"V"+b+"H"+ -3*b+"Z"},diamond:function(a){var b=Math.sqrt(a/(2*ce)),c=b*ce;return"M0,"+ -b+"L"+c+",0"+" 0,"+b+" "+ -c+",0"+"Z"},square:function(a){var b=Math.sqrt(a)/2;return"M"+ -b+","+ -b+"L"+b+","+ -b+" "+b+","+b+" "+ -b+","+b+"Z"},"triangle-down":function(a){var b=Math.sqrt(a/cd),c=b*cd/2;return"M0,"+c+"L"+b+","+ -c+" "+ -b+","+ -c+"Z"},"triangle-up":function(a){var b=Math.sqrt(a/cd),c=b*cd/2;return"M0,"+ -c+"L"+b+","+c+" "+ -b+","+c+"Z"}},cd=Math.sqrt(3),ce=Math.tan(30*Math.PI/180)})() \ No newline at end of file +(function(){function cb(){return"circle"}function ca(){return 64}function b_(a,b){var c=(a.ownerSVGElement||a).createSVGPoint();if(b$<0&&(window.scrollX||window.scrollY)){var d=d3.select(document.body).append("svg:svg").style("position","absolute").style("top",0).style("left",0),e=d[0][0].getScreenCTM();b$=!e.f&&!e.e,d.remove()}b$?(c.x=b.pageX,c.y=b.pageY):(c.x=b.clientX,c.y=b.clientY),c=c.matrixTransform(a.getScreenCTM().inverse());return[c.x,c.y]}function bZ(a){return[a.x,a.y]}function bY(a){return a.endAngle}function bX(a){return a.startAngle}function bW(a){return a.radius}function bV(a){return a.target}function bU(a){return a.source}function bT(){return 0}function bS(a){return a.length<3?bz(a):a[0]+bF(a,bR(a))}function bR(a){var b=[],c,d,e,f,g=bQ(a),h=-1,i=a.length-1;while(++h9&&(f=c*3/Math.sqrt(f),g[h]=f*d,g[h+1]=f*e));h=-1;while(++h<=i)f=(a[Math.min(i,h+1)][0]-a[Math.max(0,h-1)][0])/(6*(1+g[h]*g[h])),b.push([f||0,g[h]*f||0]);return b}function bQ(a){var b=0,c=a.length-1,d=[],e=a[0],f=a[1],g=d[0]=bP(e,f);while(++b1){h=b[1],f=a[i],i++,d+="C"+(e[0]+g[0])+","+(e[1]+g[1])+","+(f[0]-h[0])+","+(f[1]-h[1])+","+f[0]+","+f[1];for(var j=2;jc.delay&&(c.flush=c.callback(a)),c=c.next;var d=bd()-b;d>24?(isFinite(d)&&(clearTimeout(ba),ba=setTimeout(bc,d)),_=0):(_=1,be(bc))}function bb(a,b){var c=Date.now(),d=!1,e,f=$;if(!!isFinite(b)){while(f){if(f.callback===a){f.then=c,f.delay=b,d=!0;break}e=f,f=f.next}d||($={callback:a,then:c,delay:b,next:$}),_||(ba=clearTimeout(ba),_=1,be(bc))}}function Z(a){return typeof a=="function"?function(b,c,d){return d3.interpolate(d,String(a.call(this,b,c)))}:(a=String(a),function(b,c,d){return d3.interpolate(d,a)})}function Y(a){function n(b){var g=!0,l=-1;a.each(function(){if(i[++l]!==2){var a=(b-j[l])/k[l],n=this.__transition__,o,p,q=e[l];if(a<1){g=!1;if(a<0)return}else a=1;if(i[l]){if(!n||n.active!==c){i[l]=2;return}}else{if(!n||n.active>c){i[l]=2;return}i[l]=1,h.start.dispatch.apply(this,arguments),q=e[l]={},n.active=c;for(p in d)if(o=d[p].apply(this,arguments))q[p]=o}o=m(a);for(p in q)q[p].call(this,o);if(a===1){i[l]=2;if(n.active===c){var r=n.owner;r===c&&(delete this.__transition__,f&&this.parentNode.removeChild(this)),X=c,h.end.dispatch.apply(this,arguments),X=0,n.owner=r}}}});return g}var b={},c=X||++W,d={},e=[],f=!1,h=d3.dispatch("start","end"),i=[],j=[],k=[],l,m=d3.ease("cubic-in-out");a.each(function(){(this.__transition__||(this.__transition__={})).owner=c}),b.delay=function(c){var d=Infinity,e=-1;typeof c=="function"?a.each(function(a,b){var f=j[++e]=+c.apply(this,arguments);fl&&(l=e)})):(l=+c,a.each(function(a,b){k[++d]=l}));return b},b.ease=function(a){m=typeof a=="function"?a:d3.ease.apply(d3,arguments);return b},b.attrTween=function(a,c){function f(b,d){var e=c.call(this,b,d,this.getAttributeNS(a.space,a.local));return function(b){this.setAttributeNS(a.space,a.local,e(b))}}function e(b,d){var e=c.call(this,b,d,this.getAttribute(a));return function(b){this.setAttribute(a,e(b))}}d["attr."+a]=a.local?f:e;return b},b.attr=function(a,c){return b.attrTween(a,Z(c))},b.styleTween=function(a,c,e){function f(b,d){var f=c.call(this,b,d,window.getComputedStyle(this,null).getPropertyValue(a));return function(b){this.style.setProperty(a,f(b),e)}}arguments.length<3&&(e=null),d["style."+a]=f;return b},b.style=function(a,c,d){arguments.length<3&&(d=null);return b.styleTween(a,Z(c),d)},b.text=function(a){d.text=function(b,c){this.textContent=typeof a=="function"?a.call(this,b,c):a};return b},b.select=function(b){var c,d=Y(a.select(b)).ease(m);c=-1,d.delay(function(a,b){return j[++c]}),c=-1,d.duration(function(a,b){return k[++c]});return d},b.selectAll=function(b){var c,d=Y(a.selectAll(b)).ease(m);c=-1,d.delay(function(a,b){return j[b?c:++c]}),c=-1,d.duration(function(a,b){return k[b?c:++c]});return d},b.remove=function(){f=!0;return b},b.each=function(a,c){h[a].add(c);return b},b.call=g;return b.delay(0).duration(250)}function V(a){return{__data__:a}}function U(a){arguments.length||(a=d3.ascending);return function(b,c){return a(b&&b.__data__,c&&c.__data__)}}function T(a){function b(b){var c=[],d,e,f,g;for(var h=0,i=a.length;h360?a-=360:a<0&&(a+=360);if(a<60)return d+(e-d)*a/60;if(a<180)return e;if(a<240)return d+(e-d)*(240-a)/60;return d}var d,e;a=a%360,a<0&&(a+=360),b=b<0?0:b>1?1:b,c=c<0?0:c>1?1:c,e=c<=.5?c*(1+b):c+b-c*b,d=2*c-e;return E(g(a+120),g(a),g(a-120))}function N(a,b,c){this.h=a,this.s=b,this.l=c}function M(a,b,c){return new N(a,b,c)}function J(a){var b=parseFloat(a);return a.charAt(a.length-1)==="%"?Math.round(b*2.55):b}function I(a,b,c){var d=Math.min(a/=255,b/=255,c/=255),e=Math.max(a,b,c),f=e-d,g,h,i=(e+d)/2;f?(h=i<.5?f/(e+d):f/(2-e-d),a==e?g=(b-c)/f+(b=0?a.substring(b):(b=a.length,""),d=[];while(b>0)d.push(a.substring(b-=3,b+3));return d.reverse().join(",")+c}function i(a){var b={},c=[];b.add=function(a){for(var d=0;db?1:0},d3.descending=function(a,b){return ba?1:0},d3.min=function(a,b){var c=0,d=a.length,e=a[0],f;if(arguments.length===1)while(++c(f=a[c])&&(e=f);else{e=b(a[0]);while(++c(f=b(a[c]))&&(e=f)}return e},d3.max=function(a,b){var c=0,d=a.length,e=a[0],f;if(arguments.length===1)while(++c=b.length)return a;var e=[],f=c[d++],h;for(h in a)e.push({key:h,values:g(a[h],d)});f&&e.sort(function(a,b){return f(a.key,b.key)});return e}function f(c,g){if(g>=b.length)return e?e.call(a,c):d?c.sort(d):c;var h=-1,i=c.length,j=b[g++],k,l,m={};while(++hb)d.push(f);else while((f=a+c*++e)>1;a[e]>1;b=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,l=s(2),m=s(3),n={linear:function(){return r},poly:s,quad:function(){return l},cubic:function(){return m},sin:function(){return t},exp:function(){return u},circle:function(){return v},elastic:w,back:x,bounce:function(){return y}},o={"in":function(a){return a},out:p,"in-out":q,"out-in":function(a){return q(p(a))}};d3.ease=function(a){var b=a.indexOf("-"),c=b>=0?a.substring(0,b):a,d=b>=0?a.substring(b+1):"in";return o[d](n[c].apply(null,Array.prototype.slice.call(arguments,1)))},d3.event=null,d3.interpolate=function(a,b){if(typeof b=="number")return d3.interpolateNumber(+a,b);if(typeof b=="string")return b in K||/^(#|rgb\(|hsl\()/.test(b)?d3.interpolateRgb(String(a),b):d3.interpolateString(String(a),b);if(b instanceof Array)return d3.interpolateArray(a,b);return d3.interpolateObject(a,b)},d3.interpolateNumber=function(a,b){b-=a;return function(c){return a+b*c}},d3.interpolateRound=function(a,b){b-=a;return function(c){return Math.round(a+b*c)}},d3.interpolateString=function(a,b){var c,d,e,f=0,g=0,h=[],i=[],j,k;z.lastIndex=0;for(d=0;c=z.exec(b);++d)c.index&&h.push(b.substring(f,g=c.index)),i.push({i:h.length,x:c[0]}),h.push(null),f=z.lastIndex;f0;j--)e.push(c(f)*j)}else{for(;fi;g--);e=e.slice(f,g)}return e},d.tickFormat=function(){return function(a){return a.toPrecision(1)}};return d},bh.pow=function(a){return Math.pow(10,a)},bi.pow=function(a){return-Math.pow(10,-a)},d3.scale.pow=function(){function f(b){return a(d(b))}var a=d3.scale.linear(),b=d3.scale.linear(),c=1,d=Number,e=d;f.invert=function(b){return e(a.invert(b))},f.domain=function(g){if(!arguments.length)return a.domain().map(e);var h=(g[0]||g[1])<0?bk:bj;d=h(c),e=h(1/c),a.domain(g.map(d)),b.domain(g);return f},f.range=d3.rebind(f,a.range),f.rangeRound=d3.rebind(f,a.rangeRound),f.interpolate=d3.rebind(f,a.interpolate),f.clamp=d3.rebind(f,a.clamp),f.ticks=b.ticks,f.tickFormat=b.tickFormat,f.exponent=function(a){if(!arguments.length)return c;var b=f.domain();c=a;return f.domain(b)};return f},d3.scale.sqrt=function(){return d3.scale.pow().exponent(.5)},d3.scale.ordinal=function(){function e(d){var e=d in b?b[d]:b[d]=a.push(d)-1;return c[e%c.length]}var a=[],b={},c=[],d=0;e.domain=function(c){if(!arguments.length)return a;a=c,b={};var d=-1,f=-1,g=a.length;while(++d=bq?e?"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"M0,"+e+"A"+e+","+e+" 0 1,1 0,"+ -e+"A"+e+","+e+" 0 1,1 0,"+e+"Z":"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"Z":e?"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L"+e*m+","+e*n+"A"+e+","+e+" 0 "+j+",0 "+e*k+","+e*l+"Z":"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L0,0"+"Z"}var a=br,b=bs,c=bt,d=bu;e.innerRadius=function(b){if(!arguments.length)return a;a=d3.functor(b);return e},e.outerRadius=function(a){if(!arguments.length)return b;b=d3.functor(a);return e},e.startAngle=function(a){if(!arguments.length)return c;c=d3.functor(a);return e},e.endAngle=function(a){if(!arguments.length)return d;d=d3.functor(a);return e},e.centroid=function(){var e=(a.apply(this,arguments)+b.apply(this,arguments))/2,f=(c.apply(this,arguments)+d.apply(this,arguments))/2+bp;return[Math.cos(f)*e,Math.sin(f)*e]};return e};var bp=-Math.PI/2,bq=2*Math.PI-1e-6;d3.svg.line=function(){function f(c){return c.length<1?null:"M"+d(bv(this,c,a,b),e)}var a=bw,b=bx,c="linear",d=by[c],e=.7;f.x=function(b){if(!arguments.length)return a;a=b;return f},f.y=function(a){if(!arguments.length)return b;b=a;return f},f.interpolate=function(a){if(!arguments.length)return c;d=by[c=a];return f},f.tension=function(a){if(!arguments.length)return e;e=a;return f};return f};var by={linear:bz,"step-before":bA,"step-after":bB,basis:bH,"basis-open":bI,"basis-closed":bJ,cardinal:bE,"cardinal-open":bC,"cardinal-closed":bD,monotone:bS},bL=[0,2/3,1/3,0],bM=[0,1/3,2/3,0],bN=[0,1/6,2/3,1/6];d3.svg.area=function(){function g(d){return d.length<1?null:"M"+e(bv(this,d,a,c),f)+"L"+e(bv(this,d,a,b).reverse(),f)+"Z"}var a=bw,b=bT,c=bx,d="linear",e=by[d],f=.7;g.x=function(b){if(!arguments.length)return a;a=b;return g},g.y0=function(a){if(!arguments.length)return b;b=a;return g},g.y1=function(a){if(!arguments.length)return c;c=a;return g},g.interpolate=function(a){if(!arguments.length)return d;e=by[d=a];return g},g.tension=function(a){if(!arguments.length)return f;f=a;return g};return g},d3.svg.chord=function(){function j(a,b,c,d){return"Q 0,0 "+d}function i(a,b){return"A"+a+","+a+" 0 0,1 "+b}function h(a,b){return a.a0==b.a0&&a.a1==b.a1}function g(a,b,f,g){var h=b.call(a,f,g),i=c.call(a,h,g),j=d.call(a,h,g)+bp,k=e.call(a,h,g)+bp;return{r:i,a0:j,a1:k,p0:[i*Math.cos(j),i*Math.sin(j)],p1:[i*Math.cos(k),i*Math.sin(k)]}}function f(c,d){var e=g(this,a,c,d),f=g(this,b,c,d);return"M"+e.p0+i(e.r,e.p1)+(h(e,f)?j(e.r,e.p1,e.r,e.p0):j(e.r,e.p1,f.r,f.p0)+i(f.r,f.p1)+j(f.r,f.p1,e.r,e.p0))+"Z"}var a=bU,b=bV,c=bW,d=bt,e=bu;f.radius=function(a){if(!arguments.length)return c;c=d3.functor(a);return f},f.source=function(b){if(!arguments.length)return a;a=d3.functor(b);return f},f.target=function(a){if(!arguments.length)return b;b=d3.functor(a);return f},f.startAngle=function(a){if(!arguments.length)return d;d=d3.functor(a);return f},f.endAngle=function(a){if(!arguments.length)return e;e=d3.functor(a);return f};return f},d3.svg.diagonal=function(){function d(d,e){var f=a.call(this,d,e),g=b.call(this,d,e),h=(f.y+g.y)/2,i=[f,{x:f.x,y:h},{x:g.x,y:h},g];i=i.map(c);return"M"+i[0]+"C"+i[1]+" "+i[2]+" "+i[3]}var a=bU,b=bV,c=bZ;d.source=function(b){if(!arguments.length)return a;a=d3.functor(b);return d},d.target=function(a){if(!arguments.length)return b;b=d3.functor(a);return d},d.projection=function(a){if(!arguments.length)return c;c=a;return d};return d},d3.svg.mouse=function(a){return b_(a,d3.event)};var b$=/WebKit/.test(navigator.userAgent)?-1:0;d3.svg.touches=function(b){var c=d3.event.touches;return c?a(c).map(function(a){var c=b_(b,a);c.identifier=a.identifier;return c}):[]},d3.svg.symbol=function(){function c(c,d){return(cc[a.call(this,c,d)]||cc.circle)(b.call(this,c,d))}var a=cb,b=ca;c.type=function(b){if(!arguments.length)return a;a=d3.functor(b);return c},c.size=function(a){if(!arguments.length)return b;b=d3.functor(a);return c};return c},d3.svg.symbolTypes=["circle","cross","diamond","square","triangle-down","triangle-up"];var cc={circle:function(a){var b=Math.sqrt(a/Math.PI);return"M0,"+b+"A"+b+","+b+" 0 1,1 0,"+ -b+"A"+b+","+b+" 0 1,1 0,"+b+"Z"},cross:function(a){var b=Math.sqrt(a/5)/2;return"M"+ -3*b+","+ -b+"H"+ -b+"V"+ -3*b+"H"+b+"V"+ -b+"H"+3*b+"V"+b+"H"+b+"V"+3*b+"H"+ -b+"V"+b+"H"+ -3*b+"Z"},diamond:function(a){var b=Math.sqrt(a/(2*ce)),c=b*ce;return"M0,"+ -b+"L"+c+",0"+" 0,"+b+" "+ -c+",0"+"Z"},square:function(a){var b=Math.sqrt(a)/2;return"M"+ -b+","+ -b+"L"+b+","+ -b+" "+b+","+b+" "+ -b+","+b+"Z"},"triangle-down":function(a){var b=Math.sqrt(a/cd),c=b*cd/2;return"M0,"+c+"L"+b+","+ -c+" "+ -b+","+ -c+"Z"},"triangle-up":function(a){var b=Math.sqrt(a/cd),c=b*cd/2;return"M0,"+ -c+"L"+b+","+c+" "+ -b+","+c+"Z"}},cd=Math.sqrt(3),ce=Math.tan(30*Math.PI/180)})() \ No newline at end of file diff --git a/examples/histogram/histogram.html b/examples/histogram/histogram.html index 945ada3a..e2a855e3 100644 --- a/examples/histogram/histogram.html +++ b/examples/histogram/histogram.html @@ -10,18 +10,28 @@ body { font: 10px sans-serif; } +rect { + fill: steelblue; + stroke: white; +} + +line { + stroke: black; + shape-rendering: crispEdges; +} + diff --git a/src/core/bisect.js b/src/core/bisect.js new file mode 100644 index 00000000..01819786 --- /dev/null +++ b/src/core/bisect.js @@ -0,0 +1,38 @@ +// Locate the insertion point for x in a to maintain sorted order. The +// arguments lo and hi may be used to specify a subset of the array which should +// be considered; by default the entire array is used. If x is already present +// in a, the insertion point will be before (to the left of) any existing +// entries. The return value is suitable for use as the first argument to +// `array.splice` assuming that a is already sorted. +// +// The returned insertion point i partitions the array a into two halves so that +// all v < x for v in a[lo:i] for the left side and all v >= x for v in a[i:hi] +// for the right side. +d3.bisectLeft = function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = (lo + hi) >> 1; + if (a[mid] < x) lo = mid + 1; + else hi = mid; + } + return lo; +}; + +// Similar to bisectLeft, but returns an insertion point which comes after (to +// the right of) any existing entries of x in a. +// +// The returned insertion point i partitions the array into two halves so that +// all v <= x for v in a[lo:i] for the left side and all v > x for v in a[i:hi] +// for the right side. +d3.bisect = +d3.bisectRight = function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = (lo + hi) >> 1; + if (x < a[mid]) hi = mid; + else lo = mid + 1; + } + return lo; +}; diff --git a/src/layout/histogram.js b/src/layout/histogram.js index b4a2e29c..0a32a36a 100644 --- a/src/layout/histogram.js +++ b/src/layout/histogram.js @@ -4,37 +4,35 @@ d3.layout.histogram = function() { ticksFunction = d3_layout_histogramTicks; function histogram(data, i) { - var x = data.map(value), bins = []; - - // Initialize default ticks. - var ticks = ticksFunction.call(this, data, i); + var x = data.map(value), + bins = [], + bin, + ticks = ticksFunction.call(this, data, i), + i = -1, + n = x.length, + m = ticks.length - 1, + k = frequency ? 1 / n : 1; // Initialize the bins. - for (var i = 0; i < ticks.length - 1; i++) { - var bin = bins[i] = []; - bin.x = ticks[i]; - bin.dx = ticks[i + 1] - ticks[i]; + while (++i < m) { + bin = bins[i] = []; + bin.dx = ticks[i + 1] - (bin.x = ticks[i]); bin.y = 0; } // Count the number of samples per bin. - for (var i = 0; i < x.length; i++) { - var bin = bins[d3_layout_histogramSearch(ticks, x[i])]; - bin.y++; + i = -1; while(++i < n) { + bin = bins[d3.bisect(ticks, x[i], 0, m - 1)]; + bin.y += k; bin.push(data[i]); } - // Convert frequencies to probabilities. - if (!frequency) for (var i = 0; i < bins.length; i++) { - bins[i].y /= x.length; - } - return bins; } histogram.frequency = function(x) { if (!arguments.length) return frequency; - frequency = Boolean(x); + frequency = !!x; return histogram; }; @@ -53,18 +51,6 @@ d3.layout.histogram = function() { return histogram; }; -// Performs a binary search on a sorted array. -function d3_layout_histogramSearch(array, value) { - var low = 1, high = array.length - 2; - while (low <= high) { - var mid = (low + high) >> 1, midValue = array[mid]; - if (midValue < value) low = mid + 1; - else if (midValue > value) high = mid - 1; - else return mid; - } - return low - 1; -} - function d3_layout_histogramTicks(x) { return d3.scale.linear().domain(x).ticks(10); } diff --git a/src/scale/polylinear.js b/src/scale/polylinear.js index 1eb5d272..8f9cc869 100644 --- a/src/scale/polylinear.js +++ b/src/scale/polylinear.js @@ -9,19 +9,8 @@ function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { i.push(interpolate(range[j - 1], range[j])); } - function search(x) { - var low = 1, high = domain.length - 2; - while (low <= high) { - var mid = (low + high) >> 1, midValue = domain[mid]; - if (midValue < x) low = mid + 1; - else if (midValue > x) high = mid - 1; - else return mid; - } - return low - 1; - } - return function(x) { - var j = search(x); + var j = d3.bisect(domain, x, 1, domain.length - 1) - 1; return i[j](u[j](x)); }; } diff --git a/src/scale/quantile.js b/src/scale/quantile.js index 5968f131..18ec40ca 100644 --- a/src/scale/quantile.js +++ b/src/scale/quantile.js @@ -4,26 +4,21 @@ d3.scale.quantile = function() { thresholds = []; function rescale() { - var i = -1, - n = thresholds.length = range.length, - k = domain.length / n; - while (++i < n) thresholds[i] = domain[~~(i * k)]; - } - - function quantile(value) { - if (isNaN(value = +value)) return NaN; - var low = 0, high = thresholds.length - 1; - while (low <= high) { - var mid = (low + high) >> 1, midValue = thresholds[mid]; - if (midValue < value) low = mid + 1; - else if (midValue > value) high = mid - 1; - else return mid; + var k = 0, + n = domain.length, + q = range.length, + i; + thresholds.length = Math.max(0, q - 1); + while (++k < q) { + i = n * k / q; + if (i % 1) thresholds[k - 1] = domain[~~i]; + else thresholds[k - 1] = (domain[i = ~~i] + domain[i - 1]) / 2; } - return high < 0 ? 0 : high; } function scale(x) { - return range[quantile(x)]; + if (isNaN(x = +x)) return NaN; + return range[d3.bisect(thresholds, x)]; } scale.domain = function(x) { diff --git a/tests/test-bisect.js b/tests/test-bisect.js new file mode 100644 index 00000000..5089863e --- /dev/null +++ b/tests/test-bisect.js @@ -0,0 +1,66 @@ +require("./../lib/env-js/envjs/node"); +require("./../d3"); + +var a = [1,2,3,4], + l = d3.bisectLeft, + r = d3.bisectRight; + +console.log("exact match:"); +console.log(" -1 ->", l(a, -1), r(a, -1)); +console.log(" 0 ->", l(a, 0), r(a, 0)); +console.log(" 1 ->", l(a, 1), r(a, 1)); +console.log(" 2 ->", l(a, 2), r(a, 2)); +console.log(" 3 ->", l(a, 3), r(a, 3)); +console.log(" 4 ->", l(a, 4), r(a, 4)); +console.log(" 5 ->", l(a, 5), r(a, 5)); +console.log(""); + +console.log("non-exact match:"); +console.log(" -.1 ->", l(a, -.1), r(a, -.1)); +console.log(" .1 ->", l(a, .1), r(a, .1)); +console.log(" 1.1 ->", l(a, 1.1), r(a, 1.1)); +console.log(" 2.1 ->", l(a, 2.1), r(a, 2.1)); +console.log(" 3.1 ->", l(a, 3.1), r(a, 3.1)); +console.log(" 4.1 ->", l(a, 4.1), r(a, 4.1)); +console.log(" 5.1 ->", l(a, 5.1), r(a, 5.1)); +console.log(""); + +console.log("weird values:"); +console.log(" NaN ->", l(a, NaN), r(a, NaN)); +console.log(" Infinity ->", l(a, Infinity), r(a, Infinity)); +console.log(" -Infinity ->", l(a, -Infinity), r(a, -Infinity)); +console.log(""); + +console.log("d3.bisect === d3.bisectRight:"); +console.log(" ", d3.bisect === r); +console.log(""); + +console.log("lo:"); +console.log(" -1 ->", l(a, -1, 2), r(a, -1, 2)); +console.log(" 0 ->", l(a, 0, 2), r(a, 0, 2)); +console.log(" 1 ->", l(a, 1, 2), r(a, 1, 2)); +console.log(" 2 ->", l(a, 2, 2), r(a, 2, 2)); +console.log(" 3 ->", l(a, 3, 2), r(a, 3, 2)); +console.log(" 4 ->", l(a, 4, 2), r(a, 4, 2)); +console.log(" 5 ->", l(a, 5, 2), r(a, 5, 2)); +console.log(""); + +console.log("hi:"); +console.log(" -1 ->", l(a, -1, 0, 2), r(a, -1, 0, 2)); +console.log(" 0 ->", l(a, 0, 0, 2), r(a, 0, 0, 2)); +console.log(" 1 ->", l(a, 1, 0, 2), r(a, 1, 0, 2)); +console.log(" 2 ->", l(a, 2, 0, 2), r(a, 2, 0, 2)); +console.log(" 3 ->", l(a, 3, 0, 2), r(a, 3, 0, 2)); +console.log(" 4 ->", l(a, 4, 0, 2), r(a, 4, 0, 2)); +console.log(" 5 ->", l(a, 5, 0, 2), r(a, 5, 0, 2)); +console.log(""); + +console.log("lo and hi:"); +console.log(" -1 ->", l(a, -1, 1, 3), r(a, -1, 1, 3)); +console.log(" 0 ->", l(a, 0, 1, 3), r(a, 0, 1, 3)); +console.log(" 1 ->", l(a, 1, 1, 3), r(a, 1, 1, 3)); +console.log(" 2 ->", l(a, 2, 1, 3), r(a, 2, 1, 3)); +console.log(" 3 ->", l(a, 3, 1, 3), r(a, 3, 1, 3)); +console.log(" 4 ->", l(a, 4, 1, 3), r(a, 4, 1, 3)); +console.log(" 5 ->", l(a, 5, 1, 3), r(a, 5, 1, 3)); +console.log(""); diff --git a/tests/test-bisect.out b/tests/test-bisect.out new file mode 100644 index 00000000..b556385c --- /dev/null +++ b/tests/test-bisect.out @@ -0,0 +1,53 @@ +exact match: + -1 -> 0 0 + 0 -> 0 0 + 1 -> 0 1 + 2 -> 1 2 + 3 -> 2 3 + 4 -> 3 4 + 5 -> 4 4 + +non-exact match: + -.1 -> 0 0 + .1 -> 0 0 + 1.1 -> 1 1 + 2.1 -> 2 2 + 3.1 -> 3 3 + 4.1 -> 4 4 + 5.1 -> 4 4 + +weird values: + NaN -> 0 4 + Infinity -> 4 4 + -Infinity -> 0 0 + +d3.bisect === d3.bisectRight: + true + +lo: + -1 -> 2 2 + 0 -> 2 2 + 1 -> 2 2 + 2 -> 2 2 + 3 -> 2 3 + 4 -> 3 4 + 5 -> 4 4 + +hi: + -1 -> 0 0 + 0 -> 0 0 + 1 -> 0 1 + 2 -> 1 2 + 3 -> 2 2 + 4 -> 2 2 + 5 -> 2 2 + +lo and hi: + -1 -> 1 1 + 0 -> 1 1 + 1 -> 1 1 + 2 -> 1 2 + 3 -> 2 3 + 4 -> 3 3 + 5 -> 3 3 + diff --git a/tests/test-scale-polylinear.js b/tests/test-scale-polylinear.js index 23c83278..0e9c7061 100644 --- a/tests/test-scale-polylinear.js +++ b/tests/test-scale-polylinear.js @@ -1,10 +1,30 @@ require("./../lib/env-js/envjs/node"); require("./../d3"); +var f = d3.format(" .3f"); + var x = d3.scale.linear().domain([-1, 0, 1]).range(["red", "white", "green"]); -console.log("domain([-1, 0, 1]).range([\"red\", \"white\", \"green\"]):"); -console.log(" -0.5 -> ", x(-0.5)); -console.log(" 0.0 -> ", x(0.0)); -console.log(" 0.5 -> ", x(0.5)); -console.log(" 1.0 -> ", x(1.0)); +console.log("domain(-1, 0, 1).range(red, white, green):"); +console.log(" -1.0 -> " + x(-1)); +console.log(" -0.8 -> " + x(-.8)); +console.log(" -0.6 -> " + x(-.6)); +console.log(" -0.4 -> " + x(-.4)); +console.log(" -0.2 -> " + x(-.2)); +console.log(" 0.0 -> " + x(0)); +console.log(" 0.2 -> " + x(.2)); +console.log(" 0.4 -> " + x(.4)); +console.log(" 0.6 -> " + x(.6)); +console.log(" 0.8 -> " + x(.8)); +console.log(" 1.0 -> " + x(1)); +console.log(""); + +var x = d3.scale.linear().domain([-1, 0, 1]).range([-100, 0, 10]); +console.log("domain(-1, 0, 1).range(-100, 0, 10):"); +console.log(" -1.5 -> " + f(x(-1.5))); +console.log(" -1.0 -> " + f(x(-1))); +console.log(" -0.5 -> " + f(x(-.5))); +console.log(" 0.0 -> " + f(x(0))); +console.log(" 0.5 -> " + f(x(.5))); +console.log(" 1.0 -> " + f(x(1))); +console.log(" 1.5 -> " + f(x(1.5))); console.log(""); diff --git a/tests/test-scale-polylinear.out b/tests/test-scale-polylinear.out index 47f31392..bdd50860 100644 --- a/tests/test-scale-polylinear.out +++ b/tests/test-scale-polylinear.out @@ -1,6 +1,22 @@ -domain([-1, 0, 1]).range(["red", "white", "green"]): - -0.5 -> rgb(255,128,128) - 0.0 -> rgb(255,255,255) - 0.5 -> rgb(128,192,128) - 1.0 -> rgb(0,128,0) +domain(-1, 0, 1).range(red, white, green): + -1.0 -> rgb(255,0,0) + -0.8 -> rgb(255,51,51) + -0.6 -> rgb(255,102,102) + -0.4 -> rgb(255,153,153) + -0.2 -> rgb(255,204,204) + 0.0 -> rgb(255,255,255) + 0.2 -> rgb(204,230,204) + 0.4 -> rgb(153,204,153) + 0.6 -> rgb(102,179,102) + 0.8 -> rgb(51,153,51) + 1.0 -> rgb(0,128,0) + +domain(-1, 0, 1).range(-100, 0, 10): + -1.5 -> −150.000 + -1.0 -> −100.000 + -0.5 -> −50.000 + 0.0 -> 0.000 + 0.5 -> 5.000 + 1.0 -> 10.000 + 1.5 -> 15.000 diff --git a/tests/test-scale-quantile.js b/tests/test-scale-quantile.js new file mode 100644 index 00000000..382bb785 --- /dev/null +++ b/tests/test-scale-quantile.js @@ -0,0 +1,142 @@ +require("./../lib/env-js/envjs/node"); +require("./../d3"); + +var x = d3.scale.quantile() + .domain([3, 6, 7, 8, 8, 10, 13, 15, 16, 20]) + .range([0, 1, 2, 3]); + +console.log("domain(3, 6, 7, 8, 8, 10, 13, 15, 16, 20).range(0, 1, 2, 3):"); +console.log(" quantiles -> " + x.quantiles()); +console.log(" 3 -> " + x(3)); +console.log(" 6 -> " + x(6)); +console.log(" 6.9 -> " + x(6.9)); +console.log(" 7 -> " + x(7)); +console.log(" 7.1 -> " + x(7.1)); +console.log(" 8 -> " + x(8)); +console.log(" 8.9 -> " + x(8.9)); +console.log(" 9 -> " + x(9)); +console.log(" 9.1 -> " + x(9.1)); +console.log(" 10 -> " + x(10)); +console.log(" 13 -> " + x(13)); +console.log(" 14.9 -> " + x(14.9)); +console.log(" 15 -> " + x(15)); +console.log(" 15.1 -> " + x(15.1)); +console.log(" 16 -> " + x(16)); +console.log(" 20 -> " + x(20)); +console.log(""); + +var x = d3.scale.quantile() + .domain([3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20]) + .range([0, 1, 2, 3]); + +console.log("domain(3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20).range(0, 1, 2, 3):"); +console.log(" quantiles -> " + x.quantiles()); +console.log(" 3 -> " + x(3)); +console.log(" 6 -> " + x(6)); +console.log(" 6.9 -> " + x(6.9)); +console.log(" 7 -> " + x(7)); +console.log(" 7.1 -> " + x(7.1)); +console.log(" 8 -> " + x(8)); +console.log(" 8.9 -> " + x(8.9)); +console.log(" 9 -> " + x(9)); +console.log(" 9.1 -> " + x(9.1)); +console.log(" 10 -> " + x(10)); +console.log(" 13 -> " + x(13)); +console.log(" 14.9 -> " + x(14.9)); +console.log(" 15 -> " + x(15)); +console.log(" 15.1 -> " + x(15.1)); +console.log(" 16 -> " + x(16)); +console.log(" 20 -> " + x(20)); +console.log(""); + +var x = d3.scale.quantile() + .domain([0, 1]) + .range([0, 1]); + +console.log("domain(0, 1).range(0, 1):"); +console.log(" quantiles -> " + x.quantiles()); +console.log(" -.5 -> " + x(-.5)); +console.log(" 0 -> " + x(0)); +console.log(" .49 -> " + x(.49)); +console.log(" .51 -> " + x(.51)); +console.log(" 1 -> " + x(1)); +console.log(" 1.5 -> " + x(1.5)); +console.log(""); + +var x = d3.scale.quantile() + .domain([1, 2, 3, 4]) + .range(["a", "b"]); + +console.log("domain(1, 2, 3, 4).range(a, b):"); +console.log(" quantiles -> " + x.quantiles()); +console.log(" 0 -> " + x(0)); +console.log(" 1 -> " + x(1)); +console.log(" 2 -> " + x(2)); +console.log(" 2.49 -> " + x(2.49)); +console.log(" 2.51 -> " + x(2.51)); +console.log(" 3 -> " + x(3)); +console.log(" 4 -> " + x(4)); +console.log(" 5 -> " + x(5)); +console.log(""); + +var x = d3.scale.quantile() + .domain([1, 2, 3, 4]) + .range(["a", "b", "c"]); + +console.log("domain(1, 2, 3, 4).range(a, b, c):"); +console.log(" quantiles -> " + x.quantiles()); +console.log(" 0 -> " + x(0)); +console.log(" 1 -> " + x(1)); +console.log(" 1.9 -> " + x(1.9)); +console.log(" 2 -> " + x(2)); +console.log(" 2.1 -> " + x(2.1)); +console.log(" 2.9 -> " + x(2.9)); +console.log(" 3 -> " + x(3)); +console.log(" 3.1 -> " + x(3.1)); +console.log(" 4 -> " + x(4)); +console.log(" 5 -> " + x(5)); +console.log(""); + +var x = d3.scale.quantile() + .domain([1, 1, 2, 2, 3, 3, 4, 4]) + .range(["a", "b", "c", "d"]); + +console.log("domain(1, 1, 2, 2, 3, 3, 4, 4).range(a, b, c, d):"); +console.log(" quantiles -> " + x.quantiles()); +console.log(" 0 -> " + x(0)); +console.log(" 1 -> " + x(1)); +console.log(" 1.49 -> " + x(1.49)); +console.log(" 1.51 -> " + x(1.51)); +console.log(" 2 -> " + x(2)); +console.log(" 2.49 -> " + x(2.49)); +console.log(" 2.51 -> " + x(2.51)); +console.log(" 3 -> " + x(3)); +console.log(" 3.49 -> " + x(3.49)); +console.log(" 3.51 -> " + x(3.51)); +console.log(" 4 -> " + x(4)); +console.log(" 5 -> " + x(5)); +console.log(""); + +var x = d3.scale.quantile() + .domain([1, 2, 3, 4, 5, 6, 7, 8]) + .range(["a", "b", "c", "d"]); + +console.log("domain(1, 2, 3, 4, 5, 6, 7, 8).range(a, b, c, d):"); +console.log(" quantiles -> " + x.quantiles()); +console.log(" 0 -> " + x(0)); +console.log(" 1 -> " + x(1)); +console.log(" 2 -> " + x(2)); +console.log(" 2.49 -> " + x(2.49)); +console.log(" 2.51 -> " + x(2.51)); +console.log(" 3 -> " + x(3)); +console.log(" 4 -> " + x(4)); +console.log(" 4.49 -> " + x(4.49)); +console.log(" 4.51 -> " + x(4.51)); +console.log(" 5 -> " + x(5)); +console.log(" 6 -> " + x(6)); +console.log(" 6.49 -> " + x(6.49)); +console.log(" 6.51 -> " + x(6.51)); +console.log(" 7 -> " + x(7)); +console.log(" 8 -> " + x(8)); +console.log(" 9 -> " + x(9)); +console.log(""); diff --git a/tests/test-scale-quantile.out b/tests/test-scale-quantile.out new file mode 100644 index 00000000..c95e8e90 --- /dev/null +++ b/tests/test-scale-quantile.out @@ -0,0 +1,105 @@ +domain(3, 6, 7, 8, 8, 10, 13, 15, 16, 20).range(0, 1, 2, 3): + quantiles -> 7,9,15 + 3 -> 0 + 6 -> 0 + 6.9 -> 0 + 7 -> 1 + 7.1 -> 1 + 8 -> 1 + 8.9 -> 1 + 9 -> 2 + 9.1 -> 2 + 10 -> 2 + 13 -> 2 + 14.9 -> 2 + 15 -> 3 + 15.1 -> 3 + 16 -> 3 + 20 -> 3 + +domain(3, 6, 7, 8, 8, 9, 10, 13, 15, 16, 20).range(0, 1, 2, 3): + quantiles -> 7,9,15 + 3 -> 0 + 6 -> 0 + 6.9 -> 0 + 7 -> 1 + 7.1 -> 1 + 8 -> 1 + 8.9 -> 1 + 9 -> 2 + 9.1 -> 2 + 10 -> 2 + 13 -> 2 + 14.9 -> 2 + 15 -> 3 + 15.1 -> 3 + 16 -> 3 + 20 -> 3 + +domain(0, 1).range(0, 1): + quantiles -> 0.5 + -.5 -> 0 + 0 -> 0 + .49 -> 0 + .51 -> 1 + 1 -> 1 + 1.5 -> 1 + +domain(1, 2, 3, 4).range(a, b): + quantiles -> 2.5 + 0 -> a + 1 -> a + 2 -> a + 2.49 -> a + 2.51 -> b + 3 -> b + 4 -> b + 5 -> b + +domain(1, 2, 3, 4).range(a, b, c): + quantiles -> 2,3 + 0 -> a + 1 -> a + 1.9 -> a + 2 -> b + 2.1 -> b + 2.9 -> b + 3 -> c + 3.1 -> c + 4 -> c + 5 -> c + +domain(1, 1, 2, 2, 3, 3, 4, 4).range(a, b, c, d): + quantiles -> 1.5,2.5,3.5 + 0 -> a + 1 -> a + 1.49 -> a + 1.51 -> b + 2 -> b + 2.49 -> b + 2.51 -> c + 3 -> c + 3.49 -> c + 3.51 -> d + 4 -> d + 5 -> d + +domain(1, 2, 3, 4, 5, 6, 7, 8).range(a, b, c, d): + quantiles -> 2.5,4.5,6.5 + 0 -> a + 1 -> a + 2 -> a + 2.49 -> a + 2.51 -> b + 3 -> b + 4 -> b + 4.49 -> b + 4.51 -> c + 5 -> c + 6 -> c + 6.49 -> c + 6.51 -> d + 7 -> d + 8 -> d + 9 -> d +