Skip to content

Commit

Permalink
Use explicit floor or ceil for forceful int to double conversions (#217)
Browse files Browse the repository at this point in the history
- Uses static_cast with floor for clear truncation cases (without subtraction).
- Use static_cast with floor or ceil depending on the type of treatment based on the original code (in treatments and tests).
  • Loading branch information
wenzeslaus authored Mar 12, 2024
1 parent fc1fa92 commit 15e3b04
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 30 deletions.
3 changes: 2 additions & 1 deletion include/pops/actions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,8 @@ class MoveOverpopulatedPests
// for leaving_percentage == 0.5
// 2 infected -> 1 leaving
// 3 infected -> 1 leaving
int leaving = original_count * leaving_percentage_;
int leaving =
static_cast<int>(std::floor(original_count * leaving_percentage_));
leaving = hosts.pests_from(i, j, leaving, generator.overpopulation());
if (row < 0 || row >= rows_ || col < 0 || col >= cols_) {
pests.add_outside_dispersers_at(row, col, leaving);
Expand Down
15 changes: 8 additions & 7 deletions include/pops/host_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,8 @@ class HostPool : public HostPoolInterface<RasterIndex>
}
}
else {
dispersers_from_cell = lambda * infected_at(row, col);
dispersers_from_cell =
static_cast<int>(std::floor(lambda * infected_at(row, col)));
}
return dispersers_from_cell;
}
Expand Down Expand Up @@ -532,10 +533,10 @@ class HostPool : public HostPoolInterface<RasterIndex>
void completely_remove_hosts_at(
RasterIndex row,
RasterIndex col,
double susceptible,
std::vector<double> exposed,
double infected,
const std::vector<double>& mortality)
int susceptible,
std::vector<int> exposed,
int infected,
const std::vector<int>& mortality)
{
if (susceptible > 0)
susceptible_(row, col) = susceptible_(row, col) - susceptible;
Expand Down Expand Up @@ -824,8 +825,8 @@ class HostPool : public HostPoolInterface<RasterIndex>
mortality_in_index = mortality_tracker_vector_[index](row, col);
}
else {
mortality_in_index =
mortality_rate * mortality_tracker_vector_[index](row, col);
mortality_in_index = static_cast<int>(std::floor(
mortality_rate * mortality_tracker_vector_[index](row, col)));
}
mortality_tracker_vector_[index](row, col) -= mortality_in_index;
died_(row, col) += mortality_in_index;
Expand Down
2 changes: 1 addition & 1 deletion include/pops/pest_host_table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class PestHostTable
* @param host Pointer to the host to get the information for
* @return Mortality time lag value
*/
double mortality_time_lag(const HostPool* host) const
int mortality_time_lag(const HostPool* host) const
{
auto host_index = environment_.host_index(host);
return mortality_time_lags_.at(host_index);
Expand Down
8 changes: 4 additions & 4 deletions include/pops/quarantine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,20 +147,20 @@ class QuarantineEscapeAction
DistDir closest;
if (directions_.at(Direction::N)
&& (i - n) * north_south_resolution_ < mindist) {
mindist = (i - n) * north_south_resolution_;
mindist = static_cast<int>(std::floor((i - n) * north_south_resolution_));
closest = std::make_tuple(mindist, Direction::N);
}
if (directions_.at(Direction::S)
&& (s - i) * north_south_resolution_ < mindist) {
mindist = (s - i) * north_south_resolution_;
mindist = static_cast<int>(std::floor((s - i) * north_south_resolution_));
closest = std::make_tuple(mindist, Direction::S);
}
if (directions_.at(Direction::E) && (e - j) * west_east_resolution_ < mindist) {
mindist = (e - j) * west_east_resolution_;
mindist = static_cast<int>(std::floor((e - j) * west_east_resolution_));
closest = std::make_tuple(mindist, Direction::E);
}
if (directions_.at(Direction::W) && (j - w) * west_east_resolution_ < mindist) {
mindist = (j - w) * west_east_resolution_;
mindist = static_cast<int>(std::floor((j - w) * west_east_resolution_));
closest = std::make_tuple(mindist, Direction::W);
}
return closest;
Expand Down
36 changes: 22 additions & 14 deletions include/pops/treatments.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,18 +173,20 @@ class SimpleTreatment : public BaseTreatment<HostPool, FloatRaster>
for (auto indices : host_pool.suitable_cells()) {
int i = indices[0];
int j = indices[1];
double remove_susceptible = this->get_treated(
i, j, host_pool.susceptible_at(i, j), TreatmentApplication::Ratio);
double remove_infected =
this->get_treated(i, j, host_pool.infected_at(i, j));
std::vector<double> remove_mortality;
int remove_susceptible = static_cast<int>(std::ceil(this->get_treated(
i, j, host_pool.susceptible_at(i, j), TreatmentApplication::Ratio)));
int remove_infected = static_cast<int>(
std::ceil(this->get_treated(i, j, host_pool.infected_at(i, j))));
std::vector<int> remove_mortality;
for (int count : host_pool.mortality_by_group_at(i, j)) {
remove_mortality.push_back(this->get_treated(i, j, count));
remove_mortality.push_back(
static_cast<int>(std::ceil(this->get_treated(i, j, count))));
}

std::vector<double> remove_exposed;
std::vector<int> remove_exposed;
for (int count : host_pool.exposed_by_group_at(i, j)) {
remove_exposed.push_back(this->get_treated(i, j, count));
remove_exposed.push_back(
static_cast<int>(std::ceil(this->get_treated(i, j, count))));
}
host_pool.completely_remove_hosts_at(
i,
Expand Down Expand Up @@ -241,23 +243,29 @@ class PesticideTreatment : public BaseTreatment<HostPool, FloatRaster>
// Given how the original code was written (everything was first converted
// to ints and subtractions happened only afterwards), this needs ints,
// not doubles to pass the r.pops.spread test (unlike the other code which
// did substractions before converting to ints).
int susceptible_resistant = this->get_treated(
i, j, host_pool.susceptible_at(i, j), TreatmentApplication::Ratio);
// did substractions before converting to ints), so the conversion to ints
// happened only later. Now get_treated returns double and floor or ceil is
// applied to the result to get the same results as before.
int susceptible_resistant = static_cast<int>(std::floor(this->get_treated(
i, j, host_pool.susceptible_at(i, j), TreatmentApplication::Ratio)));
std::vector<int> resistant_exposed_list;
for (const auto& number : host_pool.exposed_by_group_at(i, j)) {
resistant_exposed_list.push_back(this->get_treated(i, j, number));
resistant_exposed_list.push_back(
static_cast<int>(std::floor(this->get_treated(i, j, number))));
}
std::vector<int> resistant_mortality_list;
for (const auto& number : host_pool.mortality_by_group_at(i, j)) {
resistant_mortality_list.push_back(this->get_treated(i, j, number));
resistant_mortality_list.push_back(
static_cast<int>(std::floor(this->get_treated(i, j, number))));
}
int infected = static_cast<int>(
std::floor(this->get_treated(i, j, host_pool.infected_at(i, j))));
host_pool.make_resistant_at(
i,
j,
susceptible_resistant,
resistant_exposed_list,
this->get_treated(i, j, host_pool.infected_at(i, j)),
infected,
resistant_mortality_list);
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/test_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,8 +705,8 @@ int test_model_sei_deterministic_with_treatments()
for (int row = 0; row < expected_infected.rows(); ++row)
for (int col = 0; col < expected_infected.rows(); ++col)
if (pesticide_treatment(row, col) > 0)
expected_infected(row, col) =
2 * pesticide_treatment(row, col) * infected(row, col);
expected_infected(row, col) = static_cast<int>(
std::floor(2 * pesticide_treatment(row, col) * infected(row, col)));
// Valus is based on the result which is considered correct.
Raster<int> expected_dispersers = {{0, 0, 0}, {0, 5, 0}, {0, 0, 2}};

Expand Down
3 changes: 2 additions & 1 deletion tests/test_overpopulation_movements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ int test_model()
config.use_spreadrates = false;
config.create_schedules();
// More reference data
auto leaving = infected(0, 0) * config.leaving_percentage;
int leaving =
static_cast<int>(std::ceil(infected(0, 0) * config.leaving_percentage));
// Objects
std::vector<std::vector<int>> suitable_cells =
find_suitable_cells<int>(total_hosts);
Expand Down

0 comments on commit 15e3b04

Please sign in to comment.