Advertisement
adwas33

Untitled

May 29th, 2022
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.83 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <iostream>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6.  
  7.  
  8.  
  9. /* ----------------------- norm ----------------------- */
  10. /* Given an array and its length, this function
  11. computes the 2-norm of the array.
  12.  
  13. Input variables:
  14. x : pointer to array for which the 2-norm should
  15. be computed.
  16. length: number of entries in x.
  17. Features: This implementation has time complexity
  18. O(length) and requires O(1) additional memory. */
  19. using namespace std;
  20.  
  21. double norm(double *x, int length) {
  22. int i, length5;
  23. double a, sum = 0;
  24.  
  25. length5 = length % 5;
  26.  
  27. for (i = 0; i < length5; i++) {
  28. sum += x[i] * x[i];
  29. }
  30. for (; i < length; i += 5) {
  31. sum += x[i] * x[i] + x[i + 1] * x[i + 1] + x[i + 2] * x[i + 2]
  32. + x[i + 3] * x[i + 3] + x[i + 4] * x[i + 4];
  33. }
  34.  
  35. return sqrt(sum);
  36. }
  37.  
  38.  
  39. /* ----------------------- vec_copy ----------------------- */
  40. /* Given two arrays of the same length and their length,
  41. this function stores the values from the first array
  42. in the second array.
  43.  
  44. Input variables:
  45. x : pointer to array whose entries are to be
  46. copied.
  47. y : pointer to array in which the components
  48. of x are to be stored.
  49. length: number of entries in x and in y.
  50. Features: This implementation has time complexity
  51. O(length) and requires O(1) additional memory. */
  52.  
  53. void vec_copy(double *x, double *y, int length) {
  54. int i, length5;
  55.  
  56. length5 = length % 5;
  57.  
  58. for (i = 0; i < length5; i++) {
  59. y[i] = x[i];
  60. }
  61. for (; i < length; i += 5) {
  62. y[i] = x[i];
  63. y[i + 1] = x[i + 1];
  64. y[i + 2] = x[i + 2];
  65. y[i + 3] = x[i + 3];
  66. y[i + 4] = x[i + 4];
  67. }
  68. }
  69.  
  70.  
  71. /* ------------------- partialvec_copy ------------------- */
  72. /* Given two arrays, the length of the second array, and
  73. an index this function stores the values from the
  74. subarray x[index : index + length] in the array
  75. y[0 : length].
  76.  
  77. Input variables:
  78. x : pointer to array whose entries are to be
  79. copied.
  80. y : pointer to array in which the components
  81. of x are to be stored.
  82. length: number of entries in y.
  83. index : starting index of subarray of x to be
  84. copied to y.
  85. Example: Suppose x is a pointer to the array
  86. {1, 2, 3, 4, 5}, y is a pointer to the array {0, 0, 0},
  87. length = 3, and index = 2. Then after executing
  88. partialvec_copy(x, y, 3, 2), the array pointed to by
  89. y is now {3, 4, 5}.
  90. Features: This implementation has time complexity
  91. O(length) and requires O(1) additional memory. */
  92.  
  93. void partialvec_copy(double *x, double *y, int length, int index) {
  94. int i, length5;
  95.  
  96. length5 = length % 5;
  97.  
  98. for (i = 0; i < length5; i++) {
  99. y[i] = x[i + index];
  100. }
  101. for (; i < length; i += 5) {
  102. y[i] = x[i + index];
  103. y[i + 1] = x[i + index + 1];
  104. y[i + 2] = x[i + index + 2];
  105. y[i + 3] = x[i + index + 3];
  106. y[i + 4] = x[i + index + 4];
  107. }
  108. }
  109.  
  110.  
  111. /* ----------------------- scalar_div ----------------------- */
  112. /* Given two arrays of the same length, their length, and a
  113. scalar value this function divides the values from the
  114. first array by the scalar value and stores the computed
  115. number in the second array.
  116.  
  117. Input variables:
  118. x : pointer to array whose components are to be
  119. divided by r and stored in second array, y.
  120. r : scalar used in division.
  121. length: number of entries in x and in y.
  122. y : pointer to array in which the components
  123. of x are to be stored.
  124. Features: This implementation has time complexity
  125. O(length) and requires O(1) additional memory. */
  126.  
  127. void scalar_div(double *x, double r, int length, double *y) {
  128. int i, length5;
  129.  
  130. length5 = length % 5;
  131.  
  132. for (i = 0; i < length5; i++) {
  133. y[i] = x[i] / r;
  134. }
  135. for (; i < length; i += 5) {
  136. y[i] = x[i] / r;
  137. y[i + 1] = x[i + 1] / r;
  138. y[i + 2] = x[i + 2] / r;
  139. y[i + 3] = x[i + 3] / r;
  140. y[i + 4] = x[i + 4] / r;
  141. }
  142. }
  143.  
  144.  
  145. /* ----------------------- scalar_sub ----------------------- */
  146. /* Given two arrays of the same length, their length, and a
  147. scalar value this function multiplies the values from the
  148. first array by the scalar value and then subtracts the
  149. computed components from the components the second array.
  150.  
  151. Input variables:
  152. x : pointer to array whose components are to be
  153. multiplied by r then subtracted from the
  154. components of the second array, y.
  155. r : scalar used in multiplication.
  156. length: number of entries in x and in y.
  157. y : pointer to array in which the components
  158. of x are to be stored.
  159. Features: This implementation has time complexity
  160. O(length) and requires O(1) additional memory. */
  161.  
  162. void scalar_sub(double *x, double r, int length, double *y) {
  163. int i, length5;
  164.  
  165. length5 = length % 5;
  166.  
  167. for (i = 0; i < length5; i++) {
  168. y[i] -= r * x[i];
  169. }
  170. for (; i < length; i += 5) {
  171. y[i] -= r * x[i];
  172. y[i + 1] -= r * x[i + 1];
  173. y[i + 2] -= r * x[i + 2];
  174. y[i + 3] -= r * x[i + 3];
  175. y[i + 4] -= r * x[i + 4];
  176. }
  177. }
  178.  
  179.  
  180. /* --------------------- partialscalar_sub --------------------- */
  181. /* Given two arrays, the length of the second array, a scalar
  182. value, and an index, this function multiplies the values
  183. starting at the given index from the first array by the
  184. scalar value and then subtracts the computed components from
  185. the components the second array.
  186.  
  187. Input variables:
  188. x : pointer to array whose components are to be
  189. multiplied by r then subtracted from the
  190. components of the second array, y.
  191. r : scalar used in multiplication.
  192. length: number of entries in y.
  193. index :
  194. y : pointer to array in which the components
  195. of x are to be stored.
  196. Example: Suppose x is a pointer to the array
  197. {1, 2, 3, 4, 5}, y is a pointer to the array {0, 0, 0},
  198. length = 3, r = -1, and index = 2. Then after executing
  199. partialscalar_sub(x, -1, 3, 2, y), the array pointed to
  200. by y is now {-3, -4, -5}.
  201. Features: This implementation has time complexity
  202. O(length) and requires O(1) additional memory. */
  203.  
  204. void partialscalar_sub(double *x, double r, int length,
  205. int index, double *y) {
  206. int i, length5;
  207.  
  208. length5 = length % 5;
  209.  
  210. for (i = 0; i < length5; i++) {
  211. y[i + index] -= r * x[i];
  212. }
  213. for (; i < length; i += 5) {
  214. y[i + index] -= r * x[i];
  215. y[i + index + 1] -= r * x[i + 1];
  216. y[i + index + 2] -= r * x[i + 2];
  217. y[i + index + 3] -= r * x[i + 3];
  218. y[i + index + 4] -= r * x[i + 4];
  219. }
  220. }
  221.  
  222.  
  223. /* --------------------- dot_product --------------------- */
  224. /* Given two arrays of the same length and their length,
  225. this function returns the dot product of the two
  226. arrays.
  227.  
  228. Input variables:
  229. x : pointer to first array.
  230. y : pointer to second array.
  231. length: number of entries in x and in y.
  232. Features: This implementation has time complexity
  233. O(length) and requires O(1) additional memory. */
  234.  
  235. double dot_product(double *x, double *y, int length) {
  236. int i, length5;
  237. double sum = 0;
  238.  
  239. length5 = length % 5;
  240.  
  241. for (i = 0; i < length5; i++) {
  242. sum += x[i] * y[i];
  243. }
  244. for (; i < length; i += 5) {
  245. sum += x[i] * y[i] + x[i + 1] * y[i + 1] + x[i + 2] * y[i + 2]
  246. + x[i + 3] * y[i + 3] + x[i + 4] * y[i + 4];
  247. }
  248.  
  249. return sum;
  250. }
  251.  
  252.  
  253. /* ------------------ partialdot_product ------------------ */
  254. /* Given two arrays of the same length, their length, and
  255. an index this function returns the dot product of the
  256. two subarrays x[index : length] and y[index : length].
  257.  
  258. Input variables:
  259. x : pointer to first array.
  260. y : pointer to second array.
  261. length: number of entries in x and in y.
  262. index : starting index for subarrays.
  263. Example: Suppose x is a pointer to the array
  264. {1, 2, 3, 4}, y is a pointer to the array {5, 6, 7, 8},
  265. length = 4, and index = 2. Then the value returned by
  266. executing partialdot_product(x, y, 4, 2) is 53, which
  267. is computed by
  268. x[2] * y[2] + x[3] * y[3] = 3 * 7 + 4 * 8
  269. = 21 + 32
  270. = 53.
  271. Features: This implementation has time complexity
  272. O(length) and requires O(1) additional memory. */
  273.  
  274. double partialdot_product(double *x, double *y, int length, int index) {
  275. int i, length5;
  276. double sum = 0;
  277.  
  278. length5 = length % 5;
  279.  
  280. for (i = index; i < length5; i++) {
  281. sum += x[i] * y[i];
  282. }
  283. for (; i < length; i += 5) {
  284. sum += x[i] * y[i] + x[i + 1] * y[i + 1] + x[i + 2] * y[i + 2]
  285. + x[i + 3] * y[i + 3] + x[i + 4] * y[i + 4];
  286. }
  287.  
  288. return sum;
  289. }
  290.  
  291.  
  292. /* -------------------- subdot_product -------------------- */
  293. /* Given two arrays, the length of the second array, and
  294. an index this function returns the dot product of the
  295. two subarrays x[index : index + length] and
  296. y[0 : length]. It is necessary that index + length is
  297. at most the length of the first array.
  298.  
  299. Input variables:
  300. x : pointer to first array.
  301. y : pointer to second array.
  302. length: number of entries in y.
  303. index : starting index for subarray of x.
  304. Example: Suppose x is a pointer to the array
  305. {1, 2, 3, 4, 5}, y is a pointer to the array
  306. {-1, -2, -3}, length = 3, and index = 2. Then the value
  307. returned by executing subdot_product(x, y, 3, 2) is 53,
  308. which is computed by
  309. x[2] * y[0] + x[3] * y[1] + x[4] * y[2]
  310. = 3 * -1 + 4 * -2 + 5 * -3
  311. = - 3 - 8 - 15
  312. = -26.
  313. Features: This implementation has time complexity
  314. O(length) and requires O(1) additional memory. */
  315.  
  316. double subdot_product(double *x, double *y, int length, int index) {
  317. int i, length5;
  318. double sum = 0;
  319.  
  320. length5 = length % 5;
  321.  
  322. for (i = 0; i < length5; i++) {
  323. sum += x[i + index] * y[i];
  324. }
  325. for (; i < length; i += 5) {
  326. sum += x[i + index] * y[i] + x[i + index + 1] * y[i + 1]
  327. + x[i + index + 2] * y[i + 2]
  328. + x[i + index + 3] * y[i + 3]
  329. + x[i + index + 4] * y[i + 4];
  330. }
  331.  
  332. return sum;
  333. }
  334.  
  335. /* ----------------------- gramSchmidt ----------------------- */
  336. /* Given a matrix A of dimension m by n, this algorithm
  337. computes a QR decomposition of A, where Q is a unitary
  338. m by n matrix and R is a n by n upper triangular matrix
  339. and A = QR.
  340.  
  341. Input variables:
  342. a : pointer to array of arrays, the ith array of
  343. which should correspond to the ith column of the
  344. matrix A. During the algorithm, the columns of Q
  345. will replace the columns of A.
  346. r : pointer to array of arrays in which the ith
  347. column of the upper triangular matrix R will be
  348. stored in the ith subarray of r.
  349. m : number of columns in A.
  350. n : number of rows in A.
  351. thin: TRUE => thin QR factorization computed
  352. FALSE => full QR factorization computed
  353. Features: This implementation has time complexity O(m n^2)
  354. and requires O(1) additional memory.
  355. Remarks: Due to the nature of the problem, if A is nearly
  356. rank-deficient then the resulting columns of Q may not
  357. exhibit the orthogonality property. */
  358.  
  359. void gramSchmidt(double **a, double **r, int m, int n, bool full) {
  360. int i, j;
  361. double anorm, tol = 10e-7;
  362.  
  363. for (i = 0; i < n; i++) {
  364. r[i][i] = norm(a[i], m); // r_ii = ||a_i||
  365.  
  366. if (r[i][i] > tol) {
  367. scalar_div(a[i], r[i][i], m, a[i]); // a_i = a_i/r_ii
  368. } else if (i == 0) { // set a[0] = [1 0 0 ... 0]^T
  369. a[i][0] = 1;
  370. for (j = 1; j < m; j++) {
  371. a[i][j] = 0;
  372. }
  373. } else { // need to choose a_i orthogonal to < a_1, ... a_{i-1} >
  374. for (j = 0; j < m; j++) {
  375. a[i][j] = -a[0][i] * a[0][j];
  376. }
  377. a[i][i] += 1;
  378.  
  379. for (j = 1; j < i; j++) {
  380. scalar_sub(a[j], a[j][i], m, a[i]);
  381. }
  382.  
  383. // anorm = norm(a[i], m);
  384. // scalar_div(a[i], anorm, m, a[i]);
  385. }
  386.  
  387. for (j = i + 1; j < n; j++) {
  388. r[j][i] = dot_product(a[i], a[j], m); // r_ij = a_i*a_j
  389. scalar_sub(a[i], r[j][i], m, a[j]); // a_j -= r_ij a_i
  390. }
  391. }
  392.  
  393. /* if full QR factorization requested, we choose remaining
  394. columns of Q so that the m columns of Q form an
  395. orthonormal set */
  396. if (full) {
  397. for (; i < m; i++) {
  398. for (j = 0; j < m; j++) {
  399. a[i][j] = -a[0][i] * a[0][j];
  400. }
  401. a[i][i] += 1;
  402.  
  403. for (j = 1; j < i; j++) {
  404. scalar_sub(a[j], a[j][i], m, a[i]);
  405. }
  406.  
  407. anorm = norm(a[i], m);
  408. scalar_div(a[i], anorm, m, a[i]);
  409. }
  410. }
  411. }
  412.  
  413.  
  414. int main() {
  415. int i, j, n, m, q_n, r_m;
  416. bool full;
  417. double x;
  418.  
  419. /* let user set the dimension of matrix A */
  420. cout << "Wprowadz wymiar m (Gdzie macierz A jest macierza m na n): ";
  421. cin >> m;
  422. cout << "Wprowadz wymiar n (Gdzie macierz A jest macierza m na n): ";
  423. cin >> n;
  424.  
  425. if (m != n) {
  426. /* check if m < n */
  427. if (m < n) {
  428. printf("For a successful factorization, this implementation "
  429. "requires n <= m.\nTerminating program.\n");
  430. return 0;
  431. }
  432. /* let user choose either full or thin QR factorization */
  433. cout << "Enter either 0 to compute a thin QR factorization"
  434. << endl;
  435. cout << " or 1 to compute a full QR factorization: ";
  436. cin >> full;
  437. } else { // else m == n so full and thin QR factorization are identical */
  438. full = 1;
  439. }
  440.  
  441. /* set dimensions of matrices Q and R based on full or thin QR */
  442. if (full) { // Q is m by m and R is m by n
  443. q_n = m;
  444. r_m = m;
  445. } else { // Q is m by n and R is n by n
  446. q_n = n;
  447. r_m = n;
  448. }
  449.  
  450. /* allocate memory for the matrices A and R */
  451. double **a = new double *[q_n];
  452. double **r = new double *[n];
  453. for (i = 0; i < n; i++) {
  454. a[i] = new double[m];
  455. r[i] = new double[r_m];
  456. }
  457. for (; i < q_n; i++) {
  458. a[i] = new double[m];
  459. }
  460.  
  461. /* initialize the values in matrix A (only n columns regardless of
  462. thin QR or full QR) */
  463. for (i = 0; i < n; i++) {
  464. for (j = i; j < m; j++) {
  465. a[i][j] = j - i + 1; // this choice of values was arbitrary
  466. }
  467. }
  468.  
  469. /* print the matrix A before calling gramSchmidt */
  470. cout << "A = " << endl;
  471. for (i = 0; i < m; i++) {
  472. for (j = 0; j < n; j++) {
  473. printf("%9.6lg ", a[j][i]);
  474. }
  475. cout << endl;
  476. }
  477. cout << endl;
  478.  
  479. /* execute gramSchmidt to compute QR factorization */
  480. gramSchmidt(a, r, m, n, full);
  481.  
  482. /* print the matrix Q resulting from gramSchmidt */
  483. cout << "Q = " << endl;
  484. for (i = 0; i < m; i++) {
  485. for (j = 0; j < q_n; j++) {
  486. if (a[j][i] >= 0) {
  487. cout << " ";
  488. }
  489. printf("%9.6lg ", a[j][i]);
  490. }
  491. cout << endl;
  492. }
  493. cout << endl;
  494.  
  495. /* print the matrix R resulting from gramSchmidt */
  496. cout << "R = " << endl;
  497. for (i = 0; i < r_m; i++) {
  498. for (j = 0; j < n; j++) {
  499. printf("%9.6lg ", r[j][i]);
  500. }
  501. cout << endl;
  502. }
  503. cout << endl;
  504.  
  505. /* print numerical evidence that columns of Q are orthonormal */
  506. printf("Numerical verification that {q_1, ..., q_%i} is an "
  507. "orthonormal set:\n", q_n);
  508. for (i = 0; i < q_n; i++) {
  509. for (j = i; j < q_n; j++) {
  510. x = dot_product(a[i], a[j], m);
  511. printf("q_%i * q_%i = %lg\n", i + 1, j + 1, x);
  512. }
  513. }
  514.  
  515. /* free memory */
  516. for (i = 0; i < n; i++) {
  517. delete[] a[i];
  518. delete[] r[i];
  519. }
  520. for (; i < q_n; i++) {
  521. delete[] a[i];
  522. }
  523. delete[] a;
  524. delete[] r;
  525.  
  526. return 0; // exit main
  527. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement