LCOV - code coverage report
Current view: top level - include/xo/unit - bpu_store.hpp (source / functions) Hit Total Coverage
Test: out3.info Lines: 61 63 96.8 %
Date: 1980-01-01 00:00:00 Functions: 28 28 100.0 %

          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 **/

Generated by: LCOV version 1.0