Skip to content

Commit 8d0a2e6

Browse files
committed
add decompose method to dimensions
1 parent 88b016c commit 8d0a2e6

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

python/units_python.cpp

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,37 @@ NB_MODULE(units_llnl_ext, mod)
689689
new (dim) Dimension{def};
690690
},
691691
"dimension"_a)
692+
.def(
693+
"__init__",
694+
[](Dimension* dim, const nb::dict &composition) {
695+
units::precise_unit def;
696+
697+
for (const auto& element : composition)
698+
{
699+
nb::handle key_handle = element.first;
700+
nb::handle value_handle = element.second;
701+
702+
// Convert the key handle to a std::string
703+
std::string key = nb::cast<std::string>(key_handle);
704+
705+
// Convert the value handle to an int
706+
int value = nb::cast<int>(value_handle);
707+
if (key == "custom")
708+
{
709+
def=def*units::precise::generate_custom_unit(static_cast<std::uint16_t>(value));
710+
}
711+
else if (key == "custom_count")
712+
{
713+
def=def*units::precise::generate_custom_count_unit(static_cast<std::uint16_t>(value));
714+
}
715+
else
716+
{
717+
def=def*(units::unit_from_string(key).pow(value));
718+
}
719+
}
720+
new (dim) Dimension{def};
721+
},
722+
"composition"_a)
692723
.def_prop_ro(
693724
"default_unit",
694725
[](const Dimension& dim) { return (dim.base); },
@@ -747,6 +778,92 @@ NB_MODULE(units_llnl_ext, mod)
747778
.def(
748779
"__invert__",
749780
[](const Dimension& dim) { return Dimension{dim.base.inv()}; })
781+
.def("decompose",
782+
[](const Dimension& dim) {
783+
nb::dict dictionary;
784+
auto base_units=dim.base;
785+
units::detail::unit_data base=base_units.base_units();
786+
bool custom{false};
787+
if (units::precise::custom::is_custom_unit(base))
788+
{
789+
dictionary["custom"]=units::precise::custom::custom_unit_number(base);
790+
if (units::precise::custom::is_custom_unit_inverted(base))
791+
{
792+
dictionary["inverted"]=1;
793+
}
794+
custom=true;
795+
}
796+
else if(units::precise::custom::is_custom_count_unit(base))
797+
{
798+
dictionary["custom_count"]=units::precise::custom::custom_count_unit_number(base);
799+
if (units::precise::custom::is_custom_count_unit_inverted(base))
800+
{
801+
dictionary["inverted"]=1;
802+
}
803+
custom=true;
804+
}
805+
if (!custom)
806+
{
807+
if (base.meter() != 0)
808+
{
809+
dictionary["meters"] = base.meter();
810+
}
811+
if (base.kg() != 0)
812+
{
813+
dictionary["kilogram"] = base.kg();
814+
}
815+
if (base.second() != 0)
816+
{
817+
dictionary["second"] = base.second();
818+
}
819+
if (base.ampere() != 0)
820+
{
821+
dictionary["ampere"] = base.ampere();
822+
}
823+
if (base.kelvin() != 0)
824+
{
825+
dictionary["kelvin"] = base.kelvin();
826+
}
827+
if (base.mole() != 0)
828+
{
829+
dictionary["mole"] = base.mole();
830+
}
831+
if (base.candela() != 0)
832+
{
833+
dictionary["candela"] = base.candela();
834+
}
835+
if (base.currency() != 0)
836+
{
837+
dictionary["currency"] = base.currency();
838+
}
839+
if (base.count() != 0)
840+
{
841+
dictionary["count"] = base.count();
842+
}
843+
if (base.radian() != 0)
844+
{
845+
dictionary["radian"] = base.radian();
846+
}
847+
if (base.is_per_unit())
848+
{
849+
dictionary["per_unit"] = 1;
850+
}
851+
if (base.has_i_flag())
852+
{
853+
dictionary["iflag"] = 1;
854+
}
855+
if (base.has_e_flag())
856+
{
857+
dictionary["eflag"] = 1;
858+
}
859+
860+
}
861+
if (base.is_equation())
862+
{
863+
dictionary["equation"] = 1;
864+
}
865+
return dictionary;
866+
} )
750867
.def(
751868
"__pow__",
752869
[](const Dimension& dim, int power) {

test/python/test_dimensions.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,18 @@ def test_dimensions_units():
7070
d1 = Dimension("volume")
7171
u1 = Unit("m^3")
7272
assert d1.default_unit == u1
73+
74+
def test_dimensions_decompose1():
75+
d1 = Dimension("volume")
76+
decomposition=d1.decompose()
77+
78+
assert decomposition["meters"]==3
79+
80+
def test_dimensions_decompose2():
81+
u1 = Unit("$ per watt radian")
82+
dim=u1.dimension
83+
decomposition=dim.decompose()
84+
85+
dim2=Dimension(decomposition)
86+
assert dim2==dim
87+
assert dim2.default_unit==u1

0 commit comments

Comments
 (0)