core: add cast_int<> function

We had a pattern where doubles were converted to long with
lrint() and then down-cast to a narrower int type.

Because this is unwieldy, introduce a function encapsulating
this.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2024-09-03 09:52:12 +02:00 committed by bstoeger
parent 110e64bc66
commit 77b12bbccf
10 changed files with 34 additions and 23 deletions

View file

@ -554,7 +554,7 @@ static void match_standard_cylinder(cylinder_type_t &type)
default:
return;
}
type.description = format_string_std(fmt, (int)lrint(cuft));
type.description = format_string_std(fmt, int_cast<int>(cuft));
}
/*
@ -2439,7 +2439,7 @@ int dive::rel_mbar_to_depth(int mbar) const
/* whole mbar gives us cm precision */
double specific_weight = salinity_to_specific_weight(salinity);
return (int)lrint(mbar / specific_weight);
return int_cast<int>(mbar / specific_weight);
}
int dive::mbar_to_depth(int mbar) const
@ -2459,7 +2459,7 @@ int dive::mbar_to_depth(int mbar) const
depth_t dive::gas_mod(struct gasmix mix, pressure_t po2_limit, int roundto) const
{
double depth = (double) mbar_to_depth(po2_limit.mbar * 1000 / get_o2(mix));
return depth_t { .mm = (int)lrint(depth / roundto) * roundto };
return depth_t { .mm = int_cast<int>(depth / roundto) * roundto };
}
/* Maximum narcotic depth rounded to multiples of roundto mm */
@ -2468,14 +2468,14 @@ depth_t dive::gas_mnd(struct gasmix mix, depth_t end, int roundto) const
pressure_t ppo2n2 { .mbar = depth_to_mbar(end.mm) };
int maxambient = prefs.o2narcotic ?
(int)lrint(ppo2n2.mbar / (1 - get_he(mix) / 1000.0))
int_cast<int>(ppo2n2.mbar / (1 - get_he(mix) / 1000.0))
:
get_n2(mix) > 0 ?
(int)lrint(ppo2n2.mbar * N2_IN_AIR / get_n2(mix))
int_cast<int>(ppo2n2.mbar * N2_IN_AIR / get_n2(mix))
:
// Actually: Infinity
1000000;
return depth_t { .mm = (int)lrint(((double)mbar_to_depth(maxambient)) / roundto) * roundto };
return depth_t { .mm = int_cast<int>(((double)mbar_to_depth(maxambient)) / roundto) * roundto };
}
std::string dive::get_country() const

View file

