Skip to content

Commit fe6c5bc

Browse files
Fix bugs
1 parent 9825eed commit fe6c5bc

File tree

3 files changed

+108
-40
lines changed

3 files changed

+108
-40
lines changed

mathml-rs/src/lib.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,14 @@ pub fn parse_fragment(
5454
b"lt" => attach![Op::Lt to Apply],
5555
b"geq" => attach![Op::Geq to Apply],
5656
b"leq" => attach![Op::Leq to Apply],
57+
b"and" => attach![Op::And to Apply],
58+
b"or" => attach![Op::Or to Apply],
59+
b"xor" => attach![Op::Xor to Apply],
5760
b"ceiling" => attach![Op::Ceiling to Apply],
5861
b"floor" => attach![Op::Floor to Apply],
5962
b"true" => attach![Constant::True to Apply | Piece ],
6063
b"false" => attach![Constant::False to Apply | Piece ],
61-
b"ci" => attach![Ci to Apply | BVar | Piece | Otherwise | Lambda ],
64+
b"ci" => attach![Ci to Root | Apply | BVar | Piece | Otherwise | Lambda ],
6265
b"cn" => attach![Cn with
6366
r#type as NumType,
6467
to Root | Apply | BVar | Piece | Otherwise | Lambda ],
@@ -67,6 +70,7 @@ pub fn parse_fragment(
6770
b"piecewise" => attach![Piecewise to Root | Apply | Lambda],
6871
b"piece" => attach![Piece to Piecewise],
6972
b"otherwise" => attach![Otherwise to Piecewise],
73+
b"sep" => new_tag = None,
7074
_ => {
7175
panic!("Tag not parsed: {}", std::str::from_utf8(e.name()).unwrap());
7276
}
@@ -90,6 +94,9 @@ pub fn parse_fragment(
9094
b"leq" => close![Op],
9195
b"gt" => close![Op],
9296
b"lt" => close![Op],
97+
b"and" => close![Op],
98+
b"or" => close![Op],
99+
b"xor" => close![Op],
93100
b"ceiling" => close![Op],
94101
b"floor" => close![Op],
95102
b"piecewise" => close![Piecewise],
@@ -120,6 +127,29 @@ pub fn parse_fragment(
120127
let value = s.parse::<i32>().expect("Incorrect type");
121128
cn.value = Some(Number::Integer(value));
122129
}
130+
Some(NumType::Rational) => {
131+
let value = s.parse::<i32>().expect("Incorrect type");
132+
if cn.value.is_none() {
133+
cn.value = Some(Number::Rational(value.into(), 1));
134+
} else if let Some(Number::Rational(x, y)) = cn.value {
135+
if y != 1 {
136+
panic!("Error occurred while storing rational number.");
137+
}
138+
cn.value = Some(Number::Rational(x, value.into()));
139+
}
140+
}
141+
142+
Some(NumType::ENotation) => {
143+
let value = s.parse::<i32>().expect("Incorrect type");
144+
if cn.value.is_none() {
145+
cn.value = Some(Number::ENotation(value.into(), 1));
146+
} else if let Some(Number::ENotation(x, y)) = cn.value {
147+
if y != 1 {
148+
panic!("Error occurred while storing rational number.");
149+
}
150+
cn.value = Some(Number::ENotation(x, value.into()));
151+
}
152+
}
123153
_ => {
124154
panic!("Math type did not match for cn: {:?}", cn);
125155
}

mathml-rs/src/methods/evaluate.rs

Lines changed: 74 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub fn evaluate_node(
1313
functions: &HashMap<String, Vec<MathNode>>,
1414
) -> Result<f64, String> {
1515
let head = nodes[head_idx].clone();
16+
//dbg!(values);
1617
match head {
1718
MathNode::Root(root) => {
1819
if root.children.len() != 1 {
@@ -99,9 +100,14 @@ pub fn evaluate_node(
99100
for operand in apply.operands {
100101
argument_values.push(evaluate_node(nodes, operand, values, functions)?);
101102
}
102-
//println!("evaluating");
103-
res = Some(evaluate_lambda(lambda, 0, &argument_values, functions)?);
104-
//dbg!(res);
103+
res = Some(evaluate_lambda(
104+
lambda,
105+
0,
106+
&argument_values,
107+
values,
108+
functions,
109+
)?);
110+
//dbg!(lambda_name, res);
105111
}
106112
}
107113
if let Some(value) = res {
@@ -128,6 +134,20 @@ pub fn evaluate_node(
128134
Err("Wrong type".to_string())
129135
}
130136
}
137+
Some(NumType::Rational) => {
138+
if let Some(Number::Rational(x, y)) = cn.value {
139+
Ok((x as f64) / (y as f64))
140+
} else {
141+
Err("Wrong type".to_string())
142+
}
143+
}
144+
Some(NumType::ENotation) => {
145+
if let Some(Number::ENotation(x, y)) = cn.value {
146+
Ok(x * 10.0_f64.powf(y as f64))
147+
} else {
148+
Err("Wrong type".to_string())
149+
}
150+
}
131151
_ => Err("Invalid Cn type".to_string()),
132152
},
133153
MathNode::Ci(ci) => {
@@ -153,6 +173,7 @@ pub fn evaluate_lambda(
153173
nodes: &[MathNode],
154174
head_idx: NodeIndex,
155175
argument_values: &[f64],
176+
values: &HashMap<String, f64>,
156177
functions: &HashMap<String, Vec<MathNode>>,
157178
) -> Result<f64, String> {
158179
let head = nodes[head_idx].clone();
@@ -161,7 +182,7 @@ pub fn evaluate_lambda(
161182
if root.children.len() != 1 {
162183
return Err("Root with multiple/zero children!".to_string());
163184
}
164-
evaluate_lambda(nodes, root.children[0], argument_values, functions)
185+
evaluate_lambda(nodes, root.children[0], argument_values, values, functions)
165186
}
166187
MathNode::Lambda(lambda) => {
167188
let mut argument_names = Vec::new();
@@ -182,18 +203,11 @@ pub fn evaluate_lambda(
182203
for i in 0..argument_values.len() {
183204
assignments.insert(argument_names[i].clone(), argument_values[i]);
184205
}
185-
Ok(evaluate_node(
186-
nodes,
187-
lambda.expr.unwrap(),
188-
&assignments,
189-
functions,
190-
)?)
206+
let res = evaluate_node(nodes, lambda.expr.unwrap(), &assignments, functions)?;
207+
Ok(res)
191208
}
192209
}
193-
_ => {
194-
//dbg!(head);
195-
Err("couldn't parse lambda".to_string())
196-
}
210+
_ => evaluate_node(nodes, head_idx, values, functions),
197211
}
198212
}
199213

@@ -292,40 +306,66 @@ pub fn evaluate_condition(
292306
let mut result = None;
293307
// If this is a regular mathematical operator, go ahead
294308
if let Ok(op) = op_result {
295-
let mut a = None;
296-
let mut b = None;
309+
let mut operand_results = Vec::<f64>::new();
310+
let mut child_condition_results = Vec::<bool>::new();
297311
match op {
298312
Op::Eq | Op::Neq | Op::Geq | Op::Leq | Op::Gt | Op::Lt => {
299313
if apply.operands.len() != 2 {
300314
return Err("Invalid number of operands.".to_string());
301315
}
302-
a = Some(evaluate_node(nodes, apply.operands[0], values, functions)?);
303-
b = Some(evaluate_node(nodes, apply.operands[1], values, functions)?);
316+
for operand_location in apply.operands {
317+
operand_results.push(evaluate_node(
318+
nodes,
319+
operand_location,
320+
values,
321+
functions,
322+
)?);
323+
}
324+
}
325+
Op::And | Op::Or | Op::Xor => {
326+
for operand_location in apply.operands {
327+
child_condition_results.push(evaluate_condition(
328+
nodes,
329+
operand_location,
330+
values,
331+
functions,
332+
)?);
333+
}
304334
}
305335
_ => {}
306336
}
307-
if let Some(first_value) = a {
308-
if let Some(second_value) = b {
309-
match op {
310-
Op::Eq => {
311-
result = Some((first_value - second_value).abs() <= f64::EPSILON)
312-
}
313-
Op::Neq => {
314-
result = Some((first_value - second_value).abs() > f64::EPSILON)
315-
}
316-
Op::Gt => result = Some(first_value > second_value),
317-
Op::Lt => result = Some(first_value < second_value),
318-
Op::Geq => result = Some(first_value >= second_value),
319-
Op::Leq => result = Some(first_value <= second_value),
320-
_ => {}
321-
}
337+
338+
let condition_count = child_condition_results.len();
339+
let true_count = child_condition_results.iter().filter(|x| **x).count();
340+
match op {
341+
Op::Eq => {
342+
result =
343+
Some((operand_results[0] - operand_results[1]).abs() <= f64::EPSILON)
322344
}
345+
Op::Neq => {
346+
result =
347+
Some((operand_results[0] - operand_results[1]).abs() > f64::EPSILON)
348+
}
349+
Op::Gt => result = Some(operand_results[0] > operand_results[1]),
350+
Op::Lt => result = Some(operand_results[0] < operand_results[1]),
351+
Op::Geq => result = Some(operand_results[0] >= operand_results[1]),
352+
Op::Leq => result = Some(operand_results[0] <= operand_results[1]),
353+
Op::And => result = Some(condition_count == true_count),
354+
Op::Or => result = Some(true_count > 0),
355+
Op::Xor => {
356+
result = Some(true_count % 2 == 1);
357+
//dbg!(child_condition_results);
358+
//if result.unwrap() {
359+
//dbg!(result.unwrap());
360+
//}
361+
}
362+
_ => {}
323363
}
324364
}
325365
if let Some(value) = result {
326366
Ok(value)
327367
} else {
328-
Err("Invalid operator".to_string())
368+
Err("Condition not supported".to_string())
329369
}
330370
}
331371
_ => {

mathml-rs/src/structs/lambda.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ impl Lambda {
1616
| MathNodeType::Apply
1717
| MathNodeType::Lambda
1818
| MathNodeType::Piecewise
19+
| MathNodeType::Ci
20+
| MathNodeType::Cn
1921
| MathNodeType::Constant => {
2022
if self.expr == None {
2123
self.expr = Some(location);
@@ -26,11 +28,7 @@ impl Lambda {
2628
MathNodeType::BVar => {
2729
self.bindings.push(location);
2830
}
29-
MathNodeType::Root
30-
| MathNodeType::Ci
31-
| MathNodeType::Cn
32-
| MathNodeType::Piece
33-
| MathNodeType::Otherwise => {
31+
MathNodeType::Root | MathNodeType::Piece | MathNodeType::Otherwise => {
3432
panic!("Can't have {} in a lambda function!", tag_type);
3533
}
3634
}

0 commit comments

Comments
 (0)