Skip to content

Commit f527ebe

Browse files
committed
Tweaks
1 parent 57c43e1 commit f527ebe

File tree

4 files changed

+38
-19
lines changed

4 files changed

+38
-19
lines changed

b+tree.d.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,27 @@ export declare type DefaultComparable = number | string | Date | boolean | null
1616
*
1717
* Handles +/-0 and NaN like Map: NaN is equal to NaN, and -0 is equal to +0.
1818
*
19-
* Arrays are compared using '<' and '>', which may cause unexpected equality: for example [1] will be considered equal to ['1'].
19+
* Arrays are compared using '<' and '>', which may cause unexpected equality:
20+
* for example [1] will be considered equal to ['1'].
2021
*
21-
* Two objects with equal valueOf compare the same, but compare unequal to primitives that have the same value.
22+
* Two objects with equal valueOf compare the same, but compare unequal to
23+
* primitives that have the same value.
2224
*/
2325
export declare function defaultComparator(a: DefaultComparable, b: DefaultComparable): number;
2426
/**
2527
* Compares items using the < and > operators. This function is probably slightly
2628
* faster than the defaultComparator for Dates and strings, but has not been benchmarked.
2729
* Unlike defaultComparator, this comparator doesn't support mixed types correctly,
28-
* i.e. use it with `BTree<string>` or `BTree<Date>` but not `BTree<string|Date>`.
30+
* i.e. use it with `BTree<string>` or `BTree<number>` but not `BTree<string|number>`.
2931
*
30-
* Note: null compares as less than any number or Date, but in general null is
31-
* incomparable with strings, and undefined is not comparable with other types
32-
* using the > and < operators
32+
* Note: null is treated like 0 when compared with numbers or Date, but in general
33+
* null is not ordered with respect to strings (neither greater nor less), and
34+
* undefined is not ordered with other types.
3335
*/
3436
export declare function simpleComparator(a: string, b: string): number;
3537
export declare function simpleComparator(a: number | null, b: number | null): number;
3638
export declare function simpleComparator(a: Date | null, b: Date | null): number;
39+
export declare function simpleComparator(a: (number | string)[], b: (number | string)[]): number;
3740
/**
3841
* A reasonably fast collection of key-value pairs with a powerful API.
3942
* Largely compatible with the standard Map. BTree is a B+ tree data structure,

b+tree.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ exports.EmptyBTree = exports.simpleComparator = exports.defaultComparator = void
1919
*
2020
* Handles +/-0 and NaN like Map: NaN is equal to NaN, and -0 is equal to +0.
2121
*
22-
* Arrays are compared using '<' and '>', which may cause unexpected equality: for example [1] will be considered equal to ['1'].
22+
* Arrays are compared using '<' and '>', which may cause unexpected equality:
23+
* for example [1] will be considered equal to ['1'].
2324
*
24-
* Two objects with equal valueOf compare the same, but compare unequal to primitives that have the same value.
25+
* Two objects with equal valueOf compare the same, but compare unequal to
26+
* primitives that have the same value.
2527
*/
2628
function defaultComparator(a, b) {
2729
// Special case finite numbers first for performance.
@@ -66,7 +68,8 @@ function defaultComparator(a, b) {
6668
return Number.isNaN(b) ? 0 : -1;
6769
else if (Number.isNaN(b))
6870
return 1;
69-
return 0; // unreachable?
71+
// This could be two objects (e.g. [7] and ['7']), that aren't greater or less
72+
return Array.isArray(a) ? 0 : Number.NaN;
7073
}
7174
exports.defaultComparator = defaultComparator;
7275
;
@@ -756,8 +759,12 @@ var BTree = /** @class */ (function () {
756759
};
757760
/** Ensures mutations are allowed, reversing the effect of freeze(). */
758761
BTree.prototype.unfreeze = function () {
762+
// @ts-ignore "The operand of a 'delete' operator must be optional."
763+
// (wrong: delete does not affect the prototype.)
759764
delete this.clear;
765+
// @ts-ignore
760766
delete this.set;
767+
// @ts-ignore
761768
delete this.editRange;
762769
};
763770
Object.defineProperty(BTree.prototype, "isFrozen", {
@@ -812,7 +819,6 @@ var BNode = /** @class */ (function () {
812819
// If key not found, returns i^failXor where i is the insertion index.
813820
// Callers that don't care whether there was a match will set failXor=0.
814821
BNode.prototype.indexOf = function (key, failXor, cmp) {
815-
// TODO: benchmark multiple search strategies
816822
var keys = this.keys;
817823
var lo = 0, hi = keys.length, mid = hi >> 1;
818824
while (lo < hi) {

b+tree.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ function testComparison(comparison: (a: any, b: any) => number, inOrder: any[],
7979
function compare(a: any, b: any): number {
8080
const v = comparison(a, b);
8181
expect(typeof v).toEqual('number');
82+
if (v !== v)
83+
console.log('!!!', a, b);
8284
expect(v === v).toEqual(true); // Not NaN
8385
return Math.sign(v);
8486
}

b+tree.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,19 @@ type index = number;
3333
/**
3434
* Types that BTree supports by default
3535
*/
36-
export type DefaultComparable = number | string | Date | boolean | null | undefined | (number | string)[] | { valueOf: ()=> number | string | Date | boolean | null | undefined | (number | string)[] };
36+
export type DefaultComparable = number | string | Date | boolean | null | undefined | (number | string)[] |
37+
{ valueOf: () => number | string | Date | boolean | null | undefined | (number | string)[] };
3738

3839
/**
3940
* Compares DefaultComparables to form a strict partial ordering.
4041
*
4142
* Handles +/-0 and NaN like Map: NaN is equal to NaN, and -0 is equal to +0.
4243
*
43-
* Arrays are compared using '<' and '>', which may cause unexpected equality: for example [1] will be considered equal to ['1'].
44+
* Arrays are compared using '<' and '>', which may cause unexpected equality:
45+
* for example [1] will be considered equal to ['1'].
4446
*
45-
* Two objects with equal valueOf compare the same, but compare unequal to primitives that have the same value.
47+
* Two objects with equal valueOf compare the same, but compare unequal to
48+
* primitives that have the same value.
4649
*/
4750
export function defaultComparator(a: DefaultComparable, b: DefaultComparable): number {
4851
// Special case finite numbers first for performance.
@@ -89,22 +92,24 @@ export function defaultComparator(a: DefaultComparable, b: DefaultComparable): n
8992
return Number.isNaN(b) ? 0 : -1;
9093
else if (Number.isNaN(b))
9194
return 1;
92-
return 0; // unreachable?
95+
// This could be two objects (e.g. [7] and ['7']) that aren't ordered
96+
return Array.isArray(a) ? 0 : Number.NaN;
9397
};
9498

9599
/**
96100
* Compares items using the < and > operators. This function is probably slightly
97101
* faster than the defaultComparator for Dates and strings, but has not been benchmarked.
98102
* Unlike defaultComparator, this comparator doesn't support mixed types correctly,
99-
* i.e. use it with `BTree<string>` or `BTree<Date>` but not `BTree<string|Date>`.
103+
* i.e. use it with `BTree<string>` or `BTree<number>` but not `BTree<string|number>`.
100104
*
101-
* Note: null compares as less than any number or Date, but in general null is
102-
* incomparable with strings, and undefined is not comparable with other types
103-
* using the > and < operators
105+
* Note: null is treated like 0 when compared with numbers or Date, but in general
106+
* null is not ordered with respect to strings (neither greater nor less), and
107+
* undefined is not ordered with other types.
104108
*/
105109
export function simpleComparator(a: string, b:string): number;
106110
export function simpleComparator(a: number|null, b:number|null): number;
107111
export function simpleComparator(a: Date|null, b:Date|null): number;
112+
export function simpleComparator(a: (number|string)[], b:(number|string)[]): number;
108113
export function simpleComparator(a: any, b: any): number {
109114
return a > b ? 1 : a < b ? -1 : 0;
110115
};
@@ -848,8 +853,12 @@ export default class BTree<K=any, V=any> implements ISortedMapF<K,V>, ISortedMap
848853

849854
/** Ensures mutations are allowed, reversing the effect of freeze(). */
850855
unfreeze() {
856+
// @ts-ignore "The operand of a 'delete' operator must be optional."
857+
// (wrong: delete does not affect the prototype.)
851858
delete this.clear;
859+
// @ts-ignore
852860
delete this.set;
861+
// @ts-ignore
853862
delete this.editRange;
854863
}
855864

@@ -907,7 +916,6 @@ class BNode<K,V> {
907916
// If key not found, returns i^failXor where i is the insertion index.
908917
// Callers that don't care whether there was a match will set failXor=0.
909918
indexOf(key: K, failXor: number, cmp: (a:K, b:K) => number): index {
910-
// TODO: benchmark multiple search strategies
911919
const keys = this.keys;
912920
var lo = 0, hi = keys.length, mid = hi >> 1;
913921
while(lo < hi) {

0 commit comments

Comments
 (0)