1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 - This software is distributed in the hope that it will be
4 - useful, but with NO WARRANTY OF ANY KIND.
5 - No author or distributor accepts responsibility to anyone for the
6 - consequences of using this software, or for whether it serves any
7 - particular purpose or works at all, unless he or she says so in
8 - writing. Everyone is granted permission to copy, modify and
9 - redistribute this source code, for commercial or non-commercial
10 - purposes, with the following restrictions: (1) the origin of this
11 - source code must not be misrepresented; (2) modified versions must
12 - be plainly marked as such; and (3) this notice may not be removed
13 - or altered from any source or modified source distribution.
14 *====================================================================*/
15
16 /*
17 * numabasic.c
18 *
19 * Numa creation, destruction, copy, clone, etc.
20 * NUMA *numaCreate()
21 * NUMA *numaCreateFromIArray()
22 * void *numaDestroy()
23 * NUMA *numaCopy()
24 * NUMA *numaClone()
25 * l_int32 numaEmpty()
26 *
27 * Add/remove number (float or integer)
28 * l_int32 numaAddNumber()
29 * l_int32 numaExtendArray()
30 * l_int32 numaInsertNumber()
31 * l_int32 numaRemoveNumber()
32 * l_int32 numaReplaceNumber()
33 *
34 * Numa accessors
35 * l_int32 numaGetCount()
36 * l_int32 numaSetCount()
37 * l_int32 numaGetIValue()
38 * l_int32 numaGetFValue()
39 * l_int32 numaSetValue()
40 * l_int32 numaShiftValue()
41 * l_int32 *numaGetIArray()
42 * l_float32 *numaGetFArray()
43 * l_int32 numaGetRefcount()
44 * l_int32 numaChangeRefcount()
45 * l_int32 numaGetXParameters()
46 * l_int32 numaSetXParameters()
47 * l_int32 numaCopyXParameters()
48 *
49 * Serialize numa for I/O
50 * l_int32 numaRead()
51 * l_int32 numaReadStream()
52 * l_int32 numaWrite()
53 * l_int32 numaWriteStream()
54 *
55 * Numaa creation, destruction
56 * NUMAA *numaaCreate()
57 * void *numaaDestroy()
58 *
59 * Add Numa to Numaa
60 * l_int32 numaaAddNuma()
61 * l_int32 numaaExtendArray()
62 *
63 * Numaa accessors
64 * l_int32 numaaGetCount()
65 * l_int32 numaaGetNumberCount()
66 * NUMA **numaaGetPtrArray()
67 * NUMA *numaaGetNuma()
68 * NUMA *numaaReplaceNuma()
69 * l_int32 numaaAddNumber()
70 *
71 * Serialize numaa for I/O
72 * l_int32 numaaRead()
73 * l_int32 numaaReadStream()
74 * l_int32 numaaWrite()
75 * l_int32 numaaWriteStream()
76 *
77 * Numa2d creation, destruction
78 * NUMA2D *numa2dCreate()
79 * void *numa2dDestroy()
80 *
81 * Numa2d Accessors
82 * l_int32 numa2dAddNumber()
83 * l_int32 numa2dGetCount()
84 * NUMA *numa2dGetNuma()
85 * l_int32 numa2dGetFValue()
86 * l_int32 numa2dGetIValue()
87 *
88 * NumaHash creation, destruction
89 * NUMAHASH *numaHashCreate()
90 * void *numaHashDestroy()
91 *
92 * NumaHash Accessors
93 * NUMA *numaHashGetNuma()
94 * void *numaHashAdd()
95 *
96 * (1) The numa is a struct, not an array. Always use the accessors
97 * in this file, never the fields directly.
98 *
99 * (2) The number array holds l_float32 values. It can also
100 * be used to store l_int32 values.
101 *
102 * (3) Storing and retrieving numbers:
103 *
104 * * to append a new number to the array, use numaAddNumber(). If
105 * the number is an int, it will will automatically be converted
106 * to l_float32 and stored.
107 *
108 * * to reset a value stored in the array, use numaSetValue().
109 *
110 * * to increment or decrement a value stored in the array,
111 * use numaShiftValue().
112 *
113 * * to obtain a value from the array, use either numaGetIValue()
114 * or numaGetFValue(), depending on whether you are retrieving
115 * an integer or a float. This avoids doing an explicit cast,
116 * such as
117 * (a) return a l_float32 and cast it to an l_int32
118 * (b) cast the return directly to (l_float32 *) to
119 * satisfy the function prototype, as in
120 * numaGetFValue(na, index, (l_float32 *)&ival); [ugly!]
121 *
122 * (4) int <--> float conversions:
123 *
124 * Tradition dictates that type conversions go automatically from
125 * l_int32 --> l_float32, even though it is possible to lose
126 * precision for large integers, whereas you must cast (l_int32)
127 * to go from l_float32 --> l_int32 because you're truncating
128 * to the integer value.
129 *
130 * (5) As with other arrays in leptonica, the numa has both an allocated
131 * size and a count of the stored numbers. When you add a number, it
132 * goes on the end of the array, and causes a realloc if the array
133 * is already filled. However, in situations where you want to
134 * add numbers randomly into an array, such as when you build a
135 * histogram, you must set the count of stored numbers in advance.
136 * This is done with numaSetCount(). If you set a count larger
137 * than the allocated array, it does a realloc to the size requested.
138 *
139 * (6) In situations where the data in a numa correspond to a function
140 * y(x), the values can be either at equal spacings in x or at
141 * arbitrary spacings. For the former, we can represent all x values
142 * by two parameters: startx (corresponding to y[0]) and delx
143 * for the change in x for adjacent values y[i] and y[i+1].
144 * startx and delx are initialized to 0.0 and 1.0, rsp.
145 * For arbitrary spacings, we use a second numa, and the two
146 * numas are typically denoted nay and nax.
147 *
148 * (7) The numa is also the basic struct used for histograms. Every numa
149 * has startx and delx fields, initialized to 0.0 and 1.0, that can
150 * be used to represent the "x" value for the location of the
151 * first bin and the bin width, respectively. Accessors are the
152 * numa*XParameters() functions. All functions that make numa
153 * histograms must set these fields properly, and many functions
154 * that use numa histograms rely on the correctness of these values.
155 */
156
157 #include <stdio.h>
158 #include <string.h>
159 #include <stdlib.h>
160 #include <math.h>
161 #include "allheaders.h"
162
163 static const l_int32 INITIAL_PTR_ARRAYSIZE = 50; /* n'importe quoi */
164
165
166 /*--------------------------------------------------------------------------*
167 * Numa creation, destruction, copy, clone, etc. *
168 *--------------------------------------------------------------------------*/
169 /*!
170 * numaCreate()
171 *
172 * Input: size of number array to be alloc'd (0 for default)
173 * Return: na, or null on error
174 */
175 NUMA *
numaCreate(l_int32 n)176 numaCreate(l_int32 n)
177 {
178 NUMA *na;
179
180 PROCNAME("numaCreate");
181
182 if (n <= 0)
183 n = INITIAL_PTR_ARRAYSIZE;
184
185 if ((na = (NUMA *)CALLOC(1, sizeof(NUMA))) == NULL)
186 return (NUMA *)ERROR_PTR("na not made", procName, NULL);
187 if ((na->array = (l_float32 *)CALLOC(n, sizeof(l_float32))) == NULL)
188 return (NUMA *)ERROR_PTR("number array not made", procName, NULL);
189
190 na->nalloc = n;
191 na->n = 0;
192 na->refcount = 1;
193 na->startx = 0.0;
194 na->delx = 1.0;
195
196 return na;
197 }
198
199
200 /*!
201 * numaCreateFromIArray()
202 *
203 * Input: int array
204 * size (of the array)
205 * Return: na, or null on error
206 *
207 * Notes:
208 * (1) This just copies the data from the int array into the numa.
209 * (2) The input array is NOT owned by the numa.
210 */
211 NUMA *
numaCreateFromIArray(l_int32 * array,l_int32 size)212 numaCreateFromIArray(l_int32 *array,
213 l_int32 size)
214 {
215 l_int32 i;
216 NUMA *na;
217
218 PROCNAME("numaCreateFromIArray");
219
220 if (!array)
221 return (NUMA *)ERROR_PTR("array not defined", procName, NULL);
222
223 na = numaCreate(size);
224 for (i = 0; i < size; i++)
225 numaAddNumber(na, array[i]);
226
227 return na;
228 }
229
230
231 /*!
232 * numaDestroy()
233 *
234 * Input: &na (<to be nulled if it exists>)
235 * Return: void
236 *
237 * Notes:
238 * (1) Decrements the ref count and, if 0, destroys the numa.
239 * (2) Always nulls the input ptr.
240 */
241 void
numaDestroy(NUMA ** pna)242 numaDestroy(NUMA **pna)
243 {
244 NUMA *na;
245
246 PROCNAME("numaDestroy");
247
248 if (pna == NULL) {
249 L_WARNING("ptr address is NULL", procName);
250 return;
251 }
252
253 if ((na = *pna) == NULL)
254 return;
255
256 /* Decrement the ref count. If it is 0, destroy the numa. */
257 numaChangeRefcount(na, -1);
258 if (numaGetRefcount(na) <= 0) {
259 if (na->array)
260 FREE(na->array);
261 FREE(na);
262 }
263
264 *pna = NULL;
265 return;
266 }
267
268
269 /*!
270 * numaCopy()
271 *
272 * Input: na
273 * Return: copy of numa, or null on error
274 */
275 NUMA *
numaCopy(NUMA * na)276 numaCopy(NUMA *na)
277 {
278 l_int32 i;
279 NUMA *cna;
280
281 PROCNAME("numaCopy");
282
283 if (!na)
284 return (NUMA *)ERROR_PTR("na not defined", procName, NULL);
285
286 if ((cna = numaCreate(na->nalloc)) == NULL)
287 return (NUMA *)ERROR_PTR("cna not made", procName, NULL);
288 cna->startx = na->startx;
289 cna->delx = na->delx;
290
291 for (i = 0; i < na->n; i++)
292 numaAddNumber(cna, na->array[i]);
293
294 return cna;
295 }
296
297
298 /*!
299 * numaClone()
300 *
301 * Input: na
302 * Return: ptr to same numa, or null on error
303 */
304 NUMA *
numaClone(NUMA * na)305 numaClone(NUMA *na)
306 {
307 PROCNAME("numaClone");
308
309 if (!na)
310 return (NUMA *)ERROR_PTR("na not defined", procName, NULL);
311
312 numaChangeRefcount(na, 1);
313 return na;
314 }
315
316
317 /*!
318 * numaEmpty()
319 *
320 * Input: na
321 * Return: 0 if OK; 1 on error
322 *
323 * Notes:
324 * (1) This does not change the allocation of the array.
325 * It just clears the number of stored numbers, so that
326 * the array appears to be empty.
327 */
328 l_int32
numaEmpty(NUMA * na)329 numaEmpty(NUMA *na)
330 {
331 PROCNAME("numaEmpty");
332
333 if (!na)
334 return ERROR_INT("na not defined", procName, 1);
335
336 na->n = 0;
337 return 0;
338 }
339
340
341
342 /*--------------------------------------------------------------------------*
343 * Number array: add number and extend array *
344 *--------------------------------------------------------------------------*/
345 /*!
346 * numaAddNumber()
347 *
348 * Input: na
349 * val (float or int to be added; stored as a float)
350 * Return: 0 if OK, 1 on error
351 */
352 l_int32
numaAddNumber(NUMA * na,l_float32 val)353 numaAddNumber(NUMA *na,
354 l_float32 val)
355 {
356 l_int32 n;
357
358 PROCNAME("numaAddNumber");
359
360 if (!na)
361 return ERROR_INT("na not defined", procName, 1);
362
363 n = numaGetCount(na);
364 if (n >= na->nalloc)
365 numaExtendArray(na);
366 na->array[n] = val;
367 na->n++;
368 return 0;
369 }
370
371
372 /*!
373 * numaExtendArray()
374 *
375 * Input: na
376 * Return: 0 if OK, 1 on error
377 */
378 l_int32
numaExtendArray(NUMA * na)379 numaExtendArray(NUMA *na)
380 {
381 PROCNAME("numaExtendArray");
382
383 if (!na)
384 return ERROR_INT("na not defined", procName, 1);
385
386 if ((na->array = (l_float32 *)reallocNew((void **)&na->array,
387 sizeof(l_float32) * na->nalloc,
388 2 * sizeof(l_float32) * na->nalloc)) == NULL)
389 return ERROR_INT("new ptr array not returned", procName, 1);
390
391 na->nalloc *= 2;
392 return 0;
393 }
394
395
396 /*!
397 * numaInsertNumber()
398 *
399 * Input: na
400 * index (location in na to insert new value)
401 * val (float32 or integer to be added)
402 * Return: 0 if OK, 1 on error
403 *
404 * Notes:
405 * (1) This shifts na[i] --> na[i + 1] for all i >= index,
406 * and then inserts val as na[index].
407 * (2) It should not be used repeatedly on large arrays,
408 * because the function is O(n).
409 *
410 */
411 l_int32
numaInsertNumber(NUMA * na,l_int32 index,l_float32 val)412 numaInsertNumber(NUMA *na,
413 l_int32 index,
414 l_float32 val)
415 {
416 l_int32 i, n;
417
418 PROCNAME("numaInsertNumber");
419
420 if (!na)
421 return ERROR_INT("na not defined", procName, 1);
422 n = numaGetCount(na);
423 if (index < 0 || index > n)
424 return ERROR_INT("index not in {0...n}", procName, 1);
425
426 if (n >= na->nalloc)
427 numaExtendArray(na);
428 for (i = n; i > index; i--)
429 na->array[i] = na->array[i - 1];
430 na->array[index] = val;
431 na->n++;
432 return 0;
433 }
434
435
436 /*!
437 * numaRemoveNumber()
438 *
439 * Input: na
440 * index (element to be removed)
441 * Return: 0 if OK, 1 on error
442 *
443 * Notes:
444 * (1) This shifts na[i] --> na[i - 1] for all i > index.
445 * (2) It should not be used repeatedly on large arrays,
446 * because the function is O(n).
447 */
448 l_int32
numaRemoveNumber(NUMA * na,l_int32 index)449 numaRemoveNumber(NUMA *na,
450 l_int32 index)
451 {
452 l_int32 i, n;
453
454 PROCNAME("numaRemoveNumber");
455
456 if (!na)
457 return ERROR_INT("na not defined", procName, 1);
458 n = numaGetCount(na);
459 if (index < 0 || index >= n)
460 return ERROR_INT("index not in {0...n - 1}", procName, 1);
461
462 for (i = index + 1; i < n; i++)
463 na->array[i - 1] = na->array[i];
464 na->n--;
465 return 0;
466 }
467
468
469 /*!
470 * numaReplaceNumber()
471 *
472 * Input: na
473 * index (element to be replaced)
474 * val (new value to replace old one)
475 * Return: 0 if OK, 1 on error
476 */
477 l_int32
numaReplaceNumber(NUMA * na,l_int32 index,l_float32 val)478 numaReplaceNumber(NUMA *na,
479 l_int32 index,
480 l_float32 val)
481 {
482 l_int32 n;
483
484 PROCNAME("numaReplaceNumber");
485
486 if (!na)
487 return ERROR_INT("na not defined", procName, 1);
488 n = numaGetCount(na);
489 if (index < 0 || index >= n)
490 return ERROR_INT("index not in {0...n - 1}", procName, 1);
491
492 na->array[index] = val;
493 return 0;
494 }
495
496
497 /*----------------------------------------------------------------------*
498 * Numa accessors *
499 *----------------------------------------------------------------------*/
500 /*!
501 * numaGetCount()
502 *
503 * Input: na
504 * Return: count, or 0 if no numbers or on error
505 */
506 l_int32
numaGetCount(NUMA * na)507 numaGetCount(NUMA *na)
508 {
509 PROCNAME("numaGetCount");
510
511 if (!na)
512 return ERROR_INT("na not defined", procName, 0);
513 return na->n;
514 }
515
516
517 /*!
518 * numaSetCount()
519 *
520 * Input: na
521 * newcount
522 * Return: 0 if OK, 1 on error
523 *
524 * Notes:
525 * (1) If newcount <= na->nalloc, this resets na->n.
526 * Using newcount = 0 is equivalent to numaEmpty().
527 * (2) If newcount > na->nalloc, this causes a realloc
528 * to a size na->nalloc = newcount.
529 * (3) All the previously unused values in na are set to 0.0.
530 */
531 l_int32
numaSetCount(NUMA * na,l_int32 newcount)532 numaSetCount(NUMA *na,
533 l_int32 newcount)
534 {
535 PROCNAME("numaSetCount");
536
537 if (!na)
538 return ERROR_INT("na not defined", procName, 1);
539 if (newcount > na->nalloc) {
540 if ((na->array = (l_float32 *)reallocNew((void **)&na->array,
541 sizeof(l_float32) * na->nalloc,
542 sizeof(l_float32) * newcount)) == NULL)
543 return ERROR_INT("new ptr array not returned", procName, 1);
544 na->nalloc = newcount;
545 }
546 na->n = newcount;
547 return 0;
548 }
549
550
551 /*!
552 * numaGetFValue()
553 *
554 * Input: na
555 * index (into numa)
556 * &val (<return> float value; 0.0 on error)
557 * Return: 0 if OK; 1 on error
558 *
559 * Notes:
560 * (1) Caller may need to check the function return value to
561 * decide if a 0.0 in the returned ival is valid.
562 */
563 l_int32
numaGetFValue(NUMA * na,l_int32 index,l_float32 * pval)564 numaGetFValue(NUMA *na,
565 l_int32 index,
566 l_float32 *pval)
567 {
568 PROCNAME("numaGetFValue");
569
570 if (!pval)
571 return ERROR_INT("&val not defined", procName, 1);
572 *pval = 0.0;
573 if (!na)
574 return ERROR_INT("na not defined", procName, 1);
575
576 if (index < 0 || index >= na->n)
577 return ERROR_INT("index not valid", procName, 1);
578
579 *pval = na->array[index];
580 return 0;
581 }
582
583
584 /*!
585 * numaGetIValue()
586 *
587 * Input: na
588 * index (into numa)
589 * &ival (<return> integer value; 0 on error)
590 * Return: 0 if OK; 1 on error
591 *
592 * Notes:
593 * (1) Caller may need to check the function return value to
594 * decide if a 0 in the returned ival is valid.
595 */
596 l_int32
numaGetIValue(NUMA * na,l_int32 index,l_int32 * pival)597 numaGetIValue(NUMA *na,
598 l_int32 index,
599 l_int32 *pival)
600 {
601 l_float32 val;
602
603 PROCNAME("numaGetIValue");
604
605 if (!pival)
606 return ERROR_INT("&ival not defined", procName, 1);
607 *pival = 0;
608 if (!na)
609 return ERROR_INT("na not defined", procName, 1);
610
611 if (index < 0 || index >= na->n)
612 return ERROR_INT("index not valid", procName, 1);
613
614 val = na->array[index];
615 *pival = (l_int32)(val + L_SIGN(val) * 0.5);
616 return 0;
617 }
618
619
620 /*!
621 * numaSetValue()
622 *
623 * Input: na
624 * index (to element to be set)
625 * val (to set element)
626 * Return: 0 if OK; 1 on error
627 */
628 l_int32
numaSetValue(NUMA * na,l_int32 index,l_float32 val)629 numaSetValue(NUMA *na,
630 l_int32 index,
631 l_float32 val)
632 {
633 PROCNAME("numaSetValue");
634
635 if (!na)
636 return ERROR_INT("na not defined", procName, 1);
637 if (index < 0 || index >= na->n)
638 return ERROR_INT("index not valid", procName, 1);
639
640 na->array[index] = val;
641 return 0;
642 }
643
644
645 /*!
646 * numaShiftValue()
647 *
648 * Input: na
649 * index (to element to change relative to the current value)
650 * diff (increment if diff > 0 or decrement if diff < 0)
651 * Return: 0 if OK; 1 on error
652 */
653 l_int32
numaShiftValue(NUMA * na,l_int32 index,l_float32 diff)654 numaShiftValue(NUMA *na,
655 l_int32 index,
656 l_float32 diff)
657 {
658 PROCNAME("numaShiftValue");
659
660 if (!na)
661 return ERROR_INT("na not defined", procName, 1);
662 if (index < 0 || index >= na->n)
663 return ERROR_INT("index not valid", procName, 1);
664
665 na->array[index] += diff;
666 return 0;
667 }
668
669
670 /*!
671 * numaGetIArray()
672 *
673 * Input: na
674 * Return: a copy of the bare internal array, integerized
675 * by rounding, or null on error
676 * Notes:
677 * (1) A copy of the array is always made, because we need to
678 * generate an integer array from the bare float array.
679 * The caller is responsible for freeing the array.
680 * (2) The array size is determined by the number of stored numbers,
681 * not by the size of the allocated array in the Numa.
682 * (3) This function is provided to simplify calculations
683 * using the bare internal array, rather than continually
684 * calling accessors on the numa. It is typically used
685 * on an array of size 256.
686 */
687 l_int32 *
numaGetIArray(NUMA * na)688 numaGetIArray(NUMA *na)
689 {
690 l_int32 i, n, ival;
691 l_int32 *array;
692
693 PROCNAME("numaGetIArray");
694
695 if (!na)
696 return (l_int32 *)ERROR_PTR("na not defined", procName, NULL);
697
698 n = numaGetCount(na);
699 if ((array = (l_int32 *)CALLOC(n, sizeof(l_int32))) == NULL)
700 return (l_int32 *)ERROR_PTR("array not made", procName, NULL);
701 for (i = 0; i < n; i++) {
702 numaGetIValue(na, i, &ival);
703 array[i] = ival;
704 }
705
706 return array;
707 }
708
709
710 /*!
711 * numaGetFArray()
712 *
713 * Input: na
714 * copyflag (L_NOCOPY or L_COPY)
715 * Return: either the bare internal array or a copy of it,
716 * or null on error
717 *
718 * Notes:
719 * (1) If copyflag == L_COPY, it makes a copy which the caller
720 * is responsible for freeing. Otherwise, it operates
721 * directly on the bare array of the numa.
722 * (2) Very important: for L_NOCOPY, any writes to the array
723 * will be in the numa. Do not write beyond the size of
724 * the count field, because it will not be accessable
725 * from the numa! If necessary, be sure to set the count
726 * the count field to a larger number (such as the alloc
727 * size) BEFORE calling this function.
728 */
729 l_float32 *
numaGetFArray(NUMA * na,l_int32 copyflag)730 numaGetFArray(NUMA *na,
731 l_int32 copyflag)
732 {
733 l_int32 i, n;
734 l_float32 *array;
735
736 PROCNAME("numaGetFArray");
737
738 if (!na)
739 return (l_float32 *)ERROR_PTR("na not defined", procName, NULL);
740
741 if (copyflag == L_NOCOPY)
742 array = na->array;
743 else { /* copyflag == L_COPY */
744 n = numaGetCount(na);
745 if ((array = (l_float32 *)CALLOC(n, sizeof(l_float32))) == NULL)
746 return (l_float32 *)ERROR_PTR("array not made", procName, NULL);
747 for (i = 0; i < n; i++)
748 array[i] = na->array[i];
749 }
750
751 return array;
752 }
753
754
755 /*!
756 * numaGetRefCount()
757 *
758 * Input: na
759 * Return: refcount, or UNDEF on error
760 */
761 l_int32
numaGetRefcount(NUMA * na)762 numaGetRefcount(NUMA *na)
763 {
764 PROCNAME("numaGetRefcount");
765
766 if (!na)
767 return ERROR_INT("na not defined", procName, UNDEF);
768 return na->refcount;
769 }
770
771
772 /*!
773 * numaChangeRefCount()
774 *
775 * Input: na
776 * delta (change to be applied)
777 * Return: 0 if OK, 1 on error
778 */
779 l_int32
numaChangeRefcount(NUMA * na,l_int32 delta)780 numaChangeRefcount(NUMA *na,
781 l_int32 delta)
782 {
783 PROCNAME("numaChangeRefcount");
784
785 if (!na)
786 return ERROR_INT("na not defined", procName, 1);
787 na->refcount += delta;
788 return 0;
789 }
790
791
792 /*!
793 * numaGetXParameters()
794 *
795 * Input: na
796 * &startx (<optional return> startx)
797 * &delx (<optional return> delx)
798 * Return: 0 if OK, 1 on error
799 */
800 l_int32
numaGetXParameters(NUMA * na,l_float32 * pstartx,l_float32 * pdelx)801 numaGetXParameters(NUMA *na,
802 l_float32 *pstartx,
803 l_float32 *pdelx)
804 {
805 PROCNAME("numaGetXParameters");
806
807 if (!na)
808 return ERROR_INT("na not defined", procName, 1);
809
810 if (pstartx) *pstartx = na->startx;
811 if (pdelx) *pdelx = na->delx;
812 return 0;
813 }
814
815
816 /*!
817 * numaSetXParameters()
818 *
819 * Input: na
820 * startx (x value corresponding to na[0])
821 * delx (difference in x values for the situation where the
822 * elements of na correspond to the evaulation of a
823 * function at equal intervals of size @delx)
824 * Return: 0 if OK, 1 on error
825 */
826 l_int32
numaSetXParameters(NUMA * na,l_float32 startx,l_float32 delx)827 numaSetXParameters(NUMA *na,
828 l_float32 startx,
829 l_float32 delx)
830 {
831 PROCNAME("numaSetXParameters");
832
833 if (!na)
834 return ERROR_INT("na not defined", procName, 1);
835
836 na->startx = startx;
837 na->delx = delx;
838 return 0;
839 }
840
841
842 /*!
843 * numaCopyXParameters()
844 *
845 * Input: nad (destination Numa)
846 * nas (source Numa)
847 * Return: 0 if OK, 1 on error
848 */
849 l_int32
numaCopyXParameters(NUMA * nad,NUMA * nas)850 numaCopyXParameters(NUMA *nad,
851 NUMA *nas)
852 {
853 l_float32 start, binsize;
854
855 PROCNAME("numaCopyXParameters");
856
857 if (!nas || !nad)
858 return ERROR_INT("nas and nad not both defined", procName, 1);
859
860 numaGetXParameters(nas, &start, &binsize);
861 numaSetXParameters(nad, start, binsize);
862 return 0;
863 }
864
865
866 /*----------------------------------------------------------------------*
867 * Serialize numa for I/O *
868 *----------------------------------------------------------------------*/
869 /*!
870 * numaRead()
871 *
872 * Input: filename
873 * Return: na, or null on error
874 */
875 NUMA *
numaRead(const char * filename)876 numaRead(const char *filename)
877 {
878 FILE *fp;
879 NUMA *na;
880
881 PROCNAME("numaRead");
882
883 if (!filename)
884 return (NUMA *)ERROR_PTR("filename not defined", procName, NULL);
885
886 if ((fp = fopenReadStream(filename)) == NULL)
887 return (NUMA *)ERROR_PTR("stream not opened", procName, NULL);
888
889 if ((na = numaReadStream(fp)) == NULL) {
890 fclose(fp);
891 return (NUMA *)ERROR_PTR("na not read", procName, NULL);
892 }
893
894 fclose(fp);
895 return na;
896 }
897
898
899 /*!
900 * numaReadStream()
901 *
902 * Input: stream
903 * Return: numa, or null on error
904 */
905 NUMA *
numaReadStream(FILE * fp)906 numaReadStream(FILE *fp)
907 {
908 l_int32 i, n, index, ret, version;
909 l_float32 val, startx, delx;
910 NUMA *na;
911
912 PROCNAME("numaReadStream");
913
914 if (!fp)
915 return (NUMA *)ERROR_PTR("stream not defined", procName, NULL);
916
917 ret = fscanf(fp, "\nNuma Version %d\n", &version);
918 if (ret != 1)
919 return (NUMA *)ERROR_PTR("not a numa file", procName, NULL);
920 if (version != NUMA_VERSION_NUMBER)
921 return (NUMA *)ERROR_PTR("invalid numa version", procName, NULL);
922 fscanf(fp, "Number of numbers = %d\n", &n);
923
924 if ((na = numaCreate(n)) == NULL)
925 return (NUMA *)ERROR_PTR("na not made", procName, NULL);
926
927 for (i = 0; i < n; i++) {
928 if ((fscanf(fp, " [%d] = %f\n", &index, &val)) != 2)
929 return (NUMA *)ERROR_PTR("bad input data", procName, NULL);
930 numaAddNumber(na, val);
931 }
932
933 /* Optional data */
934 if ((fscanf(fp, "startx = %f, delx = %f\n", &startx, &delx)) == 2)
935 numaSetXParameters(na, startx, delx);
936
937 return na;
938 }
939
940
941 /*!
942 * numaWrite()
943 *
944 * Input: filename, na
945 * Return: 0 if OK, 1 on error
946 */
947 l_int32
numaWrite(const char * filename,NUMA * na)948 numaWrite(const char *filename,
949 NUMA *na)
950 {
951 FILE *fp;
952
953 PROCNAME("numaWrite");
954
955 if (!filename)
956 return ERROR_INT("filename not defined", procName, 1);
957 if (!na)
958 return ERROR_INT("na not defined", procName, 1);
959
960 if ((fp = fopen(filename, "w")) == NULL)
961 return ERROR_INT("stream not opened", procName, 1);
962 if (numaWriteStream(fp, na))
963 return ERROR_INT("na not written to stream", procName, 1);
964 fclose(fp);
965
966 return 0;
967 }
968
969
970 /*!
971 * numaWriteStream()
972 *
973 * Input: stream, na
974 * Return: 0 if OK, 1 on error
975 */
976 l_int32
numaWriteStream(FILE * fp,NUMA * na)977 numaWriteStream(FILE *fp,
978 NUMA *na)
979 {
980 l_int32 i, n;
981 l_float32 startx, delx;
982
983 PROCNAME("numaWriteStream");
984
985 if (!fp)
986 return ERROR_INT("stream not defined", procName, 1);
987 if (!na)
988 return ERROR_INT("na not defined", procName, 1);
989
990 n = numaGetCount(na);
991 fprintf(fp, "\nNuma Version %d\n", NUMA_VERSION_NUMBER);
992 fprintf(fp, "Number of numbers = %d\n", n);
993 for (i = 0; i < n; i++)
994 fprintf(fp, " [%d] = %f\n", i, na->array[i]);
995 fprintf(fp, "\n");
996
997 /* Optional data */
998 numaGetXParameters(na, &startx, &delx);
999 if (startx != 0.0 || delx != 1.0)
1000 fprintf(fp, "startx = %f, delx = %f\n", startx, delx);
1001
1002 return 0;
1003 }
1004
1005
1006
1007 /*--------------------------------------------------------------------------*
1008 * Numaa creation, destruction *
1009 *--------------------------------------------------------------------------*/
1010 /*!
1011 * numaaCreate()
1012 *
1013 * Input: size of numa ptr array to be alloc'd (0 for default)
1014 * Return: naa, or null on error
1015 *
1016 */
1017 NUMAA *
numaaCreate(l_int32 n)1018 numaaCreate(l_int32 n)
1019 {
1020 NUMAA *naa;
1021
1022 PROCNAME("numaaCreate");
1023
1024 if (n <= 0)
1025 n = INITIAL_PTR_ARRAYSIZE;
1026
1027 if ((naa = (NUMAA *)CALLOC(1, sizeof(NUMAA))) == NULL)
1028 return (NUMAA *)ERROR_PTR("naa not made", procName, NULL);
1029 if ((naa->numa = (NUMA **)CALLOC(n, sizeof(NUMA *))) == NULL)
1030 return (NUMAA *)ERROR_PTR("numa ptr array not made", procName, NULL);
1031
1032 naa->nalloc = n;
1033 naa->n = 0;
1034
1035 return naa;
1036 }
1037
1038
1039 /*!
1040 * numaaDestroy()
1041 *
1042 * Input: &numaa <to be nulled if it exists>
1043 * Return: void
1044 */
1045 void
numaaDestroy(NUMAA ** pnaa)1046 numaaDestroy(NUMAA **pnaa)
1047 {
1048 l_int32 i;
1049 NUMAA *naa;
1050
1051 PROCNAME("numaaDestroy");
1052
1053 if (pnaa == NULL) {
1054 L_WARNING("ptr address is NULL!", procName);
1055 return;
1056 }
1057
1058 if ((naa = *pnaa) == NULL)
1059 return;
1060
1061 for (i = 0; i < naa->n; i++)
1062 numaDestroy(&naa->numa[i]);
1063 FREE(naa->numa);
1064 FREE(naa);
1065 *pnaa = NULL;
1066
1067 return;
1068 }
1069
1070
1071
1072 /*--------------------------------------------------------------------------*
1073 * Add Numa to Numaa *
1074 *--------------------------------------------------------------------------*/
1075 /*!
1076 * numaaAddNuma()
1077 *
1078 * Input: naa
1079 * na (to be added)
1080 * copyflag (L_INSERT, L_COPY, L_CLONE)
1081 * Return: 0 if OK, 1 on error
1082 */
1083 l_int32
numaaAddNuma(NUMAA * naa,NUMA * na,l_int32 copyflag)1084 numaaAddNuma(NUMAA *naa,
1085 NUMA *na,
1086 l_int32 copyflag)
1087 {
1088 l_int32 n;
1089 NUMA *nac;
1090
1091 PROCNAME("numaaAddNuma");
1092
1093 if (!naa)
1094 return ERROR_INT("naa not defined", procName, 1);
1095 if (!na)
1096 return ERROR_INT("na not defined", procName, 1);
1097
1098 if (copyflag == L_INSERT)
1099 nac = na;
1100 else if (copyflag == L_COPY) {
1101 if ((nac = numaCopy(na)) == NULL)
1102 return ERROR_INT("nac not made", procName, 1);
1103 }
1104 else if (copyflag == L_CLONE)
1105 nac = numaClone(na);
1106 else
1107 return ERROR_INT("invalid copyflag", procName, 1);
1108
1109 n = numaaGetCount(naa);
1110 if (n >= naa->nalloc)
1111 numaaExtendArray(naa);
1112 naa->numa[n] = nac;
1113 naa->n++;
1114 return 0;
1115 }
1116
1117
1118 /*!
1119 * numaaExtendArray()
1120 *
1121 * Input: naa
1122 * Return: 0 if OK, 1 on error
1123 */
1124 l_int32
numaaExtendArray(NUMAA * naa)1125 numaaExtendArray(NUMAA *naa)
1126 {
1127 PROCNAME("numaaExtendArray");
1128
1129 if (!naa)
1130 return ERROR_INT("naa not defined", procName, 1);
1131
1132 if ((naa->numa = (NUMA **)reallocNew((void **)&naa->numa,
1133 sizeof(NUMA *) * naa->nalloc,
1134 2 * sizeof(NUMA *) * naa->nalloc)) == NULL)
1135 return ERROR_INT("new ptr array not returned", procName, 1);
1136
1137 naa->nalloc *= 2;
1138 return 0;
1139 }
1140
1141
1142 /*----------------------------------------------------------------------*
1143 * Numaa accessors *
1144 *----------------------------------------------------------------------*/
1145 /*!
1146 * numaaGetCount()
1147 *
1148 * Input: naa
1149 * Return: count (number of numa), or 0 if no numa or on error
1150 */
1151 l_int32
numaaGetCount(NUMAA * naa)1152 numaaGetCount(NUMAA *naa)
1153 {
1154 PROCNAME("numaaGetCount");
1155
1156 if (!naa)
1157 return ERROR_INT("naa not defined", procName, 0);
1158 return naa->n;
1159 }
1160
1161
1162 /*!
1163 * numaaGetNumberCount()
1164 *
1165 * Input: naa
1166 * Return: count (number of numbers), or 0 if no numbers or on error
1167 */
1168 l_int32
numaaGetNumberCount(NUMAA * naa)1169 numaaGetNumberCount(NUMAA *naa)
1170 {
1171 NUMA *na;
1172 l_int32 n, sum, i;
1173
1174 PROCNAME("numaaGetNumberCount");
1175
1176 if (!naa)
1177 return ERROR_INT("naa not defined", procName, 0);
1178
1179 n = numaaGetCount(naa);
1180 for (sum = 0, i = 0; i < n; i++) {
1181 na = numaaGetNuma(naa, i, L_CLONE);
1182 sum += numaGetCount(na);
1183 numaDestroy(&na);
1184 }
1185
1186 return sum;
1187 }
1188
1189
1190 /*!
1191 * numaaGetPtrArray()
1192 *
1193 * Input: naa
1194 * Return: the internal array of ptrs to Numa, or null on error
1195 *
1196 * Notes:
1197 * (1) This function is convenient for doing direct manipulation on
1198 * a fixed size array of Numas. To do this, it sets the count
1199 * to the full size of the allocated array of Numa ptrs.
1200 * The originating Numaa owns this array: DO NOT free it!
1201 * (2) Intended usage:
1202 * Numaa *naa = numaaCreate(n);
1203 * Numa **array = numaaGetPtrArray(naa);
1204 * ... [manipulate Numas directly on the array]
1205 * numaaDestroy(&naa);
1206 * (3) Cautions:
1207 * - Do not free this array; it is owned by tne Numaa.
1208 * - Do not call any functions on the Numaa, other than
1209 * numaaDestroy() when you're finished with the array.
1210 * Adding a Numa will force a resize, destroying the ptr array.
1211 * - Do not address the array outside its allocated size.
1212 * With the bare array, there are no protections. If the
1213 * allocated size is n, array[n] is an error.
1214 */
1215 NUMA **
numaaGetPtrArray(NUMAA * naa)1216 numaaGetPtrArray(NUMAA *naa)
1217 {
1218 PROCNAME("numaaGetPtrArray");
1219
1220 if (!naa)
1221 return (NUMA **)ERROR_PTR("naa not defined", procName, NULL);
1222
1223 naa->n = naa->nalloc;
1224 return naa->numa;
1225 }
1226
1227
1228 /*!
1229 * numaaGetNuma()
1230 *
1231 * Input: naa
1232 * index (to the index-th numa)
1233 * accessflag (L_COPY or L_CLONE)
1234 * Return: numa, or null on error
1235 */
1236 NUMA *
numaaGetNuma(NUMAA * naa,l_int32 index,l_int32 accessflag)1237 numaaGetNuma(NUMAA *naa,
1238 l_int32 index,
1239 l_int32 accessflag)
1240 {
1241 PROCNAME("numaaGetNuma");
1242
1243 if (!naa)
1244 return (NUMA *)ERROR_PTR("naa not defined", procName, NULL);
1245 if (index < 0 || index >= naa->n)
1246 return (NUMA *)ERROR_PTR("index not valid", procName, NULL);
1247
1248 if (accessflag == L_COPY)
1249 return numaCopy(naa->numa[index]);
1250 else if (accessflag == L_CLONE)
1251 return numaClone(naa->numa[index]);
1252 else
1253 return (NUMA *)ERROR_PTR("invalid accessflag", procName, NULL);
1254 }
1255
1256
1257 /*!
1258 * numaaReplaceNuma()
1259 *
1260 * Input: naa
1261 * index (to the index-th numa)
1262 * numa (insert and replace any existing one)
1263 * Return: 0 if OK, 1 on error
1264 *
1265 * Notes:
1266 * (1) Any existing numa is destroyed, and the input one
1267 * is inserted in its place.
1268 * (2) If the index is invalid, return 1 (error)
1269 */
1270 l_int32
numaaReplaceNuma(NUMAA * naa,l_int32 index,NUMA * na)1271 numaaReplaceNuma(NUMAA *naa,
1272 l_int32 index,
1273 NUMA *na)
1274 {
1275 l_int32 n;
1276
1277 PROCNAME("numaaReplaceNuma");
1278
1279 if (!naa)
1280 return ERROR_INT("naa not defined", procName, 1);
1281 if (!na)
1282 return ERROR_INT("na not defined", procName, 1);
1283 n = numaaGetCount(naa);
1284 if (index < 0 || index >= n)
1285 return ERROR_INT("index not valid", procName, 1);
1286
1287 numaDestroy(&naa->numa[index]);
1288 naa->numa[index] = na;
1289 return 0;
1290 }
1291
1292
1293 /*!
1294 * numaaAddNumber()
1295 *
1296 * Input: naa
1297 * index (of numa within numaa)
1298 * val (float or int to be added; stored as a float)
1299 * Return: 0 if OK, 1 on error
1300 *
1301 * Notes:
1302 * (1) Adds to an existing numa only.
1303 */
1304 l_int32
numaaAddNumber(NUMAA * naa,l_int32 index,l_float32 val)1305 numaaAddNumber(NUMAA *naa,
1306 l_int32 index,
1307 l_float32 val)
1308 {
1309 l_int32 n;
1310 NUMA *na;
1311
1312 PROCNAME("numaaAddNumber");
1313
1314 if (!naa)
1315 return ERROR_INT("naa not defined", procName, 1);
1316 n = numaaGetCount(naa);
1317 if (index < 0 || index >= n)
1318 return ERROR_INT("invalid index in naa", procName, 1);
1319
1320 na = numaaGetNuma(naa, index, L_CLONE);
1321 numaAddNumber(na, val);
1322 numaDestroy(&na);
1323 return 0;
1324 }
1325
1326
1327 /*----------------------------------------------------------------------*
1328 * Serialize numaa for I/O *
1329 *----------------------------------------------------------------------*/
1330 /*!
1331 * numaaRead()
1332 *
1333 * Input: filename
1334 * Return: naa, or null on error
1335 */
1336 NUMAA *
numaaRead(const char * filename)1337 numaaRead(const char *filename)
1338 {
1339 FILE *fp;
1340 NUMAA *naa;
1341
1342 PROCNAME("numaaRead");
1343
1344 if (!filename)
1345 return (NUMAA *)ERROR_PTR("filename not defined", procName, NULL);
1346
1347 if ((fp = fopenReadStream(filename)) == NULL)
1348 return (NUMAA *)ERROR_PTR("stream not opened", procName, NULL);
1349
1350 if ((naa = numaaReadStream(fp)) == NULL) {
1351 fclose(fp);
1352 return (NUMAA *)ERROR_PTR("naa not read", procName, NULL);
1353 }
1354
1355 fclose(fp);
1356 return naa;
1357 }
1358
1359
1360 /*!
1361 * numaaReadStream()
1362 *
1363 * Input: stream
1364 * Return: naa, or null on error
1365 */
1366 NUMAA *
numaaReadStream(FILE * fp)1367 numaaReadStream(FILE *fp)
1368 {
1369 l_int32 i, n, index, ret, version;
1370 NUMA *na;
1371 NUMAA *naa;
1372
1373 PROCNAME("numaaReadStream");
1374
1375 if (!fp)
1376 return (NUMAA *)ERROR_PTR("stream not defined", procName, NULL);
1377
1378 ret = fscanf(fp, "\nNumaa Version %d\n", &version);
1379 if (ret != 1)
1380 return (NUMAA *)ERROR_PTR("not a numa file", procName, NULL);
1381 if (version != NUMA_VERSION_NUMBER)
1382 return (NUMAA *)ERROR_PTR("invalid numaa version", procName, NULL);
1383 fscanf(fp, "Number of numa = %d\n\n", &n);
1384 if ((naa = numaaCreate(n)) == NULL)
1385 return (NUMAA *)ERROR_PTR("naa not made", procName, NULL);
1386
1387 for (i = 0; i < n; i++) {
1388 fscanf(fp, "Numa[%d]:", &index);
1389 if ((na = numaReadStream(fp)) == NULL)
1390 return (NUMAA *)ERROR_PTR("na not made", procName, NULL);
1391 numaaAddNuma(naa, na, L_INSERT);
1392 }
1393
1394 return naa;
1395 }
1396
1397
1398 /*!
1399 * numaaWrite()
1400 *
1401 * Input: filename, naa
1402 * Return: 0 if OK, 1 on error
1403 */
1404 l_int32
numaaWrite(const char * filename,NUMAA * naa)1405 numaaWrite(const char *filename,
1406 NUMAA *naa)
1407 {
1408 FILE *fp;
1409
1410 PROCNAME("numaaWrite");
1411
1412 if (!filename)
1413 return ERROR_INT("filename not defined", procName, 1);
1414 if (!naa)
1415 return ERROR_INT("naa not defined", procName, 1);
1416
1417 if ((fp = fopen(filename, "w")) == NULL)
1418 return ERROR_INT("stream not opened", procName, 1);
1419 if (numaaWriteStream(fp, naa))
1420 return ERROR_INT("naa not written to stream", procName, 1);
1421 fclose(fp);
1422
1423 return 0;
1424 }
1425
1426
1427 /*!
1428 * numaaWriteStream()
1429 *
1430 * Input: stream, naa
1431 * Return: 0 if OK, 1 on error
1432 */
1433 l_int32
numaaWriteStream(FILE * fp,NUMAA * naa)1434 numaaWriteStream(FILE *fp,
1435 NUMAA *naa)
1436 {
1437 l_int32 i, n;
1438 NUMA *na;
1439
1440 PROCNAME("numaaWriteStream");
1441
1442 if (!fp)
1443 return ERROR_INT("stream not defined", procName, 1);
1444 if (!naa)
1445 return ERROR_INT("naa not defined", procName, 1);
1446
1447 n = numaaGetCount(naa);
1448 fprintf(fp, "\nNumaa Version %d\n", NUMA_VERSION_NUMBER);
1449 fprintf(fp, "Number of numa = %d\n\n", n);
1450 for (i = 0; i < n; i++) {
1451 if ((na = numaaGetNuma(naa, i, L_CLONE)) == NULL)
1452 return ERROR_INT("na not found", procName, 1);
1453 fprintf(fp, "Numa[%d]:", i);
1454 numaWriteStream(fp, na);
1455 numaDestroy(&na);
1456 }
1457
1458 return 0;
1459 }
1460
1461
1462 /*--------------------------------------------------------------------------*
1463 * Numa2d creation, destruction *
1464 *--------------------------------------------------------------------------*/
1465 /*!
1466 * numa2dCreate()
1467 *
1468 * Input: nrows (of 2d array)
1469 * ncols (of 2d array)
1470 * initsize (initial size of each allocated numa)
1471 * Return: numa2d, or null on error
1472 *
1473 * Notes:
1474 * (1) The numa2d holds a doubly-indexed array of numa.
1475 * (2) The numa ptr array is initialized with all ptrs set to NULL.
1476 * (3) The numas are created only when a number is to be stored
1477 * at an index (i,j) for which a numa has not yet been made.
1478 */
1479 NUMA2D *
numa2dCreate(l_int32 nrows,l_int32 ncols,l_int32 initsize)1480 numa2dCreate(l_int32 nrows,
1481 l_int32 ncols,
1482 l_int32 initsize)
1483 {
1484 l_int32 i;
1485 NUMA2D *na2d;
1486
1487 PROCNAME("numa2dCreate");
1488
1489 if (nrows <= 1 || ncols <= 1)
1490 return (NUMA2D *)ERROR_PTR("rows, cols not both >= 1", procName, NULL);
1491
1492 if ((na2d = (NUMA2D *)CALLOC(1, sizeof(NUMA2D))) == NULL)
1493 return (NUMA2D *)ERROR_PTR("na2d not made", procName, NULL);
1494 na2d->nrows = nrows;
1495 na2d->ncols = ncols;
1496 na2d->initsize = initsize;
1497
1498 /* Set up the 2D array */
1499 if ((na2d->numa = (NUMA ***)CALLOC(nrows, sizeof(NUMA **))) == NULL)
1500 return (NUMA2D *)ERROR_PTR("numa row array not made", procName, NULL);
1501 for (i = 0; i < nrows; i++) {
1502 if ((na2d->numa[i] = (NUMA **)CALLOC(ncols, sizeof(NUMA *))) == NULL)
1503 return (NUMA2D *)ERROR_PTR("numa cols not made", procName, NULL);
1504 }
1505
1506 return na2d;
1507 }
1508
1509
1510 /*!
1511 * numa2dDestroy()
1512 *
1513 * Input: &numa2d (<to be nulled if it exists>)
1514 * Return: void
1515 */
1516 void
numa2dDestroy(NUMA2D ** pna2d)1517 numa2dDestroy(NUMA2D **pna2d)
1518 {
1519 l_int32 i, j;
1520 NUMA2D *na2d;
1521
1522 PROCNAME("numa2dDestroy");
1523
1524 if (pna2d == NULL) {
1525 L_WARNING("ptr address is NULL!", procName);
1526 return;
1527 }
1528
1529 if ((na2d = *pna2d) == NULL)
1530 return;
1531
1532 for (i = 0; i < na2d->nrows; i++) {
1533 for (j = 0; j < na2d->ncols; j++)
1534 numaDestroy(&na2d->numa[i][j]);
1535 FREE(na2d->numa[i]);
1536 }
1537 FREE(na2d->numa);
1538 FREE(na2d);
1539 *pna2d = NULL;
1540
1541 return;
1542 }
1543
1544
1545
1546 /*--------------------------------------------------------------------------*
1547 * Numa2d accessors *
1548 *--------------------------------------------------------------------------*/
1549 /*!
1550 * numa2dAddNumber()
1551 *
1552 * Input: na2d
1553 * row of 2d array
1554 * col of 2d array
1555 * val (float or int to be added; stored as a float)
1556 * Return: 0 if OK, 1 on error
1557 */
1558 l_int32
numa2dAddNumber(NUMA2D * na2d,l_int32 row,l_int32 col,l_float32 val)1559 numa2dAddNumber(NUMA2D *na2d,
1560 l_int32 row,
1561 l_int32 col,
1562 l_float32 val)
1563 {
1564 NUMA *na;
1565
1566 PROCNAME("numa2dAddNumber");
1567
1568 if (!na2d)
1569 return ERROR_INT("na2d not defined", procName, 1);
1570 if (row < 0 || row >= na2d->nrows)
1571 return ERROR_INT("row out of bounds", procName, 1);
1572 if (col < 0 || col >= na2d->ncols)
1573 return ERROR_INT("col out of bounds", procName, 1);
1574
1575 if ((na = na2d->numa[row][col]) == NULL) {
1576 na = numaCreate(na2d->initsize);
1577 na2d->numa[row][col] = na;
1578 }
1579 numaAddNumber(na, val);
1580 return 0;
1581 }
1582
1583
1584 /*!
1585 * numa2dGetCount()
1586 *
1587 * Input: na2d
1588 * row of 2d array
1589 * col of 2d array
1590 * Return: size of numa at [row][col], or 0 if the numa doesn't exist
1591 * or on error
1592 */
1593 l_int32
numa2dGetCount(NUMA2D * na2d,l_int32 row,l_int32 col)1594 numa2dGetCount(NUMA2D *na2d,
1595 l_int32 row,
1596 l_int32 col)
1597 {
1598 NUMA *na;
1599
1600 PROCNAME("numa2dGetCount");
1601
1602 if (!na2d)
1603 return ERROR_INT("na2d not defined", procName, 0);
1604 if (row < 0 || row >= na2d->nrows)
1605 return ERROR_INT("row out of bounds", procName, 0);
1606 if (col < 0 || col >= na2d->ncols)
1607 return ERROR_INT("col out of bounds", procName, 0);
1608 if ((na = na2d->numa[row][col]) == NULL)
1609 return 0;
1610 else
1611 return na->n;
1612 }
1613
1614
1615 /*!
1616 * numa2dGetNuma()
1617 *
1618 * Input: na2d
1619 * row of 2d array
1620 * col of 2d array
1621 * Return: na (a clone of the numa if it exists) or null if it doesn't
1622 *
1623 * Notes:
1624 * (1) This does not give an error if the index is out of bounds.
1625 */
1626 NUMA *
numa2dGetNuma(NUMA2D * na2d,l_int32 row,l_int32 col)1627 numa2dGetNuma(NUMA2D *na2d,
1628 l_int32 row,
1629 l_int32 col)
1630 {
1631 NUMA *na;
1632
1633 PROCNAME("numa2dGetNuma");
1634
1635 if (!na2d)
1636 return (NUMA *)ERROR_PTR("na2d not defined", procName, NULL);
1637 if (row < 0 || row >= na2d->nrows || col < 0 || col >= na2d->ncols)
1638 return NULL;
1639 if ((na = na2d->numa[row][col]) == NULL)
1640 return NULL;
1641 return numaClone(na);
1642 }
1643
1644
1645 /*!
1646 * numa2dGetFValue()
1647 *
1648 * Input: na2d
1649 * row of 2d array
1650 * col of 2d array
1651 * index (into numa)
1652 * &val (<return> float value)
1653 * Return: 0 if OK, 1 on error
1654 */
1655 l_int32
numa2dGetFValue(NUMA2D * na2d,l_int32 row,l_int32 col,l_int32 index,l_float32 * pval)1656 numa2dGetFValue(NUMA2D *na2d,
1657 l_int32 row,
1658 l_int32 col,
1659 l_int32 index,
1660 l_float32 *pval)
1661 {
1662 NUMA *na;
1663
1664 PROCNAME("numa2dGetFValue");
1665
1666 if (!na2d)
1667 return ERROR_INT("na2d not defined", procName, 1);
1668 if (!pval)
1669 return ERROR_INT("&val not defined", procName, 1);
1670 *pval = 0.0;
1671
1672 if (row < 0 || row >= na2d->nrows)
1673 return ERROR_INT("row out of bounds", procName, 1);
1674 if (col < 0 || col >= na2d->ncols)
1675 return ERROR_INT("col out of bounds", procName, 1);
1676 if ((na = na2d->numa[row][col]) == NULL)
1677 return ERROR_INT("numa does not exist", procName, 1);
1678
1679 return numaGetFValue(na, index, pval);
1680 }
1681
1682
1683 /*!
1684 * numa2dGetIValue()
1685 *
1686 * Input: na2d
1687 * row of 2d array
1688 * col of 2d array
1689 * index (into numa)
1690 * &val (<return> integer value)
1691 * Return: 0 if OK, 1 on error
1692 */
1693 l_int32
numa2dGetIValue(NUMA2D * na2d,l_int32 row,l_int32 col,l_int32 index,l_int32 * pval)1694 numa2dGetIValue(NUMA2D *na2d,
1695 l_int32 row,
1696 l_int32 col,
1697 l_int32 index,
1698 l_int32 *pval)
1699 {
1700 NUMA *na;
1701
1702 PROCNAME("numa2dGetIValue");
1703
1704 if (!na2d)
1705 return ERROR_INT("na2d not defined", procName, 1);
1706 if (!pval)
1707 return ERROR_INT("&val not defined", procName, 1);
1708 *pval = 0;
1709
1710 if (row < 0 || row >= na2d->nrows)
1711 return ERROR_INT("row out of bounds", procName, 1);
1712 if (col < 0 || col >= na2d->ncols)
1713 return ERROR_INT("col out of bounds", procName, 1);
1714 if ((na = na2d->numa[row][col]) == NULL)
1715 return ERROR_INT("numa does not exist", procName, 1);
1716
1717 return numaGetIValue(na, index, pval);
1718 }
1719
1720
1721 /*--------------------------------------------------------------------------*
1722 * Number array hash: Creation and destruction *
1723 *--------------------------------------------------------------------------*/
1724 /*!
1725 * numaHashCreate()
1726 *
1727 * Input: nbuckets (the number of buckets in the hash table,
1728 * which should be prime.)
1729 * initsize (initial size of each allocated numa; 0 for default)
1730 * Return: ptr to new nahash, or null on error
1731 *
1732 * Note: actual numa are created only as required by numaHashAdd()
1733 */
1734 NUMAHASH *
numaHashCreate(l_int32 nbuckets,l_int32 initsize)1735 numaHashCreate(l_int32 nbuckets,
1736 l_int32 initsize)
1737 {
1738 NUMAHASH *nahash;
1739
1740 PROCNAME("numaHashCreate");
1741
1742 if (nbuckets <= 0)
1743 return (NUMAHASH *)ERROR_PTR("negative hash size", procName, NULL);
1744 if ((nahash = (NUMAHASH *)CALLOC(1, sizeof(NUMAHASH))) == NULL)
1745 return (NUMAHASH *)ERROR_PTR("nahash not made", procName, NULL);
1746 if ((nahash->numa = (NUMA **)CALLOC(nbuckets, sizeof(NUMA *))) == NULL) {
1747 FREE(nahash);
1748 return (NUMAHASH *)ERROR_PTR("numa ptr array not made", procName, NULL);
1749 }
1750
1751 nahash->nbuckets = nbuckets;
1752 nahash->initsize = initsize;
1753 return nahash;
1754 }
1755
1756
1757 /*!
1758 * numaHashDestroy()
1759 *
1760 * Input: &nahash (<to be nulled, if it exists>)
1761 * Return: void
1762 */
1763 void
numaHashDestroy(NUMAHASH ** pnahash)1764 numaHashDestroy(NUMAHASH **pnahash)
1765 {
1766 NUMAHASH *nahash;
1767 l_int32 i;
1768
1769 PROCNAME("numaHashDestroy");
1770
1771 if (pnahash == NULL) {
1772 L_WARNING("ptr address is NULL!", procName);
1773 return;
1774 }
1775
1776 if ((nahash = *pnahash) == NULL)
1777 return;
1778
1779 for (i = 0; i < nahash->nbuckets; i++)
1780 numaDestroy(&nahash->numa[i]);
1781 FREE(nahash->numa);
1782 FREE(nahash);
1783 *pnahash = NULL;
1784 }
1785
1786
1787 /*--------------------------------------------------------------------------*
1788 * Number array hash: Add elements and return numas
1789 *--------------------------------------------------------------------------*/
1790 /*!
1791 * numaHashGetNuma()
1792 *
1793 * Input: nahash
1794 * key (key to be hashed into a bucket number)
1795 * Return: ptr to numa
1796 */
1797 NUMA *
numaHashGetNuma(NUMAHASH * nahash,l_uint32 key)1798 numaHashGetNuma(NUMAHASH *nahash,
1799 l_uint32 key)
1800 {
1801 l_int32 bucket;
1802 NUMA *na;
1803
1804 PROCNAME("numaHashGetNuma");
1805
1806 if (!nahash)
1807 return (NUMA *)ERROR_PTR("nahash not defined", procName, NULL);
1808 bucket = key % nahash->nbuckets;
1809 na = nahash->numa[bucket];
1810 if (na)
1811 return numaClone(na);
1812 else
1813 return NULL;
1814 }
1815
1816 /*!
1817 * numaHashAdd()
1818 *
1819 * Input: nahash
1820 * key (key to be hashed into a bucket number)
1821 * value (float value to be appended to the specific numa)
1822 * Return: 0 if OK; 1 on error
1823 */
1824 l_int32
numaHashAdd(NUMAHASH * nahash,l_uint32 key,l_float32 value)1825 numaHashAdd(NUMAHASH *nahash,
1826 l_uint32 key,
1827 l_float32 value)
1828 {
1829 l_int32 bucket;
1830 NUMA *na;
1831
1832 PROCNAME("numaHashAdd");
1833
1834 if (!nahash)
1835 return ERROR_INT("nahash not defined", procName, 1);
1836 if (key < 0)
1837 return ERROR_INT("key < 0", procName, 1);
1838 bucket = key % nahash->nbuckets;
1839 na = nahash->numa[bucket];
1840 if (!na) {
1841 if ((na = numaCreate(nahash->initsize)) == NULL)
1842 return ERROR_INT("na not made", procName, 1);
1843 nahash->numa[bucket] = na;
1844 }
1845 numaAddNumber(na, value);
1846 return 0;
1847 }
1848
1849
1850