42template <
typename Cond, JanusScalar T1, JanusScalar T2>
43auto where(
const Cond &cond,
const T1 &if_true,
const T2 &if_false) {
44 if constexpr (std::is_floating_point_v<T1> && std::is_floating_point_v<T2>) {
45 return cond ? if_true : if_false;
48 return if_else(cond, if_true, if_false);
54template <
typename Cond,
typename DerivedTrue,
typename DerivedFalse>
55auto select(
const Cond &cond,
const Eigen::MatrixBase<DerivedTrue> &if_true,
56 const Eigen::MatrixBase<DerivedFalse> &if_false) {
57 if (if_true.rows() != if_false.rows() || if_true.cols() != if_false.cols()) {
58 throw InvalidArgument(
"select: matrix inputs must have the same shape");
62 std::declval<Cond>(), std::declval<typename DerivedTrue::Scalar>(),
63 std::declval<typename DerivedFalse::Scalar>()))>;
65 Eigen::Matrix<ResultScalar, DerivedTrue::RowsAtCompileTime, DerivedTrue::ColsAtCompileTime,
66 DerivedTrue::Options, DerivedTrue::MaxRowsAtCompileTime,
67 DerivedTrue::MaxColsAtCompileTime>;
69 ResultMatrix res(if_true.rows(), if_true.cols());
70 for (Eigen::Index i = 0; i < if_true.rows(); ++i) {
71 for (Eigen::Index j = 0; j < if_true.cols(); ++j) {
72 res(i, j) =
janus::where(cond, if_true(i, j), if_false(i, j));
79 if (expr.n_dep() == 0) {
101template <
typename Derived>
104 for (Eigen::Index i = 0; i < a.rows(); ++i) {
105 for (Eigen::Index j = 0; j < a.cols(); ++j) {
123template <
typename DerivedCond,
typename DerivedTrue,
typename DerivedFalse>
124auto where(
const Eigen::ArrayBase<DerivedCond> &cond,
const Eigen::MatrixBase<DerivedTrue> &if_true,
125 const Eigen::MatrixBase<DerivedFalse> &if_false) {
126 using Scalar =
typename DerivedTrue::Scalar;
127 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
130 Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> res(if_true.rows(), if_true.cols());
131 for (Eigen::Index i = 0; i < if_true.rows(); ++i) {
132 for (Eigen::Index j = 0; j < if_true.cols(); ++j) {
134 res(i, j) =
janus::where(cond.derived().coeff(i, j), if_true(i, j), if_false(i, j));
139 return cond.select(if_true, if_false);
151template <JanusScalar T1, JanusScalar T2>
auto min(
const T1 &a,
const T2 &b) {
152 if constexpr (std::is_floating_point_v<T1> && std::is_floating_point_v<T2>) {
153 return std::min(a, b);
169template <
typename Derived>
170auto min(
const Eigen::MatrixBase<Derived> &a,
const Eigen::MatrixBase<Derived> &b) {
171 using Scalar =
typename Derived::Scalar;
172 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
173 Eigen::Matrix<Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime> res(a.rows(),
175 for (Eigen::Index i = 0; i < a.rows(); ++i) {
176 for (Eigen::Index j = 0; j < a.cols(); ++j) {
182 return a.cwiseMin(b);
194template <JanusScalar T1, JanusScalar T2>
auto max(
const T1 &a,
const T2 &b) {
195 if constexpr (std::is_floating_point_v<T1> && std::is_floating_point_v<T2>) {
196 return std::max(a, b);
209template <
typename Derived>
210auto max(
const Eigen::MatrixBase<Derived> &a,
const Eigen::MatrixBase<Derived> &b) {
211 using Scalar =
typename Derived::Scalar;
212 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
213 Eigen::Matrix<Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime> res(a.rows(),
215 for (Eigen::Index i = 0; i < a.rows(); ++i) {
216 for (Eigen::Index j = 0; j < a.cols(); ++j) {
222 return a.cwiseMax(b);
235template <JanusScalar T, JanusScalar TLow, JanusScalar THigh>
236auto clamp(
const T &val,
const TLow &low,
const THigh &high) {
249template <
typename Derived,
typename Scalar>
250auto clamp(
const Eigen::MatrixBase<Derived> &val,
const Scalar &low,
const Scalar &high) {
251 using MatrixScalar =
typename Derived::Scalar;
252 if constexpr (std::is_same_v<MatrixScalar, SymbolicScalar>) {
253 return val.unaryExpr([=](
const auto &x) {
return janus::clamp(x, low, high); });
255 return val.cwiseMax(low).cwiseMin(high);
269template <
typename DerivedA,
typename DerivedB>
270auto lt(
const Eigen::MatrixBase<DerivedA> &a,
const Eigen::MatrixBase<DerivedB> &b) {
271 using Scalar =
typename DerivedA::Scalar;
272 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
273 return a.binaryExpr(b, [](
const auto &x,
const auto &y) {
return x < y; });
275 return (a.array() < b.array());
288template <
typename DerivedA,
typename DerivedB>
289auto gt(
const Eigen::MatrixBase<DerivedA> &a,
const Eigen::MatrixBase<DerivedB> &b) {
290 using Scalar =
typename DerivedA::Scalar;
291 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
292 return a.binaryExpr(b, [](
const auto &x,
const auto &y) {
return x > y; });
294 return (a.array() > b.array());
307template <
typename DerivedA,
typename DerivedB>
308auto le(
const Eigen::MatrixBase<DerivedA> &a,
const Eigen::MatrixBase<DerivedB> &b) {
309 using Scalar =
typename DerivedA::Scalar;
310 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
311 return a.binaryExpr(b, [](
const auto &x,
const auto &y) {
return x <= y; });
313 return (a.array() <= b.array());
326template <
typename DerivedA,
typename DerivedB>
327auto ge(
const Eigen::MatrixBase<DerivedA> &a,
const Eigen::MatrixBase<DerivedB> &b) {
328 using Scalar =
typename DerivedA::Scalar;
329 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
330 return a.binaryExpr(b, [](
const auto &x,
const auto &y) {
return x >= y; });
332 return (a.array() >= b.array());
345template <
typename DerivedA,
typename DerivedB>
346auto eq(
const Eigen::MatrixBase<DerivedA> &a,
const Eigen::MatrixBase<DerivedB> &b) {
347 using Scalar =
typename DerivedA::Scalar;
348 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
349 return a.binaryExpr(b, [](
const auto &x,
const auto &y) {
return x == y; });
351 return (a.array() == b.array());
364template <
typename DerivedA,
typename DerivedB>
365auto neq(
const Eigen::MatrixBase<DerivedA> &a,
const Eigen::MatrixBase<DerivedB> &b) {
366 using Scalar =
typename DerivedA::Scalar;
367 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
368 return a.binaryExpr(b, [](
const auto &x,
const auto &y) {
return x != y; });
370 return (a.array() != b.array());
386template <JanusScalar T, JanusScalar TLow, JanusScalar THigh, JanusScalar Sharpness =
double>
388 const Sharpness &sharpness = 1.0) {
390 auto alpha = 1.0 / (1.0 +
janus::exp(-sharpness * x));
391 return val_low + alpha * (val_high - val_low);
408template <
typename Derived,
typename Scalar>
409auto sigmoid_blend(
const Eigen::MatrixBase<Derived> &x,
const Scalar &val_low,
410 const Scalar &val_high,
const Scalar &sharpness = 1.0) {
411 auto alpha = (1.0 + (-sharpness * x.array()).
exp()).inverse();
412 return (val_low + alpha * (val_high - val_low)).matrix();
422template <JanusScalar T1, JanusScalar T2>
auto logical_and(
const T1 &x1,
const T2 &x2) {
435template <
typename DerivedA,
typename DerivedB>
436auto logical_and(
const Eigen::MatrixBase<DerivedA> &a,
const Eigen::MatrixBase<DerivedB> &b) {
437 using Scalar =
typename DerivedA::Scalar;
438 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
439 return a.binaryExpr(b, [](
const auto &x,
const auto &y) {
return x && y; });
442 return ((a.array() != 0) && (b.array() != 0));
453template <JanusScalar T1, JanusScalar T2>
auto logical_or(
const T1 &x1,
const T2 &x2) {
465template <
typename DerivedA,
typename DerivedB>
466auto logical_or(
const Eigen::MatrixBase<DerivedA> &a,
const Eigen::MatrixBase<DerivedB> &b) {
467 using Scalar =
typename DerivedA::Scalar;
468 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
469 return a.binaryExpr(b, [](
const auto &x,
const auto &y) {
return x || y; });
471 return ((a.array() != 0) || (b.array() != 0));
481template <JanusScalar T>
auto logical_not(
const T &x) {
return !x; }
489template <
typename Derived>
auto logical_not(
const Eigen::MatrixBase<Derived> &a) {
490 using Scalar =
typename Derived::Scalar;
491 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
492 return a.unaryExpr([](
const auto &x) {
return !x; });
494 return (a.array() == 0);
504template <
typename Derived>
auto all(
const Eigen::MatrixBase<Derived> &a) {
505 using Scalar =
typename Derived::Scalar;
506 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
509 return (a.array() != 0).all();
519template <
typename Derived>
auto any(
const Eigen::MatrixBase<Derived> &a) {
520 using Scalar =
typename Derived::Scalar;
521 if constexpr (std::is_same_v<Scalar, SymbolicScalar>) {
524 return (a.array() != 0).any();
546template <
typename CondType,
typename Scalar>
547Scalar
select(
const std::vector<CondType> &conditions,
const std::vector<Scalar> &values,
548 const Scalar &default_value) {
549 if (conditions.size() != values.size()) {
550 throw InvalidArgument(
"select: conditions and values must have same size");
554 Scalar result = default_value;
557 for (
int i =
static_cast<int>(conditions.size()) - 1; i >= 0; --i) {
558 result =
where(conditions[i], values[i], result);
565template <
typename CondType,
typename Scalar>
566Scalar
select(std::initializer_list<CondType> conditions, std::initializer_list<Scalar> values,
567 const Scalar &default_value) {
568 return select(std::vector<CondType>(conditions), std::vector<Scalar>(values), default_value);
Scalar and element-wise arithmetic functions (abs, sqrt, pow, exp, log, etc.).
C++20 concepts constraining valid Janus scalar types.
Custom exception hierarchy for Janus framework.
Core type aliases for numeric and symbolic Eigen/CasADi interop.
Input validation failed (e.g., mismatched sizes, invalid parameters).
Definition JanusError.hpp:31
SymbolicScalar as_symbolic_predicate(const SymbolicScalar &expr)
Definition Logic.hpp:97
bool is_symbolic_predicate(const SymbolicScalar &expr)
Definition Logic.hpp:78
auto select(const Cond &cond, const Eigen::MatrixBase< DerivedTrue > &if_true, const Eigen::MatrixBase< DerivedFalse > &if_false)
Definition Logic.hpp:55
SymbolicScalar count_symbolic_truthy(const Eigen::MatrixBase< Derived > &a)
Definition Logic.hpp:102
Definition Diagnostics.hpp:19
auto sigmoid_blend(const T &x, const TLow &val_low, const THigh &val_high, const Sharpness &sharpness=1.0)
Smoothly blends between val_low and val_high using a sigmoid function blend = val_low + (val_high - v...
Definition Logic.hpp:387
Scalar select(const std::vector< CondType > &conditions, const std::vector< Scalar > &values, const Scalar &default_value)
Multi-way conditional selection (cleaner alternative to nested where).
Definition Logic.hpp:547
auto where(const Cond &cond, const T1 &if_true, const T2 &if_false)
Select values based on condition (ternary operator) Returns: cond ? if_true : if_false Supports mixed...
Definition Logic.hpp:43
auto logical_not(const T &x)
Logical NOT (!x).
Definition Logic.hpp:481
auto clamp(const T &val, const TLow &low, const THigh &high)
Clamps value between low and high.
Definition Logic.hpp:236
auto le(const Eigen::MatrixBase< DerivedA > &a, const Eigen::MatrixBase< DerivedB > &b)
Element-wise less than or equal comparison.
Definition Logic.hpp:308
auto ge(const Eigen::MatrixBase< DerivedA > &a, const Eigen::MatrixBase< DerivedB > &b)
Element-wise greater than or equal comparison.
Definition Logic.hpp:327
auto any(const Eigen::MatrixBase< Derived > &a)
Returns true if any element is true (non-zero).
Definition Logic.hpp:519
typename BooleanType< T >::type BooleanType_t
Definition Logic.hpp:28
auto logical_and(const T1 &x1, const T2 &x2)
Logical AND (x && y).
Definition Logic.hpp:422
auto lt(const Eigen::MatrixBase< DerivedA > &a, const Eigen::MatrixBase< DerivedB > &b)
Element-wise less than comparison.
Definition Logic.hpp:270
auto gt(const Eigen::MatrixBase< DerivedA > &a, const Eigen::MatrixBase< DerivedB > &b)
Element-wise greater than comparison.
Definition Logic.hpp:289
auto neq(const Eigen::MatrixBase< DerivedA > &a, const Eigen::MatrixBase< DerivedB > &b)
Element-wise inequality comparison.
Definition Logic.hpp:365
auto logical_or(const T1 &x1, const T2 &x2)
Logical OR (x || y).
Definition Logic.hpp:453
auto eq(const Eigen::MatrixBase< DerivedA > &a, const Eigen::MatrixBase< DerivedB > &b)
Element-wise equality comparison.
Definition Logic.hpp:346
auto min(const T1 &a, const T2 &b)
Computes minimum of two values.
Definition Logic.hpp:151
casadi::MX SymbolicScalar
CasADi MX symbolic scalar.
Definition JanusTypes.hpp:70
auto max(const T1 &a, const T2 &b)
Computes maximum of two values.
Definition Logic.hpp:194
auto all(const Eigen::MatrixBase< Derived > &a)
Returns true if all elements are true (non-zero).
Definition Logic.hpp:504
T exp(const T &x)
Computes the exponential function e^x.
Definition Arithmetic.hpp:131
SymbolicScalar type
Definition Logic.hpp:25
bool type
Definition Logic.hpp:21