Version: SMASH-3.4
tabulation.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-2019,2024,2026
3  * SMASH Team
4  *
5  * GNU General Public License (GPLv3 or later)
6  */
7 
8 #include "smash/tabulation.h"
9 
10 #include "smash/numeric_cast.h"
11 
12 namespace smash {
13 
14 Tabulation::Tabulation(double x_min, double range, size_t num,
15  std::function<double(double)> f)
16  : x_min_(x_min), x_max_(x_min + range), inv_dx_(num / range) {
17  if (num < 2) {
18  throw std::runtime_error("Tabulation needs at least two values");
19  }
20  values_.resize(num + 1);
21  const double dx = range / num;
22  for (size_t i = 0; i <= num; i++) {
23  values_[i] = f(x_min_ + i * dx);
24  }
25 }
26 
27 double Tabulation::get_value_step(double x) const {
28  if (x < x_min_) {
29  return 0.;
30  }
31  const unsigned int n =
32  numeric_cast<unsigned int>(std::floor((x - x_min_) * inv_dx_ + 0.5));
33  if (n >= values_.size()) {
34  return values_.back();
35  } else {
36  return values_[n];
37  }
38 }
39 
41  double x, ExtrapolationType extrapolation_type_for_x_beyond_xmax) const {
42  if (x < x_min_) {
43  return 0.;
44  }
45  switch (extrapolation_type_for_x_beyond_xmax) {
47  if (x > x_max_) {
48  return 0.;
49  }
50  [[fallthrough]];
52  if (x > x_max_) {
53  return values_.back();
54  }
55  [[fallthrough]];
57  return linear_approximation_(x);
58  default:
59  throw std::invalid_argument(
60  "The provided extrapolation type is not supported. Valid types are "
61  "'Zero', 'Constant', and 'Linear'.");
62  }
63 }
64 
65 /**
66  * Write binary representation to stream.
67  *
68  * \param stream Output stream.
69  * \param x Value to be written.
70  */
71 static void swrite(std::ofstream& stream, double x) {
72  stream.write(reinterpret_cast<const char*>(&x), sizeof(x));
73 }
74 
75 /**
76  * Read binary representation of a double.
77  *
78  * \param[in] stream Input stream.
79  * \return Read value.
80  */
81 static double sread_double(std::ifstream& stream) {
82  double x;
83  stream.read(reinterpret_cast<char*>(&x), sizeof(x));
84  return x;
85 }
86 
87 /**
88  * Write binary representation to stream.
89  *
90  * \param stream Output stream.
91  * \param x Value to be written.
92  */
93 static void swrite(std::ofstream& stream, size_t x) {
94  // We want to support 32-bit and 64-bit platforms, so we store a 64-bit
95  // integer on all platforms.
96  const auto const_size_x = static_cast<uint64_t>(x);
97  stream.write(reinterpret_cast<const char*>(&const_size_x),
98  sizeof(const_size_x));
99 }
100 
101 /**
102  * Read binary representation of a size_t.
103  *
104  * \param[in] stream Input stream.
105  * \return Read value.
106  */
107 static size_t sread_size(std::ifstream& stream) {
108  uint64_t x;
109  stream.read(reinterpret_cast<char*>(&x), sizeof(x));
110  if (x > std::numeric_limits<size_t>::max()) {
111  throw std::runtime_error("trying to read vector larger than supported");
112  }
113  return x;
114 }
115 
116 /**
117  * Write binary representation to stream.
118  *
119  * \param stream Output stream.
120  * \param x Value to be written.
121  */
122 static void swrite(std::ofstream& stream, const std::vector<double> x) {
123  swrite(stream, x.size());
124  if (x.size() > 0) {
125  stream.write(reinterpret_cast<const char*>(x.data()),
126  sizeof(x[0]) * x.size());
127  }
128 }
129 
130 /**
131  * Read binary representation of a vector of doubles.
132  *
133  * \param[in] stream Input stream.
134  * \return Read value.
135  */
136 static std::vector<double> sread_vector(std::ifstream& stream) {
137  const size_t n = sread_size(stream);
138  std::vector<double> x;
139  x.resize(n);
140  stream.read(reinterpret_cast<char*>(x.data()), sizeof(double) * n);
141  return x;
142 }
143 
144 /**
145  * Write binary representation to stream.
146  *
147  * \param stream Output stream.
148  * \param x Value to be written.
149  */
150 static void swrite(std::ofstream& stream, sha256::Hash x) {
151  // The size is always the same, so there is no need to write it.
152  stream.write(reinterpret_cast<const char*>(x.data()),
153  sizeof(x[0]) * x.size());
154 }
155 
156 /**
157  * Read binary representation of a SHA256 hash.
158  *
159  * \param[in] stream Input stream.
160  * \return Read value.
161  */
162 static sha256::Hash sread_hash(std::ifstream& stream) {
163  sha256::Hash x;
164  stream.read(reinterpret_cast<char*>(x.data()), x.size());
165  return x;
166 }
167 
168 void Tabulation::write(std::ofstream& stream, sha256::Hash hash) const {
169  swrite(stream, hash);
170  swrite(stream, x_min_);
171  swrite(stream, x_max_);
172  swrite(stream, inv_dx_);
173  swrite(stream, values_);
174 }
175 
176 Tabulation Tabulation::from_file(std::ifstream& stream, sha256::Hash hash) {
177  sha256::Hash hash_from_stream = sread_hash(stream);
178  Tabulation t;
179  if (hash != hash_from_stream) {
180  return t;
181  }
182  t.x_min_ = sread_double(stream);
183  t.x_max_ = sread_double(stream);
184  t.inv_dx_ = sread_double(stream);
185  t.values_ = sread_vector(stream);
186  return t;
187 }
188 
189 } // namespace smash
A class for storing a one-dimensional lookup table of floating-point values.
Definition: tabulation.h:30
double x_min_
lower bound for tabulation
Definition: tabulation.h:111
double inv_dx_
inverse step size 1/dx
Definition: tabulation.h:117
double x_max_
upper bound for tabulation
Definition: tabulation.h:114
double get_value_linear(double x, ExtrapolationType extrapolation=ExtrapolationType::Linear) const
Look up a value from the tabulation using linear interpolation.
Definition: tabulation.cc:40
std::vector< double > values_
vector for storing tabulated values
Definition: tabulation.h:108
static Tabulation from_file(std::ifstream &stream, sha256::Hash hash)
Construct a tabulation object by reading binary data from a stream.
Definition: tabulation.cc:176
Tabulation()
Construct an empty tabulation object.
Definition: tabulation.h:35
void write(std::ofstream &stream, sha256::Hash hash) const
Write a binary representation of the tabulation to a stream.
Definition: tabulation.cc:168
double linear_approximation_(double x) const
Linear approximation to interpolate and extrapolate tabulations.
Definition: tabulation.h:120
double get_value_step(double x) const
Look up a value from the tabulation (without any interpolation, simply using the closest tabulated va...
Definition: tabulation.cc:27
ExtrapolationType
Allows to specify the desired extrapolation type.
@ Linear
Extrapolate using a linear approach.
@ Constant
Extrapolate using a constant value.
@ Zero
Extrapolate with zero.
constexpr int n
Neutron.
std::array< uint8_t, HASH_SIZE > Hash
A SHA256 hash.
Definition: sha256.h:25
Definition: action.h:24
static std::vector< double > sread_vector(std::ifstream &stream)
Read binary representation of a vector of doubles.
Definition: tabulation.cc:136
static double sread_double(std::ifstream &stream)
Read binary representation of a double.
Definition: tabulation.cc:81
static sha256::Hash sread_hash(std::ifstream &stream)
Read binary representation of a SHA256 hash.
Definition: tabulation.cc:162
static void swrite(std::ofstream &stream, double x)
Write binary representation to stream.
Definition: tabulation.cc:71
static size_t sread_size(std::ifstream &stream)
Read binary representation of a size_t.
Definition: tabulation.cc:107