Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

gnn_node_vector.c

Go to the documentation of this file.
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 

Generated on Sun Jun 13 20:50:12 2004 for libgnn Gradient Retropropagation Machine Library by doxygen1.2.18