Alexandria  2.27.0
SDC-CH common library for the Euclid project
multiplication.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2022 Euclid Science Ground Segment
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 3.0 of the License, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
31 #include <memory>
32 #include <set>
33 #include <vector>
34 
35 namespace Euclid {
36 namespace MathUtils {
37 
40  const auto& p1 = dynamic_cast<const Polynomial&>(f1);
41  const auto& p2 = dynamic_cast<const Polynomial&>(f2);
42  std::vector<double> c1 = p1.getCoefficients();
43  std::vector<double> c2 = p2.getCoefficients();
44  std::vector<double> resultCoef(c1.size() + c2.size() - 1, 0.);
45  for (size_t i = 0; i < c1.size(); ++i)
46  for (size_t j = 0; j < c2.size(); ++j)
47  resultCoef[i + j] += c1[i] * c2[j];
48  return make_unique<Polynomial>(std::move(resultCoef));
49 }
50 
54  const auto& piecewise = dynamic_cast<const Piecewise&>(f1);
55  const auto& interval_functions = piecewise.getFunctions();
56 
57  std::vector<std::shared_ptr<Function>> functions(interval_functions.size());
58  std::transform(interval_functions.begin(), interval_functions.end(), functions.begin(),
59  [&f2](const std::unique_ptr<Function>& original) { return multiply(*original, f2); });
60  return make_unique<Piecewise>(piecewise.getKnots(), functions);
61 }
62 
63 template <typename Iter>
64 static std::pair<Iter, Iter> overlappingStart(Iter start1, Iter end1, Iter start2, Iter end2) {
65  for (auto i1 = start1, i2 = start2; i1 != end1 && i2 != end2;) {
66  if (*i1 < *i2) {
67  ++i1;
68  if (i1 != end1 && *i1 > *i2) {
69  return {i1, i2};
70  }
71  } else {
72  ++i2;
73  if (i2 != end2 && *i1 < *i2) {
74  return {i1, i2};
75  }
76  }
77  }
78  return {end1, end2};
79 }
80 
83  std::set<double> knotSet{};
86  std::tie(p1Iter, p2Iter) = overlappingStart(knots1.begin(), knots1.end(), knots2.begin(), knots2.end());
87 
88  while (p1Iter != knots1.end() && p2Iter != knots2.end()) {
89  if (*p1Iter < *p2Iter) {
90  knotSet.insert(*p1Iter);
91  ++p1Iter;
92  } else {
93  knotSet.insert(*p2Iter);
94  ++p2Iter;
95  }
96  }
97  return std::vector<double>{knotSet.begin(), knotSet.end()};
98 }
99 
100 // Multiply two Piecewise Function%s by multiplying all their sub-functions
102  const auto& p1 = dynamic_cast<const Piecewise&>(f1);
103  const auto& p2 = dynamic_cast<const Piecewise&>(f2);
104 
105  auto knots = overlappingKnots(p1.getKnots(), p2.getKnots());
106 
107  if (knots.empty()) {
108  return make_unique<Polynomial>(std::vector<double>{0.});
109  }
110 
112  auto& p1func = p1.getFunctions();
113  auto& p2func = p2.getFunctions();
114  int i1{};
115  int i2{};
116  for (double knot : knots) {
117  if (knot == knots.back()) {
118  break;
119  }
120  while (p1.getKnots()[i1 + 1] <= knot) {
121  ++i1;
122  }
123  while (p2.getKnots()[i2 + 1] <= knot) {
124  ++i2;
125  }
126  functions.push_back(std::shared_ptr<Function>{Euclid::MathUtils::multiply(*p1func[i1], *p2func[i2]).release()});
127  }
128 
129  return make_unique<Piecewise>(knots, std::move(functions));
130 }
131 
135 
138 
139 } // namespace MathUtils
140 } // end of namespace Euclid
T begin(T... args)
Interface class representing a function with an arbitrary number of parameters.
Definition: Function.h:104
Represents a piecewise function.
Definition: Piecewise.h:87
const std::vector< std::unique_ptr< Function > > & getFunctions() const
Returns the functions in the ranges between the knots.
Definition: Piecewise.cpp:67
Represents a polynomial function.
Definition: Polynomial.h:43
T end(T... args)
T insert(T... args)
T move(T... args)
ELEMENTS_API std::map< std::pair< std::type_index, std::type_index >, MultiplyFunction > multiplySpecificSpecificMap
ELEMENTS_API std::map< std::type_index, MultiplyFunction > multiplySpecificGenericMap
std::unique_ptr< Function >(* MultiplyFunction)(const Function &, const Function &)
Alias of a function which multiplies Function objects.
std::unique_ptr< Function > multiplyPiecewiseWithGeneric(const Function &f1, const Function &f2)
std::vector< double > overlappingKnots(const std::vector< double > &knots1, const std::vector< double > &knots2)
Returns a vector of the overlapping knots from the given vectors.
std::unique_ptr< Function > multiplyPiecewises(const Function &f1, const Function &f2)
static std::pair< Iter, Iter > overlappingStart(Iter start1, Iter end1, Iter start2, Iter end2)
ELEMENTS_API std::unique_ptr< Function > multiply(const Function &f1, const Function &f2)
std::unique_ptr< Function > multiplyPolynomials(const Function &f1, const Function &f2)
Function for multiplying two Polynomials. It multiplies their coefficients.
T push_back(T... args)
T size(T... args)
T tie(T... args)
T transform(T... args)