Merge branch 'master' into add-kolmar-cipher
This commit is contained in:
commit
ea7b8843d5
@ -245,6 +245,7 @@
|
||||
"Subtract",
|
||||
"Multiply",
|
||||
"Divide",
|
||||
"MOD",
|
||||
"Extended GCD",
|
||||
"Modular Inverse",
|
||||
"Mean",
|
||||
|
||||
@ -124,6 +124,19 @@ export function median(data) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes modulo of two numbers and returns the value.
|
||||
*
|
||||
* @param {BigNumber[]} data
|
||||
* @returns {BigNumber}
|
||||
*/
|
||||
export function mod(data) {
|
||||
if (data.length > 0) {
|
||||
return data.reduce((acc, curr) => acc.mod(curr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Computes standard deviation of a number array and returns the value.
|
||||
*
|
||||
|
||||
@ -39,7 +39,7 @@ class AvroToJSON extends Operation {
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
async run(input, args) {
|
||||
if (input.byteLength <= 0) {
|
||||
throw new OperationError("Please provide an input.");
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ class Bzip2Compress extends Operation {
|
||||
* @param {Object[]} args
|
||||
* @returns {File}
|
||||
*/
|
||||
run(input, args) {
|
||||
async run(input, args) {
|
||||
const [blockSize, workFactor] = args;
|
||||
if (input.byteLength <= 0) {
|
||||
throw new OperationError("Please provide an input.");
|
||||
|
||||
@ -9,7 +9,7 @@ import {DELIM_OPTIONS} from "../lib/Delim.mjs";
|
||||
import {fromDecimal} from "../lib/Decimal.mjs";
|
||||
|
||||
/**
|
||||
* From Decimal delimiters, plus auto-detection.
|
||||
* From Decimal delimiters, plus auto-detection.
|
||||
*/
|
||||
const FROM_DECIMAL_DELIM_OPTIONS = [...DELIM_OPTIONS, "Auto"];
|
||||
|
||||
|
||||
62
src/core/operations/MOD.mjs
Normal file
62
src/core/operations/MOD.mjs
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import BigNumber from "bignumber.js";
|
||||
import Operation from "../Operation.mjs";
|
||||
import { createNumArray } from "../lib/Arithmetic.mjs";
|
||||
import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs";
|
||||
|
||||
|
||||
/**
|
||||
* MOD operation
|
||||
*/
|
||||
class MOD extends Operation {
|
||||
|
||||
/**
|
||||
* MOD constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "MOD";
|
||||
this.module = "Default";
|
||||
this.description = "Computes the modulo of each number in a list with a given modulus value. Numbers are extracted from the input based on the delimiter, and non-numeric values are ignored.<br><br>e.g. <code>15 4 7</code> with modulus <code>3</code> becomes <code>0 1 1</code>";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Modulus",
|
||||
"type": "number",
|
||||
"value": 2
|
||||
},
|
||||
{
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": ARITHMETIC_DELIM_OPTIONS,
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const modulus = new BigNumber(args[0]);
|
||||
const delimiter = args[1];
|
||||
|
||||
if (modulus.isZero()) {
|
||||
throw new Error("Modulus cannot be zero");
|
||||
}
|
||||
|
||||
const numbers = createNumArray(input, delimiter);
|
||||
const results = numbers.map(num => num.mod(modulus));
|
||||
|
||||
return results.join(" ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MOD;
|
||||
@ -264,6 +264,18 @@ Full hash: $2a$10$ODeP1.6fMsb.ENk2ngPUCO7qTGVPyHA9TqDVcyupyed8FjsiF65L6`;
|
||||
assert.strictEqual(result.toString(), "Fit as a Fiddle");
|
||||
}),
|
||||
|
||||
it("Bzip2 Compress: round-trips through the Node API", async () => {
|
||||
const compressed = await chef.bzip2Compress("The quick brown fox.");
|
||||
const result = await chef.bzip2Decompress(compressed);
|
||||
assert.strictEqual(result.toString(), "The quick brown fox.");
|
||||
}),
|
||||
|
||||
it("Avro to JSON: decodes an object container file through the Node API", async () => {
|
||||
const avro = chef.fromHex("4f626a0104166176726f2e736368656d6196017b2274797065223a227265636f7264222c226e616d65223a22736d616c6c222c226669656c6473223a5b7b226e616d65223a226e616d65222c2274797065223a22737472696e67227d5d7d146176726f2e636f646563086e756c6c004e0247632e3702e5b75cdab9a62f1541020e0c6d796e616d654e0247632e3702e5b75cdab9a62f1541");
|
||||
const result = await chef.avroToJSON(avro);
|
||||
assert.strictEqual(result.toString(), "{\n \"name\": \"myname\"\n}");
|
||||
}),
|
||||
|
||||
it("cartesianProduct: binary string", () => {
|
||||
const result = cartesianProduct("1:2\\n\\n3:4", {
|
||||
itemDelimiter: ":",
|
||||
|
||||
@ -722,6 +722,39 @@ TestRegister.addTests([
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: Decimal key space-delimited matches Latin1 key (fromDecimal Auto delimiter regression)",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "9b641a008211bb0464a10899d5b37a24ab08ffcf839f5e74d17d99f856530957",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Decimal", "string": "65 65"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: Latin1 key matches space-delimited Decimal key (fromDecimal Auto delimiter regression)",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "9b641a008211bb0464a10899d5b37a24ab08ffcf839f5e74d17d99f856530957",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Latin1", "string": "AA"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC: Decimal key comma-delimited matches Latin1 key (fromDecimal Auto delimiter regression)",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "9b641a008211bb0464a10899d5b37a24ab08ffcf839f5e74d17d99f856530957",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HMAC",
|
||||
"args": [{"option": "Decimal", "string": "65,65"}, "SHA256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "MD5: Complex bytes",
|
||||
input: "10dc10e32010de10d010dc10d810d910d010e12e",
|
||||
|
||||
208
tests/operations/tests/MOD.mjs
Normal file
208
tests/operations/tests/MOD.mjs
Normal file
@ -0,0 +1,208 @@
|
||||
/**
|
||||
* MOD tests
|
||||
*
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "MOD: Basic modulo operation",
|
||||
input: "15 4 7",
|
||||
expectedOutput: "0 1 1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Single number",
|
||||
input: "10",
|
||||
expectedOutput: "1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Comma-separated numbers",
|
||||
input: "15,8,23,16,5",
|
||||
expectedOutput: "1 1 2 2 5",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [7, "Comma"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Line feed separated numbers",
|
||||
input: "25\n13\n44\n7",
|
||||
expectedOutput: "0 3 4 2",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [5, "Line feed"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Large numbers",
|
||||
input: "123456789012345 987654321098765",
|
||||
expectedOutput: "123456789012345 987654321098765",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [1234567890123456, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Mixed with non-numeric values",
|
||||
input: "15 abc 4 def 7 xyz 23",
|
||||
expectedOutput: "0 1 1 2",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Decimal numbers",
|
||||
input: "10.5 15.7 8.2",
|
||||
expectedOutput: "1.5 0.7 2.2",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Negative numbers",
|
||||
input: "-15 -8 25 -10",
|
||||
expectedOutput: "0 -2 1 -1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Zero in input",
|
||||
input: "0 5 10 15 20",
|
||||
expectedOutput: "0 2 1 0 2",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Modulus of 2 (even/odd check)",
|
||||
input: "1 2 3 4 5 6 7 8 9 10",
|
||||
expectedOutput: "1 0 1 0 1 0 1 0 1 0",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [2, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Numbers with extra whitespace",
|
||||
input: " 15 4 7 ",
|
||||
expectedOutput: "0 1 1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Empty input",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Scientific notation",
|
||||
input: "1e3 2e2 5e1",
|
||||
expectedOutput: "1 2 2",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Floating point precision",
|
||||
input: "10.123456789 20.987654321",
|
||||
expectedOutput: "1.123456789 2.987654321",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [3, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Zero modulus error",
|
||||
input: "15 4 7",
|
||||
expectedError: true,
|
||||
expectedOutput: "MOD - Modulus cannot be zero",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [0, "Space"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Semi-colon separated numbers",
|
||||
input: "17;5;8;13",
|
||||
expectedOutput: "2 0 3 3",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [5, "Semi-colon"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: Colon separated numbers",
|
||||
input: "25:9:14:7",
|
||||
expectedOutput: "1 1 2 3",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [4, "Colon"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "MOD: CRLF separated numbers",
|
||||
input: "30\r\n18\r\n22\r\n11",
|
||||
expectedOutput: "0 0 4 5",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "MOD",
|
||||
"args": [6, "CRLF"]
|
||||
}
|
||||
],
|
||||
},
|
||||
]);
|
||||
Loading…
x
Reference in New Issue
Block a user