GetFEM++  5.3
bgeot_poly.cc
1 /*===========================================================================
2 
3  Copyright (C) 2000-2017 Yves Renard
4 
5  This file is a part of GetFEM++
6 
7  GetFEM++ is free software; you can redistribute it and/or modify it
8  under the terms of the GNU Lesser General Public License as published
9  by the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version along with the GCC Runtime Library
11  Exception either version 3.1 or (at your option) any later version.
12  This program is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15  License and GCC Runtime Library Exception for more details.
16  You should have received a copy of the GNU Lesser General Public License
17  along with this program; if not, write to the Free Software Foundation,
18  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20 ===========================================================================*/
21 
22 
23 
24 #include "getfem/bgeot_poly.h"
26 #include "getfem/bgeot_ftool.h"
27 
28 namespace bgeot {
29 
30 #define STORED 150
31  static gmm::dense_matrix<size_type> alpha_M_(STORED, STORED);
32  static void alpha_init_() {
33  static bool init = false;
34  if (!init) {
35  for (short_type i = 0; i < STORED; ++i) {
36  alpha_M_(i, 0) = alpha_M_(0, i) = 1;
37  for (short_type j = 1; j <= i; ++j)
38  alpha_M_(i,j) = alpha_M_(j,i) = (alpha_M_(i, j-1) * (i+j)) / j;
39  }
40  init = true;
41  }
42  }
43  static inline size_type alpha_(short_type n, short_type d)
44  { return alpha_M_(d,n); }
45 
47  alpha_init_();
48  GMM_ASSERT1(n < STORED && d < STORED,
49  "alpha called with n = " << n << " and d = " << d);
50  return alpha_(n,d);
51  }
52 
54  short_type n = short_type(size()), l;
55  if (n > 0) {
56  size_type g_idx = global_index_; short_type deg = degree_;
57  reverse_iterator it = rbegin() + 1;
58  for (l = short_type(n-2); l != short_type(-1); --l, ++it)
59  if (*it != 0) break;
60  short_type a = (*this)[n-1]; (*this)[n-1] = 0;
61  (*this)[short_type(l+1)] = short_type(a + 1);
62  if (l != short_type(-1)) ((*this)[l])--;
63  else if (short_type(deg+1)) degree_ = short_type(deg+1);
64  if (g_idx+1) global_index_ = g_idx+1;
65  //degree_ = short_type(-1);
66  }
67  return *this;
68  }
69 
71  short_type n = short_type(size()), l;
72  if (n > 0) {
73  size_type g_idx = global_index_; short_type deg = degree_;
74  reverse_iterator it = rbegin();
75  for (l = short_type(n-1); l != short_type(-1); --l, ++it) {
76  if (*it != 0) break;
77  }
78  if (l != short_type(-1)) {
79  short_type a = (*this)[l];
80  (*this)[l] = 0; (*this)[n-1] = short_type(a - 1);
81  if (l > 0) ((*this)[l-1])++;
82  else if (short_type(deg+1)) degree_ = short_type(deg-1);
83  }
84  if (g_idx+1) global_index_ = g_idx-1;
85  }
86  return *this;
87  }
88 
90  if (degree_ != short_type(-1)) return degree_;
91  degree_ = short_type(std::accumulate(begin(), end(), 0));
92  return degree_;
93  }
94 
96  if (global_index_ != size_type(-1)) return global_index_;
97  short_type d = degree(), n = short_type(size());
98  global_index_ = 0;
99  const_iterator it = begin(), ite = end();
100  for ( ; it != ite && d > 0; ++it)
101  { global_index_ += alpha_(n,short_type(d-1)); d=short_type(d-*it); --n; }
102  return global_index_;
103  }
104 
105  power_index::power_index(short_type nn) : v(nn), degree_(0), global_index_(0)
106  { std::fill(begin(), end(), short_type(0)); alpha_init_(); }
107 
108 
109  // functions to read a polynomial on a stream
110 
111  static void parse_error(int i)
112  { GMM_ASSERT1(false, "Syntax error reading a polynomial " << i); }
113 
114  static std::string stored_s;
115  int stored_tokent;
116 
117  static void unget_token(int i, std::string s)
118  { std::swap(s, stored_s); stored_tokent = i; }
119 
120  static int get_next_token(std::string &s, std::istream &f) {
121  if (stored_s.size() == 0) {
122  int r = get_token(f, s, true, false, false);
123  return r;
124  }
125  else { s.clear(); std::swap(s, stored_s); return stored_tokent; }
126  }
127 
128  static base_poly read_expression(short_type n, std::istream &f) {
129  gmm::stream_standard_locale sl(f);
131  base_poly result(n,0);
132  std::string s;
133  int i = get_next_token(s, f), j;
134  switch (i) {
135  case 2 : result.one();
136  result *= opt_long_scalar_type(::strtod(s.c_str(), 0));
137  break;
138  case 4 :
139  if (s == "x") result = base_poly(n, 1, 0);
140  else if (s == "y" && n > 1) result = base_poly(n, 1, 1);
141  else if (s == "z" && n > 2) result = base_poly(n, 1, 2);
142  else if (s == "w" && n > 3) result = base_poly(n, 1, 3);
143  else if (s == "v" && n > 4) result = base_poly(n, 1, 4);
144  else if (s == "u" && n > 5) result = base_poly(n, 1, 5);
145  else if (s == "t" && n > 6) result = base_poly(n, 1, 6);
146  else if (s == "sqrt") {
147  base_poly p = read_expression(n, f);
148  if (p.degree() > 0) parse_error(1);
149  result.one(); result *= sqrt(p[0]);
150  }
151  else { parse_error(2); }
152  break;
153  case 5 :
154  switch (s[0]) {
155  case '(' :
156  result = read_base_poly(n, f);
157  j = get_next_token(s, f);
158  if (j != 5 || s[0] != ')') parse_error(3);
159  break;
160  default : parse_error(4);
161  }
162  break;
163  default : parse_error(5);
164  }
165  return result;
166  }
167 
168  static void operator_priority_(int i, char c, int &prior, int &op) {
169  if (i == 5)
170  switch (c) {
171  case '*' : prior = 2; op = 1; return;
172  case '/' : prior = 2; op = 2; return;
173  case '+' : prior = 3; op = 3; return;
174  case '-' : prior = 3; op = 4; return;
175  case '^' : prior = 1; op = 5; return;
176  }
177  prior = op = 0;
178  }
179 
180  void do_bin_op(std::vector<base_poly> &value_list,
181  std::vector<int> &op_list,
182  std::vector<int> &prior_list) {
183  base_poly &p2 = *(value_list.rbegin());
184  if (op_list.back() != 6) {
185  assert(value_list.size()>1);
186  base_poly &p1 = *(value_list.rbegin()+1);
187  switch (op_list.back()) {
188  case 1 : p1 *= p2; break;
189  case 2 : if (p2.degree() > 0) parse_error(6); p1 /= p2[0]; break;
190  case 3 : p1 += p2; break;
191  case 4 : p1 -= p2; break;
192  case 5 :
193  {
194  if (p2.degree() > 0) parse_error(7);
195  int pow = int(to_scalar(p2[0]));
196  if (p2[0] != opt_long_scalar_type(pow) || pow < 0) parse_error(8);
197  base_poly p = p1; p1.one();
198  for (int i = 0; i < pow; ++i) p1 *= p;
199  }
200  break;
201  default: assert(0);
202  }
203  value_list.pop_back();
204  } else {
205  p2 *= opt_long_scalar_type(-1);
206  }
207  op_list.pop_back(); prior_list.pop_back();
208  }
209 
210  base_poly read_base_poly(short_type n, std::istream &f) {
211  std::vector<base_poly> value_list;
212  std::string s;
213  std::vector<int> op_list, prior_list;
214 
215  int i = get_next_token(s, f), prior, op;
216  if (i == 5 && s[0] == '-')
217  { op_list.push_back(6); prior_list.push_back(2); }
218  else if (i == 5 && s[0] == '+') ;
219  else unget_token(i, s);
220 
221  value_list.push_back(read_expression(n, f));
222  i = get_next_token(s, f);
223  operator_priority_(i, i ? s[0] : '0', prior, op);
224  while (op) {
225  while (!prior_list.empty() && prior_list.back() <= prior)
226  do_bin_op(value_list, op_list, prior_list);
227 
228  value_list.push_back(read_expression(n, f));
229  op_list.push_back(op);
230  prior_list.push_back(prior);
231 
232  i = get_next_token(s, f);
233  operator_priority_(i, i ? s[0] : '0', prior, op);
234  }
235 
236  if (i == 5 && s[0] == ')') { f.putback(')'); }
237  else if (i != 0 && (i != 5 || s[0] != ';')) {
238  cout << "s = " << s << endl;
239  parse_error(9);
240  }
241 
242  while (!prior_list.empty()) do_bin_op(value_list, op_list, prior_list);
243 
244  return value_list[0];
245  }
246 
247  base_poly read_base_poly(short_type n, const std::string &s) {
248  std::stringstream f(s);
249  return read_base_poly(n, f);
250  }
251 
252 
253 } /* end of namespace bgeot. */
Small (dim < 8) vectors.
base_poly read_base_poly(short_type n, std::istream &f)
read a base_poly on the stream ist.
Definition: bgeot_poly.cc:210
const power_index & operator--()
Gives the next previous index.
Definition: bgeot_poly.cc:70
void one()
Makes P = 1.
Definition: bgeot_poly.h:242
Multivariate polynomials.
int get_token(std::istream &ist, std::string &st, bool ignore_cr, bool to_up, bool read_un_pm, int *linenb)
Very simple lexical analysis of general interest for reading small langages with a "MATLAB like" synt...
Definition: bgeot_ftool.cc:49
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
Vector of integer (16 bits type) which represent the powers of a monomial.
Definition: bgeot_poly.h:64
const power_index & operator++()
Gives the next power index.
Definition: bgeot_poly.cc:53
this is the above solutions for linux, but it still needs to be tested.
Definition: gmm_std.h:238
power_index()
Constructor.
Definition: bgeot_poly.h:108
gmm::uint16_type short_type
used as the common short type integer in the library
Definition: bgeot_config.h:79
"File Tools"
short_type degree() const
Gives the degree of the polynomial.
Definition: bgeot_poly.h:193
Basic Geometric Tools.
size_type alpha(short_type n, short_type d)
Return the value of which is the number of monomials of a polynomial of variables and degree ...
Definition: bgeot_poly.cc:46
size_type global_index() const
Gives the global number of the index (i.e.
Definition: bgeot_poly.cc:95
short_type degree() const
Gives the degree.
Definition: bgeot_poly.cc:89