diff --git a/share/input.rng b/share/input.rng
index 3edd84bd5e..787ca2596a 100644
--- a/share/input.rng
+++ b/share/input.rng
@@ -632,6 +632,7 @@
+
@@ -837,6 +838,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ab313c8d2b..639ef973cc 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -32,6 +32,7 @@ set(SCRAM_CORE_SRC
"${CMAKE_CURRENT_SOURCE_DIR}/element.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/expression.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/parameter.cc"
+ "${CMAKE_CURRENT_SOURCE_DIR}/expression/conditional.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/expression/constant.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/expression/numerical.cc"
"${CMAKE_CURRENT_SOURCE_DIR}/expression/exponential.cc"
diff --git a/src/expression/conditional.cc b/src/expression/conditional.cc
new file mode 100644
index 0000000000..b86246ab43
--- /dev/null
+++ b/src/expression/conditional.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/// @file conditional.cc
+/// Implementation of conditional expressions.
+
+#include "conditional.h"
+
+#include
+
+namespace scram {
+namespace mef {
+
+Interval Ite::interval() noexcept {
+ assert(args().size() == 3);
+ Interval then_interval = args()[1]->interval();
+ Interval else_interval = args()[2]->interval();
+ return Interval::closed(
+ std::min(then_interval.lower(), else_interval.lower()),
+ std::max(then_interval.upper(), else_interval.upper()));
+}
+
+} // namespace mef
+} // namespace scram
diff --git a/src/expression/conditional.h b/src/expression/conditional.h
new file mode 100644
index 0000000000..0b3f9eb487
--- /dev/null
+++ b/src/expression/conditional.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 Olzhas Rakhimov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/// @file conditional.h
+/// Conditional (if-then-else, switch-case) expressions.
+
+#ifndef SCRAM_SRC_EXPRESSION_CONDITIONAL_H_
+#define SCRAM_SRC_EXPRESSION_CONDITIONAL_H_
+
+#include "src/expression.h"
+
+namespace scram {
+namespace mef {
+
+/// If-Then-Else ternary expression.
+class Ite : public ExpressionFormula {
+ public:
+ /// @param[in] condition The Boolean expression to be tested.
+ /// @param[in] then_arm The expression if the Boolean is true.
+ /// @param[in] else_arm The expression if the Boolean is false.
+ Ite(Expression* condition, Expression* then_arm, Expression* else_arm)
+ : ExpressionFormula({condition, then_arm, else_arm}) {}
+
+ Interval interval() noexcept override;
+
+ /// Computes the if-then-else expression with the given evaluator.
+ template
+ double Compute(F&& eval) noexcept {
+ assert(args().size() == 3);
+ return eval(args()[0]) ? eval(args()[1]) : eval(args()[2]);
+ }
+};
+
+} // namespace mef
+} // namespace scram
+
+#endif // SCRAM_SRC_EXPRESSION_CONDITIONAL_H_
diff --git a/src/initializer.cc b/src/initializer.cc
index 4692e97ca7..0c4010d32d 100644
--- a/src/initializer.cc
+++ b/src/initializer.cc
@@ -30,6 +30,7 @@
#include "env.h"
#include "error.h"
#include "expression/boolean.h"
+#include "expression/conditional.h"
#include "expression/exponential.h"
#include "expression/numerical.h"
#include "expression/random_deviate.h"
@@ -834,7 +835,8 @@ const Initializer::ExtractorMap Initializer::kExpressionExtractors_ = {
{"lt", &Extract},
{"gt", &Extract},
{"leq", &Extract},
- {"geq", &Extract}};
+ {"geq", &Extract},
+ {"ite", &Extract}};
Expression* Initializer::GetExpression(const xmlpp::Element* expr_element,
const std::string& base_path) {
diff --git a/tests/expression_tests.cc b/tests/expression_tests.cc
index 32dcb2ef39..ed4eda2d3d 100644
--- a/tests/expression_tests.cc
+++ b/tests/expression_tests.cc
@@ -17,6 +17,7 @@
#include "expression.h"
#include "expression/boolean.h"
+#include "expression/conditional.h"
#include "expression/exponential.h"
#include "expression/constant.h"
#include "expression/numerical.h"
@@ -1150,6 +1151,22 @@ TEST(ExpressionTest, Geq) {
EXPECT_DOUBLE_EQ(0, dev->value());
}
+TEST(ExpressionTest, Ite) {
+ OpenExpression arg_one(1);
+ OpenExpression arg_two(42, 42, 32, 52);
+ OpenExpression arg_three(10, 10, 5, 15);
+ std::unique_ptr dev;
+ ASSERT_NO_THROW(dev = std::make_unique(&arg_one, &arg_two, &arg_three));
+ EXPECT_DOUBLE_EQ(42, dev->value());
+ arg_one.mean = 0;
+ EXPECT_DOUBLE_EQ(10, dev->value());
+ arg_one.mean = 0.5;
+ EXPECT_DOUBLE_EQ(42, dev->value());
+
+ EXPECT_TRUE(Interval::closed(5, 52) == dev->interval())
+ << dev->interval();
+}
+
} // namespace test
} // namespace mef
} // namespace scram
diff --git a/tests/input/fta/correct_expressions.xml b/tests/input/fta/correct_expressions.xml
index d32df4bd38..4df168874e 100644
--- a/tests/input/fta/correct_expressions.xml
+++ b/tests/input/fta/correct_expressions.xml
@@ -353,5 +353,12 @@ The input tries to utilize all the functionality including optional cases.
+
+
+
+
+
+
+