Program Listing for File deparse.cpp¶
↰ Return to documentation for file (SeQuant/core/parse/deparse.cpp
)
#include <SeQuant/core/parse.hpp>
#include <SeQuant/core/attr.hpp>
#include <SeQuant/core/complex.hpp>
#include <SeQuant/core/expr.hpp>
#include <SeQuant/core/index.hpp>
#include <SeQuant/core/tensor.hpp>
#include <range/v3/all.hpp>
#include <cassert>
#include <codecvt>
#include <cstddef>
#include <locale>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
namespace sequant {
namespace details {
template <typename Range>
std::wstring deparse_indices(const Range& indices) {
std::wstring deparsed;
for (std::size_t i = 0; i < indices.size(); ++i) {
deparsed += deparse(indices[i]);
if (i + 1 < indices.size()) {
deparsed += L",";
}
}
return deparsed;
}
std::wstring deparse_sym(Symmetry sym) {
switch (sym) {
case Symmetry::symm:
return L"S";
case Symmetry::antisymm:
return L"A";
case Symmetry::nonsymm:
return L"N";
case Symmetry::invalid:
return L"INVALID";
}
assert(false);
return L"INVALIDANDUNREACHABLE";
}
std::wstring deparse_scalar(const Constant::scalar_type& scalar) {
const auto& real = scalar.real();
const auto& realNumerator = boost::multiprecision::numerator(real);
const auto& realDenominator = boost::multiprecision::denominator(real);
const auto& imag = scalar.imag();
const auto& imagNumerator = boost::multiprecision::numerator(imag);
const auto& imagDenominator = boost::multiprecision::denominator(imag);
std::string deparsed;
if (realNumerator != 0) {
deparsed += realNumerator.str();
if (realDenominator != 1) {
deparsed += "/" + realDenominator.str();
}
}
if (imagNumerator != 0) {
if (!deparsed.empty()) {
deparsed += imagNumerator < 0 ? " + i " : " - i ";
}
deparsed += imagNumerator.str();
if (imagDenominator != 1) {
deparsed += "/" + imagDenominator.str();
}
}
SEQUANT_PRAGMA_CLANG(diagnostic push)
SEQUANT_PRAGMA_CLANG(diagnostic ignored "-Wdeprecated-declarations")
SEQUANT_PRAGMA_GCC(diagnostic push)
SEQUANT_PRAGMA_GCC(diagnostic ignored "-Wdeprecated-declarations")
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.from_bytes(deparsed);
SEQUANT_PRAGMA_CLANG(diagnostic pop)
SEQUANT_PRAGMA_GCC(diagnostic pop)
}
} // namespace details
std::wstring deparse(const ExprPtr& expr, bool annot_sym) {
using namespace details;
if (!expr) return {};
if (expr->is<Tensor>())
return deparse(expr->as<Tensor>(), annot_sym);
else if (expr->is<Sum>())
return deparse(expr->as<Sum>(), annot_sym);
else if (expr->is<Product>())
return deparse(expr->as<Product>(), annot_sym);
else if (expr->is<Constant>())
return deparse(expr->as<Constant>());
else if (expr->is<Variable>())
return deparse(expr->as<Variable>());
else
throw std::runtime_error("Unsupported expr type for deparse!");
}
std::wstring deparse(const Index& index) {
std::wstring deparsed(index.label());
if (index.has_proto_indices()) {
deparsed += L"<";
const auto& protos = index.proto_indices();
for (std::size_t i = 0; i < protos.size(); ++i) {
deparsed += protos[i].label();
if (i + 1 < protos.size()) {
deparsed += L",";
}
}
deparsed += L">";
}
return deparsed;
}
std::wstring deparse(Tensor const& tensor, bool annot_sym) {
std::wstring deparsed(tensor.label());
deparsed += L"{" + details::deparse_indices(tensor.bra());
if (tensor.ket_rank() > 0) {
deparsed += L";" + details::deparse_indices(tensor.ket());
}
deparsed += L"}";
if (annot_sym) {
deparsed += L":" + details::deparse_sym(tensor.symmetry());
}
return deparsed;
}
std::wstring deparse(const Constant& constant) {
return details::deparse_scalar(constant.value());
}
std::wstring deparse(const Variable& variable) {
return std::wstring(variable.label());
}
std::wstring deparse(Product const& prod, bool annot_sym) {
std::wstring deparsed;
const auto& scal = prod.scalar();
if (scal != Product::scalar_type{1}) {
deparsed += details::deparse_scalar(scal) + L" ";
}
for (std::size_t i = 0; i < prod.size(); ++i) {
const ExprPtr& current = prod[i];
bool parenthesize = false;
if (current->is<Product>() || current->is<Sum>()) {
parenthesize = true;
deparsed += L"(";
}
deparsed += deparse(current, annot_sym);
if (parenthesize) {
deparsed += L")";
}
if (i + 1 < prod.size()) {
deparsed += L" * ";
}
}
return deparsed;
}
std::wstring deparse(Sum const& sum, bool annot_sym) {
std::wstring deparsed;
for (std::size_t i = 0; i < sum.size(); ++i) {
ExprPtr& current = sum[i];
const bool parenthesize = current->is<Sum>();
std::wstring current_deparsed = deparse(current, annot_sym);
bool is_negative = false;
if (parenthesize) {
current_deparsed += L"(" + current_deparsed + L")";
} else {
is_negative = current_deparsed.front() == L'-';
}
if (i > 0) {
if (is_negative) {
deparsed += L" - " + current_deparsed.substr(1);
} else {
deparsed += L" + " + current_deparsed;
}
} else {
deparsed = std::move(current_deparsed);
}
}
return deparsed;
}
} // namespace sequant