24template<
typename ValueType>
29template<
typename ValueType>
34template<
typename ValueType>
39template<
typename ValueType>
46template<
typename ValueType>
48 localA = std::make_unique<storm::storage::SparseMatrix<ValueType>>(std::move(A));
49 this->A = localA.get();
53template<
typename ValueType>
56 viOperator = std::make_shared<helper::ValueIterationOperator<ValueType, true>>();
57 viOperator->setMatrixBackwards(*this->A);
61template<
typename ValueType>
62bool NativeLinearEquationSolver<ValueType>::solveEquationsSOR(Environment
const& env, std::vector<ValueType>& x, std::vector<ValueType>
const& b,
63 ValueType
const& omega)
const {
64 STORM_LOG_INFO(
"Solving linear equation system (" << x.size() <<
" rows) with NativeLinearEquationSolver (Gauss-Seidel, SOR omega = " << omega <<
")");
66 if (!this->cachedRowVector) {
67 this->cachedRowVector = std::make_unique<std::vector<ValueType>>(getMatrixRowCount());
70 ValueType precision = storm::utility::convertNumber<ValueType>(env.solver().native().getPrecision());
71 uint64_t maxIter = env.solver().native().getMaximalNumberOfIterations();
72 bool relative = env.solver().native().getRelativeTerminationCriterion();
75 uint_fast64_t iterations = 0;
78 this->startMeasureProgress();
80 A->performSuccessiveOverRelaxationStep(omega, x, b);
83 if (storm::utility::vector::equalModuloPrecision<ValueType>(*this->cachedRowVector, x, precision, relative)) {
88 *this->cachedRowVector = x;
92 this->showProgressIterative(iterations);
100 if (!this->isCachingEnabled()) {
104 this->reportStatus(status, iterations);
109template<
typename ValueType>
112 this->LUMatrix = std::move(decomposition.first);
113 this->DVector = std::move(decomposition.second);
117template<
typename ValueType>
118bool NativeLinearEquationSolver<ValueType>::solveEquationsJacobi(Environment
const& env, std::vector<ValueType>& x, std::vector<ValueType>
const& b)
const {
119 STORM_LOG_INFO(
"Solving linear equation system (" << x.size() <<
" rows) with NativeLinearEquationSolver (Jacobi)");
121 if (!this->cachedRowVector) {
122 this->cachedRowVector = std::make_unique<std::vector<ValueType>>(getMatrixRowCount());
126 if (!jacobiDecomposition) {
127 jacobiDecomposition = std::make_unique<JacobiDecomposition>(env, *A);
130 ValueType precision = storm::utility::convertNumber<ValueType>(env.solver().native().getPrecision());
131 uint64_t maxIter = env.solver().native().getMaximalNumberOfIterations();
132 bool relative = env.solver().native().getRelativeTerminationCriterion();
134 std::vector<ValueType>* currentX = &x;
135 std::vector<ValueType>* nextX = this->cachedRowVector.get();
138 uint_fast64_t iterations = 0;
141 this->startMeasureProgress();
144 jacobiDecomposition->multiplier->multiply(env, *currentX,
nullptr, *nextX);
149 if (storm::utility::vector::equalModuloPrecision<ValueType>(*currentX, *nextX, precision, relative)) {
153 std::swap(nextX, currentX);
156 this->showProgressIterative(iterations);
166 if (currentX == this->cachedRowVector.get()) {
167 std::swap(x, *currentX);
170 if (!this->isCachingEnabled()) {
174 this->reportStatus(status, iterations);
179template<
typename ValueType>
181 std::vector<ValueType>
const& originalB)
183 computeWalkerChaeMatrix(originalMatrix);
184 computeNewB(originalB);
185 precomputeAuxiliaryData();
189template<
typename ValueType>
193 for (
auto const& e : originalMatrix) {
194 if (e.getValue() < zero) {
195 columnsWithNegativeEntries.set(e.getColumn());
198 std::vector<uint64_t> columnsWithNegativeEntriesBefore = columnsWithNegativeEntries.getNumberOfSetBitsBeforeIndices();
204 for (; row < originalMatrix.
getRowCount(); ++row) {
205 for (
auto const& entry : originalMatrix.getRow(row)) {
206 if (entry.getValue() < zero) {
207 builder.
addNextValue(row, originalMatrix.
getRowCount() + columnsWithNegativeEntriesBefore[entry.getColumn()], -entry.getValue());
209 builder.
addNextValue(row, entry.getColumn(), entry.getValue());
214 for (
auto column : columnsWithNegativeEntries) {
220 matrix = builder.
build();
223template<
typename ValueType>
224void NativeLinearEquationSolver<ValueType>::WalkerChaeData::computeNewB(std::vector<ValueType>
const& originalB) {
225 b = std::vector<ValueType>(originalB);
226 b.resize(matrix.getRowCount());
229template<
typename ValueType>
230void NativeLinearEquationSolver<ValueType>::WalkerChaeData::precomputeAuxiliaryData() {
231 columnSums = std::vector<ValueType>(matrix.getColumnCount());
232 for (
auto const& e : matrix) {
233 columnSums[e.getColumn()] += e.getValue();
236 newX.resize(matrix.getRowCount());
239template<
typename ValueType>
240bool NativeLinearEquationSolver<ValueType>::solveEquationsWalkerChae(Environment
const& env, std::vector<ValueType>& x, std::vector<ValueType>
const& b)
const {
241 STORM_LOG_INFO(
"Solving linear equation system (" << x.size() <<
" rows) with NativeLinearEquationSolver (WalkerChae)");
244 if (!walkerChaeData) {
245 walkerChaeData = std::make_unique<WalkerChaeData>(env, *this->A, b);
249 x.resize(walkerChaeData->matrix.getRowCount());
255 uint64_t maxIter = env.solver().native().getMaximalNumberOfIterations();
258 std::vector<ValueType>* currentX = &x;
259 std::vector<ValueType>* nextX = &walkerChaeData->newX;
261 std::vector<ValueType> tmp = walkerChaeData->matrix.getRowSumVector();
263 [
this](ValueType
const& first, ValueType
const& second) -> ValueType { return walkerChaeData->t * first + second; });
269 std::vector<ValueType> currentAx(x.size());
270 walkerChaeData->multiplier->multiply(env, *currentX,
nullptr, currentAx);
274 uint64_t iterations = 0;
275 this->startMeasureProgress();
278 walkerChaeData->matrix.performWalkerChaeStep(*currentX, walkerChaeData->columnSums, walkerChaeData->b, currentAx, *nextX);
281 walkerChaeData->multiplier->multiply(env, *nextX,
nullptr, currentAx);
289 std::swap(currentX, nextX);
292 this->showProgressIterative(iterations);
304 if (currentX == &walkerChaeData->newX) {
305 std::swap(x, *currentX);
314 if (!this->isCachingEnabled()) {
318 this->reportStatus(status, iterations);
323template<
typename ValueType>
324typename NativeLinearEquationSolver<ValueType>::PowerIterationResult NativeLinearEquationSolver<ValueType>::performPowerIteration(
325 Environment
const& env, std::vector<ValueType>*& currentX, std::vector<ValueType>*& newX, std::vector<ValueType>
const& b, ValueType
const& precision,
326 bool relative,
SolverGuarantee const& guarantee, uint64_t currentIterations, uint64_t maxIterations,
330 uint64_t iterations = currentIterations;
333 if (useGaussSeidelMultiplication) {
335 this->multiplier->multiplyGaussSeidel(env, *newX, &b);
337 this->multiplier->multiply(env, *currentX, &b, *newX);
341 if (storm::utility::vector::equalModuloPrecision<ValueType>(*currentX, *newX, precision, relative)) {
346 std::swap(currentX, newX);
349 status = this->updateStatus(status, *currentX, guarantee, iterations, maxIterations);
352 this->showProgressIterative(iterations);
355 return PowerIterationResult(iterations - currentIterations, status);
358template<
typename ValueType>
359bool NativeLinearEquationSolver<ValueType>::solveEquationsPower(Environment
const& env, std::vector<ValueType>& x, std::vector<ValueType>
const& b)
const {
360 STORM_LOG_INFO(
"Solving linear equation system (" << x.size() <<
" rows) with NativeLinearEquationSolver (Power)");
365 if (this->hasCustomTerminationCondition()) {
367 this->createLowerBoundsVector(x);
370 this->createUpperBoundsVector(x);
376 uint64_t numIterations{0};
378 this->showProgressIterative(numIterations);
379 return this->updateStatus(current, x, guarantee, numIterations, env.solver().native().getMaximalNumberOfIterations());
381 this->startMeasureProgress();
382 auto status = viHelper.VI(x, b, numIterations, env.solver().native().getRelativeTerminationCriterion(),
383 storm::utility::convertNumber<ValueType>(env.solver().native().getPrecision()), {}, viCallback,
384 env.solver().native().getPowerMethodMultiplicationStyle());
386 this->reportStatus(status, numIterations);
388 if (!this->isCachingEnabled()) {
395template<
typename ValueType>
400template<
typename ValueType>
402 ValueType result = storm::utility::zero<ValueType>();
403 auto oldValueIt = oldValues.begin();
404 for (
auto value : relevantValues) {
405 result = storm::utility::max<ValueType>(result, storm::utility::abs<ValueType>(allValues[value] - *oldValueIt));
410template<
typename ValueType>
411ValueType
computeMaxAbsDiff(std::vector<ValueType>
const& allOldValues, std::vector<ValueType>
const& allNewValues,
413 ValueType result = storm::utility::zero<ValueType>();
414 for (
auto value : relevantValues) {
415 result = storm::utility::max<ValueType>(result, storm::utility::abs<ValueType>(allNewValues[value] - allOldValues[value]));
420template<
typename ValueType>
421bool NativeLinearEquationSolver<ValueType>::solveEquationsIntervalIteration(
Environment const& env, std::vector<ValueType>& x,
422 std::vector<ValueType>
const& b)
const {
423 STORM_LOG_THROW(this->hasLowerBound(), storm::exceptions::UnmetRequirementException,
"Solver requires lower bound, but none was given.");
424 STORM_LOG_THROW(this->hasUpperBound(), storm::exceptions::UnmetRequirementException,
"Solver requires upper bound, but none was given.");
425 STORM_LOG_INFO(
"Solving linear equation system (" << x.size() <<
" rows) with NativeLinearEquationSolver (IntervalIteration)");
427 helper::IntervalIterationHelper<ValueType, true> iiHelper(viOperator);
429 auto lowerBoundsCallback = [&](std::vector<ValueType>& vector) { this->createLowerBoundsVector(vector); };
430 auto upperBoundsCallback = [&](std::vector<ValueType>& vector) { this->createUpperBoundsVector(vector); };
432 uint64_t numIterations{0};
433 auto iiCallback = [&](helper::IIData<ValueType>
const& data) {
434 this->showProgressIterative(numIterations);
435 bool terminateEarly = this->hasCustomTerminationCondition() && this->getTerminationCondition().terminateNow(data.x,
SolverGuarantee::LessOrEqual) &&
439 std::optional<storm::storage::BitVector> optionalRelevantValues;
440 if (this->hasRelevantValues()) {
441 optionalRelevantValues = this->getRelevantValues();
443 this->startMeasureProgress();
445 iiCallback, optionalRelevantValues);
446 this->reportStatus(status, numIterations);
448 if (!this->isCachingEnabled()) {
455template<
typename ValueType>
456bool NativeLinearEquationSolver<ValueType>::solveEquationsSoundValueIteration(Environment
const& env, std::vector<ValueType>& x,
457 std::vector<ValueType>
const& b)
const {
459 assert(x.size() == this->A->getRowGroupCount());
461 std::optional<ValueType> lowerBound, upperBound;
462 if (this->hasLowerBound()) {
463 lowerBound = this->getLowerBound(
true);
465 if (this->hasUpperBound()) {
466 upperBound = this->getUpperBound(
true);
471 auto precision = storm::utility::convertNumber<ValueType>(env.solver().native().getPrecision());
472 uint64_t numIterations{0};
473 auto sviCallback = [&](
typename helper::SoundValueIterationHelper<ValueType, true>::SVIData
const& current) {
474 this->showProgressIterative(numIterations);
475 return this->updateStatus(current.status,
476 this->hasCustomTerminationCondition() && current.checkCustomTerminationCondition(this->getTerminationCondition()),
477 numIterations, env.solver().native().getMaximalNumberOfIterations());
479 std::optional<storm::storage::BitVector> optionalRelevantValues;
480 if (this->hasRelevantValues()) {
481 optionalRelevantValues = this->getRelevantValues();
483 this->startMeasureProgress();
484 helper::SoundValueIterationHelper<ValueType, true> sviHelper(viOperator);
485 auto status = sviHelper.SVI(x, b, numIterations, env.solver().native().getRelativeTerminationCriterion(), precision, {}, lowerBound, upperBound,
486 sviCallback, optionalRelevantValues);
488 this->reportStatus(status, numIterations);
490 if (!this->isCachingEnabled()) {
497template<
typename ValueType>
498bool NativeLinearEquationSolver<ValueType>::solveEquationsOptimisticValueIteration(Environment
const& env, std::vector<ValueType>& x,
499 std::vector<ValueType>
const& b)
const {
502 x.assign(x.size(), storm::utility::zero<ValueType>());
508 helper::OptimisticValueIterationHelper<ValueType, true> oviHelper(viOperator);
509 auto prec = storm::utility::convertNumber<ValueType>(env.solver().native().getPrecision());
510 std::optional<ValueType> lowerBound, upperBound;
511 if (this->hasLowerBound()) {
512 lowerBound = this->getLowerBound(
true);
514 if (this->hasUpperBound()) {
515 upperBound = this->getUpperBound(
true);
517 uint64_t numIterations{0};
518 auto oviCallback = [&](
SolverStatus const& current, std::vector<ValueType>
const& v) {
519 this->showProgressIterative(numIterations);
520 return this->updateStatus(current, v,
SolverGuarantee::LessOrEqual, numIterations, env.solver().native().getMaximalNumberOfIterations());
522 this->createLowerBoundsVector(x);
523 std::optional<ValueType> guessingFactor;
524 if (env.solver().ovi().getUpperBoundGuessingFactor()) {
525 guessingFactor = storm::utility::convertNumber<ValueType>(*env.solver().ovi().getUpperBoundGuessingFactor());
527 this->startMeasureProgress();
528 auto status = oviHelper.OVI(x, b, env.solver().native().getRelativeTerminationCriterion(), prec, {}, guessingFactor, lowerBound, upperBound, oviCallback);
529 this->reportStatus(status, numIterations);
531 if (!this->isCachingEnabled()) {
538template<
typename ValueType>
539bool NativeLinearEquationSolver<ValueType>::solveEquationsGuessingValueIteration(
const Environment& env, std::vector<ValueType>& x,
540 const std::vector<ValueType>& b)
const {
541 if (!this->cachedRowVector) {
542 this->cachedRowVector = std::make_unique<std::vector<ValueType>>(this->A->
getRowCount());
546 std::vector<ValueType>* lowerX = &x;
547 this->createLowerBoundsVector(*lowerX);
548 this->createUpperBoundsVector(this->cachedRowVector, this->getMatrixRowCount());
549 std::vector<ValueType>* upperX = this->cachedRowVector.get();
553 uint64_t numIterations{0};
554 auto gviCallback = [&](helper::GVIData<ValueType>
const& data) {
555 this->showProgressIterative(numIterations);
556 bool terminateEarly = this->hasCustomTerminationCondition() && this->getTerminationCondition().terminateNow(data.x,
SolverGuarantee::LessOrEqual) &&
558 return this->updateStatus(data.status, terminateEarly, numIterations, env.solver().native().getMaximalNumberOfIterations());
561 this->startMeasureProgress();
562 auto status = helper.solveEquations(*lowerX, *upperX, b, numIterations, storm::utility::convertNumber<ValueType>(env.solver().native().getPrecision()),
565 auto two = storm::utility::convertNumber<ValueType>(2.0);
566 storm::utility::vector::applyPointwise<ValueType, ValueType, ValueType>(
567 *lowerX, *upperX, x, [&two](ValueType
const& a, ValueType
const& b) -> ValueType {
return (a + b) / two; });
568 this->reportStatus(status, numIterations);
570 if (!this->isCachingEnabled()) {
576template<
typename ValueType>
577bool NativeLinearEquationSolver<ValueType>::solveEquationsRationalSearch(Environment
const& env, std::vector<ValueType>& x,
578 std::vector<ValueType>
const& b)
const {
581 std::shared_ptr<helper::ValueIterationOperator<storm::RationalNumber, true>> exactOp;
582 std::shared_ptr<helper::ValueIterationOperator<double, true>> impreciseOp;
584 if constexpr (std::is_same_v<ValueType, storm::RationalNumber>) {
585 exactOp = viOperator;
586 impreciseOp = std::make_shared<helper::ValueIterationOperator<double, true>>();
587 impreciseOp->setMatrixBackwards(this->A->template toValueType<double>());
589 impreciseOp = viOperator;
590 exactOp = std::make_shared<helper::ValueIterationOperator<storm::RationalNumber, true>>();
591 exactOp->setMatrixBackwards(this->A->template toValueType<storm::RationalNumber>());
595 uint64_t numIterations{0};
597 this->showProgressIterative(numIterations);
598 return this->updateStatus(current, x,
SolverGuarantee::None, numIterations, env.solver().native().getMaximalNumberOfIterations());
600 this->startMeasureProgress();
601 auto status = rsHelper.RS(x, b, numIterations, storm::utility::convertNumber<ValueType>(env.solver().native().getPrecision()), {}, rsCallback);
603 this->reportStatus(status, numIterations);
605 if (!this->isCachingEnabled()) {
612template<
typename ValueType>
613NativeLinearEquationSolverMethod NativeLinearEquationSolver<ValueType>::getMethod(Environment
const& env,
bool isExactMode)
const {
615 auto method = env.solver().native().getMethod();
617 if (isExactMode && method != NativeLinearEquationSolverMethod::RationalSearch) {
618 if (env.solver().native().isMethodSetFromDefault()) {
619 method = NativeLinearEquationSolverMethod::RationalSearch;
622 "' as the solution technique to guarantee exact results. If you want to override this, please explicitly specify a different method.");
624 STORM_LOG_WARN(
"The selected solution method does not guarantee exact results.");
626 }
else if (env.solver().isForceSoundness() && method != NativeLinearEquationSolverMethod::SoundValueIteration &&
627 method != NativeLinearEquationSolverMethod::OptimisticValueIteration && method != NativeLinearEquationSolverMethod::IntervalIteration &&
628 method != NativeLinearEquationSolverMethod::RationalSearch) {
629 if (env.solver().native().isMethodSetFromDefault()) {
630 method = NativeLinearEquationSolverMethod::OptimisticValueIteration;
633 "' as the solution technique to guarantee sound results. If you want to override this, please explicitly specify a different method.");
635 STORM_LOG_WARN(
"The selected solution method does not guarantee sound results.");
641template<
typename ValueType>
644 case NativeLinearEquationSolverMethod::SOR:
645 return this->solveEquationsSOR(env, x, b, storm::utility::convertNumber<ValueType>(env.
solver().
native().
getSorOmega()));
646 case NativeLinearEquationSolverMethod::GaussSeidel:
647 return this->solveEquationsSOR(env, x, b, storm::utility::one<ValueType>());
648 case NativeLinearEquationSolverMethod::Jacobi:
649 return this->solveEquationsJacobi(env, x, b);
650 case NativeLinearEquationSolverMethod::WalkerChae:
651 return this->solveEquationsWalkerChae(env, x, b);
652 case NativeLinearEquationSolverMethod::Power:
653 return this->solveEquationsPower(env, x, b);
654 case NativeLinearEquationSolverMethod::SoundValueIteration:
655 return this->solveEquationsSoundValueIteration(env, x, b);
656 case NativeLinearEquationSolverMethod::OptimisticValueIteration:
657 return this->solveEquationsOptimisticValueIteration(env, x, b);
658 case NativeLinearEquationSolverMethod::GuessingValueIteration:
659 return this->solveEquationsGuessingValueIteration(env, x, b);
660 case NativeLinearEquationSolverMethod::IntervalIteration:
661 return this->solveEquationsIntervalIteration(env, x, b);
662 case NativeLinearEquationSolverMethod::RationalSearch:
663 return this->solveEquationsRationalSearch(env, x, b);
665 STORM_LOG_THROW(
false, storm::exceptions::InvalidEnvironmentException,
"Unknown solving technique.");
669template<
typename ValueType>
672 if (method == NativeLinearEquationSolverMethod::Power || method == NativeLinearEquationSolverMethod::SoundValueIteration ||
673 method == NativeLinearEquationSolverMethod::OptimisticValueIteration || method == NativeLinearEquationSolverMethod::RationalSearch ||
674 method == NativeLinearEquationSolverMethod::IntervalIteration || method == NativeLinearEquationSolverMethod::GuessingValueIteration) {
681template<
typename ValueType>
685 if (method == NativeLinearEquationSolverMethod::IntervalIteration || method == NativeLinearEquationSolverMethod::GuessingValueIteration) {
687 }
else if (method == NativeLinearEquationSolverMethod::RationalSearch || method == NativeLinearEquationSolverMethod::OptimisticValueIteration) {
689 }
else if (method == NativeLinearEquationSolverMethod::SoundValueIteration) {
695template<
typename ValueType>
697 jacobiDecomposition.reset();
698 walkerChaeData.reset();
704template<
typename ValueType>
709template<
typename ValueType>
710uint64_t NativeLinearEquationSolver<ValueType>::getMatrixColumnCount()
const {
714template<
typename ValueType>
716 return std::make_unique<storm::solver::NativeLinearEquationSolver<ValueType>>();
719template<
typename ValueType>
721 return std::make_unique<NativeLinearEquationSolverFactory<ValueType>>(*this);
SolverEnvironment & solver()
storm::RationalNumber const & getPrecision() const
uint64_t const & getMaximalNumberOfIterations() const
bool const & getRelativeTerminationCriterion() const
storm::RationalNumber const & getSorOmega() const
bool isForceExact() const
NativeSolverEnvironment & native()
virtual void clearCache() const
LinearEquationSolverRequirements & requireLowerBounds(bool critical=true)
LinearEquationSolverRequirements & requireBounds(bool critical=true)
std::unique_ptr< Multiplier< ValueType > > create(Environment const &env, storm::storage::SparseMatrix< ValueType > const &matrix)
virtual std::unique_ptr< storm::solver::LinearEquationSolver< ValueType > > create(Environment const &env) const override
Creates an equation solver with the current settings, but without a matrix.
virtual std::unique_ptr< LinearEquationSolverFactory< ValueType > > clone() const override
Creates a copy of this factory.
A class that uses storm's native matrix operations to implement the LinearEquationSolver interface.
virtual LinearEquationSolverProblemFormat getEquationProblemFormat(storm::Environment const &env) const override
Retrieves the format in which this solver expects to solve equations.
friend class NativeLinearEquationSolver
virtual bool internalSolveEquations(storm::Environment const &env, std::vector< ValueType > &x, std::vector< ValueType > const &b) const override
virtual void setMatrix(storm::storage::SparseMatrix< ValueType > const &A) override
virtual void clearCache() const override
virtual LinearEquationSolverRequirements getRequirements(Environment const &env) const override
Retrieves the requirements of the solver under the current settings.
Implements guessing value iteration.
Implements rational search.
A bit vector that is internally represented as a vector of 64-bit values.
A class that can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
A class that holds a possibly non-square matrix in the compressed row storage format.
index_type getColumnCount() const
Returns the number of columns of the matrix.
std::pair< storm::storage::SparseMatrix< value_type >, std::vector< value_type > > getJacobiDecomposition() const
Calculates the Jacobi decomposition of this sparse matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
LinearEquationSolverProblemFormat
void preserveOldRelevantValues(std::vector< ValueType > const &allValues, storm::storage::BitVector const &relevantValues, std::vector< ValueType > &oldValues)
std::string toString(GurobiSolverMethod const &method)
Yields a string representation of the GurobiSolverMethod.
ValueType computeMaxAbsDiff(std::vector< ValueType > const &allValues, storm::storage::BitVector const &relevantValues, std::vector< ValueType > const &oldValues)
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
void selectVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Selects the elements from a vector at the specified positions and writes them consecutively into anot...
T computeSquaredNorm2Difference(std::vector< T > const &b1, std::vector< T > const &b2)
void multiplyVectorsPointwise(std::vector< InValueType1 > const &firstOperand, std::vector< InValueType2 > const &secondOperand, std::vector< OutValueType > &target)
Multiplies the two given vectors (pointwise) and writes the result to the target vector.
void applyPointwise(std::vector< InValueType1 > const &firstOperand, std::vector< InValueType2 > const &secondOperand, std::vector< OutValueType > &target, Operation f=Operation())
Applies the given operation pointwise on the two given vectors and writes the result to the third vec...
void subtractVectors(std::vector< InValueType1 > const &firstOperand, std::vector< InValueType2 > const &secondOperand, std::vector< OutValueType > &target)
Subtracts the two given vectors and writes the result to the target vector.
bool hasNonZeroEntry(std::vector< T > const &v)
ValueType pow(ValueType const &value, int_fast64_t exponent)
TargetType convertNumber(SourceType const &number)