Skip to content

Commit

Permalink
arrays arithmetic (#628)
Browse files Browse the repository at this point in the history
* redoing ops

* matrix size

* unary minus

* renaming

* binary wrapper

* binary ops refactor

* bugfix

* refactor for binary ops

* index

* index test

* binsearch fix

* refactor of searching

* .

* fancy test

* doc

* doc

* .
  • Loading branch information
izulin committed May 14, 2021
1 parent 0eb13b2 commit aa1e4d1
Show file tree
Hide file tree
Showing 18 changed files with 331 additions and 151 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Added support for array arithmetic. (#628)
- Accepting time in JS Date() objects on the input. (#648)

## [0.6.0] - 2021-04-27
Expand Down
5 changes: 5 additions & 0 deletions src/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type GPUMode = 'gpu' | 'cpu' | 'dev'
const PossibleGPUModeString: GPUMode[] = ['gpu', 'cpu', 'dev']

export interface ConfigParams {
arrays: boolean, //FIXME
/**
* Specifies if the string comparison is accent sensitive or not.
* Applies to comparison operators only.
Expand Down Expand Up @@ -380,6 +381,7 @@ type ConfigParamsList = keyof ConfigParams
export class Config implements ConfigParams, ParserConfig {

public static defaultConfig: ConfigParams = {
arrays: false,
accentSensitive: false,
caseSensitive: false,
caseFirst: 'lower',
Expand Down Expand Up @@ -420,6 +422,7 @@ export class Config implements ConfigParams, ParserConfig {
currencySymbol: ['$'],
}

public readonly arrays: boolean
/** @inheritDoc */
public readonly caseSensitive: boolean
/** @inheritDoc */
Expand Down Expand Up @@ -524,6 +527,7 @@ export class Config implements ConfigParams, ParserConfig {

constructor(
{
arrays,
accentSensitive,
caseSensitive,
caseFirst,
Expand Down Expand Up @@ -564,6 +568,7 @@ export class Config implements ConfigParams, ParserConfig {
currencySymbol,
}: Partial<ConfigParams> = {},
) {
this.arrays = this.valueFromParam(arrays, 'boolean', 'arrays')
this.accentSensitive = this.valueFromParam(accentSensitive, 'boolean', 'accentSensitive')
this.caseSensitive = this.valueFromParam(caseSensitive, 'boolean', 'caseSensitive')
this.caseFirst = this.valueFromParam(caseFirst, ['upper', 'lower', 'false'], 'caseFirst')
Expand Down
15 changes: 11 additions & 4 deletions src/Lookup/AdvancedFind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,26 @@

import {AbsoluteCellRange} from '../AbsoluteCellRange'
import {DependencyGraph} from '../DependencyGraph'
import {getRawValue, RawInterpreterValue} from '../interpreter/InterpreterValue'
import {getRawValue, InternalScalarValue, RawInterpreterValue} from '../interpreter/InterpreterValue'
import {SimpleRangeValue} from '../interpreter/SimpleRangeValue'

export abstract class AdvancedFind {
protected constructor(
protected dependencyGraph: DependencyGraph
) {
}

public advancedFind(keyMatcher: (arg: RawInterpreterValue) => boolean, range: AbsoluteCellRange): number {
const values = this.dependencyGraph.computeListOfValuesInRange(range)
public advancedFind(keyMatcher: (arg: RawInterpreterValue) => boolean, rangeValue: SimpleRangeValue): number {
let values: InternalScalarValue[]
const range = rangeValue.range()
if(range === undefined) {
values = rangeValue.valuesFromTopLeftCorner()
} else {
values = this.dependencyGraph.computeListOfValuesInRange(range)
}
for (let i = 0; i < values.length; i++) {
if (keyMatcher(getRawValue(values[i]))) {
return i + range.start.col
return i
}
}
return -1
Expand Down
14 changes: 8 additions & 6 deletions src/Lookup/ColumnBinarySearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {DependencyGraph} from '../DependencyGraph'
import {forceNormalizeString} from '../interpreter/ArithmeticHelper'
import {rangeLowerBound} from '../interpreter/binarySearch'
import {getRawValue, RawNoErrorScalarValue, RawScalarValue} from '../interpreter/InterpreterValue'
import {SimpleRangeValue} from '../interpreter/SimpleRangeValue'
import {Matrix} from '../Matrix'
import {ColumnsSpan} from '../Span'
import {AdvancedFind} from './AdvancedFind'
Expand Down Expand Up @@ -42,16 +43,17 @@ export class ColumnBinarySearch extends AdvancedFind implements ColumnSearchStra

public destroy(): void {}

public find(key: RawNoErrorScalarValue, range: AbsoluteCellRange, sorted: boolean): number {
public find(key: RawNoErrorScalarValue, rangeValue: SimpleRangeValue, sorted: boolean): number {
if(typeof key === 'string') {
key = forceNormalizeString(key)
}
if (range.height() < this.config.binarySearchThreshold || !sorted) {
const values = this.dependencyGraph.computeListOfValuesInRange(range).map(getRawValue).map(arg =>
const range = rangeValue.range()
if(range === undefined) {
return rangeValue.valuesFromTopLeftCorner().map(getRawValue).map(arg =>
(typeof arg === 'string') ? forceNormalizeString(arg) : arg
)
const index = values.indexOf(key)
return index < 0 ? index : index + range.start.row
).indexOf(key)
} else if (range.height() < this.config.binarySearchThreshold || !sorted) {
return this.dependencyGraph.computeListOfValuesInRange(range).map(getRawValue).indexOf(key)
} else {
return rangeLowerBound(range, key, this.dependencyGraph, 'row')
}
Expand Down
12 changes: 8 additions & 4 deletions src/Lookup/ColumnIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@ export class ColumnIndex implements ColumnSearchStrategy {
}
}

public find(key: RawNoErrorScalarValue, range: AbsoluteCellRange, sorted: boolean): number {
public find(key: RawNoErrorScalarValue, rangeValue: SimpleRangeValue, sorted: boolean): number {
const range = rangeValue.range()
if(range === undefined) {
return this.binarySearchStrategy.find(key, rangeValue, sorted)
}
this.ensureRecentData(range.sheet, range.start.col, key)

const columnMap = this.getColumnMap(range.sheet, range.start.col)
Expand All @@ -104,15 +108,15 @@ export class ColumnIndex implements ColumnSearchStrategy {

const valueIndex = columnMap.get(key)
if (!valueIndex) {
return this.binarySearchStrategy.find(key, range, sorted)
return this.binarySearchStrategy.find(key, rangeValue, sorted)
}

const index = upperBound(valueIndex.index, range.start.row)
const rowNumber = valueIndex.index[index]
return rowNumber <= range.end.row ? rowNumber : this.binarySearchStrategy.find(key, range, sorted)
return rowNumber <= range.end.row ? rowNumber - range.start.row : this.binarySearchStrategy.find(key, rangeValue, sorted)
}

public advancedFind(keyMatcher: (arg: RawInterpreterValue) => boolean, range: AbsoluteCellRange): number {
public advancedFind(keyMatcher: (arg: RawInterpreterValue) => boolean, range: SimpleRangeValue): number {
return this.binarySearchStrategy.advancedFind(keyMatcher, range)
}

Expand Down
14 changes: 8 additions & 6 deletions src/Lookup/RowSearchStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {DependencyGraph} from '../DependencyGraph'
import {forceNormalizeString} from '../interpreter/ArithmeticHelper'
import {rangeLowerBound} from '../interpreter/binarySearch'
import {getRawValue, RawNoErrorScalarValue} from '../interpreter/InterpreterValue'
import {SimpleRangeValue} from '../interpreter/SimpleRangeValue'
import {AdvancedFind} from './AdvancedFind'
import {SearchStrategy} from './SearchStrategy'

Expand All @@ -20,16 +21,17 @@ export class RowSearchStrategy extends AdvancedFind implements SearchStrategy {
super(dependencyGraph)
}

public find(key: RawNoErrorScalarValue, range: AbsoluteCellRange, sorted: boolean): number {
public find(key: RawNoErrorScalarValue, rangeValue: SimpleRangeValue, sorted: boolean): number {
if(typeof key === 'string') {
key = forceNormalizeString(key)
}
if (range.width() < this.config.binarySearchThreshold || !sorted) {
const values = this.dependencyGraph.computeListOfValuesInRange(range).map(getRawValue).map(arg =>
const range = rangeValue.range()
if(range === undefined) {
return rangeValue.valuesFromTopLeftCorner().map(getRawValue).indexOf(key)
} else if (range.width() < this.config.binarySearchThreshold || !sorted) {
return this.dependencyGraph.computeListOfValuesInRange(range).map(getRawValue).map(arg =>
(typeof arg === 'string') ? forceNormalizeString(arg) : arg
)
const index = values.indexOf(key)
return index < 0 ? index : index + range.start.col
).indexOf(key)
} else {
return rangeLowerBound(range, key, this.dependencyGraph, 'col')
}
Expand Down
5 changes: 3 additions & 2 deletions src/Lookup/SearchStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ import {SimpleCellAddress} from '../Cell'
import {Config} from '../Config'
import {DependencyGraph} from '../DependencyGraph'
import {RawInterpreterValue, RawNoErrorScalarValue, RawScalarValue} from '../interpreter/InterpreterValue'
import {SimpleRangeValue} from '../interpreter/SimpleRangeValue'
import {Matrix} from '../Matrix'
import {ColumnsSpan} from '../Span'
import {Statistics} from '../statistics/Statistics'
import {ColumnBinarySearch} from './ColumnBinarySearch'
import {ColumnIndex} from './ColumnIndex'

export interface SearchStrategy {
find(key: RawNoErrorScalarValue, range: AbsoluteCellRange, sorted: boolean): number,
find(key: RawNoErrorScalarValue, range: SimpleRangeValue, sorted: boolean): number,

advancedFind(keyMatcher: (arg: RawInterpreterValue) => boolean, range: AbsoluteCellRange): number,
advancedFind(keyMatcher: (arg: RawInterpreterValue) => boolean, range: SimpleRangeValue): number,
}

export interface ColumnSearchStrategy extends SearchStrategy {
Expand Down
3 changes: 3 additions & 0 deletions src/Matrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {ErrorMessage} from './error-message'
import {Ast, AstNodeType} from './parser'

export class MatrixSize {
public static fromMatrix<T>(matrix: T[][]): MatrixSize {
return new MatrixSize(matrix.length > 0 ? matrix[0].length : 0, matrix.length)
}
constructor(
public width: number,
public height: number,
Expand Down
5 changes: 2 additions & 3 deletions src/interpreter/ArithmeticHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,8 @@ export class ArithmeticHelper {
return cloneNumber(arg, -getRawValue(arg))
}

public unaryPlus = (arg: ExtendedNumber): ExtendedNumber => {
return arg
}
public unaryPlus = (arg: InternalScalarValue): InternalScalarValue => arg


public unaryPercent = (arg: ExtendedNumber): ExtendedNumber => {
return new PercentNumber(getRawValue(arg)/100)
Expand Down
Loading

0 comments on commit aa1e4d1

Please sign in to comment.