00001 /*************************************************************************** 00002 * @file gnn_node_vector.c 00003 * @brief gnn_node_vector Implementation. 00004 * 00005 * @date : 30-09-03 20:18 00006 * @author : Pedro Ortega C. <peortega@dcc.uchile.cl> 00007 * Copyright 2003 Pedro Ortega C. 00008 ****************************************************************************/ 00009 /* 00010 * This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with this program; if not, write to the Free Software 00022 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00023 */ 00024 00025 /** 00026 * @defgroup gnn_node_vector_doc gnn_node_vector : Vector of nodes. 00027 * @ingroup gnn_node_doc 00028 * 00029 * A node vector is a vector which can contain \em pointers to nodes. 00030 * 00031 * Node vectors are defined by a \ref gnn_node_vector structure which 00032 * describes a slice of an array of \ref gnn_node pointers. Different 00033 * vectors can be created which point to the same block. A vector 00034 * slice is a set of equally-spaced elements of an area of memory. 00035 * 00036 * The \ref gnn_node_vector structure contains five components, 00037 * the size, the stride, a pointer to the memory where the elements are stored, data, a pointer to the block owned by the vector, block, if any, and an ownership flag, owner. The structure is very simple and looks like this, 00038 * 00039 * \code 00040 * typedef struct 00041 * { 00042 * size_t size; 00043 * size_t stride; 00044 * size_t blocksize; 00045 * double * data; 00046 * int owner; 00047 * } gnn_node_vector; 00048 * \endcode 00049 * 00050 * The \em size corresponds to the number of vector elements. The valid indices 00051 * are 0, 1, 2, ..., \em size-1. The \em stride is the step size from one 00052 * element to another in physical memory, measured in \c sizeof(gnn_node*). 00053 * The pointer \em data points to the first vector element. If the vector 00054 * own this pointer array, i.e. if it was created and will be destroyed with 00055 * it, then \em owner is equal to 1. If it doesn't own the array, then 00056 * \em owner is 0, and at deallocation of the \ref gnn_node_vector, the 00057 * array isn't deallocated. The \em blocksize field measures the number of 00058 * memory units that the vector spans. 00059 */ 00060 00061 00062 00063 /******************************************/ 00064 /* Include Files */ 00065 /******************************************/ 00066 00067 #include "gnn_node.h" 00068 00069 00070 00071 /******************************************/ 00072 /* Public Interface */ 00073 /******************************************/ 00074 00075 /** 00076 * @brief Creates a new \ref gnn_node vector. 00077 * @ingroup gnn_node_vector_doc 00078 * 00079 * This function creates a new vector with NULL pointers of size \c size. 00080 * The underlying memory block will be owned by the vector. 00081 * 00082 * @param size The number of elements. 00083 * @return A pointer to a new \ref gnn_node_vector. 00084 */ 00085 gnn_node_vector * 00086 gnn_node_vector_new (size_t size) 00087 { 00088 gnn_node_vector *v; 00089 00090 assert (size > 1); 00091 00092 /* alloc node */ 00093 v = (gnn_node_vector *) malloc (sizeof (*v)); 00094 if (v == NULL) 00095 { 00096 GSL_ERROR_VAL ("couldn't allocate memory for gnn_node_vector", 00097 GSL_ENOMEM, NULL); 00098 } 00099 00100 /* allocate block */ 00101 v->data = (gnn_node **) calloc (sizeof (gnn_node *) * size, 1); 00102 if (v->data == NULL) 00103 { 00104 gnn_node_vector_destroy_all (v); 00105 GSL_ERROR_VAL ("couldn't allocate memory for gnn_node_vector block", 00106 GSL_ENOMEM, NULL); 00107 } 00108 00109 /* set internal fields */ 00110 v->size = size; 00111 v->stride = 1; 00112 v->blocksize = size; 00113 v->owner = 1; 00114 00115 return v; 00116 } 00117 00118 /** 00119 * @brief Frees \ref gnn_node vector. 00120 * @ingroup gnn_node_vector_doc 00121 * 00122 * This function frees the memory of a \ref gnn_node_vector. The pointed 00123 * nodes won't be destroyed. 00124 * 00125 * @param v A pointer to a \ref gnn_node_vector. 00126 */ 00127 void 00128 gnn_node_vector_free (gnn_node_vector *v) 00129 { 00130 size_t j; 00131 00132 assert (v != NULL); 00133 00134 free (v->data); 00135 free (v); 00136 } 00137 00138 /** 00139 * @brief Frees \ref gnn_node vector and the pointed nodes. 00140 * @ingroup gnn_node_vector_doc 00141 * 00142 * This function frees the memory of a \ref gnn_node_vector and destroys all 00143 * its pointed nodes by calling \ref gnn_node_destroy on each one of them. 00144 * 00145 * @param v A pointer to a \ref gnn_node_vector. 00146 */ 00147 void 00148 gnn_node_vector_destroy_all (gnn_node_vector *v) 00149 { 00150 size_t j; 00151 00152 assert (v != NULL); 00153 00154 if (v->data != NULL) 00155 { 00156 for (j=0; j<v->size; ++j) 00157 { 00158 if (v->data[j * v->stride] != NULL) 00159 gnn_node_destroy (v->data[j * v->stride]); 00160 } 00161 } 00162 free (v->data); 00163 free (v); 00164 } 00165 00166 /** 00167 * @brief Gets an element. 00168 * @ingroup gnn_node_vector_doc 00169 * 00170 * This function returns the pointer located at the i-th position. 00171 * 00172 * @param v A pointer to a \ref gnn_node_vector. 00173 * @param i The index of the element to be retrieved. 00174 * @Return Returns the i-th elements, which can point to a node or NULL. 00175 */ 00176 gnn_node * 00177 gnn_node_vector_get (gnn_node_vector *v, size_t i) 00178 { 00179 assert (v != NULL); 00180 00181 if (i < 0 || v->size <= i) 00182 GSL_ERROR_VAL ("access out of bounds", GSL_EINVAL, NULL); 00183 00184 return v->data[i * v->stride]; 00185 } 00186 00187 /** 00188 * @brief Sets an element. 00189 * @ingroup gnn_node_vector_doc 00190 * 00191 * This function sets a new value for the element located at the i-th position. 00192 * It should be a pointer to a valid \ref gnn_node or NULL. You should be 00193 * carefull and not delete a needed pointer in order to not lose memory. 00194 * 00195 * @param v A pointer to a \ref gnn_node_vector. 00196 * @param i The index of the element to be retrieved. 00197 * @param n A pointer to a \ref gnn_node or NULL. 00198 * @Return Returns 0 if succeeded. 00199 */ 00200 int 00201 gnn_node_vector_set (gnn_node_vector *v, size_t i, gnn_node *n) 00202 { 00203 assert (v != NULL); 00204 00205 if (i < 0 || v->size <= i) 00206 GSL_ERROR ("access out of bounds", GSL_EINVAL); 00207 00208 v->data[i * v->stride] = n; 00209 00210 return 0; 00211 } 00212 00213 /** 00214 * @brief Checks if vector is null. 00215 * @ingroup gnn_node_vector_doc 00216 * 00217 * This function returns 1 if all elements are equal to NULL. 00218 * 00219 * @param v A pointer to a \ref gnn_node_vector. 00220 * @Return Returns 1 (null) or 0 (not null). 00221 */ 00222 int 00223 gnn_node_vector_isnull (gnn_node_vector *v) 00224 { 00225 size_t j; 00226 00227 assert (v != NULL); 00228 00229 for (j=0; j<v->size; ++j) 00230 { 00231 if (v->data[j * v->stride] != NULL) 00232 return 0; 00233 } 00234 00235 return 1; 00236 } 00237 00238 /** 00239 * @brief Returns the number of elements pointing to a node. 00240 * @ingroup gnn_node_vector_doc 00241 * 00242 * This function counts the number of elements pointing to a non-NULL location. 00243 * 00244 * @param v A pointer to a \ref gnn_node_vector. 00245 * @Return Returns the count. 00246 */ 00247 size_t 00248 gnn_node_vector_count_nodes (gnn_node_vector *v) 00249 { 00250 size_t i; 00251 size_t count; 00252 00253 assert (v != NULL); 00254 00255 /* count the number of non-null nodes */ 00256 count = 0; 00257 for (i=0; i<v->size; ++i) 00258 if (gnn_node_vector_get (v, i) != NULL) 00259 count++; 00260 00261 return count; 00262 } 00263 00264 /** 00265 * @brief Swap two vectors. 00266 * @ingroup gnn_node_vector_doc 00267 * 00268 * This function swaps the elements of the node vectors. This is accomplished 00269 * by interchanging its underlying arrays. 00270 * 00271 * @param v A pointer to a \ref gnn_node_vector. 00272 * @param w A pointer to a \ref gnn_node_vector. 00273 * @Return Returns 0 if succeeded. 00274 */ 00275 int 00276 gnn_node_vector_swap (gnn_node_vector *v, gnn_node_vector *w) 00277 { 00278 gnn_node_vector n; 00279 00280 assert (v != NULL); 00281 assert (w != NULL); 00282 00283 n = *v; 00284 *v = *w; 00285 *w = n; 00286 00287 return 0; 00288 } 00289 00290 /** 00291 * @brief Swap two vector elements. 00292 * @ingroup gnn_node_vector_doc 00293 * 00294 * This function swaps the element located at \c i with the element located 00295 * at position \c j. 00296 * 00297 * @param v A pointer to a \ref gnn_node_vector. 00298 * @param i An index. 00299 * @param j An index. 00300 * @Return Returns 0 if succeeded. 00301 */ 00302 int 00303 gnn_node_vector_swap_elements (gnn_node_vector *v, size_t i, size_t j) 00304 { 00305 gnn_node *n; 00306 00307 assert (v != NULL); 00308 00309 if ( i < 0 || v->size <= i || j < 0 || v->size <= j ) 00310 GSL_ERROR ("access out of bounds", GSL_EINVAL); 00311 00312 n = v->data[i * v->stride]; 00313 v->data[i * v->stride] = v->data[j * v->stride]; 00314 v->data[j * v->stride] = n; 00315 00316 return 0; 00317 } 00318 00319 /** 00320 * @brief Reverse a vector's elements. 00321 * @ingroup gnn_node_vector_doc 00322 * 00323 * @param v A pointer to a \ref gnn_node_vector. 00324 * @Return Returns 0 if succeeded. 00325 */ 00326 int 00327 gnn_node_vector_reverse (gnn_node_vector *v) 00328 { 00329 size_t j; 00330 00331 assert (v != NULL); 00332 00333 for (j=0; j<v->size / 2; ++j) 00334 { 00335 gnn_node_vector_swap_elements (v, j, v->size - j - 1); 00336 } 00337 00338 return 0; 00339 } 00340 00341 /** 00342 * @brief Duplicate a vector. 00343 * @ingroup gnn_node_vector_doc 00344 * 00345 * This function duplicates a given vector, by creating a new fresh one 00346 * pointing to the same nodes. 00347 * 00348 * @param v A pointer to a \ref gnn_node_vector. 00349 * @Return A pointer to a new \ref gnn_node_vector or NULL if failed. 00350 */ 00351 gnn_node_vector * 00352 gnn_node_vector_dup (gnn_node_vector *v) 00353 { 00354 gnn_node_vector *w; 00355 00356 assert (v != NULL); 00357 00358 w = gnn_node_vector_new (v->size); 00359 if (w == NULL) 00360 { 00361 GSL_ERROR_VAL ("couldn't allocate memory for duplicate", 00362 GSL_ENOMEM, NULL); 00363 } 00364 00365 gnn_node_vector_copy (w, v); 00366 00367 return w; 00368 } 00369 00370 /** 00371 * @brief Copy a vector. 00372 * @ingroup gnn_node_vector_doc 00373 * 00374 * This function copies the elements of the vector \c w into \c v. 00375 * 00376 * @param v A pointer to a destiny \ref gnn_node_vector. 00377 * @param v A pointer to a source \ref gnn_node_vector. 00378 * @Return Returns 0 if succeeded. 00379 */ 00380 int 00381 gnn_node_vector_copy (gnn_node_vector *v, const gnn_node_vector *w) 00382 { 00383 size_t j; 00384 00385 assert (v != NULL); 00386 assert (w != NULL); 00387 00388 if (v->size != w->size) 00389 { 00390 GSL_ERROR ("vectors should be of the same size", GSL_EINVAL); 00391 } 00392 00393 for (j=0; j<v->size; ++j) 00394 { 00395 v->data[j * v->stride] = w->data[j * w->stride]; 00396 } 00397 00398 return 0; 00399 } 00400 00401 00402 00403 /* Views */ 00404 00405 /** 00406 * @brief Creates a subvector view of a vector. 00407 * @ingroup gnn_node_vector_doc 00408 * 00409 * This function creates a subvector view of the given vector, starting at \c i 00410 * and ending at \c n. The returned gnn_node_view contains a \c vector field, 00411 * where the subvector will be stored. To obtain a pointer of this vector, 00412 * use the \c "&" operator: 00413 * 00414 * \code 00415 * gnn_node_vector_view view; 00416 * gnn_node_vector *w; 00417 * 00418 * // v is a pointer to a gnn_node_vector 00419 * view = gnn_node_vector_subvector (v, 2, 5); 00420 * 00421 * // get a pointer 00422 * w = &(view.vector); 00423 * \endcode 00424 * 00425 * @param v A pointer to a \ref gnn_node_vector. 00426 * @param i The starting index. 00427 * @param n The size of the subvector. 00428 * @Return Returns a vector view. 00429 */ 00430 gnn_node_vector_view 00431 gnn_node_vector_subvector (gnn_node_vector *v, size_t i, size_t n) 00432 { 00433 return gnn_node_vector_subvector_with_stride (v, i, 1, n); 00434 } 00435 00436 /** 00437 * @brief Creates a subvector view of a vector. 00438 * @ingroup gnn_node_vector_doc 00439 * 00440 * This function creates a subvector view of the given vector, starting at \c i 00441 * and ending at \c n, with stride \c stride. The returned gnn_node_view 00442 * contains a \c vector field, 00443 * where the subvector will be stored. To obtain a pointer of this vector, 00444 * use the \c "&" operator: 00445 * 00446 * \code 00447 * gnn_node_vector_view view; 00448 * gnn_node_vector *w; 00449 * 00450 * // obtain a view of the first 5 odd elements of the vector v 00451 * view = gnn_node_vector_subvector_with_stride (v, 1, 2, 5); 00452 * 00453 * // get a pointer 00454 * w = &(view.vector); 00455 * \endcode 00456 * 00457 * @param v A pointer to a \ref gnn_node_vector. 00458 * @param i The starting index. 00459 * @param stried The stride. 00460 * @param n The size of the subvector. 00461 * @Return Returns a vector view. 00462 */ 00463 gnn_node_vector_view 00464 gnn_node_vector_subvector_with_stride (gnn_node_vector *v, 00465 size_t i, 00466 size_t stride, 00467 size_t n) 00468 { 00469 size_t bn; /* required block size */ 00470 gnn_node_vector_view view; 00471 00472 assert (v != NULL); 00473 00474 /* clear view */ 00475 view.vector.size = 0; 00476 view.vector.stride = 0; 00477 view.vector.blocksize = 0; 00478 view.vector.data = NULL; 00479 view.vector.owner = 0; 00480 00481 /* compute required block size */ 00482 bn = n * stride - stride + 1; 00483 00484 /* check bounds */ 00485 if (i < 0 || v->size <= i) 00486 { 00487 GSL_ERROR_VAL ("starting index out of bounds", GSL_EINVAL, view); 00488 } 00489 if (i+bn < 0 || v->size <= i+bn) 00490 { 00491 GSL_ERROR_VAL ("the required subvector doesn't fit into the vector", 00492 GSL_EINVAL, view); 00493 } 00494 00495 /* set view */ 00496 view.vector.size = n; 00497 view.vector.stride = stride * v->stride; 00498 view.vector.blocksize = (n-1) * view.vector.stride + 1; 00499 view.vector.data = &(v->data[i * v->stride]); 00500 00501 return view; 00502 } 00503 00504 00505 00506
1.2.18