Line data Source code
1 : /** @file bpu_store.hpp **/
2 :
3 : #pragma once
4 :
5 : #include "bpu.hpp"
6 : #include <vector>
7 :
8 : namespace xo {
9 : namespace qty {
10 : /** @class basis_unit2_store
11 : * @brief Store known basis units for runtime
12 : **/
13 : template <typename Tag>
14 1 : struct basis_unit2_store {
15 1 : basis_unit2_store() : bu_abbrev_vv_(static_cast<std::size_t>(dim::n_dim)) {
16 1 : this->bu_establish_abbrev_for<dim::mass, 1, 1000000000>();
17 1 : this->bu_establish_abbrev_for<dim::mass, 1, 1000000>();
18 1 : this->bu_establish_abbrev_for<dim::mass, 1, 1000>();
19 1 : this->bu_establish_abbrev_for<dim::mass, 1, 1>();
20 1 : this->bu_establish_abbrev_for<dim::mass, 1000, 1>();
21 1 : this->bu_establish_abbrev_for<dim::mass, 1000000, 1>();
22 1 : this->bu_establish_abbrev_for<dim::mass, 1000000000, 1>();
23 :
24 1 : this->bu_establish_abbrev_for<dim::distance, 1, 1000000000>();
25 1 : this->bu_establish_abbrev_for<dim::distance, 1, 1000000>();
26 1 : this->bu_establish_abbrev_for<dim::distance, 1, 1000>();
27 1 : this->bu_establish_abbrev_for<dim::distance, 1, 1>();
28 1 : this->bu_establish_abbrev_for<dim::distance, 1000, 1>();
29 :
30 1 : this->bu_establish_abbrev_for<dim::time, 1, 1000000000>();
31 1 : this->bu_establish_abbrev_for<dim::time, 1, 1000000>();
32 1 : this->bu_establish_abbrev_for<dim::time, 1, 1000>();
33 1 : this->bu_establish_abbrev_for<dim::time, 1, 1>();
34 1 : this->bu_establish_abbrev_for<dim::time, 60, 1>();
35 1 : this->bu_establish_abbrev_for<dim::time, 3600, 1>();
36 1 : this->bu_establish_abbrev_for<dim::time, 24*3600, 1>();
37 1 : this->bu_establish_abbrev_for<dim::time, 250*24*3600, 1>();
38 1 : this->bu_establish_abbrev_for<dim::time, 360*24*3600, 1>();
39 1 : this->bu_establish_abbrev_for<dim::time, 365*24*3600, 1>();
40 :
41 1 : this->bu_establish_abbrev_for<dim::currency, 1, 1>();
42 :
43 1 : this->bu_establish_abbrev_for<dim::price, 1, 1>();
44 1 : }
45 :
46 : /* e.g.
47 : * [(1/1000000000, "nm"), (1/1000000, "um"), (1/1000, "mm"), (1/1, "m"), (1000/1, "km")]
48 : */
49 : using native_scale_v = std::vector<std::pair<scalefactor_ratio_type, basis_unit2_abbrev_type>>;
50 :
51 : /** @brief get basis-unit abbreviation at runtime **/
52 22 : basis_unit2_abbrev_type bu_abbrev(dim basis_dim,
53 : const scalefactor_ratio_type & scalefactor) const
54 : {
55 22 : const auto & bu_abbrev_v = bu_abbrev_vv_[static_cast<std::size_t>(basis_dim)];
56 :
57 22 : std::size_t i_abbrev = bu_abbrev_lub_ix(basis_dim, scalefactor, bu_abbrev_v);
58 :
59 22 : if ((i_abbrev < bu_abbrev_v.size())
60 22 : && (bu_abbrev_v[i_abbrev].first == scalefactor))
61 : {
62 22 : return bu_abbrev_v[i_abbrev].second;
63 : } else {
64 0 : return units::bu_fallback_abbrev(basis_dim, scalefactor);
65 : }
66 : }
67 :
68 : /** @brief get basis-power-unit abbreviation at runtime **/
69 : bpu_abbrev_type bpu_abbrev(dim basis_dim,
70 : const scalefactor_ratio_type & scalefactor,
71 : const power_ratio_type & power)
72 : {
73 : return abbrev::bpu_abbrev(basis_dim,
74 : scalefactor,
75 : power);
76 : }
77 :
78 : template <dim BasisDim, std::int64_t InnerScaleNum, std::int64_t InnerScaleDen>
79 24 : void bu_establish_abbrev_for() {
80 : this->bu_establish_abbrev
81 24 : (basis_unit(BasisDim,
82 24 : scalefactor_ratio_type(InnerScaleNum, InnerScaleDen)),
83 24 : abbrev::basis_unit2_abbrev(BasisDim, scalefactor_ratio_type(InnerScaleNum, InnerScaleDen)));
84 24 : }
85 :
86 : /** @brief establish abbreviation @p abbrev for basis unit @p bu
87 : **/
88 24 : void bu_establish_abbrev(const basis_unit & bu,
89 : const basis_unit2_abbrev_type & abbrev) {
90 :
91 24 : auto & bu_abbrev_v = bu_abbrev_vv_[static_cast<std::size_t>(bu.native_dim())];
92 :
93 24 : std::int32_t i_abbrev = 0;
94 :
95 24 : if (!bu_abbrev_v.empty()) {
96 19 : i_abbrev = bu_abbrev_lub_ix(bu.native_dim(),
97 : bu.scalefactor(),
98 : bu_abbrev_v);
99 : }
100 :
101 24 : auto entry = std::make_pair(bu.scalefactor(), abbrev);
102 :
103 24 : if ((i_abbrev < bu_abbrev_v.size())
104 24 : && (bu_abbrev_v[i_abbrev].first == bu.scalefactor()))
105 : {
106 0 : bu_abbrev_v[i_abbrev] = entry;
107 : } else {
108 24 : bu_abbrev_v.insert(bu_abbrev_v.begin() + i_abbrev, entry);
109 : }
110 24 : }
111 :
112 : private:
113 : /** @brief get least-upper-bound index position in bu_abbrev_v[]
114 : *
115 : * return value in [0, n] where n = bu_abbrev_v.size()
116 : **/
117 41 : static std::size_t bu_abbrev_lub_ix(dim basis_dim,
118 : const scalefactor_ratio_type & scalefactor,
119 : const native_scale_v & bu_abbrev_v)
120 : {
121 41 : std::size_t n = bu_abbrev_v.size();
122 :
123 41 : if (n == 0)
124 : return 0;
125 :
126 41 : std::size_t lo = 0;
127 41 : std::size_t hi = n-1;
128 :
129 41 : if (scalefactor <= bu_abbrev_v[lo].first)
130 : return 0;
131 :
132 38 : auto cmp = (scalefactor <=> bu_abbrev_v[hi].first);
133 :
134 38 : if (cmp > 0)
135 : return n;
136 :
137 19 : if (cmp == 0)
138 : return hi;
139 :
140 60 : while (hi-lo > 1) {
141 : /* inv:
142 : * bu_abbrev_v[lo].first < scalefactor <= bu_abbrev_v[hi].first
143 : */
144 :
145 44 : std::size_t mid = lo + (hi - lo)/2;
146 :
147 44 : if (scalefactor > bu_abbrev_v[mid].first)
148 : lo = mid;
149 : else
150 24 : hi = mid;
151 : }
152 :
153 : return hi;
154 : }
155 :
156 : private:
157 : /* bu_abbrev_v[dim] holds known units for native unit dim */
158 : std::vector<native_scale_v> bu_abbrev_vv_;
159 : };
160 : } /*namespace qty*/
161 : } /*namespace xo*/
162 :
163 : /** end bpu_store.hpp **/
|