Leptonica 1.68
C Image Processing Library
|
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