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
27 /*!
28 * \file dnabasic.c
29 * <pre>
30 *
31 * Dna creation, destruction, copy, clone, etc.
32 * L_DNA *l_dnaCreate()
33 * L_DNA *l_dnaCreateFromIArray()
34 * L_DNA *l_dnaCreateFromDArray()
35 * L_DNA *l_dnaMakeSequence()
36 * void *l_dnaDestroy()
37 * L_DNA *l_dnaCopy()
38 * L_DNA *l_dnaClone()
39 * l_int32 l_dnaEmpty()
40 *
41 * Dna: add/remove number and extend array
42 * l_int32 l_dnaAddNumber()
43 * static l_int32 l_dnaExtendArray()
44 * l_int32 l_dnaInsertNumber()
45 * l_int32 l_dnaRemoveNumber()
46 * l_int32 l_dnaReplaceNumber()
47 *
48 * Dna accessors
49 * l_int32 l_dnaGetCount()
50 * l_int32 l_dnaSetCount()
51 * l_int32 l_dnaGetIValue()
52 * l_int32 l_dnaGetDValue()
53 * l_int32 l_dnaSetValue()
54 * l_int32 l_dnaShiftValue()
55 * l_int32 *l_dnaGetIArray()
56 * l_float64 *l_dnaGetDArray()
57 * l_int32 l_dnaGetRefcount()
58 * l_int32 l_dnaChangeRefcount()
59 * l_int32 l_dnaGetParameters()
60 * l_int32 l_dnaSetParameters()
61 * l_int32 l_dnaCopyParameters()
62 *
63 * Serialize Dna for I/O
64 * L_DNA *l_dnaRead()
65 * L_DNA *l_dnaReadStream()
66 * l_int32 l_dnaWrite()
67 * l_int32 l_dnaWriteStream()
68 *
69 * Dnaa creation, destruction
70 * L_DNAA *l_dnaaCreate()
71 * L_DNAA *l_dnaaCreateFull()
72 * l_int32 l_dnaaTruncate()
73 * void *l_dnaaDestroy()
74 *
75 * Add Dna to Dnaa
76 * l_int32 l_dnaaAddDna()
77 * static l_int32 l_dnaaExtendArray()
78 *
79 * Dnaa accessors
80 * l_int32 l_dnaaGetCount()
81 * l_int32 l_dnaaGetDnaCount()
82 * l_int32 l_dnaaGetNumberCount()
83 * L_DNA *l_dnaaGetDna()
84 * L_DNA *l_dnaaReplaceDna()
85 * l_int32 l_dnaaGetValue()
86 * l_int32 l_dnaaAddNumber()
87 *
88 * Serialize Dnaa for I/O
89 * L_DNAA *l_dnaaRead()
90 * L_DNAA *l_dnaaReadStream()
91 * l_int32 l_dnaaWrite()
92 * l_int32 l_dnaaWriteStream()
93 *
94 * (1) The Dna is a struct holding an array of doubles. It can also
95 * be used to store l_int32 values, up to the full precision
96 * of int32. Always use it whenever integers larger than a
97 * few million need to be stored.
98 *
99 * (2) Always use the accessors in this file, never the fields directly.
100 *
101 * (3) Storing and retrieving numbers:
102 *
103 * * to append a new number to the array, use l_dnaAddNumber(). If
104 * the number is an int, it will will automatically be converted
105 * to l_float64 and stored.
106 *
107 * * to reset a value stored in the array, use l_dnaSetValue().
108 *
109 * * to increment or decrement a value stored in the array,
110 * use l_dnaShiftValue().
111 *
112 * * to obtain a value from the array, use either l_dnaGetIValue()
113 * or l_dnaGetDValue(), depending on whether you are retrieving
114 * an integer or a float64. This avoids doing an explicit cast,
115 * such as
116 * (a) return a l_float64 and cast it to an l_int32
117 * (b) cast the return directly to (l_float64 *) to
118 * satisfy the function prototype, as in
119 * l_dnaGetDValue(da, index, (l_float64 *)&ival); [ugly!]
120 *
121 * (4) int <--> double conversions:
122 *
123 * Conversions go automatically from l_int32 --> l_float64,
124 * without loss of precision. You must cast (l_int32)
125 * to go from l_float64 --> l_int32 because you're truncating
126 * to the integer value.
127 *
128 * (5) As with other arrays in leptonica, the l_dna has both an allocated
129 * size and a count of the stored numbers. When you add a number, it
130 * goes on the end of the array, and causes a realloc if the array
131 * is already filled. However, in situations where you want to
132 * add numbers randomly into an array, such as when you build a
133 * histogram, you must set the count of stored numbers in advance.
134 * This is done with l_dnaSetCount(). If you set a count larger
135 * than the allocated array, it does a realloc to the size requested.
136 *
137 * (6) In situations where the data in a l_dna correspond to a function
138 * y(x), the values can be either at equal spacings in x or at
139 * arbitrary spacings. For the former, we can represent all x values
140 * by two parameters: startx (corresponding to y[0]) and delx
141 * for the change in x for adjacent values y[i] and y[i+1].
142 * startx and delx are initialized to 0.0 and 1.0, rsp.
143 * For arbitrary spacings, we use a second l_dna, and the two
144 * l_dnas are typically denoted dnay and dnax.
145 * </pre>
146 */
147
148 #include <string.h>
149 #include <math.h>
150 #include "allheaders.h"
151
152 static const l_int32 INITIAL_PTR_ARRAYSIZE = 50; /*!< n'importe quoi */
153
154 /* Static functions */
155 static l_int32 l_dnaExtendArray(L_DNA *da);
156 static l_int32 l_dnaaExtendArray(L_DNAA *daa);
157
158
159 /*--------------------------------------------------------------------------*
160 * Dna creation, destruction, copy, clone, etc. *
161 *--------------------------------------------------------------------------*/
162 /*!
163 * \brief l_dnaCreate()
164 *
165 * \param[in] n size of number array to be alloc'd; 0 for default
166 * \return da, or NULL on error
167 */
168 L_DNA *
l_dnaCreate(l_int32 n)169 l_dnaCreate(l_int32 n)
170 {
171 L_DNA *da;
172
173 PROCNAME("l_dnaCreate");
174
175 if (n <= 0)
176 n = INITIAL_PTR_ARRAYSIZE;
177
178 da = (L_DNA *)LEPT_CALLOC(1, sizeof(L_DNA));
179 if ((da->array = (l_float64 *)LEPT_CALLOC(n, sizeof(l_float64))) == NULL) {
180 l_dnaDestroy(&da);
181 return (L_DNA *)ERROR_PTR("double array not made", procName, NULL);
182 }
183
184 da->nalloc = n;
185 da->n = 0;
186 da->refcount = 1;
187 da->startx = 0.0;
188 da->delx = 1.0;
189
190 return da;
191 }
192
193
194 /*!
195 * \brief l_dnaCreateFromIArray()
196 *
197 * \param[in] iarray integer
198 * \param[in] size of the array
199 * \return da, or NULL on error
200 *
201 * <pre>
202 * Notes:
203 * (1) We can't insert this int array into the l_dna, because a l_dna
204 * takes a double array. So this just copies the data from the
205 * input array into the l_dna. The input array continues to be
206 * owned by the caller.
207 * </pre>
208 */
209 L_DNA *
l_dnaCreateFromIArray(l_int32 * iarray,l_int32 size)210 l_dnaCreateFromIArray(l_int32 *iarray,
211 l_int32 size)
212 {
213 l_int32 i;
214 L_DNA *da;
215
216 PROCNAME("l_dnaCreateFromIArray");
217
218 if (!iarray)
219 return (L_DNA *)ERROR_PTR("iarray not defined", procName, NULL);
220 if (size <= 0)
221 return (L_DNA *)ERROR_PTR("size must be > 0", procName, NULL);
222
223 da = l_dnaCreate(size);
224 for (i = 0; i < size; i++)
225 l_dnaAddNumber(da, iarray[i]);
226
227 return da;
228 }
229
230
231 /*!
232 * \brief l_dnaCreateFromDArray()
233 *
234 * \param[in] darray float
235 * \param[in] size of the array
236 * \param[in] copyflag L_INSERT or L_COPY
237 * \return da, or NULL on error
238 *
239 * <pre>
240 * Notes:
241 * (1) With L_INSERT, ownership of the input array is transferred
242 * to the returned l_dna, and all %size elements are considered
243 * to be valid.
244 * </pre>
245 */
246 L_DNA *
l_dnaCreateFromDArray(l_float64 * darray,l_int32 size,l_int32 copyflag)247 l_dnaCreateFromDArray(l_float64 *darray,
248 l_int32 size,
249 l_int32 copyflag)
250 {
251 l_int32 i;
252 L_DNA *da;
253
254 PROCNAME("l_dnaCreateFromDArray");
255
256 if (!darray)
257 return (L_DNA *)ERROR_PTR("darray not defined", procName, NULL);
258 if (size <= 0)
259 return (L_DNA *)ERROR_PTR("size must be > 0", procName, NULL);
260 if (copyflag != L_INSERT && copyflag != L_COPY)
261 return (L_DNA *)ERROR_PTR("invalid copyflag", procName, NULL);
262
263 da = l_dnaCreate(size);
264 if (copyflag == L_INSERT) {
265 if (da->array) LEPT_FREE(da->array);
266 da->array = darray;
267 da->n = size;
268 } else { /* just copy the contents */
269 for (i = 0; i < size; i++)
270 l_dnaAddNumber(da, darray[i]);
271 }
272
273 return da;
274 }
275
276
277 /*!
278 * \brief l_dnaMakeSequence()
279 *
280 * \param[in] startval
281 * \param[in] increment
282 * \param[in] size of sequence
283 * \return l_dna of sequence of evenly spaced values, or NULL on error
284 */
285 L_DNA *
l_dnaMakeSequence(l_float64 startval,l_float64 increment,l_int32 size)286 l_dnaMakeSequence(l_float64 startval,
287 l_float64 increment,
288 l_int32 size)
289 {
290 l_int32 i;
291 l_float64 val;
292 L_DNA *da;
293
294 PROCNAME("l_dnaMakeSequence");
295
296 if ((da = l_dnaCreate(size)) == NULL)
297 return (L_DNA *)ERROR_PTR("da not made", procName, NULL);
298
299 for (i = 0; i < size; i++) {
300 val = startval + i * increment;
301 l_dnaAddNumber(da, val);
302 }
303
304 return da;
305 }
306
307
308 /*!
309 * \brief l_dnaDestroy()
310 *
311 * \param[in,out] pda to be nulled if it exists
312 * \return void
313 *
314 * <pre>
315 * Notes:
316 * (1) Decrements the ref count and, if 0, destroys the l_dna.
317 * (2) Always nulls the input ptr.
318 * </pre>
319 */
320 void
l_dnaDestroy(L_DNA ** pda)321 l_dnaDestroy(L_DNA **pda)
322 {
323 L_DNA *da;
324
325 PROCNAME("l_dnaDestroy");
326
327 if (pda == NULL) {
328 L_WARNING("ptr address is NULL\n", procName);
329 return;
330 }
331
332 if ((da = *pda) == NULL)
333 return;
334
335 /* Decrement the ref count. If it is 0, destroy the l_dna. */
336 l_dnaChangeRefcount(da, -1);
337 if (l_dnaGetRefcount(da) <= 0) {
338 if (da->array)
339 LEPT_FREE(da->array);
340 LEPT_FREE(da);
341 }
342
343 *pda = NULL;
344 return;
345 }
346
347
348 /*!
349 * \brief l_dnaCopy()
350 *
351 * \param[in] da
352 * \return copy of da, or NULL on error
353 *
354 * <pre>
355 * Notes:
356 * (1) This removes unused ptrs above da->n.
357 * </pre>
358 */
359 L_DNA *
l_dnaCopy(L_DNA * da)360 l_dnaCopy(L_DNA *da)
361 {
362 l_int32 i;
363 L_DNA *dac;
364
365 PROCNAME("l_dnaCopy");
366
367 if (!da)
368 return (L_DNA *)ERROR_PTR("da not defined", procName, NULL);
369
370 if ((dac = l_dnaCreate(da->n)) == NULL)
371 return (L_DNA *)ERROR_PTR("dac not made", procName, NULL);
372 dac->startx = da->startx;
373 dac->delx = da->delx;
374
375 for (i = 0; i < da->n; i++)
376 l_dnaAddNumber(dac, da->array[i]);
377
378 return dac;
379 }
380
381
382 /*!
383 * \brief l_dnaClone()
384 *
385 * \param[in] da
386 * \return ptr to same da, or NULL on error
387 */
388 L_DNA *
l_dnaClone(L_DNA * da)389 l_dnaClone(L_DNA *da)
390 {
391 PROCNAME("l_dnaClone");
392
393 if (!da)
394 return (L_DNA *)ERROR_PTR("da not defined", procName, NULL);
395
396 l_dnaChangeRefcount(da, 1);
397 return da;
398 }
399
400
401 /*!
402 * \brief l_dnaEmpty()
403 *
404 * \param[in] da
405 * \return 0 if OK; 1 on error
406 *
407 * <pre>
408 * Notes:
409 * (1) This does not change the allocation of the array.
410 * It just clears the number of stored numbers, so that
411 * the array appears to be empty.
412 * </pre>
413 */
414 l_int32
l_dnaEmpty(L_DNA * da)415 l_dnaEmpty(L_DNA *da)
416 {
417 PROCNAME("l_dnaEmpty");
418
419 if (!da)
420 return ERROR_INT("da not defined", procName, 1);
421
422 da->n = 0;
423 return 0;
424 }
425
426
427
428 /*--------------------------------------------------------------------------*
429 * Dna: add/remove number and extend array *
430 *--------------------------------------------------------------------------*/
431 /*!
432 * \brief l_dnaAddNumber()
433 *
434 * \param[in] da
435 * \param[in] val float or int to be added; stored as a float
436 * \return 0 if OK, 1 on error
437 */
438 l_int32
l_dnaAddNumber(L_DNA * da,l_float64 val)439 l_dnaAddNumber(L_DNA *da,
440 l_float64 val)
441 {
442 l_int32 n;
443
444 PROCNAME("l_dnaAddNumber");
445
446 if (!da)
447 return ERROR_INT("da not defined", procName, 1);
448
449 n = l_dnaGetCount(da);
450 if (n >= da->nalloc)
451 l_dnaExtendArray(da);
452 da->array[n] = val;
453 da->n++;
454 return 0;
455 }
456
457
458 /*!
459 * \brief l_dnaExtendArray()
460 *
461 * \param[in] da
462 * \return 0 if OK, 1 on error
463 */
464 static l_int32
l_dnaExtendArray(L_DNA * da)465 l_dnaExtendArray(L_DNA *da)
466 {
467 PROCNAME("l_dnaExtendArray");
468
469 if (!da)
470 return ERROR_INT("da not defined", procName, 1);
471
472 if ((da->array = (l_float64 *)reallocNew((void **)&da->array,
473 sizeof(l_float64) * da->nalloc,
474 2 * sizeof(l_float64) * da->nalloc)) == NULL)
475 return ERROR_INT("new ptr array not returned", procName, 1);
476
477 da->nalloc *= 2;
478 return 0;
479 }
480
481
482 /*!
483 * \brief l_dnaInsertNumber()
484 *
485 * \param[in] da
486 * \param[in] index location in da to insert new value
487 * \param[in] val float64 or integer to be added
488 * \return 0 if OK, 1 on error
489 *
490 * <pre>
491 * Notes:
492 * (1) This shifts da[i] --> da[i + 1] for all i >= index,
493 * and then inserts val as da[index].
494 * (2) It should not be used repeatedly on large arrays,
495 * because the function is O(n).
496 *
497 * </pre>
498 */
499 l_int32
l_dnaInsertNumber(L_DNA * da,l_int32 index,l_float64 val)500 l_dnaInsertNumber(L_DNA *da,
501 l_int32 index,
502 l_float64 val)
503 {
504 l_int32 i, n;
505
506 PROCNAME("l_dnaInsertNumber");
507
508 if (!da)
509 return ERROR_INT("da not defined", procName, 1);
510 n = l_dnaGetCount(da);
511 if (index < 0 || index > n)
512 return ERROR_INT("index not in {0...n}", procName, 1);
513
514 if (n >= da->nalloc)
515 l_dnaExtendArray(da);
516 for (i = n; i > index; i--)
517 da->array[i] = da->array[i - 1];
518 da->array[index] = val;
519 da->n++;
520 return 0;
521 }
522
523
524 /*!
525 * \brief l_dnaRemoveNumber()
526 *
527 * \param[in] da
528 * \param[in] index element to be removed
529 * \return 0 if OK, 1 on error
530 *
531 * <pre>
532 * Notes:
533 * (1) This shifts da[i] --> da[i - 1] for all i > index.
534 * (2) It should not be used repeatedly on large arrays,
535 * because the function is O(n).
536 * </pre>
537 */
538 l_int32
l_dnaRemoveNumber(L_DNA * da,l_int32 index)539 l_dnaRemoveNumber(L_DNA *da,
540 l_int32 index)
541 {
542 l_int32 i, n;
543
544 PROCNAME("l_dnaRemoveNumber");
545
546 if (!da)
547 return ERROR_INT("da not defined", procName, 1);
548 n = l_dnaGetCount(da);
549 if (index < 0 || index >= n)
550 return ERROR_INT("index not in {0...n - 1}", procName, 1);
551
552 for (i = index + 1; i < n; i++)
553 da->array[i - 1] = da->array[i];
554 da->n--;
555 return 0;
556 }
557
558
559 /*!
560 * \brief l_dnaReplaceNumber()
561 *
562 * \param[in] da
563 * \param[in] index element to be replaced
564 * \param[in] val new value to replace old one
565 * \return 0 if OK, 1 on error
566 */
567 l_int32
l_dnaReplaceNumber(L_DNA * da,l_int32 index,l_float64 val)568 l_dnaReplaceNumber(L_DNA *da,
569 l_int32 index,
570 l_float64 val)
571 {
572 l_int32 n;
573
574 PROCNAME("l_dnaReplaceNumber");
575
576 if (!da)
577 return ERROR_INT("da not defined", procName, 1);
578 n = l_dnaGetCount(da);
579 if (index < 0 || index >= n)
580 return ERROR_INT("index not in {0...n - 1}", procName, 1);
581
582 da->array[index] = val;
583 return 0;
584 }
585
586
587 /*----------------------------------------------------------------------*
588 * Dna accessors *
589 *----------------------------------------------------------------------*/
590 /*!
591 * \brief l_dnaGetCount()
592 *
593 * \param[in] da
594 * \return count, or 0 if no numbers or on error
595 */
596 l_int32
l_dnaGetCount(L_DNA * da)597 l_dnaGetCount(L_DNA *da)
598 {
599 PROCNAME("l_dnaGetCount");
600
601 if (!da)
602 return ERROR_INT("da not defined", procName, 0);
603 return da->n;
604 }
605
606
607 /*!
608 * \brief l_dnaSetCount()
609 *
610 * \param[in] da
611 * \param[in] newcount
612 * \return 0 if OK, 1 on error
613 *
614 * <pre>
615 * Notes:
616 * (1) If newcount <= da->nalloc, this resets da->n.
617 * Using newcount = 0 is equivalent to l_dnaEmpty().
618 * (2) If newcount > da->nalloc, this causes a realloc
619 * to a size da->nalloc = newcount.
620 * (3) All the previously unused values in da are set to 0.0.
621 * </pre>
622 */
623 l_int32
l_dnaSetCount(L_DNA * da,l_int32 newcount)624 l_dnaSetCount(L_DNA *da,
625 l_int32 newcount)
626 {
627 PROCNAME("l_dnaSetCount");
628
629 if (!da)
630 return ERROR_INT("da not defined", procName, 1);
631 if (newcount > da->nalloc) {
632 if ((da->array = (l_float64 *)reallocNew((void **)&da->array,
633 sizeof(l_float64) * da->nalloc,
634 sizeof(l_float64) * newcount)) == NULL)
635 return ERROR_INT("new ptr array not returned", procName, 1);
636 da->nalloc = newcount;
637 }
638 da->n = newcount;
639 return 0;
640 }
641
642
643 /*!
644 * \brief l_dnaGetDValue()
645 *
646 * \param[in] da
647 * \param[in] index into l_dna
648 * \param[out] pval double value; 0.0 on error
649 * \return 0 if OK; 1 on error
650 *
651 * <pre>
652 * Notes:
653 * (1) Caller may need to check the function return value to
654 * decide if a 0.0 in the returned ival is valid.
655 * </pre>
656 */
657 l_int32
l_dnaGetDValue(L_DNA * da,l_int32 index,l_float64 * pval)658 l_dnaGetDValue(L_DNA *da,
659 l_int32 index,
660 l_float64 *pval)
661 {
662 PROCNAME("l_dnaGetDValue");
663
664 if (!pval)
665 return ERROR_INT("&val not defined", procName, 1);
666 *pval = 0.0;
667 if (!da)
668 return ERROR_INT("da not defined", procName, 1);
669
670 if (index < 0 || index >= da->n)
671 return ERROR_INT("index not valid", procName, 1);
672
673 *pval = da->array[index];
674 return 0;
675 }
676
677
678 /*!
679 * \brief l_dnaGetIValue()
680 *
681 * \param[in] da
682 * \param[in] index into l_dna
683 * \param[out] pival integer value; 0 on error
684 * \return 0 if OK; 1 on error
685 *
686 * <pre>
687 * Notes:
688 * (1) Caller may need to check the function return value to
689 * decide if a 0 in the returned ival is valid.
690 * </pre>
691 */
692 l_int32
l_dnaGetIValue(L_DNA * da,l_int32 index,l_int32 * pival)693 l_dnaGetIValue(L_DNA *da,
694 l_int32 index,
695 l_int32 *pival)
696 {
697 l_float64 val;
698
699 PROCNAME("l_dnaGetIValue");
700
701 if (!pival)
702 return ERROR_INT("&ival not defined", procName, 1);
703 *pival = 0;
704 if (!da)
705 return ERROR_INT("da not defined", procName, 1);
706
707 if (index < 0 || index >= da->n)
708 return ERROR_INT("index not valid", procName, 1);
709
710 val = da->array[index];
711 *pival = (l_int32)(val + L_SIGN(val) * 0.5);
712 return 0;
713 }
714
715
716 /*!
717 * \brief l_dnaSetValue()
718 *
719 * \param[in] da
720 * \param[in] index to element to be set
721 * \param[in] val to set element
722 * \return 0 if OK; 1 on error
723 */
724 l_int32
l_dnaSetValue(L_DNA * da,l_int32 index,l_float64 val)725 l_dnaSetValue(L_DNA *da,
726 l_int32 index,
727 l_float64 val)
728 {
729 PROCNAME("l_dnaSetValue");
730
731 if (!da)
732 return ERROR_INT("da not defined", procName, 1);
733 if (index < 0 || index >= da->n)
734 return ERROR_INT("index not valid", procName, 1);
735
736 da->array[index] = val;
737 return 0;
738 }
739
740
741 /*!
742 * \brief l_dnaShiftValue()
743 *
744 * \param[in] da
745 * \param[in] index to element to change relative to the current value
746 * \param[in] diff increment if diff > 0 or decrement if diff < 0
747 * \return 0 if OK; 1 on error
748 */
749 l_int32
l_dnaShiftValue(L_DNA * da,l_int32 index,l_float64 diff)750 l_dnaShiftValue(L_DNA *da,
751 l_int32 index,
752 l_float64 diff)
753 {
754 PROCNAME("l_dnaShiftValue");
755
756 if (!da)
757 return ERROR_INT("da not defined", procName, 1);
758 if (index < 0 || index >= da->n)
759 return ERROR_INT("index not valid", procName, 1);
760
761 da->array[index] += diff;
762 return 0;
763 }
764
765
766 /*!
767 * \brief l_dnaGetIArray()
768 *
769 * \param[in] da
770 * \return a copy of the bare internal array, integerized
771 * by rounding, or NULL on error
772 * <pre>
773 * Notes:
774 * (1) A copy of the array is made, because we need to
775 * generate an integer array from the bare double array.
776 * The caller is responsible for freeing the array.
777 * (2) The array size is determined by the number of stored numbers,
778 * not by the size of the allocated array in the l_dna.
779 * (3) This function is provided to simplify calculations
780 * using the bare internal array, rather than continually
781 * calling accessors on the l_dna. It is typically used
782 * on an array of size 256.
783 * </pre>
784 */
785 l_int32 *
l_dnaGetIArray(L_DNA * da)786 l_dnaGetIArray(L_DNA *da)
787 {
788 l_int32 i, n, ival;
789 l_int32 *array;
790
791 PROCNAME("l_dnaGetIArray");
792
793 if (!da)
794 return (l_int32 *)ERROR_PTR("da not defined", procName, NULL);
795
796 n = l_dnaGetCount(da);
797 if ((array = (l_int32 *)LEPT_CALLOC(n, sizeof(l_int32))) == NULL)
798 return (l_int32 *)ERROR_PTR("array not made", procName, NULL);
799 for (i = 0; i < n; i++) {
800 l_dnaGetIValue(da, i, &ival);
801 array[i] = ival;
802 }
803
804 return array;
805 }
806
807
808 /*!
809 * \brief l_dnaGetDArray()
810 *
811 * \param[in] da
812 * \param[in] copyflag L_NOCOPY or L_COPY
813 * \return either the bare internal array or a copy of it,
814 * or NULL on error
815 *
816 * <pre>
817 * Notes:
818 * (1) If copyflag == L_COPY, it makes a copy which the caller
819 * is responsible for freeing. Otherwise, it operates
820 * directly on the bare array of the l_dna.
821 * (2) Very important: for L_NOCOPY, any writes to the array
822 * will be in the l_dna. Do not write beyond the size of
823 * the count field, because it will not be accessible
824 * from the l_dna! If necessary, be sure to set the count
825 * field to a larger number (such as the alloc size)
826 * BEFORE calling this function. Creating with l_dnaMakeConstant()
827 * is another way to insure full initialization.
828 * </pre>
829 */
830 l_float64 *
l_dnaGetDArray(L_DNA * da,l_int32 copyflag)831 l_dnaGetDArray(L_DNA *da,
832 l_int32 copyflag)
833 {
834 l_int32 i, n;
835 l_float64 *array;
836
837 PROCNAME("l_dnaGetDArray");
838
839 if (!da)
840 return (l_float64 *)ERROR_PTR("da not defined", procName, NULL);
841
842 if (copyflag == L_NOCOPY) {
843 array = da->array;
844 } else { /* copyflag == L_COPY */
845 n = l_dnaGetCount(da);
846 if ((array = (l_float64 *)LEPT_CALLOC(n, sizeof(l_float64))) == NULL)
847 return (l_float64 *)ERROR_PTR("array not made", procName, NULL);
848 for (i = 0; i < n; i++)
849 array[i] = da->array[i];
850 }
851
852 return array;
853 }
854
855
856 /*!
857 * \brief l_dnaGetRefCount()
858 *
859 * \param[in] da
860 * \return refcount, or UNDEF on error
861 */
862 l_int32
l_dnaGetRefcount(L_DNA * da)863 l_dnaGetRefcount(L_DNA *da)
864 {
865 PROCNAME("l_dnaGetRefcount");
866
867 if (!da)
868 return ERROR_INT("da not defined", procName, UNDEF);
869 return da->refcount;
870 }
871
872
873 /*!
874 * \brief l_dnaChangeRefCount()
875 *
876 * \param[in] da
877 * \param[in] delta change to be applied
878 * \return 0 if OK, 1 on error
879 */
880 l_int32
l_dnaChangeRefcount(L_DNA * da,l_int32 delta)881 l_dnaChangeRefcount(L_DNA *da,
882 l_int32 delta)
883 {
884 PROCNAME("l_dnaChangeRefcount");
885
886 if (!da)
887 return ERROR_INT("da not defined", procName, 1);
888 da->refcount += delta;
889 return 0;
890 }
891
892
893 /*!
894 * \brief l_dnaGetParameters()
895 *
896 * \param[in] da
897 * \param[out] pstartx [optional] startx
898 * \param[out] pdelx [optional] delx
899 * \return 0 if OK, 1 on error
900 */
901 l_int32
l_dnaGetParameters(L_DNA * da,l_float64 * pstartx,l_float64 * pdelx)902 l_dnaGetParameters(L_DNA *da,
903 l_float64 *pstartx,
904 l_float64 *pdelx)
905 {
906 PROCNAME("l_dnaGetParameters");
907
908 if (pstartx) *pstartx = 0.0;
909 if (pdelx) *pdelx = 1.0;
910 if (!pstartx && !pdelx)
911 return ERROR_INT("neither &startx nor &delx are defined", procName, 1);
912 if (!da)
913 return ERROR_INT("da not defined", procName, 1);
914
915 if (pstartx) *pstartx = da->startx;
916 if (pdelx) *pdelx = da->delx;
917 return 0;
918 }
919
920
921 /*!
922 * \brief l_dnaSetParameters()
923 *
924 * \param[in] da
925 * \param[in] startx x value corresponding to da[0]
926 * \param[in] delx difference in x values for the situation where the
927 * elements of da correspond to the evaulation of a
928 * function at equal intervals of size %delx
929 * \return 0 if OK, 1 on error
930 */
931 l_int32
l_dnaSetParameters(L_DNA * da,l_float64 startx,l_float64 delx)932 l_dnaSetParameters(L_DNA *da,
933 l_float64 startx,
934 l_float64 delx)
935 {
936 PROCNAME("l_dnaSetParameters");
937
938 if (!da)
939 return ERROR_INT("da not defined", procName, 1);
940
941 da->startx = startx;
942 da->delx = delx;
943 return 0;
944 }
945
946
947 /*!
948 * \brief l_dnaCopyParameters()
949 *
950 * \param[in] dad destination DNuma
951 * \param[in] das source DNuma
952 * \return 0 if OK, 1 on error
953 */
954 l_int32
l_dnaCopyParameters(L_DNA * dad,L_DNA * das)955 l_dnaCopyParameters(L_DNA *dad,
956 L_DNA *das)
957 {
958 l_float64 start, binsize;
959
960 PROCNAME("l_dnaCopyParameters");
961
962 if (!das || !dad)
963 return ERROR_INT("das and dad not both defined", procName, 1);
964
965 l_dnaGetParameters(das, &start, &binsize);
966 l_dnaSetParameters(dad, start, binsize);
967 return 0;
968 }
969
970
971 /*----------------------------------------------------------------------*
972 * Serialize Dna for I/O *
973 *----------------------------------------------------------------------*/
974 /*!
975 * \brief l_dnaRead()
976 *
977 * \param[in] filename
978 * \return da, or NULL on error
979 */
980 L_DNA *
l_dnaRead(const char * filename)981 l_dnaRead(const char *filename)
982 {
983 FILE *fp;
984 L_DNA *da;
985
986 PROCNAME("l_dnaRead");
987
988 if (!filename)
989 return (L_DNA *)ERROR_PTR("filename not defined", procName, NULL);
990
991 if ((fp = fopenReadStream(filename)) == NULL)
992 return (L_DNA *)ERROR_PTR("stream not opened", procName, NULL);
993 da = l_dnaReadStream(fp);
994 fclose(fp);
995 if (!da)
996 return (L_DNA *)ERROR_PTR("da not read", procName, NULL);
997 return da;
998 }
999
1000
1001 /*!
1002 * \brief l_dnaReadStream()
1003 *
1004 * \param[in] fp file stream
1005 * \return da, or NULL on error
1006 *
1007 * <pre>
1008 * Notes:
1009 * (1) fscanf takes %lf to read a double; fprintf takes %f to write it.
1010 * </pre>
1011 */
1012 L_DNA *
l_dnaReadStream(FILE * fp)1013 l_dnaReadStream(FILE *fp)
1014 {
1015 l_int32 i, n, index, ret, version;
1016 l_float64 val, startx, delx;
1017 L_DNA *da;
1018
1019 PROCNAME("l_dnaReadStream");
1020
1021 if (!fp)
1022 return (L_DNA *)ERROR_PTR("stream not defined", procName, NULL);
1023
1024 ret = fscanf(fp, "\nL_Dna Version %d\n", &version);
1025 if (ret != 1)
1026 return (L_DNA *)ERROR_PTR("not a l_dna file", procName, NULL);
1027 if (version != DNA_VERSION_NUMBER)
1028 return (L_DNA *)ERROR_PTR("invalid l_dna version", procName, NULL);
1029 if (fscanf(fp, "Number of numbers = %d\n", &n) != 1)
1030 return (L_DNA *)ERROR_PTR("invalid number of numbers", procName, NULL);
1031
1032 if ((da = l_dnaCreate(n)) == NULL)
1033 return (L_DNA *)ERROR_PTR("da not made", procName, NULL);
1034 for (i = 0; i < n; i++) {
1035 if (fscanf(fp, " [%d] = %lf\n", &index, &val) != 2) {
1036 l_dnaDestroy(&da);
1037 return (L_DNA *)ERROR_PTR("bad input data", procName, NULL);
1038 }
1039 l_dnaAddNumber(da, val);
1040 }
1041
1042 /* Optional data */
1043 if (fscanf(fp, "startx = %lf, delx = %lf\n", &startx, &delx) == 2)
1044 l_dnaSetParameters(da, startx, delx);
1045 return da;
1046 }
1047
1048
1049 /*!
1050 * \brief l_dnaWrite()
1051 *
1052 * \param[in] filename, da
1053 * \return 0 if OK, 1 on error
1054 */
1055 l_int32
l_dnaWrite(const char * filename,L_DNA * da)1056 l_dnaWrite(const char *filename,
1057 L_DNA *da)
1058 {
1059 l_int32 ret;
1060 FILE *fp;
1061
1062 PROCNAME("l_dnaWrite");
1063
1064 if (!filename)
1065 return ERROR_INT("filename not defined", procName, 1);
1066 if (!da)
1067 return ERROR_INT("da not defined", procName, 1);
1068
1069 if ((fp = fopenWriteStream(filename, "w")) == NULL)
1070 return ERROR_INT("stream not opened", procName, 1);
1071 ret = l_dnaWriteStream(fp, da);
1072 fclose(fp);
1073 if (ret)
1074 return ERROR_INT("da not written to stream", procName, 1);
1075 return 0;
1076 }
1077
1078
1079 /*!
1080 * \brief l_dnaWriteStream()
1081 *
1082 * \param[in] fp file stream
1083 * \param[in] da
1084 * \return 0 if OK, 1 on error
1085 */
1086 l_int32
l_dnaWriteStream(FILE * fp,L_DNA * da)1087 l_dnaWriteStream(FILE *fp,
1088 L_DNA *da)
1089 {
1090 l_int32 i, n;
1091 l_float64 startx, delx;
1092
1093 PROCNAME("l_dnaWriteStream");
1094
1095 if (!fp)
1096 return ERROR_INT("stream not defined", procName, 1);
1097 if (!da)
1098 return ERROR_INT("da not defined", procName, 1);
1099
1100 n = l_dnaGetCount(da);
1101 fprintf(fp, "\nL_Dna Version %d\n", DNA_VERSION_NUMBER);
1102 fprintf(fp, "Number of numbers = %d\n", n);
1103 for (i = 0; i < n; i++)
1104 fprintf(fp, " [%d] = %f\n", i, da->array[i]);
1105 fprintf(fp, "\n");
1106
1107 /* Optional data */
1108 l_dnaGetParameters(da, &startx, &delx);
1109 if (startx != 0.0 || delx != 1.0)
1110 fprintf(fp, "startx = %f, delx = %f\n", startx, delx);
1111
1112 return 0;
1113 }
1114
1115
1116 /*--------------------------------------------------------------------------*
1117 * Dnaa creation, destruction *
1118 *--------------------------------------------------------------------------*/
1119 /*!
1120 * \brief l_dnaaCreate()
1121 *
1122 * \param[in] n size of l_dna ptr array to be alloc'd 0 for default
1123 * \return daa, or NULL on error
1124 *
1125 */
1126 L_DNAA *
l_dnaaCreate(l_int32 n)1127 l_dnaaCreate(l_int32 n)
1128 {
1129 L_DNAA *daa;
1130
1131 PROCNAME("l_dnaaCreate");
1132
1133 if (n <= 0)
1134 n = INITIAL_PTR_ARRAYSIZE;
1135
1136 daa = (L_DNAA *)LEPT_CALLOC(1, sizeof(L_DNAA));
1137 if ((daa->dna = (L_DNA **)LEPT_CALLOC(n, sizeof(L_DNA *))) == NULL) {
1138 l_dnaaDestroy(&daa);
1139 return (L_DNAA *)ERROR_PTR("l_dna ptr array not made", procName, NULL);
1140 }
1141 daa->nalloc = n;
1142 daa->n = 0;
1143 return daa;
1144 }
1145
1146
1147 /*!
1148 * \brief l_dnaaCreateFull()
1149 *
1150 * \param[in] nptr: size of dna ptr array to be alloc'd
1151 * \param[in] n: size of individual dna arrays to be alloc'd 0 for default
1152 * \return daa, or NULL on error
1153 *
1154 * <pre>
1155 * Notes:
1156 * (1) This allocates a dnaa and fills the array with allocated dnas.
1157 * In use, after calling this function, use
1158 * l_dnaaAddNumber(dnaa, index, val);
1159 * to add val to the index-th dna in dnaa.
1160 * </pre>
1161 */
1162 L_DNAA *
l_dnaaCreateFull(l_int32 nptr,l_int32 n)1163 l_dnaaCreateFull(l_int32 nptr,
1164 l_int32 n)
1165 {
1166 l_int32 i;
1167 L_DNAA *daa;
1168 L_DNA *da;
1169
1170 daa = l_dnaaCreate(nptr);
1171 for (i = 0; i < nptr; i++) {
1172 da = l_dnaCreate(n);
1173 l_dnaaAddDna(daa, da, L_INSERT);
1174 }
1175
1176 return daa;
1177 }
1178
1179
1180 /*!
1181 * \brief l_dnaaTruncate()
1182 *
1183 * \param[in] daa
1184 * \return 0 if OK, 1 on error
1185 *
1186 * <pre>
1187 * Notes:
1188 * (1) This identifies the largest index containing a dna that
1189 * has any numbers within it, destroys all dna beyond that
1190 * index, and resets the count.
1191 * </pre>
1192 */
1193 l_int32
l_dnaaTruncate(L_DNAA * daa)1194 l_dnaaTruncate(L_DNAA *daa)
1195 {
1196 l_int32 i, n, nn;
1197 L_DNA *da;
1198
1199 PROCNAME("l_dnaaTruncate");
1200
1201 if (!daa)
1202 return ERROR_INT("daa not defined", procName, 1);
1203
1204 n = l_dnaaGetCount(daa);
1205 for (i = n - 1; i >= 0; i--) {
1206 da = l_dnaaGetDna(daa, i, L_CLONE);
1207 if (!da)
1208 continue;
1209 nn = l_dnaGetCount(da);
1210 l_dnaDestroy(&da); /* the clone */
1211 if (nn == 0)
1212 l_dnaDestroy(&daa->dna[i]);
1213 else
1214 break;
1215 }
1216 daa->n = i + 1;
1217 return 0;
1218 }
1219
1220
1221 /*!
1222 * \brief l_dnaaDestroy()
1223 *
1224 * \param[in,out] pdaa to be nulled if it exists
1225 * \return void
1226 */
1227 void
l_dnaaDestroy(L_DNAA ** pdaa)1228 l_dnaaDestroy(L_DNAA **pdaa)
1229 {
1230 l_int32 i;
1231 L_DNAA *daa;
1232
1233 PROCNAME("l_dnaaDestroy");
1234
1235 if (pdaa == NULL) {
1236 L_WARNING("ptr address is NULL!\n", procName);
1237 return;
1238 }
1239
1240 if ((daa = *pdaa) == NULL)
1241 return;
1242
1243 for (i = 0; i < daa->n; i++)
1244 l_dnaDestroy(&daa->dna[i]);
1245 LEPT_FREE(daa->dna);
1246 LEPT_FREE(daa);
1247 *pdaa = NULL;
1248
1249 return;
1250 }
1251
1252
1253 /*--------------------------------------------------------------------------*
1254 * Add Dna to Dnaa *
1255 *--------------------------------------------------------------------------*/
1256 /*!
1257 * \brief l_dnaaAddDna()
1258 *
1259 * \param[in] daa
1260 * \param[in] da to be added
1261 * \param[in] copyflag L_INSERT, L_COPY, L_CLONE
1262 * \return 0 if OK, 1 on error
1263 */
1264 l_int32
l_dnaaAddDna(L_DNAA * daa,L_DNA * da,l_int32 copyflag)1265 l_dnaaAddDna(L_DNAA *daa,
1266 L_DNA *da,
1267 l_int32 copyflag)
1268 {
1269 l_int32 n;
1270 L_DNA *dac;
1271
1272 PROCNAME("l_dnaaAddDna");
1273
1274 if (!daa)
1275 return ERROR_INT("daa not defined", procName, 1);
1276 if (!da)
1277 return ERROR_INT("da not defined", procName, 1);
1278
1279 if (copyflag == L_INSERT) {
1280 dac = da;
1281 } else if (copyflag == L_COPY) {
1282 if ((dac = l_dnaCopy(da)) == NULL)
1283 return ERROR_INT("dac not made", procName, 1);
1284 } else if (copyflag == L_CLONE) {
1285 dac = l_dnaClone(da);
1286 } else {
1287 return ERROR_INT("invalid copyflag", procName, 1);
1288 }
1289
1290 n = l_dnaaGetCount(daa);
1291 if (n >= daa->nalloc)
1292 l_dnaaExtendArray(daa);
1293 daa->dna[n] = dac;
1294 daa->n++;
1295 return 0;
1296 }
1297
1298
1299 /*!
1300 * \brief l_dnaaExtendArray()
1301 *
1302 * \param[in] daa
1303 * \return 0 if OK, 1 on error
1304 */
1305 static l_int32
l_dnaaExtendArray(L_DNAA * daa)1306 l_dnaaExtendArray(L_DNAA *daa)
1307 {
1308 PROCNAME("l_dnaaExtendArray");
1309
1310 if (!daa)
1311 return ERROR_INT("daa not defined", procName, 1);
1312
1313 if ((daa->dna = (L_DNA **)reallocNew((void **)&daa->dna,
1314 sizeof(L_DNA *) * daa->nalloc,
1315 2 * sizeof(L_DNA *) * daa->nalloc)) == NULL)
1316 return ERROR_INT("new ptr array not returned", procName, 1);
1317
1318 daa->nalloc *= 2;
1319 return 0;
1320 }
1321
1322
1323 /*----------------------------------------------------------------------*
1324 * DNumaa accessors *
1325 *----------------------------------------------------------------------*/
1326 /*!
1327 * \brief l_dnaaGetCount()
1328 *
1329 * \param[in] daa
1330 * \return count number of l_dna, or 0 if no l_dna or on error
1331 */
1332 l_int32
l_dnaaGetCount(L_DNAA * daa)1333 l_dnaaGetCount(L_DNAA *daa)
1334 {
1335 PROCNAME("l_dnaaGetCount");
1336
1337 if (!daa)
1338 return ERROR_INT("daa not defined", procName, 0);
1339 return daa->n;
1340 }
1341
1342
1343 /*!
1344 * \brief l_dnaaGetDnaCount()
1345 *
1346 * \param[in] daa
1347 * \param[in] index of l_dna in daa
1348 * \return count of numbers in the referenced l_dna, or 0 on error.
1349 */
1350 l_int32
l_dnaaGetDnaCount(L_DNAA * daa,l_int32 index)1351 l_dnaaGetDnaCount(L_DNAA *daa,
1352 l_int32 index)
1353 {
1354 PROCNAME("l_dnaaGetDnaCount");
1355
1356 if (!daa)
1357 return ERROR_INT("daa not defined", procName, 0);
1358 if (index < 0 || index >= daa->n)
1359 return ERROR_INT("invalid index into daa", procName, 0);
1360 return l_dnaGetCount(daa->dna[index]);
1361 }
1362
1363
1364 /*!
1365 * \brief l_dnaaGetNumberCount()
1366 *
1367 * \param[in] daa
1368 * \return count total number of numbers in the l_dnaa,
1369 * or 0 if no numbers or on error
1370 */
1371 l_int32
l_dnaaGetNumberCount(L_DNAA * daa)1372 l_dnaaGetNumberCount(L_DNAA *daa)
1373 {
1374 L_DNA *da;
1375 l_int32 n, sum, i;
1376
1377 PROCNAME("l_dnaaGetNumberCount");
1378
1379 if (!daa)
1380 return ERROR_INT("daa not defined", procName, 0);
1381
1382 n = l_dnaaGetCount(daa);
1383 for (sum = 0, i = 0; i < n; i++) {
1384 da = l_dnaaGetDna(daa, i, L_CLONE);
1385 sum += l_dnaGetCount(da);
1386 l_dnaDestroy(&da);
1387 }
1388
1389 return sum;
1390 }
1391
1392
1393 /*!
1394 * \brief l_dnaaGetDna()
1395 *
1396 * \param[in] daa
1397 * \param[in] index to the index-th l_dna
1398 * \param[in] accessflag L_COPY or L_CLONE
1399 * \return l_dna, or NULL on error
1400 */
1401 L_DNA *
l_dnaaGetDna(L_DNAA * daa,l_int32 index,l_int32 accessflag)1402 l_dnaaGetDna(L_DNAA *daa,
1403 l_int32 index,
1404 l_int32 accessflag)
1405 {
1406 PROCNAME("l_dnaaGetDna");
1407
1408 if (!daa)
1409 return (L_DNA *)ERROR_PTR("daa not defined", procName, NULL);
1410 if (index < 0 || index >= daa->n)
1411 return (L_DNA *)ERROR_PTR("index not valid", procName, NULL);
1412
1413 if (accessflag == L_COPY)
1414 return l_dnaCopy(daa->dna[index]);
1415 else if (accessflag == L_CLONE)
1416 return l_dnaClone(daa->dna[index]);
1417 else
1418 return (L_DNA *)ERROR_PTR("invalid accessflag", procName, NULL);
1419 }
1420
1421
1422 /*!
1423 * \brief l_dnaaReplaceDna()
1424 *
1425 * \param[in] daa
1426 * \param[in] index to the index-th l_dna
1427 * \param[in] da insert and replace any existing one
1428 * \return 0 if OK, 1 on error
1429 *
1430 * <pre>
1431 * Notes:
1432 * (1) Any existing l_dna is destroyed, and the input one
1433 * is inserted in its place.
1434 * (2) If the index is invalid, return 1 (error)
1435 * </pre>
1436 */
1437 l_int32
l_dnaaReplaceDna(L_DNAA * daa,l_int32 index,L_DNA * da)1438 l_dnaaReplaceDna(L_DNAA *daa,
1439 l_int32 index,
1440 L_DNA *da)
1441 {
1442 l_int32 n;
1443
1444 PROCNAME("l_dnaaReplaceDna");
1445
1446 if (!daa)
1447 return ERROR_INT("daa not defined", procName, 1);
1448 if (!da)
1449 return ERROR_INT("da not defined", procName, 1);
1450 n = l_dnaaGetCount(daa);
1451 if (index < 0 || index >= n)
1452 return ERROR_INT("index not valid", procName, 1);
1453
1454 l_dnaDestroy(&daa->dna[index]);
1455 daa->dna[index] = da;
1456 return 0;
1457 }
1458
1459
1460 /*!
1461 * \brief l_dnaaGetValue()
1462 *
1463 * \param[in] daa
1464 * \param[in] i index of l_dna within l_dnaa
1465 * \param[in] j index into l_dna
1466 * \param[out] pval double value
1467 * \return 0 if OK, 1 on error
1468 */
1469 l_int32
l_dnaaGetValue(L_DNAA * daa,l_int32 i,l_int32 j,l_float64 * pval)1470 l_dnaaGetValue(L_DNAA *daa,
1471 l_int32 i,
1472 l_int32 j,
1473 l_float64 *pval)
1474 {
1475 l_int32 n;
1476 L_DNA *da;
1477
1478 PROCNAME("l_dnaaGetValue");
1479
1480 if (!pval)
1481 return ERROR_INT("&val not defined", procName, 1);
1482 *pval = 0.0;
1483 if (!daa)
1484 return ERROR_INT("daa not defined", procName, 1);
1485 n = l_dnaaGetCount(daa);
1486 if (i < 0 || i >= n)
1487 return ERROR_INT("invalid index into daa", procName, 1);
1488 da = daa->dna[i];
1489 if (j < 0 || j >= da->n)
1490 return ERROR_INT("invalid index into da", procName, 1);
1491 *pval = da->array[j];
1492 return 0;
1493 }
1494
1495
1496 /*!
1497 * \brief l_dnaaAddNumber()
1498 *
1499 * \param[in] daa
1500 * \param[in] index of l_dna within l_dnaa
1501 * \param[in] val number to be added; stored as a double
1502 * \return 0 if OK, 1 on error
1503 *
1504 * <pre>
1505 * Notes:
1506 * (1) Adds to an existing l_dna only.
1507 * </pre>
1508 */
1509 l_int32
l_dnaaAddNumber(L_DNAA * daa,l_int32 index,l_float64 val)1510 l_dnaaAddNumber(L_DNAA *daa,
1511 l_int32 index,
1512 l_float64 val)
1513 {
1514 l_int32 n;
1515 L_DNA *da;
1516
1517 PROCNAME("l_dnaaAddNumber");
1518
1519 if (!daa)
1520 return ERROR_INT("daa not defined", procName, 1);
1521 n = l_dnaaGetCount(daa);
1522 if (index < 0 || index >= n)
1523 return ERROR_INT("invalid index in daa", procName, 1);
1524
1525 da = l_dnaaGetDna(daa, index, L_CLONE);
1526 l_dnaAddNumber(da, val);
1527 l_dnaDestroy(&da);
1528 return 0;
1529 }
1530
1531
1532 /*----------------------------------------------------------------------*
1533 * Serialize Dna for I/O *
1534 *----------------------------------------------------------------------*/
1535 /*!
1536 * \brief l_dnaaRead()
1537 *
1538 * \param[in] filename
1539 * \return daa, or NULL on error
1540 */
1541 L_DNAA *
l_dnaaRead(const char * filename)1542 l_dnaaRead(const char *filename)
1543 {
1544 FILE *fp;
1545 L_DNAA *daa;
1546
1547 PROCNAME("l_dnaaRead");
1548
1549 if (!filename)
1550 return (L_DNAA *)ERROR_PTR("filename not defined", procName, NULL);
1551
1552 if ((fp = fopenReadStream(filename)) == NULL)
1553 return (L_DNAA *)ERROR_PTR("stream not opened", procName, NULL);
1554 daa = l_dnaaReadStream(fp);
1555 fclose(fp);
1556 if (!daa)
1557 return (L_DNAA *)ERROR_PTR("daa not read", procName, NULL);
1558 return daa;
1559 }
1560
1561
1562 /*!
1563 * \brief l_dnaaReadStream()
1564 *
1565 * \param[in] fp file stream
1566 * \return daa, or NULL on error
1567 */
1568 L_DNAA *
l_dnaaReadStream(FILE * fp)1569 l_dnaaReadStream(FILE *fp)
1570 {
1571 l_int32 i, n, index, ret, version;
1572 L_DNA *da;
1573 L_DNAA *daa;
1574
1575 PROCNAME("l_dnaaReadStream");
1576
1577 if (!fp)
1578 return (L_DNAA *)ERROR_PTR("stream not defined", procName, NULL);
1579
1580 ret = fscanf(fp, "\nL_Dnaa Version %d\n", &version);
1581 if (ret != 1)
1582 return (L_DNAA *)ERROR_PTR("not a l_dna file", procName, NULL);
1583 if (version != DNA_VERSION_NUMBER)
1584 return (L_DNAA *)ERROR_PTR("invalid l_dnaa version", procName, NULL);
1585 if (fscanf(fp, "Number of L_Dna = %d\n\n", &n) != 1)
1586 return (L_DNAA *)ERROR_PTR("invalid number of l_dna", procName, NULL);
1587 if ((daa = l_dnaaCreate(n)) == NULL)
1588 return (L_DNAA *)ERROR_PTR("daa not made", procName, NULL);
1589
1590 for (i = 0; i < n; i++) {
1591 if (fscanf(fp, "L_Dna[%d]:", &index) != 1) {
1592 l_dnaaDestroy(&daa);
1593 return (L_DNAA *)ERROR_PTR("invalid l_dna header", procName, NULL);
1594 }
1595 if ((da = l_dnaReadStream(fp)) == NULL) {
1596 l_dnaaDestroy(&daa);
1597 return (L_DNAA *)ERROR_PTR("da not made", procName, NULL);
1598 }
1599 l_dnaaAddDna(daa, da, L_INSERT);
1600 }
1601
1602 return daa;
1603 }
1604
1605
1606 /*!
1607 * \brief l_dnaaWrite()
1608 *
1609 * \param[in] filename, daa
1610 * \return 0 if OK, 1 on error
1611 */
1612 l_int32
l_dnaaWrite(const char * filename,L_DNAA * daa)1613 l_dnaaWrite(const char *filename,
1614 L_DNAA *daa)
1615 {
1616 l_int32 ret;
1617 FILE *fp;
1618
1619 PROCNAME("l_dnaaWrite");
1620
1621 if (!filename)
1622 return ERROR_INT("filename not defined", procName, 1);
1623 if (!daa)
1624 return ERROR_INT("daa not defined", procName, 1);
1625
1626 if ((fp = fopenWriteStream(filename, "w")) == NULL)
1627 return ERROR_INT("stream not opened", procName, 1);
1628 ret = l_dnaaWriteStream(fp, daa);
1629 fclose(fp);
1630 if (ret)
1631 return ERROR_INT("daa not written to stream", procName, 1);
1632 return 0;
1633 }
1634
1635
1636 /*!
1637 * \brief l_dnaaWriteStream()
1638 *
1639 * \param[in] fp file stream
1640 * \param[in] daa
1641 * \return 0 if OK, 1 on error
1642 */
1643 l_int32
l_dnaaWriteStream(FILE * fp,L_DNAA * daa)1644 l_dnaaWriteStream(FILE *fp,
1645 L_DNAA *daa)
1646 {
1647 l_int32 i, n;
1648 L_DNA *da;
1649
1650 PROCNAME("l_dnaaWriteStream");
1651
1652 if (!fp)
1653 return ERROR_INT("stream not defined", procName, 1);
1654 if (!daa)
1655 return ERROR_INT("daa not defined", procName, 1);
1656
1657 n = l_dnaaGetCount(daa);
1658 fprintf(fp, "\nL_Dnaa Version %d\n", DNA_VERSION_NUMBER);
1659 fprintf(fp, "Number of L_Dna = %d\n\n", n);
1660 for (i = 0; i < n; i++) {
1661 if ((da = l_dnaaGetDna(daa, i, L_CLONE)) == NULL)
1662 return ERROR_INT("da not found", procName, 1);
1663 fprintf(fp, "L_Dna[%d]:", i);
1664 l_dnaWriteStream(fp, da);
1665 l_dnaDestroy(&da);
1666 }
1667
1668 return 0;
1669 }
1670
1671