123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- /*!
- Temelia - Sparse matrix implementation source file
- Copyright (C) 2008 Ceata (http://ceata.org/proiecte/temelia).
- @author Dascalu Laurentiu
- This program is free software; you can redistribute it and
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 3
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
- #include "include/sparse_matrix.h"
- #include "include/vector.h"
- #include "include/red_black_tree.h"
- #include <stdlib.h>
- struct _sparse_matrix_t
- {
- /*! tree of rows with not null keys */
- red_black_tree_t *rows;
- /*! tree of columns with not null keys */
- red_black_tree_t *columns;
- /*! number of rows */
- int n_rows;
- /*! number of columns */
- int n_columns;
- /*! maximum not null keys */
- int size;
- /*! number of not null keys */
- int not_null;
- /*! type of sparse matrix: row dense, column dense or both */
- int type;
- };
- struct _sparse_matrix_key_t
- {
- int index;
- void *key;
- };
- sparse_matrix_key_t sparse_matrix_key_new(void *user_key, int index)
- {
- sparse_matrix_key_t key;
- LOGGER("[sparse matrix key new] user_key %p, index %d\n", user_key, index);
- key = (sparse_matrix_key_t) _new(sizeof(struct _sparse_matrix_key_t));
- _ASSERT(key, ==, NULL, NULL_POINTER, NULL);
- key->key = user_key;
- key->index = index;
- return key;
- }
- void sparse_matrix_key_delete(sparse_matrix_key_t key)
- {
- _ASSERT(key, ==, NULL, NULL_POINTER,);
- _delete(key);
- }
- sparse_matrix_key_t sparse_matrix_key_duplicate(sparse_matrix_key_t key)
- {
- _ASSERT(key, ==, NULL, NULL_POINTER, NULL);
- return sparse_matrix_key_new(key->key, key->index);
- }
- int sparse_matrix_key_get_index(sparse_matrix_key_t key)
- {
- _ASSERT(key, ==, NULL, NULL_POINTER, -1);
- return key->index;
- }
- void *sparse_matrix_key_get_key(sparse_matrix_key_t key)
- {
- _ASSERT(key, ==, NULL, NULL_POINTER, NULL);
- return key->key;
- }
- void sparse_matrix_key_set_index(sparse_matrix_key_t key, int index)
- {
- _ASSERT(key, ==, NULL, NULL_POINTER,);
- key->index = index;
- }
- void sparse_matrix_key_set_key(sparse_matrix_key_t key, void *user_key)
- {
- _ASSERT(key, ==, NULL, NULL_POINTER,);
- key->key = user_key;
- }
- static int __sparse_matrix_key_simple_compare(void *key1, void *key2,
- void *context)
- {
- return ((sparse_matrix_key_t) key1)->index
- - ((sparse_matrix_key_t) key2)->index;
- }
- /*
- * @brief Inserts into red black tree, identified by index, the given key.
- */
- static int _sparse_matrix_insert(red_black_tree_t *tree, int index, void *key);
- /*
- * @brief Removes key from red black tree.
- */
- static void _sparse_matrix_remove(red_black_tree_t *tree, int index);
- /*
- * @brief Iterates over black tree, calling the user handler with particular
- * parameters for-each node of the tree.
- */
- static void _sparse_matrix_iterate(red_black_tree_t tree, void key_handler(
- void *key, int row, int column, void *context), void *context,
- int index, int order);
- /*
- * @brief Returns the key in tree with given index.
- */
- static void * _sparse_matrix_get_key_at(red_black_tree_t tree, int index);
- /*
- * @brief Simple wrapper over sparse_matrix_key_delete(), used in iteration
- * for library allocated keys.
- */
- static void _sparse_matrix_key_delete(void *key, void *context);
- /*
- * @brief For-each called key, inserts it into context ( a valid [red_black_tree_t *])
- */
- static void _sparse_matrix_key_duplication(void *key, void *context);
- #define INIT_SPARSE_MATRIX(x, n, i)\
- do\
- {\
- x = (red_black_tree_t *) _new(n * sizeof(red_black_tree_t));\
- for (i = 0 ; i < n ; i++)\
- x[i] = NULL;\
- } while (0)
- #define DESTROY_SPARSE_MATRIX(x, n , i)\
- do\
- {\
- for (i = 0 ; i < n ; i++)\
- {\
- if (x[i])\
- {\
- red_black_tree_preorder(x[i], _sparse_matrix_key_delete, NULL);\
- red_black_tree_delete(x[i]);\
- }\
- }\
- _delete(x);\
- } while (0)
- sparse_matrix_t sparse_matrix_new(int rows_number, int columns_number,
- int size, int type)
- {
- int i;
- sparse_matrix_t sparse_matrix;
- LOGGER("[sparse matrix new] rows %d, columns %d, size %d\n", rows_number,
- columns_number, size);
- _ASSERT(rows_number, <=, 0, INVALID_INPUT, NULL);
- _ASSERT(columns_number, <=, 0, INVALID_INPUT, NULL);
- _ASSERT(size, <=, 0, INVALID_INPUT, NULL);
- _ASSERT(size, >, rows_number * columns_number, INVALID_INPUT, NULL);
- _ASSERT(type, ==, 0, INVALID_INPUT, NULL);
- sparse_matrix = (sparse_matrix_t) _new(sizeof(struct _sparse_matrix_t));
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
- sparse_matrix->not_null = 0;
- sparse_matrix->size = size;
- sparse_matrix->type = type;
- sparse_matrix->n_rows = rows_number;
- sparse_matrix->n_columns = columns_number;
- if (type & SPARSE_MATRIX_ROW_DENSE)
- INIT_SPARSE_MATRIX(sparse_matrix->rows, rows_number, i);
- else
- sparse_matrix->rows = NULL;
- if (type & SPARSE_MATRIX_COLUMN_DENSE)
- INIT_SPARSE_MATRIX(sparse_matrix->columns, columns_number, i);
- else
- sparse_matrix->columns = NULL;
- return sparse_matrix;
- }
- sparse_matrix_t sparse_matrix_clone(sparse_matrix_t sparse_matrix)
- {
- int i;
- sparse_matrix_t clone;
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
- _ASSERT(sparse_matrix->type, ==, 0, INVALID_INPUT, NULL);
- clone = sparse_matrix_new(sparse_matrix->n_rows, sparse_matrix->n_columns,
- sparse_matrix->size, sparse_matrix->type);
- clone->not_null = sparse_matrix->not_null;
- // Starting tree duplication
- if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
- {
- for (i = 0; i < sparse_matrix->n_rows; i++)
- if (sparse_matrix->rows[i])
- red_black_tree_inorder(sparse_matrix->rows[i],
- _sparse_matrix_key_duplication, &clone->rows[i]);
- }
- if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
- {
- for (i = 0; i < sparse_matrix->n_columns; i++)
- if (sparse_matrix->columns[i])
- red_black_tree_inorder(sparse_matrix->columns[i],
- _sparse_matrix_key_duplication, &clone->columns[i]);
- }
- return clone;
- }
- void sparse_matrix_delete(sparse_matrix_t sparse_matrix)
- {
- int i;
- LOGGER("[sparse matrix delete] sparse matrix %p\n", sparse_matrix);
- _ASSERT(sparse_matrix, ==, 0, NULL_POINTER,);
- _ASSERT(sparse_matrix->type, ==, 0, INVALID_INPUT,);
- if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
- DESTROY_SPARSE_MATRIX(sparse_matrix->rows, sparse_matrix->n_rows, i);
- if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
- DESTROY_SPARSE_MATRIX(sparse_matrix->columns, sparse_matrix->n_columns, i);
- _delete(sparse_matrix);
- }
- int sparse_matrix_is_empty(sparse_matrix_t sparse_matrix)
- {
- LOGGER("[sparse matrix is empty] sparse matrix %p\n", sparse_matrix);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
- return sparse_matrix->not_null == 0;
- }
- int sparse_matrix_is_full(sparse_matrix_t sparse_matrix)
- {
- LOGGER("[sparse matrix is full] sparse matrix %p\n", sparse_matrix);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
- return sparse_matrix->not_null == sparse_matrix->size;
- }
- void sparse_matrix_set_key_at(sparse_matrix_t sparse_matrix, int row,
- int column, void *key)
- {
- // By default, increment not_null
- int ok = 1;
- LOGGER(
- "[sparse matrix set key at] sparse matrix %p, row %d, column %d, key %p\n",
- sparse_matrix, row, column, key);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER,);
- _ASSERT(row, <, 0, INVALID_INPUT,);
- _ASSERT(row, >=, sparse_matrix->n_rows, INVALID_INPUT,);
- _ASSERT(column, <, 0, INVALID_INPUT,);
- _ASSERT(column, >=, sparse_matrix->n_columns, INVALID_INPUT,);
- _ASSERT(sparse_matrix->type, ==, 0, INVALID_INPUT,);
- // Lazy initialization
- if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
- {
- if (sparse_matrix->columns[column] == NULL)
- sparse_matrix->columns[column] = red_black_tree_new(
- sparse_matrix_key_new(key, row));
- else if (_sparse_matrix_insert(&sparse_matrix->columns[column], row,
- key) == 0)
- ok = 0;
- }
- if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
- {
- if (sparse_matrix->rows[row] == NULL)
- sparse_matrix->rows[row] = red_black_tree_new(
- sparse_matrix_key_new(key, column));
- else if (_sparse_matrix_insert(&sparse_matrix->rows[row], column, key)
- == 0)
- ok = 0;
- }
- if (ok)
- sparse_matrix->not_null++;
- }
- void *sparse_matrix_get_key_at(sparse_matrix_t sparse_matrix, int row,
- int column, int preference)
- {
- LOGGER("[sparse matrix get key at] sparse matrix %p, row %d, column %d\n",
- sparse_matrix, row, column);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
- _ASSERT(row, <, 0, INVALID_INPUT, NULL);
- _ASSERT(row, >=, sparse_matrix->n_rows, INVALID_INPUT, NULL);
- _ASSERT(column, <, 0, INVALID_INPUT, NULL);
- _ASSERT(column, >=, sparse_matrix->n_columns, INVALID_INPUT, NULL);
- // Set row dense preference as default
- if (preference != -1 && preference != 1)
- {
- if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
- preference = 1;
- else if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
- preference = -1;
- preference = 0;
- }
- if (preference == 0)
- {
- // No preference given and
- // unknown sparse matrix type
- if (sparse_matrix->columns)
- {
- if (sparse_matrix->columns[column])
- return _sparse_matrix_get_key_at(
- sparse_matrix->columns[column], row);
- }
- else if (sparse_matrix->rows)
- {
- if (sparse_matrix->rows[row])
- return _sparse_matrix_get_key_at(sparse_matrix->rows[row],
- column);
- }
- }
- if (preference == -1)
- {
- if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
- return _sparse_matrix_get_key_at(sparse_matrix->columns[column],
- row);
- return NULL;
- }
- if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
- return _sparse_matrix_get_key_at(sparse_matrix->rows[row], column);
- return NULL;
- }
- void sparse_matrix_remove_key_at(sparse_matrix_t sparse_matrix, int row,
- int column)
- {
- LOGGER(
- "[sparse matrix remove key at] sparse matrix %p, row %d, column %d\n",
- sparse_matrix, row, column);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER,);
- _ASSERT(row, <, 0, INVALID_INPUT,);
- _ASSERT(row, >=, sparse_matrix->n_rows, INVALID_INPUT,);
- _ASSERT(column, <, 0, INVALID_INPUT,);
- _ASSERT(column, >=, sparse_matrix->n_columns, INVALID_INPUT,);
- _ASSERT(sparse_matrix->columns, ==, NULL, NULL_POINTER,);
- _ASSERT(sparse_matrix->columns[column], ==, NULL, NULL_POINTER,);
- _ASSERT(sparse_matrix->rows, ==, NULL, NULL_POINTER,);
- _ASSERT(sparse_matrix->rows[row], ==, NULL, NULL_POINTER,);
- if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
- _sparse_matrix_remove(&sparse_matrix->columns[column], row);
- if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
- _sparse_matrix_remove(&sparse_matrix->rows[row], column);
- }
- int sparse_matrix_get_rows_number(sparse_matrix_t sparse_matrix)
- {
- LOGGER("[sparse matrix get rows number] sparse matrix %p\n", sparse_matrix);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
- return sparse_matrix->n_rows;
- }
- int sparse_matrix_get_columns_number(sparse_matrix_t sparse_matrix)
- {
- LOGGER("[sparse matrix get columns number] sparse matrix %p\n",
- sparse_matrix);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
- return sparse_matrix->n_columns;
- }
- int sparse_matrix_get_size(sparse_matrix_t sparse_matrix)
- {
- LOGGER("[sparse matrix get size] sparse matrix %p\n", sparse_matrix);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
- return sparse_matrix->size;
- }
- int sparse_matrix_get_type(sparse_matrix_t sparse_matrix)
- {
- LOGGER("[sparse matrix get type] sparse matrix %p\n", sparse_matrix);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
- return sparse_matrix->type;
- }
- int sparse_matrix_get_not_null_keys(sparse_matrix_t sparse_matrix)
- {
- LOGGER("[sparse matrix get not null keys] sparse matrix %p\n",
- sparse_matrix);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, -1);
- return sparse_matrix->not_null;
- }
- void *sparse_matrix_get_rows(sparse_matrix_t sparse_matrix)
- {
- LOGGER("[sparse matrix get rows] sparse matrix %p\n", sparse_matrix);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
- return sparse_matrix->rows;
- }
- void *sparse_matrix_get_columns(sparse_matrix_t sparse_matrix)
- {
- LOGGER("[sparse matrix get columns] sparse matrix %p\n", sparse_matrix);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER, NULL);
- return sparse_matrix->columns;
- }
- int _sparse_matrix_transpose_type(int type)
- {
- if (type == SPARSE_MATRIX_ROW_DENSE)
- return SPARSE_MATRIX_COLUMN_DENSE;
- else if (type == SPARSE_MATRIX_COLUMN_DENSE)
- return SPARSE_MATRIX_ROW_DENSE;
- return type;
- }
- sparse_matrix_t sparse_matrix_transpose(sparse_matrix_t sparse_matrix)
- {
- int i;
- sparse_matrix_t transpose;
- transpose = sparse_matrix_new(sparse_matrix->n_columns,
- sparse_matrix->n_rows, sparse_matrix->size,
- _sparse_matrix_transpose_type(sparse_matrix->type));
- transpose->not_null = sparse_matrix->not_null;
- // Starting tree duplication
- if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
- {
- for (i = 0; i < sparse_matrix->n_rows; i++)
- if (sparse_matrix->rows[i])
- red_black_tree_inorder(sparse_matrix->rows[i],
- _sparse_matrix_key_duplication, &transpose->columns[i]);
- }
- if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
- {
- for (i = 0; i < sparse_matrix->n_columns; i++)
- if (sparse_matrix->columns[i])
- red_black_tree_inorder(sparse_matrix->columns[i],
- _sparse_matrix_key_duplication, &transpose->rows[i]);
- }
- return transpose;
- }
- void sparse_matrix_iterate(sparse_matrix_t sparse_matrix, void key_handler(
- void *key, int row, int column, void *context), void *context,
- int order)
- {
- int i;
- LOGGER(
- "[sparse matrix iterate] sparse matrix %p, key_handler %p, context %p, order %d\n",
- sparse_matrix, key_handler, context, order);
- _ASSERT(sparse_matrix, ==, NULL, NULL_POINTER,);
- _ASSERT(key_handler, ==, NULL, NULL_POINTER,);
- switch (order)
- {
- case -1:
- {
- if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
- {
- for (i = 0; i < sparse_matrix->n_rows; i++)
- if (sparse_matrix->rows[i])
- _sparse_matrix_iterate(sparse_matrix->rows[i], key_handler,
- context, i, order);
- }
- }
- break;
- case 1:
- {
- if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
- {
- for (i = 0; i < sparse_matrix->n_columns; i++)
- if (sparse_matrix->columns[i])
- _sparse_matrix_iterate(sparse_matrix->columns[i],
- key_handler, context, i, order);
- }
- }
- break;
- default:
- _ASSERT(1, ==, 1, INVALID_INPUT,);
- }
- }
- #define GENERATE_RESIZE(trees, old_val, new_val)\
- do\
- {\
- for (i = new_val; i < old_val; i++)\
- {\
- red_black_tree_preorder(trees[i], _sparse_matrix_key_delete, NULL);\
- red_black_tree_delete(trees[i]);\
- trees[i] = NULL;\
- }\
- \
- if (old_val < new_val)\
- {\
- trees = _realloc(trees, columns * sizeof(red_black_tree_t));\
- _ASSERT(trees, ==, NULL, NULL_POINTER,);\
- \
- for (i = old_val; i < new_val; i++)\
- trees[i] = NULL;\
- }\
- old_val = new_val;\
- }\
- while(0)\
- void sparse_matrix_resize(sparse_matrix_t sparse_matrix, int rows, int columns,
- int size)
- {
- int i;
- LOGGER("[sparse matrix resize] matrix %p, rows %d, columns %d, size %d\n",
- sparse_matrix, rows, columns, size);
- _ASSERT(sparse_matrix, ==, NULL, INVALID_INPUT,);
- _ASSERT(rows, <=, 0, INVALID_INPUT,);
- _ASSERT(columns, <=, 0, INVALID_INPUT,);
- _ASSERT(size, >, sparse_matrix->size, INVALID_INPUT,);
- sparse_matrix->size = size;
- // Columns
- if (sparse_matrix->type & SPARSE_MATRIX_COLUMN_DENSE)
- GENERATE_RESIZE(sparse_matrix->columns, sparse_matrix->n_columns, columns);
- else
- sparse_matrix->n_columns = columns;
- // Rows
- if (sparse_matrix->type & SPARSE_MATRIX_ROW_DENSE)
- GENERATE_RESIZE(sparse_matrix->rows, sparse_matrix->n_rows, rows);
- else
- sparse_matrix->n_rows = rows;
- }
- static int _sparse_matrix_key_compare(void *key1, void *key2, void *context)
- {
- sparse_matrix_key_t v1 = (sparse_matrix_key_t) key1;
- sparse_matrix_key_t v2 = (sparse_matrix_key_t) key2;
- if (v1->index == v2->index)
- {
- // Hack for key stored update operation
- if (v1->key == context)
- v2->key = context;
- else if (v2->key == context)
- v1->key = context;
- else
- _ASSERT(1, ==, 1, INVALID_INPUT, -1);
- }
- // Order after their indices
- return v1->index - v2->index;
- }
- static int _sparse_matrix_insert(red_black_tree_t *tree, int index, void *key)
- {
- int result;
- sparse_matrix_key_t pair = sparse_matrix_key_new(key, index);
- _ASSERT(pair, ==, NULL, NULL_POINTER, -1);
- result = red_black_tree_insert(tree, pair, _sparse_matrix_key_compare, key,
- 1) != NULL;
- // Key already exists
- if (result == 0)
- sparse_matrix_key_delete(pair);
- return result;
- }
- static int __sparse_matrix_remove(void *key1, void *key2, void *context)
- {
- int result = ((sparse_matrix_key_t) key1)->index
- - ((sparse_matrix_key_t) key2)->index;
- if (result == 0 && key1 != key2)
- {
- if (((sparse_matrix_key_t) key1)->key)
- *(void **) context = key1;
- else if (((sparse_matrix_key_t) key2)->key)
- *(void **) context = key2;
- }
- return result;
- }
- static void _sparse_matrix_remove(red_black_tree_t *tree, int index)
- {
- void *context = NULL;
- sparse_matrix_key_t pair = sparse_matrix_key_new(NULL, index);
- /*
- * This is a true hack. When you don't have a reference to the key
- * you can create a new one, pair in this example, then
- * remove as key as usually. Deleting only your new key
- * will result in a memory leak (the old key is not freed).
- * Declare a context and save the old key there, while iterating in tree.
- *
- * See __sparse_matrix_remove how you can do this.
- */
- red_black_tree_remove(tree, pair, __sparse_matrix_remove, &context, 1);
- sparse_matrix_key_delete(pair);
- if (context)
- sparse_matrix_key_delete(context);
- }
- static void __sparse_matrix_iterate(void *key, void *context)
- {
- vector_t vector = (vector_t) context;
- sparse_matrix_key_t real_key = (sparse_matrix_key_t) key;
- int order;
- int index;
- void *real_context;
- void (*key_handler)(void *key, int row, int column, void *context);
- order = *(int *) vector_get_key_at(vector, 3);
- index = *(int *) vector_get_key_at(vector, 2);
- real_context = (void*) vector_get_key_at(vector, 1);
- key_handler = (void(*)(void *, int, int, void *)) vector_get_key_at(vector,
- 0);
- if (order == -1)
- key_handler(real_key->key, index, real_key->index, real_context);
- else if (order == 1)
- key_handler(real_key->key, real_key->index, index, real_context);
- }
- static void _sparse_matrix_iterate(red_black_tree_t tree, void key_handler(
- void *key, int row, int column, void *context), void *context,
- int index, int order)
- {
- vector_t vector = vector_new(16);
- _ASSERT(vector, ==, NULL, NULL_POINTER,);
- vector_push_back(vector, key_handler);
- vector_push_back(vector, context);
- vector_push_back(vector, &index);
- vector_push_back(vector, &order);
- red_black_tree_inorder(tree, __sparse_matrix_iterate, vector);
- vector_delete(vector);
- }
- static void _sparse_matrix_key_delete(void *key, void *context)
- {
- sparse_matrix_key_delete(key);
- }
- static void * _sparse_matrix_get_key_at(red_black_tree_t tree, int index)
- {
- red_black_tree_t node;
- sparse_matrix_key_t key;
- _ASSERT(tree, ==, NULL, NULL_POINTER, NULL);
- key = sparse_matrix_key_new(NULL, index);
- node = red_black_tree_search(tree, key, __sparse_matrix_key_simple_compare,
- NULL);
- sparse_matrix_key_delete(key);
- return node ? sparse_matrix_key_get_key(red_black_tree_get_key(node))
- : NULL;
- }
- static void _sparse_matrix_key_duplication(void *key, void *context)
- {
- sparse_matrix_key_t m_key = (sparse_matrix_key_t) key;
- red_black_tree_t *m_tree = (red_black_tree_t *) context;
- // Lazy initialization on transposing sparse matrix
- if (*m_tree == NULL)
- *m_tree = red_black_tree_new(sparse_matrix_key_duplicate(m_key));
- else
- red_black_tree_insert(m_tree, sparse_matrix_key_duplicate(m_key),
- __sparse_matrix_key_simple_compare, NULL, 1);
- }
|