Leptonica 1.68
C Image Processing Library

numabasic.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*
00017  *   numabasic.c
00018  *
00019  *      Numa creation, destruction, copy, clone, etc.
00020  *          NUMA        *numaCreate()
00021  *          NUMA        *numaCreateFromIArray()
00022  *          NUMA        *numaCreateFromFArray()
00023  *          void        *numaDestroy()
00024  *          NUMA        *numaCopy()
00025  *          NUMA        *numaClone()
00026  *          l_int32      numaEmpty()
00027  *
00028  *      Add/remove number (float or integer)
00029  *          l_int32      numaAddNumber()
00030  *          l_int32      numaExtendArray()
00031  *          l_int32      numaInsertNumber()
00032  *          l_int32      numaRemoveNumber()
00033  *          l_int32      numaReplaceNumber()
00034  *
00035  *      Numa accessors
00036  *          l_int32      numaGetCount()
00037  *          l_int32      numaSetCount()
00038  *          l_int32      numaGetIValue()
00039  *          l_int32      numaGetFValue()
00040  *          l_int32      numaSetValue()
00041  *          l_int32      numaShiftValue()
00042  *          l_int32     *numaGetIArray()
00043  *          l_float32   *numaGetFArray()
00044  *          l_int32      numaGetRefcount()
00045  *          l_int32      numaChangeRefcount()
00046  *          l_int32      numaGetXParameters()
00047  *          l_int32      numaSetXParameters()
00048  *          l_int32      numaCopyXParameters()
00049  *
00050  *      Serialize numa for I/O
00051  *          l_int32      numaRead()
00052  *          l_int32      numaReadStream()
00053  *          l_int32      numaWrite()
00054  *          l_int32      numaWriteStream()
00055  *
00056  *      Numaa creation, destruction
00057  *          NUMAA       *numaaCreate()
00058  *          void        *numaaDestroy()
00059  *
00060  *      Add Numa to Numaa
00061  *          l_int32      numaaAddNuma()
00062  *          l_int32      numaaExtendArray()
00063  *
00064  *      Numaa accessors
00065  *          l_int32      numaaGetCount()
00066  *          l_int32      numaaGetNumaCount()
00067  *          l_int32      numaaGetNumberCount()
00068  *          NUMA       **numaaGetPtrArray()
00069  *          NUMA        *numaaGetNuma()
00070  *          NUMA        *numaaReplaceNuma()
00071  *          l_int32      numaaGetValue()
00072  *          l_int32      numaaAddNumber()
00073  *
00074  *      Serialize numaa for I/O
00075  *          l_int32      numaaRead()
00076  *          l_int32      numaaReadStream()
00077  *          l_int32      numaaWrite()
00078  *          l_int32      numaaWriteStream()
00079  *
00080  *      Numa2d creation, destruction
00081  *          NUMA2D      *numa2dCreate()
00082  *          void        *numa2dDestroy()
00083  *
00084  *      Numa2d Accessors
00085  *          l_int32      numa2dAddNumber()
00086  *          l_int32      numa2dGetCount()
00087  *          NUMA        *numa2dGetNuma()
00088  *          l_int32      numa2dGetFValue()
00089  *          l_int32      numa2dGetIValue()
00090  *
00091  *      NumaHash creation, destruction
00092  *          NUMAHASH    *numaHashCreate()
00093  *          void        *numaHashDestroy()
00094  *
00095  *      NumaHash Accessors
00096  *          NUMA        *numaHashGetNuma()
00097  *          void        *numaHashAdd()
00098  *
00099  *    (1) The numa is a struct, not an array.  Always use the accessors
00100  *        in this file, never the fields directly.
00101  *
00102  *    (2) The number array holds l_float32 values.  It can also
00103  *        be used to store l_int32 values.
00104  *
00105  *    (3) Storing and retrieving numbers:
00106  *
00107  *       * to append a new number to the array, use numaAddNumber().  If
00108  *         the number is an int, it will will automatically be converted
00109  *         to l_float32 and stored.
00110  *
00111  *       * to reset a value stored in the array, use numaSetValue().
00112  *
00113  *       * to increment or decrement a value stored in the array,
00114  *         use numaShiftValue().
00115  *
00116  *       * to obtain a value from the array, use either numaGetIValue()
00117  *         or numaGetFValue(), depending on whether you are retrieving
00118  *         an integer or a float.  This avoids doing an explicit cast,
00119  *         such as
00120  *           (a) return a l_float32 and cast it to an l_int32
00121  *           (b) cast the return directly to (l_float32 *) to
00122  *               satisfy the function prototype, as in
00123  *                 numaGetFValue(na, index, (l_float32 *)&ival);   [ugly!]
00124  *
00125  *    (4) int <--> float conversions:
00126  *
00127  *        Tradition dictates that type conversions go automatically from
00128  *        l_int32 --> l_float32, even though it is possible to lose
00129  *        precision for large integers, whereas you must cast (l_int32)
00130  *        to go from l_float32 --> l_int32 because you're truncating
00131  *        to the integer value.
00132  *
00133  *    (5) As with other arrays in leptonica, the numa has both an allocated
00134  *        size and a count of the stored numbers.  When you add a number, it
00135  *        goes on the end of the array, and causes a realloc if the array
00136  *        is already filled.  However, in situations where you want to
00137  *        add numbers randomly into an array, such as when you build a
00138  *        histogram, you must set the count of stored numbers in advance.
00139  *        This is done with numaSetCount().  If you set a count larger
00140  *        than the allocated array, it does a realloc to the size requested.
00141  *
00142  *    (6) In situations where the data in a numa correspond to a function
00143  *        y(x), the values can be either at equal spacings in x or at
00144  *        arbitrary spacings.  For the former, we can represent all x values
00145  *        by two parameters: startx (corresponding to y[0]) and delx
00146  *        for the change in x for adjacent values y[i] and y[i+1].
00147  *        startx and delx are initialized to 0.0 and 1.0, rsp.
00148  *        For arbitrary spacings, we use a second numa, and the two
00149  *        numas are typically denoted nay and nax.
00150  *
00151  *    (7) The numa is also the basic struct used for histograms.  Every numa
00152  *        has startx and delx fields, initialized to 0.0 and 1.0, that can
00153  *        be used to represent the "x" value for the location of the
00154  *        first bin and the bin width, respectively.  Accessors are the
00155  *        numa*XParameters() functions.  All functions that make numa
00156  *        histograms must set these fields properly, and many functions
00157  *        that use numa histograms rely on the correctness of these values.
00158  */
00159 
00160 #include <string.h>
00161 #include <math.h>
00162 #include "allheaders.h"
00163 
00164 static const l_int32 INITIAL_PTR_ARRAYSIZE = 50;      /* n'importe quoi */
00165 
00166 
00167 /*--------------------------------------------------------------------------*
00168  *               Numa creation, destruction, copy, clone, etc.              *
00169  *--------------------------------------------------------------------------*/
00170 /*!
00171  *  numaCreate()
00172  *
00173  *      Input:  size of number array to be alloc'd (0 for default)
00174  *      Return: na, or null on error
00175  */
00176 NUMA *
00177 numaCreate(l_int32  n)
00178 {
00179 NUMA  *na;
00180 
00181     PROCNAME("numaCreate");
00182 
00183     if (n <= 0)
00184         n = INITIAL_PTR_ARRAYSIZE;
00185 
00186     if ((na = (NUMA *)CALLOC(1, sizeof(NUMA))) == NULL)
00187         return (NUMA *)ERROR_PTR("na not made", procName, NULL);
00188     if ((na->array = (l_float32 *)CALLOC(n, sizeof(l_float32))) == NULL)
00189         return (NUMA *)ERROR_PTR("number array not made", procName, NULL);
00190 
00191     na->nalloc = n;
00192     na->n = 0;
00193     na->refcount = 1;
00194     na->startx = 0.0;
00195     na->delx = 1.0;
00196 
00197     return na;
00198 }
00199 
00200 
00201 /*!
00202  *  numaCreateFromIArray()
00203  *
00204  *      Input:  iarray (integer)
00205  *              size (of the array)
00206  *      Return: na, or null on error
00207  *
00208  *  Notes:
00209  *      (1) We can't insert this int array into the numa, because a numa
00210  *          takes a float array.  So this just copies the data from the
00211  *          input array into the numa.  The input array continues to be
00212  *          owned by the caller.
00213  */
00214 NUMA *
00215 numaCreateFromIArray(l_int32  *iarray,
00216                      l_int32   size)
00217 {
00218 l_int32  i;
00219 NUMA    *na;
00220 
00221     PROCNAME("numaCreateFromIArray");
00222 
00223     if (!iarray)
00224         return (NUMA *)ERROR_PTR("iarray not defined", procName, NULL);
00225     if (size <= 0)
00226         return (NUMA *)ERROR_PTR("size must be > 0", procName, NULL);
00227 
00228     na = numaCreate(size);
00229     for (i = 0; i < size; i++)
00230         numaAddNumber(na, iarray[i]);
00231 
00232     return na;
00233 }
00234 
00235 
00236 /*!
00237  *  numaCreateFromFArray()
00238  *
00239  *      Input:  farray (float)
00240  *              size (of the array)
00241  *              copyflag (L_INSERT or L_COPY)
00242  *      Return: na, or null on error
00243  *
00244  *  Notes:
00245  *      (1) With L_INSERT, ownership of the input array is transferred
00246  *          to the returned numa, and all @size elements are considered
00247  *          to be valid.
00248  */
00249 NUMA *
00250 numaCreateFromFArray(l_float32  *farray,
00251                      l_int32     size,
00252                      l_int32     copyflag)
00253 {
00254 l_int32  i;
00255 NUMA    *na;
00256 
00257     PROCNAME("numaCreateFromFArray");
00258 
00259     if (!farray)
00260         return (NUMA *)ERROR_PTR("farray not defined", procName, NULL);
00261     if (size <= 0)
00262         return (NUMA *)ERROR_PTR("size must be > 0", procName, NULL);
00263     if (copyflag != L_INSERT && copyflag != L_COPY)
00264         return (NUMA *)ERROR_PTR("invalid copyflag", procName, NULL);
00265 
00266     na = numaCreate(size);
00267     if (copyflag == L_INSERT) {
00268         if (na->array) FREE(na->array);
00269         na->array = farray;
00270         na->n = size;
00271     }
00272     else {  /* just copy the contents */
00273         for (i = 0; i < size; i++)
00274             numaAddNumber(na, farray[i]);
00275     }
00276 
00277     return na;
00278 }
00279 
00280 
00281 /*!
00282  *  numaDestroy()
00283  *
00284  *      Input:  &na (<to be nulled if it exists>)
00285  *      Return: void
00286  *
00287  *  Notes:
00288  *      (1) Decrements the ref count and, if 0, destroys the numa.
00289  *      (2) Always nulls the input ptr.
00290  */
00291 void
00292 numaDestroy(NUMA  **pna)
00293 {
00294 NUMA  *na;
00295 
00296     PROCNAME("numaDestroy");
00297 
00298     if (pna == NULL) {
00299         L_WARNING("ptr address is NULL", procName);
00300         return;
00301     }
00302 
00303     if ((na = *pna) == NULL)
00304         return;
00305 
00306         /* Decrement the ref count.  If it is 0, destroy the numa. */
00307     numaChangeRefcount(na, -1);
00308     if (numaGetRefcount(na) <= 0) {
00309         if (na->array)
00310             FREE(na->array);
00311         FREE(na);
00312     }
00313 
00314     *pna = NULL;
00315     return;
00316 }
00317 
00318 
00319 /*!
00320  *  numaCopy()
00321  *
00322  *      Input:  na
00323  *      Return: copy of numa, or null on error
00324  */
00325 NUMA *
00326 numaCopy(NUMA  *na)
00327 {
00328 l_int32  i;
00329 NUMA    *cna;
00330 
00331     PROCNAME("numaCopy");
00332 
00333     if (!na)
00334         return (NUMA *)ERROR_PTR("na not defined", procName, NULL);
00335 
00336     if ((cna = numaCreate(na->nalloc)) == NULL)
00337         return (NUMA *)ERROR_PTR("cna not made", procName, NULL);
00338     cna->startx = na->startx;
00339     cna->delx = na->delx;
00340 
00341     for (i = 0; i < na->n; i++)
00342         numaAddNumber(cna, na->array[i]);
00343 
00344     return cna;
00345 }
00346 
00347 
00348 /*!
00349  *  numaClone()
00350  *
00351  *      Input:  na
00352  *      Return: ptr to same numa, or null on error
00353  */
00354 NUMA *
00355 numaClone(NUMA  *na)
00356 {
00357     PROCNAME("numaClone");
00358 
00359     if (!na)
00360         return (NUMA *)ERROR_PTR("na not defined", procName, NULL);
00361 
00362     numaChangeRefcount(na, 1);
00363     return na;
00364 }
00365 
00366 
00367 /*!
00368  *  numaEmpty()
00369  *
00370  *      Input:  na
00371  *      Return: 0 if OK; 1 on error
00372  *
00373  *  Notes:
00374  *      (1) This does not change the allocation of the array.
00375  *          It just clears the number of stored numbers, so that
00376  *          the array appears to be empty.
00377  */
00378 l_int32
00379 numaEmpty(NUMA  *na)
00380 {
00381     PROCNAME("numaEmpty");
00382 
00383     if (!na)
00384         return ERROR_INT("na not defined", procName, 1);
00385 
00386     na->n = 0;
00387     return 0;
00388 }
00389 
00390 
00391 
00392 /*--------------------------------------------------------------------------*
00393  *                 Number array: add number and extend array                *
00394  *--------------------------------------------------------------------------*/
00395 /*!
00396  *  numaAddNumber()
00397  *
00398  *      Input:  na
00399  *              val  (float or int to be added; stored as a float)
00400  *      Return: 0 if OK, 1 on error
00401  */
00402 l_int32
00403 numaAddNumber(NUMA      *na,
00404               l_float32  val)
00405 {
00406 l_int32  n;
00407 
00408     PROCNAME("numaAddNumber");
00409 
00410     if (!na)
00411         return ERROR_INT("na not defined", procName, 1);
00412 
00413     n = numaGetCount(na);
00414     if (n >= na->nalloc)
00415         numaExtendArray(na);
00416     na->array[n] = val;
00417     na->n++;
00418     return 0;
00419 }
00420 
00421 
00422 /*!
00423  *  numaExtendArray()
00424  *
00425  *      Input:  na
00426  *      Return: 0 if OK, 1 on error
00427  */
00428 l_int32
00429 numaExtendArray(NUMA  *na)
00430 {
00431     PROCNAME("numaExtendArray");
00432 
00433     if (!na)
00434         return ERROR_INT("na not defined", procName, 1);
00435 
00436     if ((na->array = (l_float32 *)reallocNew((void **)&na->array,
00437                                 sizeof(l_float32) * na->nalloc,
00438                                 2 * sizeof(l_float32) * na->nalloc)) == NULL)
00439             return ERROR_INT("new ptr array not returned", procName, 1);
00440 
00441     na->nalloc *= 2;
00442     return 0;
00443 }
00444 
00445 
00446 /*!
00447  *  numaInsertNumber()
00448  *
00449  *      Input:  na
00450  *              index (location in na to insert new value)
00451  *              val  (float32 or integer to be added)
00452  *      Return: 0 if OK, 1 on error
00453  *
00454  *  Notes:
00455  *      (1) This shifts na[i] --> na[i + 1] for all i >= index,
00456  *          and then inserts val as na[index].
00457  *      (2) It should not be used repeatedly on large arrays,
00458  *          because the function is O(n).
00459  *
00460  */
00461 l_int32
00462 numaInsertNumber(NUMA      *na,
00463                  l_int32    index,
00464                  l_float32  val)
00465 {
00466 l_int32  i, n;
00467 
00468     PROCNAME("numaInsertNumber");
00469 
00470     if (!na)
00471         return ERROR_INT("na not defined", procName, 1);
00472     n = numaGetCount(na);
00473     if (index < 0 || index > n)
00474         return ERROR_INT("index not in {0...n}", procName, 1);
00475 
00476     if (n >= na->nalloc)
00477         numaExtendArray(na);
00478     for (i = n; i > index; i--)
00479         na->array[i] = na->array[i - 1];
00480     na->array[index] = val;
00481     na->n++;
00482     return 0;
00483 }
00484 
00485 
00486 /*!
00487  *  numaRemoveNumber()
00488  *
00489  *      Input:  na
00490  *              index (element to be removed)
00491  *      Return: 0 if OK, 1 on error
00492  *
00493  *  Notes:
00494  *      (1) This shifts na[i] --> na[i - 1] for all i > index.
00495  *      (2) It should not be used repeatedly on large arrays,
00496  *          because the function is O(n).
00497  */
00498 l_int32
00499 numaRemoveNumber(NUMA    *na,
00500                  l_int32  index)
00501 {
00502 l_int32  i, n;
00503 
00504     PROCNAME("numaRemoveNumber");
00505 
00506     if (!na)
00507         return ERROR_INT("na not defined", procName, 1);
00508     n = numaGetCount(na);
00509     if (index < 0 || index >= n)
00510         return ERROR_INT("index not in {0...n - 1}", procName, 1);
00511 
00512     for (i = index + 1; i < n; i++)
00513         na->array[i - 1] = na->array[i];
00514     na->n--;
00515     return 0;
00516 }
00517 
00518 
00519 /*!
00520  *  numaReplaceNumber()
00521  *
00522  *      Input:  na
00523  *              index (element to be replaced)
00524  *              val (new value to replace old one)
00525  *      Return: 0 if OK, 1 on error
00526  */
00527 l_int32
00528 numaReplaceNumber(NUMA      *na,
00529                   l_int32    index,
00530                   l_float32  val)
00531 {
00532 l_int32  n;
00533 
00534     PROCNAME("numaReplaceNumber");
00535 
00536     if (!na)
00537         return ERROR_INT("na not defined", procName, 1);
00538     n = numaGetCount(na);
00539     if (index < 0 || index >= n)
00540         return ERROR_INT("index not in {0...n - 1}", procName, 1);
00541 
00542     na->array[index] = val;
00543     return 0;
00544 }
00545 
00546 
00547 /*----------------------------------------------------------------------*
00548  *                            Numa accessors                            *
00549  *----------------------------------------------------------------------*/
00550 /*!
00551  *  numaGetCount()
00552  *
00553  *      Input:  na
00554  *      Return: count, or 0 if no numbers or on error
00555  */
00556 l_int32
00557 numaGetCount(NUMA  *na)
00558 {
00559     PROCNAME("numaGetCount");
00560 
00561     if (!na)
00562         return ERROR_INT("na not defined", procName, 0);
00563     return na->n;
00564 }
00565 
00566 
00567 /*!
00568  *  numaSetCount()
00569  *
00570  *      Input:  na
00571  *              newcount
00572  *      Return: 0 if OK, 1 on error
00573  *
00574  *  Notes:
00575  *      (1) If newcount <= na->nalloc, this resets na->n.
00576  *          Using newcount = 0 is equivalent to numaEmpty().
00577  *      (2) If newcount > na->nalloc, this causes a realloc
00578  *          to a size na->nalloc = newcount.
00579  *      (3) All the previously unused values in na are set to 0.0.
00580  */
00581 l_int32
00582 numaSetCount(NUMA    *na,
00583              l_int32  newcount)
00584 {
00585     PROCNAME("numaSetCount");
00586 
00587     if (!na)
00588         return ERROR_INT("na not defined", procName, 1);
00589     if (newcount > na->nalloc) {
00590         if ((na->array = (l_float32 *)reallocNew((void **)&na->array,
00591                          sizeof(l_float32) * na->nalloc,
00592                          sizeof(l_float32) * newcount)) == NULL)
00593             return ERROR_INT("new ptr array not returned", procName, 1);
00594         na->nalloc = newcount;
00595     }
00596     na->n = newcount;
00597     return 0;
00598 }
00599 
00600 
00601 /*!
00602  *  numaGetFValue()
00603  *
00604  *      Input:  na
00605  *              index (into numa)
00606  *              &val  (<return> float value; 0.0 on error)
00607  *      Return: 0 if OK; 1 on error
00608  *
00609  *  Notes:
00610  *      (1) Caller may need to check the function return value to
00611  *          decide if a 0.0 in the returned ival is valid.
00612  */
00613 l_int32
00614 numaGetFValue(NUMA       *na,
00615               l_int32     index,
00616               l_float32  *pval)
00617 {
00618     PROCNAME("numaGetFValue");
00619 
00620     if (!pval)
00621         return ERROR_INT("&val not defined", procName, 1);
00622     *pval = 0.0;
00623     if (!na)
00624         return ERROR_INT("na not defined", procName, 1);
00625 
00626     if (index < 0 || index >= na->n)
00627         return ERROR_INT("index not valid", procName, 1);
00628 
00629     *pval = na->array[index];
00630     return 0;
00631 }
00632 
00633 
00634 /*!
00635  *  numaGetIValue()
00636  *
00637  *      Input:  na
00638  *              index (into numa)
00639  *              &ival  (<return> integer value; 0 on error)
00640  *      Return: 0 if OK; 1 on error
00641  *
00642  *  Notes:
00643  *      (1) Caller may need to check the function return value to
00644  *          decide if a 0 in the returned ival is valid.
00645  */
00646 l_int32
00647 numaGetIValue(NUMA     *na,
00648               l_int32   index,
00649               l_int32  *pival)
00650 {
00651 l_float32  val;
00652 
00653     PROCNAME("numaGetIValue");
00654 
00655     if (!pival)
00656         return ERROR_INT("&ival not defined", procName, 1);
00657     *pival = 0;
00658     if (!na)
00659         return ERROR_INT("na not defined", procName, 1);
00660 
00661     if (index < 0 || index >= na->n)
00662         return ERROR_INT("index not valid", procName, 1);
00663 
00664     val = na->array[index];
00665     *pival = (l_int32)(val + L_SIGN(val) * 0.5);
00666     return 0;
00667 }
00668 
00669 
00670 /*!
00671  *  numaSetValue()
00672  *
00673  *      Input:  na
00674  *              index   (to element to be set)
00675  *              val  (to set element)
00676  *      Return: 0 if OK; 1 on error
00677  */
00678 l_int32
00679 numaSetValue(NUMA      *na,
00680              l_int32    index,
00681              l_float32  val)
00682 {
00683     PROCNAME("numaSetValue");
00684 
00685     if (!na)
00686         return ERROR_INT("na not defined", procName, 1);
00687     if (index < 0 || index >= na->n)
00688         return ERROR_INT("index not valid", procName, 1);
00689 
00690     na->array[index] = val;
00691     return 0;
00692 }
00693 
00694 
00695 /*!
00696  *  numaShiftValue()
00697  *
00698  *      Input:  na
00699  *              index (to element to change relative to the current value)
00700  *              diff  (increment if diff > 0 or decrement if diff < 0)
00701  *      Return: 0 if OK; 1 on error
00702  */
00703 l_int32
00704 numaShiftValue(NUMA      *na,
00705                l_int32    index,
00706                l_float32  diff)
00707 {
00708     PROCNAME("numaShiftValue");
00709 
00710     if (!na)
00711         return ERROR_INT("na not defined", procName, 1);
00712     if (index < 0 || index >= na->n)
00713         return ERROR_INT("index not valid", procName, 1);
00714 
00715     na->array[index] += diff;
00716     return 0;
00717 }
00718 
00719 
00720 /*!
00721  *  numaGetIArray()
00722  *
00723  *      Input:  na
00724  *      Return: a copy of the bare internal array, integerized
00725  *              by rounding, or null on error
00726  *  Notes:
00727  *      (1) A copy of the array is always made, because we need to
00728  *          generate an integer array from the bare float array.
00729  *          The caller is responsible for freeing the array.
00730  *      (2) The array size is determined by the number of stored numbers,
00731  *          not by the size of the allocated array in the Numa.
00732  *      (3) This function is provided to simplify calculations
00733  *          using the bare internal array, rather than continually
00734  *          calling accessors on the numa.  It is typically used
00735  *          on an array of size 256.
00736  */
00737 l_int32 *
00738 numaGetIArray(NUMA  *na)
00739 {
00740 l_int32   i, n, ival;
00741 l_int32  *array;
00742 
00743     PROCNAME("numaGetIArray");
00744 
00745     if (!na)
00746         return (l_int32 *)ERROR_PTR("na not defined", procName, NULL);
00747 
00748     n = numaGetCount(na);
00749     if ((array = (l_int32 *)CALLOC(n, sizeof(l_int32))) == NULL)
00750         return (l_int32 *)ERROR_PTR("array not made", procName, NULL);
00751     for (i = 0; i < n; i++) {
00752         numaGetIValue(na, i, &ival);
00753         array[i] = ival;
00754     }
00755 
00756     return array;
00757 }
00758 
00759 
00760 /*!
00761  *  numaGetFArray()
00762  *
00763  *      Input:  na
00764  *              copyflag (L_NOCOPY or L_COPY)
00765  *      Return: either the bare internal array or a copy of it,
00766  *              or null on error
00767  *
00768  *  Notes:
00769  *      (1) If copyflag == L_COPY, it makes a copy which the caller
00770  *          is responsible for freeing.  Otherwise, it operates
00771  *          directly on the bare array of the numa.
00772  *      (2) Very important: for L_NOCOPY, any writes to the array
00773  *          will be in the numa.  Do not write beyond the size of
00774  *          the count field, because it will not be accessable
00775  *          from the numa!  If necessary, be sure to set the count
00776  *          field to a larger number (such as the alloc size)
00777  *          BEFORE calling this function.  Creating with numaMakeConstant()
00778  *          is another way to insure full initialization.
00779  */
00780 l_float32 *
00781 numaGetFArray(NUMA    *na,
00782               l_int32  copyflag)
00783 {
00784 l_int32     i, n;
00785 l_float32  *array;
00786 
00787     PROCNAME("numaGetFArray");
00788 
00789     if (!na)
00790         return (l_float32 *)ERROR_PTR("na not defined", procName, NULL);
00791 
00792     if (copyflag == L_NOCOPY)
00793         array = na->array;
00794     else {  /* copyflag == L_COPY */
00795         n = numaGetCount(na);
00796         if ((array = (l_float32 *)CALLOC(n, sizeof(l_float32))) == NULL)
00797             return (l_float32 *)ERROR_PTR("array not made", procName, NULL);
00798         for (i = 0; i < n; i++)
00799             array[i] = na->array[i];
00800     }
00801 
00802     return array;
00803 }
00804 
00805 
00806 /*!
00807  *  numaGetRefCount()
00808  *
00809  *      Input:  na
00810  *      Return: refcount, or UNDEF on error
00811  */
00812 l_int32
00813 numaGetRefcount(NUMA  *na)
00814 {
00815     PROCNAME("numaGetRefcount");
00816 
00817     if (!na)
00818         return ERROR_INT("na not defined", procName, UNDEF);
00819     return na->refcount;
00820 }
00821 
00822 
00823 /*!
00824  *  numaChangeRefCount()
00825  *
00826  *      Input:  na
00827  *              delta (change to be applied)
00828  *      Return: 0 if OK, 1 on error
00829  */
00830 l_int32
00831 numaChangeRefcount(NUMA    *na,
00832                    l_int32  delta)
00833 {
00834     PROCNAME("numaChangeRefcount");
00835 
00836     if (!na)
00837         return ERROR_INT("na not defined", procName, 1);
00838     na->refcount += delta;
00839     return 0;
00840 }
00841 
00842 
00843 /*!
00844  *  numaGetXParameters()
00845  *
00846  *      Input:  na
00847  *              &startx (<optional return> startx)
00848  *              &delx (<optional return> delx)
00849  *      Return: 0 if OK, 1 on error
00850  */
00851 l_int32
00852 numaGetXParameters(NUMA       *na,
00853                    l_float32  *pstartx,
00854                    l_float32  *pdelx)
00855 {
00856     PROCNAME("numaGetXParameters");
00857 
00858     if (!na)
00859         return ERROR_INT("na not defined", procName, 1);
00860 
00861     if (pstartx) *pstartx = na->startx;
00862     if (pdelx) *pdelx = na->delx;
00863     return 0;
00864 }
00865 
00866 
00867 /*!
00868  *  numaSetXParameters()
00869  *
00870  *      Input:  na
00871  *              startx (x value corresponding to na[0])
00872  *              delx (difference in x values for the situation where the
00873  *                    elements of na correspond to the evaulation of a
00874  *                    function at equal intervals of size @delx)
00875  *      Return: 0 if OK, 1 on error
00876  */
00877 l_int32
00878 numaSetXParameters(NUMA      *na,
00879                    l_float32  startx,
00880                    l_float32  delx)
00881 {
00882     PROCNAME("numaSetXParameters");
00883 
00884     if (!na)
00885         return ERROR_INT("na not defined", procName, 1);
00886 
00887     na->startx = startx;
00888     na->delx = delx;
00889     return 0;
00890 }
00891 
00892 
00893 /*!
00894  *  numaCopyXParameters()
00895  *
00896  *      Input:  nad (destination Numa)
00897  *              nas (source Numa)
00898  *      Return: 0 if OK, 1 on error
00899  */
00900 l_int32
00901 numaCopyXParameters(NUMA  *nad,
00902                     NUMA  *nas)
00903 {
00904 l_float32  start, binsize;
00905 
00906     PROCNAME("numaCopyXParameters");
00907 
00908     if (!nas || !nad)
00909         return ERROR_INT("nas and nad not both defined", procName, 1);
00910 
00911     numaGetXParameters(nas, &start, &binsize);
00912     numaSetXParameters(nad, start, binsize);
00913     return 0;
00914 }
00915 
00916 
00917 /*----------------------------------------------------------------------*
00918  *                       Serialize numa for I/O                         *
00919  *----------------------------------------------------------------------*/
00920 /*!
00921  *  numaRead()
00922  *
00923  *      Input:  filename
00924  *      Return: na, or null on error
00925  */
00926 NUMA *
00927 numaRead(const char  *filename)
00928 {
00929 FILE  *fp;
00930 NUMA  *na;
00931 
00932     PROCNAME("numaRead");
00933 
00934     if (!filename)
00935         return (NUMA *)ERROR_PTR("filename not defined", procName, NULL);
00936 
00937     if ((fp = fopenReadStream(filename)) == NULL)
00938         return (NUMA *)ERROR_PTR("stream not opened", procName, NULL);
00939 
00940     if ((na = numaReadStream(fp)) == NULL) {
00941         fclose(fp);
00942         return (NUMA *)ERROR_PTR("na not read", procName, NULL);
00943     }
00944 
00945     fclose(fp);
00946     return na;
00947 }
00948 
00949 
00950 /*!
00951  *  numaReadStream()
00952  *
00953  *      Input:  stream
00954  *      Return: numa, or null on error
00955  */
00956 NUMA *
00957 numaReadStream(FILE  *fp)
00958 {
00959 l_int32    i, n, index, ret, version;
00960 l_float32  val, startx, delx;
00961 NUMA      *na;
00962 
00963     PROCNAME("numaReadStream");
00964 
00965     if (!fp)
00966         return (NUMA *)ERROR_PTR("stream not defined", procName, NULL);
00967 
00968     ret = fscanf(fp, "\nNuma Version %d\n", &version);
00969     if (ret != 1)
00970         return (NUMA *)ERROR_PTR("not a numa file", procName, NULL);
00971     if (version != NUMA_VERSION_NUMBER)
00972         return (NUMA *)ERROR_PTR("invalid numa version", procName, NULL);
00973     if (fscanf(fp, "Number of numbers = %d\n", &n) != 1)
00974         return (NUMA *)ERROR_PTR("invalid number of numbers", procName, NULL);
00975 
00976     if ((na = numaCreate(n)) == NULL)
00977         return (NUMA *)ERROR_PTR("na not made", procName, NULL);
00978 
00979     for (i = 0; i < n; i++) {
00980         if (fscanf(fp, "  [%d] = %f\n", &index, &val) != 2)
00981             return (NUMA *)ERROR_PTR("bad input data", procName, NULL);
00982         numaAddNumber(na, val);
00983     }
00984 
00985         /* Optional data */
00986     if (fscanf(fp, "startx = %f, delx = %f\n", &startx, &delx) == 2)
00987         numaSetXParameters(na, startx, delx);
00988 
00989     return na;
00990 }
00991 
00992 
00993 /*!
00994  *  numaWrite()
00995  *
00996  *      Input:  filename, na
00997  *      Return: 0 if OK, 1 on error
00998  */
00999 l_int32
01000 numaWrite(const char  *filename,
01001           NUMA        *na)
01002 {
01003 FILE  *fp;
01004 
01005     PROCNAME("numaWrite");
01006 
01007     if (!filename)
01008         return ERROR_INT("filename not defined", procName, 1);
01009     if (!na)
01010         return ERROR_INT("na not defined", procName, 1);
01011 
01012     if ((fp = fopenWriteStream(filename, "w")) == NULL)
01013         return ERROR_INT("stream not opened", procName, 1);
01014     if (numaWriteStream(fp, na))
01015         return ERROR_INT("na not written to stream", procName, 1);
01016     fclose(fp);
01017 
01018     return 0;
01019 }
01020 
01021 
01022 /*!
01023  *  numaWriteStream()
01024  *
01025  *      Input:  stream, na
01026  *      Return: 0 if OK, 1 on error
01027  */
01028 l_int32
01029 numaWriteStream(FILE  *fp,
01030                 NUMA  *na)
01031 {
01032 l_int32    i, n;
01033 l_float32  startx, delx;
01034 
01035     PROCNAME("numaWriteStream");
01036 
01037     if (!fp)
01038         return ERROR_INT("stream not defined", procName, 1);
01039     if (!na)
01040         return ERROR_INT("na not defined", procName, 1);
01041 
01042     n = numaGetCount(na);
01043     fprintf(fp, "\nNuma Version %d\n", NUMA_VERSION_NUMBER);
01044     fprintf(fp, "Number of numbers = %d\n", n);
01045     for (i = 0; i < n; i++)
01046         fprintf(fp, "  [%d] = %f\n", i, na->array[i]);
01047     fprintf(fp, "\n");
01048 
01049         /* Optional data */
01050     numaGetXParameters(na, &startx, &delx);
01051     if (startx != 0.0 || delx != 1.0)
01052         fprintf(fp, "startx = %f, delx = %f\n", startx, delx);
01053 
01054     return 0;
01055 }
01056 
01057 
01058 
01059 /*--------------------------------------------------------------------------*
01060  *                     Numaa creation, destruction                          *
01061  *--------------------------------------------------------------------------*/
01062 /*!
01063  *  numaaCreate()
01064  *
01065  *      Input:  size of numa ptr array to be alloc'd (0 for default)
01066  *      Return: naa, or null on error
01067  *
01068  */
01069 NUMAA *
01070 numaaCreate(l_int32  n)
01071 {
01072 NUMAA  *naa;
01073 
01074     PROCNAME("numaaCreate");
01075 
01076     if (n <= 0)
01077         n = INITIAL_PTR_ARRAYSIZE;
01078 
01079     if ((naa = (NUMAA *)CALLOC(1, sizeof(NUMAA))) == NULL)
01080         return (NUMAA *)ERROR_PTR("naa not made", procName, NULL);
01081     if ((naa->numa = (NUMA **)CALLOC(n, sizeof(NUMA *))) == NULL)
01082         return (NUMAA *)ERROR_PTR("numa ptr array not made", procName, NULL);
01083 
01084     naa->nalloc = n;
01085     naa->n = 0;
01086 
01087     return naa;
01088 }
01089 
01090 
01091 /*!
01092  *  numaaDestroy()
01093  *
01094  *      Input: &numaa <to be nulled if it exists>
01095  *      Return: void
01096  */
01097 void
01098 numaaDestroy(NUMAA  **pnaa)
01099 {
01100 l_int32  i;
01101 NUMAA   *naa;
01102 
01103     PROCNAME("numaaDestroy");
01104 
01105     if (pnaa == NULL) {
01106         L_WARNING("ptr address is NULL!", procName);
01107         return;
01108     }
01109 
01110     if ((naa = *pnaa) == NULL)
01111         return;
01112 
01113     for (i = 0; i < naa->n; i++)
01114         numaDestroy(&naa->numa[i]);
01115     FREE(naa->numa);
01116     FREE(naa);
01117     *pnaa = NULL;
01118 
01119     return;
01120 }
01121 
01122 
01123 
01124 /*--------------------------------------------------------------------------*
01125  *                              Add Numa to Numaa                           *
01126  *--------------------------------------------------------------------------*/
01127 /*!
01128  *  numaaAddNuma()
01129  *
01130  *      Input:  naa
01131  *              na   (to be added)
01132  *              copyflag  (L_INSERT, L_COPY, L_CLONE)
01133  *      Return: 0 if OK, 1 on error
01134  */
01135 l_int32
01136 numaaAddNuma(NUMAA   *naa,
01137              NUMA    *na,
01138              l_int32  copyflag)
01139 {
01140 l_int32  n;
01141 NUMA    *nac;
01142 
01143     PROCNAME("numaaAddNuma");
01144 
01145     if (!naa)
01146         return ERROR_INT("naa not defined", procName, 1);
01147     if (!na)
01148         return ERROR_INT("na not defined", procName, 1);
01149 
01150     if (copyflag == L_INSERT)
01151         nac = na;
01152     else if (copyflag == L_COPY) {
01153         if ((nac = numaCopy(na)) == NULL)
01154             return ERROR_INT("nac not made", procName, 1);
01155     }
01156     else if (copyflag == L_CLONE)
01157         nac = numaClone(na);
01158     else
01159         return ERROR_INT("invalid copyflag", procName, 1);
01160 
01161     n = numaaGetCount(naa);
01162     if (n >= naa->nalloc)
01163         numaaExtendArray(naa);
01164     naa->numa[n] = nac;
01165     naa->n++;
01166     return 0;
01167 }
01168 
01169 
01170 /*!
01171  *  numaaExtendArray()
01172  *
01173  *      Input:  naa
01174  *      Return: 0 if OK, 1 on error
01175  */
01176 l_int32
01177 numaaExtendArray(NUMAA  *naa)
01178 {
01179     PROCNAME("numaaExtendArray");
01180 
01181     if (!naa)
01182         return ERROR_INT("naa not defined", procName, 1);
01183 
01184     if ((naa->numa = (NUMA **)reallocNew((void **)&naa->numa,
01185                               sizeof(NUMA *) * naa->nalloc,
01186                               2 * sizeof(NUMA *) * naa->nalloc)) == NULL)
01187             return ERROR_INT("new ptr array not returned", procName, 1);
01188 
01189     naa->nalloc *= 2;
01190     return 0;
01191 }
01192 
01193 
01194 /*----------------------------------------------------------------------*
01195  *                           Numaa accessors                            *
01196  *----------------------------------------------------------------------*/
01197 /*!
01198  *  numaaGetCount()
01199  *
01200  *      Input:  naa
01201  *      Return: count (number of numa), or 0 if no numa or on error
01202  */
01203 l_int32
01204 numaaGetCount(NUMAA  *naa)
01205 {
01206     PROCNAME("numaaGetCount");
01207 
01208     if (!naa)
01209         return ERROR_INT("naa not defined", procName, 0);
01210     return naa->n;
01211 }
01212 
01213 
01214 /*!
01215  *  numaaGetNumaCount()
01216  *
01217  *      Input:  naa
01218  *              index (of numa in naa)
01219  *      Return: count of numbers in the referenced numa, or 0 on error.
01220  */
01221 l_int32
01222 numaaGetNumaCount(NUMAA   *naa,
01223                   l_int32  index)
01224 {
01225     PROCNAME("numaaGetNumaCount");
01226 
01227     if (!naa)
01228         return ERROR_INT("naa not defined", procName, 0);
01229     if (index < 0 || index >= naa->n)
01230         return ERROR_INT("invalid index into naa", procName, 0);
01231     return numaGetCount(naa->numa[index]);
01232 }
01233 
01234 
01235 /*!
01236  *  numaaGetNumberCount()
01237  *
01238  *      Input:  naa
01239  *      Return: count (total number of numbers in the numaa),
01240  *                     or 0 if no numbers or on error
01241  */
01242 l_int32
01243 numaaGetNumberCount(NUMAA  *naa)
01244 {
01245 NUMA    *na;
01246 l_int32  n, sum, i;
01247 
01248     PROCNAME("numaaGetNumberCount");
01249 
01250     if (!naa)
01251         return ERROR_INT("naa not defined", procName, 0);
01252 
01253     n = numaaGetCount(naa);
01254     for (sum = 0, i = 0; i < n; i++) {
01255         na = numaaGetNuma(naa, i, L_CLONE);
01256         sum += numaGetCount(na);
01257         numaDestroy(&na);
01258     }
01259 
01260     return sum;
01261 }
01262 
01263 
01264 /*!
01265  *  numaaGetPtrArray()
01266  *
01267  *      Input:  naa
01268  *      Return: the internal array of ptrs to Numa, or null on error
01269  *
01270  *  Notes:
01271  *      (1) This function is convenient for doing direct manipulation on
01272  *          a fixed size array of Numas.  To do this, it sets the count
01273  *          to the full size of the allocated array of Numa ptrs.
01274  *          The originating Numaa owns this array: DO NOT free it!
01275  *      (2) Intended usage:
01276  *            Numaa *naa = numaaCreate(n);
01277  *            Numa **array = numaaGetPtrArray(naa);
01278  *             ...  [manipulate Numas directly on the array]
01279  *            numaaDestroy(&naa);
01280  *      (3) Cautions:
01281  *           - Do not free this array; it is owned by tne Numaa.
01282  *           - Do not call any functions on the Numaa, other than
01283  *             numaaDestroy() when you're finished with the array.
01284  *             Adding a Numa will force a resize, destroying the ptr array.
01285  *           - Do not address the array outside its allocated size.
01286  *             With the bare array, there are no protections.  If the
01287  *             allocated size is n, array[n] is an error.
01288  */
01289 NUMA **
01290 numaaGetPtrArray(NUMAA  *naa)
01291 {
01292     PROCNAME("numaaGetPtrArray");
01293 
01294     if (!naa)
01295         return (NUMA **)ERROR_PTR("naa not defined", procName, NULL);
01296 
01297     naa->n = naa->nalloc;
01298     return naa->numa;
01299 }
01300 
01301 
01302 /*!
01303  *  numaaGetNuma()
01304  *
01305  *      Input:  naa
01306  *              index  (to the index-th numa)
01307  *              accessflag   (L_COPY or L_CLONE)
01308  *      Return: numa, or null on error
01309  */
01310 NUMA *
01311 numaaGetNuma(NUMAA   *naa,
01312              l_int32  index,
01313              l_int32  accessflag)
01314 {
01315     PROCNAME("numaaGetNuma");
01316 
01317     if (!naa)
01318         return (NUMA *)ERROR_PTR("naa not defined", procName, NULL);
01319     if (index < 0 || index >= naa->n)
01320         return (NUMA *)ERROR_PTR("index not valid", procName, NULL);
01321 
01322     if (accessflag == L_COPY)
01323         return numaCopy(naa->numa[index]);
01324     else if (accessflag == L_CLONE)
01325         return numaClone(naa->numa[index]);
01326     else
01327         return (NUMA *)ERROR_PTR("invalid accessflag", procName, NULL);
01328 }
01329 
01330 
01331 /*!
01332  *  numaaReplaceNuma()
01333  *
01334  *      Input:  naa
01335  *              index  (to the index-th numa)
01336  *              numa (insert and replace any existing one)
01337  *      Return: 0 if OK, 1 on error
01338  *
01339  *  Notes:
01340  *      (1) Any existing numa is destroyed, and the input one
01341  *          is inserted in its place.
01342  *      (2) If the index is invalid, return 1 (error)
01343  */
01344 l_int32
01345 numaaReplaceNuma(NUMAA   *naa,
01346                  l_int32  index,
01347                  NUMA    *na)
01348 {
01349 l_int32  n;
01350 
01351     PROCNAME("numaaReplaceNuma");
01352 
01353     if (!naa)
01354         return ERROR_INT("naa not defined", procName, 1);
01355     if (!na)
01356         return ERROR_INT("na not defined", procName, 1);
01357     n = numaaGetCount(naa);
01358     if (index < 0 || index >= n)
01359         return ERROR_INT("index not valid", procName, 1);
01360 
01361     numaDestroy(&naa->numa[index]);
01362     naa->numa[index] = na;
01363     return 0;
01364 }
01365 
01366 
01367 /*!
01368  *  numaaGetValue()
01369  *
01370  *      Input:  naa
01371  *              i (index of numa within numaa)
01372  *              j (index into numa)
01373  *              val (<return> float value)
01374  *      Return: 0 if OK, 1 on error
01375  */
01376 l_int32
01377 numaaGetValue(NUMAA      *naa,
01378               l_int32     i,
01379               l_int32     j,
01380               l_float32  *pval)
01381 {
01382 l_int32  n;
01383 NUMA    *na;
01384 
01385     PROCNAME("numaaGetFValue");
01386 
01387     if (!pval)
01388         return ERROR_INT("&val not defined", procName, 1);
01389     *pval = 0.0;
01390     if (!naa)
01391         return ERROR_INT("naa not defined", procName, 1);
01392     n = numaaGetCount(naa);
01393     if (i < 0 || i >= n)
01394         return ERROR_INT("invalid index into naa", procName, 1);
01395     na = naa->numa[i];
01396     if (j < 0 || j >= na->n)
01397         return ERROR_INT("invalid index into na", procName, 1);
01398     *pval = na->array[j];
01399     return 0;
01400 }
01401 
01402 
01403 /*!
01404  *  numaaAddNumber()
01405  *
01406  *      Input:  naa
01407  *              index (of numa within numaa)
01408  *              val  (float or int to be added; stored as a float)
01409  *      Return: 0 if OK, 1 on error
01410  *
01411  *  Notes:
01412  *      (1) Adds to an existing numa only.
01413  */
01414 l_int32
01415 numaaAddNumber(NUMAA     *naa,
01416                l_int32    index,
01417                l_float32  val)
01418 {
01419 l_int32  n;
01420 NUMA    *na;
01421 
01422     PROCNAME("numaaAddNumber");
01423 
01424     if (!naa)
01425         return ERROR_INT("naa not defined", procName, 1);
01426     n = numaaGetCount(naa);
01427     if (index < 0 || index >= n)
01428         return ERROR_INT("invalid index in naa", procName, 1);
01429 
01430     na = numaaGetNuma(naa, index, L_CLONE);
01431     numaAddNumber(na, val);
01432     numaDestroy(&na);
01433     return 0;
01434 }
01435 
01436 
01437 /*----------------------------------------------------------------------*
01438  *                      Serialize numaa for I/O                         *
01439  *----------------------------------------------------------------------*/
01440 /*!
01441  *  numaaRead()
01442  *
01443  *      Input:  filename
01444  *      Return: naa, or null on error
01445  */
01446 NUMAA *
01447 numaaRead(const char  *filename)
01448 {
01449 FILE   *fp;
01450 NUMAA  *naa;
01451 
01452     PROCNAME("numaaRead");
01453 
01454     if (!filename)
01455         return (NUMAA *)ERROR_PTR("filename not defined", procName, NULL);
01456 
01457     if ((fp = fopenReadStream(filename)) == NULL)
01458         return (NUMAA *)ERROR_PTR("stream not opened", procName, NULL);
01459 
01460     if ((naa = numaaReadStream(fp)) == NULL) {
01461         fclose(fp);
01462         return (NUMAA *)ERROR_PTR("naa not read", procName, NULL);
01463     }
01464 
01465     fclose(fp);
01466     return naa;
01467 }
01468 
01469 
01470 /*!
01471  *  numaaReadStream()
01472  *
01473  *      Input:  stream
01474  *      Return: naa, or null on error
01475  */
01476 NUMAA *
01477 numaaReadStream(FILE  *fp)
01478 {
01479 l_int32    i, n, index, ret, version;
01480 NUMA      *na;
01481 NUMAA     *naa;
01482 
01483     PROCNAME("numaaReadStream");
01484 
01485     if (!fp)
01486         return (NUMAA *)ERROR_PTR("stream not defined", procName, NULL);
01487 
01488     ret = fscanf(fp, "\nNumaa Version %d\n", &version);
01489     if (ret != 1)
01490         return (NUMAA *)ERROR_PTR("not a numa file", procName, NULL);
01491     if (version != NUMA_VERSION_NUMBER)
01492         return (NUMAA *)ERROR_PTR("invalid numaa version", procName, NULL);
01493     if (fscanf(fp, "Number of numa = %d\n\n", &n) != 1)
01494         return (NUMAA *)ERROR_PTR("invalid number of numa", procName, NULL);
01495     if ((naa = numaaCreate(n)) == NULL)
01496         return (NUMAA *)ERROR_PTR("naa not made", procName, NULL);
01497 
01498     for (i = 0; i < n; i++) {
01499         if (fscanf(fp, "Numa[%d]:", &index) != 1)
01500             return (NUMAA *)ERROR_PTR("invalid numa header", procName, NULL);
01501         if ((na = numaReadStream(fp)) == NULL)
01502             return (NUMAA *)ERROR_PTR("na not made", procName, NULL);
01503         numaaAddNuma(naa, na, L_INSERT);
01504     }
01505 
01506     return naa;
01507 }
01508 
01509 
01510 /*!
01511  *  numaaWrite()
01512  *
01513  *      Input:  filename, naa
01514  *      Return: 0 if OK, 1 on error
01515  */
01516 l_int32
01517 numaaWrite(const char  *filename,
01518            NUMAA       *naa)
01519 {
01520 FILE  *fp;
01521 
01522     PROCNAME("numaaWrite");
01523 
01524     if (!filename)
01525         return ERROR_INT("filename not defined", procName, 1);
01526     if (!naa)
01527         return ERROR_INT("naa not defined", procName, 1);
01528 
01529     if ((fp = fopenWriteStream(filename, "w")) == NULL)
01530         return ERROR_INT("stream not opened", procName, 1);
01531     if (numaaWriteStream(fp, naa))
01532         return ERROR_INT("naa not written to stream", procName, 1);
01533     fclose(fp);
01534 
01535     return 0;
01536 }
01537 
01538 
01539 /*!
01540  *  numaaWriteStream()
01541  *
01542  *      Input:  stream, naa
01543  *      Return: 0 if OK, 1 on error
01544  */
01545 l_int32
01546 numaaWriteStream(FILE   *fp,
01547                  NUMAA  *naa)
01548 {
01549 l_int32  i, n;
01550 NUMA    *na;
01551 
01552     PROCNAME("numaaWriteStream");
01553 
01554     if (!fp)
01555         return ERROR_INT("stream not defined", procName, 1);
01556     if (!naa)
01557         return ERROR_INT("naa not defined", procName, 1);
01558 
01559     n = numaaGetCount(naa);
01560     fprintf(fp, "\nNumaa Version %d\n", NUMA_VERSION_NUMBER);
01561     fprintf(fp, "Number of numa = %d\n\n", n);
01562     for (i = 0; i < n; i++) {
01563         if ((na = numaaGetNuma(naa, i, L_CLONE)) == NULL)
01564             return ERROR_INT("na not found", procName, 1);
01565         fprintf(fp, "Numa[%d]:", i);
01566         numaWriteStream(fp, na);
01567         numaDestroy(&na);
01568     }
01569 
01570     return 0;
01571 }
01572 
01573 
01574 /*--------------------------------------------------------------------------*
01575  *                      Numa2d creation, destruction                        *
01576  *--------------------------------------------------------------------------*/
01577 /*!
01578  *  numa2dCreate()
01579  *
01580  *      Input:  nrows (of 2d array)
01581  *              ncols (of 2d array)
01582  *              initsize (initial size of each allocated numa)
01583  *      Return: numa2d, or null on error
01584  *
01585  *  Notes:
01586  *      (1) The numa2d holds a doubly-indexed array of numa.
01587  *      (2) The numa ptr array is initialized with all ptrs set to NULL.
01588  *      (3) The numas are created only when a number is to be stored
01589  *          at an index (i,j) for which a numa has not yet been made.
01590  */
01591 NUMA2D *
01592 numa2dCreate(l_int32  nrows,
01593              l_int32  ncols,
01594              l_int32  initsize)
01595 {
01596 l_int32  i;
01597 NUMA2D  *na2d;
01598 
01599     PROCNAME("numa2dCreate");
01600 
01601     if (nrows <= 1 || ncols <= 1)
01602         return (NUMA2D *)ERROR_PTR("rows, cols not both >= 1", procName, NULL);
01603 
01604     if ((na2d = (NUMA2D *)CALLOC(1, sizeof(NUMA2D))) == NULL)
01605         return (NUMA2D *)ERROR_PTR("na2d not made", procName, NULL);
01606     na2d->nrows = nrows;
01607     na2d->ncols = ncols;
01608     na2d->initsize = initsize;
01609 
01610         /* Set up the 2D array */
01611     if ((na2d->numa = (NUMA ***)CALLOC(nrows, sizeof(NUMA **))) == NULL)
01612         return (NUMA2D *)ERROR_PTR("numa row array not made", procName, NULL);
01613     for (i = 0; i < nrows; i++) {
01614         if ((na2d->numa[i] = (NUMA **)CALLOC(ncols, sizeof(NUMA *))) == NULL)
01615             return (NUMA2D *)ERROR_PTR("numa cols not made", procName, NULL);
01616     }
01617 
01618     return na2d;
01619 }
01620 
01621 
01622 /*!
01623  *  numa2dDestroy()
01624  *
01625  *      Input:  &numa2d (<to be nulled if it exists>)
01626  *      Return: void
01627  */
01628 void
01629 numa2dDestroy(NUMA2D  **pna2d)
01630 {
01631 l_int32  i, j;
01632 NUMA2D  *na2d;
01633 
01634     PROCNAME("numa2dDestroy");
01635 
01636     if (pna2d == NULL) {
01637         L_WARNING("ptr address is NULL!", procName);
01638         return;
01639     }
01640 
01641     if ((na2d = *pna2d) == NULL)
01642         return;
01643 
01644     for (i = 0; i < na2d->nrows; i++) {
01645         for (j = 0; j < na2d->ncols; j++)
01646             numaDestroy(&na2d->numa[i][j]);
01647         FREE(na2d->numa[i]);
01648     }
01649     FREE(na2d->numa);
01650     FREE(na2d);
01651     *pna2d = NULL;
01652 
01653     return;
01654 }
01655 
01656 
01657 
01658 /*--------------------------------------------------------------------------*
01659  *                               Numa2d accessors                           *
01660  *--------------------------------------------------------------------------*/
01661 /*!
01662  *  numa2dAddNumber()
01663  *
01664  *      Input:  na2d
01665  *              row of 2d array
01666  *              col of 2d array
01667  *              val  (float or int to be added; stored as a float)
01668  *      Return: 0 if OK, 1 on error
01669  */
01670 l_int32
01671 numa2dAddNumber(NUMA2D    *na2d,
01672                 l_int32    row,
01673                 l_int32    col,
01674                 l_float32  val)
01675 {
01676 NUMA  *na;
01677 
01678     PROCNAME("numa2dAddNumber");
01679 
01680     if (!na2d)
01681         return ERROR_INT("na2d not defined", procName, 1);
01682     if (row < 0 || row >= na2d->nrows)
01683         return ERROR_INT("row out of bounds", procName, 1);
01684     if (col < 0 || col >= na2d->ncols)
01685         return ERROR_INT("col out of bounds", procName, 1);
01686 
01687     if ((na = na2d->numa[row][col]) == NULL) {
01688         na = numaCreate(na2d->initsize);
01689         na2d->numa[row][col] = na;
01690     }
01691     numaAddNumber(na, val);
01692     return 0;
01693 }
01694 
01695 
01696 /*!
01697  *  numa2dGetCount()
01698  *
01699  *      Input:  na2d
01700  *              row of 2d array
01701  *              col of 2d array
01702  *      Return: size of numa at [row][col], or 0 if the numa doesn't exist
01703  *              or on error
01704  */
01705 l_int32
01706 numa2dGetCount(NUMA2D  *na2d,
01707                l_int32  row,
01708                l_int32  col)
01709 {
01710 NUMA  *na;
01711 
01712     PROCNAME("numa2dGetCount");
01713 
01714     if (!na2d)
01715         return ERROR_INT("na2d not defined", procName, 0);
01716     if (row < 0 || row >= na2d->nrows)
01717         return ERROR_INT("row out of bounds", procName, 0);
01718     if (col < 0 || col >= na2d->ncols)
01719         return ERROR_INT("col out of bounds", procName, 0);
01720     if ((na = na2d->numa[row][col]) == NULL)
01721         return 0;
01722     else
01723         return na->n;
01724 }
01725 
01726 
01727 /*!
01728  *  numa2dGetNuma()
01729  *
01730  *      Input:  na2d
01731  *              row of 2d array
01732  *              col of 2d array
01733  *      Return: na (a clone of the numa if it exists) or null if it doesn't
01734  *
01735  *  Notes:
01736  *      (1) This does not give an error if the index is out of bounds.
01737  */
01738 NUMA *
01739 numa2dGetNuma(NUMA2D     *na2d,
01740               l_int32     row,
01741               l_int32     col)
01742 {
01743 NUMA  *na;
01744 
01745     PROCNAME("numa2dGetNuma");
01746 
01747     if (!na2d)
01748         return (NUMA *)ERROR_PTR("na2d not defined", procName, NULL);
01749     if (row < 0 || row >= na2d->nrows || col < 0 || col >= na2d->ncols)
01750         return NULL;
01751     if ((na = na2d->numa[row][col]) == NULL)
01752         return NULL;
01753     return numaClone(na);
01754 }
01755 
01756 
01757 /*!
01758  *  numa2dGetFValue()
01759  *
01760  *      Input:  na2d
01761  *              row of 2d array
01762  *              col of 2d array
01763  *              index (into numa)
01764  *              &val (<return> float value)
01765  *      Return: 0 if OK, 1 on error
01766  */
01767 l_int32
01768 numa2dGetFValue(NUMA2D     *na2d,
01769                 l_int32     row,
01770                 l_int32     col,
01771                 l_int32     index,
01772                 l_float32  *pval)
01773 {
01774 NUMA  *na;
01775 
01776     PROCNAME("numa2dGetFValue");
01777 
01778     if (!na2d)
01779         return ERROR_INT("na2d not defined", procName, 1);
01780     if (!pval)
01781         return ERROR_INT("&val not defined", procName, 1);
01782     *pval = 0.0;
01783 
01784     if (row < 0 || row >= na2d->nrows)
01785         return ERROR_INT("row out of bounds", procName, 1);
01786     if (col < 0 || col >= na2d->ncols)
01787         return ERROR_INT("col out of bounds", procName, 1);
01788     if ((na = na2d->numa[row][col]) == NULL)
01789         return ERROR_INT("numa does not exist", procName, 1);
01790 
01791     return numaGetFValue(na, index, pval);
01792 }
01793 
01794 
01795 /*!
01796  *  numa2dGetIValue()
01797  *
01798  *      Input:  na2d
01799  *              row of 2d array
01800  *              col of 2d array
01801  *              index (into numa)
01802  *              &val (<return> integer value)
01803  *      Return: 0 if OK, 1 on error
01804  */
01805 l_int32
01806 numa2dGetIValue(NUMA2D   *na2d,
01807                 l_int32   row,
01808                 l_int32   col,
01809                 l_int32   index,
01810                 l_int32  *pval)
01811 {
01812 NUMA  *na;
01813 
01814     PROCNAME("numa2dGetIValue");
01815 
01816     if (!na2d)
01817         return ERROR_INT("na2d not defined", procName, 1);
01818     if (!pval)
01819         return ERROR_INT("&val not defined", procName, 1);
01820     *pval = 0;
01821 
01822     if (row < 0 || row >= na2d->nrows)
01823         return ERROR_INT("row out of bounds", procName, 1);
01824     if (col < 0 || col >= na2d->ncols)
01825         return ERROR_INT("col out of bounds", procName, 1);
01826     if ((na = na2d->numa[row][col]) == NULL)
01827         return ERROR_INT("numa does not exist", procName, 1);
01828 
01829     return numaGetIValue(na, index, pval);
01830 }
01831 
01832 
01833 /*--------------------------------------------------------------------------*
01834  *               Number array hash: Creation and destruction                *
01835  *--------------------------------------------------------------------------*/
01836 /*!
01837  *  numaHashCreate()
01838  *
01839  *      Input: nbuckets (the number of buckets in the hash table,
01840  *                       which should be prime.)
01841  *             initsize (initial size of each allocated numa; 0 for default)
01842  *      Return: ptr to new nahash, or null on error
01843  *
01844  *  Note: actual numa are created only as required by numaHashAdd()
01845  */
01846 NUMAHASH *
01847 numaHashCreate(l_int32  nbuckets,
01848                l_int32  initsize)
01849 {
01850 NUMAHASH  *nahash;
01851 
01852     PROCNAME("numaHashCreate");
01853 
01854     if (nbuckets <= 0)
01855         return (NUMAHASH *)ERROR_PTR("negative hash size", procName, NULL);
01856     if ((nahash = (NUMAHASH *)CALLOC(1, sizeof(NUMAHASH))) == NULL)
01857         return (NUMAHASH *)ERROR_PTR("nahash not made", procName, NULL);
01858     if ((nahash->numa = (NUMA **)CALLOC(nbuckets, sizeof(NUMA *))) == NULL) {
01859         FREE(nahash);
01860         return (NUMAHASH *)ERROR_PTR("numa ptr array not made", procName, NULL);
01861     }
01862 
01863     nahash->nbuckets = nbuckets;
01864     nahash->initsize = initsize;
01865     return nahash;
01866 }
01867 
01868 
01869 /*!
01870  *  numaHashDestroy()
01871  *
01872  *      Input:  &nahash (<to be nulled, if it exists>)
01873  *      Return: void
01874  */
01875 void
01876 numaHashDestroy(NUMAHASH **pnahash)
01877 {
01878 NUMAHASH  *nahash;
01879 l_int32    i;
01880 
01881     PROCNAME("numaHashDestroy");
01882 
01883     if (pnahash == NULL) {
01884         L_WARNING("ptr address is NULL!", procName);
01885         return;
01886     }
01887 
01888     if ((nahash = *pnahash) == NULL)
01889         return;
01890 
01891     for (i = 0; i < nahash->nbuckets; i++)
01892         numaDestroy(&nahash->numa[i]);
01893     FREE(nahash->numa);
01894     FREE(nahash);
01895     *pnahash = NULL;
01896 }
01897 
01898 
01899 /*--------------------------------------------------------------------------*
01900  *               Number array hash: Add elements and return numas
01901  *--------------------------------------------------------------------------*/
01902 /*!
01903  *  numaHashGetNuma()
01904  *
01905  *      Input:  nahash
01906  *              key  (key to be hashed into a bucket number)
01907  *      Return: ptr to numa
01908  */
01909 NUMA *
01910 numaHashGetNuma(NUMAHASH  *nahash,
01911                 l_uint32   key)
01912 {
01913 l_int32  bucket;
01914 NUMA    *na;
01915 
01916     PROCNAME("numaHashGetNuma");
01917 
01918     if (!nahash)
01919         return (NUMA *)ERROR_PTR("nahash not defined", procName, NULL);
01920     bucket = key % nahash->nbuckets;
01921     na = nahash->numa[bucket];
01922     if (na)
01923         return numaClone(na);
01924     else
01925         return NULL;
01926 }
01927 
01928 /*!
01929  *  numaHashAdd()
01930  *
01931  *      Input:  nahash
01932  *              key  (key to be hashed into a bucket number)
01933  *              value  (float value to be appended to the specific numa)
01934  *      Return: 0 if OK; 1 on error
01935  */
01936 l_int32
01937 numaHashAdd(NUMAHASH  *nahash,
01938             l_uint32   key,
01939             l_float32  value)
01940 {
01941 l_int32  bucket;
01942 NUMA    *na;
01943 
01944     PROCNAME("numaHashAdd");
01945 
01946     if (!nahash)
01947         return ERROR_INT("nahash not defined", procName, 1);
01948     if (key < 0)
01949         return ERROR_INT("key < 0", procName, 1);
01950     bucket = key % nahash->nbuckets;
01951     na = nahash->numa[bucket];
01952     if (!na) {
01953         if ((na = numaCreate(nahash->initsize)) == NULL)
01954             return ERROR_INT("na not made", procName, 1);
01955         nahash->numa[bucket] = na;
01956     }
01957     numaAddNumber(na, value);
01958     return 0;
01959 }
01960 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines