Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Corryvreckan
Corryvreckan
Commits
1be5173a
Commit
1be5173a
authored
Jun 28, 2018
by
Simon Spannagel
Browse files
Update unit class, move implementations of templates inot template file
parent
0ab1f7d6
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/core/utils/unit.cpp
View file @
1be5173a
...
...
@@ -3,10 +3,8 @@
* @brief Implementation of unit system
*
* @copyright Copyright (c) 2017 CERN and the Allpix Squared authors.
* This software is distributed under the terms of the MIT License, copied
* verbatim in the file "LICENSE.md".
* In applying this license, CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an
* This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
* In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
* Intergovernmental Organization or submit itself to any jurisdiction.
*/
...
...
@@ -20,7 +18,7 @@
#include <string>
#include <type_traits>
#include "core/utils/
string
.h"
#include "core/utils/
text
.h"
using
namespace
corryvreckan
;
...
...
@@ -29,8 +27,7 @@ std::map<std::string, corryvreckan::Units::UnitType> Units::unit_map_;
/**
* @throws std::invalid_argument If the unit already exists
*
* Units should consist of only alphabetical characters. Units are converted to
* lowercase internally. All the defined units
* Units should consist of only alphabetical characters. Units are converted to lowercase internally. All the defined units
* should have unique values and it is not possible to redefine them.
*
* @note No explicit check is done for alphabetical units
...
...
@@ -49,8 +46,7 @@ void Units::add(std::string str, UnitType value) {
/**
* @throws std::invalid_argument If the requested unit does not exist
*
* All units are converted to lowercase before finding their value in the
* internal database.
* All units are converted to lowercase before finding their value in the internal database.
*/
corryvreckan
::
Units
::
UnitType
Units
::
getSingle
(
std
::
string
str
)
{
if
(
corryvreckan
::
trim
(
str
).
empty
())
{
...
...
@@ -70,10 +66,8 @@ corryvreckan::Units::UnitType Units::getSingle(std::string str) {
/**
* @throws invalid_argument If one tries to get the value of an empty unit
*
* Units are combined by applying the multiplication operator * and the division
* operator / linearly. The first unit is
* always multiplied, following common sense. Grouping units together within
* brackets or parentheses is not supported. Thus
* Units are combined by applying the multiplication operator * and the division operator / linearly. The first unit is
* always multiplied, following common sense. Grouping units together within brackets or parentheses is not supported. Thus
* any other character then a name of a unit, * or \ should lead to an error
*/
corryvreckan
::
Units
::
UnitType
Units
::
get
(
std
::
string
str
)
{
...
...
@@ -143,11 +137,9 @@ corryvreckan::Units::UnitType Units::convert(UnitType input, std::string str) {
* @throws std::invalid_argument If the list of units is empty
*
* The best unit is determined using the two rules below:
* - If there exists at least one unit for which the value is larger than one,
* the unit with value nearest to one is chosen
* - If there exists at least one unit for which the value is larger than one, the unit with value nearest to one is chosen
* from all units with values larger than one
* - Otherwise the unit is chosen that has a value as close as possible to one
* (from below)
* - Otherwise the unit is chosen that has a value as close as possible to one (from below)
*/
std
::
string
Units
::
display
(
UnitType
input
,
std
::
initializer_list
<
std
::
string
>
units
)
{
if
(
units
.
size
()
==
0
)
{
...
...
src/core/utils/unit.h
View file @
1be5173a
...
...
@@ -128,55 +128,22 @@ namespace corryvreckan {
// TODO [doc] Shall we change the name in something better here
static
std
::
string
display
(
UnitType
input
,
std
::
string
unit
);
/**
* @brief Return value for display in the best of all the provided units for all vector elements
* @param input Vector of values in the base unit system
* @param units Name of the possible output units
* @return Vector of values between parentheses with best display units for each element
* @note Works for all vector types that can be converted to a string using \ref StringConversions "the string
* utilities".
*/
template
<
typename
T
>
static
std
::
string
display
(
T
input
,
std
::
initializer_list
<
std
::
string
>
units
);
private:
static
std
::
map
<
std
::
string
,
UnitType
>
unit_map_
;
};
// TODO [doc] Move these to a separate template implementation file?
/**
* @throws std::overflow_error If the converted unit overflows the requested
* type
*
* The unit type is internally converted to the type \ref Units::UnitType. After
* multiplying the unit, the output is
* checked for overflow problems before the type is converted back to the
* original type.
*/
template
<
typename
T
>
T
Units
::
get
(
T
inp
,
std
::
string
str
)
{
UnitType
out
=
static_cast
<
UnitType
>
(
inp
)
*
get
(
std
::
move
(
str
));
if
(
out
>
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
max
())
||
out
<
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
lowest
()))
{
throw
std
::
overflow_error
(
"unit conversion overflows the type"
);
}
return
static_cast
<
T
>
(
out
);
}
// Getters for single and inverse units
template
<
typename
T
>
T
Units
::
getSingle
(
T
inp
,
std
::
string
str
)
{
UnitType
out
=
static_cast
<
UnitType
>
(
inp
)
*
getSingle
(
std
::
move
(
str
));
if
(
out
>
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
max
())
||
out
<
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
lowest
()))
{
throw
std
::
overflow_error
(
"unit conversion overflows the type"
);
}
return
static_cast
<
T
>
(
out
);
}
template
<
typename
T
>
T
Units
::
getSingleInverse
(
T
inp
,
std
::
string
str
)
{
UnitType
out
=
static_cast
<
UnitType
>
(
inp
)
/
getSingle
(
std
::
move
(
str
));
if
(
out
>
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
max
())
||
out
<
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
lowest
()))
{
throw
std
::
overflow_error
(
"unit conversion overflows the type"
);
}
return
static_cast
<
T
>
(
out
);
}
template
<
typename
T
>
T
Units
::
getInverse
(
T
inp
,
std
::
string
str
)
{
UnitType
out
=
static_cast
<
UnitType
>
(
inp
)
/
get
(
std
::
move
(
str
));
if
(
out
>
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
max
())
||
out
<
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
lowest
()))
{
throw
std
::
overflow_error
(
"unit conversion overflows the type"
);
}
return
static_cast
<
T
>
(
out
);
}
}
// namespace corryvreckan
// Include template definitions
#include "unit.tpp"
#endif
/* CORRYVRECKAN_UNIT_H */
src/core/utils/unit.tpp
0 → 100644
View file @
1be5173a
#include "text.h"
namespace
corryvreckan
{
/**
* @throws std::overflow_error If the converted unit overflows the requested type
*
* The unit type is internally converted to the type \ref Units::UnitType. After multiplying the unit, the output is
* checked for overflow problems before the type is converted back to the original type.
*/
template
<
typename
T
>
T
Units
::
get
(
T
inp
,
std
::
string
str
)
{
UnitType
out
=
static_cast
<
UnitType
>
(
inp
)
*
get
(
std
::
move
(
str
));
if
(
out
>
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
max
())
||
out
<
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
lowest
()))
{
throw
std
::
overflow_error
(
"unit conversion overflows the type"
);
}
return
static_cast
<
T
>
(
out
);
}
// Getters for single and inverse units
template
<
typename
T
>
T
Units
::
getSingle
(
T
inp
,
std
::
string
str
)
{
UnitType
out
=
static_cast
<
UnitType
>
(
inp
)
*
getSingle
(
std
::
move
(
str
));
if
(
out
>
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
max
())
||
out
<
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
lowest
()))
{
throw
std
::
overflow_error
(
"unit conversion overflows the type"
);
}
return
static_cast
<
T
>
(
out
);
}
template
<
typename
T
>
T
Units
::
getSingleInverse
(
T
inp
,
std
::
string
str
)
{
UnitType
out
=
static_cast
<
UnitType
>
(
inp
)
/
getSingle
(
std
::
move
(
str
));
if
(
out
>
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
max
())
||
out
<
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
lowest
()))
{
throw
std
::
overflow_error
(
"unit conversion overflows the type"
);
}
return
static_cast
<
T
>
(
out
);
}
template
<
typename
T
>
T
Units
::
getInverse
(
T
inp
,
std
::
string
str
)
{
UnitType
out
=
static_cast
<
UnitType
>
(
inp
)
/
get
(
std
::
move
(
str
));
if
(
out
>
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
max
())
||
out
<
static_cast
<
UnitType
>
(
std
::
numeric_limits
<
T
>::
lowest
()))
{
throw
std
::
overflow_error
(
"unit conversion overflows the type"
);
}
return
static_cast
<
T
>
(
out
);
}
// Display function for vectors
template
<
typename
T
>
std
::
string
Units
::
display
(
T
inp
,
std
::
initializer_list
<
std
::
string
>
units
)
{
auto
split
=
corryvreckan
::
split
<
Units
::
UnitType
>
(
corryvreckan
::
to_string
(
inp
));
std
::
string
ret_str
;
if
(
split
.
size
()
>
1
)
{
ret_str
+=
"("
;
}
for
(
auto
&
element
:
split
)
{
ret_str
+=
Units
::
display
(
element
,
units
);
ret_str
+=
","
;
}
if
(
split
.
size
()
>
1
)
{
ret_str
[
ret_str
.
size
()
-
1
]
=
')'
;
}
else
{
ret_str
.
pop_back
();
}
return
ret_str
;
}
}
// namespace corryvreckan
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment