blas_level_2.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*****************************************************************************
  2. *
  3. * MODULE: Grass numerical math interface
  4. * AUTHOR(S): Soeren Gebbert, Berlin (GER) Dec 2006
  5. * soerengebbert <at> googlemail <dot> com
  6. *
  7. * PURPOSE: grass blas implementation
  8. * part of the gmath library
  9. *
  10. * COPYRIGHT: (C) 2010 by the GRASS Development Team
  11. *
  12. * This program is free software under the GNU General Public
  13. * License (>=v2). Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. *****************************************************************************/
  17. #include <math.h>
  18. #include <unistd.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include <grass/gmath.h>
  23. #include <grass/gis.h>
  24. #define EPSILON 0.00000000000000001
  25. /*!
  26. * \brief Compute the matrix - vector product
  27. * of matrix A and vector x.
  28. *
  29. * This function is multi-threaded with OpenMP and can be called within a parallel OpenMP region.
  30. *
  31. * y = A * x
  32. *
  33. *
  34. * \param A (double ** )
  35. * \param x (double *)
  36. * \param y (double *)
  37. * \param rows (int)
  38. * \param cols (int)
  39. * \return (void)
  40. *
  41. * */
  42. void G_math_d_Ax(double **A, double *x, double *y, int rows, int cols)
  43. {
  44. int i, j;
  45. double tmp;
  46. #pragma omp for schedule (static) private(i, j, tmp)
  47. for (i = 0; i < rows; i++) {
  48. tmp = 0;
  49. for (j = cols - 1; j >= 0; j--) {
  50. tmp += A[i][j] * x[j];
  51. }
  52. y[i] = tmp;
  53. }
  54. return;
  55. }
  56. /*!
  57. * \brief Compute the matrix - vector product
  58. * of matrix A and vector x.
  59. *
  60. * This function is multi-threaded with OpenMP and can be called within a parallel OpenMP region.
  61. *
  62. * y = A * x
  63. *
  64. *
  65. * \param A (float ** )
  66. * \param x (float *)
  67. * \param y (float *)
  68. * \param rows (int)
  69. * \param cols (int)
  70. * \return (void)
  71. *
  72. * */
  73. void G_math_f_Ax(float **A, float *x, float *y, int rows, int cols)
  74. {
  75. int i, j;
  76. float tmp;
  77. #pragma omp for schedule (static) private(i, j, tmp)
  78. for (i = 0; i < rows; i++) {
  79. tmp = 0;
  80. for (j = cols - 1; j >= 0; j--) {
  81. tmp += A[i][j] * x[j];
  82. }
  83. y[i] = tmp;
  84. }
  85. return;
  86. }
  87. /*!
  88. * \brief Compute the dyadic product of two vectors.
  89. * The result is stored in the matrix A.
  90. *
  91. * This function is multi-threaded with OpenMP and can be called within a parallel OpenMP region.
  92. *
  93. * A = x * y^T
  94. *
  95. *
  96. * \param x (double *)
  97. * \param y (double *)
  98. * \param A (float **) -- matrix of size rows*cols
  99. * \param rows (int) -- length of vector x
  100. * \param cols (int) -- lengt of vector y
  101. * \return (void)
  102. *
  103. * */
  104. void G_math_d_x_dyad_y(double *x, double *y, double **A, int rows, int cols)
  105. {
  106. int i, j;
  107. #pragma omp for schedule (static) private(i, j)
  108. for (i = 0; i < rows; i++) {
  109. for (j = cols - 1; j >= 0; j--) {
  110. A[i][j] = x[i] * y[j];
  111. }
  112. }
  113. return;
  114. }
  115. /*!
  116. * \brief Compute the dyadic product of two vectors.
  117. * The result is stored in the matrix A.
  118. *
  119. * This function is multi-threaded with OpenMP and can be called within a parallel OpenMP region.
  120. *
  121. * A = x * y^T
  122. *
  123. *
  124. * \param x (float *)
  125. * \param y (float *)
  126. * \param A (float **= -- matrix of size rows*cols
  127. * \param rows (int) -- length of vector x
  128. * \param cols (int) -- lengt of vector y
  129. * \return (void)
  130. *
  131. * */
  132. void G_math_f_x_dyad_y(float *x, float *y, float **A, int rows, int cols)
  133. {
  134. int i, j;
  135. #pragma omp for schedule (static) private(i, j)
  136. for (i = 0; i < rows; i++) {
  137. for (j = cols - 1; j >= 0; j--) {
  138. A[i][j] = x[i] * y[j];
  139. }
  140. }
  141. return;
  142. }
  143. /*!
  144. * \brief Compute the scaled matrix - vector product
  145. * of matrix double **A and vector x and y.
  146. *
  147. * z = a * A * x + b * y
  148. *
  149. * This function is multi-threaded with OpenMP and can be called within a parallel OpenMP region.
  150. *
  151. *
  152. * \param A (double **)
  153. * \param x (double *)
  154. * \param y (double *)
  155. * \param a (double)
  156. * \param b (double)
  157. * \param z (double *)
  158. * \param rows (int)
  159. * \param cols (int)
  160. * \return (void)
  161. *
  162. * */
  163. void G_math_d_aAx_by(double **A, double *x, double *y, double a, double b,
  164. double *z, int rows, int cols)
  165. {
  166. int i, j;
  167. double tmp;
  168. /*catch specific cases */
  169. if (a == b) {
  170. #pragma omp for schedule (static) private(i, j, tmp)
  171. for (i = 0; i < rows; i++) {
  172. tmp = 0;
  173. for (j = cols - 1; j >= 0; j--) {
  174. tmp += A[i][j] * x[j] + y[j];
  175. }
  176. z[i] = a * tmp;
  177. }
  178. }
  179. else if (b == -1.0) {
  180. #pragma omp for schedule (static) private(i, j, tmp)
  181. for (i = 0; i < rows; i++) {
  182. tmp = 0;
  183. for (j = cols - 1; j >= 0; j--) {
  184. tmp += a * A[i][j] * x[j] - y[j];
  185. }
  186. z[i] = tmp;
  187. }
  188. }
  189. else if (b == 0.0) {
  190. #pragma omp for schedule (static) private(i, j, tmp)
  191. for (i = 0; i < rows; i++) {
  192. tmp = 0;
  193. for (j = cols - 1; j >= 0; j--) {
  194. tmp += A[i][j] * x[j];
  195. }
  196. z[i] = a * tmp;
  197. }
  198. }
  199. else if (a == -1.0) {
  200. #pragma omp for schedule (static) private(i, j, tmp)
  201. for (i = 0; i < rows; i++) {
  202. tmp = 0;
  203. for (j = cols - 1; j >= 0; j--) {
  204. tmp += b * y[j] - A[i][j] * x[j];
  205. }
  206. z[i] = tmp;
  207. }
  208. }
  209. else {
  210. #pragma omp for schedule (static) private(i, j, tmp)
  211. for (i = 0; i < rows; i++) {
  212. tmp = 0;
  213. for (j = cols - 1; j >= 0; j--) {
  214. tmp += a * A[i][j] * x[j] + b * y[j];
  215. }
  216. z[i] = tmp;
  217. }
  218. }
  219. return;
  220. }
  221. /*!
  222. * \brief Compute the scaled matrix - vector product
  223. * of matrix A and vectors x and y.
  224. *
  225. * z = a * A * x + b * y
  226. *
  227. * This function is multi-threaded with OpenMP and can be called within a parallel OpenMP region.
  228. *
  229. *
  230. * \param A (float **)
  231. * \param x (float *)
  232. * \param y (float *)
  233. * \param a (float)
  234. * \param b (float)
  235. * \param z (float *)
  236. * \param rows (int)
  237. * \param cols (int)
  238. * \return (void)
  239. *
  240. * */
  241. void G_math_f_aAx_by(float **A, float *x, float *y, float a, float b,
  242. float *z, int rows, int cols)
  243. {
  244. int i, j;
  245. float tmp;
  246. /*catch specific cases */
  247. if (a == b) {
  248. #pragma omp for schedule (static) private(i, j, tmp)
  249. for (i = 0; i < rows; i++) {
  250. tmp = 0;
  251. for (j = cols - 1; j >= 0; j--) {
  252. tmp += A[i][j] * x[j] + y[j];
  253. }
  254. z[i] = a * tmp;
  255. }
  256. }
  257. else if (b == -1.0) {
  258. #pragma omp for schedule (static) private(i, j, tmp)
  259. for (i = 0; i < rows; i++) {
  260. tmp = 0;
  261. for (j = cols - 1; j >= 0; j--) {
  262. tmp += a * A[i][j] * x[j] - y[j];
  263. }
  264. z[i] = tmp;
  265. }
  266. }
  267. else if (b == 0.0) {
  268. #pragma omp for schedule (static) private(i, j, tmp)
  269. for (i = 0; i < rows; i++) {
  270. tmp = 0;
  271. for (j = cols - 1; j >= 0; j--) {
  272. tmp += A[i][j] * x[j];
  273. }
  274. z[i] = a * tmp;
  275. }
  276. }
  277. else if (a == -1.0) {
  278. #pragma omp for schedule (static) private(i, j, tmp)
  279. for (i = 0; i < rows; i++) {
  280. tmp = 0;
  281. for (j = cols - 1; j >= 0; j--) {
  282. tmp += b * y[j] - A[i][j] * x[j];
  283. }
  284. z[i] = tmp;
  285. }
  286. }
  287. else {
  288. #pragma omp for schedule (static) private(i, j, tmp)
  289. for (i = 0; i < rows; i++) {
  290. tmp = 0;
  291. for (j = cols - 1; j >= 0; j--) {
  292. tmp += a * A[i][j] * x[j] + b * y[j];
  293. }
  294. z[i] = tmp;
  295. }
  296. }
  297. return;
  298. }
  299. /*!
  300. * \fn int G_math_d_A_T(double **A, int rows)
  301. *
  302. * \brief Compute the transposition of matrix A.
  303. * Matrix A will be overwritten.
  304. *
  305. * This function is multi-threaded with OpenMP and can be called within a parallel OpenMP region.
  306. *
  307. * Returns 0.
  308. *
  309. * \param A (double **)
  310. * \param rows (int)
  311. * \return int
  312. */
  313. int G_math_d_A_T(double **A, int rows)
  314. {
  315. int i, j;
  316. double tmp;
  317. #pragma omp for schedule (static) private(i, j, tmp)
  318. for (i = 0; i < rows; i++)
  319. for (j = 0; j < i; j++) {
  320. tmp = A[i][j];
  321. A[i][j] = A[j][i];
  322. A[j][i] = tmp;
  323. }
  324. return 0;
  325. }
  326. /*!
  327. * \fn int G_math_f_A_T(float **A, int rows)
  328. *
  329. * \brief Compute the transposition of matrix A.
  330. * Matrix A will be overwritten.
  331. *
  332. * This function is multi-threaded with OpenMP and can be called within a parallel OpenMP region.
  333. *
  334. * Returns 0.
  335. *
  336. * \param A (float **)
  337. * \param rows (int)
  338. * \return int
  339. */
  340. int G_math_f_A_T(float **A, int rows)
  341. {
  342. int i, j;
  343. float tmp;
  344. #pragma omp for schedule (static) private(i, j, tmp)
  345. for (i = 0; i < rows; i++)
  346. for (j = 0; j < i; j++) {
  347. tmp = A[i][j];
  348. A[i][j] = A[j][i];
  349. A[j][i] = tmp;
  350. }
  351. return 0;
  352. }