Files
AMSS-NCKU/AMSS_NCKU_source/linear_map.h
2026-01-13 15:01:15 +08:00

132 lines
3.8 KiB
C++

#ifndef AHFINDERDIRECT__LINEAR_MAP_HH
#define AHFINDERDIRECT__LINEAR_MAP_HH
namespace AHFinderDirect
{
namespace jtutil
{
template <typename fp_t>
class linear_map
{
public:
// integer bounds info
int min_int() const { return min_int_; }
int max_int() const { return max_int_; }
int N_points() const
{
return jtutil::how_many_in_range(min_int_, max_int_);
}
bool is_in_range(int i) const
{
return (i >= min_int()) && (i <= max_int());
}
int clamp(int i) const
{
if (i < min_int())
then return min_int();
else if (i > max_int())
then return max_int();
else
return i;
}
// convert int --> fp
fp_t fp_of_int_unchecked(int i) const
{
return origin_ + delta_ * i;
}
fp_t fp_of_int(int i) const
{
assert(is_in_range(i));
return fp_of_int_unchecked(i);
}
// converg delta_int --> delta_fp
fp_t delta_fp_of_delta_int(int delta_i) const
{
return delta_ * delta_i;
}
// fp bounds info
fp_t origin() const { return origin_; }
fp_t delta_fp() const { return delta_; }
fp_t inverse_delta_fp() const { return inverse_delta_; }
fp_t min_fp() const { return fp_of_int_unchecked(min_int_); }
fp_t max_fp() const { return fp_of_int_unchecked(max_int_); }
bool is_in_range(fp_t x) const
{
return fuzzy<fp_t>::GE(x, min_fp()) && fuzzy<fp_t>::LE(x, max_fp());
}
fp_t clamp(fp_t x) const
{
if (x < min_fp())
then return min_fp();
else if (x > max_fp())
then return max_fp();
else
return x;
}
// convert linear map indices <--> C-style 0-origin indices
int zero_origin_int(int i) const { return i - min_int(); }
int map_int(int zero_origin_i) { return zero_origin_i + min_int(); }
// convert fp --> int coordinate, but return result as fp
// (which need not be fuzzily integral)
fp_t fp_int_of_fp(fp_t x) const;
// convert fp --> int, check being fuzzily integral
enum noninteger_action // what to do if "int"
// isn't fuzzily integral?
{
nia_error, // jtutil::error_exit(...)
nia_warning, // print warning msg,
// then round to nearest
nia_round, // (silently) round to nearest
nia_floor, // (silently) round to -infinity
nia_ceiling // (silently) round to +infinity
};
int int_of_fp(fp_t x, noninteger_action nia = nia_error) const;
// convert delta_fp --> delta_int, check being fuzzily integral
int delta_int_of_delta_fp(fp_t delta_x,
noninteger_action nia = nia_error)
const;
// constructors
linear_map(int min_int_in, int max_int_in,
fp_t min_fp_in, fp_t delta_fp_in, fp_t max_fp_in);
// ... construct with subrange of existing linear_map
linear_map(const linear_map<fp_t> &lm_in,
int min_int_in, int max_int_in);
// no need for explicit destructor, compiler-generated no-op is ok
// no need for copy constructor or assignment operator,
// compiler-generated defaults are ok
private:
// common code (argument validation & setup) for all constructors
// assumes min_int_, max_int_, delta_ already initialized,
// other class members *not* initialized
void constructor_common(fp_t min_fp_in, fp_t max_fp_in);
// these define the actual mapping
// via the fp_of_int() function (above)
fp_t origin_, delta_;
// cache of 1.0/delta_
// ==> avoids fp divide in inverse_delta_fp()
// ==> also makes fp --> int conversions slightly faster
fp_t inverse_delta_;
const int min_int_, max_int_;
};
//******************************************************************************
} // namespace jtutil
} // namespace AHFinderDirect
#endif /* AHFINDERDIRECT__LINEAR_MAP_HH */