sparse_matrix.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. /*!
  2. Temelia - Sparse matrix implementation source file
  3. Copyright (C) 2008 Ceata (http://ceata.org/proiecte/temelia).
  4. @author Dascalu Laurentiu
  5. This program is free software; you can redistribute it and
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 3
  8. of the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. */
  17. #include "include/sparse_matrix.h"
  18. #include "include/vector.h"
  19. #include "include/red_black_tree.h"
  20. #include <stdlib.h>
  21. struct _sparse_matrix_t
  22. {
  23. /*! tree of rows with not null keys */
  24. red_black_tree_t *rows;
  25. /*! tree of columns with not null keys */
  26. red_black_tree_t *columns;
  27. /*! number of rows */
  28. int n_rows;
  29. /*! number of columns */
  30. int n_columns;
  31. /*! maximum not null keys */
  32. int size;
  33. /*! number of not null keys */
  34. int not_null;
  35. /*! type of sparse matrix: row dense, column dense or both */
  36. int type;
  37. };
  38. struct _sparse_matrix_key_t
  39. {
  40. int index;
  41. void *key;
  42. };
  43. sparse_matrix_key_t sparse_matrix_key_new(void *user_key, int index)
  44. {
  45. sparse_matrix_key_t key;
  46. LOGGER("[sparse matrix key new] user_key %p, index %d\n", user_key, index);
  47. key = (sparse_matrix_key_t) _new(sizeof(struct _sparse_matrix_key_t));
  48. _ASSERT(key, ==, NULL, NULL_POINTER, NULL);
  49. key->key = user_key;
  50. key->index = index;
  51. return key;
  52. }
  53. void sparse_matrix_key_delete(sparse_matrix_key_t key)
  54. {
  55. _ASSERT(key, ==, NULL, NULL_POINTER,);
  56. _delete(key);
  57. }
  58. sparse_matrix_key_t sparse_matrix_key_duplicate(sparse_matrix_key_t key)
  59. {
  60. _ASSERT(key, ==, NULL, NULL_POINTER, NULL);
  61. return sparse_matrix_key_new(key->key, key->index);
  62. }
  63. int sparse_matrix_key_get_index(sparse_matrix_key_t key)
  64. {
  65. _ASSERT(key, ==, NULL, NULL_POINTER, -1);
  66. return key->index;
  67. }
  68. void *sparse_matrix_key_get_key(sparse_matrix_key_t key)
  69. {
  70. _ASSERT(key, ==, NULL, NULL_POINTER, NULL);
  71. return key->key;
  72. }
  73. void sparse_matrix_key_set_index(sparse_matrix_key_t key, int index)
  74. {
  75. _ASSERT(key, ==, NULL, NULL_POINTER,);
  76. key->index = index;
  77. }
  78. void sparse_matrix_key_set_key(sparse_matrix_key_t key, void *user_key)
  79. {
  80. _ASSERT(key, ==, NULL, NULL_POINTER,);
  81. key->key = user_key;
  82. }
  83. static int __sparse_matrix_key_simple_compare(void *key1, void *key2,
  84. void *context)
  85. {
  86. return ((sparse_matrix_key_t) key1)->index
  87. - ((sparse_matrix_key_t) key2)->index;
  88. }
  89. /*
  90. * @brief Inserts into red black tree, identified by index, the given key.
  91. */
  92. static int _sparse_matrix_insert(red_black_tree_t *tree, int index, void *key);
  93. /*
  94. * @brief Removes key from red black tree.
  95. */
  96. static void _sparse_matrix_remove(red_black_tree_t *tree, int index);
  97. /*
  98. * @brief Iterates over black tree, calling the user handler with particular
  99. * parameters for-each node of the tree.
  100. */
  101. static void _sparse_matrix_iterate(red_black_tree_t tree, void key_handler(
  102. void *key, int row, int column, void *context), void *context,
  103. int index, int order);
  104. /*
  105. * @brief Returns the key in tree with given index.
  106. */
  107. static void * _sparse_matrix_get_key_at(red_black_tree_t tree, int index);
  108. /*
  109. * @brief Simple wrapper over sparse_matrix_key_delete(), used in iteration
  110. * for library allocated keys.
  111. */
  112. static void _sparse_matrix_key_delete(void *key, void *context);
  113. /*
  114. * @brief For-each called key, inserts it into context ( a valid [red_black_tree_t *])
  115. */
  116. static void _sparse_matrix_key_duplication(void *key, void *context);
  117. #define INIT_SPARSE_MATRIX(x, n, i)\
  118. do\
  119. {\
  120. x = (red_black_tree_t *) _new(n * sizeof(red_black_tree_t));\
  121. for (i = 0 ; i < n ; i++)\
  122. x[i] = NULL;\
  123. } while (0)
  124. #define DESTROY_SPARSE_MATRIX(x, n , i)\
  125. do\
  126. {\
  127. for (i = 0 ; i < n ; i++)\
  128. {\
  129. if (x[i])\
  130. {\
  131. red_black_tree_preorder(x[i], _sparse_matrix_key_delete, NULL);\
  132. red_black_tree_delete(x[i]);\
  133. }\
  134. }\
  135. _delete(x);\
  136. } while (0)
  137. sparse_matrix_t sparse_matrix_new(int rows_number, int columns_number,
  138. int size, int type)
  139. {
  140. int i;
  141. sparse_matrix_t sparse_matrix;
  142. LOGGER("[sparse matrix new] rows %d, columns %d, size %d\n", rows_number,
  143. columns_number, size);
  144. _ASSERT(rows_number, <=, 0, INVALID_INPUT, NULL);
  145. _ASSERT(columns_number, <=, 0, INVALID_INPUT, NULL);
  146. _ASSERT(size, <=, 0, INVALID_INPUT, NULL);
  147. _ASSERT(size, >, rows_number * columns_number, INVALID_INPUT, NULL);
  148. _ASSERT(type, ==, 0, INVALID_INPUT, NULL);
  149. sparse_matrix = (sparse_matrix_t) _new(sizeof(struct _sparse_matrix_t));
  150. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
  151. sparse_matrix->not_null = 0;
  152. sparse_matrix->size = size;
  153. sparse_matrix->type = type;
  154. sparse_matrix->n_rows = rows_number;
  155. sparse_matrix->n_columns = columns_number;
  156. if (type & SPARSE_MATRIX_ROW_DENSE)
  157. INIT_SPARSE_MATRIX(sparse_matrix->rows, rows_number, i);
  158. else
  159. sparse_matrix->rows = NULL;
  160. if (type & SPARSE_MATRIX_COLUMN_DENSE)
  161. INIT_SPARSE_MATRIX(sparse_matrix->columns, columns_number, i);
  162. else
  163. sparse_matrix->columns = NULL;
  164. return sparse_matrix;
  165. }
  166. sparse_matrix_t sparse_matrix_clone(sparse_matrix_t sparse_matrix)
  167. {
  168. int i;
  169. sparse_matrix_t clone;
  170. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
  171. _ASSERT(sparse_matrix->type, ==, 0, INVALID_INPUT, NULL);
  172. clone = sparse_matrix_new(sparse_matrix->n_rows, sparse_matrix->n_columns,
  173. sparse_matrix->size, sparse_matrix->type);
  174. clone->not_null = sparse_matrix->not_null;
  175. // Starting tree duplication
  176. if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
  177. {
  178. for (i = 0; i < sparse_matrix->n_rows; i++)
  179. if (sparse_matrix->rows[i])
  180. red_black_tree_inorder(sparse_matrix->rows[i],
  181. _sparse_matrix_key_duplication, &clone->rows[i]);
  182. }
  183. if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
  184. {
  185. for (i = 0; i < sparse_matrix->n_columns; i++)
  186. if (sparse_matrix->columns[i])
  187. red_black_tree_inorder(sparse_matrix->columns[i],
  188. _sparse_matrix_key_duplication, &clone->columns[i]);
  189. }
  190. return clone;
  191. }
  192. void sparse_matrix_delete(sparse_matrix_t sparse_matrix)
  193. {
  194. int i;
  195. LOGGER("[sparse matrix delete] sparse matrix %p\n", sparse_matrix);
  196. _ASSERT(sparse_matrix, ==, 0, NULL_POINTER,);
  197. _ASSERT(sparse_matrix->type, ==, 0, INVALID_INPUT,);
  198. if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
  199. DESTROY_SPARSE_MATRIX(sparse_matrix->rows, sparse_matrix->n_rows, i);
  200. if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
  201. DESTROY_SPARSE_MATRIX(sparse_matrix->columns, sparse_matrix->n_columns, i);
  202. _delete(sparse_matrix);
  203. }
  204. int sparse_matrix_is_empty(sparse_matrix_t sparse_matrix)
  205. {
  206. LOGGER("[sparse matrix is empty] sparse matrix %p\n", sparse_matrix);
  207. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
  208. return sparse_matrix->not_null == 0;
  209. }
  210. int sparse_matrix_is_full(sparse_matrix_t sparse_matrix)
  211. {
  212. LOGGER("[sparse matrix is full] sparse matrix %p\n", sparse_matrix);
  213. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
  214. return sparse_matrix->not_null == sparse_matrix->size;
  215. }
  216. void sparse_matrix_set_key_at(sparse_matrix_t sparse_matrix, int row,
  217. int column, void *key)
  218. {
  219. // By default, increment not_null
  220. int ok = 1;
  221. LOGGER(
  222. "[sparse matrix set key at] sparse matrix %p, row %d, column %d, key %p\n",
  223. sparse_matrix, row, column, key);
  224. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER,);
  225. _ASSERT(row, <, 0, INVALID_INPUT,);
  226. _ASSERT(row, >=, sparse_matrix->n_rows, INVALID_INPUT,);
  227. _ASSERT(column, <, 0, INVALID_INPUT,);
  228. _ASSERT(column, >=, sparse_matrix->n_columns, INVALID_INPUT,);
  229. _ASSERT(sparse_matrix->type, ==, 0, INVALID_INPUT,);
  230. // Lazy initialization
  231. if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
  232. {
  233. if (sparse_matrix->columns[column] == NULL)
  234. sparse_matrix->columns[column] = red_black_tree_new(
  235. sparse_matrix_key_new(key, row));
  236. else if (_sparse_matrix_insert(&sparse_matrix->columns[column], row,
  237. key) == 0)
  238. ok = 0;
  239. }
  240. if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
  241. {
  242. if (sparse_matrix->rows[row] == NULL)
  243. sparse_matrix->rows[row] = red_black_tree_new(
  244. sparse_matrix_key_new(key, column));
  245. else if (_sparse_matrix_insert(&sparse_matrix->rows[row], column, key)
  246. == 0)
  247. ok = 0;
  248. }
  249. if (ok)
  250. sparse_matrix->not_null++;
  251. }
  252. void *sparse_matrix_get_key_at(sparse_matrix_t sparse_matrix, int row,
  253. int column, int preference)
  254. {
  255. LOGGER("[sparse matrix get key at] sparse matrix %p, row %d, column %d\n",
  256. sparse_matrix, row, column);
  257. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
  258. _ASSERT(row, <, 0, INVALID_INPUT, NULL);
  259. _ASSERT(row, >=, sparse_matrix->n_rows, INVALID_INPUT, NULL);
  260. _ASSERT(column, <, 0, INVALID_INPUT, NULL);
  261. _ASSERT(column, >=, sparse_matrix->n_columns, INVALID_INPUT, NULL);
  262. // Set row dense preference as default
  263. if (preference != -1 && preference != 1)
  264. {
  265. if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
  266. preference = 1;
  267. else if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
  268. preference = -1;
  269. preference = 0;
  270. }
  271. if (preference == 0)
  272. {
  273. // No preference given and
  274. // unknown sparse matrix type
  275. if (sparse_matrix->columns)
  276. {
  277. if (sparse_matrix->columns[column])
  278. return _sparse_matrix_get_key_at(
  279. sparse_matrix->columns[column], row);
  280. }
  281. else if (sparse_matrix->rows)
  282. {
  283. if (sparse_matrix->rows[row])
  284. return _sparse_matrix_get_key_at(sparse_matrix->rows[row],
  285. column);
  286. }
  287. }
  288. if (preference == -1)
  289. {
  290. if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
  291. return _sparse_matrix_get_key_at(sparse_matrix->columns[column],
  292. row);
  293. return NULL;
  294. }
  295. if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
  296. return _sparse_matrix_get_key_at(sparse_matrix->rows[row], column);
  297. return NULL;
  298. }
  299. void sparse_matrix_remove_key_at(sparse_matrix_t sparse_matrix, int row,
  300. int column)
  301. {
  302. LOGGER(
  303. "[sparse matrix remove key at] sparse matrix %p, row %d, column %d\n",
  304. sparse_matrix, row, column);
  305. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER,);
  306. _ASSERT(row, <, 0, INVALID_INPUT,);
  307. _ASSERT(row, >=, sparse_matrix->n_rows, INVALID_INPUT,);
  308. _ASSERT(column, <, 0, INVALID_INPUT,);
  309. _ASSERT(column, >=, sparse_matrix->n_columns, INVALID_INPUT,);
  310. _ASSERT(sparse_matrix->columns, ==, NULL, NULL_POINTER,);
  311. _ASSERT(sparse_matrix->columns[column], ==, NULL, NULL_POINTER,);
  312. _ASSERT(sparse_matrix->rows, ==, NULL, NULL_POINTER,);
  313. _ASSERT(sparse_matrix->rows[row], ==, NULL, NULL_POINTER,);
  314. if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
  315. _sparse_matrix_remove(&sparse_matrix->columns[column], row);
  316. if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
  317. _sparse_matrix_remove(&sparse_matrix->rows[row], column);
  318. }
  319. int sparse_matrix_get_rows_number(sparse_matrix_t sparse_matrix)
  320. {
  321. LOGGER("[sparse matrix get rows number] sparse matrix %p\n", sparse_matrix);
  322. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
  323. return sparse_matrix->n_rows;
  324. }
  325. int sparse_matrix_get_columns_number(sparse_matrix_t sparse_matrix)
  326. {
  327. LOGGER("[sparse matrix get columns number] sparse matrix %p\n",
  328. sparse_matrix);
  329. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
  330. return sparse_matrix->n_columns;
  331. }
  332. int sparse_matrix_get_size(sparse_matrix_t sparse_matrix)
  333. {
  334. LOGGER("[sparse matrix get size] sparse matrix %p\n", sparse_matrix);
  335. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
  336. return sparse_matrix->size;
  337. }
  338. int sparse_matrix_get_type(sparse_matrix_t sparse_matrix)
  339. {
  340. LOGGER("[sparse matrix get type] sparse matrix %p\n", sparse_matrix);
  341. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
  342. return sparse_matrix->type;
  343. }
  344. int sparse_matrix_get_not_null_keys(sparse_matrix_t sparse_matrix)
  345. {
  346. LOGGER("[sparse matrix get not null keys] sparse matrix %p\n",
  347. sparse_matrix);
  348. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
  349. return sparse_matrix->not_null;
  350. }
  351. void *sparse_matrix_get_rows(sparse_matrix_t sparse_matrix)
  352. {
  353. LOGGER("[sparse matrix get rows] sparse matrix %p\n", sparse_matrix);
  354. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
  355. return sparse_matrix->rows;
  356. }
  357. void *sparse_matrix_get_columns(sparse_matrix_t sparse_matrix)
  358. {
  359. LOGGER("[sparse matrix get columns] sparse matrix %p\n", sparse_matrix);
  360. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
  361. return sparse_matrix->columns;
  362. }
  363. int _sparse_matrix_transpose_type(int type)
  364. {
  365. if (type == SPARSE_MATRIX_ROW_DENSE)
  366. return SPARSE_MATRIX_COLUMN_DENSE;
  367. else if (type == SPARSE_MATRIX_COLUMN_DENSE)
  368. return SPARSE_MATRIX_ROW_DENSE;
  369. return type;
  370. }
  371. sparse_matrix_t sparse_matrix_transpose(sparse_matrix_t sparse_matrix)
  372. {
  373. int i;
  374. sparse_matrix_t transpose;
  375. transpose = sparse_matrix_new(sparse_matrix->n_columns,
  376. sparse_matrix->n_rows, sparse_matrix->size,
  377. _sparse_matrix_transpose_type(sparse_matrix->type));
  378. transpose->not_null = sparse_matrix->not_null;
  379. // Starting tree duplication
  380. if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
  381. {
  382. for (i = 0; i < sparse_matrix->n_rows; i++)
  383. if (sparse_matrix->rows[i])
  384. red_black_tree_inorder(sparse_matrix->rows[i],
  385. _sparse_matrix_key_duplication, &transpose->columns[i]);
  386. }
  387. if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
  388. {
  389. for (i = 0; i < sparse_matrix->n_columns; i++)
  390. if (sparse_matrix->columns[i])
  391. red_black_tree_inorder(sparse_matrix->columns[i],
  392. _sparse_matrix_key_duplication, &transpose->rows[i]);
  393. }
  394. return transpose;
  395. }
  396. void sparse_matrix_iterate(sparse_matrix_t sparse_matrix, void key_handler(
  397. void *key, int row, int column, void *context), void *context,
  398. int order)
  399. {
  400. int i;
  401. LOGGER(
  402. "[sparse matrix iterate] sparse matrix %p, key_handler %p, context %p, order %d\n",
  403. sparse_matrix, key_handler, context, order);
  404. _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER,);
  405. _ASSERT(key_handler, ==, NULL, NULL_POINTER,);
  406. switch (order)
  407. {
  408. case -1:
  409. {
  410. if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
  411. {
  412. for (i = 0; i < sparse_matrix->n_rows; i++)
  413. if (sparse_matrix->rows[i])
  414. _sparse_matrix_iterate(sparse_matrix->rows[i], key_handler,
  415. context, i, order);
  416. }
  417. }
  418. break;
  419. case 1:
  420. {
  421. if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
  422. {
  423. for (i = 0; i < sparse_matrix->n_columns; i++)
  424. if (sparse_matrix->columns[i])
  425. _sparse_matrix_iterate(sparse_matrix->columns[i],
  426. key_handler, context, i, order);
  427. }
  428. }
  429. break;
  430. default:
  431. _ASSERT(1, ==, 1, INVALID_INPUT,);
  432. }
  433. }
  434. #define GENERATE_RESIZE(trees, old_val, new_val)\
  435. do\
  436. {\
  437. for (i = new_val; i < old_val; i++)\
  438. {\
  439. red_black_tree_preorder(trees[i], _sparse_matrix_key_delete, NULL);\
  440. red_black_tree_delete(trees[i]);\
  441. trees[i] = NULL;\
  442. }\
  443. \
  444. if (old_val < new_val)\
  445. {\
  446. trees = _realloc(trees, columns * sizeof(red_black_tree_t));\
  447. _ASSERT(trees, ==, NULL, NULL_POINTER,);\
  448. \
  449. for (i = old_val; i < new_val; i++)\
  450. trees[i] = NULL;\
  451. }\
  452. old_val = new_val;\
  453. }\
  454. while(0)\
  455. void sparse_matrix_resize(sparse_matrix_t sparse_matrix, int rows, int columns,
  456. int size)
  457. {
  458. int i;
  459. LOGGER("[sparse matrix resize] matrix %p, rows %d, columns %d, size %d\n",
  460. sparse_matrix, rows, columns, size);
  461. _ASSERT(sparse_matrix, ==, NULL, INVALID_INPUT,);
  462. _ASSERT(rows, <=, 0, INVALID_INPUT,);
  463. _ASSERT(columns, <=, 0, INVALID_INPUT,);
  464. _ASSERT(size, >, sparse_matrix->size, INVALID_INPUT,);
  465. sparse_matrix->size = size;
  466. // Columns
  467. if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
  468. GENERATE_RESIZE(sparse_matrix->columns, sparse_matrix->n_columns, columns);
  469. else
  470. sparse_matrix->n_columns = columns;
  471. // Rows
  472. if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
  473. GENERATE_RESIZE(sparse_matrix->rows, sparse_matrix->n_rows, rows);
  474. else
  475. sparse_matrix->n_rows = rows;
  476. }
  477. static int _sparse_matrix_key_compare(void *key1, void *key2, void *context)
  478. {
  479. sparse_matrix_key_t v1 = (sparse_matrix_key_t) key1;
  480. sparse_matrix_key_t v2 = (sparse_matrix_key_t) key2;
  481. if (v1->index == v2->index)
  482. {
  483. // Hack for key stored update operation
  484. if (v1->key == context)
  485. v2->key = context;
  486. else if (v2->key == context)
  487. v1->key = context;
  488. else
  489. _ASSERT(1, ==, 1, INVALID_INPUT, -1);
  490. }
  491. // Order after their indices
  492. return v1->index - v2->index;
  493. }
  494. static int _sparse_matrix_insert(red_black_tree_t *tree, int index, void *key)
  495. {
  496. int result;
  497. sparse_matrix_key_t pair = sparse_matrix_key_new(key, index);
  498. _ASSERT(pair, ==, NULL, NULL_POINTER, -1);
  499. result = red_black_tree_insert(tree, pair, _sparse_matrix_key_compare, key,
  500. 1) != NULL;
  501. // Key already exists
  502. if (result == 0)
  503. sparse_matrix_key_delete(pair);
  504. return result;
  505. }
  506. static int __sparse_matrix_remove(void *key1, void *key2, void *context)
  507. {
  508. int result = ((sparse_matrix_key_t) key1)->index
  509. - ((sparse_matrix_key_t) key2)->index;
  510. if (result == 0 && key1 != key2)
  511. {
  512. if (((sparse_matrix_key_t) key1)->key)
  513. *(void **) context = key1;
  514. else if (((sparse_matrix_key_t) key2)->key)
  515. *(void **) context = key2;
  516. }
  517. return result;
  518. }
  519. static void _sparse_matrix_remove(red_black_tree_t *tree, int index)
  520. {
  521. void *context = NULL;
  522. sparse_matrix_key_t pair = sparse_matrix_key_new(NULL, index);
  523. /*
  524. * This is a true hack. When you don't have a reference to the key
  525. * you can create a new one, pair in this example, then
  526. * remove as key as usually. Deleting only your new key
  527. * will result in a memory leak (the old key is not freed).
  528. * Declare a context and save the old key there, while iterating in tree.
  529. *
  530. * See __sparse_matrix_remove how you can do this.
  531. */
  532. red_black_tree_remove(tree, pair, __sparse_matrix_remove, &context, 1);
  533. sparse_matrix_key_delete(pair);
  534. if (context)
  535. sparse_matrix_key_delete(context);
  536. }
  537. static void __sparse_matrix_iterate(void *key, void *context)
  538. {
  539. vector_t vector = (vector_t) context;
  540. sparse_matrix_key_t real_key = (sparse_matrix_key_t) key;
  541. int order;
  542. int index;
  543. void *real_context;
  544. void (*key_handler)(void *key, int row, int column, void *context);
  545. order = *(int *) vector_get_key_at(vector, 3);
  546. index = *(int *) vector_get_key_at(vector, 2);
  547. real_context = (void*) vector_get_key_at(vector, 1);
  548. key_handler = (void(*)(void *, int, int, void *)) vector_get_key_at(vector,
  549. 0);
  550. if (order == -1)
  551. key_handler(real_key->key, index, real_key->index, real_context);
  552. else if (order == 1)
  553. key_handler(real_key->key, real_key->index, index, real_context);
  554. }
  555. static void _sparse_matrix_iterate(red_black_tree_t tree, void key_handler(
  556. void *key, int row, int column, void *context), void *context,
  557. int index, int order)
  558. {
  559. vector_t vector = vector_new(16);
  560. _ASSERT(vector, ==, NULL, NULL_POINTER,);
  561. vector_push_back(vector, key_handler);
  562. vector_push_back(vector, context);
  563. vector_push_back(vector, &index);
  564. vector_push_back(vector, &order);
  565. red_black_tree_inorder(tree, __sparse_matrix_iterate, vector);
  566. vector_delete(vector);
  567. }
  568. static void _sparse_matrix_key_delete(void *key, void *context)
  569. {
  570. sparse_matrix_key_delete(key);
  571. }
  572. static void * _sparse_matrix_get_key_at(red_black_tree_t tree, int index)
  573. {
  574. red_black_tree_t node;
  575. sparse_matrix_key_t key;
  576. _ASSERT(tree, ==, NULL, NULL_POINTER, NULL);
  577. key = sparse_matrix_key_new(NULL, index);
  578. node = red_black_tree_search(tree, key, __sparse_matrix_key_simple_compare,
  579. NULL);
  580. sparse_matrix_key_delete(key);
  581. return node ? sparse_matrix_key_get_key(red_black_tree_get_key(node))
  582. : NULL;
  583. }
  584. static void _sparse_matrix_key_duplication(void *key, void *context)
  585. {
  586. sparse_matrix_key_t m_key = (sparse_matrix_key_t) key;
  587. red_black_tree_t *m_tree = (red_black_tree_t *) context;
  588. // Lazy initialization on transposing sparse matrix
  589. if (*m_tree == NULL)
  590. *m_tree = red_black_tree_new(sparse_matrix_key_duplicate(m_key));
  591. else
  592. red_black_tree_insert(m_tree, sparse_matrix_key_duplicate(m_key),
  593. __sparse_matrix_key_simple_compare, NULL, 1);
  594. }