line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------- |
2
|
|
|
|
|
|
|
| Copyright (c) 2013-2017, Nucleic Development Team. |
3
|
|
|
|
|
|
|
| |
4
|
|
|
|
|
|
|
| Distributed under the terms of the Modified BSD License. |
5
|
|
|
|
|
|
|
| |
6
|
|
|
|
|
|
|
| The full license is in the file LICENSE, distributed with this software. |
7
|
|
|
|
|
|
|
|----------------------------------------------------------------------------*/ |
8
|
|
|
|
|
|
|
#pragma once |
9
|
|
|
|
|
|
|
#include "maptype.h" |
10
|
|
|
|
|
|
|
#include "symbol.h" |
11
|
|
|
|
|
|
|
#include "util.h" |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
namespace kiwi |
14
|
|
|
|
|
|
|
{ |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
namespace impl |
17
|
|
|
|
|
|
|
{ |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
class Row |
20
|
|
|
|
|
|
|
{ |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
public: |
23
|
|
|
|
|
|
|
using CellMap = MapType<Symbol, double>; |
24
|
|
|
|
|
|
|
|
25
|
10
|
|
|
|
|
|
Row() : Row(0.0) {} |
26
|
|
|
|
|
|
|
|
27
|
3221
|
50
|
|
|
|
|
Row(double constant) : m_constant(constant) {} |
28
|
|
|
|
|
|
|
|
29
|
1660
|
|
|
|
|
|
Row(const Row &other) = default; |
30
|
|
|
|
|
|
|
|
31
|
8102
|
|
|
|
|
|
~Row() = default; |
32
|
|
|
|
|
|
|
|
33
|
15214
|
|
|
|
|
|
const CellMap &cells() const |
34
|
|
|
|
|
|
|
{ |
35
|
15214
|
|
|
|
|
|
return m_cells; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
1021717
|
|
|
|
|
|
double constant() const |
39
|
|
|
|
|
|
|
{ |
40
|
1021717
|
|
|
|
|
|
return m_constant; |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
/* Add a constant value to the row constant. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
The new value of the constant is returned. |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
*/ |
48
|
1832
|
|
|
|
|
|
double add(double value) |
49
|
|
|
|
|
|
|
{ |
50
|
1832
|
|
|
|
|
|
return m_constant += value; |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
/* Insert a symbol into the row with a given coefficient. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
If the symbol already exists in the row, the coefficient will be |
56
|
|
|
|
|
|
|
added to the existing coefficient. If the resulting coefficient |
57
|
|
|
|
|
|
|
is zero, the symbol will be removed from the row. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
*/ |
60
|
16810
|
|
|
|
|
|
void insert(const Symbol &symbol, double coefficient = 1.0) |
61
|
|
|
|
|
|
|
{ |
62
|
16810
|
50
|
|
|
|
|
if (nearZero(m_cells[symbol] += coefficient)) |
63
|
0
|
|
|
|
|
|
m_cells.erase(symbol); |
64
|
16810
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
/* Insert a row into this row with a given coefficient. |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
The constant and the cells of the other row will be multiplied by |
69
|
|
|
|
|
|
|
the coefficient and added to this row. Any cell with a resulting |
70
|
|
|
|
|
|
|
coefficient of zero will be removed from the row. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
*/ |
73
|
1225667
|
|
|
|
|
|
void insert(const Row &other, double coefficient = 1.0) |
74
|
|
|
|
|
|
|
{ |
75
|
1225667
|
|
|
|
|
|
m_constant += other.m_constant * coefficient; |
76
|
|
|
|
|
|
|
|
77
|
10784308
|
100
|
|
|
|
|
for (const auto & cellPair : other.m_cells) |
78
|
|
|
|
|
|
|
{ |
79
|
9558641
|
|
|
|
|
|
double coeff = cellPair.second * coefficient; |
80
|
9558641
|
50
|
|
|
|
|
if (nearZero(m_cells[cellPair.first] += coeff)) |
|
|
100
|
|
|
|
|
|
81
|
3538214
|
50
|
|
|
|
|
m_cells.erase(cellPair.first); |
82
|
|
|
|
|
|
|
} |
83
|
1225667
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
/* Remove the given symbol from the row. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
*/ |
88
|
172254
|
|
|
|
|
|
void remove(const Symbol &symbol) |
89
|
|
|
|
|
|
|
{ |
90
|
172254
|
50
|
|
|
|
|
auto it = m_cells.find(symbol); |
91
|
172254
|
100
|
|
|
|
|
if (it != m_cells.end()) |
92
|
24289
|
50
|
|
|
|
|
m_cells.erase(it); |
93
|
172254
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
/* Reverse the sign of the constant and all cells in the row. |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
*/ |
98
|
578
|
|
|
|
|
|
void reverseSign() |
99
|
|
|
|
|
|
|
{ |
100
|
578
|
|
|
|
|
|
m_constant = -m_constant; |
101
|
3510
|
100
|
|
|
|
|
for (auto &cellPair : m_cells) |
102
|
2932
|
|
|
|
|
|
cellPair.second = -cellPair.second; |
103
|
578
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
/* Solve the row for the given symbol. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
This method assumes the row is of the form a * x + b * y + c = 0 |
108
|
|
|
|
|
|
|
and (assuming solve for x) will modify the row to represent the |
109
|
|
|
|
|
|
|
right hand side of x = -b/a * y - c / a. The target symbol will |
110
|
|
|
|
|
|
|
be removed from the row, and the constant and other cells will |
111
|
|
|
|
|
|
|
be multiplied by the negative inverse of the target coefficient. |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
The given symbol *must* exist in the row. |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
*/ |
116
|
10753
|
|
|
|
|
|
void solveFor(const Symbol &symbol) |
117
|
|
|
|
|
|
|
{ |
118
|
10753
|
|
|
|
|
|
double coeff = -1.0 / m_cells[symbol]; |
119
|
10753
|
|
|
|
|
|
m_cells.erase(symbol); |
120
|
10753
|
|
|
|
|
|
m_constant *= coeff; |
121
|
112817
|
100
|
|
|
|
|
for (auto &cellPair : m_cells) |
122
|
102064
|
|
|
|
|
|
cellPair.second *= coeff; |
123
|
10753
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
/* Solve the row for the given symbols. |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
This method assumes the row is of the form x = b * y + c and will |
128
|
|
|
|
|
|
|
solve the row such that y = x / b - c / b. The rhs symbol will be |
129
|
|
|
|
|
|
|
removed from the row, the lhs added, and the result divided by the |
130
|
|
|
|
|
|
|
negative inverse of the rhs coefficient. |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
The lhs symbol *must not* exist in the row, and the rhs symbol |
133
|
|
|
|
|
|
|
*must* exist in the row. |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
*/ |
136
|
7952
|
|
|
|
|
|
void solveFor(const Symbol &lhs, const Symbol &rhs) |
137
|
|
|
|
|
|
|
{ |
138
|
7952
|
|
|
|
|
|
insert(lhs, -1.0); |
139
|
7952
|
|
|
|
|
|
solveFor(rhs); |
140
|
7952
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
/* Get the coefficient for the given symbol. |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
If the symbol does not exist in the row, zero will be returned. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
*/ |
147
|
952848
|
|
|
|
|
|
double coefficientFor(const Symbol &symbol) const |
148
|
|
|
|
|
|
|
{ |
149
|
952848
|
50
|
|
|
|
|
CellMap::const_iterator it = m_cells.find(symbol); |
150
|
952848
|
100
|
|
|
|
|
if (it == m_cells.end()) |
151
|
587894
|
|
|
|
|
|
return 0.0; |
152
|
952848
|
|
|
|
|
|
return it->second; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
/* Substitute a symbol with the data from another row. |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
Given a row of the form a * x + b and a substitution of the |
158
|
|
|
|
|
|
|
form x = 3 * y + c the row will be updated to reflect the |
159
|
|
|
|
|
|
|
expression 3 * a * y + a * c + b. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
If the symbol does not exist in the row, this is a no-op. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
*/ |
164
|
3078111
|
|
|
|
|
|
void substitute(const Symbol &symbol, const Row &row) |
165
|
|
|
|
|
|
|
{ |
166
|
3078111
|
50
|
|
|
|
|
auto it = m_cells.find(symbol); |
167
|
3078111
|
100
|
|
|
|
|
if (it != m_cells.end()) |
168
|
|
|
|
|
|
|
{ |
169
|
1223028
|
|
|
|
|
|
double coefficient = it->second; |
170
|
1223028
|
50
|
|
|
|
|
m_cells.erase(it); |
171
|
1223028
|
50
|
|
|
|
|
insert(row, coefficient); |
172
|
|
|
|
|
|
|
} |
173
|
3078111
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
private: |
176
|
|
|
|
|
|
|
CellMap m_cells; |
177
|
|
|
|
|
|
|
double m_constant; |
178
|
|
|
|
|
|
|
}; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
} // namespace impl |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
} // namespace kiwi |