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 * field to a larger number (such as the alloc size)
727 * BEFORE calling this function. Creating with numaMakeConstant()
728 * is another way to insure full initialization.
729 */
730 l_float32 *
numaGetFArray(NUMA * na,l_int32 copyflag)731 numaGetFArray(NUMA *na,
732 l_int32 copyflag)
733 {
734 l_int32 i, n;
735 l_float32 *array;
736
737 PROCNAME("numaGetFArray");
738
739 if (!na)
740 return (l_float32 *)ERROR_PTR("na not defined", procName, NULL);
741
742 if (copyflag == L_NOCOPY)
743 array = na->array;
744 else { /* copyflag == L_COPY */
745 n = numaGetCount(na);
746 if ((array = (l_float32 *)CALLOC(n, sizeof(l_float32))) == NULL)
747 return (l_float32 *)ERROR_PTR("array not made", procName, NULL);
748 for (i = 0; i < n; i++)
749 array[i] = na->array[i];
750 }
751
752 return array;
753 }
754
755
756 /*!
757 * numaGetRefCount()
758 *
759 * Input: na
760 * Return: refcount, or UNDEF on error
761 */
762 l_int32
numaGetRefcount(NUMA * na)763 numaGetRefcount(NUMA *na)
764 {
765 PROCNAME("numaGetRefcount");
766
767 if (!na)
768 return ERROR_INT("na not defined", procName, UNDEF);
769 return na->refcount;
770 }
771
772
773 /*!
774 * numaChangeRefCount()
775 *
776 * Input: na
777 * delta (change to be applied)
778 * Return: 0 if OK, 1 on error
779 */
780 l_int32
numaChangeRefcount(NUMA * na,l_int32 delta)781 numaChangeRefcount(NUMA *na,
782 l_int32 delta)
783 {
784 PROCNAME("numaChangeRefcount");
785
786 if (!na)
787 return ERROR_INT("na not defined", procName, 1);
788 na->refcount += delta;
789 return 0;
790 }
791
792
793 /*!
794 * numaGetXParameters()
795 *
796 * Input: na
797 * &startx (<optional return> startx)
798 * &delx (<optional return> delx)
799 * Return: 0 if OK, 1 on error
800 */
801 l_int32
numaGetXParameters(NUMA * na,l_float32 * pstartx,l_float32 * pdelx)802 numaGetXParameters(NUMA *na,
803 l_float32 *pstartx,
804 l_float32 *pdelx)
805 {
806 PROCNAME("numaGetXParameters");
807
808 if (!na)
809 return ERROR_INT("na not defined", procName, 1);
810
811 if (pstartx) *pstartx = na->startx;
812 if (pdelx) *pdelx = na->delx;
813 return 0;
814 }
815
816
817 /*!
818 * numaSetXParameters()
819 *
820 * Input: na
821 * startx (x value corresponding to na[0])
822 * delx (difference in x values for the situation where the
823 * elements of na correspond to the evaulation of a
824 * function at equal intervals of size @delx)
825 * Return: 0 if OK, 1 on error
826 */
827 l_int32
numaSetXParameters(NUMA * na,l_float32 startx,l_float32 delx)828 numaSetXParameters(NUMA *na,
829 l_float32 startx,
830 l_float32 delx)
831 {
832 PROCNAME("numaSetXParameters");
833
834 if (!na)
835 return ERROR_INT("na not defined", procName, 1);
836
837 na->startx = startx;
838 na->delx = delx;
839 return 0;
840 }
841
842
843 /*!
844 * numaCopyXParameters()
845 *
846 * Input: nad (destination Numa)
847 * nas (source Numa)
848 * Return: 0 if OK, 1 on error
849 */
850 l_int32
numaCopyXParameters(NUMA * nad,NUMA * nas)851 numaCopyXParameters(NUMA *nad,
852 NUMA *nas)
853 {
854 l_float32 start, binsize;
855
856 PROCNAME("numaCopyXParameters");
857
858 if (!nas || !nad)
859 return ERROR_INT("nas and nad not both defined", procName, 1);
860
861 numaGetXParameters(nas, &start, &binsize);
862 numaSetXParameters(nad, start, binsize);
863 return 0;
864 }
865
866
867 /*----------------------------------------------------------------------*
868 * Serialize numa for I/O *
869 *----------------------------------------------------------------------*/
870 /*!
871 * numaRead()
872 *
873 * Input: filename
874 * Return: na, or null on error
875 */
876 NUMA *
numaRead(const char * filename)877 numaRead(const char *filename)
878 {
879 FILE *fp;
880 NUMA *na;
881
882 PROCNAME("numaRead");
883
884 if (!filename)
885 return (NUMA *)ERROR_PTR("filename not defined", procName, NULL);
886
887 if ((fp = fopenReadStream(filename)) == NULL)
888 return (NUMA *)ERROR_PTR("stream not opened", procName, NULL);
889
890 if ((na = numaReadStream(fp)) == NULL) {
891 fclose(fp);
892 return (NUMA *)ERROR_PTR("na not read", procName, NULL);
893 }
894
895 fclose(fp);
896 return na;
897 }
898
899
900 /*!
901 * numaReadStream()
902 *
903 * Input: stream
904 * Return: numa, or null on error
905 */
906 NUMA *
numaReadStream(FILE * fp)907 numaReadStream(FILE *fp)
908 {
909 l_int32 i, n, index, ret, version;
910 l_float32 val, startx, delx;
911 NUMA *na;
912
913 PROCNAME("numaReadStream");
914
915 if (!fp)
916 return (NUMA *)ERROR_PTR("stream not defined", procName, NULL);
917
918 ret = fscanf(fp, "\nNuma Version %d\n", &version);
919 if (ret != 1)
920 return (NUMA *)ERROR_PTR("not a numa file", procName, NULL);
921 if (version != NUMA_VERSION_NUMBER)
922 return (NUMA *)ERROR_PTR("invalid numa version", procName, NULL);
923 fscanf(fp, "Number of numbers = %d\n", &n);
924
925 if ((na = numaCreate(n)) == NULL)
926 return (NUMA *)ERROR_PTR("na not made", procName, NULL);
927
928 for (i = 0; i < n; i++) {
929 if ((fscanf(fp, " [%d] = %f\n", &index, &val)) != 2)
930 return (NUMA *)ERROR_PTR("bad input data", procName, NULL);
931 numaAddNumber(na, val);
932 }
933
934 /* Optional data */
935 if ((fscanf(fp, "startx = %f, delx = %f\n", &startx, &delx)) == 2)
936 numaSetXParameters(na, startx, delx);
937
938 return na;
939 }
940
941
942 /*!
943 * numaWrite()
944 *
945 * Input: filename, na
946 * Return: 0 if OK, 1 on error
947 */
948 l_int32
numaWrite(const char * filename,NUMA * na)949 numaWrite(const char *filename,
950 NUMA *na)
951 {
952 FILE *fp;
953
954 PROCNAME("numaWrite");
955
956 if (!filename)
957 return ERROR_INT("filename not defined", procName, 1);
958 if (!na)
959 return ERROR_INT("na not defined", procName, 1);
960
961 if ((fp = fopen(filename, "w")) == NULL)
962 return ERROR_INT("stream not opened", procName, 1);
963 if (numaWriteStream(fp, na))
964 return ERROR_INT("na not written to stream", procName, 1);
965 fclose(fp);
966
967 return 0;
968 }
969
970
971 /*!
972 * numaWriteStream()
973 *
974 * Input: stream, na
975 * Return: 0 if OK, 1 on error
976 */
977 l_int32
numaWriteStream(FILE * fp,NUMA * na)978 numaWriteStream(FILE *fp,
979 NUMA *na)
980 {
981 l_int32 i, n;
982 l_float32 startx, delx;
983
984 PROCNAME("numaWriteStream");
985
986 if (!fp)
987 return ERROR_INT("stream not defined", procName, 1);
988 if (!na)
989 return ERROR_INT("na not defined", procName, 1);
990
991 n = numaGetCount(na);
992 fprintf(fp, "\nNuma Version %d\n", NUMA_VERSION_NUMBER);
993 fprintf(fp, "Number of numbers = %d\n", n);
994 for (i = 0; i < n; i++)
995 fprintf(fp, " [%d] = %f\n", i, na->array[i]);
996 fprintf(fp, "\n");
997
998 /* Optional data */
999 numaGetXParameters(na, &startx, &delx);
1000 if (startx != 0.0 || delx != 1.0)
1001 fprintf(fp, "startx = %f, delx = %f\n", startx, delx);
1002
1003 return 0;
1004 }
1005
1006
1007
1008 /*--------------------------------------------------------------------------*
1009 * Numaa creation, destruction *
1010 *--------------------------------------------------------------------------*/
1011 /*!
1012 * numaaCreate()
1013 *
1014 * Input: size of numa ptr array to be alloc'd (0 for default)
1015 * Return: naa, or null on error
1016 *
1017 */
1018 NUMAA *
numaaCreate(l_int32 n)1019 numaaCreate(l_int32 n)
1020 {
1021 NUMAA *naa;
1022
1023 PROCNAME("numaaCreate");
1024
1025 if (n <= 0)
1026 n = INITIAL_PTR_ARRAYSIZE;
1027
1028 if ((naa = (NUMAA *)CALLOC(1, sizeof(NUMAA))) == NULL)
1029 return (NUMAA *)ERROR_PTR("naa not made", procName, NULL);
1030 if ((naa->numa = (NUMA **)CALLOC(n, sizeof(NUMA *))) == NULL)
1031 return (NUMAA *)ERROR_PTR("numa ptr array not made", procName, NULL);
1032
1033 naa->nalloc = n;
1034 naa->n = 0;
1035
1036 return naa;
1037 }
1038
1039
1040 /*!
1041 * numaaDestroy()
1042 *
1043 * Input: &numaa <to be nulled if it exists>
1044 * Return: void
1045 */
1046 void
numaaDestroy(NUMAA ** pnaa)1047 numaaDestroy(NUMAA **pnaa)
1048 {
1049 l_int32 i;
1050 NUMAA *naa;
1051
1052 PROCNAME("numaaDestroy");
1053
1054 if (pnaa == NULL) {
1055 L_WARNING("ptr address is NULL!", procName);
1056 return;
1057 }
1058
1059 if ((naa = *pnaa) == NULL)
1060 return;
1061
1062 for (i = 0; i < naa->n; i++)
1063 numaDestroy(&naa->numa[i]);
1064 FREE(naa->numa);
1065 FREE(naa);
1066 *pnaa = NULL;
1067
1068 return;
1069 }
1070
1071
1072
1073 /*--------------------------------------------------------------------------*
1074 * Add Numa to Numaa *
1075 *--------------------------------------------------------------------------*/
1076 /*!
1077 * numaaAddNuma()
1078 *
1079 * Input: naa
1080 * na (to be added)
1081 * copyflag (L_INSERT, L_COPY, L_CLONE)
1082 * Return: 0 if OK, 1 on error
1083 */
1084 l_int32
numaaAddNuma(NUMAA * naa,NUMA * na,l_int32 copyflag)1085 numaaAddNuma(NUMAA *naa,
1086 NUMA *na,
1087 l_int32 copyflag)
1088 {
1089 l_int32 n;
1090 NUMA *nac;
1091
1092 PROCNAME("numaaAddNuma");
1093
1094 if (!naa)
1095 return ERROR_INT("naa not defined", procName, 1);
1096 if (!na)
1097 return ERROR_INT("na not defined", procName, 1);
1098
1099 if (copyflag == L_INSERT)
1100 nac = na;
1101 else if (copyflag == L_COPY) {
1102 if ((nac = numaCopy(na)) == NULL)
1103 return ERROR_INT("nac not made", procName, 1);
1104 }
1105 else if (copyflag == L_CLONE)
1106 nac = numaClone(na);
1107 else
1108 return ERROR_INT("invalid copyflag", procName, 1);
1109
1110 n = numaaGetCount(naa);
1111 if (n >= naa->nalloc)
1112 numaaExtendArray(naa);
1113 naa->numa[n] = nac;
1114 naa->n++;
1115 return 0;
1116 }
1117
1118
1119 /*!
1120 * numaaExtendArray()
1121 *
1122 * Input: naa
1123 * Return: 0 if OK, 1 on error
1124 */
1125 l_int32
numaaExtendArray(NUMAA * naa)1126 numaaExtendArray(NUMAA *naa)
1127 {
1128 PROCNAME("numaaExtendArray");
1129
1130 if (!naa)
1131 return ERROR_INT("naa not defined", procName, 1);
1132
1133 if ((naa->numa = (NUMA **)reallocNew((void **)&naa->numa,
1134 sizeof(NUMA *) * naa->nalloc,
1135 2 * sizeof(NUMA *) * naa->nalloc)) == NULL)
1136 return ERROR_INT("new ptr array not returned", procName, 1);
1137
1138 naa->nalloc *= 2;
1139 return 0;
1140 }
1141
1142
1143 /*----------------------------------------------------------------------*
1144 * Numaa accessors *
1145 *----------------------------------------------------------------------*/
1146 /*!
1147 * numaaGetCount()
1148 *
1149 * Input: naa
1150 * Return: count (number of numa), or 0 if no numa or on error
1151 */
1152 l_int32
numaaGetCount(NUMAA * naa)1153 numaaGetCount(NUMAA *naa)
1154 {
1155 PROCNAME("numaaGetCount");
1156
1157 if (!naa)
1158 return ERROR_INT("naa not defined", procName, 0);
1159 return naa->n;
1160 }
1161
1162
1163 /*!
1164 * numaaGetNumberCount()
1165 *
1166 * Input: naa
1167 * Return: count (number of numbers), or 0 if no numbers or on error
1168 */
1169 l_int32
numaaGetNumberCount(NUMAA * naa)1170 numaaGetNumberCount(NUMAA *naa)
1171 {
1172 NUMA *na;
1173 l_int32 n, sum, i;
1174
1175 PROCNAME("numaaGetNumberCount");
1176
1177 if (!naa)
1178 return ERROR_INT("naa not defined", procName, 0);
1179
1180 n = numaaGetCount(naa);
1181 for (sum = 0, i = 0; i < n; i++) {
1182 na = numaaGetNuma(naa, i, L_CLONE);
1183 sum += numaGetCount(na);
1184 numaDestroy(&na);
1185 }
1186
1187 return sum;
1188 }
1189
1190
1191 /*!
1192 * numaaGetPtrArray()
1193 *
1194 * Input: naa
1195 * Return: the internal array of ptrs to Numa, or null on error
1196 *
1197 * Notes:
1198 * (1) This function is convenient for doing direct manipulation on
1199 * a fixed size array of Numas. To do this, it sets the count
1200 * to the full size of the allocated array of Numa ptrs.
1201 * The originating Numaa owns this array: DO NOT free it!
1202 * (2) Intended usage:
1203 * Numaa *naa = numaaCreate(n);
1204 * Numa **array = numaaGetPtrArray(naa);
1205 * ... [manipulate Numas directly on the array]
1206 * numaaDestroy(&naa);
1207 * (3) Cautions:
1208 * - Do not free this array; it is owned by tne Numaa.
1209 * - Do not call any functions on the Numaa, other than
1210 * numaaDestroy() when you're finished with the array.
1211 * Adding a Numa will force a resize, destroying the ptr array.
1212 * - Do not address the array outside its allocated size.
1213 * With the bare array, there are no protections. If the
1214 * allocated size is n, array[n] is an error.
1215 */
1216 NUMA **
numaaGetPtrArray(NUMAA * naa)1217 numaaGetPtrArray(NUMAA *naa)
1218 {
1219 PROCNAME("numaaGetPtrArray");
1220
1221 if (!naa)
1222 return (NUMA **)ERROR_PTR("naa not defined", procName, NULL);
1223
1224 naa->n = naa->nalloc;
1225 return naa->numa;
1226 }
1227
1228
1229 /*!
1230 * numaaGetNuma()
1231 *
1232 * Input: naa
1233 * index (to the index-th numa)
1234 * accessflag (L_COPY or L_CLONE)
1235 * Return: numa, or null on error
1236 */
1237 NUMA *
numaaGetNuma(NUMAA * naa,l_int32 index,l_int32 accessflag)1238 numaaGetNuma(NUMAA *naa,
1239 l_int32 index,
1240 l_int32 accessflag)
1241 {
1242 PROCNAME("numaaGetNuma");
1243
1244 if (!naa)
1245 return (NUMA *)ERROR_PTR("naa not defined", procName, NULL);
1246 if (index < 0 || index >= naa->n)
1247 return (NUMA *)ERROR_PTR("index not valid", procName, NULL);
1248
1249 if (accessflag == L_COPY)
1250 return numaCopy(naa->numa[index]);
1251 else if (accessflag == L_CLONE)
1252 return numaClone(naa->numa[index]);
1253 else
1254 return (NUMA *)ERROR_PTR("invalid accessflag", procName, NULL);
1255 }
1256
1257
1258 /*!
1259 * numaaReplaceNuma()
1260 *
1261 * Input: naa
1262 * index (to the index-th numa)
1263 * numa (insert and replace any existing one)
1264 * Return: 0 if OK, 1 on error
1265 *
1266 * Notes:
1267 * (1) Any existing numa is destroyed, and the input one
1268 * is inserted in its place.
1269 * (2) If the index is invalid, return 1 (error)
1270 */
1271 l_int32
numaaReplaceNuma(NUMAA * naa,l_int32 index,NUMA * na)1272 numaaReplaceNuma(NUMAA *naa,
1273 l_int32 index,
1274 NUMA *na)
1275 {
1276 l_int32 n;
1277
1278 PROCNAME("numaaReplaceNuma");
1279
1280 if (!naa)
1281 return ERROR_INT("naa not defined", procName, 1);
1282 if (!na)
1283 return ERROR_INT("na not defined", procName, 1);
1284 n = numaaGetCount(naa);
1285 if (index < 0 || index >= n)
1286 return ERROR_INT("index not valid", procName, 1);
1287
1288 numaDestroy(&naa->numa[index]);
1289 naa->numa[index] = na;
1290 return 0;
1291 }
1292
1293
1294 /*!
1295 * numaaAddNumber()
1296 *
1297 * Input: naa
1298 * index (of numa within numaa)
1299 * val (float or int to be added; stored as a float)
1300 * Return: 0 if OK, 1 on error
1301 *
1302 * Notes:
1303 * (1) Adds to an existing numa only.
1304 */
1305 l_int32
numaaAddNumber(NUMAA * naa,l_int32 index,l_float32 val)1306 numaaAddNumber(NUMAA *naa,
1307 l_int32 index,
1308 l_float32 val)
1309 {
1310 l_int32 n;
1311 NUMA *na;
1312
1313 PROCNAME("numaaAddNumber");
1314
1315 if (!naa)
1316 return ERROR_INT("naa not defined", procName, 1);
1317 n = numaaGetCount(naa);
1318 if (index < 0 || index >= n)
1319 return ERROR_INT("invalid index in naa", procName, 1);
1320
1321 na = numaaGetNuma(naa, index, L_CLONE);
1322 numaAddNumber(na, val);
1323 numaDestroy(&na);
1324 return 0;
1325 }
1326
1327
1328 /*----------------------------------------------------------------------*
1329 * Serialize numaa for I/O *
1330 *----------------------------------------------------------------------*/
1331 /*!
1332 * numaaRead()
1333 *
1334 * Input: filename
1335 * Return: naa, or null on error
1336 */
1337 NUMAA *
numaaRead(const char * filename)1338 numaaRead(const char *filename)
1339 {
1340 FILE *fp;
1341 NUMAA *naa;
1342
1343 PROCNAME("numaaRead");
1344
1345 if (!filename)
1346 return (NUMAA *)ERROR_PTR("filename not defined", procName, NULL);
1347
1348 if ((fp = fopenReadStream(filename)) == NULL)
1349 return (NUMAA *)ERROR_PTR("stream not opened", procName, NULL);
1350
1351 if ((naa = numaaReadStream(fp)) == NULL) {
1352 fclose(fp);
1353 return (NUMAA *)ERROR_PTR("naa not read", procName, NULL);
1354 }
1355
1356 fclose(fp);
1357 return naa;
1358 }
1359
1360
1361 /*!
1362 * numaaReadStream()
1363 *
1364 * Input: stream
1365 * Return: naa, or null on error
1366 */
1367 NUMAA *
numaaReadStream(FILE * fp)1368 numaaReadStream(FILE *fp)
1369 {
1370 l_int32 i, n, index, ret, version;
1371 NUMA *na;
1372 NUMAA *naa;
1373
1374 PROCNAME("numaaReadStream");
1375
1376 if (!fp)
1377 return (NUMAA *)ERROR_PTR("stream not defined", procName, NULL);
1378
1379 ret = fscanf(fp, "\nNumaa Version %d\n", &version);
1380 if (ret != 1)
1381 return (NUMAA *)ERROR_PTR("not a numa file", procName, NULL);
1382 if (version != NUMA_VERSION_NUMBER)
1383 return (NUMAA *)ERROR_PTR("invalid numaa version", procName, NULL);
1384 fscanf(fp, "Number of numa = %d\n\n", &n);
1385 if ((naa = numaaCreate(n)) == NULL)
1386 return (NUMAA *)ERROR_PTR("naa not made", procName, NULL);
1387
1388 for (i = 0; i < n; i++) {
1389 fscanf(fp, "Numa[%d]:", &index);
1390 if ((na = numaReadStream(fp)) == NULL)
1391 return (NUMAA *)ERROR_PTR("na not made", procName, NULL);
1392 numaaAddNuma(naa, na, L_INSERT);
1393 }
1394
1395 return naa;
1396 }
1397
1398
1399 /*!
1400 * numaaWrite()
1401 *
1402 * Input: filename, naa
1403 * Return: 0 if OK, 1 on error
1404 */
1405 l_int32
numaaWrite(const char * filename,NUMAA * naa)1406 numaaWrite(const char *filename,
1407 NUMAA *naa)
1408 {
1409 FILE *fp;
1410
1411 PROCNAME("numaaWrite");
1412
1413 if (!filename)
1414 return ERROR_INT("filename not defined", procName, 1);
1415 if (!naa)
1416 return ERROR_INT("naa not defined", procName, 1);
1417
1418 if ((fp = fopen(filename, "w")) == NULL)
1419 return ERROR_INT("stream not opened", procName, 1);
1420 if (numaaWriteStream(fp, naa))
1421 return ERROR_INT("naa not written to stream", procName, 1);
1422 fclose(fp);
1423
1424 return 0;
1425 }
1426
1427
1428 /*!
1429 * numaaWriteStream()
1430 *
1431 * Input: stream, naa
1432 * Return: 0 if OK, 1 on error
1433 */
1434 l_int32
numaaWriteStream(FILE * fp,NUMAA * naa)1435 numaaWriteStream(FILE *fp,
1436 NUMAA *naa)
1437 {
1438 l_int32 i, n;
1439 NUMA *na;
1440
1441 PROCNAME("numaaWriteStream");
1442
1443 if (!fp)
1444 return ERROR_INT("stream not defined", procName, 1);
1445 if (!naa)
1446 return ERROR_INT("naa not defined", procName, 1);
1447
1448 n = numaaGetCount(naa);
1449 fprintf(fp, "\nNumaa Version %d\n", NUMA_VERSION_NUMBER);
1450 fprintf(fp, "Number of numa = %d\n\n", n);
1451 for (i = 0; i < n; i++) {
1452 if ((na = numaaGetNuma(naa, i, L_CLONE)) == NULL)
1453 return ERROR_INT("na not found", procName, 1);
1454 fprintf(fp, "Numa[%d]:", i);
1455 numaWriteStream(fp, na);
1456 numaDestroy(&na);
1457 }
1458
1459 return 0;
1460 }
1461
1462
1463 /*--------------------------------------------------------------------------*
1464 * Numa2d creation, destruction *
1465 *--------------------------------------------------------------------------*/
1466 /*!
1467 * numa2dCreate()
1468 *
1469 * Input: nrows (of 2d array)
1470 * ncols (of 2d array)
1471 * initsize (initial size of each allocated numa)
1472 * Return: numa2d, or null on error
1473 *
1474 * Notes:
1475 * (1) The numa2d holds a doubly-indexed array of numa.
1476 * (2) The numa ptr array is initialized with all ptrs set to NULL.
1477 * (3) The numas are created only when a number is to be stored
1478 * at an index (i,j) for which a numa has not yet been made.
1479 */
1480 NUMA2D *
numa2dCreate(l_int32 nrows,l_int32 ncols,l_int32 initsize)1481 numa2dCreate(l_int32 nrows,
1482 l_int32 ncols,
1483 l_int32 initsize)
1484 {
1485 l_int32 i;
1486 NUMA2D *na2d;
1487
1488 PROCNAME("numa2dCreate");
1489
1490 if (nrows <= 1 || ncols <= 1)
1491 return (NUMA2D *)ERROR_PTR("rows, cols not both >= 1", procName, NULL);
1492
1493 if ((na2d = (NUMA2D *)CALLOC(1, sizeof(NUMA2D))) == NULL)
1494 return (NUMA2D *)ERROR_PTR("na2d not made", procName, NULL);
1495 na2d->nrows = nrows;
1496 na2d->ncols = ncols;
1497 na2d->initsize = initsize;
1498
1499 /* Set up the 2D array */
1500 if ((na2d->numa = (NUMA ***)CALLOC(nrows, sizeof(NUMA **))) == NULL)
1501 return (NUMA2D *)ERROR_PTR("numa row array not made", procName, NULL);
1502 for (i = 0; i < nrows; i++) {
1503 if ((na2d->numa[i] = (NUMA **)CALLOC(ncols, sizeof(NUMA *))) == NULL)
1504 return (NUMA2D *)ERROR_PTR("numa cols not made", procName, NULL);
1505 }
1506
1507 return na2d;
1508 }
1509
1510
1511 /*!
1512 * numa2dDestroy()
1513 *
1514 * Input: &numa2d (<to be nulled if it exists>)
1515 * Return: void
1516 */
1517 void
numa2dDestroy(NUMA2D ** pna2d)1518 numa2dDestroy(NUMA2D **pna2d)
1519 {
1520 l_int32 i, j;
1521 NUMA2D *na2d;
1522
1523 PROCNAME("numa2dDestroy");
1524
1525 if (pna2d == NULL) {
1526 L_WARNING("ptr address is NULL!", procName);
1527 return;
1528 }
1529
1530 if ((na2d = *pna2d) == NULL)
1531 return;
1532
1533 for (i = 0; i < na2d->nrows; i++) {
1534 for (j = 0; j < na2d->ncols; j++)
1535 numaDestroy(&na2d->numa[i][j]);
1536 FREE(na2d->numa[i]);
1537 }
1538 FREE(na2d->numa);
1539 FREE(na2d);
1540 *pna2d = NULL;
1541
1542 return;
1543 }
1544
1545
1546
1547 /*--------------------------------------------------------------------------*
1548 * Numa2d accessors *
1549 *--------------------------------------------------------------------------*/
1550 /*!
1551 * numa2dAddNumber()
1552 *
1553 * Input: na2d
1554 * row of 2d array
1555 * col of 2d array
1556 * val (float or int to be added; stored as a float)
1557 * Return: 0 if OK, 1 on error
1558 */
1559 l_int32
numa2dAddNumber(NUMA2D * na2d,l_int32 row,l_int32 col,l_float32 val)1560 numa2dAddNumber(NUMA2D *na2d,
1561 l_int32 row,
1562 l_int32 col,
1563 l_float32 val)
1564 {
1565 NUMA *na;
1566
1567 PROCNAME("numa2dAddNumber");
1568
1569 if (!na2d)
1570 return ERROR_INT("na2d not defined", procName, 1);
1571 if (row < 0 || row >= na2d->nrows)
1572 return ERROR_INT("row out of bounds", procName, 1);
1573 if (col < 0 || col >= na2d->ncols)
1574 return ERROR_INT("col out of bounds", procName, 1);
1575
1576 if ((na = na2d->numa[row][col]) == NULL) {
1577 na = numaCreate(na2d->initsize);
1578 na2d->numa[row][col] = na;
1579 }
1580 numaAddNumber(na, val);
1581 return 0;
1582 }
1583
1584
1585 /*!
1586 * numa2dGetCount()
1587 *
1588 * Input: na2d
1589 * row of 2d array
1590 * col of 2d array
1591 * Return: size of numa at [row][col], or 0 if the numa doesn't exist
1592 * or on error
1593 */
1594 l_int32
numa2dGetCount(NUMA2D * na2d,l_int32 row,l_int32 col)1595 numa2dGetCount(NUMA2D *na2d,
1596 l_int32 row,
1597 l_int32 col)
1598 {
1599 NUMA *na;
1600
1601 PROCNAME("numa2dGetCount");
1602
1603 if (!na2d)
1604 return ERROR_INT("na2d not defined", procName, 0);
1605 if (row < 0 || row >= na2d->nrows)
1606 return ERROR_INT("row out of bounds", procName, 0);
1607 if (col < 0 || col >= na2d->ncols)
1608 return ERROR_INT("col out of bounds", procName, 0);
1609 if ((na = na2d->numa[row][col]) == NULL)
1610 return 0;
1611 else
1612 return na->n;
1613 }
1614
1615
1616 /*!
1617 * numa2dGetNuma()
1618 *
1619 * Input: na2d
1620 * row of 2d array
1621 * col of 2d array
1622 * Return: na (a clone of the numa if it exists) or null if it doesn't
1623 *
1624 * Notes:
1625 * (1) This does not give an error if the index is out of bounds.
1626 */
1627 NUMA *
numa2dGetNuma(NUMA2D * na2d,l_int32 row,l_int32 col)1628 numa2dGetNuma(NUMA2D *na2d,
1629 l_int32 row,
1630 l_int32 col)
1631 {
1632 NUMA *na;
1633
1634 PROCNAME("numa2dGetNuma");
1635
1636 if (!na2d)
1637 return (NUMA *)ERROR_PTR("na2d not defined", procName, NULL);
1638 if (row < 0 || row >= na2d->nrows || col < 0 || col >= na2d->ncols)
1639 return NULL;
1640 if ((na = na2d->numa[row][col]) == NULL)
1641 return NULL;
1642 return numaClone(na);
1643 }
1644
1645
1646 /*!
1647 * numa2dGetFValue()
1648 *
1649 * Input: na2d
1650 * row of 2d array
1651 * col of 2d array
1652 * index (into numa)
1653 * &val (<return> float value)
1654 * Return: 0 if OK, 1 on error
1655 */
1656 l_int32
numa2dGetFValue(NUMA2D * na2d,l_int32 row,l_int32 col,l_int32 index,l_float32 * pval)1657 numa2dGetFValue(NUMA2D *na2d,
1658 l_int32 row,
1659 l_int32 col,
1660 l_int32 index,
1661 l_float32 *pval)
1662 {
1663 NUMA *na;
1664
1665 PROCNAME("numa2dGetFValue");
1666
1667 if (!na2d)
1668 return ERROR_INT("na2d not defined", procName, 1);
1669 if (!pval)
1670 return ERROR_INT("&val not defined", procName, 1);
1671 *pval = 0.0;
1672
1673 if (row < 0 || row >= na2d->nrows)
1674 return ERROR_INT("row out of bounds", procName, 1);
1675 if (col < 0 || col >= na2d->ncols)
1676 return ERROR_INT("col out of bounds", procName, 1);
1677 if ((na = na2d->numa[row][col]) == NULL)
1678 return ERROR_INT("numa does not exist", procName, 1);
1679
1680 return numaGetFValue(na, index, pval);
1681 }
1682
1683
1684 /*!
1685 * numa2dGetIValue()
1686 *
1687 * Input: na2d
1688 * row of 2d array
1689 * col of 2d array
1690 * index (into numa)
1691 * &val (<return> integer value)
1692 * Return: 0 if OK, 1 on error
1693 */
1694 l_int32
numa2dGetIValue(NUMA2D * na2d,l_int32 row,l_int32 col,l_int32 index,l_int32 * pval)1695 numa2dGetIValue(NUMA2D *na2d,
1696 l_int32 row,
1697 l_int32 col,
1698 l_int32 index,
1699 l_int32 *pval)
1700 {
1701 NUMA *na;
1702
1703 PROCNAME("numa2dGetIValue");
1704
1705 if (!na2d)
1706 return ERROR_INT("na2d not defined", procName, 1);
1707 if (!pval)
1708 return ERROR_INT("&val not defined", procName, 1);
1709 *pval = 0;
1710
1711 if (row < 0 || row >= na2d->nrows)
1712 return ERROR_INT("row out of bounds", procName, 1);
1713 if (col < 0 || col >= na2d->ncols)
1714 return ERROR_INT("col out of bounds", procName, 1);
1715 if ((na = na2d->numa[row][col]) == NULL)
1716 return ERROR_INT("numa does not exist", procName, 1);
1717
1718 return numaGetIValue(na, index, pval);
1719 }
1720
1721
1722 /*--------------------------------------------------------------------------*
1723 * Number array hash: Creation and destruction *
1724 *--------------------------------------------------------------------------*/
1725 /*!
1726 * numaHashCreate()
1727 *
1728 * Input: nbuckets (the number of buckets in the hash table,
1729 * which should be prime.)
1730 * initsize (initial size of each allocated numa; 0 for default)
1731 * Return: ptr to new nahash, or null on error
1732 *
1733 * Note: actual numa are created only as required by numaHashAdd()
1734 */
1735 NUMAHASH *
numaHashCreate(l_int32 nbuckets,l_int32 initsize)1736 numaHashCreate(l_int32 nbuckets,
1737 l_int32 initsize)
1738 {
1739 NUMAHASH *nahash;
1740
1741 PROCNAME("numaHashCreate");
1742
1743 if (nbuckets <= 0)
1744 return (NUMAHASH *)ERROR_PTR("negative hash size", procName, NULL);
1745 if ((nahash = (NUMAHASH *)CALLOC(1, sizeof(NUMAHASH))) == NULL)
1746 return (NUMAHASH *)ERROR_PTR("nahash not made", procName, NULL);
1747 if ((nahash->numa = (NUMA **)CALLOC(nbuckets, sizeof(NUMA *))) == NULL) {
1748 FREE(nahash);
1749 return (NUMAHASH *)ERROR_PTR("numa ptr array not made", procName, NULL);
1750 }
1751
1752 nahash->nbuckets = nbuckets;
1753 nahash->initsize = initsize;
1754 return nahash;
1755 }
1756
1757
1758 /*!
1759 * numaHashDestroy()
1760 *
1761 * Input: &nahash (<to be nulled, if it exists>)
1762 * Return: void
1763 */
1764 void
numaHashDestroy(NUMAHASH ** pnahash)1765 numaHashDestroy(NUMAHASH **pnahash)
1766 {
1767 NUMAHASH *nahash;
1768 l_int32 i;
1769
1770 PROCNAME("numaHashDestroy");
1771
1772 if (pnahash == NULL) {
1773 L_WARNING("ptr address is NULL!", procName);
1774 return;
1775 }
1776
1777 if ((nahash = *pnahash) == NULL)
1778 return;
1779
1780 for (i = 0; i < nahash->nbuckets; i++)
1781 numaDestroy(&nahash->numa[i]);
1782 FREE(nahash->numa);
1783 FREE(nahash);
1784 *pnahash = NULL;
1785 }
1786
1787
1788 /*--------------------------------------------------------------------------*
1789 * Number array hash: Add elements and return numas
1790 *--------------------------------------------------------------------------*/
1791 /*!
1792 * numaHashGetNuma()
1793 *
1794 * Input: nahash
1795 * key (key to be hashed into a bucket number)
1796 * Return: ptr to numa
1797 */
1798 NUMA *
numaHashGetNuma(NUMAHASH * nahash,l_uint32 key)1799 numaHashGetNuma(NUMAHASH *nahash,
1800 l_uint32 key)
1801 {
1802 l_int32 bucket;
1803 NUMA *na;
1804
1805 PROCNAME("numaHashGetNuma");
1806
1807 if (!nahash)
1808 return (NUMA *)ERROR_PTR("nahash not defined", procName, NULL);
1809 bucket = key % nahash->nbuckets;
1810 na = nahash->numa[bucket];
1811 if (na)
1812 return numaClone(na);
1813 else
1814 return NULL;
1815 }
1816
1817 /*!
1818 * numaHashAdd()
1819 *
1820 * Input: nahash
1821 * key (key to be hashed into a bucket number)
1822 * value (float value to be appended to the specific numa)
1823 * Return: 0 if OK; 1 on error
1824 */
1825 l_int32
numaHashAdd(NUMAHASH * nahash,l_uint32 key,l_float32 value)1826 numaHashAdd(NUMAHASH *nahash,
1827 l_uint32 key,
1828 l_float32 value)
1829 {
1830 l_int32 bucket;
1831 NUMA *na;
1832
1833 PROCNAME("numaHashAdd");
1834
1835 if (!nahash)
1836 return ERROR_INT("nahash not defined", procName, 1);
1837 if (key < 0)
1838 return ERROR_INT("key < 0", procName, 1);
1839 bucket = key % nahash->nbuckets;
1840 na = nahash->numa[bucket];
1841 if (!na) {
1842 if ((na = numaCreate(nahash->initsize)) == NULL)
1843 return ERROR_INT("na not made", procName, 1);
1844 nahash->numa[bucket] = na;
1845 }
1846 numaAddNumber(na, value);
1847 return 0;
1848 }
1849
1850
1851