Skip to content
Snippets Groups Projects
Commit b4b329be authored by David Sehnal's avatar David Sehnal
Browse files

ArrayColumn

parent d5f7cc60
No related branches found
No related tags found
No related merge requests found
...@@ -24,7 +24,11 @@ class Builder { ...@@ -24,7 +24,11 @@ class Builder {
beginUnit() { this.currentUnit = []; } beginUnit() { this.currentUnit = []; }
addToUnit(a: number) { this.currentUnit[this.currentUnit.length] = a; } addToUnit(a: number) { this.currentUnit[this.currentUnit.length] = a; }
commitUnit(u: number) { if (this.currentUnit.length === 0) return; this.keys[this.keys.length] = u; this.units[u] = this.currentUnit; } commitUnit(u: number) {
if (this.currentUnit.length === 0) return;
this.keys[this.keys.length] = u;
this.units[u] = this.currentUnit;
}
getSet(): AtomSet { getSet(): AtomSet {
const sets: { [key: number]: OrderedSet } = Object.create(null); const sets: { [key: number]: OrderedSet } = Object.create(null);
......
...@@ -59,9 +59,10 @@ export namespace Field { ...@@ -59,9 +59,10 @@ export namespace Field {
export function vector(rows: number, spec?: Spec) { return createSchema(spec, Vector(rows)); } export function vector(rows: number, spec?: Spec) { return createSchema(spec, Vector(rows)); }
export function matrix(rows: number, cols: number, spec?: Spec) { return createSchema(spec, Matrix(rows, cols)); } export function matrix(rows: number, cols: number, spec?: Spec) { return createSchema(spec, Matrix(rows, cols)); }
function create<T>(field: Data.Field, value: (row: number) => T, toArray: Column.Column<T>['toArray']): Column.Column<T> { function create<T>(type: Column.ColumnType, field: Data.Field, value: (row: number) => T, toArray: Column.Column<T>['toArray']): Column.Column<T> {
const presence = field.presence; const presence = field.presence;
return { return {
'@type': type,
isDefined: field.isDefined, isDefined: field.isDefined,
rowCount: field.rowCount, rowCount: field.rowCount,
value, value,
...@@ -76,23 +77,23 @@ export namespace Field { ...@@ -76,23 +77,23 @@ export namespace Field {
const pool = StringPool.create(); const pool = StringPool.create();
const value = (row: number) => StringPool.get(pool, field.str(row)); const value = (row: number) => StringPool.get(pool, field.str(row));
const array = (params?: Column.ToArrayParams) => Column.createAndFillArray(field.rowCount, value, params); const array = (params?: Column.ToArrayParams) => Column.createAndFillArray(field.rowCount, value, params);
return create<string>(field, value, array); return create<string>(Column.ColumnType.str, field, value, array);
} }
function Str(field: Data.Field) { return create(field, field.str, field.toStringArray); } function Str(field: Data.Field) { return create(Column.ColumnType.str, field, field.str, field.toStringArray); }
function Int(field: Data.Field) { return create(field, field.int, field.toIntArray); } function Int(field: Data.Field) { return create(Column.ColumnType.int, field, field.int, field.toIntArray); }
function Float(field: Data.Field) { return create(field, field.float, field.toFloatArray); } function Float(field: Data.Field) { return create(Column.ColumnType.float, field, field.float, field.toFloatArray); }
function Vector(rows: number) { function Vector(rows: number) {
return function(field: Data.Field, category: Data.Category, key: string) { return function(field: Data.Field, category: Data.Category, key: string) {
const value = (row: number) => Data.getVector(category, key, rows, row); const value = (row: number) => Data.getVector(category, key, rows, row);
return create(field, value, params => Column.createAndFillArray(field.rowCount, value, params)); return create(Column.ColumnType.vector, field, value, params => Column.createAndFillArray(field.rowCount, value, params));
} }
} }
function Matrix(rows: number, cols: number) { function Matrix(rows: number, cols: number) {
return function(field: Data.Field, category: Data.Category, key: string) { return function(field: Data.Field, category: Data.Category, key: string) {
const value = (row: number) => Data.getMatrix(category, key, rows, cols, row); const value = (row: number) => Data.getMatrix(category, key, rows, cols, row);
return create(field, value, params => Column.createAndFillArray(field.rowCount, value, params)); return create(Column.ColumnType.matrix, field, value, params => Column.createAndFillArray(field.rowCount, value, params));
} }
} }
......
...@@ -4,13 +4,14 @@ ...@@ -4,13 +4,14 @@
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
*/ */
export type ColumnType = typeof ColumnType.str | typeof ColumnType.pooledStr | typeof ColumnType.int | typeof ColumnType.float export type ColumnType = typeof ColumnType.str | typeof ColumnType.int | typeof ColumnType.float | typeof ColumnType.vector | typeof ColumnType.matrix
export namespace ColumnType { export namespace ColumnType {
export const str = { '@type': '' as string, kind: 'str' as 'str' }; export const str = { '@type': '' as string, kind: 'str' as 'str', isScalar: false };
export const pooledStr = { '@type': '' as string, kind: 'pooled-str' as 'pooled-str' }; export const int = { '@type': 0 as number, kind: 'int' as 'int', isScalar: true };
export const int = { '@type': 0 as number, kind: 'int' as 'int' }; export const float = { '@type': 0 as number, kind: 'float' as 'float', isScalar: true };
export const float = { '@type': 0 as number, kind: 'float' as 'float' }; export const vector = { '@type': [] as number[], kind: 'vector' as 'vector', isScalar: false };
export const matrix = { '@type': [] as number[][], kind: 'matrix' as 'matrix', isScalar: false };
} }
export interface ToArrayParams { export interface ToArrayParams {
...@@ -22,6 +23,7 @@ export interface ToArrayParams { ...@@ -22,6 +23,7 @@ export interface ToArrayParams {
} }
export interface Column<T> { export interface Column<T> {
readonly '@type': ColumnType,
readonly isDefined: boolean, readonly isDefined: boolean,
readonly rowCount: number, readonly rowCount: number,
value(row: number): T, value(row: number): T,
...@@ -34,6 +36,7 @@ export interface Column<T> { ...@@ -34,6 +36,7 @@ export interface Column<T> {
export function UndefinedColumn<T extends ColumnType>(rowCount: number, type: T): Column<T['@type']> { export function UndefinedColumn<T extends ColumnType>(rowCount: number, type: T): Column<T['@type']> {
const value: Column<T['@type']>['value'] = type.kind === 'str' ? row => '' : row => 0; const value: Column<T['@type']>['value'] = type.kind === 'str' ? row => '' : row => 0;
return { return {
'@type': type,
isDefined: false, isDefined: false,
rowCount, rowCount,
value, value,
...@@ -48,34 +51,48 @@ export function UndefinedColumn<T extends ColumnType>(rowCount: number, type: T) ...@@ -48,34 +51,48 @@ export function UndefinedColumn<T extends ColumnType>(rowCount: number, type: T)
} }
} }
export function ArrayColumn<T>(array: ArrayLike<T>): Column<T> { export interface ArrayColumnSpec<T extends ColumnType> {
array: ArrayLike<T['@type']>,
type: T,
isValueDefined?: (row: number) => boolean
}
export function ArrayColumn<T extends ColumnType>({ array, type, isValueDefined }: ArrayColumnSpec<T>): Column<T['@type']> {
const rowCount = array.length; const rowCount = array.length;
const value: Column<T>['value'] = row => array[row]; const value: Column<T['@type']>['value'] = row => array[row];
const isTyped = isTypedArray(array); const isTyped = isTypedArray(array);
return { return {
isDefined: false, '@type': type,
isDefined: true,
rowCount, rowCount,
value, value,
isValueDefined: row => true, isValueDefined: isValueDefined ? isValueDefined : row => true,
toArray: isTyped toArray: isTyped
? params => typedArrayWindow(array, params) as any as ReadonlyArray<T> ? params => typedArrayWindow(array, params) as any as ReadonlyArray<T>
: params => { : params => {
const { start, end } = getArrayBounds(rowCount, params); const { start, end } = getArrayBounds(rowCount, params);
const ret = new Array(end - start); if (start === 0 && end === array.length) return array as ReadonlyArray<T['@type']>;
const ret = new (params && typeof params.array !== 'undefined' ? params.array : (array as any).constructor)(end - start) as any;
for (let i = 0, _i = end - start; i < _i; i++) ret[i] = array[start + i]; for (let i = 0, _i = end - start; i < _i; i++) ret[i] = array[start + i];
return ret; return ret;
}, },
stringEquals: isTyped stringEquals: isTyped
? (row, value) => (array as any)[row] === +value ? (row, value) => (array as any)[row] === +value
: (row, value) => { : type.kind === 'str'
const v = array[row]; ? (row, value) => array[row] === value
if (typeof v !== 'string') return '' + v === value; : type.isScalar
return v === value; ? (row, value) => array[row] === '' + value
}, : (row, value) => false,
areValuesEqual: (rowA, rowB) => array[rowA] === array[rowB] areValuesEqual: (rowA, rowB) => array[rowA] === array[rowB]
} }
} }
/** Makes the column backned by an array. Useful for columns that accessed often. */
export function toArrayColumn<T>(c: Column<T>): Column<T> {
if (!c.isDefined) return UndefinedColumn(c.rowCount, c['@type']) as any as Column<T>;
return ArrayColumn({ array: c.toArray(), type: c['@type'] as any, isValueDefined: c.isValueDefined });
}
/** A helped function for Column.toArray */ /** A helped function for Column.toArray */
export function getArrayBounds(rowCount: number, params?: ToArrayParams) { export function getArrayBounds(rowCount: number, params?: ToArrayParams) {
const start = params && typeof params.start !== 'undefined' ? Math.max(Math.min(params.start, rowCount - 1), 0) : 0; const start = params && typeof params.start !== 'undefined' ? Math.max(Math.min(params.start, rowCount - 1), 0) : 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment