Program Listing for File Vector.hpp

Return to documentation for file (include/networkit/algebraic/Vector.hpp)

/*
 * Vector.hpp
 *
 *  Created on: 12.03.2014
 *      Author: Michael Wegner (michael.wegner@student.kit.edu)
 */

#ifndef NETWORKIT_ALGEBRAIC_VECTOR_HPP_
#define NETWORKIT_ALGEBRAIC_VECTOR_HPP_

#include <cassert>
#include <cmath>
#include <iostream>
#include <numeric>
#include <stdexcept>
#include <vector>

#include <networkit/Globals.hpp>
#include <networkit/algebraic/AlgebraicGlobals.hpp>

namespace NetworKit {

// forward declaration of DynamicMatrix class
class DynamicMatrix;

class Vector final {
private:
    std::vector<double> values;
    bool transposed;

public:
    Vector();

    Vector(count dimension, double initialValue = 0, bool transpose = false);

    Vector(const std::vector<double> &values, bool transpose = false);

    Vector(const std::initializer_list<double> &list);

    inline count getDimension() const { return values.size(); }

    bool isTransposed() const;

    Vector transpose() const;

    double length() const;

    double mean() const;

    inline double &operator[](index idx) {
        assert(idx < values.size());
        return values[idx];
    }

    void fill(double val) { std::fill(values.begin(), values.end(), val); }

    inline double operator[](index idx) const {
        assert(idx < values.size());
        return values[idx];
    }

    double &at(index idx) {
        if (idx >= values.size()) {
            throw std::runtime_error("index out of range");
        } else {
            return values[idx];
        }
    }

    bool operator==(const Vector &other) const;

    bool operator!=(const Vector &other) const;

    template <class Matrix = DynamicMatrix>
    static Matrix outerProduct(const Vector &v1, const Vector &v2);

    static double innerProduct(const Vector &v1, const Vector &v2);

    double operator*(const Vector &other) const;

    template <typename Matrix = DynamicMatrix>
    Vector operator*(const Matrix &matrix) const;

    Vector operator*(double scalar) const;

    /*
     * Multiplies this vector with a scalar specified in @a scalar.
     * @return Reference to this vector.
     */
    Vector &operator*=(double scalar);

    Vector operator/(double divisor) const;

    Vector &operator/=(double divisor);

    Vector operator+(const Vector &other) const;

    Vector operator+(double value) const;

    Vector &operator+=(const Vector &other);

    Vector &operator+=(double value);

    Vector operator-(const Vector &other) const;

    Vector operator-(double value) const;

    Vector &operator-=(const Vector &other);

    Vector &operator-=(double value);

    template <typename F>
    void apply(F unaryElementFunction);

    template <typename L>
    void forElements(L handle);

    template <typename L>
    void forElements(L handle) const;

    template <typename L>
    void parallelForElements(L handle);

    template <typename L>
    void parallelForElements(L handle) const;
};

inline Vector operator*(double scalar, const Vector &v) {
    return v.operator*(scalar);
}

template <class Matrix>
Matrix Vector::outerProduct(const Vector &v1, const Vector &v2) {
    std::vector<Triplet> triplets;

    for (index i = 0; i < v1.getDimension(); ++i) {
        for (index j = 0; j < v2.getDimension(); ++j) {
            double result = v1[i] * v2[j];
            if (std::fabs(result) >= FLOAT_EPSILON) {
                triplets.push_back({i, j, result});
            }
        }
    }

    return Matrix(v1.getDimension(), v2.getDimension(), triplets);
}

template <class Matrix>
Vector Vector::operator*(const Matrix &matrix) const {
    assert(isTransposed());                          // vector must be of the form 1xn
    assert(getDimension() == matrix.numberOfRows()); // dimensions of vector and matrix must match

    Vector result(matrix.numberOfColumns(), 0.0, true);
#pragma omp parallel for
    for (omp_index k = 0; k < static_cast<omp_index>(matrix.numberOfColumns()); ++k) {
        Vector column = matrix.column(k);
        result[k] = (*this) * column;
    }

    return result;
}

template <typename F>
void Vector::apply(F unaryElementFunction) {
#pragma omp parallel for
    for (omp_index i = 0; i < static_cast<omp_index>(getDimension()); ++i) {
        values[i] = unaryElementFunction(values[i]);
    }
}

template <typename L>
inline void Vector::forElements(L handle) {
    for (uint64_t i = 0; i < getDimension(); ++i) {
        handle(values[i]);
    }
}

template <typename L>
inline void Vector::forElements(L handle) const {
    for (uint64_t i = 0; i < getDimension(); ++i) {
        handle(values[i]);
    }
}

template <typename L>
inline void Vector::parallelForElements(L handle) {
#pragma omp parallel for
    for (omp_index i = 0; i < static_cast<omp_index>(getDimension()); ++i) {
        handle(i, values[i]);
    }
}

template <typename L>
inline void Vector::parallelForElements(L handle) const {
#pragma omp parallel for
    for (omp_index i = 0; i < static_cast<omp_index>(getDimension()); ++i) {
        handle(i, values[i]);
    }
}

// print functions for test debugging / output. Prints Vector as [0, 1, 2, 3, 4]
inline std::ostream &operator<<(std::ostream &os, const Vector &vec) {
    os << "[";
    for (index i = 0; i < vec.getDimension(); i++) {
        if (i != 0)
            os << ", ";
        os << vec[i];
    }
    os << "]";
    return os;
}

} /* namespace NetworKit */
#endif // NETWORKIT_ALGEBRAIC_VECTOR_HPP_