Leptonica  1.83.1
Image processing and image analysis suite
numafunc1.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 
144 #ifdef HAVE_CONFIG_H
145 #include <config_auto.h>
146 #endif /* HAVE_CONFIG_H */
147 
148 #include <math.h>
149 #include "allheaders.h"
150 #include "array_internal.h"
151 
152 /*----------------------------------------------------------------------*
153  * Arithmetic and logical ops on Numas *
154  *----------------------------------------------------------------------*/
173 NUMA *
175  NUMA *na1,
176  NUMA *na2,
177  l_int32 op)
178 {
179 l_int32 i, n;
180 l_float32 val1, val2;
181 
182  if (!na1 || !na2)
183  return (NUMA *)ERROR_PTR("na1, na2 not both defined", __func__, nad);
184  n = numaGetCount(na1);
185  if (n != numaGetCount(na2))
186  return (NUMA *)ERROR_PTR("na1, na2 sizes differ", __func__, nad);
187  if (nad && nad != na1)
188  return (NUMA *)ERROR_PTR("nad defined but not in-place", __func__, nad);
189  if (op != L_ARITH_ADD && op != L_ARITH_SUBTRACT &&
190  op != L_ARITH_MULTIPLY && op != L_ARITH_DIVIDE)
191  return (NUMA *)ERROR_PTR("invalid op", __func__, nad);
192  if (op == L_ARITH_DIVIDE) {
193  for (i = 0; i < n; i++) {
194  numaGetFValue(na2, i, &val2);
195  if (val2 == 0.0)
196  return (NUMA *)ERROR_PTR("na2 has 0 element", __func__, nad);
197  }
198  }
199 
200  /* If nad is not identical to na1, make it an identical copy */
201  if (!nad)
202  nad = numaCopy(na1);
203 
204  for (i = 0; i < n; i++) {
205  numaGetFValue(nad, i, &val1);
206  numaGetFValue(na2, i, &val2);
207  switch (op) {
208  case L_ARITH_ADD:
209  numaSetValue(nad, i, val1 + val2);
210  break;
211  case L_ARITH_SUBTRACT:
212  numaSetValue(nad, i, val1 - val2);
213  break;
214  case L_ARITH_MULTIPLY:
215  numaSetValue(nad, i, val1 * val2);
216  break;
217  case L_ARITH_DIVIDE:
218  numaSetValue(nad, i, val1 / val2);
219  break;
220  default:
221  lept_stderr(" Unknown arith op: %d\n", op);
222  return nad;
223  }
224  }
225 
226  return nad;
227 }
228 
229 
251 NUMA *
253  NUMA *na1,
254  NUMA *na2,
255  l_int32 op)
256 {
257 l_int32 i, n, val1, val2, val;
258 
259  if (!na1 || !na2)
260  return (NUMA *)ERROR_PTR("na1, na2 not both defined", __func__, nad);
261  n = numaGetCount(na1);
262  if (n != numaGetCount(na2))
263  return (NUMA *)ERROR_PTR("na1, na2 sizes differ", __func__, nad);
264  if (nad && nad != na1)
265  return (NUMA *)ERROR_PTR("nad defined; not in-place", __func__, nad);
266  if (op != L_UNION && op != L_INTERSECTION &&
267  op != L_SUBTRACTION && op != L_EXCLUSIVE_OR)
268  return (NUMA *)ERROR_PTR("invalid op", __func__, nad);
269 
270  /* If nad is not identical to na1, make it an identical copy */
271  if (!nad)
272  nad = numaCopy(na1);
273 
274  for (i = 0; i < n; i++) {
275  numaGetIValue(nad, i, &val1);
276  numaGetIValue(na2, i, &val2);
277  val1 = (val1 == 0) ? 0 : 1;
278  val2 = (val2 == 0) ? 0 : 1;
279  switch (op) {
280  case L_UNION:
281  val = (val1 || val2) ? 1 : 0;
282  numaSetValue(nad, i, val);
283  break;
284  case L_INTERSECTION:
285  val = (val1 && val2) ? 1 : 0;
286  numaSetValue(nad, i, val);
287  break;
288  case L_SUBTRACTION:
289  val = (val1 && !val2) ? 1 : 0;
290  numaSetValue(nad, i, val);
291  break;
292  case L_EXCLUSIVE_OR:
293  val = (val1 != val2) ? 1 : 0;
294  numaSetValue(nad, i, val);
295  break;
296  default:
297  lept_stderr(" Unknown logical op: %d\n", op);
298  return nad;
299  }
300  }
301 
302  return nad;
303 }
304 
305 
322 NUMA *
324  NUMA *nas)
325 {
326 l_int32 i, n, val;
327 
328  if (!nas)
329  return (NUMA *)ERROR_PTR("nas not defined", __func__, nad);
330  if (nad && nad != nas)
331  return (NUMA *)ERROR_PTR("nad defined; not in-place", __func__, nad);
332 
333  if (!nad)
334  nad = numaCopy(nas);
335  n = numaGetCount(nad);
336  for (i = 0; i < n; i++) {
337  numaGetIValue(nad, i, &val);
338  if (!val)
339  val = 1;
340  else
341  val = 0;
342  numaSetValue(nad, i, val);
343  }
344  return nad;
345 }
346 
347 
364 l_int32
366  NUMA *na2,
367  l_float32 maxdiff,
368  l_int32 *psimilar)
369 {
370 l_int32 i, n;
371 l_float32 val1, val2;
372 
373  if (!psimilar)
374  return ERROR_INT("&similar not defined", __func__, 1);
375  *psimilar = 0;
376  if (!na1 || !na2)
377  return ERROR_INT("na1 and na2 not both defined", __func__, 1);
378  maxdiff = L_ABS(maxdiff);
379 
380  n = numaGetCount(na1);
381  if (n != numaGetCount(na2)) return 0;
382 
383  for (i = 0; i < n; i++) {
384  numaGetFValue(na1, i, &val1);
385  numaGetFValue(na2, i, &val2);
386  if (L_ABS(val1 - val2) > maxdiff) return 0;
387  }
388 
389  *psimilar = 1;
390  return 0;
391 }
392 
393 
411 l_ok
413  l_int32 index,
414  l_float32 val)
415 {
416 l_int32 n;
417 
418  if (!na)
419  return ERROR_INT("na not defined", __func__, 1);
420  if ((n = numaGetCount(na)) == 0)
421  return ERROR_INT("na is empty", __func__, 1);
422  if (index < 0 || index >= n) {
423  L_ERROR("index %d not in [0,...,%d]\n", __func__, index, n - 1);
424  return 1;
425  }
426 
427  na->array[index] += val;
428  return 0;
429 }
430 
431 
432 /*----------------------------------------------------------------------*
433  * Simple extractions *
434  *----------------------------------------------------------------------*/
443 l_ok
445  l_float32 *pminval,
446  l_int32 *piminloc)
447 {
448 l_int32 i, n, iminloc;
449 l_float32 val, minval;
450 
451  if (!pminval && !piminloc)
452  return ERROR_INT("nothing to do", __func__, 1);
453  if (pminval) *pminval = 0.0;
454  if (piminloc) *piminloc = 0;
455  if (!na)
456  return ERROR_INT("na not defined", __func__, 1);
457  if ((n = numaGetCount(na)) == 0)
458  return ERROR_INT("na is empty", __func__, 1);
459 
460  minval = +1000000000.;
461  iminloc = 0;
462  for (i = 0; i < n; i++) {
463  numaGetFValue(na, i, &val);
464  if (val < minval) {
465  minval = val;
466  iminloc = i;
467  }
468  }
469 
470  if (pminval) *pminval = minval;
471  if (piminloc) *piminloc = iminloc;
472  return 0;
473 }
474 
475 
484 l_ok
486  l_float32 *pmaxval,
487  l_int32 *pimaxloc)
488 {
489 l_int32 i, n, imaxloc;
490 l_float32 val, maxval;
491 
492  if (!pmaxval && !pimaxloc)
493  return ERROR_INT("nothing to do", __func__, 1);
494  if (pmaxval) *pmaxval = 0.0;
495  if (pimaxloc) *pimaxloc = 0;
496  if (!na)
497  return ERROR_INT("na not defined", __func__, 1);
498  if ((n = numaGetCount(na)) == 0)
499  return ERROR_INT("na is empty", __func__, 1);
500 
501  maxval = -1000000000.;
502  imaxloc = 0;
503  for (i = 0; i < n; i++) {
504  numaGetFValue(na, i, &val);
505  if (val > maxval) {
506  maxval = val;
507  imaxloc = i;
508  }
509  }
510 
511  if (pmaxval) *pmaxval = maxval;
512  if (pimaxloc) *pimaxloc = imaxloc;
513  return 0;
514 }
515 
516 
524 l_ok
526  l_float32 *psum)
527 {
528 l_int32 i, n;
529 l_float32 val, sum;
530 
531  if (!psum)
532  return ERROR_INT("&sum not defined", __func__, 1);
533  *psum = 0;
534  if (!na)
535  return ERROR_INT("na not defined", __func__, 1);
536 
537  if ((n = numaGetCount(na)) == 0)
538  return ERROR_INT("na is empty", __func__, 1);
539  sum = 0.0;
540  for (i = 0; i < n; i++) {
541  numaGetFValue(na, i, &val);
542  sum += val;
543  }
544  *psum = sum;
545  return 0;
546 }
547 
548 
563 NUMA *
565 {
566 l_int32 i, n;
567 l_float32 val, sum;
568 NUMA *nasum;
569 
570  if (!na)
571  return (NUMA *)ERROR_PTR("na not defined", __func__, NULL);
572 
573  if ((n = numaGetCount(na)) == 0)
574  L_WARNING("na is empty\n", __func__);
575  nasum = numaCreate(n);
576  sum = 0.0;
577  for (i = 0; i < n; i++) {
578  numaGetFValue(na, i, &val);
579  sum += val;
580  numaAddNumber(nasum, sum);
581  }
582  return nasum;
583 }
584 
585 
595 l_ok
597  l_int32 first,
598  l_int32 last,
599  l_float32 *psum)
600 {
601 l_int32 i, n;
602 l_float32 val, sum;
603 
604  if (!psum)
605  return ERROR_INT("&sum not defined", __func__, 1);
606  *psum = 0.0;
607  if (!na)
608  return ERROR_INT("na not defined", __func__, 1);
609 
610  sum = 0.0;
611  if ((n = numaGetCount(na)) == 0)
612  return ERROR_INT("na is empty", __func__, 1);
613  if (first < 0) first = 0;
614  if (first >= n || last < -1) /* not an error */
615  return 0;
616  if (last == -1)
617  last = n - 1;
618  last = L_MIN(last, n - 1);
619 
620  for (i = first; i <= last; i++) {
621  numaGetFValue(na, i, &val);
622  sum += val;
623  }
624  *psum = sum;
625  return 0;
626 }
627 
628 
636 l_ok
638  l_int32 *pallints)
639 {
640 l_int32 i, n;
641 l_float32 val;
642 
643  if (!pallints)
644  return ERROR_INT("&allints not defined", __func__, 1);
645  *pallints = TRUE;
646  if (!na)
647  return ERROR_INT("na not defined", __func__, 1);
648 
649  if ((n = numaGetCount(na)) == 0)
650  return ERROR_INT("na is empty", __func__, 1);
651  for (i = 0; i < n; i ++) {
652  numaGetFValue(na, i, &val);
653  if (val != (l_int32)val) {
654  *pallints = FALSE;
655  return 0;
656  }
657  }
658  return 0;
659 }
660 
661 
669 l_ok
671  l_float32 *pave)
672 {
673 l_int32 n;
674 l_float32 sum;
675 
676  if (!pave)
677  return ERROR_INT("&ave not defined", __func__, 1);
678  *pave = 0;
679  if (!na)
680  return ERROR_INT("na not defined", __func__, 1);
681  if ((n = numaGetCount(na)) == 0)
682  return ERROR_INT("na is empty", __func__, 1);
683 
684  numaGetSum(na, &sum);
685  *pave = sum / n;
686  return 0;
687 }
688 
696 l_ok
698  l_float32 *paveabs)
699 {
700 l_int32 n;
701 NUMA *na1;
702 
703  if (!paveabs)
704  return ERROR_INT("&aveabs not defined", __func__, 1);
705  *paveabs = 0;
706  if (!na)
707  return ERROR_INT("na not defined", __func__, 1);
708  if ((n = numaGetCount(na)) == 0)
709  return ERROR_INT("na is empty", __func__, 1);
710 
711  na1 = numaMakeAbsval(NULL, na);
712  numaGetMean(na1, paveabs);
713  numaDestroy(&na1);
714  return 0;
715 }
716 
717 
725 NUMA *
727  l_int32 subfactor)
728 {
729 l_int32 i, n;
730 l_float32 val;
731 NUMA *nad;
732 
733  if (!nas)
734  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
735  if (subfactor < 1)
736  return (NUMA *)ERROR_PTR("subfactor < 1", __func__, NULL);
737 
738  nad = numaCreate(0);
739  if ((n = numaGetCount(nas)) == 0)
740  L_WARNING("nas is empty\n", __func__);
741  for (i = 0; i < n; i++) {
742  if (i % subfactor != 0) continue;
743  numaGetFValue(nas, i, &val);
744  numaAddNumber(nad, val);
745  }
746 
747  return nad;
748 }
749 
750 
758 NUMA *
760 {
761 l_int32 i, n;
762 l_float32 prev, cur;
763 NUMA *nad;
764 
765  if (!nas)
766  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
767  if ((n = numaGetCount(nas)) < 2) {
768  L_WARNING("n < 2; returning empty numa\n", __func__);
769  return numaCreate(1);
770  }
771 
772  nad = numaCreate(n - 1);
773  numaGetFValue(nas, 0, &prev);
774  for (i = 1; i < n; i++) {
775  numaGetFValue(nas, i, &cur);
776  numaAddNumber(nad, cur - prev);
777  prev = cur;
778  }
779  return nad;
780 }
781 
782 
791 NUMA *
792 numaMakeSequence(l_float32 startval,
793  l_float32 increment,
794  l_int32 size)
795 {
796 l_int32 i;
797 l_float32 val;
798 NUMA *na;
799 
800  if ((na = numaCreate(size)) == NULL)
801  return (NUMA *)ERROR_PTR("na not made", __func__, NULL);
802 
803  for (i = 0; i < size; i++) {
804  val = startval + i * increment;
805  numaAddNumber(na, val);
806  }
807  return na;
808 }
809 
810 
819 NUMA *
820 numaMakeConstant(l_float32 val,
821  l_int32 size)
822 {
823  return numaMakeSequence(val, 0.0, size);
824 }
825 
826 
835 NUMA *
837  NUMA *nas)
838 {
839 l_int32 i, n;
840 l_float32 val;
841 
842  if (!nas)
843  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
844  if (nad && nad != nas)
845  return (NUMA *)ERROR_PTR("nad and not in-place", __func__, NULL);
846 
847  if (!nad)
848  nad = numaCopy(nas);
849  n = numaGetCount(nad);
850  for (i = 0; i < n; i++) {
851  val = nad->array[i];
852  nad->array[i] = L_ABS(val);
853  }
854 
855  return nad;
856 }
857 
858 
868 NUMA *
870  l_int32 left,
871  l_int32 right,
872  l_float32 val)
873 {
874 l_int32 i, n, len;
875 l_float32 startx, delx;
876 l_float32 *fas, *fad;
877 NUMA *nad;
878 
879  if (!nas)
880  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
881  if (left < 0) left = 0;
882  if (right < 0) right = 0;
883  if (left == 0 && right == 0)
884  return numaCopy(nas);
885 
886  n = numaGetCount(nas);
887  len = n + left + right;
888  nad = numaMakeConstant(val, len);
889  numaGetParameters(nas, &startx, &delx);
890  numaSetParameters(nad, startx - delx * left, delx);
891  fas = numaGetFArray(nas, L_NOCOPY);
892  fad = numaGetFArray(nad, L_NOCOPY);
893  for (i = 0; i < n; i++)
894  fad[left + i] = fas[i];
895 
896  return nad;
897 }
898 
899 
909 NUMA *
911  l_int32 left,
912  l_int32 right,
913  l_int32 type)
914 {
915 l_int32 i, n;
916 l_float32 *fa;
917 NUMA *nad;
918 
919  if (!nas)
920  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
921  if (left < 0) left = 0;
922  if (right < 0) right = 0;
923  if (left == 0 && right == 0)
924  return numaCopy(nas);
925  if (type != L_CONTINUED_BORDER && type != L_MIRRORED_BORDER)
926  return (NUMA *)ERROR_PTR("invalid type", __func__, NULL);
927  n = numaGetCount(nas);
928  if (type == L_MIRRORED_BORDER && (left > n || right > n))
929  return (NUMA *)ERROR_PTR("border too large", __func__, NULL);
930 
931  nad = numaAddBorder(nas, left, right, 0);
932  n = numaGetCount(nad);
933  fa = numaGetFArray(nad, L_NOCOPY);
934  if (type == L_CONTINUED_BORDER) {
935  for (i = 0; i < left; i++)
936  fa[i] = fa[left];
937  for (i = n - right; i < n; i++)
938  fa[i] = fa[n - right - 1];
939  } else { /* type == L_MIRRORED_BORDER */
940  for (i = 0; i < left; i++)
941  fa[i] = fa[2 * left - 1 - i];
942  for (i = 0; i < right; i++)
943  fa[n - right + i] = fa[n - right - i - 1];
944  }
945 
946  return nad;
947 }
948 
949 
958 NUMA *
960  l_int32 left,
961  l_int32 right)
962 {
963 l_int32 i, n, len;
964 l_float32 startx, delx;
965 l_float32 *fas, *fad;
966 NUMA *nad;
967 
968  if (!nas)
969  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
970  if (left < 0) left = 0;
971  if (right < 0) right = 0;
972  if (left == 0 && right == 0)
973  return numaCopy(nas);
974 
975  n = numaGetCount(nas);
976  if ((len = n - left - right) < 0)
977  return (NUMA *)ERROR_PTR("len < 0 after removal", __func__, NULL);
978  nad = numaMakeConstant(0, len);
979  numaGetParameters(nas, &startx, &delx);
980  numaSetParameters(nad, startx + delx * left, delx);
981  fas = numaGetFArray(nas, L_NOCOPY);
982  fad = numaGetFArray(nad, L_NOCOPY);
983  for (i = 0; i < len; i++)
984  fad[i] = fas[left + i];
985 
986  return nad;
987 }
988 
989 
997 l_ok
999  l_int32 *pcount)
1000 {
1001 l_int32 n, i, val, count, inrun;
1002 
1003  if (!pcount)
1004  return ERROR_INT("&count not defined", __func__, 1);
1005  *pcount = 0;
1006  if (!na)
1007  return ERROR_INT("na not defined", __func__, 1);
1008  if ((n = numaGetCount(na)) == 0)
1009  return ERROR_INT("na is empty", __func__, 1);
1010 
1011  count = 0;
1012  inrun = FALSE;
1013  for (i = 0; i < n; i++) {
1014  numaGetIValue(na, i, &val);
1015  if (!inrun && val > 0) {
1016  count++;
1017  inrun = TRUE;
1018  } else if (inrun && val == 0) {
1019  inrun = FALSE;
1020  }
1021  }
1022  *pcount = count;
1023  return 0;
1024 }
1025 
1026 
1036 l_ok
1038  l_float32 eps,
1039  l_int32 *pfirst,
1040  l_int32 *plast)
1041 {
1042 l_int32 n, i, found;
1043 l_float32 val;
1044 
1045  if (pfirst) *pfirst = 0;
1046  if (plast) *plast = 0;
1047  if (!pfirst || !plast)
1048  return ERROR_INT("pfirst and plast not both defined", __func__, 1);
1049  if (!na)
1050  return ERROR_INT("na not defined", __func__, 1);
1051  if ((n = numaGetCount(na)) == 0)
1052  return ERROR_INT("na is empty", __func__, 1);
1053 
1054  found = FALSE;
1055  for (i = 0; i < n; i++) {
1056  numaGetFValue(na, i, &val);
1057  if (val > eps) {
1058  found = TRUE;
1059  break;
1060  }
1061  }
1062  if (!found) {
1063  *pfirst = n - 1;
1064  *plast = 0;
1065  return 1;
1066  }
1067 
1068  *pfirst = i;
1069  for (i = n - 1; i >= 0; i--) {
1070  numaGetFValue(na, i, &val);
1071  if (val > eps)
1072  break;
1073  }
1074  *plast = i;
1075  return 0;
1076 }
1077 
1078 
1087 l_ok
1089  l_int32 type,
1090  l_int32 *pcount)
1091 {
1092 l_int32 n, i, count;
1093 l_float32 val;
1094 
1095  if (!pcount)
1096  return ERROR_INT("&count not defined", __func__, 1);
1097  *pcount = 0;
1098  if (!na)
1099  return ERROR_INT("na not defined", __func__, 1);
1100  if ((n = numaGetCount(na)) == 0)
1101  return ERROR_INT("na is empty", __func__, 1);
1102 
1103  for (i = 0, count = 0; i < n; i++) {
1104  numaGetFValue(na, i, &val);
1105  if (type == L_LESS_THAN_ZERO && val < 0.0)
1106  count++;
1107  else if (type == L_EQUAL_TO_ZERO && val == 0.0)
1108  count++;
1109  else if (type == L_GREATER_THAN_ZERO && val > 0.0)
1110  count++;
1111  }
1112 
1113  *pcount = count;
1114  return 0;
1115 }
1116 
1117 
1136 NUMA *
1138  l_int32 first,
1139  l_int32 last)
1140 {
1141 l_int32 n, i;
1142 l_float32 val, startx, delx;
1143 NUMA *nad;
1144 
1145  if (!nas)
1146  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
1147  if ((n = numaGetCount(nas)) == 0)
1148  return (NUMA *)ERROR_PTR("nas is empty", __func__, NULL);
1149  if (first < 0 || first > last)
1150  return (NUMA *)ERROR_PTR("range not valid", __func__, NULL);
1151  if (first >= n)
1152  return (NUMA *)ERROR_PTR("no elements in range", __func__, NULL);
1153 
1154  last = L_MIN(last, n - 1);
1155  if ((nad = numaCreate(last - first + 1)) == NULL)
1156  return (NUMA *)ERROR_PTR("nad not made", __func__, NULL);
1157  for (i = first; i <= last; i++) {
1158  numaGetFValue(nas, i, &val);
1159  numaAddNumber(nad, val);
1160  }
1161  numaGetParameters(nas, &startx, &delx);
1162  numaSetParameters(nad, startx + first * delx, delx);
1163  return nad;
1164 }
1165 
1166 
1183 NUMA *
1185  l_float32 thresh,
1186  l_int32 type)
1187 {
1188 l_int32 n, i, ival;
1189 l_float32 fval;
1190 NUMA *nai;
1191 
1192  if (!nas)
1193  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
1194  if ((n = numaGetCount(nas)) == 0)
1195  return (NUMA *)ERROR_PTR("nas is empty", __func__, NULL);
1196 
1197  nai = numaCreate(n);
1198  for (i = 0; i < n; i++) {
1199  numaGetFValue(nas, i, &fval);
1200  ival = 0;
1201  switch (type)
1202  {
1203  case L_SELECT_IF_LT:
1204  if (fval < thresh) ival = 1;
1205  break;
1206  case L_SELECT_IF_GT:
1207  if (fval > thresh) ival = 1;
1208  break;
1209  case L_SELECT_IF_LTE:
1210  if (fval <= thresh) ival = 1;
1211  break;
1212  case L_SELECT_IF_GTE:
1213  if (fval >= thresh) ival = 1;
1214  break;
1215  default:
1216  numaDestroy(&nai);
1217  return (NUMA *)ERROR_PTR("invalid type", __func__, NULL);
1218  }
1219  numaAddNumber(nai, ival);
1220  }
1221 
1222  return nai;
1223 }
1224 
1225 
1239 NUMA *
1241  l_int32 nsamp)
1242 {
1243 l_int32 n, i, j, ileft, iright;
1244 l_float32 left, right, binsize, lfract, rfract, sum, startx, delx;
1245 l_float32 *array;
1246 NUMA *nad;
1247 
1248  if (!nas)
1249  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
1250  if ((n = numaGetCount(nas)) == 0)
1251  return (NUMA *)ERROR_PTR("nas is empty", __func__, NULL);
1252  if (nsamp <= 0)
1253  return (NUMA *)ERROR_PTR("nsamp must be > 0", __func__, NULL);
1254 
1255  nad = numaCreate(nsamp);
1256  array = numaGetFArray(nas, L_NOCOPY);
1257  binsize = (l_float32)n / (l_float32)nsamp;
1258  numaGetParameters(nas, &startx, &delx);
1259  numaSetParameters(nad, startx, binsize * delx);
1260  left = 0.0;
1261  for (i = 0; i < nsamp; i++) {
1262  sum = 0.0;
1263  right = left + binsize;
1264  ileft = (l_int32)left;
1265  lfract = 1.0 - left + ileft;
1266  if (lfract >= 1.0) /* on left bin boundary */
1267  lfract = 0.0;
1268  iright = (l_int32)right;
1269  rfract = right - iright;
1270  iright = L_MIN(iright, n - 1);
1271  if (ileft == iright) { /* both are within the same original sample */
1272  sum += (lfract + rfract - 1.0) * array[ileft];
1273  } else {
1274  if (lfract > 0.0001) /* left fraction */
1275  sum += lfract * array[ileft];
1276  if (rfract > 0.0001) /* right fraction */
1277  sum += rfract * array[iright];
1278  for (j = ileft + 1; j < iright; j++) /* entire pixels */
1279  sum += array[j];
1280  }
1281 
1282  numaAddNumber(nad, sum);
1283  left = right;
1284  }
1285  return nad;
1286 }
1287 
1288 
1303 NUMA *
1305  NUMA *nas)
1306 {
1307 l_int32 n, i;
1308 l_float32 val1, val2;
1309 
1310  if (!nas)
1311  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
1312  if (nad && nas != nad)
1313  return (NUMA *)ERROR_PTR("nad defined but != nas", __func__, NULL);
1314 
1315  n = numaGetCount(nas);
1316  if (nad) { /* in-place */
1317  for (i = 0; i < n / 2; i++) {
1318  numaGetFValue(nad, i, &val1);
1319  numaGetFValue(nad, n - i - 1, &val2);
1320  numaSetValue(nad, i, val2);
1321  numaSetValue(nad, n - i - 1, val1);
1322  }
1323  } else {
1324  nad = numaCreate(n);
1325  for (i = n - 1; i >= 0; i--) {
1326  numaGetFValue(nas, i, &val1);
1327  numaAddNumber(nad, val1);
1328  }
1329  }
1330 
1331  /* Reverse the startx and delx fields */
1332  nad->startx = nas->startx + (n - 1) * nas->delx;
1333  nad->delx = -nas->delx;
1334  return nad;
1335 }
1336 
1337 
1338 /*----------------------------------------------------------------------*
1339  * Signal feature extraction *
1340  *----------------------------------------------------------------------*/
1356 NUMA *
1358  l_float32 thresh,
1359  l_float32 maxn)
1360 {
1361 l_int32 n, i, inrun;
1362 l_float32 maxval, threshval, fval, startx, delx, x0, x1;
1363 NUMA *nad;
1364 
1365  if (!nas)
1366  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
1367  if ((n = numaGetCount(nas)) == 0)
1368  return (NUMA *)ERROR_PTR("nas is empty", __func__, NULL);
1369  if (thresh < 0.0 || thresh > 1.0)
1370  return (NUMA *)ERROR_PTR("invalid thresh", __func__, NULL);
1371 
1372  /* The input threshold is a fraction of the max.
1373  * The first entry in nad is the value of the max. */
1374  if (maxn == 0.0)
1375  numaGetMax(nas, &maxval, NULL);
1376  else
1377  maxval = maxn;
1378  numaGetParameters(nas, &startx, &delx);
1379  threshval = thresh * maxval;
1380  nad = numaCreate(0);
1381  numaAddNumber(nad, maxval);
1382 
1383  /* Write pairs of pts (x0, x1) for the intervals */
1384  inrun = FALSE;
1385  for (i = 0; i < n; i++) {
1386  numaGetFValue(nas, i, &fval);
1387  if (fval < threshval && inrun == FALSE) { /* start a new run */
1388  inrun = TRUE;
1389  x0 = startx + i * delx;
1390  } else if (fval > threshval && inrun == TRUE) { /* end the run */
1391  inrun = FALSE;
1392  x1 = startx + i * delx;
1393  numaAddNumber(nad, x0);
1394  numaAddNumber(nad, x1);
1395  }
1396  }
1397  if (inrun == TRUE) { /* must end the last run */
1398  x1 = startx + (n - 1) * delx;
1399  numaAddNumber(nad, x0);
1400  numaAddNumber(nad, x1);
1401  }
1402 
1403  return nad;
1404 }
1405 
1406 
1431 NUMA *
1433  l_float32 thresh1,
1434  l_float32 thresh2,
1435  l_float32 maxn)
1436 {
1437 l_int32 n, i, istart, inband, output, sign;
1438 l_int32 startbelow, below, above, belowlast, abovelast;
1439 l_float32 maxval, threshval1, threshval2, fval, startx, delx, x0, x1;
1440 NUMA *nad;
1441 
1442  if (!nas)
1443  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
1444  if ((n = numaGetCount(nas)) == 0)
1445  return (NUMA *)ERROR_PTR("nas is empty", __func__, NULL);
1446  if (thresh1 < 0.0 || thresh1 > 1.0 || thresh2 < 0.0 || thresh2 > 1.0)
1447  return (NUMA *)ERROR_PTR("invalid thresholds", __func__, NULL);
1448  if (thresh2 < thresh1)
1449  return (NUMA *)ERROR_PTR("thresh2 < thresh1", __func__, NULL);
1450 
1451  /* The input thresholds are fractions of the max.
1452  * The first entry in nad is the value of the max used
1453  * here for normalization. */
1454  if (maxn == 0.0)
1455  numaGetMax(nas, &maxval, NULL);
1456  else
1457  maxval = maxn;
1458  numaGetMax(nas, &maxval, NULL);
1459  numaGetParameters(nas, &startx, &delx);
1460  threshval1 = thresh1 * maxval;
1461  threshval2 = thresh2 * maxval;
1462  nad = numaCreate(0);
1463  numaAddNumber(nad, maxval);
1464 
1465  /* Write triplets of pts (x0, x1, sign) for the edges.
1466  * First make sure we start search from outside the band.
1467  * Only one of {belowlast, abovelast} is true. */
1468  for (i = 0; i < n; i++) {
1469  istart = i;
1470  numaGetFValue(nas, i, &fval);
1471  belowlast = (fval < threshval1) ? TRUE : FALSE;
1472  abovelast = (fval > threshval2) ? TRUE : FALSE;
1473  if (belowlast == TRUE || abovelast == TRUE)
1474  break;
1475  }
1476  if (istart == n) /* no intervals found */
1477  return nad;
1478 
1479  /* x0 and x1 can only be set from outside the edge.
1480  * They are the values just before entering the band,
1481  * and just after entering the band. We can jump through
1482  * the band, in which case they differ by one index in nas. */
1483  inband = FALSE;
1484  startbelow = belowlast; /* one of these is true */
1485  output = FALSE;
1486  x0 = startx + istart * delx;
1487  for (i = istart + 1; i < n; i++) {
1488  numaGetFValue(nas, i, &fval);
1489  below = (fval < threshval1) ? TRUE : FALSE;
1490  above = (fval > threshval2) ? TRUE : FALSE;
1491  if (!inband && belowlast && above) { /* full jump up */
1492  x1 = startx + i * delx;
1493  sign = 1;
1494  startbelow = FALSE; /* for the next transition */
1495  output = TRUE;
1496  } else if (!inband && abovelast && below) { /* full jump down */
1497  x1 = startx + i * delx;
1498  sign = -1;
1499  startbelow = TRUE; /* for the next transition */
1500  output = TRUE;
1501  } else if (inband && startbelow && above) { /* exit rising; success */
1502  x1 = startx + i * delx;
1503  sign = 1;
1504  inband = FALSE;
1505  startbelow = FALSE; /* for the next transition */
1506  output = TRUE;
1507  } else if (inband && !startbelow && below) {
1508  /* exit falling; success */
1509  x1 = startx + i * delx;
1510  sign = -1;
1511  inband = FALSE;
1512  startbelow = TRUE; /* for the next transition */
1513  output = TRUE;
1514  } else if (inband && !startbelow && above) { /* exit rising; failure */
1515  x0 = startx + i * delx;
1516  inband = FALSE;
1517  } else if (inband && startbelow && below) { /* exit falling; failure */
1518  x0 = startx + i * delx;
1519  inband = FALSE;
1520  } else if (!inband && !above && !below) { /* enter */
1521  inband = TRUE;
1522  startbelow = belowlast;
1523  } else if (!inband && (above || below)) { /* outside and remaining */
1524  x0 = startx + i * delx; /* update position */
1525  }
1526  belowlast = below;
1527  abovelast = above;
1528  if (output) { /* we have exited; save new x0 */
1529  numaAddNumber(nad, x0);
1530  numaAddNumber(nad, x1);
1531  numaAddNumber(nad, sign);
1532  output = FALSE;
1533  x0 = startx + i * delx;
1534  }
1535  }
1536 
1537  return nad;
1538 }
1539 
1540 
1550 l_int32
1552  l_int32 span,
1553  l_int32 *pstart,
1554  l_int32 *pend)
1555 {
1556 l_int32 n, nspans;
1557 
1558  if (!na)
1559  return ERROR_INT("na not defined", __func__, 1);
1560  if ((n = numaGetCount(na)) == 0)
1561  return ERROR_INT("na is empty", __func__, 1);
1562  if (n % 2 != 1)
1563  return ERROR_INT("n is not odd", __func__, 1);
1564  nspans = n / 2;
1565  if (nspans < 0 || span >= nspans)
1566  return ERROR_INT("invalid span", __func__, 1);
1567 
1568  if (pstart) numaGetIValue(na, 2 * span + 1, pstart);
1569  if (pend) numaGetIValue(na, 2 * span + 2, pend);
1570  return 0;
1571 }
1572 
1573 
1585 l_int32
1587  l_int32 edge,
1588  l_int32 *pstart,
1589  l_int32 *pend,
1590  l_int32 *psign)
1591 {
1592 l_int32 n, nedges;
1593 
1594  if (!na)
1595  return ERROR_INT("na not defined", __func__, 1);
1596  if ((n = numaGetCount(na)) == 0)
1597  return ERROR_INT("na is empty", __func__, 1);
1598  if (n % 3 != 1)
1599  return ERROR_INT("n % 3 is not 1", __func__, 1);
1600  nedges = (n - 1) / 3;
1601  if (edge < 0 || edge >= nedges)
1602  return ERROR_INT("invalid edge", __func__, 1);
1603 
1604  if (pstart) numaGetIValue(na, 3 * edge + 1, pstart);
1605  if (pend) numaGetIValue(na, 3 * edge + 2, pend);
1606  if (psign) numaGetIValue(na, 3 * edge + 3, psign);
1607  return 0;
1608 }
1609 
1610 
1611 /*----------------------------------------------------------------------*
1612  * Interpolation *
1613  *----------------------------------------------------------------------*/
1641 l_ok
1642 numaInterpolateEqxVal(l_float32 startx,
1643  l_float32 deltax,
1644  NUMA *nay,
1645  l_int32 type,
1646  l_float32 xval,
1647  l_float32 *pyval)
1648 {
1649 l_int32 i, n, i1, i2, i3;
1650 l_float32 x1, x2, x3, fy1, fy2, fy3, d1, d2, d3, del, fi, maxx;
1651 l_float32 *fa;
1652 
1653  if (!pyval)
1654  return ERROR_INT("&yval not defined", __func__, 1);
1655  *pyval = 0.0;
1656  if (!nay)
1657  return ERROR_INT("nay not defined", __func__, 1);
1658  if (deltax <= 0.0)
1659  return ERROR_INT("deltax not > 0", __func__, 1);
1660  if (type != L_LINEAR_INTERP && type != L_QUADRATIC_INTERP)
1661  return ERROR_INT("invalid interp type", __func__, 1);
1662  if ((n = numaGetCount(nay)) < 2)
1663  return ERROR_INT("not enough points", __func__, 1);
1664  if (type == L_QUADRATIC_INTERP && n == 2) {
1665  type = L_LINEAR_INTERP;
1666  L_WARNING("only 2 points; using linear interp\n", __func__);
1667  }
1668  maxx = startx + deltax * (n - 1);
1669  if (xval < startx || xval > maxx)
1670  return ERROR_INT("xval is out of bounds", __func__, 1);
1671 
1672  fa = numaGetFArray(nay, L_NOCOPY);
1673  fi = (xval - startx) / deltax;
1674  i = (l_int32)fi;
1675  del = fi - i;
1676  if (del == 0.0) { /* no interpolation required */
1677  *pyval = fa[i];
1678  return 0;
1679  }
1680 
1681  if (type == L_LINEAR_INTERP) {
1682  *pyval = fa[i] + del * (fa[i + 1] - fa[i]);
1683  return 0;
1684  }
1685 
1686  /* Quadratic interpolation */
1687  d1 = d3 = 0.5 / (deltax * deltax);
1688  d2 = -2. * d1;
1689  if (i == 0) {
1690  i1 = i;
1691  i2 = i + 1;
1692  i3 = i + 2;
1693  } else {
1694  i1 = i - 1;
1695  i2 = i;
1696  i3 = i + 1;
1697  }
1698  x1 = startx + i1 * deltax;
1699  x2 = startx + i2 * deltax;
1700  x3 = startx + i3 * deltax;
1701  fy1 = d1 * fa[i1];
1702  fy2 = d2 * fa[i2];
1703  fy3 = d3 * fa[i3];
1704  *pyval = fy1 * (xval - x2) * (xval - x3) +
1705  fy2 * (xval - x1) * (xval - x3) +
1706  fy3 * (xval - x1) * (xval - x2);
1707  return 0;
1708 }
1709 
1710 
1731 l_ok
1733  NUMA *nay,
1734  l_int32 type,
1735  l_float32 xval,
1736  l_float32 *pyval)
1737 {
1738 l_int32 i, im, nx, ny, i1, i2, i3;
1739 l_float32 delu, dell, fract, d1, d2, d3;
1740 l_float32 minx, maxx;
1741 l_float32 *fax, *fay;
1742 
1743  if (!pyval)
1744  return ERROR_INT("&yval not defined", __func__, 1);
1745  *pyval = 0.0;
1746  if (!nax)
1747  return ERROR_INT("nax not defined", __func__, 1);
1748  if (!nay)
1749  return ERROR_INT("nay not defined", __func__, 1);
1750  if (type != L_LINEAR_INTERP && type != L_QUADRATIC_INTERP)
1751  return ERROR_INT("invalid interp type", __func__, 1);
1752  ny = numaGetCount(nay);
1753  nx = numaGetCount(nax);
1754  if (nx != ny)
1755  return ERROR_INT("nax and nay not same size arrays", __func__, 1);
1756  if (ny < 2)
1757  return ERROR_INT("not enough points", __func__, 1);
1758  if (type == L_QUADRATIC_INTERP && ny == 2) {
1759  type = L_LINEAR_INTERP;
1760  L_WARNING("only 2 points; using linear interp\n", __func__);
1761  }
1762  numaGetFValue(nax, 0, &minx);
1763  numaGetFValue(nax, nx - 1, &maxx);
1764  if (xval < minx || xval > maxx)
1765  return ERROR_INT("xval is out of bounds", __func__, 1);
1766 
1767  fax = numaGetFArray(nax, L_NOCOPY);
1768  fay = numaGetFArray(nay, L_NOCOPY);
1769 
1770  /* Linear search for interval. We are guaranteed
1771  * to either return or break out of the loop.
1772  * In addition, we are assured that fax[i] - fax[im] > 0.0 */
1773  if (xval == fax[0]) {
1774  *pyval = fay[0];
1775  return 0;
1776  }
1777  im = 0;
1778  dell = 0.0;
1779  for (i = 1; i < nx; i++) {
1780  delu = fax[i] - xval;
1781  if (delu >= 0.0) { /* we've passed it */
1782  if (delu == 0.0) {
1783  *pyval = fay[i];
1784  return 0;
1785  }
1786  im = i - 1;
1787  dell = xval - fax[im]; /* >= 0 */
1788  break;
1789  }
1790  }
1791  fract = dell / (fax[i] - fax[im]);
1792 
1793  if (type == L_LINEAR_INTERP) {
1794  *pyval = fay[i] + fract * (fay[i + 1] - fay[i]);
1795  return 0;
1796  }
1797 
1798  /* Quadratic interpolation */
1799  if (im == 0) {
1800  i1 = im;
1801  i2 = im + 1;
1802  i3 = im + 2;
1803  } else {
1804  i1 = im - 1;
1805  i2 = im;
1806  i3 = im + 1;
1807  }
1808  d1 = (fax[i1] - fax[i2]) * (fax[i1] - fax[i3]);
1809  d2 = (fax[i2] - fax[i1]) * (fax[i2] - fax[i3]);
1810  d3 = (fax[i3] - fax[i1]) * (fax[i3] - fax[i2]);
1811  *pyval = fay[i1] * (xval - fax[i2]) * (xval - fax[i3]) / d1 +
1812  fay[i2] * (xval - fax[i1]) * (xval - fax[i3]) / d2 +
1813  fay[i3] * (xval - fax[i1]) * (xval - fax[i2]) / d3;
1814  return 0;
1815 }
1816 
1817 
1846 l_ok
1848  l_float32 deltax,
1849  NUMA *nasy,
1850  l_int32 type,
1851  l_float32 x0,
1852  l_float32 x1,
1853  l_int32 npts,
1854  NUMA **pnax,
1855  NUMA **pnay)
1856 {
1857 l_int32 i, n;
1858 l_float32 x, yval, maxx, delx;
1859 NUMA *nax, *nay;
1860 
1861  if (pnax) *pnax = NULL;
1862  if (!pnay)
1863  return ERROR_INT("&nay not defined", __func__, 1);
1864  *pnay = NULL;
1865  if (!nasy)
1866  return ERROR_INT("nasy not defined", __func__, 1);
1867  if ((n = numaGetCount(nasy)) < 2)
1868  return ERROR_INT("n < 2", __func__, 1);
1869  if (deltax <= 0.0)
1870  return ERROR_INT("deltax not > 0", __func__, 1);
1871  if (type != L_LINEAR_INTERP && type != L_QUADRATIC_INTERP)
1872  return ERROR_INT("invalid interp type", __func__, 1);
1873  if (type == L_QUADRATIC_INTERP && n == 2) {
1874  type = L_LINEAR_INTERP;
1875  L_WARNING("only 2 points; using linear interp\n", __func__);
1876  }
1877  maxx = startx + deltax * (n - 1);
1878  if (x0 < startx || x1 > maxx || x1 <= x0)
1879  return ERROR_INT("[x0 ... x1] is not valid", __func__, 1);
1880  if (npts < 3)
1881  return ERROR_INT("npts < 3", __func__, 1);
1882  delx = (x1 - x0) / (l_float32)(npts - 1); /* delx is for output nay */
1883 
1884  if ((nay = numaCreate(npts)) == NULL)
1885  return ERROR_INT("nay not made", __func__, 1);
1886  numaSetParameters(nay, x0, delx);
1887  *pnay = nay;
1888  if (pnax) {
1889  nax = numaCreate(npts);
1890  *pnax = nax;
1891  }
1892 
1893  for (i = 0; i < npts; i++) {
1894  x = x0 + i * delx;
1895  if (pnax)
1896  numaAddNumber(nax, x);
1897  numaInterpolateEqxVal(startx, deltax, nasy, type, x, &yval);
1898  numaAddNumber(nay, yval);
1899  }
1900 
1901  return 0;
1902 }
1903 
1904 
1933 l_ok
1935  NUMA *nay,
1936  l_int32 type,
1937  l_float32 x0,
1938  l_float32 x1,
1939  l_int32 npts,
1940  NUMA **pnadx,
1941  NUMA **pnady)
1942 {
1943 l_int32 i, im, j, nx, ny, i1, i2, i3, sorted;
1944 l_int32 *index;
1945 l_float32 del, xval, yval, excess, fract, minx, maxx, d1, d2, d3;
1946 l_float32 *fax, *fay;
1947 NUMA *nasx, *nasy, *nadx, *nady;
1948 
1949  if (pnadx) *pnadx = NULL;
1950  if (!pnady)
1951  return ERROR_INT("&nady not defined", __func__, 1);
1952  *pnady = NULL;
1953  if (!nay)
1954  return ERROR_INT("nay not defined", __func__, 1);
1955  if (!nax)
1956  return ERROR_INT("nax not defined", __func__, 1);
1957  if (type != L_LINEAR_INTERP && type != L_QUADRATIC_INTERP)
1958  return ERROR_INT("invalid interp type", __func__, 1);
1959  if (x0 > x1)
1960  return ERROR_INT("x0 > x1", __func__, 1);
1961  ny = numaGetCount(nay);
1962  nx = numaGetCount(nax);
1963  if (nx != ny)
1964  return ERROR_INT("nax and nay not same size arrays", __func__, 1);
1965  if (ny < 2)
1966  return ERROR_INT("not enough points", __func__, 1);
1967  if (type == L_QUADRATIC_INTERP && ny == 2) {
1968  type = L_LINEAR_INTERP;
1969  L_WARNING("only 2 points; using linear interp\n", __func__);
1970  }
1971  numaGetMin(nax, &minx, NULL);
1972  numaGetMax(nax, &maxx, NULL);
1973  if (x0 < minx || x1 > maxx)
1974  return ERROR_INT("xval is out of bounds", __func__, 1);
1975 
1976  /* Make sure that nax is sorted in increasing order */
1977  numaIsSorted(nax, L_SORT_INCREASING, &sorted);
1978  if (!sorted) {
1979  L_WARNING("we are sorting nax in increasing order\n", __func__);
1980  numaSortPair(nax, nay, L_SORT_INCREASING, &nasx, &nasy);
1981  } else {
1982  nasx = numaClone(nax);
1983  nasy = numaClone(nay);
1984  }
1985 
1986  fax = numaGetFArray(nasx, L_NOCOPY);
1987  fay = numaGetFArray(nasy, L_NOCOPY);
1988 
1989  /* Get array of indices into fax for interpolated locations */
1990  if ((index = (l_int32 *)LEPT_CALLOC(npts, sizeof(l_int32))) == NULL) {
1991  numaDestroy(&nasx);
1992  numaDestroy(&nasy);
1993  return ERROR_INT("ind not made", __func__, 1);
1994  }
1995  del = (x1 - x0) / (npts - 1.0);
1996  for (i = 0, j = 0; j < nx && i < npts; i++) {
1997  xval = x0 + i * del;
1998  while (j < nx - 1 && xval > fax[j])
1999  j++;
2000  if (xval == fax[j])
2001  index[i] = L_MIN(j, nx - 1);
2002  else /* the index of fax[] is just below xval */
2003  index[i] = L_MAX(j - 1, 0);
2004  }
2005 
2006  /* For each point to be interpolated, get the y value */
2007  nady = numaCreate(npts);
2008  *pnady = nady;
2009  if (pnadx) {
2010  nadx = numaCreate(npts);
2011  *pnadx = nadx;
2012  }
2013  for (i = 0; i < npts; i++) {
2014  xval = x0 + i * del;
2015  if (pnadx)
2016  numaAddNumber(nadx, xval);
2017  im = index[i];
2018  excess = xval - fax[im];
2019  if (excess == 0.0) {
2020  numaAddNumber(nady, fay[im]);
2021  continue;
2022  }
2023  fract = excess / (fax[im + 1] - fax[im]);
2024 
2025  if (type == L_LINEAR_INTERP) {
2026  yval = fay[im] + fract * (fay[im + 1] - fay[im]);
2027  numaAddNumber(nady, yval);
2028  continue;
2029  }
2030 
2031  /* Quadratic interpolation */
2032  if (im == 0) {
2033  i1 = im;
2034  i2 = im + 1;
2035  i3 = im + 2;
2036  } else {
2037  i1 = im - 1;
2038  i2 = im;
2039  i3 = im + 1;
2040  }
2041  d1 = (fax[i1] - fax[i2]) * (fax[i1] - fax[i3]);
2042  d2 = (fax[i2] - fax[i1]) * (fax[i2] - fax[i3]);
2043  d3 = (fax[i3] - fax[i1]) * (fax[i3] - fax[i2]);
2044  yval = fay[i1] * (xval - fax[i2]) * (xval - fax[i3]) / d1 +
2045  fay[i2] * (xval - fax[i1]) * (xval - fax[i3]) / d2 +
2046  fay[i3] * (xval - fax[i1]) * (xval - fax[i2]) / d3;
2047  numaAddNumber(nady, yval);
2048  }
2049 
2050  LEPT_FREE(index);
2051  numaDestroy(&nasx);
2052  numaDestroy(&nasy);
2053  return 0;
2054 }
2055 
2056 
2057 /*----------------------------------------------------------------------*
2058  * Functions requiring interpolation *
2059  *----------------------------------------------------------------------*/
2092 l_ok
2094  l_float32 *pmaxval,
2095  NUMA *naloc,
2096  l_float32 *pmaxloc)
2097 {
2098 l_float32 val;
2099 l_float32 smaxval; /* start value of maximum sample, before interpolating */
2100 l_int32 n, imaxloc;
2101 l_float32 x1, x2, x3, y1, y2, y3, c1, c2, c3, a, b, xmax, ymax;
2102 
2103  if (pmaxval) *pmaxval = 0.0;
2104  if (pmaxloc) *pmaxloc = 0.0;
2105  if (!na)
2106  return ERROR_INT("na not defined", __func__, 1);
2107  if ((n = numaGetCount(na)) == 0)
2108  return ERROR_INT("na is empty", __func__, 1);
2109  if (!pmaxval)
2110  return ERROR_INT("&maxval not defined", __func__, 1);
2111  if (!pmaxloc)
2112  return ERROR_INT("&maxloc not defined", __func__, 1);
2113  if (naloc) {
2114  if (n != numaGetCount(naloc))
2115  return ERROR_INT("na and naloc of unequal size", __func__, 1);
2116  }
2117 
2118  numaGetMax(na, &smaxval, &imaxloc);
2119 
2120  /* Simple case: max is at end point */
2121  if (imaxloc == 0 || imaxloc == n - 1) {
2122  *pmaxval = smaxval;
2123  if (naloc) {
2124  numaGetFValue(naloc, imaxloc, &val);
2125  *pmaxloc = val;
2126  } else {
2127  *pmaxloc = imaxloc;
2128  }
2129  return 0;
2130  }
2131 
2132  /* Interior point; use quadratic interpolation */
2133  y2 = smaxval;
2134  numaGetFValue(na, imaxloc - 1, &val);
2135  y1 = val;
2136  numaGetFValue(na, imaxloc + 1, &val);
2137  y3 = val;
2138  if (naloc) {
2139  numaGetFValue(naloc, imaxloc - 1, &val);
2140  x1 = val;
2141  numaGetFValue(naloc, imaxloc, &val);
2142  x2 = val;
2143  numaGetFValue(naloc, imaxloc + 1, &val);
2144  x3 = val;
2145  } else {
2146  x1 = imaxloc - 1;
2147  x2 = imaxloc;
2148  x3 = imaxloc + 1;
2149  }
2150 
2151  /* Can't interpolate; just use the max val in na
2152  * and the corresponding one in naloc */
2153  if (x1 == x2 || x1 == x3 || x2 == x3) {
2154  *pmaxval = y2;
2155  *pmaxloc = x2;
2156  return 0;
2157  }
2158 
2159  /* Use lagrangian interpolation; set dy/dx = 0 */
2160  c1 = y1 / ((x1 - x2) * (x1 - x3));
2161  c2 = y2 / ((x2 - x1) * (x2 - x3));
2162  c3 = y3 / ((x3 - x1) * (x3 - x2));
2163  a = c1 + c2 + c3;
2164  b = c1 * (x2 + x3) + c2 * (x1 + x3) + c3 * (x1 + x2);
2165  xmax = b / (2 * a);
2166  ymax = c1 * (xmax - x2) * (xmax - x3) +
2167  c2 * (xmax - x1) * (xmax - x3) +
2168  c3 * (xmax - x1) * (xmax - x2);
2169  *pmaxval = ymax;
2170  *pmaxloc = xmax;
2171 
2172  return 0;
2173 }
2174 
2175 
2196 l_ok
2198  NUMA *nay,
2199  l_float32 x0,
2200  l_float32 x1,
2201  l_int32 npts,
2202  NUMA **pnadx,
2203  NUMA **pnady)
2204 {
2205 l_int32 i, nx, ny;
2206 l_float32 minx, maxx, der, invdel;
2207 l_float32 *fay;
2208 NUMA *nady, *naiy;
2209 
2210  if (pnadx) *pnadx = NULL;
2211  if (!pnady)
2212  return ERROR_INT("&nady not defined", __func__, 1);
2213  *pnady = NULL;
2214  if (!nay)
2215  return ERROR_INT("nay not defined", __func__, 1);
2216  if (!nax)
2217  return ERROR_INT("nax not defined", __func__, 1);
2218  if (x0 > x1)
2219  return ERROR_INT("x0 > x1", __func__, 1);
2220  ny = numaGetCount(nay);
2221  nx = numaGetCount(nax);
2222  if (nx != ny)
2223  return ERROR_INT("nax and nay not same size arrays", __func__, 1);
2224  if (ny < 2)
2225  return ERROR_INT("not enough points", __func__, 1);
2226  numaGetMin(nax, &minx, NULL);
2227  numaGetMax(nax, &maxx, NULL);
2228  if (x0 < minx || x1 > maxx)
2229  return ERROR_INT("xval is out of bounds", __func__, 1);
2230  if (npts < 2)
2231  return ERROR_INT("npts < 2", __func__, 1);
2232 
2233  /* Generate interpolated array over specified interval */
2234  if (numaInterpolateArbxInterval(nax, nay, L_LINEAR_INTERP, x0, x1,
2235  npts, pnadx, &naiy))
2236  return ERROR_INT("interpolation failed", __func__, 1);
2237 
2238  nady = numaCreate(npts);
2239  *pnady = nady;
2240  invdel = 0.5 * ((l_float32)npts - 1.0) / (x1 - x0);
2241  fay = numaGetFArray(naiy, L_NOCOPY);
2242 
2243  /* Compute and save derivatives */
2244  der = 0.5 * invdel * (fay[1] - fay[0]);
2245  numaAddNumber(nady, der);
2246  for (i = 1; i < npts - 1; i++) {
2247  der = invdel * (fay[i + 1] - fay[i - 1]);
2248  numaAddNumber(nady, der);
2249  }
2250  der = 0.5 * invdel * (fay[npts - 1] - fay[npts - 2]);
2251  numaAddNumber(nady, der);
2252 
2253  numaDestroy(&naiy);
2254  return 0;
2255 }
2256 
2257 
2277 l_ok
2279  NUMA *nay,
2280  l_float32 x0,
2281  l_float32 x1,
2282  l_int32 npts,
2283  l_float32 *psum)
2284 {
2285 l_int32 i, nx, ny;
2286 l_float32 minx, maxx, sum, del;
2287 l_float32 *fay;
2288 NUMA *naiy;
2289 
2290  if (!psum)
2291  return ERROR_INT("&sum not defined", __func__, 1);
2292  *psum = 0.0;
2293  if (!nay)
2294  return ERROR_INT("nay not defined", __func__, 1);
2295  if (!nax)
2296  return ERROR_INT("nax not defined", __func__, 1);
2297  if (x0 > x1)
2298  return ERROR_INT("x0 > x1", __func__, 1);
2299  if (npts < 2)
2300  return ERROR_INT("npts < 2", __func__, 1);
2301  ny = numaGetCount(nay);
2302  nx = numaGetCount(nax);
2303  if (nx != ny)
2304  return ERROR_INT("nax and nay not same size arrays", __func__, 1);
2305  if (ny < 2)
2306  return ERROR_INT("not enough points", __func__, 1);
2307  numaGetMin(nax, &minx, NULL);
2308  numaGetMax(nax, &maxx, NULL);
2309  if (x0 < minx || x1 > maxx)
2310  return ERROR_INT("xval is out of bounds", __func__, 1);
2311 
2312  /* Generate interpolated array over specified interval */
2313  if (numaInterpolateArbxInterval(nax, nay, L_LINEAR_INTERP, x0, x1,
2314  npts, NULL, &naiy))
2315  return ERROR_INT("interpolation failed", __func__, 1);
2316 
2317  del = (x1 - x0) / ((l_float32)npts - 1.0);
2318  fay = numaGetFArray(naiy, L_NOCOPY);
2319 
2320  /* Compute integral (simple trapezoid) */
2321  sum = 0.5 * (fay[0] + fay[npts - 1]);
2322  for (i = 1; i < npts - 1; i++)
2323  sum += fay[i];
2324  *psum = del * sum;
2325 
2326  numaDestroy(&naiy);
2327  return 0;
2328 }
2329 
2330 
2331 /*----------------------------------------------------------------------*
2332  * Sorting *
2333  *----------------------------------------------------------------------*/
2380 l_ok
2382  NUMA **pnasort,
2383  NUMA **pnaindex,
2384  NUMA **pnainvert,
2385  l_int32 sortorder,
2386  l_int32 sorttype)
2387 {
2388 l_int32 isize;
2389 l_float32 size;
2390 NUMA *naindex = NULL;
2391 
2392  if (pnasort) *pnasort = NULL;
2393  if (pnaindex) *pnaindex = NULL;
2394  if (pnainvert) *pnainvert = NULL;
2395  if (!na)
2396  return ERROR_INT("na not defined", __func__, 1);
2397  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
2398  return ERROR_INT("invalid sort order", __func__, 1);
2399  if (sorttype != L_SHELL_SORT && sorttype != L_BIN_SORT)
2400  return ERROR_INT("invalid sort type", __func__, 1);
2401  if (!pnasort && !pnaindex && !pnainvert)
2402  return ERROR_INT("nothing to do", __func__, 1);
2403 
2404  if (sorttype == L_BIN_SORT) {
2405  numaGetMax(na, &size, NULL);
2406  isize = (l_int32)size;
2407  if (isize > MaxInitPtraSize - 1) {
2408  L_WARNING("array too large; using shell sort\n", __func__);
2409  sorttype = L_SHELL_SORT;
2410  } else {
2411  naindex = numaGetBinSortIndex(na, sortorder);
2412  }
2413  }
2414 
2415  if (sorttype == L_SHELL_SORT)
2416  naindex = numaGetSortIndex(na, sortorder);
2417 
2418  if (pnasort)
2419  *pnasort = numaSortByIndex(na, naindex);
2420  if (pnainvert)
2421  *pnainvert = numaInvertMap(naindex);
2422  if (pnaindex)
2423  *pnaindex = naindex;
2424  else
2425  numaDestroy(&naindex);
2426  return 0;
2427 }
2428 
2429 
2443 NUMA *
2445  l_int32 sortorder)
2446 {
2447 l_int32 type;
2448 
2449  if (!nas)
2450  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
2451  if (numaGetCount(nas) == 0) {
2452  L_WARNING("nas is empty; returning copy\n", __func__);
2453  return numaCopy(nas);
2454  }
2455  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
2456  return (NUMA *)ERROR_PTR("invalid sort order", __func__, NULL);
2457 
2458  type = numaChooseSortType(nas);
2459  if (type != L_SHELL_SORT && type != L_BIN_SORT)
2460  return (NUMA *)ERROR_PTR("invalid sort type", __func__, NULL);
2461 
2462  if (type == L_BIN_SORT)
2463  return numaBinSort(nas, sortorder);
2464  else /* shell sort */
2465  return numaSort(NULL, nas, sortorder);
2466 }
2467 
2468 
2482 NUMA *
2484  l_int32 sortorder)
2485 {
2486 l_int32 type;
2487 
2488  if (!nas)
2489  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
2490  if (numaGetCount(nas) == 0) {
2491  L_WARNING("nas is empty; returning copy\n", __func__);
2492  return numaCopy(nas);
2493  }
2494  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
2495  return (NUMA *)ERROR_PTR("invalid sort order", __func__, NULL);
2496  type = numaChooseSortType(nas);
2497  if (type != L_SHELL_SORT && type != L_BIN_SORT)
2498  return (NUMA *)ERROR_PTR("invalid sort type", __func__, NULL);
2499 
2500  if (type == L_BIN_SORT)
2501  return numaGetBinSortIndex(nas, sortorder);
2502  else /* shell sort */
2503  return numaGetSortIndex(nas, sortorder);
2504 }
2505 
2506 
2520 l_int32
2522 {
2523 l_int32 n;
2524 l_float32 minval, maxval;
2525 
2526  if (!nas)
2527  return ERROR_INT("nas not defined", __func__, UNDEF);
2528 
2529  /* If small histogram or negative values; use shell sort */
2530  numaGetMin(nas, &minval, NULL);
2531  n = numaGetCount(nas);
2532  if (minval < 0.0 || n < 200)
2533  return L_SHELL_SORT;
2534 
2535  /* If large maxval, use shell sort */
2536  numaGetMax(nas, &maxval, NULL);
2537  if (maxval > MaxInitPtraSize - 1)
2538  return L_SHELL_SORT;
2539 
2540  /* Otherwise, need to compare nlog(n) with maxval.
2541  * The factor of 0.003 was determined by comparing times for
2542  * different histogram sizes and maxval. It is very small
2543  * because binsort is fast and shell sort gets slow for large n. */
2544  if (n * log((l_float32)n) < 0.003 * maxval)
2545  return L_SHELL_SORT;
2546  else
2547  return L_BIN_SORT;
2548 }
2549 
2550 
2566 NUMA *
2568  NUMA *nain,
2569  l_int32 sortorder)
2570 {
2571 l_int32 i, n, gap, j;
2572 l_float32 tmp;
2573 l_float32 *array;
2574 
2575  if (!nain)
2576  return (NUMA *)ERROR_PTR("nain not defined", __func__, NULL);
2577  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
2578  return (NUMA *)ERROR_PTR("invalid sort order", __func__, NULL);
2579 
2580  /* Make naout if necessary; otherwise do in-place */
2581  if (!naout)
2582  naout = numaCopy(nain);
2583  else if (nain != naout)
2584  return (NUMA *)ERROR_PTR("invalid: not in-place", __func__, NULL);
2585  if ((n = numaGetCount(naout)) == 0) {
2586  L_WARNING("naout is empty\n", __func__);
2587  return naout;
2588  }
2589  array = naout->array; /* operate directly on the array */
2590  n = numaGetCount(naout);
2591 
2592  /* Shell sort */
2593  for (gap = n/2; gap > 0; gap = gap / 2) {
2594  for (i = gap; i < n; i++) {
2595  for (j = i - gap; j >= 0; j -= gap) {
2596  if ((sortorder == L_SORT_INCREASING &&
2597  array[j] > array[j + gap]) ||
2598  (sortorder == L_SORT_DECREASING &&
2599  array[j] < array[j + gap]))
2600  {
2601  tmp = array[j];
2602  array[j] = array[j + gap];
2603  array[j + gap] = tmp;
2604  }
2605  }
2606  }
2607  }
2608 
2609  return naout;
2610 }
2611 
2612 
2632 NUMA *
2634  l_int32 sortorder)
2635 {
2636 NUMA *nat, *nad;
2637 
2638  if (!nas)
2639  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
2640  if (numaGetCount(nas) == 0) {
2641  L_WARNING("nas is empty; returning copy\n", __func__);
2642  return numaCopy(nas);
2643  }
2644  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
2645  return (NUMA *)ERROR_PTR("invalid sort order", __func__, NULL);
2646 
2647  if ((nat = numaGetBinSortIndex(nas, sortorder)) == NULL)
2648  return (NUMA *)ERROR_PTR("bin sort failed", __func__, NULL);
2649  nad = numaSortByIndex(nas, nat);
2650  numaDestroy(&nat);
2651  return nad;
2652 }
2653 
2654 
2663 NUMA *
2665  l_int32 sortorder)
2666 {
2667 l_int32 i, n, gap, j;
2668 l_float32 tmp;
2669 l_float32 *array; /* copy of input array */
2670 l_float32 *iarray; /* array of indices */
2671 NUMA *naisort;
2672 
2673  if (!na)
2674  return (NUMA *)ERROR_PTR("na not defined", __func__, NULL);
2675  if (numaGetCount(na) == 0) {
2676  L_WARNING("na is empty\n", __func__);
2677  return numaCreate(1);
2678  }
2679  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
2680  return (NUMA *)ERROR_PTR("invalid sortorder", __func__, NULL);
2681 
2682  n = numaGetCount(na);
2683  if ((array = numaGetFArray(na, L_COPY)) == NULL)
2684  return (NUMA *)ERROR_PTR("array not made", __func__, NULL);
2685  if ((iarray = (l_float32 *)LEPT_CALLOC(n, sizeof(l_float32))) == NULL) {
2686  LEPT_FREE(array);
2687  return (NUMA *)ERROR_PTR("iarray not made", __func__, NULL);
2688  }
2689  for (i = 0; i < n; i++)
2690  iarray[i] = i;
2691 
2692  /* Shell sort */
2693  for (gap = n/2; gap > 0; gap = gap / 2) {
2694  for (i = gap; i < n; i++) {
2695  for (j = i - gap; j >= 0; j -= gap) {
2696  if ((sortorder == L_SORT_INCREASING &&
2697  array[j] > array[j + gap]) ||
2698  (sortorder == L_SORT_DECREASING &&
2699  array[j] < array[j + gap]))
2700  {
2701  tmp = array[j];
2702  array[j] = array[j + gap];
2703  array[j + gap] = tmp;
2704  tmp = iarray[j];
2705  iarray[j] = iarray[j + gap];
2706  iarray[j + gap] = tmp;
2707  }
2708  }
2709  }
2710  }
2711 
2712  naisort = numaCreate(n);
2713  for (i = 0; i < n; i++)
2714  numaAddNumber(naisort, iarray[i]);
2715 
2716  LEPT_FREE(array);
2717  LEPT_FREE(iarray);
2718  return naisort;
2719 }
2720 
2721 
2743 NUMA *
2745  l_int32 sortorder)
2746 {
2747 l_int32 i, n, isize, ival, imax;
2748 l_float32 minsize, size;
2749 NUMA *na, *nai, *nad;
2750 L_PTRA *paindex;
2751 
2752  if (!nas)
2753  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
2754  if (numaGetCount(nas) == 0) {
2755  L_WARNING("nas is empty\n", __func__);
2756  return numaCreate(1);
2757  }
2758  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
2759  return (NUMA *)ERROR_PTR("invalid sort order", __func__, NULL);
2760  numaGetMin(nas, &minsize, NULL);
2761  if (minsize < 0)
2762  return (NUMA *)ERROR_PTR("nas has negative numbers", __func__, NULL);
2763  numaGetMax(nas, &size, NULL);
2764  isize = (l_int32)size;
2765  if (isize > MaxInitPtraSize - 1) {
2766  L_ERROR("array too large: %d elements > max size = %d\n",
2767  __func__, isize, MaxInitPtraSize - 1);
2768  return NULL;
2769  }
2770 
2771  /* Set up a ptra holding numa at indices for which there
2772  * are values in nas. Suppose nas has the value 230 at index
2773  * 7355. A numa holding the index 7355 is created and stored
2774  * at the ptra index 230. If there is another value of 230
2775  * in nas, its index is added to the same numa (at index 230
2776  * in the ptra). When finished, the ptra can be scanned for numa,
2777  * and the original indices in the nas can be read out. In this
2778  * way, the ptra effectively sorts the input numbers in the nas. */
2779  paindex = ptraCreate(isize + 1);
2780  n = numaGetCount(nas);
2781  for (i = 0; i < n; i++) {
2782  numaGetIValue(nas, i, &ival);
2783  nai = (NUMA *)ptraGetPtrToItem(paindex, ival);
2784  if (!nai) { /* make it; no shifting will occur */
2785  nai = numaCreate(1);
2786  ptraInsert(paindex, ival, nai, L_MIN_DOWNSHIFT);
2787  }
2788  numaAddNumber(nai, i);
2789  }
2790 
2791  /* Sort by scanning the ptra, extracting numas and pulling
2792  * the (index into nas) numbers out of each numa, taken
2793  * successively in requested order. */
2794  ptraGetMaxIndex(paindex, &imax);
2795  nad = numaCreate(0);
2796  if (sortorder == L_SORT_INCREASING) {
2797  for (i = 0; i <= imax; i++) {
2798  na = (NUMA *)ptraRemove(paindex, i, L_NO_COMPACTION);
2799  if (!na) continue;
2800  numaJoin(nad, na, 0, -1);
2801  numaDestroy(&na);
2802  }
2803  } else { /* L_SORT_DECREASING */
2804  for (i = imax; i >= 0; i--) {
2805  na = (NUMA *)ptraRemoveLast(paindex);
2806  if (!na) break; /* they've all been removed */
2807  numaJoin(nad, na, 0, -1);
2808  numaDestroy(&na);
2809  }
2810  }
2811 
2812  ptraDestroy(&paindex, FALSE, FALSE);
2813  return nad;
2814 }
2815 
2816 
2824 NUMA *
2826  NUMA *naindex)
2827 {
2828 l_int32 i, n, ni, index;
2829 l_float32 val;
2830 NUMA *nad;
2831 
2832  if (!nas)
2833  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
2834  if (!naindex)
2835  return (NUMA *)ERROR_PTR("naindex not defined", __func__, NULL);
2836  n = numaGetCount(nas);
2837  ni = numaGetCount(naindex);
2838  if (n != ni)
2839  return (NUMA *)ERROR_PTR("numa sizes differ", __func__, NULL);
2840  if (n == 0) {
2841  L_WARNING("nas is empty\n", __func__);
2842  return numaCopy(nas);
2843  }
2844 
2845  nad = numaCreate(n);
2846  for (i = 0; i < n; i++) {
2847  numaGetIValue(naindex, i, &index);
2848  numaGetFValue(nas, index, &val);
2849  numaAddNumber(nad, val);
2850  }
2851 
2852  return nad;
2853 }
2854 
2855 
2871 l_int32
2873  l_int32 sortorder,
2874  l_int32 *psorted)
2875 {
2876 l_int32 i, n;
2877 l_float32 prevval, val;
2878 
2879  if (!psorted)
2880  return ERROR_INT("&sorted not defined", __func__, 1);
2881  *psorted = FALSE;
2882  if (!nas)
2883  return ERROR_INT("nas not defined", __func__, 1);
2884  if ((n = numaGetCount(nas))== 0) {
2885  L_WARNING("nas is empty\n", __func__);
2886  *psorted = TRUE;
2887  return 0;
2888  }
2889  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
2890  return ERROR_INT("invalid sortorder", __func__, 1);
2891 
2892  n = numaGetCount(nas);
2893  numaGetFValue(nas, 0, &prevval);
2894  for (i = 1; i < n; i++) {
2895  numaGetFValue(nas, i, &val);
2896  if ((sortorder == L_SORT_INCREASING && val < prevval) ||
2897  (sortorder == L_SORT_DECREASING && val > prevval))
2898  return 0;
2899  }
2900 
2901  *psorted = TRUE;
2902  return 0;
2903 }
2904 
2905 
2921 l_ok
2923  NUMA *nay,
2924  l_int32 sortorder,
2925  NUMA **pnasx,
2926  NUMA **pnasy)
2927 {
2928 l_int32 sorted;
2929 NUMA *naindex;
2930 
2931  if (pnasx) *pnasx = NULL;
2932  if (pnasy) *pnasy = NULL;
2933  if (!pnasx || !pnasy)
2934  return ERROR_INT("&nasx and/or &nasy not defined", __func__, 1);
2935  if (!nax)
2936  return ERROR_INT("nax not defined", __func__, 1);
2937  if (!nay)
2938  return ERROR_INT("nay not defined", __func__, 1);
2939  if (sortorder != L_SORT_INCREASING && sortorder != L_SORT_DECREASING)
2940  return ERROR_INT("invalid sortorder", __func__, 1);
2941 
2942  numaIsSorted(nax, sortorder, &sorted);
2943  if (sorted == TRUE) {
2944  *pnasx = numaCopy(nax);
2945  *pnasy = numaCopy(nay);
2946  } else {
2947  naindex = numaGetSortIndex(nax, sortorder);
2948  *pnasx = numaSortByIndex(nax, naindex);
2949  *pnasy = numaSortByIndex(nay, naindex);
2950  numaDestroy(&naindex);
2951  }
2952 
2953  return 0;
2954 }
2955 
2956 
2970 NUMA *
2972 {
2973 l_int32 i, n, val, error;
2974 l_int32 *test;
2975 NUMA *nad;
2976 
2977  if (!nas)
2978  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
2979  if ((n = numaGetCount(nas)) == 0) {
2980  L_WARNING("nas is empty\n", __func__);
2981  return numaCopy(nas);
2982  }
2983 
2984  nad = numaMakeConstant(0.0, n);
2985  test = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32));
2986  error = 0;
2987  for (i = 0; i < n; i++) {
2988  numaGetIValue(nas, i, &val);
2989  if (val >= n) {
2990  error = 1;
2991  break;
2992  }
2993  numaReplaceNumber(nad, val, i);
2994  if (test[val] == 0) {
2995  test[val] = 1;
2996  } else {
2997  error = 1;
2998  break;
2999  }
3000  }
3001 
3002  LEPT_FREE(test);
3003  if (error) {
3004  numaDestroy(&nad);
3005  return (NUMA *)ERROR_PTR("nas not invertible", __func__, NULL);
3006  }
3007 
3008  return nad;
3009 }
3010 
3024 l_ok
3026  l_float32 val)
3027 {
3028 l_int32 index;
3029 
3030  if (!na)
3031  return ERROR_INT("na not defined", __func__, 1);
3032 
3033  if (numaFindSortedLoc(na, val, &index) == 1)
3034  return ERROR_INT("insert failure", __func__, 1);
3035  numaInsertNumber(na, index, val);
3036  return 0;
3037 }
3038 
3039 
3062 l_ok
3064  l_float32 val,
3065  l_int32 *pindex)
3066 {
3067 l_int32 n, increasing, lindex, rindex, midindex;
3068 l_float32 val0, valn, valmid;
3069 
3070  if (!pindex)
3071  return ERROR_INT("&index not defined", __func__, 1);
3072  *pindex = 0;
3073  if (!na)
3074  return ERROR_INT("na not defined", __func__, 1);
3075 
3076  n = numaGetCount(na);
3077  if (n == 0) return 0;
3078  numaGetFValue(na, 0, &val0);
3079  if (n == 1) { /* use increasing sort order */
3080  if (val >= val0)
3081  *pindex = 1;
3082  return 0;
3083  }
3084 
3085  /* ----------------- n >= 2 ----------------- */
3086  numaGetFValue(na, n - 1, &valn);
3087  increasing = (valn >= val0) ? 1 : 0; /* sort order */
3088 
3089  /* Check if outside bounds of existing array */
3090  if (increasing) {
3091  if (val < val0) {
3092  *pindex = 0;
3093  return 0;
3094  } else if (val > valn) {
3095  *pindex = n;
3096  return 0;
3097  }
3098  } else { /* decreasing */
3099  if (val > val0) {
3100  *pindex = 0;
3101  return 0;
3102  } else if (val < valn) {
3103  *pindex = n;
3104  return 0;
3105  }
3106  }
3107 
3108  /* Within bounds of existing array; search */
3109  lindex = 0;
3110  rindex = n - 1;
3111  while (1) {
3112  midindex = (lindex + rindex) / 2;
3113  if (midindex == lindex || midindex == rindex) break;
3114  numaGetFValue(na, midindex, &valmid);
3115  if (increasing) {
3116  if (val > valmid)
3117  lindex = midindex;
3118  else
3119  rindex = midindex;
3120  } else { /* decreasing */
3121  if (val > valmid)
3122  rindex = midindex;
3123  else
3124  lindex = midindex;
3125  }
3126  }
3127  *pindex = rindex;
3128  return 0;
3129 }
3130 
3131 
3132 /*----------------------------------------------------------------------*
3133  * Random permutation *
3134  *----------------------------------------------------------------------*/
3150 NUMA *
3152  l_int32 seed)
3153 {
3154 l_int32 i, index, temp;
3155 l_int32 *array;
3156 NUMA *na;
3157 
3158  if (size <= 0)
3159  return (NUMA *)ERROR_PTR("size <= 0", __func__, NULL);
3160 
3161  if ((array = (l_int32 *)LEPT_CALLOC(size, sizeof(l_int32))) == NULL)
3162  return (NUMA *)ERROR_PTR("array not made", __func__, NULL);
3163  for (i = 0; i < size; i++)
3164  array[i] = i;
3165  srand(seed);
3166  for (i = size - 1; i > 0; i--) {
3167  index = (l_int32)((i + 1) * ((l_float64)rand() / (l_float64)RAND_MAX));
3168  index = L_MIN(index, i);
3169  temp = array[i];
3170  array[i] = array[index];
3171  array[index] = temp;
3172  }
3173 
3174  na = numaCreateFromIArray(array, size);
3175  LEPT_FREE(array);
3176  return na;
3177 }
3178 
3179 
3187 NUMA *
3189  l_int32 seed)
3190 {
3191 l_int32 i, index, size;
3192 l_float32 val;
3193 NUMA *naindex, *nad;
3194 
3195  if (!nas)
3196  return (NUMA *)ERROR_PTR("nas not defined", __func__, NULL);
3197  if ((size = numaGetCount(nas)) == 0) {
3198  L_WARNING("nas is empty\n", __func__);
3199  return numaCopy(nas);
3200  }
3201 
3202  naindex = numaPseudorandomSequence(size, seed);
3203  nad = numaCreate(size);
3204  for (i = 0; i < size; i++) {
3205  numaGetIValue(naindex, i, &index);
3206  numaGetFValue(nas, index, &val);
3207  numaAddNumber(nad, val);
3208  }
3209  numaDestroy(&naindex);
3210  return nad;
3211 }
3212 
3213 
3214 /*----------------------------------------------------------------------*
3215  * Functions requiring sorting *
3216  *----------------------------------------------------------------------*/
3244 l_ok
3246  l_float32 fract,
3247  NUMA *nasort,
3248  l_int32 usebins,
3249  l_float32 *pval)
3250 {
3251 l_int32 n, index;
3252 NUMA *nas;
3253 
3254  if (!pval)
3255  return ERROR_INT("&val not defined", __func__, 1);
3256  *pval = 0.0; /* init */
3257  if (!na)
3258  return ERROR_INT("na not defined", __func__, 1);
3259  if ((n = numaGetCount(na)) == 0)
3260  return ERROR_INT("na empty", __func__, 1);
3261  if (fract < 0.0 || fract > 1.0)
3262  return ERROR_INT("fract not in [0.0 ... 1.0]", __func__, 1);
3263 
3264  if (nasort) {
3265  nas = nasort;
3266  } else {
3267  if (usebins == 0)
3268  nas = numaSort(NULL, na, L_SORT_INCREASING);
3269  else
3270  nas = numaBinSort(na, L_SORT_INCREASING);
3271  if (!nas)
3272  return ERROR_INT("nas not made", __func__, 1);
3273  }
3274  index = (l_int32)(fract * (l_float32)(n - 1) + 0.5);
3275  numaGetFValue(nas, index, pval);
3276 
3277  if (!nasort) numaDestroy(&nas);
3278  return 0;
3279 }
3280 
3281 
3295 l_ok
3297  l_float32 *pval)
3298 {
3299  if (!pval)
3300  return ERROR_INT("&val not defined", __func__, 1);
3301  *pval = 0.0; /* init */
3302  if (!na || numaGetCount(na) == 0)
3303  return ERROR_INT("na not defined or empty", __func__, 1);
3304 
3305  return numaGetRankValue(na, 0.5, NULL, 0, pval);
3306 }
3307 
3308 
3324 l_ok
3326  l_int32 *pval)
3327 {
3328 l_int32 ret;
3329 l_float32 fval;
3330 
3331  if (!pval)
3332  return ERROR_INT("&val not defined", __func__, 1);
3333  *pval = 0; /* init */
3334  if (!na || numaGetCount(na) == 0)
3335  return ERROR_INT("na not defined or empty", __func__, 1);
3336 
3337  ret = numaGetRankValue(na, 0.5, NULL, 1, &fval);
3338  *pval = lept_roundftoi(fval);
3339  return ret;
3340 }
3341 
3342 
3351 l_ok
3353  l_float32 med,
3354  l_float32 *pdev)
3355 {
3356 l_int32 i, n;
3357 l_float32 val, dev;
3358 
3359  if (!pdev)
3360  return ERROR_INT("&dev not defined", __func__, 1);
3361  *pdev = 0.0; /* init */
3362  if (!na)
3363  return ERROR_INT("na not defined", __func__, 1);
3364  if ((n = numaGetCount(na)) == 0)
3365  return ERROR_INT("na is empty", __func__, 1);
3366 
3367  dev = 0.0;
3368  for (i = 0; i < n; i++) {
3369  numaGetFValue(na, i, &val);
3370  dev += L_ABS(val - med);
3371  }
3372  *pdev = dev / (l_float32)n;
3373  return 0;
3374 }
3375 
3376 
3395 l_ok
3397  l_float32 *pmed,
3398  l_float32 *pdev)
3399 {
3400 l_int32 n, i;
3401 l_float32 val, med;
3402 NUMA *nadev;
3403 
3404  if (pmed) *pmed = 0.0;
3405  if (!pdev)
3406  return ERROR_INT("&dev not defined", __func__, 1);
3407  *pdev = 0.0;
3408  if (!na || numaGetCount(na) == 0)
3409  return ERROR_INT("na not defined or empty", __func__, 1);
3410 
3411  numaGetMedian(na, &med);
3412  if (pmed) *pmed = med;
3413  n = numaGetCount(na);
3414  nadev = numaCreate(n);
3415  for (i = 0; i < n; i++) {
3416  numaGetFValue(na, i, &val);
3417  numaAddNumber(nadev, L_ABS(val - med));
3418  }
3419  numaGetMedian(nadev, pdev);
3420 
3421  numaDestroy(&nadev);
3422  return 0;
3423 }
3424 
3425 
3442 l_ok
3444  l_float32 *pval,
3445  l_int32 *pcount)
3446 {
3447 l_int32 i, n, maxcount, prevcount;
3448 l_float32 val, maxval, prevval;
3449 l_float32 *array;
3450 NUMA *nasort;
3451 
3452  if (pcount) *pcount = 0;
3453  if (!pval)
3454  return ERROR_INT("&val not defined", __func__, 1);
3455  *pval = 0.0;
3456  if (!na)
3457  return ERROR_INT("na not defined", __func__, 1);
3458  if ((n = numaGetCount(na)) == 0)
3459  return ERROR_INT("na is empty", __func__, 1);
3460 
3461  if ((nasort = numaSort(NULL, na, L_SORT_DECREASING)) == NULL)
3462  return ERROR_INT("nas not made", __func__, 1);
3463  array = numaGetFArray(nasort, L_NOCOPY);
3464 
3465  /* Initialize with array[0] */
3466  prevval = array[0];
3467  prevcount = 1;
3468  maxval = prevval;
3469  maxcount = prevcount;
3470 
3471  /* Scan the sorted array, aggregating duplicates */
3472  for (i = 1; i < n; i++) {
3473  val = array[i];
3474  if (val == prevval) {
3475  prevcount++;
3476  } else { /* new value */
3477  if (prevcount > maxcount) { /* new max */
3478  maxcount = prevcount;
3479  maxval = prevval;
3480  }
3481  prevval = val;
3482  prevcount = 1;
3483  }
3484  }
3485 
3486  /* Was the mode the last run of elements? */
3487  if (prevcount > maxcount) {
3488  maxcount = prevcount;
3489  maxval = prevval;
3490  }
3491 
3492  *pval = maxval;
3493  if (pcount)
3494  *pcount = maxcount;
3495 
3496  numaDestroy(&nasort);
3497  return 0;
3498 }
3499 
3500 
3501 /*----------------------------------------------------------------------*
3502  * Rearrangements *
3503  *----------------------------------------------------------------------*/
3520 l_ok
3522  NUMA *nas,
3523  l_int32 istart,
3524  l_int32 iend)
3525 {
3526 l_int32 n, i;
3527 l_float32 val;
3528 
3529  if (!nad)
3530  return ERROR_INT("nad not defined", __func__, 1);
3531  if (!nas)
3532  return 0;
3533 
3534  if (istart < 0)
3535  istart = 0;
3536  n = numaGetCount(nas);
3537  if (iend < 0 || iend >= n)
3538  iend = n - 1;
3539  if (istart > iend)
3540  return ERROR_INT("istart > iend; nothing to add", __func__, 1);
3541 
3542  for (i = istart; i <= iend; i++) {
3543  numaGetFValue(nas, i, &val);
3544  numaAddNumber(nad, val);
3545  }
3546 
3547  return 0;
3548 }
3549 
3550 
3567 l_ok
3569  NUMAA *naas,
3570  l_int32 istart,
3571  l_int32 iend)
3572 {
3573 l_int32 n, i;
3574 NUMA *na;
3575 
3576  if (!naad)
3577  return ERROR_INT("naad not defined", __func__, 1);
3578  if (!naas)
3579  return 0;
3580 
3581  if (istart < 0)
3582  istart = 0;
3583  n = numaaGetCount(naas);
3584  if (iend < 0 || iend >= n)
3585  iend = n - 1;
3586  if (istart > iend)
3587  return ERROR_INT("istart > iend; nothing to add", __func__, 1);
3588 
3589  for (i = istart; i <= iend; i++) {
3590  na = numaaGetNuma(naas, i, L_CLONE);
3591  numaaAddNuma(naad, na, L_INSERT);
3592  }
3593 
3594  return 0;
3595 }
3596 
3597 
3613 NUMA *
3615 {
3616 l_int32 i, nalloc;
3617 NUMA *na, *nad;
3618 NUMA **array;
3619 
3620  if (!naa)
3621  return (NUMA *)ERROR_PTR("naa not defined", __func__, NULL);
3622 
3623  nalloc = naa->nalloc;
3624  array = numaaGetPtrArray(naa);
3625  nad = numaCreate(0);
3626  for (i = 0; i < nalloc; i++) {
3627  na = array[i];
3628  if (!na) continue;
3629  numaJoin(nad, na, 0, -1);
3630  }
3631 
3632  return nad;
3633 }
3634 
@ L_LINEAR_INTERP
Definition: array.h:92
@ L_QUADRATIC_INTERP
Definition: array.h:93
@ L_CONTINUED_BORDER
Definition: array.h:98
@ L_MIRRORED_BORDER
Definition: array.h:100
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
l_ok numaReplaceNumber(NUMA *na, l_int32 index, l_float32 val)
numaReplaceNumber()
Definition: numabasic.c:601
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:687
NUMA ** numaaGetPtrArray(NUMAA *naa)
numaaGetPtrArray()
Definition: numabasic.c:1598
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
l_int32 numaaGetCount(NUMAA *naa)
numaaGetCount()
Definition: numabasic.c:1516
l_ok numaInsertNumber(NUMA *na, l_int32 index, l_float32 val)
numaInsertNumber()
Definition: numabasic.c:531
NUMA * numaaGetNuma(NUMAA *naa, l_int32 index, l_int32 accessflag)
numaaGetNuma()
Definition: numabasic.c:1617
NUMA * numaClone(NUMA *na)
numaClone()
Definition: numabasic.c:414
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_ok numaSetValue(NUMA *na, l_int32 index, l_float32 val)
numaSetValue()
Definition: numabasic.c:750
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 numaaAddNuma(NUMAA *naa, NUMA *na, l_int32 copyflag)
numaaAddNuma()
Definition: numabasic.c:1435
NUMA * numaCopy(NUMA *na)
numaCopy()
Definition: numabasic.c:387
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
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
NUMA * numaInvert(NUMA *nad, NUMA *nas)
numaInvert()
Definition: numafunc1.c:323
NUMA * numaMakeThresholdIndicator(NUMA *nas, l_float32 thresh, l_int32 type)
numaMakeThresholdIndicator()
Definition: numafunc1.c:1184
NUMA * numaPseudorandomSequence(l_int32 size, l_int32 seed)
numaPseudorandomSequence()
Definition: numafunc1.c:3151
NUMA * numaSort(NUMA *naout, NUMA *nain, l_int32 sortorder)
numaSort()
Definition: numafunc1.c:2567
l_ok numaaJoin(NUMAA *naad, NUMAA *naas, l_int32 istart, l_int32 iend)
numaaJoin()
Definition: numafunc1.c:3568
l_ok numaGetMode(NUMA *na, l_float32 *pval, l_int32 *pcount)
numaGetMode()
Definition: numafunc1.c:3443
l_ok numaInterpolateArbxVal(NUMA *nax, NUMA *nay, l_int32 type, l_float32 xval, l_float32 *pyval)
numaInterpolateArbxVal()
Definition: numafunc1.c:1732
l_ok numaGetMeanAbsval(NUMA *na, l_float32 *paveabs)
numaGetMeanAbsval()
Definition: numafunc1.c:697
NUMA * numaMakeDelta(NUMA *nas)
numaMakeDelta()
Definition: numafunc1.c:759
NUMA * numaReverse(NUMA *nad, NUMA *nas)
numaReverse()
Definition: numafunc1.c:1304
l_int32 numaGetEdgeValues(NUMA *na, l_int32 edge, l_int32 *pstart, l_int32 *pend, l_int32 *psign)
numaGetEdgeValues()
Definition: numafunc1.c:1586
l_ok numaGetMedianDevFromMedian(NUMA *na, l_float32 *pmed, l_float32 *pdev)
numaGetMedianDevFromMedian()
Definition: numafunc1.c:3396
l_int32 numaSimilar(NUMA *na1, NUMA *na2, l_float32 maxdiff, l_int32 *psimilar)
numaSimilar()
Definition: numafunc1.c:365
NUMA * numaLogicalOp(NUMA *nad, NUMA *na1, NUMA *na2, l_int32 op)
numaLogicalOp()
Definition: numafunc1.c:252
NUMA * numaAddBorder(NUMA *nas, l_int32 left, l_int32 right, l_float32 val)
numaAddBorder()
Definition: numafunc1.c:869
l_ok numaHasOnlyIntegers(NUMA *na, l_int32 *pallints)
numaHasOnlyIntegers()
Definition: numafunc1.c:637
l_ok numaGetMedian(NUMA *na, l_float32 *pval)
numaGetMedian()
Definition: numafunc1.c:3296
NUMA * numaaFlattenToNuma(NUMAA *naa)
numaaFlattenToNuma()
Definition: numafunc1.c:3614
l_ok numaGetMean(NUMA *na, l_float32 *pave)
numaGetMean()
Definition: numafunc1.c:670
NUMA * numaGetSortIndex(NUMA *na, l_int32 sortorder)
numaGetSortIndex()
Definition: numafunc1.c:2664
l_ok numaSortPair(NUMA *nax, NUMA *nay, l_int32 sortorder, NUMA **pnasx, NUMA **pnasy)
numaSortPair()
Definition: numafunc1.c:2922
l_ok numaFindSortedLoc(NUMA *na, l_float32 val, l_int32 *pindex)
numaFindSortedLoc()
Definition: numafunc1.c:3063
NUMA * numaMakeAbsval(NUMA *nad, NUMA *nas)
numaMakeAbsval()
Definition: numafunc1.c:836
l_ok numaInterpolateEqxVal(l_float32 startx, l_float32 deltax, NUMA *nay, l_int32 type, l_float32 xval, l_float32 *pyval)
numaInterpolateEqxVal()
Definition: numafunc1.c:1642
l_ok numaAddToNumber(NUMA *na, l_int32 index, l_float32 val)
numaAddToNumber()
Definition: numafunc1.c:412
NUMA * numaUniformSampling(NUMA *nas, l_int32 nsamp)
numaUniformSampling()
Definition: numafunc1.c:1240
l_int32 numaIsSorted(NUMA *nas, l_int32 sortorder, l_int32 *psorted)
numaIsSorted()
Definition: numafunc1.c:2872
l_ok numaGetSumOnInterval(NUMA *na, l_int32 first, l_int32 last, l_float32 *psum)
numaGetSumOnInterval()
Definition: numafunc1.c:596
NUMA * numaRemoveBorder(NUMA *nas, l_int32 left, l_int32 right)
numaRemoveBorder()
Definition: numafunc1.c:959
NUMA * numaSortAutoSelect(NUMA *nas, l_int32 sortorder)
numaSortAutoSelect()
Definition: numafunc1.c:2444
l_ok numaGetCountRelativeToZero(NUMA *na, l_int32 type, l_int32 *pcount)
numaGetCountRelativeToZero()
Definition: numafunc1.c:1088
l_ok numaInterpolateEqxInterval(l_float32 startx, l_float32 deltax, NUMA *nasy, l_int32 type, l_float32 x0, l_float32 x1, l_int32 npts, NUMA **pnax, NUMA **pnay)
numaInterpolateEqxInterval()
Definition: numafunc1.c:1847
l_ok numaInterpolateArbxInterval(NUMA *nax, NUMA *nay, l_int32 type, l_float32 x0, l_float32 x1, l_int32 npts, NUMA **pnadx, NUMA **pnady)
numaInterpolateArbxInterval()
Definition: numafunc1.c:1934
l_ok numaGetMeanDevFromMedian(NUMA *na, l_float32 med, l_float32 *pdev)
numaGetMeanDevFromMedian()
Definition: numafunc1.c:3352
NUMA * numaRandomPermutation(NUMA *nas, l_int32 seed)
numaRandomPermutation()
Definition: numafunc1.c:3188
l_ok numaJoin(NUMA *nad, NUMA *nas, l_int32 istart, l_int32 iend)
numaJoin()
Definition: numafunc1.c:3521
l_ok numaGetRankValue(NUMA *na, l_float32 fract, NUMA *nasort, l_int32 usebins, l_float32 *pval)
numaGetRankValue()
Definition: numafunc1.c:3245
l_ok numaGetMin(NUMA *na, l_float32 *pminval, l_int32 *piminloc)
numaGetMin()
Definition: numafunc1.c:444
NUMA * numaBinSort(NUMA *nas, l_int32 sortorder)
numaBinSort()
Definition: numafunc1.c:2633
NUMA * numaSortIndexAutoSelect(NUMA *nas, l_int32 sortorder)
numaSortIndexAutoSelect()
Definition: numafunc1.c:2483
NUMA * numaLowPassIntervals(NUMA *nas, l_float32 thresh, l_float32 maxn)
numaLowPassIntervals()
Definition: numafunc1.c:1357
l_ok numaGetBinnedMedian(NUMA *na, l_int32 *pval)
numaGetBinnedMedian()
Definition: numafunc1.c:3325
NUMA * numaInvertMap(NUMA *nas)
numaInvertMap()
Definition: numafunc1.c:2971
l_ok numaAddSorted(NUMA *na, l_float32 val)
numaAddSorted()
Definition: numafunc1.c:3025
NUMA * numaMakeConstant(l_float32 val, l_int32 size)
numaMakeConstant()
Definition: numafunc1.c:820
NUMA * numaClipToInterval(NUMA *nas, l_int32 first, l_int32 last)
numaClipToInterval()
Definition: numafunc1.c:1137
NUMA * numaSubsample(NUMA *nas, l_int32 subfactor)
numaSubsample()
Definition: numafunc1.c:726
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:485
NUMA * numaGetPartialSums(NUMA *na)
numaGetPartialSums()
Definition: numafunc1.c:564
NUMA * numaThresholdEdges(NUMA *nas, l_float32 thresh1, l_float32 thresh2, l_float32 maxn)
numaThresholdEdges()
Definition: numafunc1.c:1432
NUMA * numaArithOp(NUMA *nad, NUMA *na1, NUMA *na2, l_int32 op)
numaArithOp()
Definition: numafunc1.c:174
l_int32 numaChooseSortType(NUMA *nas)
numaChooseSortType()
Definition: numafunc1.c:2521
l_int32 numaGetSpanValues(NUMA *na, l_int32 span, l_int32 *pstart, l_int32 *pend)
numaGetSpanValues()
Definition: numafunc1.c:1551
NUMA * numaSortByIndex(NUMA *nas, NUMA *naindex)
numaSortByIndex()
Definition: numafunc1.c:2825
NUMA * numaAddSpecifiedBorder(NUMA *nas, l_int32 left, l_int32 right, l_int32 type)
numaAddSpecifiedBorder()
Definition: numafunc1.c:910
l_ok numaSortGeneral(NUMA *na, NUMA **pnasort, NUMA **pnaindex, NUMA **pnainvert, l_int32 sortorder, l_int32 sorttype)
numaSortGeneral()
Definition: numafunc1.c:2381
l_ok numaGetNonzeroRange(NUMA *na, l_float32 eps, l_int32 *pfirst, l_int32 *plast)
numaGetNonzeroRange()
Definition: numafunc1.c:1037
NUMA * numaMakeSequence(l_float32 startval, l_float32 increment, l_int32 size)
numaMakeSequence()
Definition: numafunc1.c:792
l_ok numaFitMax(NUMA *na, l_float32 *pmaxval, NUMA *naloc, l_float32 *pmaxloc)
numaFitMax()
Definition: numafunc1.c:2093
NUMA * numaGetBinSortIndex(NUMA *nas, l_int32 sortorder)
numaGetBinSortIndex()
Definition: numafunc1.c:2744
l_ok numaCountNonzeroRuns(NUMA *na, l_int32 *pcount)
numaCountNonzeroRuns()
Definition: numafunc1.c:998
l_ok numaDifferentiateInterval(NUMA *nax, NUMA *nay, l_float32 x0, l_float32 x1, l_int32 npts, NUMA **pnadx, NUMA **pnady)
numaDifferentiateInterval()
Definition: numafunc1.c:2197
l_ok numaGetSum(NUMA *na, l_float32 *psum)
numaGetSum()
Definition: numafunc1.c:525
l_ok numaIntegrateInterval(NUMA *nax, NUMA *nay, l_float32 x0, l_float32 x1, l_int32 npts, l_float32 *psum)
numaIntegrateInterval()
Definition: numafunc1.c:2278
@ L_SELECT_IF_LTE
Definition: pix.h:577
@ L_SELECT_IF_LT
Definition: pix.h:575
@ L_SELECT_IF_GT
Definition: pix.h:576
@ L_SELECT_IF_GTE
Definition: pix.h:578
@ L_COPY
Definition: pix.h:505
@ L_CLONE
Definition: pix.h:506
@ L_NOCOPY
Definition: pix.h:503
@ L_INSERT
Definition: pix.h:504
@ L_BIN_SORT
Definition: pix.h:517
@ L_SHELL_SORT
Definition: pix.h:516
@ L_SORT_DECREASING
Definition: pix.h:523
@ L_SORT_INCREASING
Definition: pix.h:522
@ L_EQUAL_TO_ZERO
Definition: pix.h:1072
@ L_LESS_THAN_ZERO
Definition: pix.h:1071
@ L_GREATER_THAN_ZERO
Definition: pix.h:1073
l_ok ptraInsert(L_PTRA *pa, l_int32 index, void *item, l_int32 shiftflag)
ptraInsert()
Definition: ptra.c:336
L_PTRA * ptraCreate(l_int32 n)
ptraCreate()
Definition: ptra.c:144
l_ok ptraGetMaxIndex(L_PTRA *pa, l_int32 *pmaxindex)
ptraGetMaxIndex()
Definition: ptra.c:683
void ptraDestroy(L_PTRA **ppa, l_int32 freeflag, l_int32 warnflag)
ptraDestroy()
Definition: ptra.c:192
void * ptraRemove(L_PTRA *pa, l_int32 index, l_int32 flag)
ptraRemove()
Definition: ptra.c:432
void * ptraGetPtrToItem(L_PTRA *pa, l_int32 index)
ptraGetPtrToItem()
Definition: ptra.c:739
void * ptraRemoveLast(L_PTRA *pa)
ptraRemoveLast()
Definition: ptra.c:479
@ L_NO_COMPACTION
Definition: ptra.h:79
@ L_MIN_DOWNSHIFT
Definition: ptra.h:86
Definition: ptra.h:54
l_float32 startx
l_float32 delx
l_float32 * array
l_int32 nalloc
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_int32 lept_roundftoi(l_float32 fval)
lept_roundftoi()
Definition: utils1.c:690