23 #ifndef COM_DAFER45_TBTK_UNIT_HANDLER
24 #define COM_DAFER45_TBTK_UNIT_HANDLER
27 #include "TBTK/Quantity/Constant.h"
37 #ifdef M_E //Avoid name clash with math.h macro M_E
200 static void setScales(
const std::vector<std::string> &scales);
203 template<
typename Quantity>
207 template<
typename Quantity>
213 template<
typename Quantity>
214 static typename std::enable_if<
215 Quantity::IsBaseQuantity::value,
217 >::type convertArbitraryToBase(
219 typename Quantity::Unit unit
221 template<
typename Quantity>
222 static typename std::enable_if<
223 !Quantity::IsBaseQuantity::value,
225 >::type convertArbitraryToBase(
227 typename Quantity::Unit unit
234 template<
typename Quantity>
235 static typename std::enable_if<
236 Quantity::IsBaseQuantity::value,
238 >::type convertBaseToArbitrary(
240 typename Quantity::Unit unit
242 template<
typename Quantity>
243 static typename std::enable_if<
244 !Quantity::IsBaseQuantity::value,
246 >::type convertBaseToArbitrary(
248 typename Quantity::Unit unit
255 template<
typename Quantity>
256 static typename std::enable_if<
257 Quantity::IsBaseQuantity::value,
259 >::type convertArbitraryToNatural(
261 typename Quantity::Unit unit
263 template<
typename Quantity>
264 static typename std::enable_if<
265 !Quantity::IsBaseQuantity::value,
267 >::type convertArbitraryToNatural(
269 typename Quantity::Unit unit
276 template<
typename Quantity>
277 static typename std::enable_if<
278 Quantity::IsBaseQuantity::value,
280 >::type convertNaturalToArbitrary(
282 typename Quantity::Unit unit
284 template<
typename Quantity>
285 static typename std::enable_if<
286 !Quantity::IsBaseQuantity::value,
288 >::type convertNaturalToArbitrary(
290 typename Quantity::Unit unit
301 template<
typename Quantity>
302 static typename std::enable_if<
303 Quantity::IsBaseQuantity::value,
305 >::type getUnitString();
306 template<
typename Quantity>
307 static typename std::enable_if<
308 !Quantity::IsBaseQuantity::value,
310 >::type getUnitString();
318 static std::string getUnitString(
const std::string &constantName);
324 > constantsDefaultUnits;
327 static std::map<std::string, double> constantsBaseUnits;
331 Quantity::Angle::Unit,
332 Quantity::Charge::Unit,
333 Quantity::Count::Unit,
334 Quantity::Energy::Unit,
335 Quantity::Length::Unit,
336 Quantity::Temperature::Unit,
352 template<
typename Quantity>
353 static void setUnit(
typename Quantity::Unit unit);
357 template<
typename Quantity>
358 static typename std::enable_if<
359 Quantity::IsBaseQuantity::value,
360 typename Quantity::Unit&
364 template<
typename Quantity>
365 static void setScale(
double scale);
369 template<
typename Quantity>
370 static double& getScale();
373 template<
typename Quantity>
374 static void setScale(
double scale,
typename Quantity::Unit unit);
377 template<
typename Quantity>
378 static void setScale(
const std::string &scale);
381 static void updateConstants();
385 template<
typename Quantity>
386 static double getConversionFactor();
390 template<
typename Quantity>
391 static double getConversionFactor(
typename Quantity::Unit unit);
394 template<
typename Quantity>
395 static typename Quantity::Unit getUnit(
const std::string &unit);
399 static std::string getUnitString(
405 int temperatureExponent,
411 template<
typename Quantity>
412 static typename std::enable_if<
413 Quantity::IsBaseQuantity::value,
415 >::type getUnitString(
int exponent);
418 static void initialize();
425 template<
typename Quantity>
426 void UnitHandler::setUnit(
typename Quantity::Unit unit){
427 double oldConversionFactor = getConversionFactor<Quantity>();
428 getUnit<Quantity>() = unit;
429 double newConversionFactor = getConversionFactor<Quantity>();
430 getScale<Quantity>() *= newConversionFactor/oldConversionFactor;
435 inline Quantity::Angle::Unit& UnitHandler::getUnit<Quantity::Angle>(
437 return std::get<0>(units);
441 inline Quantity::Charge::Unit& UnitHandler::getUnit<Quantity::Charge>(
443 return std::get<1>(units);
447 inline Quantity::Count::Unit& UnitHandler::getUnit<Quantity::Count>(
449 return std::get<2>(units);
453 inline Quantity::Energy::Unit& UnitHandler::getUnit<Quantity::Energy>(
455 return std::get<3>(units);
459 inline Quantity::Length::Unit& UnitHandler::getUnit<Quantity::Length>(
461 return std::get<4>(units);
465 inline Quantity::Temperature::Unit& UnitHandler::getUnit<
466 Quantity::Temperature
468 return std::get<5>(units);
472 inline Quantity::Time::Unit& UnitHandler::getUnit<Quantity::Time>(
474 return std::get<6>(units);
477 template <
typename Quantity>
478 void UnitHandler::setScale(
double scale,
typename Quantity::Unit unit){
479 setUnit<Quantity>(unit);
480 setScale<Quantity>(scale);
486 "UnitHandler::setScales()",
487 "'scales' must contain seven strings.",
491 setScale<Quantity::Angle>(scales[0]);
492 setScale<Quantity::Charge>(scales[1]);
493 setScale<Quantity::Count>(scales[2]);
494 setScale<Quantity::Energy>(scales[3]);
495 setScale<Quantity::Length>(scales[4]);
496 setScale<Quantity::Temperature>(scales[5]);
497 setScale<Quantity::Time>(scales[6]);
501 template<
typename Quantity>
503 return value*getScale<Quantity>();
506 template<
typename Quantity>
508 return value/getScale<Quantity>();
511 template<
typename Quantity>
512 typename std::enable_if<
513 Quantity::IsBaseQuantity::value,
515 >::type UnitHandler::convertArbitraryToBase(
517 typename Quantity::Unit unit
519 return value*getConversionFactor<Quantity>(
520 )/getConversionFactor<Quantity>(unit);
523 template<
typename Quantity>
524 typename std::enable_if<
525 !Quantity::IsBaseQuantity::value,
527 >::type UnitHandler::convertArbitraryToBase(
529 typename Quantity::Unit unit
531 return value*Quantity::getConversionFactor(
532 getUnit<TBTK::Quantity::Angle>(),
533 getUnit<TBTK::Quantity::Charge>(),
534 getUnit<TBTK::Quantity::Count>(),
535 getUnit<TBTK::Quantity::Energy>(),
536 getUnit<TBTK::Quantity::Length>(),
537 getUnit<TBTK::Quantity::Temperature>(),
538 getUnit<TBTK::Quantity::Time>()
539 )/Quantity::getConversionFactor(unit);
542 template<
typename Quantity>
543 typename std::enable_if<
544 Quantity::IsBaseQuantity::value,
546 >::type UnitHandler::convertBaseToArbitrary(
548 typename Quantity::Unit unit
550 return value*getConversionFactor<Quantity>(
552 )/getConversionFactor<Quantity>();
555 template<
typename Quantity>
556 typename std::enable_if<
557 !Quantity::IsBaseQuantity::value,
559 >::type UnitHandler::convertBaseToArbitrary(
561 typename Quantity::Unit unit
563 return value*Quantity::getConversionFactor(
565 )/Quantity::getConversionFactor(
566 getUnit<TBTK::Quantity::Angle>(),
567 getUnit<TBTK::Quantity::Charge>(),
568 getUnit<TBTK::Quantity::Count>(),
569 getUnit<TBTK::Quantity::Energy>(),
570 getUnit<TBTK::Quantity::Length>(),
571 getUnit<TBTK::Quantity::Temperature>(),
572 getUnit<TBTK::Quantity::Time>()
576 template<
typename Quantity>
577 typename std::enable_if<
578 Quantity::IsBaseQuantity::value,
580 >::type UnitHandler::convertArbitraryToNatural(
582 typename Quantity::Unit unit
584 return value*getConversionFactor<Quantity>(
585 )/(getConversionFactor<Quantity>(unit)*getScale<Quantity>());
588 template<
typename Quantity>
589 typename std::enable_if<
590 !Quantity::IsBaseQuantity::value,
592 >::type UnitHandler::convertArbitraryToNatural(
594 typename Quantity::Unit unit
596 double result = value*Quantity::getConversionFactor(
597 getUnit<TBTK::Quantity::Angle>(),
598 getUnit<TBTK::Quantity::Charge>(),
599 getUnit<TBTK::Quantity::Count>(),
600 getUnit<TBTK::Quantity::Energy>(),
601 getUnit<TBTK::Quantity::Length>(),
602 getUnit<TBTK::Quantity::Temperature>(),
603 getUnit<TBTK::Quantity::Time>()
604 )/Quantity::getConversionFactor(unit);
607 getScale<TBTK::Quantity::Angle>(),
608 Quantity::getExponent(TBTK::Quantity::Angle())
611 getScale<TBTK::Quantity::Charge>(),
612 Quantity::getExponent(TBTK::Quantity::Charge())
615 getScale<TBTK::Quantity::Count>(),
616 Quantity::getExponent(TBTK::Quantity::Count())
619 getScale<TBTK::Quantity::Energy>(),
620 Quantity::getExponent(TBTK::Quantity::Energy())
623 getScale<TBTK::Quantity::Length>(),
624 Quantity::getExponent(TBTK::Quantity::Length())
627 getScale<TBTK::Quantity::Temperature>(),
628 Quantity::getExponent(TBTK::Quantity::Temperature())
631 getScale<TBTK::Quantity::Time>(),
632 Quantity::getExponent(TBTK::Quantity::Time())
638 template<
typename Quantity>
639 typename std::enable_if<
640 Quantity::IsBaseQuantity::value,
642 >::type UnitHandler::convertNaturalToArbitrary(
644 typename Quantity::Unit unit
646 return value*getScale<Quantity>()*getConversionFactor<Quantity>(
648 )/getConversionFactor<Quantity>();
651 template<
typename Quantity>
652 typename std::enable_if<
653 !Quantity::IsBaseQuantity::value,
655 >::type UnitHandler::convertNaturalToArbitrary(
657 typename Quantity::Unit unit
659 double result = value*Quantity::getConversionFactor(
661 )/Quantity::getConversionFactor(
662 getUnit<TBTK::Quantity::Angle>(),
663 getUnit<TBTK::Quantity::Charge>(),
664 getUnit<TBTK::Quantity::Count>(),
665 getUnit<TBTK::Quantity::Energy>(),
666 getUnit<TBTK::Quantity::Length>(),
667 getUnit<TBTK::Quantity::Temperature>(),
668 getUnit<TBTK::Quantity::Time>()
672 getScale<TBTK::Quantity::Angle>(),
673 Quantity::getExponent(TBTK::Quantity::Angle())
676 getScale<TBTK::Quantity::Charge>(),
677 Quantity::getExponent(TBTK::Quantity::Charge())
680 getScale<TBTK::Quantity::Count>(),
681 Quantity::getExponent(TBTK::Quantity::Count())
684 getScale<TBTK::Quantity::Energy>(),
685 Quantity::getExponent(TBTK::Quantity::Energy())
688 getScale<TBTK::Quantity::Length>(),
689 Quantity::getExponent(TBTK::Quantity::Length())
692 getScale<TBTK::Quantity::Temperature>(),
693 Quantity::getExponent(TBTK::Quantity::Temperature())
696 getScale<TBTK::Quantity::Time>(),
697 Quantity::getExponent(TBTK::Quantity::Time())
703 template<
typename Quantity>
704 double UnitHandler::getConversionFactor(){
706 return Quantity::getConversionFactor(getUnit<Quantity>());
709 template<
typename Quantity>
710 double UnitHandler::getConversionFactor(
typename Quantity::Unit unit){
711 return Quantity::getConversionFactor(unit);
714 template<
typename Quantity>
715 inline void UnitHandler::setScale(
double scale){
716 getScale<Quantity>() = scale;
719 template<
typename Quantity>
720 inline void UnitHandler::setScale(
const std::string &scale){
721 std::stringstream stream(scale);
722 std::vector<std::string> components;
724 while(std::getline(stream, word,
' '))
725 components.push_back(word);
728 components.size() == 2,
729 "UnitHandler::setScale()",
730 "Invalid scale string '" << scale <<
"'.",
731 "The string must be on the format '[scale] [unit]', e.g. '1 K'"
736 value = stod(components[0]);
738 catch(
const std::exception &e){
740 "UnitHandler::setScale()",
741 "Unable to parse '" << components[0] <<
"' as a"
743 "The string has to be on the format '[scale] [unit]',"
748 typename Quantity::Unit unit = getUnit<Quantity>(components[1]);
750 setScale<Quantity>(value, unit);
754 inline double& UnitHandler::getScale<Quantity::Angle>(){
755 return std::get<0>(scales);
759 inline double& UnitHandler::getScale<Quantity::Charge>(){
760 return std::get<1>(scales);
764 inline double& UnitHandler::getScale<Quantity::Count>(){
765 return std::get<2>(scales);
769 inline double& UnitHandler::getScale<Quantity::Energy>(){
770 return std::get<3>(scales);
774 inline double& UnitHandler::getScale<Quantity::Length>(){
775 return std::get<4>(scales);
779 inline double& UnitHandler::getScale<Quantity::Temperature>(){
780 return std::get<5>(scales);
784 inline double& UnitHandler::getScale<Quantity::Time>(){
785 return std::get<6>(scales);
788 template<
typename Quantity>
789 inline typename std::enable_if<
790 Quantity::IsBaseQuantity::value,
792 >::type UnitHandler::getUnitString(){
793 return Quantity::getUnitString(getUnit<Quantity>());
796 template<
typename Quantity>
797 inline typename std::enable_if<
798 !Quantity::IsBaseQuantity::value,
800 >::type UnitHandler::getUnitString(){
801 return getUnitString(
802 static_cast<int>(Quantity::Exponent::Angle),
803 static_cast<int>(Quantity::Exponent::Charge),
804 static_cast<int>(Quantity::Exponent::Count),
805 static_cast<int>(Quantity::Exponent::Energy),
806 static_cast<int>(Quantity::Exponent::Length),
807 static_cast<int>(Quantity::Exponent::Temperature),
808 static_cast<int>(Quantity::Exponent::Time)
812 template<
typename Quantity>
813 typename Quantity::Unit UnitHandler::getUnit(
const std::string &unit){
814 return Quantity::getUnit(unit);
817 inline std::string UnitHandler::getUnitString(
823 int temperatureExponent,
827 result += getUnitString<Quantity::Angle>(angleExponent);
828 result += getUnitString<Quantity::Charge>(chargeExponent);
829 result += getUnitString<Quantity::Count>(countExponent);
830 result += getUnitString<Quantity::Energy>(energyExponent);
831 result += getUnitString<Quantity::Length>(lengthExponent);
832 result += getUnitString<Quantity::Temperature>(temperatureExponent);
833 result += getUnitString<Quantity::Time>(timeExponent);
835 if(result.size() != 0)
841 template<
typename Quantity>
842 inline typename std::enable_if<
843 Quantity::IsBaseQuantity::value,
845 >::type UnitHandler::getUnitString(
int exponent){
848 result += getUnitString<Quantity>();
850 result +=
"^" + std::to_string(exponent);
858 #ifdef M_E_temp //Avoid name clash with math.h macro M_E