densematrix.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /**
  2. * Copyright (c) 2016-present, Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the MIT license found in the
  6. * LICENSE file in the root directory of this source tree.
  7. */
  8. #include "densematrix.h"
  9. #include <random>
  10. #include <stdexcept>
  11. #include <thread>
  12. #include <utility>
  13. #include "utils.h"
  14. #include "vector.h"
  15. namespace fasttext {
  16. DenseMatrix::DenseMatrix() : DenseMatrix(0, 0) {}
  17. DenseMatrix::DenseMatrix(int64_t m, int64_t n) : Matrix(m, n), data_(m * n) {}
  18. DenseMatrix::DenseMatrix(DenseMatrix&& other) noexcept
  19. : Matrix(other.m_, other.n_), data_(std::move(other.data_)) {}
  20. DenseMatrix::DenseMatrix(int64_t m, int64_t n, real* dataPtr)
  21. : Matrix(m, n), data_(dataPtr, dataPtr + (m * n)) {}
  22. void DenseMatrix::zero() {
  23. std::fill(data_.begin(), data_.end(), 0.0);
  24. }
  25. void DenseMatrix::uniformThread(real a, int block, int32_t seed) {
  26. std::minstd_rand rng(block + seed);
  27. std::uniform_real_distribution<> uniform(-a, a);
  28. int64_t blockSize = (m_ * n_) / 10;
  29. for (int64_t i = blockSize * block;
  30. i < (m_ * n_) && i < blockSize * (block + 1);
  31. i++) {
  32. data_[i] = uniform(rng);
  33. }
  34. }
  35. void DenseMatrix::uniform(real a, unsigned int thread, int32_t seed) {
  36. if (thread > 1) {
  37. std::vector<std::thread> threads;
  38. for (int i = 0; i < thread; i++) {
  39. threads.push_back(std::thread([=]() { uniformThread(a, i, seed); }));
  40. }
  41. for (int32_t i = 0; i < threads.size(); i++) {
  42. threads[i].join();
  43. }
  44. } else {
  45. // webassembly can't instantiate `std::thread`
  46. uniformThread(a, 0, seed);
  47. }
  48. }
  49. void DenseMatrix::multiplyRow(const Vector& nums, int64_t ib, int64_t ie) {
  50. if (ie == -1) {
  51. ie = m_;
  52. }
  53. assert(ie <= nums.size());
  54. for (auto i = ib; i < ie; i++) {
  55. real n = nums[i - ib];
  56. if (n != 0) {
  57. for (auto j = 0; j < n_; j++) {
  58. at(i, j) *= n;
  59. }
  60. }
  61. }
  62. }
  63. void DenseMatrix::divideRow(const Vector& denoms, int64_t ib, int64_t ie) {
  64. if (ie == -1) {
  65. ie = m_;
  66. }
  67. assert(ie <= denoms.size());
  68. for (auto i = ib; i < ie; i++) {
  69. real n = denoms[i - ib];
  70. if (n != 0) {
  71. for (auto j = 0; j < n_; j++) {
  72. at(i, j) /= n;
  73. }
  74. }
  75. }
  76. }
  77. real DenseMatrix::l2NormRow(int64_t i) const {
  78. auto norm = 0.0;
  79. for (auto j = 0; j < n_; j++) {
  80. norm += at(i, j) * at(i, j);
  81. }
  82. if (std::isnan(norm)) {
  83. throw EncounteredNaNError();
  84. }
  85. return std::sqrt(norm);
  86. }
  87. void DenseMatrix::l2NormRow(Vector& norms) const {
  88. assert(norms.size() == m_);
  89. for (auto i = 0; i < m_; i++) {
  90. norms[i] = l2NormRow(i);
  91. }
  92. }
  93. real DenseMatrix::dotRow(const Vector& vec, int64_t i) const {
  94. assert(i >= 0);
  95. assert(i < m_);
  96. assert(vec.size() == n_);
  97. real d = 0.0;
  98. for (int64_t j = 0; j < n_; j++) {
  99. d += at(i, j) * vec[j];
  100. }
  101. if (std::isnan(d)) {
  102. throw EncounteredNaNError();
  103. }
  104. return d;
  105. }
  106. void DenseMatrix::addVectorToRow(const Vector& vec, int64_t i, real a) {
  107. assert(i >= 0);
  108. assert(i < m_);
  109. assert(vec.size() == n_);
  110. for (int64_t j = 0; j < n_; j++) {
  111. data_[i * n_ + j] += a * vec[j];
  112. }
  113. }
  114. void DenseMatrix::addRowToVector(Vector& x, int32_t i) const {
  115. assert(i >= 0);
  116. assert(i < this->size(0));
  117. assert(x.size() == this->size(1));
  118. for (int64_t j = 0; j < n_; j++) {
  119. x[j] += at(i, j);
  120. }
  121. }
  122. void DenseMatrix::addRowToVector(Vector& x, int32_t i, real a) const {
  123. assert(i >= 0);
  124. assert(i < this->size(0));
  125. assert(x.size() == this->size(1));
  126. for (int64_t j = 0; j < n_; j++) {
  127. x[j] += a * at(i, j);
  128. }
  129. }
  130. void DenseMatrix::save(std::ostream& out) const {
  131. out.write((char*)&m_, sizeof(int64_t));
  132. out.write((char*)&n_, sizeof(int64_t));
  133. out.write((char*)data_.data(), m_ * n_ * sizeof(real));
  134. }
  135. void DenseMatrix::load(std::istream& in) {
  136. in.read((char*)&m_, sizeof(int64_t));
  137. in.read((char*)&n_, sizeof(int64_t));
  138. data_ = std::vector<real>(m_ * n_);
  139. in.read((char*)data_.data(), m_ * n_ * sizeof(real));
  140. }
  141. void DenseMatrix::dump(std::ostream& out) const {
  142. out << m_ << " " << n_ << std::endl;
  143. for (int64_t i = 0; i < m_; i++) {
  144. for (int64_t j = 0; j < n_; j++) {
  145. if (j > 0) {
  146. out << " ";
  147. }
  148. out << at(i, j);
  149. }
  150. out << std::endl;
  151. }
  152. };
  153. } // namespace fasttext