1
+ #include < cstdint>
2
+ #include < iostream>
3
+ #include < vector>
4
+ //
5
+ [[nodiscard]] constexpr auto factorial (std::size_t val) -> std::size_t {
6
+ if (val <= 1 ) {
7
+ return 1 ;
8
+ }
9
+ return val * factorial (val - 1 );
10
+ }
11
+ //
12
+ // / @brief performs Newton's Forward Difference Formula on two dynamic
13
+ // / containers
14
+ // / @param xi container
15
+ // / @param yi container
16
+ // / @param x [by default it's `1`]
17
+ // / @return Ty
18
+ template <class Ty , class Cont >
19
+ [[nodiscard]] auto newton_forward (const Cont &xi, Cont &yi, const Ty x) -> Ty {
20
+ Cont forward{yi[0 ]}; // holds forward difference of `yi` init = yi[0]
21
+ std::size_t size{yi.size ()};
22
+ //
23
+ for (std::size_t i{}; i < size;
24
+ ++i) { // calculates forward difference of `yi`
25
+ Cont temp{};
26
+ for (std::size_t j{1 }; j < size; ++j) {
27
+ temp.push_back (yi[j - 1 ] = (yi[j] - yi[j - 1 ]));
28
+ if (j == yi.size () - 1 ) {
29
+ yi.erase (yi.begin () + static_cast <int64_t >(size - 1 ));
30
+ }
31
+ }
32
+ size = temp.size ();
33
+ forward.push_back (temp[0 ]);
34
+ }
35
+ forward.push_back (yi[0 ] = yi[1 ] - yi[0 ]);
36
+ const auto cal_u = [](const Ty u, const std::size_t times) -> Ty {
37
+ Ty result{u};
38
+ for (std::size_t i{1 }; i < times; ++i) {
39
+ result *= u - static_cast <Ty>(i);
40
+ }
41
+ return result;
42
+ };
43
+ const Ty u{(x - xi[0 ]) / (xi[1 ] - xi[0 ])};
44
+ Ty y{(forward[0 ])};
45
+ //
46
+ for (std::size_t i{1 }; i < xi.size (); ++i) {
47
+ y = y + (cal_u (u, i) * (forward[i])) / static_cast <Ty>(factorial (i));
48
+ }
49
+ return y;
50
+ }
51
+ //
52
+ auto main () -> int {
53
+ std::vector<float > xi{1891 , 1901 , 1911 , 1921 , 1931 };
54
+ std::vector<float > yi{46 , 66 , 81 , 93 , 101 };
55
+ std::cout << newton_forward (xi, yi, 1 .) << ' \n ' ;
56
+ }
0 commit comments