Skip to content

packages/engine/scram-node/src/expression/numerical.h

A collection of numerical expressions. More...

Namespaces

Name
scram
scram::mef

Classes

Name
structscram::mef::Functor <br>Creates a functor out of function pointer to common cmath functions.
structscram::mef::Bifunctor <br>Creates a functor for functions with two arguments.
classscram::mef::Mean <br>The average of argument expression values.

Detailed Description

A collection of numerical expressions.

Note: The PI value is located in constant expressions.

Source code

cpp
/*
 * Copyright (C) 2014-2018 Olzhas Rakhimov
 * Copyright (C) 2023 OpenPRA ORG Inc.
 *
 * 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 <http://www.gnu.org/licenses/>.
 */


#pragma once

#include <cmath>

#include <functional>
#include <vector>

#include "constant.h"
#include "src/expression.h"

namespace scram::mef {

template <double (*F)(double)>
struct Functor {
  double operator()(double arg) { return F(arg); }
};

template <double (*F)(double)>
using FunctorExpression = NaryExpression<Functor<F>, 1>;

template <double (*F)(double, double)>
struct Bifunctor {  // Nasty abuse of terminology :(. Haskellers will hate this.
  double operator()(double arg_one, double arg_two) {
    return F(arg_one, arg_two);
  }
};

template <double (*F)(double, double)>
using BifunctorExpression = NaryExpression<Bifunctor<F>, 2>;

using Neg = NaryExpression<std::negate<>, 1>;  
using Add = NaryExpression<std::plus<>, -1>;  
using Sub = NaryExpression<std::minus<>, -1>;  
using Mul = NaryExpression<std::multiplies<>, -1>;  
using Div = NaryExpression<std::divides<>, -1>;  
using Abs = FunctorExpression<&std::abs>;  
using Acos = FunctorExpression<&std::acos>;  
using Asin = FunctorExpression<&std::asin>;  
using Atan = FunctorExpression<&std::atan>;  
using Cos = FunctorExpression<&std::cos>;  
using Sin = FunctorExpression<&std::sin>;  
using Tan = FunctorExpression<&std::tan>;  
using Cosh = FunctorExpression<&std::cosh>;  
using Sinh = FunctorExpression<&std::sinh>;  
using Tanh = FunctorExpression<&std::tanh>;  
using Exp = FunctorExpression<&std::exp>;  
using Log = FunctorExpression<&std::log>;  
using Log10 = FunctorExpression<&std::log10>;  
using Mod = NaryExpression<std::modulus<int>, 2>;  
using Pow = BifunctorExpression<&std::pow>;  
using Sqrt = FunctorExpression<&std::sqrt>;  
using Ceil = FunctorExpression<&std::ceil>;  
using Floor = FunctorExpression<&std::floor>;  
using Min = NaryExpression<Bifunctor<&std::fmin>, -1>;  
using Max = NaryExpression<Bifunctor<&std::fmax>, -1>;  

class Mean : public ExpressionFormula<Mean> {
 public:
  explicit Mean(std::vector<Expression*> args);

  Interval interval() noexcept override {
    double min_value = 0;
    double max_value = 0;
    for (Expression* arg : Expression::args()) {
      Interval arg_interval = arg->interval();
      min_value += arg_interval.lower();
      max_value += arg_interval.upper();
    }
    min_value /= Expression::args().size();
    max_value /= Expression::args().size();
    return Interval::closed(min_value, max_value);
  }

  template <typename F>
  double Compute(F&& eval) noexcept {
    double sum = 0;
    for (Expression* arg : Expression::args())
      sum += eval(arg);
    return sum / Expression::args().size();
  }
};

template <>
void Div::Validate() const;

template <>
inline void Acos::Validate() const {
  assert(args().size() == 1);
  EnsureWithin(args().front(), Interval::closed(-1, 1), "Arc cos");
}

template <>
inline void Asin::Validate() const {
  assert(args().size() == 1);
  EnsureWithin(args().front(), Interval::closed(-1, 1), "Arc sin");
}

template <>
inline void Log::Validate() const {
  assert(args().size() == 1);
  EnsurePositive(args().front(), "Natural Logarithm");
}

template <>
inline void Log10::Validate() const {
  assert(args().size() == 1);
  EnsurePositive(args().front(), "Decimal Logarithm");
}

template <>
void Mod::Validate() const;

template <>
void Pow::Validate() const;

template <>
inline void Sqrt::Validate() const {
  assert(args().size() == 1);
  EnsureNonNegative(args().front(), "Square root");
}

template <>
inline Interval Acos::interval() noexcept {
  return Interval::closed(0, ConstantExpression::kPi.value());
}

template <>
inline Interval Asin::interval() noexcept {
  double half_pi = ConstantExpression::kPi.value() / 2;
  return Interval::closed(-half_pi, half_pi);
}

template <>
inline Interval Atan::interval() noexcept {
  double half_pi = ConstantExpression::kPi.value() / 2;
  return Interval::closed(-half_pi, half_pi);
}

template <>
inline Interval Cos::interval() noexcept {
  return Interval::closed(-1, 1);
}

template <>
inline Interval Sin::interval() noexcept {
  return Interval::closed(-1, 1);
}

}  // namespace scram::mef

Updated on 2025-11-11 at 16:51:08 +0000