Skip to content

Commit

Permalink
Replace bitwise | operator from mathematical opetation in binary func…
Browse files Browse the repository at this point in the history
…tion to explicit checking for NaN and Infinite values.
  • Loading branch information
Kapelianovych committed Aug 19, 2021
1 parent 68029a3 commit 84cd6fc
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 10 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# [0.31.1] - 2021-08-18
# [0.31.2] - 2021-08-19

### Fixed

- Replace bitwise `|` operator from numeric operations of `binary` function to explicit checking for `NaN` and `Infinity`.

## [0.31.1] - 2021-08-18

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@fluss/core",
"version": "0.31.1",
"version": "0.31.2",
"description": "Core functions and structures for functional programming.",
"keywords": [
"functional-programming",
Expand Down
19 changes: 11 additions & 8 deletions src/binary.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export interface BinaryOperation {
(operator: '+'): <O extends string | number>(
f: O,
s: O
s: O,
) => O extends number ? number : string;
(operator: '-' | '/' | '%' | '*' | '**'): (f: number, s: number) => number;
(operator: '>' | '<' | '>=' | '<='): (f: number, s: number) => boolean;
Expand All @@ -11,28 +11,31 @@ export interface BinaryOperation {
(operator: string): <O>(f: O, s: O) => [f: O, s: O];
}

const orZero = (number: number): number =>
Number.isNaN(number) || !Number.isFinite(number) ? 0 : number;

/**
* Creates function for binary operation.
* For unknown operator it returns tuple
* with left and right operands.
*/
export const binary: BinaryOperation = (
operator
operator,
): ((f: any, s: any) => any) => {
switch (operator) {
case '+':
return (f, s) =>
typeof f === 'string' || typeof s === 'string' ? f + s : (f + s) | 0;
typeof f === 'string' || typeof s === 'string' ? f + s : orZero(f + s);
case '-':
return (f, s) => (f - s) | 0;
return (f, s) => orZero(f - s);
case '/':
return (f, s) => (f / s) | 0;
return (f, s) => orZero(f / orZero(s));
case '%':
return (f, s) => f % s | 0;
return (f, s) => orZero(f % orZero(s));
case '*':
return (f, s) => (f * s) | 0;
return (f, s) => orZero(f * s);
case '**':
return (f, s) => (f ** s) | 0;
return (f, s) => orZero(f ** s);
case '>':
return (f, s) => f > s;
case '<':
Expand Down
34 changes: 34 additions & 0 deletions test/binary.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ describe('binary', () => {

it('should return add function', () => {
expect(binary('+')(1, 2)).toBe(3);
expect(binary('+')(1.1, 2.2)).toBeCloseTo(3.3);
});

it('should return string concat function', () => {
Expand All @@ -15,46 +16,79 @@ describe('binary', () => {

it('should return zero on invalid add operation', () => {
expect(binary('+')(1, NaN)).toBe(0);
expect(binary('+')(1.5, NaN)).toBe(0);
expect(binary('+')(1, Infinity)).toBe(0);
expect(binary('+')(1.5, Infinity)).toBe(0);
expect(binary('+')(Infinity, 7)).toBe(0);
expect(binary('+')(Infinity, 3.5)).toBe(0);
});

it('should return subtract function', () => {
expect(binary('-')(1, 2)).toBe(-1);
expect(binary('-')(1.1, 2)).toBeCloseTo(-0.9);
});

it('should return zero on invalid subtraction operation', () => {
expect(binary('-')(1, NaN)).toBe(0);
expect(binary('-')(1.8, NaN)).toBe(0);
expect(binary('-')(1, Infinity)).toBe(0);
expect(binary('-')(1.8, Infinity)).toBe(0);
expect(binary('-')(Infinity, 6)).toBe(0);
expect(binary('-')(Infinity, 3.0)).toBe(0);
});

it('should return division function', () => {
expect(binary('/')(2, 2)).toBe(1);
expect(binary('/')(2.2, 2)).toBeCloseTo(1.1);
});

it('should return zero on invalid division operation', () => {
expect(binary('/')(1, 0)).toBe(0);
expect(binary('/')(1.3, 0)).toBe(0);
expect(binary('/')(1, Infinity)).toBe(0);
expect(binary('/')(1.3, Infinity)).toBe(0);
expect(binary('/')(Infinity, 8)).toBe(0);
expect(binary('/')(Infinity, 4.2)).toBe(0);
});

it('should return modulo division function', () => {
expect(binary('%')(3, 2)).toBe(1);
expect(binary('%')(3, 2.5)).toBe(0.5);
});

it('should return zero on invalid modulo division operation', () => {
expect(binary('%')(1, 0)).toBe(0);
expect(binary('%')(1.4, 0)).toBe(0);
expect(binary('%')(1, Infinity)).toBe(0);
expect(binary('%')(1.4, Infinity)).toBe(0);
expect(binary('%')(Infinity, 5)).toBe(0);
expect(binary('%')(Infinity, 8.3)).toBe(0);
});

it('should return multiplication function', () => {
expect(binary('*')(3, 2)).toBe(6);
expect(binary('*')(3.2, 2)).toBe(6.4);
});

it('should return zero on invalid multiplication operation', () => {
expect(binary('*')(1, NaN)).toBe(0);
expect(binary('*')(1.6, NaN)).toBe(0);
expect(binary('*')(1, Infinity)).toBe(0);
expect(binary('*')(1.6, Infinity)).toBe(0);
});

it('should return exponentiation function', () => {
expect(binary('**')(3, 2)).toBe(9);
expect(binary('**')(3.1, 2)).toBeCloseTo(9.61);
});

it('should return zero on invalid exponentiation operation', () => {
expect(binary('**')(1, NaN)).toBe(0);
expect(binary('**')(1.9, NaN)).toBe(0);
expect(binary('**')(1, Infinity)).toBe(0);
expect(binary('**')(1.9, Infinity)).toBe(0);
expect(binary('**')(Infinity, 5)).toBe(0);
expect(binary('**')(Infinity, 63.7)).toBe(0);
});

it('should return greater than function', () => {
Expand Down

0 comments on commit 84cd6fc

Please sign in to comment.