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

ArrayColumn

parent d5f7cc60
Branches
Tags
No related merge requests found
......@@ -24,7 +24,11 @@ class Builder {
beginUnit() { this.currentUnit = []; }
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 {
const sets: { [key: number]: OrderedSet } = Object.create(null);
......
......@@ -59,9 +59,10 @@ export namespace Field {
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)); }
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;
return {
'@type': type,
isDefined: field.isDefined,
rowCount: field.rowCount,
value,
......@@ -76,23 +77,23 @@ export namespace Field {
const pool = StringPool.create();
const value = (row: number) => StringPool.get(pool, field.str(row));
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 Int(field: Data.Field) { return create(field, field.int, field.toIntArray); }
function Float(field: Data.Field) { return create(field, field.float, field.toFloatArray); }
function Str(field: Data.Field) { return create(Column.ColumnType.str, field, field.str, field.toStringArray); }
function Int(field: Data.Field) { return create(Column.ColumnType.int, field, field.int, field.toIntArray); }
function Float(field: Data.Field) { return create(Column.ColumnType.float, field, field.float, field.toFloatArray); }
function Vector(rows: number) {
return function(field: Data.Field, category: Data.Category, key: string) {
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) {
return function(field: Data.Field, category: Data.Category, key: string) {
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 @@
* @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 const str = { '@type': '' as string, kind: 'str' as 'str' };
export const pooledStr = { '@type': '' as string, kind: 'pooled-str' as 'pooled-str' };
export const int = { '@type': 0 as number, kind: 'int' as 'int' };
export const float = { '@type': 0 as number, kind: 'float' as 'float' };
export const str = { '@type': '' as string, kind: 'str' as 'str', isScalar: false };
export const int = { '@type': 0 as number, kind: 'int' as 'int', isScalar: true };
export const float = { '@type': 0 as number, kind: 'float' as 'float', isScalar: true };
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 {
......@@ -22,6 +23,7 @@ export interface ToArrayParams {
}
export interface Column<T> {
readonly '@type': ColumnType,
readonly isDefined: boolean,
readonly rowCount: number,
value(row: number): T,
......@@ -34,6 +36,7 @@ export interface Column<T> {
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;
return {
'@type': type,
isDefined: false,
rowCount,
value,
......@@ -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 value: Column<T>['value'] = row => array[row];
const value: Column<T['@type']>['value'] = row => array[row];
const isTyped = isTypedArray(array);
return {
isDefined: false,
'@type': type,
isDefined: true,
rowCount,
value,
isValueDefined: row => true,
isValueDefined: isValueDefined ? isValueDefined : row => true,
toArray: isTyped
? params => typedArrayWindow(array, params) as any as ReadonlyArray<T>
: 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];
return ret;
},
stringEquals: isTyped
? (row, value) => (array as any)[row] === +value
: (row, value) => {
const v = array[row];
if (typeof v !== 'string') return '' + v === value;
return v === value;
},
: type.kind === 'str'
? (row, value) => array[row] === value
: type.isScalar
? (row, value) => array[row] === '' + value
: (row, value) => false,
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 */
export function getArrayBounds(rowCount: number, params?: ToArrayParams) {
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.
Please register or to comment