5
5
namespace MR
6
6
{
7
7
8
- template <typename C, typename D>
8
+ template <typename C, typename D, D M >
9
9
class SparsePolynomial ;
10
- template <typename C, typename D>
11
- SparsePolynomial<C,D> operator *( const SparsePolynomial<C,D>& a, const SparsePolynomial<C,D>& b );
10
+ template <typename C, typename D, D M >
11
+ SparsePolynomial<C,D,M > operator *( const SparsePolynomial<C,D,M >& a, const SparsePolynomial<C,D,M >& b );
12
12
13
13
// / The class to store a polynomial with a large number of zero coefficient (only non-zeros are stored in std::map)
14
14
// / \tparam C - type of coefficients
15
15
// / \tparam D - type of degrees
16
- template <typename C, typename D = int >
16
+ // / \tparam M - maximum degree to store in the polynomial
17
+ template <typename C, typename D, D M>
17
18
class SparsePolynomial
18
19
{
20
+ static_assert ( M > 0 );
19
21
public:
20
22
// / constructs zero polynomial
21
23
SparsePolynomial () = default ;
@@ -29,8 +31,14 @@ class SparsePolynomial
29
31
// / constructs polynomial c0 + c1*x^d1 + c2*x^d2
30
32
SparsePolynomial ( C c0, D d1, C c1, D d2, C c2 );
31
33
34
+ // / returns true if no single polynomial coefficient is defined
35
+ [[nodiscard]] bool empty () const { return map_.empty (); }
36
+
37
+ // / returns true if the coefficient for the smallest not-zero degress is positive
38
+ [[nodiscard]] bool isPositive () const ;
39
+
32
40
// / gets read-only access to all not-zero coefficients
33
- const std::map<D, C> & get () const { return map_; }
41
+ [[nodiscard]] const std::map<D, C> & get () const { return map_; }
34
42
35
43
SparsePolynomial& operator +=( const SparsePolynomial& b );
36
44
SparsePolynomial& operator -=( const SparsePolynomial& b );
@@ -40,27 +48,31 @@ class SparsePolynomial
40
48
std::map<D, C> map_; // degree -> not-zero coefficient
41
49
};
42
50
43
- template <typename C, typename D>
44
- SparsePolynomial<C,D>::SparsePolynomial( std::map<D, C> && m ) : map_( std::move( m ) )
51
+ template <typename C, typename D, D M >
52
+ SparsePolynomial<C,D,M >::SparsePolynomial( std::map<D, C> && m ) : map_( std::move( m ) )
45
53
{
46
54
#ifndef NDEBUG
47
55
for ( const auto & [deg, cf] : map_ )
56
+ {
57
+ assert ( deg <= M );
48
58
assert ( cf != 0 );
59
+ }
49
60
#endif
50
61
}
51
62
52
- template <typename C, typename D>
53
- SparsePolynomial<C,D>::SparsePolynomial( C c0, D d1, C c1 )
63
+ template <typename C, typename D, D M >
64
+ SparsePolynomial<C,D,M >::SparsePolynomial( C c0, D d1, C c1 )
54
65
{
55
66
assert ( c1 != 0 );
56
67
assert ( d1 != 0 );
57
68
if ( c0 != 0 )
58
69
map_[D (0 )] = c0;
59
- map_[d1] = c1;
70
+ if ( d1 <= M )
71
+ map_[d1] = c1;
60
72
}
61
73
62
- template <typename C, typename D>
63
- SparsePolynomial<C,D>::SparsePolynomial( C c0, D d1, C c1, D d2, C c2 )
74
+ template <typename C, typename D, D M >
75
+ SparsePolynomial<C,D,M >::SparsePolynomial( C c0, D d1, C c1, D d2, C c2 )
64
76
{
65
77
assert ( c1 != 0 );
66
78
assert ( d1 != 0 );
@@ -69,12 +81,24 @@ SparsePolynomial<C,D>::SparsePolynomial( C c0, D d1, C c1, D d2, C c2 )
69
81
assert ( d1 != d2 );
70
82
if ( c0 != 0 )
71
83
map_[D (0 )] = c0;
72
- map_[d1] = c1;
73
- map_[d2] = c2;
84
+ if ( d1 <= M )
85
+ map_[d1] = c1;
86
+ if ( d2 <= M )
87
+ map_[d2] = c2;
88
+ }
89
+
90
+ template <typename C, typename D, D M>
91
+ bool SparsePolynomial<C,D,M>::isPositive() const
92
+ {
93
+ if ( !map_.empty () )
94
+ return map_.begin ()->second > 0 ;
95
+
96
+ assert (false );
97
+ return false ;
74
98
}
75
99
76
- template <typename C, typename D>
77
- SparsePolynomial<C,D>& SparsePolynomial<C,D>::operator +=( const SparsePolynomial& b )
100
+ template <typename C, typename D, D M >
101
+ SparsePolynomial<C,D,M >& SparsePolynomial<C,D,M >::operator +=( const SparsePolynomial& b )
78
102
{
79
103
for ( const auto & [degB, cfB] : b.map_ )
80
104
{
@@ -92,8 +116,8 @@ SparsePolynomial<C,D>& SparsePolynomial<C,D>::operator +=( const SparsePolynomia
92
116
return * this ;
93
117
}
94
118
95
- template <typename C, typename D>
96
- SparsePolynomial<C,D>& SparsePolynomial<C,D>::operator -=( const SparsePolynomial& b )
119
+ template <typename C, typename D, D M >
120
+ SparsePolynomial<C,D,M >& SparsePolynomial<C,D,M >::operator -=( const SparsePolynomial& b )
97
121
{
98
122
for ( const auto & [degB, cfB] : b.map_ )
99
123
{
@@ -111,8 +135,8 @@ SparsePolynomial<C,D>& SparsePolynomial<C,D>::operator -=( const SparsePolynomia
111
135
return * this ;
112
136
}
113
137
114
- template <typename C, typename D>
115
- SparsePolynomial<C,D> operator *( const SparsePolynomial<C,D>& a, const SparsePolynomial<C,D>& b )
138
+ template <typename C, typename D, D M >
139
+ [[nodiscard]] SparsePolynomial<C,D,M > operator *( const SparsePolynomial<C,D,M >& a, const SparsePolynomial<C,D,M >& b )
116
140
{
117
141
std::map<D,C> resMap;
118
142
for ( const auto & [degA, cfA] : a.map_ )
@@ -122,6 +146,8 @@ SparsePolynomial<C,D> operator *( const SparsePolynomial<C,D>& a, const SparsePo
122
146
{
123
147
assert ( cfB != 0 );
124
148
const auto deg = degA + degB;
149
+ if ( deg > M )
150
+ break ;
125
151
const auto cf = cfA * cfB;
126
152
auto [it,inserted] = resMap.insert ( { deg, cf } );
127
153
if ( !inserted )
0 commit comments