summaryrefslogtreecommitdiff
path: root/src/VDM.cc
blob: 0f6cc3d444bc67dc484aba633ee4c28e4ab591cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <VDM.h>

int choose_pivot(bigrational_matrix& X, const unsigned long diag_num)
{
  assert(X.get_num_row() == X.get_num_col());
  assert(X.get_num_row() > diag_num);
  
  unsigned long i, j, k;
  unsigned long ord = X.get_num_row();
  int           c;
  bigrational   y;
  
  //  1. Find a pivot X(i, j).
  
  c = 1;
  i = j = diag_num;
  
  while (c && i < ord)
  {
    while (c && j < ord)
      if (X(i, j) != 0)
        c = 0;
      else
        j++;
    
    if (c)
    {
      i++;
      j = diag_num;
    }
  }
  
  assert(!c);
  assert(i < ord && j < ord);
  
  //  2. Interchange column diag_num and column j.
  
  if (j != diag_num)
    for (k = 0; k < ord; k++)
    {
      y              = X(k, diag_num);
      X(k, diag_num) = X(k, j);
      X(k, j)        = y;
    }
  
  //  3. Interchange row diag_num and row i.
  
  if (i != diag_num)
    for (k = diag_num; k < ord; k++)
    {
      y              = X(diag_num, k);
      X(diag_num, k) = X(i, k);
      X(i, k)        = y;
    }
  
  return 0;
}

bigrational_vector Solve_VDM_GE(const bigrational_vector& Val,
                                const bigrational_vector& RHS)
{
  assert(Val.get_dim() == RHS.get_dim());
  
  long               i, j;
  unsigned long      k;
  unsigned long      ord = Val.get_dim();
  bigrational_matrix VDM(ord, ord);
  bigrational        f;
  bigrational_vector Sol(ord);
  
  //  1. Setup Vandermonte matrix VDM and initialize the solution vector Sol.
  
  for (i = 0; i < ord; i++)
  {
    VDM(i, 0) = 1;
    Sol[i]    = RHS[i];
  }
  
  for (i = 0; i < ord; i++)
    for (j = 1; j < ord; j++)
      VDM(i, j) = VDM(i, j - 1) * Val[i];
  
  //  2. Apply Gaussian elimination.
  
  //  2-1. Diagonalize the system.
  
  for (k = 0; k < ord - 1; k++)
  {
    choose_pivot(VDM, k);
    
    for (i = k + 1; i < ord; i++)
    {
      f         = VDM(i, k) / VDM(k, k);
      VDM(i, k) = 0;
      
      for (j = k + 1; j < ord; j++)
        VDM(i, j) -= f * VDM(k, j);
      
      Sol[i] -= f * Sol[k];
    }
  }
  
  assert(VDM(ord - 1, ord - 1) != 0);  //  Assert non-singularity.
  
  //  2-2. Solve the diagonal system.
  
  for (i = ord - 1; i >= 0; i--)
  {
    for (j = ord - 1; j > i; j--)
      Sol[i] -= Sol[j] * VDM(i, j);
    
    Sol[i] /= VDM(i, i);
  }
  
  return Sol;
}