Leptonica  1.83.1
Image processing and image analysis suite
numabasic.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
165 #ifdef HAVE_CONFIG_H
166 #include <config_auto.h>
167 #endif /* HAVE_CONFIG_H */
168 
169 #include <string.h>
170 #include <math.h>
171 #include "allheaders.h"
172 #include "array_internal.h"
173 
174  /* Bounds on initial array size */
175 static const l_uint32 MaxFloatArraySize = 100000000; /* for numa */
176 static const l_uint32 MaxPtrArraySize = 1000000; /* for numaa */
177 static const l_int32 InitialArraySize = 50;
179  /* Static functions */
180 static l_int32 numaExtendArray(NUMA *na);
181 static l_int32 numaaExtendArray(NUMAA *naa);
182 
183 /*--------------------------------------------------------------------------*
184  * Numa creation, destruction, copy, clone, etc. *
185  *--------------------------------------------------------------------------*/
192 NUMA *
193 numaCreate(l_int32 n)
194 {
195 NUMA *na;
196 
197  if (n <= 0 || n > MaxFloatArraySize)
198  n = InitialArraySize;
199 
200  na = (NUMA *)LEPT_CALLOC(1, sizeof(NUMA));
201  if ((na->array = (l_float32 *)LEPT_CALLOC(n, sizeof(l_float32))) == NULL) {
202  numaDestroy(&na);
203  return (NUMA *)ERROR_PTR("number array not made", __func__, NULL);
204  }
205 
206  na->nalloc = n;
207  na->n = 0;
208  na->refcount = 1;
209  na->startx = 0.0;
210  na->delx = 1.0;
211  return na;
212 }
213 
214 
230 NUMA *
231 numaCreateFromIArray(l_int32 *iarray,
232  l_int32 size)
233 {
234 l_int32 i;
235 NUMA *na;
236 
237  if (!iarray)
238  return (NUMA *)ERROR_PTR("iarray not defined", __func__, NULL);
239  if (size <= 0)
240  return (NUMA *)ERROR_PTR("size must be > 0", __func__, NULL);
241 
242  na = numaCreate(size);
243  for (i = 0; i < size; i++)
244  numaAddNumber(na, iarray[i]);
245 
246  return na;
247 }
248 
249 
265 NUMA *
266 numaCreateFromFArray(l_float32 *farray,
267  l_int32 size,
268  l_int32 copyflag)
269 {
270 l_int32 i;
271 NUMA *na;
272 
273  if (!farray)
274  return (NUMA *)ERROR_PTR("farray not defined", __func__, NULL);
275  if (size <= 0)
276  return (NUMA *)ERROR_PTR("size must be > 0", __func__, NULL);
277  if (copyflag != L_INSERT && copyflag != L_COPY)
278  return (NUMA *)ERROR_PTR("invalid copyflag", __func__, NULL);
279 
280  na = numaCreate(size);
281  if (copyflag == L_INSERT) {
282  if (na->array) LEPT_FREE(na->array);
283  na->array = farray;
284  na->n = size;
285  } else { /* just copy the contents */
286  for (i = 0; i < size; i++)
287  numaAddNumber(na, farray[i]);
288  }
289 
290  return na;
291 }
292 
293 
307 NUMA *
308 numaCreateFromString(const char *str)
309 {
310 char *substr;
311 l_int32 i, n, nerrors;
312 l_float32 val;
313 NUMA *na;
314 SARRAY *sa;
315 
316  if (!str || (strlen(str) == 0))
317  return (NUMA *)ERROR_PTR("str not defined or empty", __func__, NULL);
318 
319  sa = sarrayCreate(0);
320  sarraySplitString(sa, str, ",");
321  n = sarrayGetCount(sa);
322  na = numaCreate(n);
323  nerrors = 0;
324  for (i = 0; i < n; i++) {
325  substr = sarrayGetString(sa, i, L_NOCOPY);
326  if (sscanf(substr, "%f", &val) != 1) {
327  L_ERROR("substr %d not float\n", __func__, i);
328  nerrors++;
329  } else {
330  numaAddNumber(na, val);
331  }
332  }
333 
334  sarrayDestroy(&sa);
335  if (nerrors > 0) {
336  numaDestroy(&na);
337  return (NUMA *)ERROR_PTR("non-floats in string", __func__, NULL);
338  }
339 
340  return na;
341 }
342 
343 
356 void
358 {
359 NUMA *na;
360 
361  if (pna == NULL) {
362  L_WARNING("ptr address is NULL\n", __func__);
363  return;
364  }
365 
366  if ((na = *pna) == NULL)
367  return;
368 
369  /* Decrement the ref count. If it is 0, destroy the numa. */
370  if (--na->refcount == 0) {
371  if (na->array)
372  LEPT_FREE(na->array);
373  LEPT_FREE(na);
374  }
375 
376  *pna = NULL;
377 }
378 
379 
386 NUMA *
388 {
389 l_int32 i;
390 NUMA *cna;
391 
392  if (!na)
393  return (NUMA *)ERROR_PTR("na not defined", __func__, NULL);
394 
395  if ((cna = numaCreate(na->nalloc)) == NULL)
396  return (NUMA *)ERROR_PTR("cna not made", __func__, NULL);
397  cna->startx = na->startx;
398  cna->delx = na->delx;
399 
400  for (i = 0; i < na->n; i++)
401  numaAddNumber(cna, na->array[i]);
402 
403  return cna;
404 }
405 
406 
413 NUMA *
415 {
416  if (!na)
417  return (NUMA *)ERROR_PTR("na not defined", __func__, NULL);
418 
419  ++na->refcount;
420  return na;
421 }
422 
423 
437 l_ok
439 {
440  if (!na)
441  return ERROR_INT("na not defined", __func__, 1);
442 
443  na->n = 0;
444  return 0;
445 }
446 
447 
448 
449 /*--------------------------------------------------------------------------*
450  * Number array: add number and extend array *
451  *--------------------------------------------------------------------------*/
459 l_ok
461  l_float32 val)
462 {
463 l_int32 n;
464 
465  if (!na)
466  return ERROR_INT("na not defined", __func__, 1);
467 
468  n = numaGetCount(na);
469  if (n >= na->nalloc) {
470  if (numaExtendArray(na))
471  return ERROR_INT("extension failed", __func__, 1);
472  }
473  na->array[n] = val;
474  na->n++;
475  return 0;
476 }
477 
478 
490 static l_int32
492 {
493 size_t oldsize, newsize;
494 
495  if (!na)
496  return ERROR_INT("na not defined", __func__, 1);
497  if (na->nalloc > MaxFloatArraySize) /* belt & suspenders */
498  return ERROR_INT("na has too many ptrs", __func__, 1);
499  oldsize = na->nalloc * sizeof(l_float32);
500  newsize = 2 * oldsize;
501  if (newsize > 4 * MaxFloatArraySize)
502  return ERROR_INT("newsize > 400 MB; too large", __func__, 1);
503 
504  if ((na->array = (l_float32 *)reallocNew((void **)&na->array,
505  oldsize, newsize)) == NULL)
506  return ERROR_INT("new ptr array not returned", __func__, 1);
507 
508  na->nalloc *= 2;
509  return 0;
510 }
511 
512 
530 l_ok
532  l_int32 index,
533  l_float32 val)
534 {
535 l_int32 i, n;
536 
537  if (!na)
538  return ERROR_INT("na not defined", __func__, 1);
539  n = numaGetCount(na);
540  if (index < 0 || index > n) {
541  L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n);
542  return 1;
543  }
544 
545  if (n >= na->nalloc) {
546  if (numaExtendArray(na))
547  return ERROR_INT("extension failed", __func__, 1);
548  }
549  for (i = n; i > index; i--)
550  na->array[i] = na->array[i - 1];
551  na->array[index] = val;
552  na->n++;
553  return 0;
554 }
555 
556 
571 l_ok
573  l_int32 index)
574 {
575 l_int32 i, n;
576 
577  if (!na)
578  return ERROR_INT("na not defined", __func__, 1);
579  n = numaGetCount(na);
580  if (index < 0 || index >= n) {
581  L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n - 1);
582  return 1;
583  }
584 
585  for (i = index + 1; i < n; i++)
586  na->array[i - 1] = na->array[i];
587  na->n--;
588  return 0;
589 }
590 
591 
600 l_ok
602  l_int32 index,
603  l_float32 val)
604 {
605 l_int32 n;
606 
607  if (!na)
608  return ERROR_INT("na not defined", __func__, 1);
609  n = numaGetCount(na);
610  if (index < 0 || index >= n) {
611  L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n - 1);
612  return 1;
613  }
614 
615  na->array[index] = val;
616  return 0;
617 }
618 
619 
620 /*----------------------------------------------------------------------*
621  * Numa accessors *
622  *----------------------------------------------------------------------*/
629 l_int32
631 {
632  if (!na)
633  return ERROR_INT("na not defined", __func__, 0);
634  return na->n;
635 }
636 
637 
654 l_ok
656  l_int32 newcount)
657 {
658  if (!na)
659  return ERROR_INT("na not defined", __func__, 1);
660  if (newcount > na->nalloc) {
661  if ((na->array = (l_float32 *)reallocNew((void **)&na->array,
662  sizeof(l_float32) * na->nalloc,
663  sizeof(l_float32) * newcount)) == NULL)
664  return ERROR_INT("new ptr array not returned", __func__, 1);
665  na->nalloc = newcount;
666  }
667  na->n = newcount;
668  return 0;
669 }
670 
671 
686 l_ok
688  l_int32 index,
689  l_float32 *pval)
690 {
691  if (!pval)
692  return ERROR_INT("&val not defined", __func__, 1);
693  *pval = 0.0;
694  if (!na)
695  return ERROR_INT("na not defined", __func__, 1);
696 
697  if (index < 0 || index >= na->n)
698  return ERROR_INT("index not valid", __func__, 1);
699 
700  *pval = na->array[index];
701  return 0;
702 }
703 
704 
719 l_ok
721  l_int32 index,
722  l_int32 *pival)
723 {
724 l_float32 val;
725 
726  if (!pival)
727  return ERROR_INT("&ival not defined", __func__, 1);
728  *pival = 0;
729  if (!na)
730  return ERROR_INT("na not defined", __func__, 1);
731 
732  if (index < 0 || index >= na->n)
733  return ERROR_INT("index not valid", __func__, 1);
734 
735  val = na->array[index];
736  *pival = (l_int32)(val + L_SIGN(val) * 0.5);
737  return 0;
738 }
739 
740 
749 l_ok
751  l_int32 index,
752  l_float32 val)
753 {
754  if (!na)
755  return ERROR_INT("na not defined", __func__, 1);
756  if (index < 0 || index >= na->n)
757  return ERROR_INT("index not valid", __func__, 1);
758 
759  na->array[index] = val;
760  return 0;
761 }
762 
763 
772 l_ok
774  l_int32 index,
775  l_float32 diff)
776 {
777  if (!na)
778  return ERROR_INT("na not defined", __func__, 1);
779  if (index < 0 || index >= na->n)
780  return ERROR_INT("index not valid", __func__, 1);
781 
782  na->array[index] += diff;
783  return 0;
784 }
785 
786 
806 l_int32 *
808 {
809 l_int32 i, n, ival;
810 l_int32 *array;
811 
812  if (!na)
813  return (l_int32 *)ERROR_PTR("na not defined", __func__, NULL);
814 
815  n = numaGetCount(na);
816  if ((array = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32))) == NULL)
817  return (l_int32 *)ERROR_PTR("array not made", __func__, NULL);
818  for (i = 0; i < n; i++) {
819  numaGetIValue(na, i, &ival);
820  array[i] = ival;
821  }
822 
823  return array;
824 }
825 
826 
849 l_float32 *
851  l_int32 copyflag)
852 {
853 l_int32 i, n;
854 l_float32 *array;
855 
856  if (!na)
857  return (l_float32 *)ERROR_PTR("na not defined", __func__, NULL);
858 
859  if (copyflag == L_NOCOPY) {
860  array = na->array;
861  } else { /* copyflag == L_COPY */
862  n = numaGetCount(na);
863  if ((array = (l_float32 *)LEPT_CALLOC(n, sizeof(l_float32))) == NULL)
864  return (l_float32 *)ERROR_PTR("array not made", __func__, NULL);
865  for (i = 0; i < n; i++)
866  array[i] = na->array[i];
867  }
868 
869  return array;
870 }
871 
872 
881 l_ok
883  l_float32 *pstartx,
884  l_float32 *pdelx)
885 {
886  if (!pdelx && !pstartx)
887  return ERROR_INT("no return val requested", __func__, 1);
888  if (pstartx) *pstartx = 0.0;
889  if (pdelx) *pdelx = 1.0;
890  if (!na)
891  return ERROR_INT("na not defined", __func__, 1);
892 
893  if (pstartx) *pstartx = na->startx;
894  if (pdelx) *pdelx = na->delx;
895  return 0;
896 }
897 
898 
909 l_ok
911  l_float32 startx,
912  l_float32 delx)
913 {
914  if (!na)
915  return ERROR_INT("na not defined", __func__, 1);
916 
917  na->startx = startx;
918  na->delx = delx;
919  return 0;
920 }
921 
922 
930 l_ok
932  NUMA *nas)
933 {
934 l_float32 start, binsize;
935 
936  if (!nas || !nad)
937  return ERROR_INT("nas and nad not both defined", __func__, 1);
938 
939  numaGetParameters(nas, &start, &binsize);
940  numaSetParameters(nad, start, binsize);
941  return 0;
942 }
943 
944 
945 /*----------------------------------------------------------------------*
946  * Convert to string array *
947  *----------------------------------------------------------------------*/
966 SARRAY *
968  l_int32 size1,
969  l_int32 size2,
970  l_int32 addzeros,
971  l_int32 type)
972 {
973 char fmt[32], strbuf[64];
974 l_int32 i, n, ival;
975 l_float32 fval;
976 SARRAY *sa;
977 
978  if (!na)
979  return (SARRAY *)ERROR_PTR("na not defined", __func__, NULL);
980  if (type != L_INTEGER_VALUE && type != L_FLOAT_VALUE)
981  return (SARRAY *)ERROR_PTR("invalid type", __func__, NULL);
982 
983  if (type == L_INTEGER_VALUE) {
984  if (addzeros)
985  snprintf(fmt, sizeof(fmt), "%%0%dd", size1);
986  else
987  snprintf(fmt, sizeof(fmt), "%%%dd", size1);
988  } else { /* L_FLOAT_VALUE */
989  snprintf(fmt, sizeof(fmt), "%%%d.%df", size1, size2);
990  }
991 
992  n = numaGetCount(na);
993  if ((sa = sarrayCreate(n)) == NULL)
994  return (SARRAY *)ERROR_PTR("sa not made", __func__, NULL);
995 
996  for (i = 0; i < n; i++) {
997  if (type == L_INTEGER_VALUE) {
998  numaGetIValue(na, i, &ival);
999  snprintf(strbuf, sizeof(strbuf), fmt, ival);
1000  } else { /* L_FLOAT_VALUE */
1001  numaGetFValue(na, i, &fval);
1002  snprintf(strbuf, sizeof(strbuf), fmt, fval);
1003  }
1004  sarrayAddString(sa, strbuf, L_COPY);
1005  }
1006 
1007  return sa;
1008 }
1009 
1010 
1011 /*----------------------------------------------------------------------*
1012  * Serialize numa for I/O *
1013  *----------------------------------------------------------------------*/
1020 NUMA *
1021 numaRead(const char *filename)
1022 {
1023 FILE *fp;
1024 NUMA *na;
1025 
1026  if (!filename)
1027  return (NUMA *)ERROR_PTR("filename not defined", __func__, NULL);
1028 
1029  if ((fp = fopenReadStream(filename)) == NULL)
1030  return (NUMA *)ERROR_PTR("stream not opened", __func__, NULL);
1031  na = numaReadStream(fp);
1032  fclose(fp);
1033  if (!na)
1034  return (NUMA *)ERROR_PTR("na not read", __func__, NULL);
1035  return na;
1036 }
1037 
1038 
1045 NUMA *
1047 {
1048 l_int32 i, n, index, ret, version;
1049 l_float32 val, startx, delx;
1050 NUMA *na;
1051 
1052  if (!fp)
1053  return (NUMA *)ERROR_PTR("stream not defined", __func__, NULL);
1054 
1055  ret = fscanf(fp, "\nNuma Version %d\n", &version);
1056  if (ret != 1)
1057  return (NUMA *)ERROR_PTR("not a numa file", __func__, NULL);
1058  if (version != NUMA_VERSION_NUMBER)
1059  return (NUMA *)ERROR_PTR("invalid numa version", __func__, NULL);
1060  if (fscanf(fp, "Number of numbers = %d\n", &n) != 1)
1061  return (NUMA *)ERROR_PTR("invalid number of numbers", __func__, NULL);
1062 
1063  if (n > MaxFloatArraySize) {
1064  L_ERROR("n = %d > %d\n", __func__, n, MaxFloatArraySize);
1065  return NULL;
1066  }
1067  if ((na = numaCreate(n)) == NULL)
1068  return (NUMA *)ERROR_PTR("na not made", __func__, NULL);
1069 
1070  for (i = 0; i < n; i++) {
1071  if (fscanf(fp, " [%d] = %f\n", &index, &val) != 2) {
1072  numaDestroy(&na);
1073  return (NUMA *)ERROR_PTR("bad input data", __func__, NULL);
1074  }
1075  numaAddNumber(na, val);
1076  }
1077 
1078  /* Optional data */
1079  if (fscanf(fp, "startx = %f, delx = %f\n", &startx, &delx) == 2)
1080  numaSetParameters(na, startx, delx);
1081 
1082  return na;
1083 }
1084 
1085 
1093 NUMA *
1094 numaReadMem(const l_uint8 *data,
1095  size_t size)
1096 {
1097 FILE *fp;
1098 NUMA *na;
1099 
1100  if (!data)
1101  return (NUMA *)ERROR_PTR("data not defined", __func__, NULL);
1102  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1103  return (NUMA *)ERROR_PTR("stream not opened", __func__, NULL);
1104 
1105  na = numaReadStream(fp);
1106  fclose(fp);
1107  if (!na) L_ERROR("numa not read\n", __func__);
1108  return na;
1109 }
1110 
1111 
1128 l_ok
1129 numaWriteDebug(const char *filename,
1130  NUMA *na)
1131 {
1132  if (LeptDebugOK) {
1133  return numaWrite(filename, na);
1134  } else {
1135  L_INFO("write to named temp file %s is disabled\n", __func__, filename);
1136  return 0;
1137  }
1138 }
1139 
1140 
1148 l_ok
1149 numaWrite(const char *filename,
1150  NUMA *na)
1151 {
1152 l_int32 ret;
1153 FILE *fp;
1154 
1155  if (!filename)
1156  return ERROR_INT("filename not defined", __func__, 1);
1157  if (!na)
1158  return ERROR_INT("na not defined", __func__, 1);
1159 
1160  if ((fp = fopenWriteStream(filename, "w")) == NULL)
1161  return ERROR_INT("stream not opened", __func__, 1);
1162  ret = numaWriteStream(fp, na);
1163  fclose(fp);
1164  if (ret)
1165  return ERROR_INT("na not written to stream", __func__, 1);
1166  return 0;
1167 }
1168 
1169 
1177 l_ok
1179  NUMA *na)
1180 {
1181 l_int32 i, n;
1182 l_float32 startx, delx;
1183 
1184  if (!na)
1185  return ERROR_INT("na not defined", __func__, 1);
1186  if (!fp)
1187  return numaWriteStderr(na);
1188 
1189  n = numaGetCount(na);
1190  fprintf(fp, "\nNuma Version %d\n", NUMA_VERSION_NUMBER);
1191  fprintf(fp, "Number of numbers = %d\n", n);
1192  for (i = 0; i < n; i++)
1193  fprintf(fp, " [%d] = %f\n", i, na->array[i]);
1194  fprintf(fp, "\n");
1195 
1196  /* Optional data */
1197  numaGetParameters(na, &startx, &delx);
1198  if (startx != 0.0 || delx != 1.0)
1199  fprintf(fp, "startx = %f, delx = %f\n", startx, delx);
1200 
1201  return 0;
1202 }
1203 
1204 
1211 l_ok
1213 {
1214 l_int32 i, n;
1215 l_float32 startx, delx;
1216 
1217  if (!na)
1218  return ERROR_INT("na not defined", __func__, 1);
1219 
1220  n = numaGetCount(na);
1221  lept_stderr("\nNuma Version %d\n", NUMA_VERSION_NUMBER);
1222  lept_stderr("Number of numbers = %d\n", n);
1223  for (i = 0; i < n; i++)
1224  lept_stderr(" [%d] = %f\n", i, na->array[i]);
1225  lept_stderr("\n");
1226 
1227  /* Optional data */
1228  numaGetParameters(na, &startx, &delx);
1229  if (startx != 0.0 || delx != 1.0)
1230  lept_stderr("startx = %f, delx = %f\n", startx, delx);
1231 
1232  return 0;
1233 }
1234 
1235 
1249 l_ok
1250 numaWriteMem(l_uint8 **pdata,
1251  size_t *psize,
1252  NUMA *na)
1253 {
1254 l_int32 ret;
1255 FILE *fp;
1256 
1257  if (pdata) *pdata = NULL;
1258  if (psize) *psize = 0;
1259  if (!pdata)
1260  return ERROR_INT("&data not defined", __func__, 1);
1261  if (!psize)
1262  return ERROR_INT("&size not defined", __func__, 1);
1263  if (!na)
1264  return ERROR_INT("na not defined", __func__, 1);
1265 
1266 #if HAVE_FMEMOPEN
1267  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1268  return ERROR_INT("stream not opened", __func__, 1);
1269  ret = numaWriteStream(fp, na);
1270  fputc('\0', fp);
1271  fclose(fp);
1272  *psize = *psize - 1;
1273 #else
1274  L_INFO("work-around: writing to a temp file\n", __func__);
1275  #ifdef _WIN32
1276  if ((fp = fopenWriteWinTempfile()) == NULL)
1277  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1278  #else
1279  if ((fp = tmpfile()) == NULL)
1280  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1281  #endif /* _WIN32 */
1282  ret = numaWriteStream(fp, na);
1283  rewind(fp);
1284  *pdata = l_binaryReadStream(fp, psize);
1285  fclose(fp);
1286 #endif /* HAVE_FMEMOPEN */
1287  return ret;
1288 }
1289 
1290 
1291 /*--------------------------------------------------------------------------*
1292  * Numaa creation, destruction *
1293  *--------------------------------------------------------------------------*/
1301 NUMAA *
1302 numaaCreate(l_int32 n)
1303 {
1304 NUMAA *naa;
1305 
1306  if (n <= 0 || n > MaxPtrArraySize)
1307  n = InitialArraySize;
1308 
1309  naa = (NUMAA *)LEPT_CALLOC(1, sizeof(NUMAA));
1310  if ((naa->numa = (NUMA **)LEPT_CALLOC(n, sizeof(NUMA *))) == NULL) {
1311  numaaDestroy(&naa);
1312  return (NUMAA *)ERROR_PTR("numa ptr array not made", __func__, NULL);
1313  }
1314 
1315  naa->nalloc = n;
1316  naa->n = 0;
1317  return naa;
1318 }
1319 
1320 
1337 NUMAA *
1338 numaaCreateFull(l_int32 nptr,
1339  l_int32 n)
1340 {
1341 l_int32 i;
1342 NUMAA *naa;
1343 NUMA *na;
1344 
1345  naa = numaaCreate(nptr);
1346  for (i = 0; i < nptr; i++) {
1347  na = numaCreate(n);
1348  numaaAddNuma(naa, na, L_INSERT);
1349  }
1350 
1351  return naa;
1352 }
1353 
1354 
1368 l_ok
1370 {
1371 l_int32 i, n, nn;
1372 NUMA *na;
1373 
1374  if (!naa)
1375  return ERROR_INT("naa not defined", __func__, 1);
1376 
1377  n = numaaGetCount(naa);
1378  for (i = n - 1; i >= 0; i--) {
1379  na = numaaGetNuma(naa, i, L_CLONE);
1380  if (!na)
1381  continue;
1382  nn = numaGetCount(na);
1383  numaDestroy(&na);
1384  if (nn == 0)
1385  numaDestroy(&naa->numa[i]);
1386  else
1387  break;
1388  }
1389  naa->n = i + 1;
1390  return 0;
1391 }
1392 
1393 
1400 void
1402 {
1403 l_int32 i;
1404 NUMAA *naa;
1405 
1406  if (pnaa == NULL) {
1407  L_WARNING("ptr address is NULL!\n", __func__);
1408  return;
1409  }
1410 
1411  if ((naa = *pnaa) == NULL)
1412  return;
1413 
1414  for (i = 0; i < naa->n; i++)
1415  numaDestroy(&naa->numa[i]);
1416  LEPT_FREE(naa->numa);
1417  LEPT_FREE(naa);
1418  *pnaa = NULL;
1419 }
1420 
1421 
1422 
1423 /*--------------------------------------------------------------------------*
1424  * Add Numa to Numaa *
1425  *--------------------------------------------------------------------------*/
1434 l_ok
1436  NUMA *na,
1437  l_int32 copyflag)
1438 {
1439 l_int32 n;
1440 NUMA *nac;
1441 
1442  if (!naa)
1443  return ERROR_INT("naa not defined", __func__, 1);
1444  if (!na)
1445  return ERROR_INT("na not defined", __func__, 1);
1446 
1447  if (copyflag == L_INSERT) {
1448  nac = na;
1449  } else if (copyflag == L_COPY) {
1450  if ((nac = numaCopy(na)) == NULL)
1451  return ERROR_INT("nac not made", __func__, 1);
1452  } else if (copyflag == L_CLONE) {
1453  nac = numaClone(na);
1454  } else {
1455  return ERROR_INT("invalid copyflag", __func__, 1);
1456  }
1457 
1458  n = numaaGetCount(naa);
1459  if (n >= naa->nalloc) {
1460  if (numaaExtendArray(naa)) {
1461  if (copyflag != L_INSERT)
1462  numaDestroy(&nac);
1463  return ERROR_INT("extension failed", __func__, 1);
1464  }
1465  }
1466  naa->numa[n] = nac;
1467  naa->n++;
1468  return 0;
1469 }
1470 
1471 
1483 static l_int32
1485 {
1486 size_t oldsize, newsize;
1487 
1488  if (!naa)
1489  return ERROR_INT("naa not defined", __func__, 1);
1490  if (naa->nalloc > MaxPtrArraySize) /* belt & suspenders */
1491  return ERROR_INT("naa has too many ptrs", __func__, 1);
1492  oldsize = naa->nalloc * sizeof(NUMA *);
1493  newsize = 2 * oldsize;
1494  if (newsize > 8 * MaxPtrArraySize)
1495  return ERROR_INT("newsize > 8 MB; too large", __func__, 1);
1496 
1497  if ((naa->numa = (NUMA **)reallocNew((void **)&naa->numa,
1498  oldsize, newsize)) == NULL)
1499  return ERROR_INT("new ptr array not returned", __func__, 1);
1500 
1501  naa->nalloc *= 2;
1502  return 0;
1503 }
1504 
1505 
1506 /*----------------------------------------------------------------------*
1507  * Numaa accessors *
1508  *----------------------------------------------------------------------*/
1515 l_int32
1517 {
1518  if (!naa)
1519  return ERROR_INT("naa not defined", __func__, 0);
1520  return naa->n;
1521 }
1522 
1523 
1531 l_int32
1533  l_int32 index)
1534 {
1535  if (!naa)
1536  return ERROR_INT("naa not defined", __func__, 0);
1537  if (index < 0 || index >= naa->n)
1538  return ERROR_INT("invalid index into naa", __func__, 0);
1539  return numaGetCount(naa->numa[index]);
1540 }
1541 
1542 
1550 l_int32
1552 {
1553 NUMA *na;
1554 l_int32 n, sum, i;
1555 
1556  if (!naa)
1557  return ERROR_INT("naa not defined", __func__, 0);
1558 
1559  n = numaaGetCount(naa);
1560  for (sum = 0, i = 0; i < n; i++) {
1561  na = numaaGetNuma(naa, i, L_CLONE);
1562  sum += numaGetCount(na);
1563  numaDestroy(&na);
1564  }
1565 
1566  return sum;
1567 }
1568 
1569 
1597 NUMA **
1599 {
1600  if (!naa)
1601  return (NUMA **)ERROR_PTR("naa not defined", __func__, NULL);
1602 
1603  naa->n = naa->nalloc;
1604  return naa->numa;
1605 }
1606 
1607 
1616 NUMA *
1618  l_int32 index,
1619  l_int32 accessflag)
1620 {
1621  if (!naa)
1622  return (NUMA *)ERROR_PTR("naa not defined", __func__, NULL);
1623  if (index < 0 || index >= naa->n)
1624  return (NUMA *)ERROR_PTR("index not valid", __func__, NULL);
1625 
1626  if (accessflag == L_COPY)
1627  return numaCopy(naa->numa[index]);
1628  else if (accessflag == L_CLONE)
1629  return numaClone(naa->numa[index]);
1630  else
1631  return (NUMA *)ERROR_PTR("invalid accessflag", __func__, NULL);
1632 }
1633 
1634 
1650 l_ok
1652  l_int32 index,
1653  NUMA *na)
1654 {
1655 l_int32 n;
1656 
1657  if (!naa)
1658  return ERROR_INT("naa not defined", __func__, 1);
1659  if (!na)
1660  return ERROR_INT("na not defined", __func__, 1);
1661  n = numaaGetCount(naa);
1662  if (index < 0 || index >= n)
1663  return ERROR_INT("index not valid", __func__, 1);
1664 
1665  numaDestroy(&naa->numa[index]);
1666  naa->numa[index] = na;
1667  return 0;
1668 }
1669 
1670 
1681 l_ok
1683  l_int32 i,
1684  l_int32 j,
1685  l_float32 *pfval,
1686  l_int32 *pival)
1687 {
1688 l_int32 n;
1689 NUMA *na;
1690 
1691  if (!pfval && !pival)
1692  return ERROR_INT("no return val requested", __func__, 1);
1693  if (pfval) *pfval = 0.0;
1694  if (pival) *pival = 0;
1695  if (!naa)
1696  return ERROR_INT("naa not defined", __func__, 1);
1697  n = numaaGetCount(naa);
1698  if (i < 0 || i >= n)
1699  return ERROR_INT("invalid index into naa", __func__, 1);
1700  na = naa->numa[i];
1701  if (j < 0 || j >= na->n)
1702  return ERROR_INT("invalid index into na", __func__, 1);
1703  if (pfval) *pfval = na->array[j];
1704  if (pival) *pival = (l_int32)(na->array[j]);
1705  return 0;
1706 }
1707 
1708 
1722 l_ok
1724  l_int32 index,
1725  l_float32 val)
1726 {
1727 l_int32 n;
1728 NUMA *na;
1729 
1730  if (!naa)
1731  return ERROR_INT("naa not defined", __func__, 1);
1732  n = numaaGetCount(naa);
1733  if (index < 0 || index >= n)
1734  return ERROR_INT("invalid index in naa", __func__, 1);
1735 
1736  na = numaaGetNuma(naa, index, L_CLONE);
1737  numaAddNumber(na, val);
1738  numaDestroy(&na);
1739  return 0;
1740 }
1741 
1742 
1743 /*----------------------------------------------------------------------*
1744  * Serialize numaa for I/O *
1745  *----------------------------------------------------------------------*/
1752 NUMAA *
1753 numaaRead(const char *filename)
1754 {
1755 FILE *fp;
1756 NUMAA *naa;
1757 
1758  if (!filename)
1759  return (NUMAA *)ERROR_PTR("filename not defined", __func__, NULL);
1760 
1761  if ((fp = fopenReadStream(filename)) == NULL)
1762  return (NUMAA *)ERROR_PTR("stream not opened", __func__, NULL);
1763  naa = numaaReadStream(fp);
1764  fclose(fp);
1765  if (!naa)
1766  return (NUMAA *)ERROR_PTR("naa not read", __func__, NULL);
1767  return naa;
1768 }
1769 
1770 
1777 NUMAA *
1779 {
1780 l_int32 i, n, index, ret, version;
1781 NUMA *na;
1782 NUMAA *naa;
1783 
1784  if (!fp)
1785  return (NUMAA *)ERROR_PTR("stream not defined", __func__, NULL);
1786 
1787  ret = fscanf(fp, "\nNumaa Version %d\n", &version);
1788  if (ret != 1)
1789  return (NUMAA *)ERROR_PTR("not a numa file", __func__, NULL);
1790  if (version != NUMA_VERSION_NUMBER)
1791  return (NUMAA *)ERROR_PTR("invalid numaa version", __func__, NULL);
1792  if (fscanf(fp, "Number of numa = %d\n\n", &n) != 1)
1793  return (NUMAA *)ERROR_PTR("invalid number of numa", __func__, NULL);
1794 
1795  if (n > MaxPtrArraySize) {
1796  L_ERROR("n = %d > %d\n", __func__, n, MaxPtrArraySize);
1797  return NULL;
1798  }
1799  if ((naa = numaaCreate(n)) == NULL)
1800  return (NUMAA *)ERROR_PTR("naa not made", __func__, NULL);
1801 
1802  for (i = 0; i < n; i++) {
1803  if (fscanf(fp, "Numa[%d]:", &index) != 1) {
1804  numaaDestroy(&naa);
1805  return (NUMAA *)ERROR_PTR("invalid numa header", __func__, NULL);
1806  }
1807  if ((na = numaReadStream(fp)) == NULL) {
1808  numaaDestroy(&naa);
1809  return (NUMAA *)ERROR_PTR("na not made", __func__, NULL);
1810  }
1811  numaaAddNuma(naa, na, L_INSERT);
1812  }
1813 
1814  return naa;
1815 }
1816 
1817 
1825 NUMAA *
1826 numaaReadMem(const l_uint8 *data,
1827  size_t size)
1828 {
1829 FILE *fp;
1830 NUMAA *naa;
1831 
1832  if (!data)
1833  return (NUMAA *)ERROR_PTR("data not defined", __func__, NULL);
1834  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1835  return (NUMAA *)ERROR_PTR("stream not opened", __func__, NULL);
1836 
1837  naa = numaaReadStream(fp);
1838  fclose(fp);
1839  if (!naa) L_ERROR("naa not read\n", __func__);
1840  return naa;
1841 }
1842 
1843 
1851 l_ok
1852 numaaWrite(const char *filename,
1853  NUMAA *naa)
1854 {
1855 l_int32 ret;
1856 FILE *fp;
1857 
1858  if (!filename)
1859  return ERROR_INT("filename not defined", __func__, 1);
1860  if (!naa)
1861  return ERROR_INT("naa not defined", __func__, 1);
1862 
1863  if ((fp = fopenWriteStream(filename, "w")) == NULL)
1864  return ERROR_INT("stream not opened", __func__, 1);
1865  ret = numaaWriteStream(fp, naa);
1866  fclose(fp);
1867  if (ret)
1868  return ERROR_INT("naa not written to stream", __func__, 1);
1869  return 0;
1870 }
1871 
1872 
1880 l_ok
1882  NUMAA *naa)
1883 {
1884 l_int32 i, n;
1885 NUMA *na;
1886 
1887  if (!fp)
1888  return ERROR_INT("stream not defined", __func__, 1);
1889  if (!naa)
1890  return ERROR_INT("naa not defined", __func__, 1);
1891 
1892  n = numaaGetCount(naa);
1893  fprintf(fp, "\nNumaa Version %d\n", NUMA_VERSION_NUMBER);
1894  fprintf(fp, "Number of numa = %d\n\n", n);
1895  for (i = 0; i < n; i++) {
1896  if ((na = numaaGetNuma(naa, i, L_CLONE)) == NULL)
1897  return ERROR_INT("na not found", __func__, 1);
1898  fprintf(fp, "Numa[%d]:", i);
1899  numaWriteStream(fp, na);
1900  numaDestroy(&na);
1901  }
1902 
1903  return 0;
1904 }
1905 
1906 
1920 l_ok
1921 numaaWriteMem(l_uint8 **pdata,
1922  size_t *psize,
1923  NUMAA *naa)
1924 {
1925 l_int32 ret;
1926 FILE *fp;
1927 
1928  if (pdata) *pdata = NULL;
1929  if (psize) *psize = 0;
1930  if (!pdata)
1931  return ERROR_INT("&data not defined", __func__, 1);
1932  if (!psize)
1933  return ERROR_INT("&size not defined", __func__, 1);
1934  if (!naa)
1935  return ERROR_INT("naa not defined", __func__, 1);
1936 
1937 #if HAVE_FMEMOPEN
1938  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1939  return ERROR_INT("stream not opened", __func__, 1);
1940  ret = numaaWriteStream(fp, naa);
1941  fputc('\0', fp);
1942  fclose(fp);
1943  *psize = *psize - 1;
1944 #else
1945  L_INFO("work-around: writing to a temp file\n", __func__);
1946  #ifdef _WIN32
1947  if ((fp = fopenWriteWinTempfile()) == NULL)
1948  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1949  #else
1950  if ((fp = tmpfile()) == NULL)
1951  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1952  #endif /* _WIN32 */
1953  ret = numaaWriteStream(fp, naa);
1954  rewind(fp);
1955  *pdata = l_binaryReadStream(fp, psize);
1956  fclose(fp);
1957 #endif /* HAVE_FMEMOPEN */
1958  return ret;
1959 }
1960 
@ L_FLOAT_VALUE
Definition: array.h:106
@ L_INTEGER_VALUE
Definition: array.h:105
#define NUMA_VERSION_NUMBER
SARRAY * numaConvertToSarray(NUMA *na, l_int32 size1, l_int32 size2, l_int32 addzeros, l_int32 type)
numaConvertToSarray()
Definition: numabasic.c:967
NUMA * numaReadMem(const l_uint8 *data, size_t size)
numaReadMem()
Definition: numabasic.c:1094
NUMAA * numaaRead(const char *filename)
numaaRead()
Definition: numabasic.c:1753
l_ok numaaWriteMem(l_uint8 **pdata, size_t *psize, NUMAA *naa)
numaaWriteMem()
Definition: numabasic.c:1921
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
NUMA * numaReadStream(FILE *fp)
numaReadStream()
Definition: numabasic.c:1046
l_int32 numaaGetNumberCount(NUMAA *naa)
numaaGetNumberCount()
Definition: numabasic.c:1551
NUMAA * numaaReadMem(const l_uint8 *data, size_t size)
numaaReadMem()
Definition: numabasic.c:1826
l_ok numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:601
NUMA * numaCreateFromString(const char *str)
numaCreateFromString()
Definition: numabasic.c:308
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:687
l_ok numaWriteStderr(NUMA *na)
numaWriteStderr()
Definition: numabasic.c:1212
NUMA ** numaaGetPtrArray(NUMAA *naa)
numaaGetPtrArray()
Definition: numabasic.c:1598
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
l_ok numaWrite(const char *filename, NUMA *na)
numaWrite()
Definition: numabasic.c:1149
l_int32 numaaGetCount(NUMAA *naa)
numaaGetCount()
Definition: numabasic.c:1516
l_ok numaaAddNumber(NUMAA *naa, l_int32 index, l_float32 val)
numaaAddNumber()
Definition: numabasic.c:1723
l_ok numaInsertNumber(NUMA *na, l_int32 index, l_float32 val)
numaInsertNumber()
Definition: numabasic.c:531
NUMAA * numaaCreateFull(l_int32 nptr, l_int32 n)
numaaCreateFull()
Definition: numabasic.c:1338
NUMA * numaaGetNuma(NUMAA *naa, l_int32 index, l_int32 accessflag)
numaaGetNuma()
Definition: numabasic.c:1617
l_ok numaaWriteStream(FILE *fp, NUMAA *naa)
numaaWriteStream()
Definition: numabasic.c:1881
l_int32 numaaGetNumaCount(NUMAA *naa, l_int32 index)
numaaGetNumaCount()
Definition: numabasic.c:1532
NUMA * numaRead(const char *filename)
numaRead()
Definition: numabasic.c:1021
l_ok numaSetCount(NUMA *na, l_int32 newcount)
numaSetCount()
Definition: numabasic.c:655
NUMA * numaClone(NUMA *na)
numaClone()
Definition: numabasic.c:414
l_ok numaaGetValue(NUMAA *naa, l_int32 i, l_int32 j, l_float32 *pfval, l_int32 *pival)
numaaGetValue()
Definition: numabasic.c:1682
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_ok numaaTruncate(NUMAA *naa)
numaaTruncate()
Definition: numabasic.c:1369
NUMAA * numaaCreate(l_int32 n)
numaaCreate()
Definition: numabasic.c:1302
l_ok numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:750
l_ok numaEmpty(NUMA *na)
numaEmpty()
Definition: numabasic.c:438
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:720
l_ok numaRemoveNumber(NUMA *na, l_int32 index)
numaRemoveNumber()
Definition: numabasic.c:572
l_ok numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1435
l_ok numaaWrite(const char *filename, NUMAA *naa)
numaaWrite()
Definition: numabasic.c:1852
NUMA * numaCreateFromFArray(l_float32 *farray, l_int32 size, l_int32 copyflag)
numaCreateFromFArray()
Definition: numabasic.c:266
l_ok numaWriteDebug(const char *filename, NUMA *na)
numaWriteDebug()
Definition: numabasic.c:1129
static const l_int32 InitialArraySize
Definition: numabasic.c:177
l_ok numaShiftValue(NUMA *na, l_int32 index, l_float32 diff)
numaShiftValue()
Definition: numabasic.c:773
NUMAA * numaaReadStream(FILE *fp)
numaaReadStream()
Definition: numabasic.c:1778
NUMA * numaCopy(NUMA *na)
numaCopy()
Definition: numabasic.c:387
static l_int32 numaExtendArray(NUMA *na)
numaExtendArray()
Definition: numabasic.c:491
l_ok numaWriteMem(l_uint8 **pdata, size_t *psize, NUMA *na)
numaWriteMem()
Definition: numabasic.c:1250
l_int32 * numaGetIArray(NUMA *na)
numaGetIArray()
Definition: numabasic.c:807
l_ok numaGetParameters(NUMA *na, l_float32 *pstartx, l_float32 *pdelx)
numaGetParameters()
Definition: numabasic.c:882
NUMA * numaCreateFromIArray(l_int32 *iarray, l_int32 size)
numaCreateFromIArray()
Definition: numabasic.c:231
void numaaDestroy(NUMAA **pnaa)
numaaDestroy()
Definition: numabasic.c:1401
l_ok numaCopyParameters(NUMA *nad, NUMA *nas)
numaCopyParameters()
Definition: numabasic.c:931
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:910
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:850
l_ok numaaReplaceNuma(NUMAA *naa, l_int32 index, NUMA *na)
numaaReplaceNuma()
Definition: numabasic.c:1651
l_ok numaWriteStream(FILE *fp, NUMA *na)
numaWriteStream()
Definition: numabasic.c:1178
static l_int32 numaaExtendArray(NUMAA *naa)
numaaExtendArray()
Definition: numabasic.c:1484
@ L_COPY
Definition: pix.h:505
@ L_CLONE
Definition: pix.h:506
@ L_NOCOPY
Definition: pix.h:503
@ L_INSERT
Definition: pix.h:504
SARRAY * sarrayCreate(l_int32 n)
sarrayCreate()
Definition: sarray1.c:169
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:673
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:617
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:353
l_ok sarrayAddString(SARRAY *sa, const char *string, l_int32 copyflag)
sarrayAddString()
Definition: sarray1.c:435
l_float32 startx
l_float32 delx
l_int32 nalloc
l_float32 * array
l_int32 n
l_atomic refcount
struct Numa ** numa
l_int32 n
l_int32 nalloc
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1358
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1937
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1905
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1262
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:1981
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1864