24 void ReorderAndCapTerms(
double*
min,
double*
max) {
26 if (*
min > 0.0) *
min = 0.0;
27 if (*
max < 0.0) *
max = 0.0;
30 template <
bool use_bounds>
32 const std::vector<double>& lb,
33 const std::vector<double>& ub,
double scaling_factor,
35 double* max_scaled_sum_error) {
36 double max_error = 0.0;
37 double min_error = 0.0;
39 const int size =
input.size();
40 for (
int i = 0; i < size; ++i) {
41 const double x =
input[i];
42 if (x == 0.0)
continue;
43 const double scaled = x * scaling_factor;
52 const double error = std::round(scaled) - scaled;
53 const double error_lb = (use_bounds ? error * lb[i] : -error);
54 const double error_ub = (use_bounds ? error * ub[i] : error);
55 max_error +=
std::max(error_lb, error_ub);
56 min_error +=
std::min(error_lb, error_ub);
58 *max_scaled_sum_error =
std::max(std::abs(max_error), std::abs(min_error));
61 template <
bool use_bounds>
63 const std::vector<double>& lb,
64 const std::vector<double>& ub,
65 int64 max_absolute_sum,
66 double* scaling_factor) {
67 const double kInfinity = std::numeric_limits<double>::infinity();
73 if (max_absolute_sum < 0)
return;
81 int factor_exponent = 0;
84 bool recompute_sum =
false;
85 bool is_first_value =
true;
87 const int size =
input.size();
88 for (
int i = 0; i < size; ++i) {
89 const double x =
input[i];
90 double min_term = use_bounds ? x * lb[i] : -x;
91 double max_term = use_bounds ? x * ub[i] : x;
92 ReorderAndCapTerms(&min_term, &max_term);
99 if (min_term == 0.0 && max_term == 0.0)
continue;
103 const double c =
std::max(-min_term, max_term);
104 int candidate = msb - ilogb(c);
105 if (std::round(ldexp(std::abs(c), candidate)) > max_absolute_sum) {
108 DCHECK_LE(std::abs(
static_cast<int64>(round(ldexp(c, candidate)))),
112 if (is_first_value || candidate < factor_exponent) {
113 is_first_value =
false;
114 factor_exponent = candidate;
115 recompute_sum =
true;
119 static_cast<int64>(std::round(ldexp(min_term, factor_exponent)));
121 static_cast<int64>(std::round(ldexp(max_term, factor_exponent)));
122 if (sum_min > max_absolute_sum || sum_max > max_absolute_sum) {
124 recompute_sum =
true;
134 while (recompute_sum) {
137 for (
int j = 0; j <= i; ++j) {
138 const double x =
input[j];
139 double min_term = use_bounds ? x * lb[j] : -x;
140 double max_term = use_bounds ? x * ub[j] : x;
141 ReorderAndCapTerms(&min_term, &max_term);
143 static_cast<int64>(std::round(ldexp(min_term, factor_exponent)));
145 static_cast<int64>(std::round(ldexp(max_term, factor_exponent)));
147 if (sum_min > max_absolute_sum || sum_max > max_absolute_sum) {
150 recompute_sum =
false;
154 *scaling_factor = ldexp(1.0, factor_exponent);
160 const std::vector<double>& lb,
161 const std::vector<double>& ub,
double scaling_factor,
163 double* max_scaled_sum_error) {
164 ComputeScalingErrors<true>(
input, lb, ub, scaling_factor,
169 const std::vector<double>& lb,
170 const std::vector<double>& ub,
171 int64 max_absolute_sum) {
172 double scaling_factor;
173 GetBestScalingOfDoublesToInt64<true>(
input, lb, ub, max_absolute_sum,
175 return scaling_factor;
179 int64 max_absolute_sum,
180 double* scaling_factor,
182 double max_scaled_sum_error;
183 GetBestScalingOfDoublesToInt64<false>(
input, {}, {}, max_absolute_sum,
185 ComputeScalingErrors<false>(
input, {}, {}, *scaling_factor,
190 double scaling_factor) {
192 for (
int i = 0; i < x.size() && gcd != 1; ++i) {
193 int64 value = std::abs(std::round(x[i] * scaling_factor));
195 if (
value == 0)
continue;
208 return gcd > 0 ? gcd : 1;