Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Added

- Added support for the new license key format. A proprietary key can now grant a subset of the library: a function your key does not include evaluates to a `#LIC!` error, and the matching parts of the API throw a `LicenseCapabilityMissingError`. `getAvailableFunctions()` and `getFunctionDetails()` describe only the functions your key includes. [#1728](https://github.com/handsontable/hyperformula/pull/1728)
- Added a new function: `ERF.PRECISE`. [#1789](https://github.com/handsontable/hyperformula/pull/1789)

### Changed

Expand All @@ -19,6 +20,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Fixed

- Fixed the validation of classic (25-character) license keys depending on the time zone: east of UTC, a key that expired the day before the build was released was still accepted, and west of UTC, the console message printed an expiry date one day too early. [#1728](https://github.com/handsontable/hyperformula/pull/1728)
- Fixed the `ERF` and `ERFC` functions returning a number for a boolean or an empty text argument instead of `#VALUE!` as Excel does; numeric text, dates and empty cells are still accepted. [#1789](https://github.com/handsontable/hyperformula/pull/1789)
- Fixed the `AVERAGEIF` function returning a division-by-zero error when the calculated average was `0`. [#1733](https://github.com/handsontable/hyperformula/pull/1733)
- Fixed the localized names of `VSTACK` and `HSTACK` in 14 language packs to match Microsoft Excel. [#1748](https://github.com/handsontable/hyperformula/pull/1748)
- Fixed the MAXPOOL and MEDIANPOOL functions throwing an uncaught `TypeError` instead of returning the `#VALUE!` error when the range dimensions are not a whole multiple of the window size and the stride. [#1718](https://github.com/handsontable/hyperformula/pull/1718)
Expand Down
1 change: 1 addition & 0 deletions docs/guide/list-of-differences.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,4 @@ A few of the rows above share a root cause worth stating once:
- **Rounding toward zero, not down.** `INT` discards the fractional part rather than rounding toward negative infinity, so it differs from Excel and Google Sheets for negative input only. `ROUNDDOWN`/`ROUNDUP` are unaffected — they are defined in terms of zero in all three.
- **`ISEVEN`/`ISODD` do not truncate.** They test the remainder of the value as given, so a value with a fractional part returns `FALSE` from *both*. Excel and Google Sheets truncate to an integer first, so exactly one of the two is always `TRUE`.
- **`CEILING.MATH`/`FLOOR.MATH` honour only `mode` = 1.** Excel and Google Sheets switch the negative-number rounding direction for any non-zero `mode`.
- **`ERF.PRECISE`, like `ERF` and `ERFC`, loses relative accuracy for arguments very close to zero.** `=ERF.PRECISE(1E-10)` returns `1.128379612E-10` where Excel returns `1.12837916709551E-10`, and `=ERF.PRECISE(1E-300)` returns about `1.1E-16` where Excel returns `1.12837916709551E-300`. The comparison with Excel was measured for arguments of `0.1` and above (agreement to about 11 significant digits, the precision HyperFormula returns by default) and for `1E-10` and `1E-300`; values in between were not measured.
1 change: 1 addition & 0 deletions src/i18n/languages/csCZ.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'EOMONTH',
ERF: 'ERF',
ERFC: 'ERFC',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'ZAOKROUHLIT.NA.SUDÉ',
EXACT: 'STEJNÉ',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/daDK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'SLUT.PÅ.MÅNED',
ERF: 'FEJLFUNK',
ERFC: 'FEJLFUNK.KOMP',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'LIGE',
EXACT: 'EKSAKT',
EXP: 'EKSP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/deDE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'MONATSENDE',
ERF: 'GAUSSFEHLER',
ERFC: 'GAUSSFKOMPL',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'GERADE',
EXACT: 'IDENTISCH',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/enGB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'EOMONTH',
ERF: 'ERF',
ERFC: 'ERFC',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'EVEN',
EXACT: 'EXACT',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/esES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export const dictionary: RawTranslationPackage = {
EOMONTH: 'FIN.MES',
ERF: 'FUN.ERROR',
ERFC: 'FUN.ERROR.COMPL',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'REDONDEA.PAR',
EXACT: 'IGUAL',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/fiFI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'KUUKAUSI.LOPPU',
ERF: 'VIRHEFUNKTIO',
ERFC: 'VIRHEFUNKTIO.KOMPLEMENTTI',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'PARILLINEN',
EXACT: 'VERTAA',
EXP: 'EKSPONENTTI',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/frFR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'FIN.MOIS',
ERF: 'ERF',
ERFC: 'ERFC',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'PAIR',
EXACT: 'EXACT',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/huHU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'HÓNAP.UTOLSÓ.NAP',
ERF: 'HIBAF',
ERFC: 'HIBAF.KOMPLEMENTER',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'PÁROS',
EXACT: 'AZONOS',
EXP: 'KITEVŐ',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/idID.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'AKHIR.BULAN',
ERF: 'ERF',
ERFC: 'ERFC',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'GENAP',
EXACT: 'IDENTIK',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/itIT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'FINE.MESE',
ERF: 'FUNZ.ERRORE',
ERFC: 'FUNZ.ERRORE.COMP',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'PARI',
EXACT: 'IDENTICO',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/nbNO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'MÅNEDSSLUTT',
ERF: 'FEILF',
ERFC: 'FEILFK',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'AVRUND.TIL.PARTALL',
EXACT: 'EKSAKT',
EXP: 'EKSP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/nlNL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'LAATSTE.DAG',
ERF: 'FOUTFUNCTIE',
ERFC: 'FOUT.COMPLEMENT',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'EVEN',
EXACT: 'GELIJK',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/plPL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'NR.SER.OST.DN.MIEŚ',
ERF: 'FUNKCJA.BŁ',
ERFC: 'KOMP.FUNKCJA.BŁ',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'ZAOKR.DO.PARZ',
EXACT: 'PORÓWNAJ',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/ptPT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'FIMMÊS',
ERF: 'FUNERRO',
ERFC: 'FUNERROCOMPL',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'PAR',
EXACT: 'EXATO',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/ruRU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'КОНМЕСЯЦА',
ERF: 'ФОШ',
ERFC: 'ДФОШ',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'ЧЁТН',
EXACT: 'СОВПАД',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/svSE.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'SLUTMÅNAD',
ERF: 'FELF',
ERFC: 'FELFK',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'JÄMN',
EXACT: 'EXAKT',
EXP: 'EXP',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/languages/trTR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const dictionary: RawTranslationPackage = {
EOMONTH: 'SERİAY',
ERF: 'HATAİŞLEV',
ERFC: 'TÜMHATAİŞLEV',
'ERF.PRECISE': 'ERF.PRECISE',
EVEN: 'ÇİFT',
EXACT: 'ÖZDEŞ',
EXP: 'ÜS',
Expand Down
7 changes: 7 additions & 0 deletions src/interpreter/functionMetadata/categories/engineering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ export const ENGINEERING_DOCS: Record<string, FunctionDoc> = {
documentationUrl: 'https://hyperformula.handsontable.com/docs/guide/built-in-functions.html',
examples: ['=ERFC(1)', '=ERFC(0.5)'],
},
'ERF.PRECISE': {
category: 'Engineering',
shortDescription: 'Returns values of the Gaussian error integral.',
parameters: [{name: 'x', description: 'The upper limit of the integral, calculated from 0 to x.'}],
documentationUrl: 'https://hyperformula.handsontable.com/docs/guide/built-in-functions.html',
examples: ['=ERF.PRECISE(1)', '=ERF.PRECISE(-0.5)'],
},
HEX2BIN: {
category: 'Engineering',
shortDescription: 'The result is the binary number for the hexadecimal number entered.',
Expand Down
53 changes: 44 additions & 9 deletions src/interpreter/plugin/StatisticalPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {CellError, ErrorType} from '../../Cell'
import {ErrorMessage} from '../../error-message'
import {ProcedureAst} from '../../parser'
import {InterpreterState} from '../InterpreterState'
import {InterpreterValue} from '../InterpreterValue'
import {getRawValue, InternalScalarValue, InterpreterValue} from '../InterpreterValue'
import {besseli, besselj, besselk, bessely} from './3rdparty/bessel/bessel'
import {
beta,
Expand Down Expand Up @@ -37,14 +37,20 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPluginT
'ERF': {
method: 'erf',
parameters: [
{argumentType: FunctionArgumentType.NUMBER},
{argumentType: FunctionArgumentType.NUMBER, optionalArg: true},
{argumentType: FunctionArgumentType.SCALAR},
{argumentType: FunctionArgumentType.SCALAR, optionalArg: true},
]
},
'ERFC': {
method: 'erfc',
parameters: [
{argumentType: FunctionArgumentType.NUMBER}
{argumentType: FunctionArgumentType.SCALAR}
]
},
'ERF.PRECISE': {
method: 'erfprecise',
parameters: [
{argumentType: FunctionArgumentType.SCALAR}
]
},
'EXPON.DIST': {
Expand Down Expand Up @@ -426,18 +432,47 @@ export class StatisticalPlugin extends FunctionPlugin implements FunctionPluginT
POISSONDIST: 'POISSON.DIST',
}

/**
* Converts an argument the way Excel does for the error functions: numbers, dates, numeric text and empty cells are
* accepted, while a boolean or the empty text is #VALUE!. Errors are passed on.
*/
private strictNumber(value: InternalScalarValue): number | CellError {
if (value instanceof CellError) {
return value
}
if (typeof value === 'boolean' || value === '') {
return new CellError(ErrorType.VALUE, ErrorMessage.NumberCoercion)
}
const coerced = this.coerceScalarToNumberOrError(value)
return coerced instanceof CellError ? coerced : getRawValue(coerced)
}

public erf(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ERF'), (lowerBound, upperBound) => {
if (upperBound === undefined) {
return this.runFunction(ast.args, state, this.metadata('ERF'), (lower: InternalScalarValue, upper?: InternalScalarValue) => {
const lowerBound = this.strictNumber(lower)
if (lowerBound instanceof CellError) {
return lowerBound
}
if (upper === undefined) {
return erf(lowerBound)
} else {
return erf(upperBound) - erf(lowerBound)
}
const upperBound = this.strictNumber(upper)
return upperBound instanceof CellError ? upperBound : erf(upperBound) - erf(lowerBound)
})
}

public erfc(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ERFC'), erfc)
return this.runFunction(ast.args, state, this.metadata('ERFC'), (x: InternalScalarValue) => {
const value = this.strictNumber(x)
return value instanceof CellError ? value : erfc(value)
})
}

public erfprecise(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
return this.runFunction(ast.args, state, this.metadata('ERF.PRECISE'), (x: InternalScalarValue) => {
const value = this.strictNumber(x)
return value instanceof CellError ? value : erf(value)
})
}

public expondist(ast: ProcedureAst, state: InterpreterState): InterpreterValue {
Expand Down
2 changes: 1 addition & 1 deletion src/license/functionCapabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const UNGROUPED_FUNCTIONS = [
'CONFIDENCE.NORM', 'CONFIDENCE.T', 'CORREL', 'COSH', 'COT', 'COTH', 'COUNTUNIQUE', 'COVARIANCE.P',
'COVARIANCE.S', 'CSC', 'CSCH', 'CUMIPMT', 'CUMPRINC', 'DAVERAGE', 'DB', 'DCOUNT', 'DCOUNTA', 'DDB',
'DEC2BIN', 'DEC2OCT', 'DECIMAL', 'DEGREES', 'DELTA', 'DEVSQ', 'DGET', 'DMAX', 'DMIN', 'DOLLARDE',
'DOLLARFR', 'DPRODUCT', 'DSTDEV', 'DSTDEVP', 'DSUM', 'DVAR', 'DVARP', 'EFFECT', 'ERF', 'ERFC',
'DOLLARFR', 'DPRODUCT', 'DSTDEV', 'DSTDEVP', 'DSUM', 'DVAR', 'DVARP', 'EFFECT', 'ERF', 'ERF.PRECISE', 'ERFC',
'EXPON.DIST', 'F.DIST', 'F.DIST.RT', 'F.INV', 'F.INV.RT', 'F.TEST', 'FACT', 'FACTDOUBLE', 'FISHER',
'FISHERINV', 'FLOOR.MATH', 'FLOOR.PRECISE', 'FORMULATEXT', 'FVSCHEDULE', 'GAMMA', 'GAMMA.DIST',
'GAMMA.INV', 'GAMMALN', 'GAUSS', 'GCD', 'GEOMEAN', 'HARMEAN', 'HEX2BIN', 'HEX2OCT', 'HYPGEOM.DIST',
Expand Down
Loading