ARTS 2.5.11 (git: 725533f0)
quantum_numbers.h
Go to the documentation of this file.
1#ifndef quantun_numbers_h
2#define quantun_numbers_h
3
4#include <algorithm>
5#include <compare>
6#include <cstddef>
7#include <istream>
8#include <limits>
9#include <ostream>
10#include <sstream>
11#include <string>
12#include <string_view>
13#include <utility>
14#include <variant>
15#include <vector>
16
17#include "debug.h"
18#include "enums.h"
19#include "isotopologues.h"
20#include "matpack_concepts.h"
21#include "nonstd.h"
22#include "rational.h"
23
24constexpr Index quantum_number_error_value = -999'999'999;
25
26namespace Quantum::Number {
27
30 static constexpr std::size_t N = 16;
31 std::array<char, N> x{'\0'}; // First is \0 to be "empty"
32
34 [[nodiscard]] constexpr std::string_view val() const noexcept {
35 // Look for the first \0 or return everything
36 for (std::size_t i = 0; i < N; i++)
37 if (x[i] == '\0') return {x.data(), i};
38 return {x.data(), N};
39 }
40
42 constexpr StringValue() = default;
43
45 explicit constexpr StringValue(std::string_view s) {
46 const std::size_t n = s.size();
47
52 "The value \"",
53 s,
54 "\" is too long. Can be only ",
55 N,
56 " chars but is ",
57 n)
58
59 // Fill with correct values or zero characters
60 std::size_t i = 0;
61 for (; i < n; i++) x[i] = s[i];
62 if (i < N) x[i] = '\0';
63 }
64
65 constexpr std::strong_ordering operator<=>(const StringValue& sv) const {
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;
69 }
70 return std::strong_ordering::equal;
71 }
72};
73
76 Index x{std::numeric_limits<Index>::lowest()};
77
79 [[nodiscard]] constexpr Rational val() const noexcept { return x; }
80
81 constexpr std::strong_ordering operator<=>(const IntegerValue& i) const {return x<=> i.x;}
82};
83
86 Index x{std::numeric_limits<Index>::lowest()};
87
89 [[nodiscard]] constexpr Rational val() const noexcept {
90 return Rational(x, 2);
91 }
92
93 constexpr std::strong_ordering operator<=>(const HalfIntegerValue& h) const {return x<=> h.x;}
94};
95
97ENUMCLASS(ValueType, char, S, I, H)
98
99
101 char,
102 alpha, // FIXME: Not in VAMDC
103 config, // FIXME: Not in VAMDC
104 ElecStateLabel,
105 F,
106 F1,
107 F10,
108 F11,
109 F12,
110 F2,
111 F3,
112 F4,
113 F5,
114 F6,
115 F7,
116 F8,
117 F9,
118 I,
119 J,
120 K,
121 Ka,
122 Kc,
123 L, // FIXME: Not in VAMDC
124 Lambda,
125 N,
126 Omega,
127 S,
128 Sigma,
129 SpinComponentLabel,
130 asSym,
131 elecInv,
132 elecRefl,
133 elecSym,
134 kronigParity,
135 l,
136 l1,
137 l10,
138 l11,
139 l12,
140 l2,
141 l3,
142 l4,
143 l5,
144 l6,
145 l7,
146 l8,
147 l9,
148 n, // FIXME: Not in VAMDC
149 parity,
150 r,
151 rotSym,
152 rovibSym,
153 sym,
154 tau, // FIXME: Not in VAMDC
155 term, // FIXME: Not in VAMDC
156 v,
157 v1,
158 v10,
159 v11,
160 v12,
161 v2,
162 v3,
163 v4,
164 v5,
165 v6,
166 v7,
167 v8,
168 v9,
169 vibInv,
170 vibRefl,
171 vibSym)
172
183constexpr ValueType common_value_type(Type type) noexcept {
184 switch (type) {
185 case Type::alpha:
186 return ValueType::S;
187 case Type::config:
188 return ValueType::S;
189 case Type::ElecStateLabel:
190 return ValueType::S;
191 case Type::F:
192 return ValueType::H;
193 case Type::F1:
194 return ValueType::H;
195 case Type::F10:
196 return ValueType::H;
197 case Type::F11:
198 return ValueType::H;
199 case Type::F12:
200 return ValueType::H;
201 case Type::F2:
202 return ValueType::H;
203 case Type::F3:
204 return ValueType::H;
205 case Type::F4:
206 return ValueType::H;
207 case Type::F5:
208 return ValueType::H;
209 case Type::F6:
210 return ValueType::H;
211 case Type::F7:
212 return ValueType::H;
213 case Type::F8:
214 return ValueType::H;
215 case Type::F9:
216 return ValueType::H;
217 case Type::I:
218 return ValueType::I;
219 case Type::J:
220 return ValueType::H;
221 case Type::K:
222 return ValueType::I;
223 case Type::Ka:
224 return ValueType::I;
225 case Type::Kc:
226 return ValueType::I;
227 case Type::L:
228 return ValueType::I;
229 case Type::Lambda:
230 return ValueType::I;
231 case Type::N:
232 return ValueType::I;
233 case Type::Omega:
234 return ValueType::H;
235 case Type::S:
236 return ValueType::H;
237 case Type::Sigma:
238 return ValueType::H;
239 case Type::SpinComponentLabel:
240 return ValueType::I;
241 case Type::asSym:
242 return ValueType::S;
243 case Type::elecInv:
244 return ValueType::S;
245 case Type::elecRefl:
246 return ValueType::S;
247 case Type::elecSym:
248 return ValueType::S;
249 case Type::kronigParity:
250 return ValueType::S;
251 case Type::l:
252 return ValueType::I;
253 case Type::l1:
254 return ValueType::I;
255 case Type::l10:
256 return ValueType::I;
257 case Type::l11:
258 return ValueType::I;
259 case Type::l12:
260 return ValueType::I;
261 case Type::l2:
262 return ValueType::I;
263 case Type::l3:
264 return ValueType::I;
265 case Type::l4:
266 return ValueType::I;
267 case Type::l5:
268 return ValueType::I;
269 case Type::l6:
270 return ValueType::I;
271 case Type::l7:
272 return ValueType::I;
273 case Type::l8:
274 return ValueType::I;
275 case Type::l9:
276 return ValueType::I;
277 case Type::n:
278 return ValueType::S;
279 case Type::parity:
280 return ValueType::S;
281 case Type::r:
282 return ValueType::I;
283 case Type::rotSym:
284 return ValueType::S;
285 case Type::rovibSym:
286 return ValueType::S;
287 case Type::sym:
288 return ValueType::S;
289 case Type::tau:
290 return ValueType::S;
291 case Type::term:
292 return ValueType::S;
293 case Type::v:
294 return ValueType::I;
295 case Type::v1:
296 return ValueType::I;
297 case Type::v10:
298 return ValueType::I;
299 case Type::v11:
300 return ValueType::I;
301 case Type::v12:
302 return ValueType::I;
303 case Type::v2:
304 return ValueType::I;
305 case Type::v3:
306 return ValueType::I;
307 case Type::v4:
308 return ValueType::I;
309 case Type::v5:
310 return ValueType::I;
311 case Type::v6:
312 return ValueType::I;
313 case Type::v7:
314 return ValueType::I;
315 case Type::v8:
316 return ValueType::I;
317 case Type::v9:
318 return ValueType::I;
319 case Type::vibInv:
320 return ValueType::S;
321 case Type::vibRefl:
322 return ValueType::S;
323 case Type::vibSym:
324 return ValueType::S;
325 case Type::FINAL: {
326 }
327 }
328 return ValueType::FINAL;
329}
330
341constexpr ValueType common_value_type(ValueType a, ValueType b) noexcept {
342 // Same is same, H is I, a has both:
343 if (a == b or (a == ValueType::H and b == ValueType::I)) return a;
344
345 // H is I:
346 if (b == ValueType::H and a == ValueType::I) return ValueType::H;
347
348 // Something has gone very wrong:
349 return ValueType::FINAL;
350}
351
357
358 constexpr ValueHolder(ValueType t) noexcept : s(StringValue{"NODEF"}) {
359 switch (t) {
360 case ValueType::H:
361 h = HalfIntegerValue{0};
362 break;
363 case ValueType::I:
364 i = IntegerValue{0};
365 break;
366 default: {
367 }
368 }
369 }
370
371 constexpr ValueHolder(Type t) noexcept : ValueHolder(common_value_type(t)) {}
372 constexpr ValueHolder(const ValueHolder&) = default;
373 constexpr ValueHolder(ValueHolder&&) noexcept = default;
374 constexpr ValueHolder& operator=(const ValueHolder&) = default;
375 constexpr ValueHolder& operator=(ValueHolder&&) noexcept = default;
376};
377
383 ValueType type;
385
386 constexpr ValueDescription(ValueType t) noexcept : type(t), val(t) {}
387 constexpr ValueDescription(const ValueDescription&) = default;
388 constexpr ValueDescription(ValueDescription&&) noexcept = default;
389 constexpr ValueDescription& operator=(const ValueDescription&) = default;
390 constexpr ValueDescription& operator=(ValueDescription&&) noexcept = default;
391
393 friend std::ostream& operator<<(std::ostream& os, ValueDescription x);
394};
395
396constexpr std::strong_ordering cmp(std::strong_ordering&& a, std::strong_ordering&& b) {
397 return a == std::strong_ordering::equal ? b : a;
398}
399
409
412 : upp(u.val), low(l.val) {
413 auto ct = common_value_type(t);
414 if (u.type not_eq ct) {
415 ARTS_USER_ERROR_IF(u.type not_eq ValueType::I,
416 "Cannot convert from ",
417 u.type,
418 " to ",
419 ct)
420 upp.h.x = 2 * u.val.i.x;
421 }
422
423 if (l.type not_eq ct) {
424 ARTS_USER_ERROR_IF(l.type not_eq ValueType::I,
425 "Cannot convert from ",
426 l.type,
427 " to ",
428 ct)
429 low.h.x = 2 * l.val.i.x;
430 }
431 }
432
433 constexpr TwoLevelValueHolder(Type t) noexcept : upp(t), low(t) {}
434 constexpr TwoLevelValueHolder(const TwoLevelValueHolder&) = default;
435 constexpr TwoLevelValueHolder(TwoLevelValueHolder&&) noexcept = default;
436 constexpr TwoLevelValueHolder& operator=(const TwoLevelValueHolder&) = default;
437 constexpr TwoLevelValueHolder& operator=(TwoLevelValueHolder&&) noexcept = default;
438
439 [[nodiscard]] constexpr std::strong_ordering order(const TwoLevelValueHolder& tv, ValueType t) const {
440 switch (t) {
441 case ValueType::S:
442 return cmp(upp.s <=> tv.upp.s, low.s <=> tv.low.s);
443 case ValueType::I:
444 return cmp(upp.i <=> tv.upp.i, low.i <=> tv.low.i);
445 case ValueType::H:
446 return cmp(upp.h <=> tv.upp.h, low.h <=> tv.low.h);
447 case ValueType::FINAL: break;
448 }
449 return std::strong_ordering::equal;
450 }
451};
452
460[[nodiscard]] constexpr ValueDescription value_holder(Rational r_) {
461 const Rational r = reduce_by_gcd(r_);
462
463 // We must now have a half-integer or not
464 if (r.denom == 2) {
465 ValueDescription x{ValueType::H};
466 x.val.h.x = r.numer;
467 return x;
468 }
469
470 if (r.denom == 1) {
471 ValueDescription x{ValueType::I};
472 x.val.i.x = r.numer;
473 return x;
474 }
475
476 ValueDescription x{ValueType::I};
478 return x;
479}
480
494[[nodiscard]] constexpr Rational cast_qnrat(std::string_view s) noexcept {
495 // Counts for divides, decimals, and existence
496 int div = 0, dot = 0, any = 0, minus = false;
497 std::size_t const n = s.size();
498
499 // Counts relevant items
500 for (std::size_t i = 0; i < n; i++) {
501 auto x = s[i];
502 if (x == '-') {
503 minus = true;
504 if (i) return RATIONAL_UNDEFINED;
505 } else if (x == '+') {
506 if (i) return RATIONAL_UNDEFINED;
507 } else if (x == '/')
508 div++; // Count divs because we can have at most one
509 else if (x == '.')
510 dot++; // Count dots for the same reason
511 else if (not nonstd::isdigit(x))
512 return RATIONAL_UNDEFINED; // Error!
513
514 // There is a value!
515 any++;
516 }
517
518 // Can only have one of div or dot and need some data
519 if ((div + dot) > 1 or any == 0) return RATIONAL_UNDEFINED;
520
521 // We have a rational! Lets see which we have got
522
523 // We have a simple rational
524 if (div) {
525 Index num = 0, den = 0;
526 std::size_t i = 0;
527
528 // Numerator
529 for (; s[i] not_eq '/'; ++i) {
530 if (s[i] == '-' or s[i] == '+') continue;
531 num *= 10;
532 num += s[i] - '0';
533 }
534
535 // Denominator
536 i++;
537 for (; i < s.size(); ++i) {
538 den *= 10;
539 den += s[i] - '0';
540 }
541
542 // Guard for QN style rationals
543 return Rational(minus ? -num : num, den);
544 }
545
546 // We have a decimal number
547 if (dot) {
548 Index f = 0, d = 0;
549 std::size_t i = 0;
550
551 // The integer part
552 for (; s[i] not_eq '.'; ++i) {
553 if (s[i] == '-' or s[i] == '+') continue;
554 f *= 10;
555 f += s[i] - '0';
556 }
557
558 // The decimal part
559 i++;
560 for (; i < s.size(); ++i) {
561 d *= 10;
562 d += s[i] - '0';
563 }
564
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;
568 }
569
570 std::size_t num = 0;
571 for (auto x : s) {
572 if (x == '-' or x == '+') continue;
573 num *= 10;
574 num += x - '0';
575 }
576 return minus ? -num : num;
577}
578
587[[nodiscard]] constexpr ValueDescription value_holder(std::string_view s,
588 Type t) {
589 switch (common_value_type(t)) {
590 case ValueType::I:
591 case ValueType::H: {
592 const Rational r = cast_qnrat(s);
593 return value_holder(r);
594 }
595 case ValueType::S: {
596 ValueDescription x{ValueType::S};
597 x.val.s = StringValue(s);
598 return x;
599 }
600 case ValueType::FINAL: {
601 }
602 }
603
604 return ValueType::FINAL;
605}
606
609 bool upp{true};
610 bool low{true};
611
613 constexpr operator bool() const noexcept { return upp and low; }
614};
615
623constexpr Index count_items(std::string_view s) noexcept {
624 // Checks if we are in-between items, we start true as we are inbetween items
625 bool last_space = true;
626
627 Index count = 0;
628 for (auto& x : s) {
629 bool const this_space = nonstd::isspace(x);
630
631 // If we had a space and now no longer do, we are in an item
632 if (last_space and not this_space) count++;
633
634 // The current state must be remembere
635 last_space = this_space;
636 }
637 return count;
638}
639
645constexpr std::string_view rstrip(std::string_view x) {
646 while (not x.empty() and nonstd::isspace(x.back())) x.remove_suffix(1);
647 return x;
648}
649
655constexpr std::string_view lstrip(std::string_view x) {
656 while (not x.empty() and nonstd::isspace(x.front())) x.remove_prefix(1);
657 return x;
658}
659
665constexpr std::string_view strip(std::string_view x) {
666 return rstrip(lstrip(x));
667}
668
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;
685
686 std::size_t beg = 0, count = 0, end = s.size();
687 if (end == 0) return s;
688
689 for (std::size_t ind = 0; ind < end; ind++) {
690 bool const this_space = nonstd::isspace(s[ind]);
691
692 // Return when we find the end of the final item
693 if (this_space and count == i + n) return {&s[beg], ind - beg};
694
695 // If we had a space and now no longer do, we are in an item
696 if (last_space and not this_space) {
697 count++;
698
699 // If that is our first item, we are good!
700 if (count - 1 == i) beg = ind;
701 }
702
703 // Count up the beginning until we have found the first item
704 if (count - 1 < i) beg = ind;
705
706 // The current state must be remembere
707 last_space = this_space;
708 }
709
710 // Remove spaces at the end to be sure
711 while (nonstd::isspace(s[end - 1]) and end > beg) end--;
712 return {&s[beg], end - beg};
713}
714
716struct Value {
717 Type type;
719
720 constexpr std::strong_ordering operator<=>(const Value& v) const {
721 if (type < v.type) return std::strong_ordering::less;
722 if (v.type < type) return std::strong_ordering::greater;
723 return qn.order(v.qn, common_value_type(type));
724 }
725
726 constexpr Value(Type t=Type::FINAL) : type(t), qn(type) {}
727 Value(const Value&) = default;
728 Value(Value&&) noexcept = default;
729 Value& operator=(const Value&) = default;
730 Value& operator=(Value&&) noexcept = default;
731
732 constexpr Value(Type t, Rational upp_, Rational low_) : Value(t) {
733 Rational upp = reduce_by_gcd(upp_), low = reduce_by_gcd(low_);
734
735 if (common_value_type(type) == ValueType::H) {
736 ARTS_ASSERT(upp.denom <= 2 and low.denom <= 2)
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;
741 } else if (common_value_type(type) == ValueType::I) {
742 ARTS_ASSERT(upp.denom == 1 and low.denom == 1)
743 qn.upp.i.x = upp.numer;
744 qn.low.i.x = low.numer;
745 } else {
747 t, " is a string-type, so cannot be constructed from rationals")
748 }
749 }
750
752 constexpr Value(std::string_view s) : Value(toTypeOrThrow(items(s, 0))) {
754 "Must have ' TYPE UPPNUM LOWNUM ' but got: '",
755 s,
756 '\'')
757
758 // Get values and ensure they are good types
759 auto upv = value_holder(items(s, 1), type);
760 auto lov = value_holder(items(s, 2), type);
761
762 // Deal with errors while setting the level values
763 qn = TwoLevelValueHolder(upv, lov, type);
764 }
765
767 [[nodiscard]] constexpr Rational upp() const noexcept {
768 switch (common_value_type(type)) {
769 case ValueType::I:
770 return qn.upp.i.val();
771 case ValueType::H:
772 return qn.upp.h.val();
773 default: {
774 }
775 }
776 return RATIONAL_UNDEFINED;
777 }
778
780 [[nodiscard]] constexpr Rational low() const noexcept {
781 switch (common_value_type(type)) {
782 case ValueType::I:
783 return qn.low.i.val();
784 case ValueType::H:
785 return qn.low.h.val();
786 default: {
787 }
788 }
789 return RATIONAL_UNDEFINED;
790 }
791
793 [[nodiscard]] String str_upp() const noexcept;
794
796 [[nodiscard]] String str_low() const noexcept;
797
799 void swap_values(Value& x);
800
802 constexpr void set(std::string_view s, bool upp) {
803 ValueDescription const v = value_holder(s, type);
804 TwoLevelValueHolder const nqn(v, v, type);
805 if (upp) {
806 qn.upp = nqn.upp;
807 } else {
808 qn.low = nqn.low;
809 }
810 }
811
820 [[nodiscard]] constexpr LevelMatch level_match(Value other) const noexcept {
821 if (type == other.type) {
822 switch (common_value_type(type)) {
823 case ValueType::I:
824 case ValueType::H:
825 return {upp() == other.upp(), low() == other.low()};
826 case ValueType::S:
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: {
830 }
831 }
832 }
833 return {false, false};
834 }
835
837 friend std::ostream& operator<<(std::ostream& os, Value x);
838
840 friend std::istream& operator>>(std::istream& is, Value& x);
841
842 bofstream& write(bofstream& bof) const;
843
844 bifstream& read(bifstream& bif);
845
846 [[nodiscard]] constexpr bool good() const {return level_match(*this);}
847};
848
850ENUMCLASS(CheckValue, char, Full, AinB, BinA, Miss)
851
852
854 CheckValue upp{CheckValue::Full};
855 CheckValue low{CheckValue::Full};
856
858 constexpr operator bool() const noexcept {
859 return upp == CheckValue::Full and low == CheckValue::Full;
860 }
861};
862
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;
871}
872
874constexpr CheckMatch update(CheckMatch val, CheckValue res) noexcept {
875 return {update(val.upp, res), update(val.low, res)};
876}
877
879constexpr CheckMatch update(CheckMatch val, CheckMatch res) noexcept {
880 return {update(val.upp, res.upp), update(val.low, res.low)};
881}
882
890template <size_t N>
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;
894 return true;
895}
896
900
902 void sort_by_type();
903
905 [[nodiscard]] bool has_unique_increasing_types() const;
906
907 public:
909 explicit ValueList(std::string_view s, bool legacy = false);
910
912 ValueList(std::string_view upp, std::string_view low);
913
914 std::strong_ordering operator<=>(const ValueList& v) const {
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;
919 }
920 return values.size() <=> v.values.size();
921 }
922
924 explicit ValueList(Array<Value> values_) : values(std::move(values_)) {
925 finalize();
926 }
927
929 ValueList() : values(0) {}
930
932 Array<Value>::iterator begin() { return values.begin(); }
933 Array<Value>::iterator end() { return values.end(); }
934 Array<Value>::iterator cbegin() { return values.begin(); }
935 Array<Value>::iterator cend() { return values.end(); }
936 [[nodiscard]] Array<Value>::const_iterator begin() const {
937 return values.begin();
938 }
939 [[nodiscard]] Array<Value>::const_iterator end() const {
940 return values.end();
941 }
942 [[nodiscard]] Array<Value>::const_iterator cbegin() const {
943 return values.cbegin();
944 }
945 [[nodiscard]] Array<Value>::const_iterator cend() const {
946 return values.cend();
947 }
948
950 void finalize();
951
953 [[nodiscard]] Index nelem() const ARTS_NOEXCEPT { return values.nelem(); }
954
956 [[nodiscard]] bool perpendicular(const ValueList& that) const ARTS_NOEXCEPT;
957
959 template <typename... Types>
960 [[nodiscard]] bool has(Types... ts) const ARTS_NOEXCEPT {
961 static_assert(sizeof...(Types) > 0);
962
963 ARTS_ASSERT(is_sorted(std::array{Type(ts)...}))
964
965 auto ptr = cbegin();
966 auto end = cend();
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;
970 }
971 return true;
972 }
973
975 const Value& operator[](Type t) const ARTS_NOEXCEPT;
976
978 Value& operator[](Index i) { return values.at(i); }
979
981 Value& add(Type t);
982
984 Value& add(Value v);
985
987 void set(Value v);
988
990 void set(Index i, std::string_view upp, std::string_view low);
991
993 [[nodiscard]] CheckMatch check_match(const ValueList& other) const ARTS_NOEXCEPT;
994
996 friend std::ostream& operator<<(std::ostream& os, const ValueList& vl);
997
999 friend std::istream& operator>>(std::istream& is, ValueList& vl);
1000
1002 void add_type_wo_sort(Type);
1003
1004 [[nodiscard]] bool good() const;
1005};
1006
1007ValueList from_hitran(std::string_view upp, std::string_view low);
1008
1012
1013 std::strong_ordering operator<=>(const LocalState& l) const {
1014 return val <=> l.val;
1015 }
1016 auto operator==(const LocalState& l) const {return std::strong_ordering::equal == (*this <=> l);}
1017 auto operator!=(const LocalState& l) const {return std::strong_ordering::equal != (*this <=> l);}
1018
1019 LocalState() = default;
1020
1021 template <typename... Values>
1022 LocalState(Values... vals) : val(Array<Value>{Value(vals)...}) {}
1023
1024 void set_unsorted_qns(const Array<Type>& vals);
1025
1026 [[nodiscard]] String keys() const;
1027
1028 [[nodiscard]] String values() const;
1029
1030 [[nodiscard]] bool same_types_as(const LocalState& that) const;
1031
1033 friend std::ostream& operator<<(std::ostream& os, const LocalState& vl);
1034
1036 friend std::istream& operator>>(std::istream& is, LocalState& vl);
1037
1039 [[nodiscard]] bool good() const;
1040};
1041
1042struct LevelTest {bool upp{true}, low{true};};
1043
1046 static constexpr Index version = 1; // Second version of quantum identifiers
1047
1048 Index isotopologue_index{-1};
1050
1051 GlobalState() = default;
1052
1053 explicit GlobalState(Index i, ValueList v = {})
1054 : isotopologue_index(i), val(std::move(v)) {}
1055
1057 : isotopologue_index(Species::find_species_index(ir)) {}
1058
1059 explicit GlobalState(std::string_view s, Index v = version);
1060
1061 [[nodiscard]] Species::IsotopeRecord Isotopologue() const noexcept;
1062 [[nodiscard]] Species::Species Species() const noexcept;
1063
1064 friend std::ostream& operator<<(std::ostream& os, const GlobalState& gs);
1065
1066 friend std::istream& operator>>(std::istream& is, GlobalState& gs);
1067
1068 [[nodiscard]] GlobalState LowerLevel() const;
1069 [[nodiscard]] GlobalState UpperLevel() const;
1070
1071 std::strong_ordering operator<=>(const GlobalState& g) const {
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;
1075 }
1076 auto operator==(const GlobalState& g) const {return std::strong_ordering::equal == (*this <=> g);}
1077 auto operator!=(const GlobalState& g) const {return std::strong_ordering::equal != (*this <=> g);}
1078
1080 [[nodiscard]] bool part_of(const GlobalState& other) const;
1081
1083 [[nodiscard]] LevelTest part_of(const GlobalState& g, const LocalState& l) const;
1084
1086 [[nodiscard]] bool good() const;
1087};
1088
1090ENUMCLASS(StateMatchType, char, Full, Level, Isotopologue, Species, None)
1091
1092
1094 StateMatchType type{StateMatchType::None};
1095 bool upp{false}, low{false};
1096
1097 constexpr StateMatch() = default;
1098
1099 StateMatch(const GlobalState& target,
1100 const LocalState& local,
1101 const GlobalState& global);
1102
1103 StateMatch(const GlobalState& target, const GlobalState& key);
1104
1106 constexpr bool operator==(StateMatchType x) const noexcept {
1107 return x == type;
1108 }
1109
1110 constexpr bool operator!=(StateMatchType x) const noexcept { return not((*this) == x); }
1111};
1112
1115 VAMDC,
1116 char,
1117 asymcs, // Schema for specifying the quantum numbers of closed-shell asymmetric top molecules
1118 asymos, // Schema for specifying the quantum numbers of open-shell asymmetric top molecules
1119 dcs, // Schema for specifying the quantum numbers of closed-shell, diatomic molecules
1120 hunda, // Schema for specifying the quantum numbers for Hund's case (a) diatomic molecules
1121 hundb, // Schema for specifying the quantum numbers for Hund's case (b) diatomic molecules
1122 lpcs, // Schema for specifying the quantum numbers of closed-shell linear polyatomic molecules
1123 lpos, // Schema for specifying the quantum numbers of open-shell linear polyatomic molecules
1124 ltcs, // Schema for specifying the quantum numbers of closed-shell linear triatomic molecules
1125 ltos, // Schema for specifying the quantum numbers of open-shell linear triatomic molecules
1126 nltcs, // Schema for specifying the quantum numbers of closed-shell non-linear triatomic molecules
1127 nltos, // Schema for specifying the quantum numbers of open-shell non-linear triatomic molecules
1128 sphcs, // Schema for specifying the quantum numbers of closed-shell spherical top molecules
1129 sphos, // Schema for specifying the quantum numbers of closed-shell spherical top molecules
1130 stcs // Schema for specifying the quantum numbers of closed-shell, symmetric top molecules
1131)
1132
1133
1141bool vamdcCheck(const ValueList& l, VAMDC type) ARTS_NOEXCEPT;
1142
1144[[maybe_unused]] constexpr std::array global_types{Type::alpha,
1145 Type::config,
1146 Type::ElecStateLabel,
1147 Type::L,
1148 Type::Lambda,
1149 Type::Omega,
1150 Type::S,
1151 Type::Sigma,
1152 Type::SpinComponentLabel,
1153 Type::asSym,
1154 Type::elecInv,
1155 Type::elecRefl,
1156 Type::elecSym,
1157 Type::kronigParity,
1158 Type::l,
1159 Type::l1,
1160 Type::l10,
1161 Type::l11,
1162 Type::l12,
1163 Type::l2,
1164 Type::l3,
1165 Type::l4,
1166 Type::l5,
1167 Type::l6,
1168 Type::l7,
1169 Type::l8,
1170 Type::l9,
1171 Type::n,
1172 Type::parity,
1173 Type::r,
1174 Type::rotSym,
1175 Type::rovibSym,
1176 Type::sym,
1177 Type::tau,
1178 Type::term,
1179 Type::v,
1180 Type::v1,
1181 Type::v10,
1182 Type::v11,
1183 Type::v12,
1184 Type::v2,
1185 Type::v3,
1186 Type::v4,
1187 Type::v5,
1188 Type::v6,
1189 Type::v7,
1190 Type::v8,
1191 Type::v9,
1192 Type::vibInv,
1193 Type::vibRefl,
1194 Type::vibSym};
1195
1197[[maybe_unused]] constexpr std::array local_types{Type::F,
1198 Type::F1,
1199 Type::F10,
1200 Type::F11,
1201 Type::F12,
1202 Type::F2,
1203 Type::F3,
1204 Type::F4,
1205 Type::F5,
1206 Type::F6,
1207 Type::F7,
1208 Type::F8,
1209 Type::F9,
1210 Type::I,
1211 Type::J,
1212 Type::K,
1213 Type::Ka,
1214 Type::Kc,
1215 Type::N};
1216} // namespace Quantum::Number
1217
1218using QuantumNumberType = Quantum::Number::Type;
1224
1225#endif // quantun_numbers_h
std::ostream & operator<<(std::ostream &os, AbsorptionCutoffTagTypeStatus val)
std::istream & operator>>(std::istream &is, Time &t)
Definition artstime.cc:104
This can be used to make arrays out of anything.
Definition array.h:31
Index nelem() const ARTS_NOEXCEPT
Definition array.h:75
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.
Definition bifstream.h:26
Binary output file stream class.
Definition bofstream.h:25
Helper macros for debugging.
#define ARTS_NOEXCEPT
Definition debug.h:83
#define ARTS_ASSERT(condition,...)
Definition debug.h:86
#define ARTS_USER_ERROR(...)
Definition debug.h:153
#define ARTS_USER_ERROR_IF(condition,...)
Definition debug.h:137
#define ENUMCLASS(ENUMTYPE, TYPE,...)
Definition enums.h:142
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.
VAMDC type ARTS_NOEXCEPT
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
Definition nonstd.h:24
constexpr int isspace(int ch) noexcept
Returns 1 if x is a standard space-character.
Definition nonstd.h:39
#define F11
#define F12
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
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.
std::array< char, N > x
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
TwoLevelValueHolder qn
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.
#define u
#define d
#define v
#define a
#define b
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