commit
message
Formulas.XOR written and tested.
author
Ben Vogt <[email protected]>
date
2017-02-04 22:45:13
stats
4 file(s) changed,
81 insertions(+),
30 deletions(-)
files
src/RawFormulas/Logical.ts
src/RawFormulas/Math.ts
src/RawFormulas/RawFormulas.ts
tests/FormulasTest.ts
1diff --git a/src/RawFormulas/Logical.ts b/src/RawFormulas/Logical.ts
2index 72036de..c135483 100644
3--- a/src/RawFormulas/Logical.ts
4+++ b/src/RawFormulas/Logical.ts
5@@ -1,4 +1,4 @@
6-import { checkArgumentsAtLeastLength, checkArgumentsLength, valueToString } from "./Utils"
7+import { checkArgumentsAtLeastLength, checkArgumentsLength, valueToString, valueToBoolean } from "./Utils"
8 import { CellError } from "../Errors"
9 import * as ERRORS from "../Errors"
10
11@@ -91,9 +91,34 @@ var NOT = function (...values) : boolean {
12 }
13 };
14
15+/**
16+ * Returns true if any of the provided arguments are logically true, and false if all of the provided arguments are logically false.
17+ * TODO: Should this allow the acceptance of functions that return true or false?
18+ * @param values An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.
19+ * @returns {boolean}
20+ * @constructor
21+ */
22+var OR = function (...values) {
23+ checkArgumentsAtLeastLength(values, 1);
24+ for (var i = 0; i < values.length; i++) {
25+ if (values[i] instanceof Array) {
26+ if (values[i].length === 0) {
27+ throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
28+ }
29+ if (OR.apply(this, values[i])) {
30+ return true;
31+ }
32+ } else if (valueToBoolean(values[i])) {
33+ return true;
34+ }
35+ }
36+ return false;
37+};
38+
39 export {
40 AND,
41 EXACT,
42 TRUE,
43- NOT
44+ NOT,
45+ OR
46 }
47\ No newline at end of file
48diff --git a/src/RawFormulas/Math.ts b/src/RawFormulas/Math.ts
49index 41025c8..3b5c7ad 100644
50--- a/src/RawFormulas/Math.ts
51+++ b/src/RawFormulas/Math.ts
52@@ -672,30 +672,6 @@ var LOG = function (...values) : number {
53 return ln / lb;
54 };
55
56-/**
57- * Returns true if any of the provided arguments are logically true, and false if all of the provided arguments are logically false.
58- * TODO: Should this allow the acceptance of functions that return true or false?
59- * @param values An expression or reference to a cell containing an expression that represents some logical value, i.e. TRUE or FALSE, or an expression that can be coerced to a logical value.
60- * @returns {boolean}
61- * @constructor
62- */
63-var OR = function (...values) {
64- checkArgumentsAtLeastLength(values, 1);
65- for (var i = 0; i < values.length; i++) {
66- if (values[i] instanceof Array) {
67- if (values[i].length === 0) {
68- throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
69- }
70- if (OR.apply(this, values[i])) {
71- return true;
72- }
73- } else if (valueToBoolean(values[i])) {
74- return true;
75- }
76- }
77- return false;
78-};
79-
80 /**
81 * Returns the tangent of an angle provided in radians.
82 * @param values The angle to find the tangent of, in radians.
83@@ -755,7 +731,6 @@ export {
84 SQRT,
85 PI,
86 POWER,
87- OR,
88 LOG,
89 LOG10,
90 TAN,
91diff --git a/src/RawFormulas/RawFormulas.ts b/src/RawFormulas/RawFormulas.ts
92index a072a42..c465157 100644
93--- a/src/RawFormulas/RawFormulas.ts
94+++ b/src/RawFormulas/RawFormulas.ts
95@@ -36,7 +36,6 @@ import {
96 SQRT,
97 PI,
98 POWER,
99- OR,
100 LOG,
101 LOG10,
102 TAN,
103@@ -46,7 +45,8 @@ import {
104 AND,
105 EXACT,
106 TRUE,
107- NOT
108+ NOT,
109+ OR
110 } from "./Logical";
111 import {
112 CHAR,
113@@ -152,7 +152,37 @@ var SUMSQ = Formula["SUMSQ"];
114 var SUMX2MY2 = Formula["SUMX2MY2"];
115 var SUMX2PY2 = Formula["SUMX2PY2"];
116 var TRUNC = Formula["TRUNC"];
117-var XOR = Formula["XOR"];
118+
119+/**
120+ * Exclusive or or exclusive disjunction is a logical operation that outputs true only when inputs differ.
121+ * @param values to check for exclusivity.
122+ * @returns {boolean} returns true if only one input is considered logically true.
123+ * @constructor
124+ */
125+var XOR = function (...values) {
126+ checkArgumentsAtLeastLength(values, 1);
127+ var alreadyTruthy = false;
128+ for (var i = 0; i < values.length; i++) {
129+ if (values[i] instanceof Array) {
130+ if (values[i].length === 0) {
131+ throw new CellError(ERRORS.REF_ERROR, "Reference does not exist.");
132+ }
133+ if (XOR.apply(this, values[i])) {
134+ if (alreadyTruthy) {
135+ return false;
136+ }
137+ alreadyTruthy = true;
138+ }
139+ } else if (valueToBoolean(values[i])) {
140+ if (alreadyTruthy) {
141+ return false;
142+ }
143+ alreadyTruthy = true;
144+ }
145+ }
146+ return alreadyTruthy;
147+};
148+
149 var YEARFRAC = Formula["YEARFRAC"];
150
151 export {
152diff --git a/tests/FormulasTest.ts b/tests/FormulasTest.ts
153index 9f4e3bf..1f54db8 100644
154--- a/tests/FormulasTest.ts
155+++ b/tests/FormulasTest.ts
156@@ -1041,11 +1041,32 @@ assertEquals(TANH([1, 44]), 0.7615941559557649);
157 assertEquals(TANH([1, "str"]), 0.7615941559557649);
158
159
160+// Test TRUE
161 assertEquals(TRUE(), true);
162
163 assertEquals(TRUNC(3.1415, 2), 3.14);
164
165+// Test XOR
166 assertEquals(XOR(1, 1), false);
167+assertEquals(XOR(1, 0), true);
168+assertEquals(XOR(0, 0, 0), false);
169+assertEquals(XOR(0, 0, 1), true);
170+assertEquals(XOR(0, 0, [0, 0, 1]), true);
171+assertEquals(XOR(0, 1, [0, 0, 1]), false);
172+catchAndAssertEquals(function() {
173+ XOR("str");
174+}, ERRORS.VALUE_ERROR);
175+catchAndAssertEquals(function() {
176+ XOR();
177+}, ERRORS.NA_ERROR);
178+catchAndAssertEquals(function() {
179+ XOR(1, []);
180+}, ERRORS.REF_ERROR);
181+catchAndAssertEquals(function() {
182+ XOR([]);
183+}, ERRORS.REF_ERROR);
184+
185+
186
187 assertEquals(YEARFRAC(DATE(1969, 7, 6), DATE(1988, 7, 4), 0), 18.994444444444444);
188 // assertEquals(YEARFRAC(DATE(1969, 7, 6), DATE(1988, 7, 4), 1)', 18.99587544); // This is slightly off