From 78686cf92a8691b4d0a1430c86b6ba5b24752da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Thu, 7 Apr 2022 17:57:13 +0200 Subject: [PATCH 1/5] fix https://observablehq.com/@weiglemc/demonstrating-issue-with-d3-bins-in-d3v7-4-1-update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit unit test: d3.bin().domain([4, 5])([5]) the issue is that we have removed the last bin, but then want to assign the largest value to it because floor(x1) === x1 I'm not sure if the fix catches all cases… --- src/bin.js | 4 +++- test/bin-test.js | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bin.js b/src/bin.js index 276e0f6e..01d2e542 100644 --- a/src/bin.js +++ b/src/bin.js @@ -84,8 +84,10 @@ export default function bin() { if (isFinite(step)) { if (step > 0) { for (i = 0; i < n; ++i) { - if ((x = values[i]) != null && x0 <= x && x <= x1) { + if ((x = values[i]) != null && x0 <= x && x < x1) { bins[Math.floor((x - x0) / step)].push(data[i]); + } else if (x === x1) { + bins[bins.length - 1].push(data[i]); } } } else if (step < 0) { diff --git a/test/bin-test.js b/test/bin-test.js index 9ee6099d..de0b288b 100644 --- a/test/bin-test.js +++ b/test/bin-test.js @@ -235,6 +235,10 @@ it("bin(data) assigns floating point values to the correct bins", () => { } }); +it("bin(data) assigns integer values to the correct bins", () => { + assert.deepStrictEqual(bin().domain([4, 5])([5]), [box([5], 4, 5)]); +}); + function box(bin, x0, x1) { bin.x0 = x0; bin.x1 = x1; From 907b54a861c2b5126a48c41fcc64d66eea7c0858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Thu, 7 Apr 2022 18:10:23 +0200 Subject: [PATCH 2/5] nicer --- src/bin.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/bin.js b/src/bin.js index 01d2e542..e8bb3c8e 100644 --- a/src/bin.js +++ b/src/bin.js @@ -84,10 +84,8 @@ export default function bin() { if (isFinite(step)) { if (step > 0) { for (i = 0; i < n; ++i) { - if ((x = values[i]) != null && x0 <= x && x < x1) { - bins[Math.floor((x - x0) / step)].push(data[i]); - } else if (x === x1) { - bins[bins.length - 1].push(data[i]); + if ((x = values[i]) != null && x0 <= x && x <= x1) { + bins[Math.min(bins.length - 1, Math.floor((x - x0) / step))].push(data[i]); } } } else if (step < 0) { From 3d1b425df251a05d259ff24fe8091e970092df20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Thu, 7 Apr 2022 18:20:33 +0200 Subject: [PATCH 3/5] another test that crashes --- test/bin-test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/bin-test.js b/test/bin-test.js index de0b288b..389e505d 100644 --- a/test/bin-test.js +++ b/test/bin-test.js @@ -237,6 +237,8 @@ it("bin(data) assigns floating point values to the correct bins", () => { it("bin(data) assigns integer values to the correct bins", () => { assert.deepStrictEqual(bin().domain([4, 5])([5]), [box([5], 4, 5)]); + const eights = [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]; + assert.deepStrictEqual(bin().domain([3, 8])(eights), [box([], 3, 4), box([], 4, 5), box([], 5, 6), box([], 6, 7), box(eights, 7, 8)]); }); function box(bin, x0, x1) { From 8d50704d0e94e82c3ac486b6fc41636c92f76604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Thu, 7 Apr 2022 18:27:50 +0200 Subject: [PATCH 4/5] in this case we had step == -1 --- src/bin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin.js b/src/bin.js index e8bb3c8e..8b0aa19e 100644 --- a/src/bin.js +++ b/src/bin.js @@ -92,7 +92,7 @@ export default function bin() { for (i = 0; i < n; ++i) { if ((x = values[i]) != null && x0 <= x && x <= x1) { const j = Math.floor((x0 - x) * step); - bins[j + (tz[j] <= x)].push(data[i]); // handle off-by-one due to rounding + bins[Math.min(bins.length - 1, j + (tz[j] <= x))].push(data[i]); // handle off-by-one due to rounding } } } From ce85eef3e507e87460c18a30d7c881274ca25296 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Thu, 7 Apr 2022 10:35:40 -0700 Subject: [PATCH 5/5] m --- src/bin.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin.js b/src/bin.js index 8b0aa19e..28d64aad 100644 --- a/src/bin.js +++ b/src/bin.js @@ -85,14 +85,14 @@ export default function bin() { if (step > 0) { for (i = 0; i < n; ++i) { if ((x = values[i]) != null && x0 <= x && x <= x1) { - bins[Math.min(bins.length - 1, Math.floor((x - x0) / step))].push(data[i]); + bins[Math.min(m, Math.floor((x - x0) / step))].push(data[i]); } } } else if (step < 0) { for (i = 0; i < n; ++i) { if ((x = values[i]) != null && x0 <= x && x <= x1) { const j = Math.floor((x0 - x) * step); - bins[Math.min(bins.length - 1, j + (tz[j] <= x))].push(data[i]); // handle off-by-one due to rounding + bins[Math.min(m, j + (tz[j] <= x))].push(data[i]); // handle off-by-one due to rounding } } }