Skip to content

Commit

Permalink
store dates as float64 since no int64 is there
Browse files Browse the repository at this point in the history
  • Loading branch information
sgratzl committed Dec 23, 2018
1 parent c585c59 commit dc5d892
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 21 deletions.
15 changes: 6 additions & 9 deletions src/internal/math.ts
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ export interface IStatsWorkerMessage extends IWorkerMessage {
* reference key for the data indices
*/
refData: string;
data?: UIntTypedArray | Float32Array | Int32Array;
data?: UIntTypedArray | Float32Array | Int32Array | Float64Array;
}

/**
Expand Down Expand Up @@ -877,7 +877,7 @@ export interface ISetRefMessageRequest {
uid: number;

ref: string;
data: UIntTypedArray | Float32Array | Int32Array | null;
data: UIntTypedArray | Float32Array | Int32Array | Float64Array | null;
}

/**
Expand Down Expand Up @@ -982,18 +982,15 @@ export interface ICategoricalStatsMessageResponse {
stats: ICategoricalStatistics;
}

// max int32
const MISSING_DATE = 2147483647;

/**
* helper to build a value cache for dates, use dateValueCache2Value to convert back
* @internal
*/
export function dateValueCacheBuilder(length: number) {
const vs = new Int32Array(length);
const vs = new Float64Array(length);
let i = 0;
return {
push: (d: Date | null) => vs[i++] = d == null ? MISSING_DATE : d.getTime(),
push: (d: Date | null) => vs[i++] = d == null ? NaN : d.getTime(),
cache: vs
};
}
Expand All @@ -1002,7 +999,7 @@ export function dateValueCacheBuilder(length: number) {
* @internal
*/
export function dateValueCache2Value(v: number) {
return v === MISSING_DATE ? null : new Date(v);
return isNaN(v) ? null : new Date(v);
}

/**
Expand Down Expand Up @@ -1031,7 +1028,7 @@ export function categoricalValueCache2Value<T extends {name: string}>(v: number,

function sortWorkerMain(self: IPoorManWorkerScope) {
// stored refs to avoid duplicate copy
const refs = new Map<string, UIntTypedArray | Float32Array | Int32Array>();
const refs = new Map<string, UIntTypedArray | Float32Array | Int32Array | Float64Array>();

const sort = (r: ISortMessageRequest) => {
if (r.sortOrders) {
Expand Down
6 changes: 3 additions & 3 deletions src/internal/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ export class WorkerTaskScheduler {
pushStats(type: 'numberStats', args: Partial<INumberStatsMessageRequest>, refData: string, data: Float32Array, refIndices?: string, indices?: IndicesArray): Promise<IStatistics>;
pushStats(type: 'boxplotStats', args: Partial<IBoxPlotStatsMessageRequest>, refData: string, data: Float32Array, refIndices?: string, indices?: IndicesArray): Promise<IAdvancedBoxPlotData>;
pushStats(type: 'categoricalStats', args: Partial<ICategoricalStatsMessageRequest>, refData: string, data: UIntTypedArray, refIndices?: string, indices?: IndicesArray): Promise<ICategoricalStatistics>;
pushStats(type: 'dateStats', args: Partial<IDateStatsMessageRequest>, refData: string, data: Int32Array, refIndices?: string, indices?: IndicesArray): Promise<IDateStatistics>;
pushStats(type: 'numberStats' | 'boxplotStats' | 'categoricalStats' | 'dateStats', args: any, refData: string, data: Float32Array | UIntTypedArray | Int32Array, refIndices?: string, indices?: IndicesArray) {
pushStats(type: 'dateStats', args: Partial<IDateStatsMessageRequest>, refData: string, data: Float64Array, refIndices?: string, indices?: IndicesArray): Promise<IDateStatistics>;
pushStats(type: 'numberStats' | 'boxplotStats' | 'categoricalStats' | 'dateStats', args: any, refData: string, data: Float32Array | UIntTypedArray | Float64Array, refIndices?: string, indices?: IndicesArray) {
return new Promise((resolve) => {
const uid = this.workerTaskCounter++;
const {worker, tasks, refs} = this.checkOutWorker();
Expand Down Expand Up @@ -214,7 +214,7 @@ export class WorkerTaskScheduler {
});
}

setRef(ref: string, data: Float32Array | UIntTypedArray | Int32Array | IndicesArray) {
setRef(ref: string, data: Float32Array | UIntTypedArray | Int32Array | Float64Array | IndicesArray) {
for (const w of this.workers) {
w.refs.add(ref);
}
Expand Down
9 changes: 7 additions & 2 deletions src/model/DateColumn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export default class DateColumn extends ValueColumn<Date> implements IDateColumn
}

toCompareGroupValueType() {
return ECompareValueType.INT32;
return ECompareValueType.DOUBLE_ASC;
}
}

Expand All @@ -216,6 +216,11 @@ export function choose(rows: ISequence<IDataRow>, grouper: IDateGrouper | null,

function trueMedian(dates: ISequence<number>) {
// to avoid interpolating between the centers do it manually
const s = Uint32Array.from(dates).sort();
const s = Float64Array.from(dates);
if (s.length === 1) {
return s[0];
}

s.sort();
return s[Math.floor(s.length / 2)];
}
4 changes: 2 additions & 2 deletions src/provider/ScheduledTasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ export class ScheduleRenderTasks extends ARenderTasks implements IRenderTaskExec
const ranking = col.findMyRanker()!;
if (this.valueCacheData.has(col.id) && group.order.length > 0) {
// web worker version
return () => this.workers.pushStats('dateStats', {template: summary}, col.id, <Int32Array>this.valueCacheData.get(col.id), `${ranking.id}:${group.name}`, group.order)
return () => this.workers.pushStats('dateStats', {template: summary}, col.id, <Float64Array>this.valueCacheData.get(col.id), `${ranking.id}:${group.name}`, group.order)
.then((group) => ({group, summary, data}));
}
return this.dateStatsBuilder(group.order, col, summary, (group) => ({group, summary, data}));
Expand Down Expand Up @@ -352,7 +352,7 @@ export class ScheduleRenderTasks extends ARenderTasks implements IRenderTaskExec
const ranking = col.findMyRanker()!;
if (this.valueCacheData.has(col.id)) {
// web worker version
return () => this.workers.pushStats('dateStats', {template: data}, col.id, <Int32Array>this.valueCacheData.get(col.id), ranking.id, order ? order.joined : ranking.getOrder())
return () => this.workers.pushStats('dateStats', {template: data}, col.id, <Float64Array>this.valueCacheData.get(col.id), ranking.id, order ? order.joined : ranking.getOrder())
.then((summary) => ({summary, data}));
}
return this.dateStatsBuilder(order ? order : ranking.getOrder(), col, data, (summary) => ({summary, data}));
Expand Down
4 changes: 2 additions & 2 deletions src/provider/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ const CHUNK_SIZE = 100;
* @internal
*/
export class ARenderTasks {
protected readonly valueCacheData = new Map<string, Float32Array | UIntTypedArray | Int32Array>();
protected readonly valueCacheData = new Map<string, Float32Array | UIntTypedArray | Int32Array | Float64Array>();

protected readonly byIndex = (i: number) => this.data[i];

Expand Down Expand Up @@ -292,7 +292,7 @@ export class ARenderTasks {
this.valueCacheData.delete(`${col.id}:r`);
}

protected setValueCacheData(key: string, value: Float32Array | UIntTypedArray | Int32Array | null) {
protected setValueCacheData(key: string, value: Float32Array | UIntTypedArray | Int32Array | Float64Array | null) {
if (value == null) {
this.valueCacheData.delete(key);
} else {
Expand Down
5 changes: 2 additions & 3 deletions src/ui/dialogs/groupDate.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {IDialogContext} from './ADialog';
import {forEach} from '../../renderer/utils';
import DateColumn from '../../model/DateColumn';
import {IDateGranularity} from '../../model';
import {cssClass} from '../../styles';


/** @internal */
export default function appendDate(col: DateColumn, node: HTMLElement, dialog: IDialogContext) {
export default function appendDate(col: DateColumn, node: HTMLElement) {
const current = col.getDateGrouper();

let granularity = current.granularity;
Expand All @@ -31,7 +30,7 @@ export default function appendDate(col: DateColumn, node: HTMLElement, dialog: I
};


node.querySelector<HTMLInputElement>(`#${dialog.idPrefix}DC`)!.addEventListener('change', (evt) => {
node.querySelector<HTMLInputElement>('input[name=circular]')!.addEventListener('change', (evt) => {
circular = (<HTMLInputElement>evt.currentTarget).checked;
update();
}, { passive: true });
Expand Down

0 comments on commit dc5d892

Please sign in to comment.