Skip to content

Commit

Permalink
feat(formula): add some math function (#2761)
Browse files Browse the repository at this point in the history
Co-authored-by: panxp <Wpxp1223456>
  • Loading branch information
wpxp123456 authored Jul 19, 2024
1 parent b8bf9e2 commit 344f4dd
Show file tree
Hide file tree
Showing 75 changed files with 6,302 additions and 590 deletions.
6 changes: 3 additions & 3 deletions packages/engine-formula/src/engine/utils/math-kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function divide(a: number, b: number): number {
* @returns The rounded number.
*/
export function round(base: number, precision: number): number {
const factor = 10 ** Math.floor(precision);
const factor = 10 ** Math.trunc(precision);
const epsilon = baseEpsilon(base, factor);
return Math.round(multiply(base, factor) + epsilon) / factor;
}
Expand All @@ -55,7 +55,7 @@ export function round(base: number, precision: number): number {
* @returns The floored number.
*/
export function floor(base: number, precision: number): number {
const factor = 10 ** Math.floor(precision);
const factor = 10 ** Math.trunc(precision);
const epsilon = baseEpsilon(base, factor);
return Math.floor(multiply(base, factor) + epsilon) / factor;
}
Expand All @@ -67,7 +67,7 @@ export function floor(base: number, precision: number): number {
* @returns The ceiled number.
*/
export function ceil(base: number, precision: number): number {
const factor = 10 ** Math.floor(precision);
const factor = 10 ** Math.trunc(precision);
const epsilon = baseEpsilon(base, factor);
return Math.ceil(multiply(base, factor) - epsilon) / factor;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,15 @@ export class ArrayValueObject extends BaseValueObject {
});
}

override cosh(): BaseValueObject {
return this.map((currentValue) => {
if (currentValue.isError()) {
return currentValue;
}
return currentValue.cosh();
});
}

override acos(): BaseValueObject {
return this.map((currentValue) => {
if (currentValue.isError()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,11 @@ export class BaseValueObject extends ObjectClassType {
return ErrorValueObject.create(ErrorType.VALUE);
}

cosh(): BaseValueObject {
/** abstract */
return ErrorValueObject.create(ErrorType.VALUE);
}

acos(): BaseValueObject {
/** abstract */
return ErrorValueObject.create(ErrorType.VALUE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ export class NullValueObject extends BaseValueObject {
return NumberValueObject.create(0).cos();
}

override cosh(): BaseValueObject {
return NumberValueObject.create(0).cosh();
}

override acos(): BaseValueObject {
return NumberValueObject.create(0).acos();
}
Expand Down Expand Up @@ -343,6 +347,10 @@ export class BooleanValueObject extends BaseValueObject {
return this._convertToNumber().cos();
}

override cosh(): BaseValueObject {
return this._convertToNumber().cosh();
}

override acos(): BaseValueObject {
return this._convertToNumber().acos();
}
Expand Down Expand Up @@ -886,6 +894,22 @@ export class NumberValueObject extends BaseValueObject {
return NumberValueObject.create(result);
}

override cosh(): BaseValueObject {
const currentValue = this.getValue();

if (!Number.isFinite(currentValue)) {
return ErrorValueObject.create(ErrorType.NUM);
}

const result = Math.cosh(currentValue);

if (!Number.isFinite(result)) {
return ErrorValueObject.create(ErrorType.NUM);
}

return NumberValueObject.create(result);
}

override acos(): BaseValueObject {
const currentValue = this.getValue();

Expand Down Expand Up @@ -1170,7 +1194,8 @@ export class NumberValueObject extends BaseValueObject {
return ErrorValueObject.create(ErrorType.NUM);
}

const result = round(currentValue, value);
// for excel negative special handle
const result = currentValue < 0 ? -round(Math.abs(currentValue), value) : round(currentValue, value);

if (!Number.isFinite(result)) {
return ErrorValueObject.create(ErrorType.NUM);
Expand Down Expand Up @@ -1201,7 +1226,8 @@ export class NumberValueObject extends BaseValueObject {
return ErrorValueObject.create(ErrorType.NUM);
}

const result = floor(currentValue, value);
// for excel negative special handle
const result = currentValue < 0 ? -floor(Math.abs(currentValue), value) : floor(currentValue, value);

if (!Number.isFinite(result)) {
return ErrorValueObject.create(ErrorType.NUM);
Expand Down Expand Up @@ -1232,7 +1258,8 @@ export class NumberValueObject extends BaseValueObject {
return ErrorValueObject.create(ErrorType.NUM);
}

const result = ceil(currentValue, value);
// for excel negative special handle
const result = currentValue < 0 ? -ceil(Math.abs(currentValue), value) : ceil(currentValue, value);

if (!Number.isFinite(result)) {
return ErrorValueObject.create(ErrorType.NUM);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { FUNCTION_NAMES_MATH } from '../../function-names';
import { Base } from '../index';
import { BooleanValueObject, NullValueObject, NumberValueObject, StringValueObject } from '../../../../engine/value-object/primitive-object';
import { ErrorType } from '../../../../basics/error-type';
import type { BaseValueObject } from '../../../../engine/value-object/base-value-object';
import { ErrorValueObject } from '../../../../engine/value-object/base-value-object';
import { ArrayValueObject, transformToValue, transformToValueObject } from '../../../../engine/value-object/array-value-object';

Expand All @@ -32,76 +31,76 @@ describe('Test base function', () => {
const number = NumberValueObject.create(15);
const radix = NumberValueObject.create(2);
const minLength = NumberValueObject.create(10);
const result = testFunction.calculate(number, radix, minLength) as BaseValueObject;
const result = testFunction.calculate(number, radix, minLength);
expect(result.getValue()).toBe('0000001111');
});

it('number value is 2**53', () => {
const number = NumberValueObject.create(2 ** 53);
const radix = NumberValueObject.create(2);
const result = testFunction.calculate(number, radix) as BaseValueObject;
const result = testFunction.calculate(number, radix);
expect(result.getValue()).toBe(ErrorType.NUM);
});

it('radix value is 1.5', () => {
const number = NumberValueObject.create(15);
const radix = NumberValueObject.create(1.5);
const result = testFunction.calculate(number, radix) as BaseValueObject;
const result = testFunction.calculate(number, radix);
expect(result.getValue()).toBe(ErrorType.NUM);
});

it('radix value is 37', () => {
const number = NumberValueObject.create(15);
const radix = NumberValueObject.create(37);
const result = testFunction.calculate(number, radix) as BaseValueObject;
const result = testFunction.calculate(number, radix);
expect(result.getValue()).toBe(ErrorType.NUM);
});

it('minLength value is number negative', () => {
const number = NumberValueObject.create(15);
const radix = NumberValueObject.create(2);
const minLength = NumberValueObject.create(-2);
const result = testFunction.calculate(number, radix, minLength) as BaseValueObject;
const result = testFunction.calculate(number, radix, minLength);
expect(result.getValue()).toBe(ErrorType.NUM);
});

it('value is number string', () => {
const number = StringValueObject.create('15');
const radix = NumberValueObject.create(2);
const minLength = StringValueObject.create('7');
const result = testFunction.calculate(number, radix, minLength) as BaseValueObject;
const result = testFunction.calculate(number, radix, minLength);
expect(result.getValue()).toBe('0001111');
});

it('value is normal string', () => {
const number = StringValueObject.create('test');
const radix = NumberValueObject.create(2);
const minLength = StringValueObject.create('7');
const result = testFunction.calculate(number, radix, minLength) as BaseValueObject;
const result = testFunction.calculate(number, radix, minLength);
expect(result.getValue()).toBe(ErrorType.VALUE);
});

it('Value is boolean', () => {
const number = BooleanValueObject.create(true);
const radix = NumberValueObject.create(2);
const minLength = StringValueObject.create('7');
const result = testFunction.calculate(number, radix, minLength) as BaseValueObject;
const result = testFunction.calculate(number, radix, minLength);
expect(result.getValue()).toBe('0000001');
});

it('Value is blank cell', () => {
const number = NullValueObject.create();
const radix = NumberValueObject.create(2);
const minLength = StringValueObject.create('7');
const result = testFunction.calculate(number, radix, minLength) as BaseValueObject;
const result = testFunction.calculate(number, radix, minLength);
expect(result.getValue()).toBe('0000000');
});

it('Value is error', () => {
const number = ErrorValueObject.create(ErrorType.NAME);
const radix = NumberValueObject.create(2);
const minLength = StringValueObject.create('7');
const result = testFunction.calculate(number, radix, minLength) as BaseValueObject;
const result = testFunction.calculate(number, radix, minLength);
expect(result.getValue()).toBe(ErrorType.NAME);
});

Expand Down
54 changes: 27 additions & 27 deletions packages/engine-formula/src/functions/math/base/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { expandArrayValueObject } from '../../../engine/utils/array-object';
import type { ArrayValueObject } from '../../../engine/value-object/array-value-object';
import type { BaseValueObject } from '../../../engine/value-object/base-value-object';
import { ErrorValueObject } from '../../../engine/value-object/base-value-object';
import { StringValueObject } from '../../../engine/value-object/primitive-object';
import { NumberValueObject, StringValueObject } from '../../../engine/value-object/primitive-object';
import { BaseFunction } from '../../base-function';

export class Base extends BaseFunction {
Expand Down Expand Up @@ -58,65 +58,65 @@ export class Base extends BaseFunction {
const radixArray = expandArrayValueObject(maxRowLength, maxColumnLength, radix, ErrorValueObject.create(ErrorType.NA));
const minLengthArray = minLength ? expandArrayValueObject(maxRowLength, maxColumnLength, minLength, ErrorValueObject.create(ErrorType.NA)) : [];

const resultArray = numberArray.map((NumberItemValueObject, rowIndex, columnIndex) => {
let radixItemValueObject = radixArray.get(rowIndex, columnIndex) as BaseValueObject;
let minLengthItemValueObject = minLength ? (minLengthArray as ArrayValueObject).get(rowIndex, columnIndex) : {};
const resultArray = numberArray.map((numberObject, rowIndex, columnIndex) => {
let radixObject = radixArray.get(rowIndex, columnIndex) as BaseValueObject;
let minLengthObject = minLength ? (minLengthArray as ArrayValueObject).get(rowIndex, columnIndex) : NumberValueObject.create(0);

if (NumberItemValueObject.isString()) {
NumberItemValueObject = NumberItemValueObject.convertToNumberObjectValue();
if (numberObject.isString()) {
numberObject = numberObject.convertToNumberObjectValue();
}

if (radixItemValueObject.isString()) {
radixItemValueObject = radixItemValueObject.convertToNumberObjectValue();
if (radixObject.isString()) {
radixObject = radixObject.convertToNumberObjectValue();
}

if (minLength && (minLengthItemValueObject as BaseValueObject).isString()) {
minLengthItemValueObject = (minLengthItemValueObject as BaseValueObject).convertToNumberObjectValue();
if (minLength && (minLengthObject as BaseValueObject).isString()) {
minLengthObject = (minLengthObject as BaseValueObject).convertToNumberObjectValue();
}

if (NumberItemValueObject.isString() || radixItemValueObject.isString() || (minLength && (minLengthItemValueObject as BaseValueObject).isString())) {
if (numberObject.isString() || radixObject.isString() || (minLength && (minLengthObject as BaseValueObject).isString())) {
return ErrorValueObject.create(ErrorType.VALUE);
}

if (NumberItemValueObject.isError()) {
return NumberItemValueObject;
if (numberObject.isError()) {
return numberObject;
}

if (radixItemValueObject.isError()) {
return radixItemValueObject as BaseValueObject;
if (radixObject.isError()) {
return radixObject as BaseValueObject;
}

if (minLength && (minLengthItemValueObject as BaseValueObject).isError()) {
return minLengthItemValueObject as BaseValueObject;
if (minLength && (minLengthObject as BaseValueObject).isError()) {
return minLengthObject as BaseValueObject;
}

// Any non-integer number entered as an argument is truncated to an integer.
const NumberItemValue = Math.floor(+NumberItemValueObject.getValue());
const radixItemValue = Math.floor(+radixItemValueObject.getValue());
const minLengthItemValue = minLength ? Math.floor(+(minLengthItemValueObject as BaseValueObject).getValue()) : 0;
const numberValue = Math.floor(+numberObject.getValue());
const radixValue = Math.floor(+radixObject.getValue());
const minLengthValue = minLength ? Math.floor(+(minLengthObject as BaseValueObject).getValue()) : 0;

// The number that you want to convert. Must be an integer greater than or equal to 0 and less than 2^53.
if (NumberItemValue < 0 || NumberItemValue >= 2 ** 53) {
if (numberValue < 0 || numberValue >= 2 ** 53) {
return ErrorValueObject.create(ErrorType.NUM);
}

// The base radix that you want to convert the number into. Must be an integer greater than or equal to 2 and less than or equal to 36.
if (radixItemValue < 2 || radixItemValue > 36) {
if (radixValue < 2 || radixValue > 36) {
return ErrorValueObject.create(ErrorType.NUM);
}

// The minimum length of the returned string. Must be an integer greater than or equal to 0.
if (minLengthItemValue < 0) {
if (minLengthValue < 0) {
return ErrorValueObject.create(ErrorType.NUM);
}

let result = NumberItemValue.toString(radixItemValue);
let result = numberValue.toString(radixValue);

if (minLength && result.length < minLengthItemValue) {
result = new Array(minLengthItemValue - result.length + 1).join('0') + result;
if (minLength && result.length < minLengthValue) {
result = new Array(minLengthValue - result.length + 1).join('0') + result;
}

return StringValueObject.create(result);
return StringValueObject.create(result.toLocaleUpperCase());
});

if ((resultArray as ArrayValueObject).getRowCount() === 1 && (resultArray as ArrayValueObject).getColumnCount() === 1) {
Expand Down
Loading

0 comments on commit 344f4dd

Please sign in to comment.