Reputation: 13
Is there a way to iterate this so I don't have to add every each function? Lets say I have 4 planets and I want to add every gforcex to planet[1].forcex. (this is from an n-body simulation project)
planet[1].forcex =
gforcex(planet[1].posx, planet[1].posy, planet[2].posx, planet[2].posy)
+ gforcex(planet[1].posx, planet[1].posy, planet[3].posx, planet[3].posy)
+ gforcex(planet[1].posx, planet[1].posy, planet[4].posx, planet[4].posy);
Upvotes: 1
Views: 101
Reputation: 4288
This is a great spot for std::accumulate
.
#include <cmath>
#include <iostream>
#include <iterator>
#include <numeric>
using position_t = double;
using force_t = double;
class Planet {
public:
Planet(position_t x, position_t y)
: posx(x)
, posy(y)
, forcex(0)
{}
position_t posx;
position_t posy;
force_t forcex;
};
force_t gforcex(position_t a_x, position_t a_y, position_t b_x, position_t b_y) {
return 1.0 / std::sqrt(std::pow(a_x - b_x, 2) + std::pow(a_y - b_y, 2));
}
int main() {
Planet planet[] = {
{1, 2},
{3, 4},
{-1, -2},
{-3, -4}
};
for (auto& p : planet) {
p.forcex = std::accumulate(
std::begin(planet),
std::end(planet),
force_t(0),
[&](const force_t& force, const Planet& other) {
if (&p == &other) return force;
else return force + gforcex(p.posx, p.posy, other.posx, other.posy);
}
);
}
for (int i = 0; i < sizeof(planet)/sizeof(planet[0]); ++i) {
std::cout << "Planet " << i << " forcex: " << planet[i].forcex << "\n";
}
}
This assumes that your planet
container is full of objects of type Planet
.
You'll have to #include <numeric>
for std::accumulate
and you'll need #include <iterator>
for std::begin
and std::end
, depending on what type planet
is. If planet
is a standard container std::vector<Planet>
or std::array<Planet, N>
, then planet.begin()
and planet.end()
work as well.
I recommend calling planet
planets
, since that's more accurate.
I recommend changing your gforcex
function signature to force_t gforcex(const Planet& a, const Planet& b);
I recommend using a standard library container for planet
(s
) (probably std::vector<Planet>
, but std::array<Planet, N>
would be fine too) instead of an array if you're currently using an array.
Upvotes: 1
Reputation: 60308
Here's a simple solution:
planet[1].forcex = 0;
for (int i : {2, 3, 4})
planet[1].forcex +=
gforcex(planet[1].posx, planet[1].posy, planet[i].posx, planet[i].posy);
Upvotes: 2