| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- /**
- * Copyright (c) 2016-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
- #include "densematrix.h"
- #include <random>
- #include <stdexcept>
- #include <thread>
- #include <utility>
- #include "utils.h"
- #include "vector.h"
- namespace fasttext {
- DenseMatrix::DenseMatrix() : DenseMatrix(0, 0) {}
- DenseMatrix::DenseMatrix(int64_t m, int64_t n) : Matrix(m, n), data_(m * n) {}
- DenseMatrix::DenseMatrix(DenseMatrix&& other) noexcept
- : Matrix(other.m_, other.n_), data_(std::move(other.data_)) {}
- DenseMatrix::DenseMatrix(int64_t m, int64_t n, real* dataPtr)
- : Matrix(m, n), data_(dataPtr, dataPtr + (m * n)) {}
- void DenseMatrix::zero() {
- std::fill(data_.begin(), data_.end(), 0.0);
- }
- void DenseMatrix::uniformThread(real a, int block, int32_t seed) {
- std::minstd_rand rng(block + seed);
- std::uniform_real_distribution<> uniform(-a, a);
- int64_t blockSize = (m_ * n_) / 10;
- for (int64_t i = blockSize * block;
- i < (m_ * n_) && i < blockSize * (block + 1);
- i++) {
- data_[i] = uniform(rng);
- }
- }
- void DenseMatrix::uniform(real a, unsigned int thread, int32_t seed) {
- if (thread > 1) {
- std::vector<std::thread> threads;
- for (int i = 0; i < thread; i++) {
- threads.push_back(std::thread([=]() { uniformThread(a, i, seed); }));
- }
- for (int32_t i = 0; i < threads.size(); i++) {
- threads[i].join();
- }
- } else {
- // webassembly can't instantiate `std::thread`
- uniformThread(a, 0, seed);
- }
- }
- void DenseMatrix::multiplyRow(const Vector& nums, int64_t ib, int64_t ie) {
- if (ie == -1) {
- ie = m_;
- }
- assert(ie <= nums.size());
- for (auto i = ib; i < ie; i++) {
- real n = nums[i - ib];
- if (n != 0) {
- for (auto j = 0; j < n_; j++) {
- at(i, j) *= n;
- }
- }
- }
- }
- void DenseMatrix::divideRow(const Vector& denoms, int64_t ib, int64_t ie) {
- if (ie == -1) {
- ie = m_;
- }
- assert(ie <= denoms.size());
- for (auto i = ib; i < ie; i++) {
- real n = denoms[i - ib];
- if (n != 0) {
- for (auto j = 0; j < n_; j++) {
- at(i, j) /= n;
- }
- }
- }
- }
- real DenseMatrix::l2NormRow(int64_t i) const {
- auto norm = 0.0;
- for (auto j = 0; j < n_; j++) {
- norm += at(i, j) * at(i, j);
- }
- if (std::isnan(norm)) {
- throw EncounteredNaNError();
- }
- return std::sqrt(norm);
- }
- void DenseMatrix::l2NormRow(Vector& norms) const {
- assert(norms.size() == m_);
- for (auto i = 0; i < m_; i++) {
- norms[i] = l2NormRow(i);
- }
- }
- real DenseMatrix::dotRow(const Vector& vec, int64_t i) const {
- assert(i >= 0);
- assert(i < m_);
- assert(vec.size() == n_);
- real d = 0.0;
- for (int64_t j = 0; j < n_; j++) {
- d += at(i, j) * vec[j];
- }
- if (std::isnan(d)) {
- throw EncounteredNaNError();
- }
- return d;
- }
- void DenseMatrix::addVectorToRow(const Vector& vec, int64_t i, real a) {
- assert(i >= 0);
- assert(i < m_);
- assert(vec.size() == n_);
- for (int64_t j = 0; j < n_; j++) {
- data_[i * n_ + j] += a * vec[j];
- }
- }
- void DenseMatrix::addRowToVector(Vector& x, int32_t i) const {
- assert(i >= 0);
- assert(i < this->size(0));
- assert(x.size() == this->size(1));
- for (int64_t j = 0; j < n_; j++) {
- x[j] += at(i, j);
- }
- }
- void DenseMatrix::addRowToVector(Vector& x, int32_t i, real a) const {
- assert(i >= 0);
- assert(i < this->size(0));
- assert(x.size() == this->size(1));
- for (int64_t j = 0; j < n_; j++) {
- x[j] += a * at(i, j);
- }
- }
- void DenseMatrix::save(std::ostream& out) const {
- out.write((char*)&m_, sizeof(int64_t));
- out.write((char*)&n_, sizeof(int64_t));
- out.write((char*)data_.data(), m_ * n_ * sizeof(real));
- }
- void DenseMatrix::load(std::istream& in) {
- in.read((char*)&m_, sizeof(int64_t));
- in.read((char*)&n_, sizeof(int64_t));
- data_ = std::vector<real>(m_ * n_);
- in.read((char*)data_.data(), m_ * n_ * sizeof(real));
- }
- void DenseMatrix::dump(std::ostream& out) const {
- out << m_ << " " << n_ << std::endl;
- for (int64_t i = 0; i < m_; i++) {
- for (int64_t j = 0; j < n_; j++) {
- if (j > 0) {
- out << " ";
- }
- out << at(i, j);
- }
- out << std::endl;
- }
- };
- } // namespace fasttext
|