1#ifndef quantun_numbers_h
2#define quantun_numbers_h
20#include "matpack_concepts.h"
30 static constexpr std::size_t
N = 16;
31 std::array<char, N>
x{
'\0'};
34 [[nodiscard]]
constexpr std::string_view
val() const noexcept {
36 for (std::size_t i = 0; i <
N; i++)
37 if (
x[i] ==
'\0')
return {
x.data(), i};
46 const std::size_t n = s.size();
54 "\" is too long. Can be only ",
61 for (; i < n; i++)
x[i] = s[i];
62 if (i <
N)
x[i] =
'\0';
66 for (std::size_t i=0; i<
N; i++) {
67 if (
x[i] < sv.
x[i])
return std::strong_ordering::less;
68 if (sv.
x[i] <
x[i])
return std::strong_ordering::greater;
70 return std::strong_ordering::equal;
76 Index
x{std::numeric_limits<Index>::lowest()};
79 [[nodiscard]]
constexpr Rational
val() const noexcept {
return x; }
86 Index
x{std::numeric_limits<Index>::lowest()};
89 [[nodiscard]]
constexpr Rational
val() const noexcept {
90 return Rational(
x, 2);
189 case Type::ElecStateLabel:
239 case Type::SpinComponentLabel:
249 case Type::kronigParity:
328 return ValueType::FINAL;
343 if (
a ==
b or (
a == ValueType::H and
b == ValueType::I))
return a;
346 if (
b == ValueType::H and
a == ValueType::I)
return ValueType::H;
349 return ValueType::FINAL;
396constexpr
std::strong_ordering
cmp(
std::strong_ordering&&
a,
std::strong_ordering&&
b) {
397 return a == std::strong_ordering::equal ?
b :
a;
412 : upp(
u.val), low(l.val) {
414 if (
u.type not_eq ct) {
416 "Cannot convert from ",
420 upp.
h.
x = 2 *
u.val.i.x;
423 if (l.
type not_eq ct) {
425 "Cannot convert from ",
442 return cmp(upp.
s <=> tv.upp.s, low.
s <=> tv.low.s);
444 return cmp(upp.
i <=> tv.upp.i, low.
i <=> tv.low.i);
446 return cmp(upp.
h <=> tv.upp.h, low.
h <=> tv.low.h);
447 case ValueType::FINAL:
break;
449 return std::strong_ordering::equal;
461 const Rational r = reduce_by_gcd(r_);
494[[nodiscard]]
constexpr Rational
cast_qnrat(std::string_view
s)
noexcept {
496 int div = 0, dot = 0, any = 0, minus =
false;
497 std::size_t
const n =
s.size();
500 for (std::size_t
i = 0;
i < n;
i++) {
504 if (
i)
return RATIONAL_UNDEFINED;
505 }
else if (x ==
'+') {
506 if (
i)
return RATIONAL_UNDEFINED;
512 return RATIONAL_UNDEFINED;
519 if ((div + dot) > 1 or any == 0)
return RATIONAL_UNDEFINED;
525 Index num = 0, den = 0;
529 for (;
s[
i] not_eq
'/'; ++
i) {
530 if (
s[
i] ==
'-' or
s[
i] ==
'+')
continue;
537 for (;
i <
s.size(); ++
i) {
543 return Rational(minus ? -num : num, den);
552 for (;
s[
i] not_eq
'.'; ++
i) {
553 if (
s[
i] ==
'-' or
s[
i] ==
'+')
continue;
560 for (;
i <
s.size(); ++
i) {
565 if (
d == 0)
return minus ? -f : f;
566 if (
d == 5)
return Rational((minus ? -1 : 1) * (2 * f + 1), 2);
567 return RATIONAL_UNDEFINED;
572 if (x ==
'-' or x ==
'+')
continue;
576 return minus ? -num : num;
600 case ValueType::FINAL: {
604 return ValueType::FINAL;
613 constexpr operator bool() const noexcept {
return upp and low; }
625 bool last_space =
true;
632 if (last_space and not this_space) count++;
635 last_space = this_space;
645constexpr std::string_view
rstrip(std::string_view x) {
646 while (not x.empty() and
nonstd::isspace(x.back())) x.remove_suffix(1);
655constexpr std::string_view
lstrip(std::string_view x) {
656 while (not x.empty() and
nonstd::isspace(x.front())) x.remove_prefix(1);
665constexpr std::string_view
strip(std::string_view x) {
681template <std::
size_t n = 1>
682constexpr std::string_view
items(std::string_view
s, std::size_t
i)
noexcept {
683 static_assert(n > 0,
"Must want some items");
684 bool last_space =
true;
686 std::size_t beg = 0, count = 0, end =
s.size();
687 if (end == 0)
return s;
689 for (std::size_t ind = 0; ind < end; ind++) {
693 if (this_space and count ==
i + n)
return {&
s[beg], ind - beg};
696 if (last_space and not this_space) {
700 if (count - 1 ==
i) beg = ind;
704 if (count - 1 <
i) beg = ind;
707 last_space = this_space;
712 return {&
s[beg], end - beg};
721 if (type <
v.type)
return std::strong_ordering::less;
722 if (
v.type < type)
return std::strong_ordering::greater;
726 constexpr Value(Type t=Type::FINAL) : type(t), qn(type) {}
732 constexpr
Value(Type t, Rational upp_, Rational low_) :
Value(t) {
733 Rational upp = reduce_by_gcd(upp_), low = reduce_by_gcd(low_);
737 if (upp.denom not_eq 2) upp *= 2;
738 if (low.denom not_eq 2) low *= 2;
739 qn.
upp.
h.
x = upp.numer;
740 qn.
low.
h.
x = low.numer;
743 qn.
upp.
i.
x = upp.numer;
744 qn.
low.
i.
x = low.numer;
747 t,
" is a string-type, so cannot be constructed from rationals")
754 "Must have ' TYPE UPPNUM LOWNUM ' but got: '",
767 [[nodiscard]]
constexpr Rational
upp() const noexcept {
776 return RATIONAL_UNDEFINED;
780 [[nodiscard]]
constexpr Rational
low() const noexcept {
789 return RATIONAL_UNDEFINED;
793 [[nodiscard]]
String str_upp() const noexcept;
796 [[nodiscard]]
String str_low() const noexcept;
799 void swap_values(
Value& x);
802 constexpr
void set(
std::string_view s,
bool upp) {
821 if (type == other.type) {
825 return {upp() == other.
upp(), low() == other.low()};
827 return {qn.
upp.
s.
x == other.qn.upp.s.x,
828 qn.
low.
s.
x == other.qn.low.s.x};
829 case ValueType::FINAL: {
833 return {
false,
false};
846 [[nodiscard]]
constexpr bool good()
const {
return level_match(*
this);}
850ENUMCLASS(CheckValue,
char, Full, AinB, BinA, Miss)
854 CheckValue upp{CheckValue::Full};
855 CheckValue low{CheckValue::Full};
858 constexpr operator bool() const noexcept {
859 return upp == CheckValue::Full and low == CheckValue::Full;
864constexpr CheckValue
update(CheckValue val, CheckValue res)
noexcept {
865 if (val == CheckValue::Miss)
return val;
866 if (val == CheckValue::Full)
return res;
867 if (res == CheckValue::Miss)
return res;
868 if (res == CheckValue::Full)
return val;
869 if (val == res)
return val;
870 return CheckValue::Miss;
880 return {
update(val.upp, res.upp),
update(val.low, res.low)};
891constexpr bool is_sorted(
const std::array<Type, N>& types)
noexcept {
892 for (
size_t i = 1;
i < N;
i++)
893 if (not(types[
i - 1] < types[
i]))
return false;
905 [[nodiscard]]
bool has_unique_increasing_types()
const;
909 explicit ValueList(std::string_view s,
bool legacy =
false);
912 ValueList(std::string_view upp, std::string_view low);
915 const std::size_t n = std::min(values.size(),
v.values.size());
916 for (std::size_t i=0; i<n; i++) {
917 if (values[i] <
v.values[i])
return std::strong_ordering::less;
918 if (
v.values[i] < values[i])
return std::strong_ordering::greater;
920 return values.size() <=>
v.values.size();
937 return values.begin();
943 return values.cbegin();
946 return values.cend();
959 template <
typename...
Types>
961 static_assert(
sizeof...(Types) > 0);
967 for (Type t : {Type(ts)...}) {
968 ptr = std::find_if(ptr, end, [t](
auto& x) {
return x.type == t; });
969 if (ptr == end)
return false;
990 void set(Index i, std::string_view upp, std::string_view low);
1002 void add_type_wo_sort(Type);
1004 [[nodiscard]]
bool good()
const;
1007ValueList
from_hitran(std::string_view upp, std::string_view low);
1014 return val <=> l.
val;
1021 template <
typename... Values>
1026 [[nodiscard]]
String keys()
const;
1028 [[nodiscard]]
String values()
const;
1030 [[nodiscard]]
bool same_types_as(
const LocalState& that)
const;
1033 friend std::ostream&
operator<<(std::ostream& os,
const LocalState& vl);
1036 friend std::istream&
operator>>(std::istream& is, LocalState& vl);
1039 [[nodiscard]]
bool good()
const;
1046 static constexpr Index version = 1;
1048 Index isotopologue_index{-1};
1054 : isotopologue_index(i), val(
std::move(
v)) {}
1057 : isotopologue_index(
Species::find_species_index(ir)) {}
1059 explicit GlobalState(std::string_view s, Index
v = version);
1072 if (isotopologue_index < g.isotopologue_index)
return std::strong_ordering::less;
1073 if (g.isotopologue_index < isotopologue_index)
return std::strong_ordering::greater;
1074 return val <=> g.val;
1080 [[nodiscard]]
bool part_of(
const GlobalState& other)
const;
1086 [[nodiscard]]
bool good()
const;
1094 StateMatchType type{StateMatchType::None};
1095 bool upp{
false}, low{
false};
1110 constexpr bool operator!=(StateMatchType x)
const noexcept {
return not((*
this) == x); }
1146 Type::ElecStateLabel,
1152 Type::SpinComponentLabel,
std::ostream & operator<<(std::ostream &os, AbsorptionCutoffTagTypeStatus val)
std::istream & operator>>(std::istream &is, Time &t)
This can be used to make arrays out of anything.
Index nelem() const ARTS_NOEXCEPT
A list of many quantum numbers. Should always remain sorted.
Array< Value >::iterator cbegin()
ValueList(Array< Value > values_)
From values (resorted)
Array< Value >::iterator cend()
Array< Value >::const_iterator end() const
Array< Value >::const_iterator begin() const
Array< Value >::const_iterator cbegin() const
Array< Value >::iterator begin()
For iterators.
bool has(Types... ts) const ARTS_NOEXCEPT
Returns whether all the Types are part of the list, the types must be sorted.
Value & operator[](Index i)
Legacy manipulation operator access.
Array< Value >::iterator end()
Index nelem() const ARTS_NOEXCEPT
Return number of quantum numbers.
Array< Value >::const_iterator cend() const
std::strong_ordering operator<=>(const ValueList &v) const
Binary output file stream class.
Binary output file stream class.
Helper macros for debugging.
#define ARTS_ASSERT(condition,...)
#define ARTS_USER_ERROR(...)
#define ARTS_USER_ERROR_IF(condition,...)
#define ENUMCLASS(ENUMTYPE, TYPE,...)
constexpr ValueType common_value_type(ValueType a, ValueType b) noexcept
Return a common type between a and b.
ValueList from_hitran(std::string_view upp, std::string_view low)
constexpr Rational cast_qnrat(std::string_view s) noexcept
Returns a rational if possible or RATIONAL_UNDEFINED otherwise.
bool vamdcCheck(const ValueList &l, VAMDC type) ARTS_NOEXCEPT
constexpr std::strong_ordering cmp(std::strong_ordering &&a, std::strong_ordering &&b)
constexpr bool is_sorted(const std::array< Type, N > &types) noexcept
Checks if an array of types is sorted.
constexpr ValueDescription value_holder(Rational r_)
Takes a rational and determine which type of quantum number it is, returning this information or thro...
constexpr std::array global_types
A default state of global quantum numbers.
constexpr std::string_view rstrip(std::string_view x)
Strips spaces at the end of x before returning it.
constexpr std::string_view items(std::string_view s, std::size_t i) noexcept
Get a view of a number of space-separated items from the list.
constexpr CheckValue update(CheckValue val, CheckValue res) noexcept
Updates old by what a new check says it should be.
constexpr std::array local_types
A default state of local quantum numbers.
constexpr std::string_view lstrip(std::string_view x)
Strips spaces at the beginning x before returning it.
constexpr Index count_items(std::string_view s) noexcept
Count all space-separated items in s.
constexpr std::string_view strip(std::string_view x)
Strips spaces at the beginning and end of x before returning it.
constexpr int isdigit(int ch) noexcept
constexpr int isspace(int ch) noexcept
Returns 1 if x is a standard space-character.
Quantum::Number::Type QuantumNumberType
constexpr Index quantum_number_error_value
Status of comparing two lists that are supposedly of some type.
A logical struct for global quantum numbers with species identifiers.
GlobalState(Index i, ValueList v={})
auto operator==(const GlobalState &g) const
GlobalState(const Species::IsotopeRecord &ir)
auto operator!=(const GlobalState &g) const
Holds half integer values, but only its denominator.
constexpr Rational val() const noexcept
Returns the value as a Rational, keeping that this is a half-integer.
constexpr std::strong_ordering operator<=>(const HalfIntegerValue &h) const
constexpr Rational val() const noexcept
Returns the value as a rational.
constexpr std::strong_ordering operator<=>(const IntegerValue &i) const
Struct that converts to bool automatically but allows checking both energy levels matching status.
A logical struct for local quantum numbers.
auto operator!=(const LocalState &l) const
auto operator==(const LocalState &l) const
LocalState(Values... vals)
std::strong_ordering operator<=>(const LocalState &l) const
StateMatchType operates so that a check less than a level should be 'better', bar None.
constexpr bool operator!=(StateMatchType x) const noexcept
constexpr bool operator==(StateMatchType x) const noexcept
It is of the desired type if it is less than the value, bar None.
constexpr StateMatch()=default
Holds string values but can only hold sizeof(Index) long values.
constexpr std::strong_ordering operator<=>(const StringValue &sv) const
static constexpr std::size_t N
constexpr std::string_view val() const noexcept
Returns the value in such a way that no \0 remains in the view.
constexpr StringValue(std::string_view s)
Set to expected value from a view of something at most N-char long.
constexpr StringValue()=default
Default initializer to a zero-first solution.
The values of two levels.
constexpr TwoLevelValueHolder(ValueDescription u, ValueDescription l, Type t)
Constructor to ensure two ValueDescription have the same type, for IO purposes.
constexpr TwoLevelValueHolder(Type t) noexcept
constexpr TwoLevelValueHolder(const TwoLevelValueHolder &)=default
constexpr std::strong_ordering order(const TwoLevelValueHolder &tv, ValueType t) const
constexpr TwoLevelValueHolder(TwoLevelValueHolder &&) noexcept=default
A complete description of a value, its type and value.
constexpr ValueDescription(const ValueDescription &)=default
constexpr ValueDescription(ValueDescription &&) noexcept=default
constexpr ValueDescription(ValueType t) noexcept
A complete quantum number value with type information.
Value(Value &&) noexcept=default
constexpr Value(std::string_view s)
Default constructor from some string of values.
constexpr Value(Type t=Type::FINAL)
constexpr Rational upp() const noexcept
Returns the upper quantum number rational if it exists or an undefined.
Value(const Value &)=default
constexpr bool good() const
constexpr Rational low() const noexcept
Returns the lower quantum number rational if it exists or an undefined.
constexpr LevelMatch level_match(Value other) const noexcept
Returns a description of whether both levels match.
constexpr std::strong_ordering operator<=>(const Value &v) const
Struct containing all information needed about one isotope.
A union of the three type of values we need to consider.
constexpr ValueHolder(Type t) noexcept
constexpr ValueHolder(const ValueHolder &)=default
constexpr ValueHolder(ValueType t) noexcept
constexpr ValueHolder(ValueHolder &&) noexcept=default