Skip to content

Commit 194eb18

Browse files
committed
Merge branch 'bwhitn-math'
2 parents 5e7f8e3 + 98f59ac commit 194eb18

File tree

4 files changed

+360
-1
lines changed

4 files changed

+360
-1
lines changed

src/core/config/Categories.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ const Categories = [
113113
]
114114
},
115115
{
116-
name: "Logical operations",
116+
name: "Arithmetic / Logic",
117117
ops: [
118118
"XOR",
119119
"XOR Brute Force",
@@ -122,6 +122,13 @@ const Categories = [
122122
"AND",
123123
"ADD",
124124
"SUB",
125+
"Sum",
126+
"Subtract",
127+
"Multiply",
128+
"Divide",
129+
"Mean",
130+
"Median",
131+
"Standard Deviation",
125132
"Bit shift left",
126133
"Bit shift right",
127134
"Rotate left",

src/core/config/OperationConfig.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Arithmetic from "../operations/Arithmetic.js";
12
import Base from "../operations/Base.js";
23
import Base58 from "../operations/Base58.js";
34
import Base64 from "../operations/Base64.js";
@@ -519,6 +520,97 @@ const OperationConfig = {
519520
}
520521
]
521522
},
523+
"Sum": {
524+
module: "Default",
525+
description: "Adds together a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>18.5</code>",
526+
inputType: "string",
527+
outputType: "number",
528+
args: [
529+
{
530+
name: "Delimiter",
531+
type: "option",
532+
value: Arithmetic.DELIM_OPTIONS
533+
}
534+
]
535+
},
536+
"Subtract": {
537+
module: "Default",
538+
description: "Subtracts a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>1.5</code>",
539+
inputType: "string",
540+
outputType: "number",
541+
args: [
542+
{
543+
name: "Delimiter",
544+
type: "option",
545+
value: Arithmetic.DELIM_OPTIONS
546+
}
547+
]
548+
},
549+
"Multiply": {
550+
module: "Default",
551+
description: "Multiplies a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>40</code>",
552+
inputType: "string",
553+
outputType: "number",
554+
args: [
555+
{
556+
name: "Delimiter",
557+
type: "option",
558+
value: Arithmetic.DELIM_OPTIONS
559+
}
560+
]
561+
},
562+
"Divide": {
563+
module: "Default",
564+
description: "Divides a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>2.5</code>",
565+
inputType: "string",
566+
outputType: "number",
567+
args: [
568+
{
569+
name: "Delimiter",
570+
type: "option",
571+
value: Arithmetic.DELIM_OPTIONS
572+
}
573+
]
574+
},
575+
"Mean": {
576+
module: "Default",
577+
description: "Computes the mean (average) of a number list. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5 .5</code> becomes <code>4.75</code>",
578+
inputType: "string",
579+
outputType: "number",
580+
args: [
581+
{
582+
name: "Delimiter",
583+
type: "option",
584+
value: Arithmetic.DELIM_OPTIONS
585+
}
586+
]
587+
},
588+
"Median": {
589+
module: "Default",
590+
description: "Computes the median of a number list. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 1 .5</code> becomes <code>4.5</code>",
591+
inputType: "string",
592+
outputType: "number",
593+
args: [
594+
{
595+
name: "Delimiter",
596+
type: "option",
597+
value: Arithmetic.DELIM_OPTIONS
598+
}
599+
]
600+
},
601+
"Standard Deviation": {
602+
module: "Default",
603+
description: "Computes the standard deviation of a number list. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>4.089281382128433</code>",
604+
inputType: "string",
605+
outputType: "number",
606+
args: [
607+
{
608+
name: "Delimiter",
609+
type: "option",
610+
value: Arithmetic.DELIM_OPTIONS
611+
}
612+
]
613+
},
522614
"From Hex": {
523615
module: "Default",
524616
description: "Converts a hexadecimal byte string back into its raw value.<br><br>e.g. <code>ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a</code> becomes the UTF-8 encoded string <code>Γειά σου</code>",

src/core/config/modules/Default.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import FlowControl from "../../FlowControl.js";
2+
import Arithmetic from "../../operations/Arithmetic.js";
23
import Base from "../../operations/Base.js";
34
import Base58 from "../../operations/Base58.js";
45
import Base64 from "../../operations/Base64.js";
@@ -159,6 +160,13 @@ OpModules.Default = {
159160
"Return": FlowControl.runReturn,
160161
"Comment": FlowControl.runComment,
161162
"PHP Deserialize": PHP.runDeserialize,
163+
"Sum": Arithmetic.runSum,
164+
"Subtract": Arithmetic.runSub,
165+
"Multiply": Arithmetic.runMulti,
166+
"Divide": Arithmetic.runDiv,
167+
"Mean": Arithmetic.runMean,
168+
"Median": Arithmetic.runMedian,
169+
"Standard Deviation": Arithmetic.runStdDev,
162170

163171

164172
/*

src/core/operations/Arithmetic.js

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
import Utils from "../Utils.js";
2+
3+
4+
/**
5+
* Math operations on numbers.
6+
*
7+
* @author bwhitn [[email protected]]
8+
* @copyright Crown Copyright 2016
9+
* @license Apache-2.0
10+
*
11+
* @namespace
12+
*/
13+
const Arithmetic = {
14+
15+
/**
16+
* @constant
17+
* @default
18+
*/
19+
DELIM_OPTIONS: ["Line feed", "Space", "Comma", "Semi-colon", "Colon", "CRLF"],
20+
21+
22+
/**
23+
* Splits a string based on a delimiter and calculates the sum of numbers.
24+
*
25+
* @param {string} input
26+
* @param {Object[]} args
27+
* @returns {number}
28+
*/
29+
runSum: function(input, args) {
30+
const val = Arithmetic._sum(Arithmetic._createNumArray(input, args[0]));
31+
return typeof(val) === "number" ? val : NaN;
32+
},
33+
34+
35+
/**
36+
* Splits a string based on a delimiter and subtracts all the numbers.
37+
*
38+
* @param {string} input
39+
* @param {Object[]} args
40+
* @returns {number}
41+
*/
42+
runSub: function(input, args) {
43+
let val = Arithmetic._sub(Arithmetic._createNumArray(input, args[0]));
44+
return typeof(val) === "number" ? val : NaN;
45+
},
46+
47+
48+
/**
49+
* Splits a string based on a delimiter and multiplies the numbers.
50+
*
51+
* @param {string} input
52+
* @param {Object[]} args
53+
* @returns {number}
54+
*/
55+
runMulti: function(input, args) {
56+
let val = Arithmetic._multi(Arithmetic._createNumArray(input, args[0]));
57+
return typeof(val) === "number" ? val : NaN;
58+
},
59+
60+
61+
/**
62+
* Splits a string based on a delimiter and divides the numbers.
63+
*
64+
* @param {string} input
65+
* @param {Object[]} args
66+
* @returns {number}
67+
*/
68+
runDiv: function(input, args) {
69+
let val = Arithmetic._div(Arithmetic._createNumArray(input, args[0]));
70+
return typeof(val) === "number" ? val : NaN;
71+
},
72+
73+
74+
/**
75+
* Splits a string based on a delimiter and computes the mean (average).
76+
*
77+
* @param {string} input
78+
* @param {Object[]} args
79+
* @returns {number}
80+
*/
81+
runMean: function(input, args) {
82+
let val = Arithmetic._mean(Arithmetic._createNumArray(input, args[0]));
83+
return typeof(val) === "number" ? val : NaN;
84+
},
85+
86+
87+
/**
88+
* Splits a string based on a delimiter and finds the median.
89+
*
90+
* @param {string} input
91+
* @param {Object[]} args
92+
* @returns {number}
93+
*/
94+
runMedian: function(input, args) {
95+
let val = Arithmetic._median(Arithmetic._createNumArray(input, args[0]));
96+
return typeof(val) === "number" ? val : NaN;
97+
},
98+
99+
100+
/**
101+
* splits a string based on a delimiter and computes the standard deviation.
102+
*
103+
* @param {string} input
104+
* @param {Object[]} args
105+
* @returns {number}
106+
*/
107+
runStdDev: function(input, args) {
108+
let val = Arithmetic._stdDev(Arithmetic._createNumArray(input, args[0]));
109+
return typeof(val) === "number" ? val : NaN;
110+
},
111+
112+
113+
/**
114+
* Converts a string array to a number array.
115+
*
116+
* @private
117+
* @param {string[]} input
118+
* @param {string} delim
119+
* @returns {number[]}
120+
*/
121+
_createNumArray: function(input, delim) {
122+
delim = Utils.charRep[delim || "Space"];
123+
let splitNumbers = input.split(delim),
124+
numbers = [],
125+
num;
126+
127+
for (let i = 0; i < splitNumbers.length; i++) {
128+
if (splitNumbers[i].indexOf(".") >= 0) {
129+
num = parseFloat(splitNumbers[i].trim());
130+
} else {
131+
num = parseInt(splitNumbers[i].trim(), 0);
132+
}
133+
if (!isNaN(num)) {
134+
numbers.push(num);
135+
}
136+
}
137+
return numbers;
138+
},
139+
140+
141+
/**
142+
* Adds an array of numbers and returns the value.
143+
*
144+
* @private
145+
* @param {number[]} data
146+
* @returns {number}
147+
*/
148+
_sum: function(data) {
149+
if (data.length > 0) {
150+
return data.reduce((acc, curr) => acc + curr);
151+
}
152+
},
153+
154+
155+
/**
156+
* Subtracts an array of numbers and returns the value.
157+
*
158+
* @private
159+
* @param {number[]} data
160+
* @returns {number}
161+
*/
162+
_sub: function(data) {
163+
if (data.length > 0) {
164+
return data.reduce((acc, curr) => acc - curr);
165+
}
166+
},
167+
168+
169+
/**
170+
* Multiplies an array of numbers and returns the value.
171+
*
172+
* @private
173+
* @param {number[]} data
174+
* @returns {number}
175+
*/
176+
_multi: function(data) {
177+
if (data.length > 0) {
178+
return data.reduce((acc, curr) => acc * curr);
179+
}
180+
},
181+
182+
183+
/**
184+
* Divides an array of numbers and returns the value.
185+
*
186+
* @private
187+
* @param {number[]} data
188+
* @returns {number}
189+
*/
190+
_div: function(data) {
191+
if (data.length > 0) {
192+
return data.reduce((acc, curr) => acc / curr);
193+
}
194+
},
195+
196+
197+
/**
198+
* Computes mean of a number array and returns the value.
199+
*
200+
* @private
201+
* @param {number[]} data
202+
* @returns {number}
203+
*/
204+
_mean: function(data) {
205+
if (data.length > 0) {
206+
return Arithmetic._sum(data) / data.length;
207+
}
208+
},
209+
210+
211+
/**
212+
* Computes median of a number array and returns the value.
213+
*
214+
* @private
215+
* @param {number[]} data
216+
* @returns {number}
217+
*/
218+
_median: function (data) {
219+
if ((data.length % 2) === 0) {
220+
let first, second;
221+
data.sort(function(a, b){
222+
return a - b;
223+
});
224+
first = data[Math.floor(data.length / 2)];
225+
second = data[Math.floor(data.length / 2) - 1];
226+
return Arithmetic._mean([first, second]);
227+
} else {
228+
return data[Math.floor(data.length / 2)];
229+
}
230+
},
231+
232+
233+
/**
234+
* Computes standard deviation of a number array and returns the value.
235+
*
236+
* @private
237+
* @param {number[]} data
238+
* @returns {number}
239+
*/
240+
_stdDev: function (data) {
241+
if (data.length > 0) {
242+
let avg = Arithmetic._mean(data);
243+
let devSum = 0;
244+
for (let i = 0; i < data.length; i++) {
245+
devSum += (data[i] - avg) ** 2;
246+
}
247+
return Math.sqrt(devSum / data.length);
248+
}
249+
},
250+
};
251+
252+
export default Arithmetic;

0 commit comments

Comments
 (0)