+ex epsilon_tensor(const ex & i1, const ex & i2, const ex & i3)
+{
+ if (!is_ex_of_type(i1, idx) || !is_ex_of_type(i2, idx) || !is_ex_of_type(i3, idx))
+ throw(std::invalid_argument("indices of epsilon tensor must be of type idx"));
+
+ ex dim = ex_to_idx(i1).get_dim();
+ if (!dim.is_equal(ex_to_idx(i2).get_dim()) || !dim.is_equal(ex_to_idx(i3).get_dim()))
+ throw(std::invalid_argument("all indices of epsilon tensor must have the same dimension"));
+ if (!ex_to_idx(i1).get_dim().is_equal(_ex3()))
+ throw(std::runtime_error("index dimension of epsilon tensor must match number of indices"));
+
+ return indexed(tensepsilon(), indexed::antisymmetric, i1, i2, i3);
+}
+
+ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig)
+{
+ if (!is_ex_of_type(i1, varidx) || !is_ex_of_type(i2, varidx) || !is_ex_of_type(i3, varidx) || !is_ex_of_type(i4, varidx))
+ throw(std::invalid_argument("indices of Lorentz epsilon tensor must be of type varidx"));
+
+ ex dim = ex_to_idx(i1).get_dim();
+ if (!dim.is_equal(ex_to_idx(i2).get_dim()) || !dim.is_equal(ex_to_idx(i3).get_dim()) || !dim.is_equal(ex_to_idx(i4).get_dim()))
+ throw(std::invalid_argument("all indices of epsilon tensor must have the same dimension"));
+ if (!ex_to_idx(i1).get_dim().is_equal(_ex4()))
+ throw(std::runtime_error("index dimension of epsilon tensor must match number of indices"));
+
+ return indexed(tensepsilon(true, pos_sig), indexed::antisymmetric, i1, i2, i3, i4);
+}
+