admin管理员组文章数量:1122832
I have various methods for accumulating quantities in fixed-precision numerics based on the following data type:
int95_t {
long long int x;
int y;
};
The numbers count forward in x
until it may run out of bounds and wrap around, at which point y
accumulates +1 for overflow and -1 for underflow. (I also have methods for adding floating point numbers, which may cause several overflows or underflows of x
and thus accumulate several times in y
).
The methods for adding or subtracting in this data type are somewhat involved.
int95_t sum(const int95_t a, const int95_t b) {
int95_t result = { a.x + b.x, a.y + b.y };
result.y += (1 - (2 * (b.x < 0LL))) * ((a.x ^ result.x) < 0 && (a.x ^ b.x) >= 0LL) * 2;
return result;
}
int95_t subtract(const int95_t a, const int95_t b) {
const int95_t neg_b = { -b.x, -b.y + (2 * (b.x == LLONG_MIN)) };
return sum(a, neg_b);
}
I have overloaded the operators +
, -
, +=
, and -=
for this data type, but that doesn't help to clean up my code all that much and for the following reason: in many contexts I will be storing not an array of int95_t
values but two separate arrays of long long int
and int
values. (The reason is that there are many conditions under which the supernary accumulator y
can be safely ignored, and I want to conserve memory bandwidth.) Thus, I have a lot of situations where, in order to add one int95_t to another in these circumstances, it seems I would still need to do:
long long int primary[8];
int secondary[8];
int95_t add_this = { 81573835283, 3816 };
for (int i = 0; i < 8; i++) {
int95_t tmp = { primary[i], secondary[i] };
tmp += add_this;
primary[i] = tmp.x;
secondary[i] = tmp.y;
}
Is there any better way? I would hope that I could count on any given C++ compiler to properly interpret something like this in the above case, but I'm not sure:
for (int i = 0; i < 8; i++) {
{ primary[i], secondary[i] } += add_this;
}
Thanks for any help you all can offer.
I have various methods for accumulating quantities in fixed-precision numerics based on the following data type:
int95_t {
long long int x;
int y;
};
The numbers count forward in x
until it may run out of bounds and wrap around, at which point y
accumulates +1 for overflow and -1 for underflow. (I also have methods for adding floating point numbers, which may cause several overflows or underflows of x
and thus accumulate several times in y
).
The methods for adding or subtracting in this data type are somewhat involved.
int95_t sum(const int95_t a, const int95_t b) {
int95_t result = { a.x + b.x, a.y + b.y };
result.y += (1 - (2 * (b.x < 0LL))) * ((a.x ^ result.x) < 0 && (a.x ^ b.x) >= 0LL) * 2;
return result;
}
int95_t subtract(const int95_t a, const int95_t b) {
const int95_t neg_b = { -b.x, -b.y + (2 * (b.x == LLONG_MIN)) };
return sum(a, neg_b);
}
I have overloaded the operators +
, -
, +=
, and -=
for this data type, but that doesn't help to clean up my code all that much and for the following reason: in many contexts I will be storing not an array of int95_t
values but two separate arrays of long long int
and int
values. (The reason is that there are many conditions under which the supernary accumulator y
can be safely ignored, and I want to conserve memory bandwidth.) Thus, I have a lot of situations where, in order to add one int95_t to another in these circumstances, it seems I would still need to do:
long long int primary[8];
int secondary[8];
int95_t add_this = { 81573835283, 3816 };
for (int i = 0; i < 8; i++) {
int95_t tmp = { primary[i], secondary[i] };
tmp += add_this;
primary[i] = tmp.x;
secondary[i] = tmp.y;
}
Is there any better way? I would hope that I could count on any given C++ compiler to properly interpret something like this in the above case, but I'm not sure:
for (int i = 0; i < 8; i++) {
{ primary[i], secondary[i] } += add_this;
}
Thanks for any help you all can offer.
Share Improve this question asked Nov 22, 2024 at 3:14 dsceruttidscerutti 1916 bronze badges 2 |1 Answer
Reset to default 1One of solutions could be to create a temporary object with overloaded arithmetics which holds references to operand components. For example:
class split
{
long long int ℞
int &ry;
public:
split(long long int &x, int &y) : rx { x }, ry { y } {}
split &operator+=(const int95_t &v)
{
// implement your += logic here with rx and ry modification
return *this;
}
};
for (int i = 0; i < 8; i++) {
split(primary[i], secondary[i]) += add_this;
}
You can also re-use this class for int95_t
overloaded operators implementation, i.e.
int95_t val = { 81573835283, 3816 };
split(val.x, val.y) += add_this;
本文标签:
版权声明:本文标题:c++ - Is there an efficient way to overload operators for structs when the underlying data is piecewise? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736305880a1932747.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
sum()
you doint95_t result = { a.x + b.x, a.y + b.y };
. If calculation ofax + bx
overflows along long
, then behaviour of your program is undefined. I suggest getting the computation of the sum working correctly (i.e. avoiding undefined behaviour) before worrying about how to improve your code, by whatever measure. Essentially, to avoid problems with overflowing signed integers in C++, it is necessary to prevent any calculation that produces undefined behaviour, not allow it to occur and then take recovery action. – Peter Commented Nov 22, 2024 at 6:06std::intxx_t
includes the sign bit, so we get 64 not 63. – Passer By Commented Nov 22, 2024 at 6:20