Skip to content

Commit

Permalink
Safemath pt 2 (#5778)
Browse files Browse the repository at this point in the history
* add more fns

* accept string or number

* update errors
  • Loading branch information
brunobar79 authored and greg-schrammel committed May 29, 2024
1 parent 3a3c341 commit b8635be
Show file tree
Hide file tree
Showing 2 changed files with 285 additions and 91 deletions.
270 changes: 202 additions & 68 deletions src/__swaps__/safe-math/SafeMath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,182 +40,316 @@ const formatResultWorklet = (result: bigint): string => {
return isNegative ? `-${formattedResult}` : formattedResult;
};

// Helper function to handle string and number input types
const toStringWorklet = (value: string | number): string => {
'worklet';
return typeof value === 'number' ? value.toString() : value;
};

// Sum function
export function sumWorklet(num1: string, num2: string): string {
export function sumWorklet(num1: string | number, num2: string | number): string {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}
if (isZeroWorklet(num1)) {
return num2;
if (isZeroWorklet(num1Str)) {
return num2Str;
}

if (isZeroWorklet(num2)) {
return num1;
if (isZeroWorklet(num2Str)) {
return num1Str;
}
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
const result = scaledBigInt1 + scaledBigInt2;
return formatResultWorklet(result);
}

// Subtract function
export function subWorklet(num1: string, num2: string): string {
export function subWorklet(num1: string | number, num2: string | number): string {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}

if (isZeroWorklet(num2)) {
return num1;
if (isZeroWorklet(num2Str)) {
return num1Str;
}

const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
const result = scaledBigInt1 - scaledBigInt2;
return formatResultWorklet(result);
}

// Multiply function
export function mulWorklet(num1: string, num2: string): string {
export function mulWorklet(num1: string | number, num2: string | number): string {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}
if (isZeroWorklet(num1) || isZeroWorklet(num2)) {
if (isZeroWorklet(num1Str) || isZeroWorklet(num2Str)) {
return '0';
}
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
const result = (scaledBigInt1 * scaledBigInt2) / BigInt(10) ** BigInt(20);
return formatResultWorklet(result);
}

// Divide function
export function divWorklet(num1: string, num2: string): string {
export function divWorklet(num1: string | number, num2: string | number): string {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}
if (isZeroWorklet(num2)) {
if (isZeroWorklet(num2Str)) {
throw new Error('Division by zero');
}
if (isZeroWorklet(num1)) {
if (isZeroWorklet(num1Str)) {
return '0';
}
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
const result = (scaledBigInt1 * BigInt(10) ** BigInt(20)) / scaledBigInt2;
return formatResultWorklet(result);
}

// Modulus function
export function modWorklet(num1: string, num2: string): string {
export function modWorklet(num1: string | number, num2: string | number): string {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}
if (isZeroWorklet(num2)) {
if (isZeroWorklet(num2Str)) {
throw new Error('Division by zero');
}
if (isZeroWorklet(num1)) {
if (isZeroWorklet(num1Str)) {
return '0';
}
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
const result = scaledBigInt1 % scaledBigInt2;
return formatResultWorklet(result);
}

// Power function
export function powWorklet(base: string, exponent: string): string {
export function powWorklet(base: string | number, exponent: string | number): string {
'worklet';
if (!isNumberStringWorklet(base) || !isNumberStringWorklet(exponent)) {
throw new Error('Arguments must be a numeric string');
const baseStr = toStringWorklet(base);
const exponentStr = toStringWorklet(exponent);

if (!isNumberStringWorklet(baseStr) || !isNumberStringWorklet(exponentStr)) {
throw new Error('Arguments must be a numeric string or number');
}
if (isZeroWorklet(base)) {
if (isZeroWorklet(baseStr)) {
return '0';
}
if (isZeroWorklet(exponent)) {
if (isZeroWorklet(exponentStr)) {
return '1';
}
const [bigIntBase, decimalPlaces] = removeDecimalWorklet(base);
const [bigIntBase, decimalPlaces] = removeDecimalWorklet(baseStr);
const scaledBigIntBase = scaleUpWorklet(bigIntBase, decimalPlaces);
const result = scaledBigIntBase ** BigInt(exponent) / BigInt(10) ** BigInt(20);
const result = scaledBigIntBase ** BigInt(exponentStr) / BigInt(10) ** BigInt(20);
return formatResultWorklet(result);
}

// Logarithm base 10 function
export function log10Worklet(num: string | number): string {
'worklet';
const numStr = toStringWorklet(num);

if (!isNumberStringWorklet(numStr)) {
throw new Error('Arguments must be a numeric string or number');
}
if (isZeroWorklet(numStr)) {
throw new Error('Argument must be greater than 0');
}

const [bigIntNum, decimalPlaces] = removeDecimalWorklet(numStr);
const scaledBigIntNum = scaleUpWorklet(bigIntNum, decimalPlaces);
const result = Math.log10(Number(scaledBigIntNum)) - 20; // Adjust the scale factor for log10
const resultBigInt = BigInt(result * 10 ** 20);
return formatResultWorklet(resultBigInt);
}

// Equality function
export function equalWorklet(num1: string, num2: string): boolean {
export function equalWorklet(num1: string | number, num2: string | number): boolean {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
return scaledBigInt1 === scaledBigInt2;
}

// Greater than function
export function greaterThanWorklet(num1: string, num2: string): boolean {
export function greaterThanWorklet(num1: string | number, num2: string | number): boolean {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
return scaledBigInt1 > scaledBigInt2;
}

// Greater than or equal to function
export function greaterThanOrEqualToWorklet(num1: string, num2: string): boolean {
export function greaterThanOrEqualToWorklet(num1: string | number, num2: string | number): boolean {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
return scaledBigInt1 >= scaledBigInt2;
}

// Less than function
export function lessThanWorklet(num1: string, num2: string): boolean {
export function lessThanWorklet(num1: string | number, num2: string | number): boolean {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
return scaledBigInt1 < scaledBigInt2;
}

// Less than or equal to function
export function lessThanOrEqualToWorklet(num1: string, num2: string): boolean {
export function lessThanOrEqualToWorklet(num1: string | number, num2: string | number): boolean {
'worklet';
if (!isNumberStringWorklet(num1) || !isNumberStringWorklet(num2)) {
throw new Error('Arguments must be a numeric string');
const num1Str = toStringWorklet(num1);
const num2Str = toStringWorklet(num2);

if (!isNumberStringWorklet(num1Str) || !isNumberStringWorklet(num2Str)) {
throw new Error('Arguments must be a numeric string or number');
}
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2);
const [bigInt1, decimalPlaces1] = removeDecimalWorklet(num1Str);
const [bigInt2, decimalPlaces2] = removeDecimalWorklet(num2Str);
const scaledBigInt1 = scaleUpWorklet(bigInt1, decimalPlaces1);
const scaledBigInt2 = scaleUpWorklet(bigInt2, decimalPlaces2);
return scaledBigInt1 <= scaledBigInt2;
}

// toFixed function
export function toFixedWorklet(num: string | number, decimalPlaces: number): string {
'worklet';
const numStr = toStringWorklet(num);

if (!isNumberStringWorklet(numStr)) {
throw new Error('Argument must be a numeric string or number');
}

const [bigIntNum, numDecimalPlaces] = removeDecimalWorklet(numStr);
const scaledBigIntNum = scaleUpWorklet(bigIntNum, numDecimalPlaces);

const scaleFactor = BigInt(10) ** BigInt(20 - decimalPlaces);
const roundedBigInt = ((scaledBigIntNum + scaleFactor / BigInt(2)) / scaleFactor) * scaleFactor;

const resultStr = roundedBigInt.toString().padStart(20 + 1, '0'); // SCALE_FACTOR decimal places + at least 1 integer place
const integerPart = resultStr.slice(0, -20) || '0';
const fractionalPart = resultStr.slice(-20, -20 + decimalPlaces).padEnd(decimalPlaces, '0');

return `${integerPart}.${fractionalPart}`;
}

// Ceil function
export function ceilWorklet(num: string | number): string {
'worklet';
const numStr = toStringWorklet(num);

if (!isNumberStringWorklet(numStr)) {
throw new Error('Argument must be a numeric string or number');
}

const [bigIntNum, decimalPlaces] = removeDecimalWorklet(numStr);
const scaledBigIntNum = scaleUpWorklet(bigIntNum, decimalPlaces);

const scaleFactor = BigInt(10) ** BigInt(20);
const ceilBigInt = ((scaledBigIntNum + scaleFactor - BigInt(1)) / scaleFactor) * scaleFactor;

return formatResultWorklet(ceilBigInt);
}

// Floor function
export function floorWorklet(num: string | number): string {
'worklet';
const numStr = toStringWorklet(num);

if (!isNumberStringWorklet(numStr)) {
throw new Error('Argument must be a numeric string or number');
}

const [bigIntNum, decimalPlaces] = removeDecimalWorklet(numStr);
const scaledBigIntNum = scaleUpWorklet(bigIntNum, decimalPlaces);

const scaleFactor = BigInt(10) ** BigInt(20);
const floorBigInt = (scaledBigIntNum / scaleFactor) * scaleFactor;

return formatResultWorklet(floorBigInt);
}

// Round function
export function roundWorklet(num: string | number): string {
'worklet';
const numStr = toStringWorklet(num);

if (!isNumberStringWorklet(numStr)) {
throw new Error('Argument must be a numeric string or number');
}

const [bigIntNum, decimalPlaces] = removeDecimalWorklet(numStr);
const scaledBigIntNum = scaleUpWorklet(bigIntNum, decimalPlaces);

const scaleFactor = BigInt(10) ** BigInt(20);
const roundBigInt = ((scaledBigIntNum + scaleFactor / BigInt(2)) / scaleFactor) * scaleFactor;

return formatResultWorklet(roundBigInt);
}
Loading

0 comments on commit b8635be

Please sign in to comment.