31 #if defined(MPolynomialReader_RECURSES)
32 #error Recursive header files inclusion detected in MPolynomialReader.h
33 #else // defined(MPolynomialReader_RECURSES)
35 #define MPolynomialReader_RECURSES
37 #if !defined MPolynomialReader_h
39 #define MPolynomialReader_h
44 #include "DGtal/base/Common.h"
45 #include "DGtal/math/MPolynomial.h"
46 #include <boost/spirit/include/qi.hpp>
47 #include <boost/spirit/include/phoenix_core.hpp>
48 #include <boost/spirit/include/phoenix_operator.hpp>
49 #include <boost/spirit/include/phoenix_fusion.hpp>
50 #include <boost/spirit/include/phoenix_stl.hpp>
51 #include <boost/fusion/include/adapt_struct.hpp>
52 #include <boost/variant/recursive_variant.hpp>
72 struct monomial_node {
74 std::vector<power_node> powers;
86 boost::variant< boost::recursive_wrapper<top_node>, monomial_node >
94 std::vector<char> ops;
95 std::vector<expr_node> expressions;
107 BOOST_FUSION_ADAPT_STRUCT(
108 DGtal::detail::power_node,
117 BOOST_FUSION_ADAPT_STRUCT(
118 DGtal::detail::monomial_node,
120 (std::vector<DGtal::detail::power_node>, powers)
127 BOOST_FUSION_ADAPT_STRUCT(
128 DGtal::detail::top_node,
129 (std::vector<
char>, ops)
130 (std::vector<DGtal::detail::expr_node>, expressions)
136 namespace qi = boost::spirit::qi;
137 namespace ascii = boost::spirit::ascii;
138 namespace phoenix = boost::phoenix;
147 template <
typename Iterator>
148 struct MPolynomialGrammar
149 : qi::grammar<Iterator, detail::top_node(), ascii::space_type>
152 : MPolynomialGrammar::base_type(top)
161 using phoenix::push_back;
164 mulexpr [push_back(at_c<1>(_val), _1)]
165 >> *( ( lit(
'+') [ push_back(at_c<0>(_val),
'+') ]
166 >> mulexpr [push_back(at_c<1>(_val), _1)] )
167 | ( ( lit(
'-') [ push_back(at_c<0>(_val),
'-') ]
168 >> mulexpr [push_back(at_c<1>(_val), _1)] ) ) );
171 subexpr [push_back(at_c<1>(_val), _1)]
172 >> *( ( lit(
'*') [ push_back(at_c<0>(_val),
'*') ]
173 >> mulexpr [push_back(at_c<1>(_val), _1)] ) );
180 lit(
'(') [ push_back(at_c<0>(_val),
'^') ]
181 >> top [ push_back(at_c<1>(_val), _1) ]
183 >> ( ( lit(
'^') >> int_ [ at_c<2>(_val) = _1 ] )
184 | eps [ at_c<2>(_val) = 1 ] ) ;
187 ( double_ [at_c<0>(_val) = _1]
188 >> *( genvariable [push_back(at_c<1>(_val), _1)] ) )
189 | +( genvariable [push_back(at_c<1>(_val), _1)]
190 >> eps [at_c<0>(_val) = 1] );
193 litvariable | variable;
196 >> int_ [at_c<0>(_val) = _1]
197 >> ( ( lit(
'^') >> int_ [at_c<1>(_val) = _1] )
198 | eps [at_c<1>(_val) = 1]
201 ( lit(
'x') [at_c<0>(_val) = 0]
202 | lit(
'y') [at_c<0>(_val) = 1]
203 | lit(
'z') [at_c<0>(_val) = 2]
204 | lit(
't') [at_c<0>(_val) = 3] )
205 >> ( ( lit(
'^') >> int_ [at_c<1>(_val) = _1] )
206 | eps [at_c<1>(_val) = 1]
212 qi::rule<Iterator, detail::top_node(), ascii::space_type> top;
213 qi::rule<Iterator, detail::top_node(), ascii::space_type> mulexpr;
214 qi::rule<Iterator, detail::expr_node(), ascii::space_type> subexpr;
215 qi::rule<Iterator, detail::top_node(), ascii::space_type> expexpr;
216 qi::rule<Iterator, detail::monomial_node(), ascii::space_type> monomial;
217 qi::rule<Iterator, detail::power_node(), ascii::space_type> variable;
218 qi::rule<Iterator, detail::power_node(), ascii::space_type> genvariable;
219 qi::rule<Iterator, detail::power_node(), ascii::space_type> litvariable;
255 template <
int n,
typename TRing,
256 typename TAlloc = std::allocator<TRing>,
257 typename TIterator = std::string::const_iterator>
258 class MPolynomialReader
262 typedef TIterator Iterator;
263 typedef TAlloc Alloc;
265 typedef MPolynomialGrammar<Iterator> Grammar;
273 MPolynomialReader() {}
284 Iterator read( Polynomial & p, Iterator begin, Iterator end )
286 using qi::phrase_parse;
289 bool r = phrase_parse( begin, end, gpolynomial, space, m );
290 if (r) p = make( m );
291 return r ? begin : end;
303 void selfDisplay ( std::ostream & out )
const;
309 bool isValid()
const;
319 Polynomial make(
const detail::power_node & pnode )
321 return Xe_k<n, Ring>( pnode.k, pnode.e );
327 Polynomial make(
const detail::monomial_node & mnode )
330 if ( mnode.powers.size() != 0 )
332 m = make( mnode.powers[ 0 ] );
333 for (
unsigned int i = 1; i < mnode.powers.size(); ++i )
334 m *= make( mnode.powers[ i ] );
338 return ( (Ring) mnode.coef ) * m;
346 struct ExprNodeMaker : boost::static_visitor<> {
348 MPolynomialReader & myPR;
349 ExprNodeMaker( MPolynomialReader & reader )
352 void operator()(
const detail::monomial_node & mnode)
354 myP = myPR.make( mnode );
356 void operator()(
const detail::top_node & topnode)
358 myP = myPR.make( topnode );
366 Polynomial make(
const detail::top_node & topnode )
368 ASSERT( ! topnode.expressions.empty() );
370 ExprNodeMaker emaker( *
this );
371 if ( topnode.ops.empty() )
374 boost::apply_visitor( emaker, topnode.expressions[ 0 ] );
377 else if ( topnode.ops[ 0 ] ==
'^' )
380 boost::apply_visitor( emaker, topnode.expressions[ 0 ] );
382 for (
unsigned int i = 1; i <= (
unsigned int)topnode.exp; ++i )
389 boost::apply_visitor( emaker, topnode.expressions[ 0 ] );
391 for (
unsigned int i = 0; i < (
unsigned int)topnode.ops.size(); ++i )
393 boost::apply_visitor( emaker, topnode.expressions[ i+1 ] );
394 switch ( topnode.ops[ i ] ) {
395 case '+': p += emaker.myP;
break;
396 case '-': p -= emaker.myP;
break;
397 case '*': p *= emaker.myP;
break;
398 default: std::cerr <<
"[UNKNOWN-node]" << topnode.ops[ i ] << std::endl;
422 template <
int n,
typename TRing,
typename TAlloc,
typename TIterator>
425 const MPolynomialReader<n, TRing, TAlloc, TIterator> &
object );
454 template <
int n,
typename TRing,
class TAlloc >
464 #include "DGtal/io/readers/MPolynomialReader.ih"
469 #endif // !defined MPolynomialReader_h
471 #undef MPolynomialReader_RECURSES
472 #endif // else defined(MPolynomialReader_RECURSES)