NDEVR
API Documentation
Equation.h
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: Equation
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/String.h>
34#include <NDEVR/Dictionary.h>
35#include <cmath>
36namespace NDEVR
37{
43 template<class t_type>
45 {
46 public:
51 {}
52
56 {
57 char operation;
58 t_type value;
59 };
60
65 void setVariable(const StringView& var, t_type value)
66 {
67 m_variables[var] = value;
68 if (m_variable_locations.hasKey(var))
69 {
70 Buffer<uint04>& locations = m_variable_locations[var];
71 for (uint04 i = 0; i < locations.size(); i++)
72 m_equation_stack[locations[i]].value = value;
73 }
74 }
75
79 {
80 for (const auto& variable : m_variables)
81 {
82 Buffer<uint04>& locations = m_variable_locations[variable.first];
83 for (uint04 i = 0; i < locations.size(); i++)
84 m_equation_stack[locations[i]].value = variable.second;
85 }
86 }
87
94 static t_type solve(t_type left, const char op, t_type right)
95 {
96 switch (op)
97 {
98 case '+': return left + right;
99 case '-': return left - right;
100 case '/': return left / right;
101 case '*': return left * right;
102 case '^': return std::pow(left, right);
103 case '%': return std::fmod(left, right);
104 case 's': return std::sin(right);
105 case 'c': return std::cos(right);
106 case 't': return std::tan(right);
107 case 'q': return std::sqrt(right);
108 case '\0': return right;
109 default: return Constant<t_type>::Invalid;
110 }
111 }
112
116 t_type solve() const
117 {
118 uint04 index = 0;
119 t_type value = solve(cast<t_type>(0), index);
120
121 if (index != m_equation_stack.size())
122 return Constant<t_type>::Invalid;
123 return value;
124 }
125
130 void add(char operation, t_type value)
131 {
132 EquationPart part{};
133 part.value = value;
134 part.operation = operation;
135 m_equation_stack.add(part);
136 }
137
142 static uint04 getOrderPriority(const char op)
143 {
144 switch (op)
145 {
146 case '+': return 10;
147 case '-': return 10;
148 case '/': return 20;
149 case '*': return 20;
150 case '^': return 30;
151 case '%': return 30;
152 case 's': return 40;
153 case 'c': return 40;
154 case 't': return 40;
155 case 'q': return 40;
156 default: return Constant<t_type>::Invalid;
157 }
158 }
159
164 void addOrderOfOps(char operation, t_type value)
165 {
166 EquationPart part;
167 part.value = value;
168 part.operation = operation;
169 uint04 insertion_index = m_equation_stack.size();
170 m_equation_stack.add(insertion_index, part);
171 }
172
177 void add(char operation, const String& value)
178 {
179 m_variable_locations[value].add(m_equation_stack.size());
180
181 EquationPart part{};
182 part.value = Constant<t_type>::Invalid;
183 part.operation = operation;
184
185 m_equation_stack.add(part);
186 }
187
193 t_type solve(t_type start, uint04& current_index) const
194 {
195 for (; current_index < m_equation_stack.size(); current_index++)
196 {
197 if (IsInvalid(m_equation_stack[current_index].value))
198 return Constant<t_type>::Invalid;
199 const char current = m_equation_stack[current_index].operation;
200 switch (current)
201 {
202 case '\0': start += m_equation_stack[current_index].value; break;
203 case '+': start += m_equation_stack[current_index].value; break;
204 case '-': start -= m_equation_stack[current_index].value; break;
205 case '/': start /= m_equation_stack[current_index].value; break;
206 case '*': start *= m_equation_stack[current_index].value; break;
207 case '^': start = std::pow(start, m_equation_stack[current_index].value); break;
208 case '%': start = std::fmod(start, m_equation_stack[current_index].value); break;
209 case 's':
210 case 'c':
211 case 't':
212 case 'q':
213 case '(':
214 {
215 const char lead_operation = cast<char>(m_equation_stack[current_index].value);
216 t_type inner_solve = solve(cast<t_type>(0), ++current_index);
217 if (current_index >= m_equation_stack.size())
218 return Constant<t_type>::Invalid;//no closing ')'
219 switch (current)
220 {
221 case 's': inner_solve = sin(inner_solve); break;
222 case 'c': inner_solve = cos(inner_solve); break;
223 case 't': inner_solve = tan(inner_solve); break;
224 case 'q': inner_solve = sqrt(inner_solve); break;
225 default: break;
226 }
227 start = solve(start, lead_operation, inner_solve);
228 } break;
229 case ')': return start;
230 default: lib_assert(false, "unknown operator");
231 }
232 }
233 return start;
234 }
238 };
239
240}
241
242
The equivelent of std::vector but with a bit more control.
Definition Buffer.hpp:58
A hash-based key-value store, useful for quick associative lookups.
Definition Dictionary.h:64
Dictionary< String, Buffer< uint04 > > m_variable_locations
Maps variable names to their indices within the equation stack.
Definition Equation.h:235
t_type solve(t_type start, uint04 &current_index) const
Recursively solves the equation stack starting from the given index, accumulating onto a starting val...
Definition Equation.h:193
void add(char operation, t_type value)
Appends a numeric equation part to the equation stack.
Definition Equation.h:130
void setVariable(const StringView &var, t_type value)
Sets the value of a named variable and updates all locations in the equation stack that reference it.
Definition Equation.h:65
void addOrderOfOps(char operation, t_type value)
Adds an equation part at a position determined by order-of-operations priority.
Definition Equation.h:164
Buffer< EquationPart > m_equation_stack
The ordered stack of equation parts representing the formula.
Definition Equation.h:237
static uint04 getOrderPriority(const char op)
Returns the order-of-operations priority for the given operator.
Definition Equation.h:142
void refreshVariables()
Refreshes all variable locations in the equation stack using the currently stored variable values.
Definition Equation.h:78
static t_type solve(t_type left, const char op, t_type right)
Solves a single binary or unary operation given a left operand, operator, and right operand.
Definition Equation.h:94
Dictionary< String, t_type > m_variables
Maps variable names to their current numeric values.
Definition Equation.h:236
t_type solve() const
Solves the entire equation by evaluating the equation stack from the beginning.
Definition Equation.h:116
Equation()
Default constructor.
Definition Equation.h:50
void add(char operation, const String &value)
Appends a variable-referencing equation part to the equation stack.
Definition Equation.h:177
The core String View class for the NDEVR API.
Definition StringView.h:58
The core String class for the NDEVR API.
Definition String.h:95
The primary namespace for the NDEVR SDK.
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
static constexpr bool IsInvalid(const Angle< t_type > &value)
Checks whether the given Angle holds an invalid value.
Definition Angle.h:388
t_type sqrt(const t_type &value)
std::enable_if<!ObjectInfo< t_type >::Float, fltp08 >::type sin(const Angle< t_type > &angle)
Performs optimized sine operation on the given angle using pre-computed lookup table for optimal spee...
std::enable_if<!ObjectInfo< t_type >::Float, fltp08 >::type tan(const Angle< t_type > &angle)
Performs optimized tangent operation on the given angle using pre-computed lookup table for optimal s...
std::enable_if<!ObjectInfo< t_type >::Float, fltp08 >::type cos(const Angle< t_type > &angle)
Performs optimized cosine operation on the given angle using pre-computed lookup table for optimal sp...
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408
Represents a single element in the equation stack, consisting of an operator and a value.
Definition Equation.h:56
t_type value
The numeric value or encoded sub-expression parameter for this part.
Definition Equation.h:58
char operation
The operator character (e.g., '+', '-', '*', '/', '^', '', 's', 'c', 't', 'q', '(',...
Definition Equation.h:57