@ -182,7 +182,7 @@ volume_t cylinder_t::gas_volume(pressure_t p) const
{
double bar = p.mbar / 1000.0;
double z_factor = gas_compressibility_factor(gasmix, bar);
return volume_t { .mliter = static_cast<int>(lrint(type.size.mliter * bar_to_atm(bar) / z_factor)) };
return volume_t { .mliter = int_cast<int>(type.size.mliter * bar_to_atm(bar) / z_factor) };
}
int find_best_gasmix_match(struct gasmix mix, const struct cylinder_table &cylinders)
@ -348,7 +348,7 @@ void copy_cylinder_types(const struct dive *s, struct dive *d)
void fill_default_cylinder(const struct dive *dive, cylinder_t *cyl)
{
const std::string &cyl_name = prefs.default_cylinder;
pressure_t pO2 = {.mbar = static_cast<int>(lrint(prefs.modpO2 * 1000.0))};
pressure_t pO2 = {.mbar = int_cast<int>(prefs.modpO2 * 1000.0)};
if (cyl_name.empty())
return;

View file

@ -283,7 +283,7 @@ static int display_to_base_unit(double f, enum filter_constraint_type type)
switch (desc->units) {
case FILTER_CONSTRAINT_NO_UNIT:
default:
return (int)lrint(f);
return int_cast<int>(f);
case FILTER_CONSTRAINT_LENGTH_UNIT:
return prefs.units.length == units::METERS ? lrint(f * 1000.0) : feet_to_mm(f);
case FILTER_CONSTRAINT_DURATION_UNIT:

View file

@ -93,17 +93,17 @@ static weight_t get_weight(const char *line)
static pressure_t get_airpressure(const char *line)
{
return pressure_t { .mbar = static_cast<int32_t>(lrint(ascii_strtod(line, NULL))) };
return pressure_t { .mbar = int_cast<int32_t>(ascii_strtod(line, NULL)) };
}
static pressure_t get_pressure(const char *line)
{
return pressure_t { .mbar = static_cast<int32_t>(lrint(1000 * ascii_strtod(line, NULL))) };
return pressure_t { .mbar = int_cast<int32_t>(1000 * ascii_strtod(line, NULL)) };
}
static o2pressure_t get_o2pressure(const char *line)
{
return o2pressure_t { .mbar = static_cast<uint16_t>(lrint(1000 * ascii_strtod(line, NULL))) };
return o2pressure_t { .mbar = int_cast<uint16_t>(1000 * ascii_strtod(line, NULL)) };
}
static int get_salinity(const char *line)

View file

@ -275,8 +275,8 @@ static std::pair<volume_t, volume_t> get_gas_parts(struct gasmix mix, volume_t v
if (gasmix_is_air(mix))
return { volume_t() , volume_t() };
volume_t air { .mliter = (int)lrint(((double)vol.mliter * get_n2(mix)) / (1000 - o2_in_topup)) };
volume_t he { .mliter = (int)lrint(((double)vol.mliter * get_he(mix)) / 1000.0) };
volume_t air { .mliter = int_cast<int>(((double)vol.mliter * get_n2(mix)) / (1000 - o2_in_topup)) };
volume_t he { .mliter = int_cast<int>(((double)vol.mliter * get_he(mix)) / 1000.0) };
volume_t o2 { .mliter = vol.mliter - he.mliter - air.mliter };
return std::make_pair(o2, he);
}

View file

@ -22,7 +22,7 @@ int get_pressure_units(int mb, const char **units)
unit = translate("gettextFromC", "bar");
break;
case units::PSI:
pressure = (int)lrint(mbar_to_PSI(mb));
pressure = int_cast<int>(mbar_to_PSI(mb));
unit = translate("gettextFromC", "psi");
break;
}

View file

@ -67,6 +67,17 @@
*/
using timestamp_t = int64_t;
/*
* There is a semi-common pattern where lrint() is used to round
* doubles to long integers and then cast down to a less wide
* int. Since this is unwieldy, encapsulate this in this function
*/
template <typename INT>
INT int_cast(double v)
{
return static_cast<INT>(lrint(v));
}
// Base class for all unit types using the "Curiously recurring template pattern"
// (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)
// to implement addition, subtraction and negation.
@ -190,8 +201,8 @@ static inline bool operator!=(const location_t &a, const location_t &b)
static inline location_t create_location(double lat, double lon)
{
location_t location = {
{ .udeg = (int) lrint(lat * 1000000) },
{ .udeg = (int) lrint(lon * 1000000) }
{ .udeg = int_cast<int>(lat * 1000000) },
{ .udeg = int_cast<int>(lon * 1000000) }
};
return location;
}
@ -208,7 +219,7 @@ static inline double grams_to_lbs(int grams)
static inline int lbs_to_grams(double lbs)
{
return (int)lrint(lbs * 453.6);
return int_cast<int>(lbs * 453.6);
}
static inline double ml_to_cuft(int ml)
@ -238,7 +249,7 @@ static inline long feet_to_mm(double feet)
static inline int to_feet(depth_t depth)
{
return (int)lrint(mm_to_feet(depth.mm));
return int_cast<int>(mm_to_feet(depth.mm));
}
static inline double mkelvin_to_C(int mkelvin)

View file

@ -1170,13 +1170,13 @@ static weight_t parseWeight(const QString &text)
return {};
double number = numOnly.toDouble();
if (text.contains(gettextFromC::tr("kg"), Qt::CaseInsensitive)) {
return { .grams = static_cast<int>(lrint(number * 1000)) };
return { .grams = int_cast<int>(number * 1000) };
} else if (text.contains(gettextFromC::tr("lbs"), Qt::CaseInsensitive)) {
return { .grams = lbs_to_grams(number) };
} else {
switch (prefs.units.weight) {
case units::KG:
return { .grams = static_cast<int>(lrint(number * 1000)) };
return { .grams = int_cast<int>(number * 1000) };
case units::LBS:
return { .grams = lbs_to_grams(number) };
default:

View file

@ -296,7 +296,7 @@ QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const
case CCSETPOINT:
return (divemode == CCR) ? (double)(p.setpoint / 1000.0) : QVariant();
case DEPTH:
return (int) lrint(get_depth_units(p.depth.mm, NULL, NULL));
return int_cast<int>(get_depth_units(p.depth.mm, NULL, NULL));
case RUNTIME:
return p.time / 60;
case DURATION:

View file

@ -1001,7 +1001,7 @@ void smartrak_import(const char *file, struct divelog *log)
/* No DC related data */
smtkdive->visibility = strtod((char *)col[coln(VISIBILITY)]->bind_ptr, NULL) > 25 ? 5 : lrint(strtod((char *)col[13]->bind_ptr, NULL) / 5);
weightsystem_t ws = { { .grams = (int)lrint(strtod((char *)col[coln(WEIGHT)]->bind_ptr, NULL) * 1000)}, std::string(), false };
weightsystem_t ws = { { .grams = int_cast<int>(strtod((char *)col[coln(WEIGHT)]->bind_ptr, NULL) * 1000)}, std::string(), false };
smtkdive->weightsystems.push_back(std::move(ws));
smtkdive->suit = get(suit_list, atoi((char *)col[coln(SUITIDX)]->bind_ptr) - 1);
smtk_build_location(mdb_clon, (char *)col[coln(SITEIDX)]->bind_ptr, &smtkdive->dive_site, log);