1 /*****************************************************************************
2 FILE : $Source: /projects/higgs1/SNNS/CVS/SNNS/kernel/sources/kr_newpattern.c,v $
3 SHORTNAME : newpattern
4 SNNS VERSION : 4.2
5
6 PURPOSE : handling of new pattern files;
7 NOTES :
8
9 AUTHOR : Michael Vogt
10 DATE : 10.9.93
11
12 CHANGED BY :
13 RCS VERSION : $Revision: 2.28 $
14 LAST CHANGE : $Date: 1998/05/20 09:36:18 $
15
16 Copyright (c) 1990-1995 SNNS Group, IPVR, Univ. Stuttgart, FRG
17 Copyright (c) 1996-1998 SNNS Group, WSI, Univ. Tuebingen, FRG
18
19 ******************************************************************************/
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #ifdef NeXT
25 #ifdef HAVE_SYS_FILE_H
26 #include <sys/file.h>
27 #endif
28 #else
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #endif
33 #include <string.h>
34 #include <time.h>
35 #include <sys/types.h>
36 #ifdef HAVE_SYS_TIME_H
37 #include <sys/time.h>
38 #endif
39
40 #include "kr_typ.h"
41 #include "glob_typ.h"
42 #include "kr_mac.h"
43
44 #ifndef rand
45 #include "random.h" /* Randomize Library Function Prototypes */
46 #endif
47
48 #include "kernel.h"
49 #include "kr_const.h"
50 #include "kr_funcs.h"
51 /* for dlvq */
52 #include "dlvq_learn.h"
53 #include "kr_newpattern.ph"
54 #include "kr_pat_scan.h"
55 #include "kr_pat_parse.h"
56
57
58 #ifndef __GNUC__
59 #ifndef __FUNCTION__
60 #define __FUNCTION__ "(unknown function)"
61 #endif
62 #endif
63
64 #if defined(DEBUG_PATTERN) && defined(TRACE_PATTERN)
65 static _t_indent = 0;
66 #define TRACE_IN(); \
67 { \
68 int _i; \
69 if (_t_indent == 0) printf("\n"); \
70 for (_i=0; _i<_t_indent; _i++) \
71 printf(" "); \
72 printf("%s\n", __FUNCTION__); \
73 _t_indent += 2; \
74 }
75 #define TRACE_RETURN(x) \
76 { \
77 long _t_tmp; \
78 int _i; \
79 _t_tmp = (x); \
80 _t_indent -= 2; \
81 for (_i=0; _i<_t_indent; _i++) \
82 printf(" "); \
83 printf("<- %ld\n", _t_tmp); \
84 return(_t_tmp); \
85 }
86 #define TRACE_RETURN_VOID() \
87 { \
88 _t_indent -= 2; \
89 return; \
90 }
91 #define TRACE_INDENT() \
92 { \
93 int _i; \
94 for (_i=0; _i<_t_indent-2; _i++) \
95 printf(" "); \
96 }
97 #else
98 #define TRACE_IN()
99 #define TRACE_RETURN(x) return(x)
100 #define TRACE_RETURN_VOID() return
101 #define TRACE_INDENT()
102 #endif
103
104 /*****************************************************************************
105 FUNCTIONS WHICH ARE CALLED BY THE KERNEL USER INTERFACE TO PERFORM
106 THE KERNEL INTERFACE OF THE NEW PATTERN MANAGEMENT
107 ******************************************************************************/
108
109 /*****************************************************************************
110 FUNCTION : kr_npui_setCurrPatSet
111
112 PURPOSE : determines the number of the current pattern set (in
113 kernel terminology) numbering starts with 0
114 RETURNS : kernel error code
115 NOTES :
116
117 UPDATE :
118 ******************************************************************************/
kr_npui_setCurrPatSet(int number)119 krui_err kr_npui_setCurrPatSet(int number)
120 {
121 TRACE_IN();
122
123 if (number<0 || number>=npui_number_pat_sets)
124 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
125
126 npui_curr_pat_set = number;
127 npui_curr_pattern = 1;
128 npui_train_defined = FALSE;
129 npui_show_defined = FALSE;
130 np_abs_count_valid = FALSE;
131 np_sub_pat_sizes_valid = FALSE;
132 np_pat_mapping_valid = FALSE;
133
134 /* for dlvq */
135 newPatternsLoaded = 1;
136
137 TRACE_RETURN(kr_np_ValidateInfo(npui_pat_sets[npui_curr_pat_set]));
138 }
139
140 /*****************************************************************************
141 FUNCTION : kr_npui_deletePatSet
142
143 PURPOSE : deletes the specified pattern set from memory and
144 undefines the current pattern set, pattern, training
145 scheme and display scheme
146 RETURNS : kernel error code
147 NOTES :
148
149 UPDATE :
150 ******************************************************************************/
kr_npui_deletePatSet(int number)151 krui_err kr_npui_deletePatSet(int number)
152 {
153 int i;
154 int pat_set;
155
156 TRACE_IN();
157
158 if (number<0 || number>=npui_number_pat_sets)
159 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
160
161 pat_set = npui_pat_sets[number];
162
163 for (i=number; i<npui_number_pat_sets-1; i++)
164 npui_pat_sets[i] = npui_pat_sets[i+1];
165 npui_number_pat_sets--;
166 npui_curr_pat_set = -1;
167 npui_curr_pattern = -1;
168 npui_train_defined = FALSE;
169 npui_show_defined = FALSE;
170 np_abs_count_valid = FALSE;
171 np_sub_pat_sizes_valid = FALSE;
172 np_pat_mapping_valid = FALSE;
173
174 TRACE_RETURN(kr_np_DeletePatternSet(pat_set));
175 }
176
177 /*****************************************************************************
178 FUNCTION : kr_npui_GetPatInfo
179
180 PURPOSE : retrieves all available information concerning the
181 current pattern set and the current pattern which both
182 must be defined. The given parameter fields are filled
183 with the information.
184 RETURNS : kernel error code
185 NOTES :
186
187 UPDATE :
188 ******************************************************************************/
kr_npui_GetPatInfo(pattern_set_info * set_info,pattern_descriptor * pat_info)189 krui_err kr_npui_GetPatInfo(pattern_set_info *set_info,
190 pattern_descriptor *pat_info)
191 {
192 np_pattern_set_info int_pat_set_info;
193 np_pattern_descriptor *int_pat_info;
194 krui_err err_code;
195
196 TRACE_IN();
197
198 if (npui_curr_pat_set == -1)
199 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN_SET); }
200
201 if (npui_curr_pattern == -1)
202 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN); }
203
204 err_code = kr_np_GetInfo(npui_pat_sets[npui_curr_pat_set],
205 &int_pat_set_info);
206 if (err_code != KRERR_NO_ERROR)
207 { TRACE_RETURN(err_code); }
208
209 *set_info = int_pat_set_info.pub;
210
211 err_code = kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
212 kr_np_virtual_to_physical(npui_curr_pattern-1),
213 &int_pat_info);
214 if (err_code != KRERR_NO_ERROR)
215 { TRACE_RETURN(err_code); }
216
217 *pat_info = int_pat_info->pub;
218
219 { TRACE_RETURN(KRERR_NO_ERROR); }
220 }
221
222 /*****************************************************************************
223 FUNCTION : kr_npui_DefShowSubPat
224
225 PURPOSE : Define the display scheme:
226 Size and position of a sub pattern for the current
227 pattern in the current pattern set is defined. <insize>
228 is a pointer to an array of integer values which define
229 the dimensional sizes of the input sub pattern. <inpos>
230 is a pointer to an array of integer values which defines
231 the offset (position) of this sub pattern inside the
232 pattern. <outsize> and <outpos> are used to define the
233 respective output sub pattern
234 RETURNS : kernel error code
235 NOTES :
236
237 UPDATE :
238 ******************************************************************************/
kr_npui_DefShowSubPat(int * insize,int * outsize,int * inpos,int * outpos)239 krui_err kr_npui_DefShowSubPat(int *insize, int *outsize,
240 int *inpos, int *outpos)
241 {
242 krui_err err_code;
243 np_pattern_descriptor *pattern;
244 int i;
245
246 TRACE_IN();
247
248 npui_show_defined = FALSE;
249
250 if (npui_curr_pat_set == -1)
251 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN_SET); }
252
253 if (npui_curr_pattern == -1)
254 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN); }
255
256 err_code = kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
257 kr_np_virtual_to_physical(npui_curr_pattern-1),
258 &pattern);
259
260 if (err_code != KRERR_NO_ERROR)
261 { TRACE_RETURN(err_code); }
262
263 for (i=0; i<pattern->pub.input_dim; i++)
264 {
265 if ((pattern->pub.input_dim_sizes)[i] < insize[i] + inpos[i] - 1)
266 err_code = KRERR_NP_DIMENSION;
267 }
268 for (i=0; i<pattern->pub.output_dim; i++)
269 {
270 if ((pattern->pub.output_dim_sizes)[i] < outsize[i] + outpos[i] - 1)
271 err_code = KRERR_NP_DIMENSION;
272 }
273
274 if (err_code != KRERR_NO_ERROR)
275 { TRACE_RETURN(err_code); }
276
277 memcpy(npui_insize, insize, MAX_NO_OF_VAR_DIM * sizeof(int));
278 memcpy(npui_outsize, outsize, MAX_NO_OF_VAR_DIM * sizeof(int));
279 memcpy(npui_inpos, inpos, MAX_NO_OF_VAR_DIM * sizeof(int));
280 memcpy(npui_outpos, outpos, MAX_NO_OF_VAR_DIM * sizeof(int));
281 for (i=0; i<MAX_NO_OF_VAR_DIM; i++)
282 {
283 npui_inpos[i]--;
284 npui_outpos[i]--;
285 }
286
287 npui_show_defined = TRUE;
288
289 { TRACE_RETURN(KRERR_NO_ERROR); }
290 }
291
292 /*****************************************************************************
293 FUNCTION : kr_npui_DefTrainSubPat
294
295 PURPOSE : Define the training scheme:
296 Size and step size of sub pattern for the current pattern
297 in the current pattern set is defined for training and
298 testing. <insize> is a pointer to an array of integer
299 values which define the dimensional sizes of the input sub
300 pattern. <instep> is a pointer to an array of integer
301 values which defines the step size which is used to move
302 the sub pattern over the pattern.
303 <outsize> and <outpos> are used to define the respective
304 output sub pattern.
305 <max_n_pos> (if not NULL) returns the number of valid
306 input sub pattern positions for the current pattern and
307 the given training scheme.
308
309 RETURNS : kernel error code
310 NOTES :
311
312 UPDATE :
313 ******************************************************************************/
kr_npui_DefTrainSubPat(int * insize,int * outsize,int * instep,int * outstep,int * max_n_pos)314 krui_err kr_npui_DefTrainSubPat(int *insize, int *outsize,
315 int *instep, int *outstep, int *max_n_pos)
316 {
317 krui_err err_code;
318 int n;
319 np_pattern_descriptor *p;
320 int changes = 0;
321
322 TRACE_IN();
323
324 if (npui_curr_pat_set == -1)
325 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN_SET); }
326
327 if (npui_curr_pattern == -1)
328 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN); }
329
330 if (npui_train_defined)
331 {
332 for (n=0; n<MAX_NO_OF_VAR_DIM && changes==0; n++)
333 if (npui_insize[n] != insize[n] ||
334 npui_outsize[n] != outsize[n] ||
335 npui_instep[n] != instep[n] ||
336 npui_outstep[n] != outstep[n])
337 changes++;
338 }
339
340 if (!npui_train_defined || changes != 0)
341 {
342 npui_train_defined = FALSE;
343 np_abs_count_valid = FALSE;
344 np_sub_pat_sizes_valid = FALSE;
345
346 memcpy(npui_insize, insize, MAX_NO_OF_VAR_DIM * sizeof(int));
347 memcpy(npui_outsize, outsize, MAX_NO_OF_VAR_DIM * sizeof(int));
348 memcpy(npui_instep, instep, MAX_NO_OF_VAR_DIM * sizeof(int));
349 memcpy(npui_outstep, outstep, MAX_NO_OF_VAR_DIM * sizeof(int));
350
351 err_code =
352 kr_np_DefineSubPatternOrdering(npui_pat_sets[npui_curr_pat_set],
353 TRUE, npui_insize, npui_instep);
354 if (err_code != KRERR_NO_ERROR)
355 { TRACE_RETURN(err_code); }
356
357 err_code =
358 kr_np_DefineSubPatternOrdering(npui_pat_sets[npui_curr_pat_set],
359 FALSE, npui_outsize,
360 npui_outstep);
361 if (err_code != KRERR_NO_ERROR)
362 { TRACE_RETURN(err_code); }
363
364 npui_train_defined = TRUE;
365
366 err_code = kr_np_ValidateInfo(npui_pat_sets[npui_curr_pat_set]);
367 if (err_code != KRERR_NO_ERROR)
368 { TRACE_RETURN(err_code); }
369 }
370
371 if (max_n_pos != (int *) NULL)
372 {
373 err_code = kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
374 kr_np_virtual_to_physical(npui_curr_pattern-1), &p);
375 if (err_code != KRERR_NO_ERROR)
376 { TRACE_RETURN(err_code); }
377
378 if (!kr_np_gen_sub_pos(p->pub.input_dim, &n, p->pub.input_dim_sizes,
379 npui_insize, npui_instep, (int *) NULL,
380 TRUE))
381 { TRACE_RETURN(KRERR_NP_DIMENSION); }
382 *max_n_pos = n;
383 }
384
385 { TRACE_RETURN(KRERR_NO_ERROR); }
386 }
387
388
389 /*****************************************************************************
390 FUNCTION : kr_npui_AlignSubPat
391
392 PURPOSE : Align the position of a sub pattern:
393 Using the current training scheme and the current pattern
394 of the current pattern set, the given position of an
395 input sub pattern <inpos> and the given position of the
396 corresponding output sub pattern <outpos> is aligned to fit
397 the currently defined training scheme.
398 E.g. if the training scheme defines a step width of 5 for
399 a specific dimension, only the positions 0, 5, 10, 15 ...
400 are valid positions for a sub pattern.
401 The position of each dimension is aligned independently
402 from all other dimensions by moving to the next valid
403 position which is lower or equal to the given position.
404 <no> (if not NULL) returns the number of the sub pattern
405 which corresponds to the new aligned position which is
406 returned in place (<inpos> <outpos>).
407
408 RETURNS : kernel error code
409 NOTES :
410
411 UPDATE :
412 ******************************************************************************/
kr_npui_AlignSubPat(int * inpos,int * outpos,int * no)413 krui_err kr_npui_AlignSubPat(int *inpos, int *outpos, int *no)
414 {
415 krui_err err_code;
416 np_pattern_descriptor *p;
417 int pos;
418 int i;
419
420 TRACE_IN();
421
422 if (npui_curr_pat_set == -1)
423 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN_SET); }
424
425 if (npui_curr_pattern == -1)
426 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN); }
427
428 if (npui_train_defined == FALSE)
429 { TRACE_RETURN(KRERR_NP_NO_TRAIN_SCHEME); }
430
431 err_code = kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
432 kr_np_virtual_to_physical(npui_curr_pattern-1), &p);
433 if (err_code != KRERR_NO_ERROR)
434 { TRACE_RETURN(err_code); }
435
436 /* enumeration starts with 0, not with 1 */
437 for (i=0; i< p->pub.input_dim; i++)
438 inpos[i] -= 1;
439
440 /* align the position of the input sub pattern */
441 if (!kr_np_align_sub_pos(p->pub.input_dim, &pos,
442 p->pub.input_dim_sizes, npui_insize,
443 npui_instep, inpos))
444 {
445 for (i=0; i< p->pub.input_dim; i++)
446 inpos[i] = 1;
447 { TRACE_RETURN(KRERR_NP_DIMENSION); }
448 }
449
450 /* now enumeration starts with 1 again */
451 for (i=0; i< p->pub.input_dim; i++)
452 inpos[i] += 1;
453
454 /* find the output sub pattern which is related to the aligned */
455 /* input sub pattern */
456 if (!kr_np_gen_sub_pos(p->pub.output_dim, &pos,
457 p->pub.output_dim_sizes, npui_outsize,
458 npui_outstep, outpos, FALSE))
459 {
460 for (i=0; i< p->pub.output_dim; i++)
461 outpos[i] = 1;
462 { TRACE_RETURN(KRERR_NP_DIMENSION); }
463 }
464
465 /* now enumeration starts with 1 again */
466 for (i=0; i< p->pub.output_dim; i++)
467 outpos[i] += 1;
468
469 /* return the absolute position */
470 *no = pos+1;
471
472 { TRACE_RETURN(KRERR_NO_ERROR); }
473 }
474
475 /*****************************************************************************
476 FUNCTION : kr_npui_allocNewPatternSet
477
478 PURPOSE : Allocate an (additional) empty pattern set: A new pattern
479 set is allocated if the maximum number of loaded pattern sets
480 (NO_OF_PAT_SETS) is not exceeded. The corresponding pattern set
481 handle is returned in <set_no>. The new allocated pattern set
482 becomes the current set. There is no current pattern defined.
483 Training scheme and display scheme both become undefined.
484
485 NOTES :
486
487 RETURNS :
488 UPDATE :
489 ******************************************************************************/
kr_npui_allocNewPatternSet(int * set_no)490 krui_err kr_npui_allocNewPatternSet(int *set_no)
491 {
492 int pat_set;
493 krui_err err_code;
494
495 TRACE_IN();
496
497 if (npui_number_pat_sets >= NO_OF_PAT_SETS)
498 { TRACE_RETURN(KRERR_NP_NO_MORE_ENTRIES); }
499
500 /* allocate pattern set with zero pattern */
501 err_code = kr_np_AllocatePatternSet(&pat_set, 0);
502 if (err_code == KRERR_NO_ERROR)
503 {
504 npui_curr_pat_set = npui_number_pat_sets;
505 npui_number_pat_sets++;
506 npui_curr_pattern = -1;
507 npui_pat_sets[npui_curr_pat_set] = pat_set;
508 *set_no = npui_curr_pat_set;
509 npui_train_defined = FALSE;
510 npui_show_defined = FALSE;
511 np_abs_count_valid = FALSE;
512 np_sub_pat_sizes_valid = FALSE;
513 np_pat_mapping_valid = FALSE;
514 np_info_valid[pat_set] = FALSE;
515 err_code = kr_np_ValidateInfo(pat_set);
516 }
517
518 { TRACE_RETURN(err_code); }
519 }
520
521 /*****************************************************************************
522 FUNCTION : kr_npui_loadNewPatterns
523
524 PURPOSE : Load an (additional) pattern file:
525 The file with name <filename> is loaded into memory if
526 existent and if the maximum number of loaded pattern sets
527 (NO_OF_PAT_SETS) is not exceeded. The corresponding
528 pattern set handle is returned in <set_no>.
529
530 The new loaded pattern set becomes the current set. The
531 first pattern inside this set becomes the current
532 pattern. Training scheme and display scheme both become
533 undefined.
534
535 RETURNS : kernel error code
536 NOTES :
537
538 UPDATE :
539 ******************************************************************************/
kr_npui_loadNewPatterns(char * filename,int * set_no)540 krui_err kr_npui_loadNewPatterns(char *filename, int *set_no)
541 {
542 FILE *infile;
543 int pat_set;
544 int read_from_pipe = 0;
545 char *buf;
546 krui_err err_code;
547
548 TRACE_IN();
549
550 if (npui_number_pat_sets >= NO_OF_PAT_SETS)
551 { TRACE_RETURN(KRERR_NP_NO_MORE_ENTRIES); }
552
553 if (access(filename, F_OK) != 0)
554 { TRACE_RETURN(KRERR_FILE_OPEN); }
555 if (strcmp(&filename[strlen(filename)-2], ".Z") == 0)
556 {
557 buf = (char *) malloc(strlen(filename)+strlen("zcat ")+1);
558 if (buf == (char *) NULL)
559 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
560 sprintf(buf, "zcat %s", filename);
561 infile = popen(buf,"r");
562 read_from_pipe = 1;
563 }
564 else if (strcmp(&filename[strlen(filename)-3], ".gz") == 0)
565 {
566 buf = (char *) malloc(strlen(filename)+strlen("gunzip -c ")+1);
567 if (buf == (char *) NULL)
568 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
569 sprintf(buf, "gunzip -c %s", filename);
570 infile = popen(buf,"r");
571 read_from_pipe = 1;
572 }
573 else
574 infile = fopen(filename, "r");
575 if (infile == (FILE *) NULL)
576 { TRACE_RETURN(KRERR_FILE_OPEN); }
577
578 err_code = kr_np_LoadPatternFile(infile, &pat_set);
579 if (err_code == KRERR_NO_ERROR)
580 {
581 /* for dlvq */
582 newPatternsLoaded = 1;
583
584 npui_curr_pat_set = npui_number_pat_sets;
585 npui_number_pat_sets++;
586 npui_curr_pattern = 1;
587 npui_pat_sets[npui_curr_pat_set] = pat_set;
588 *set_no = npui_curr_pat_set;
589 npui_train_defined = FALSE;
590 npui_show_defined = FALSE;
591 np_abs_count_valid = FALSE;
592 np_sub_pat_sizes_valid = FALSE;
593 np_pat_mapping_valid = FALSE;
594 np_info_valid[pat_set] = FALSE;
595 err_code = kr_np_ValidateInfo(pat_set);
596 }
597
598 if (read_from_pipe)
599 {
600 pclose(infile);
601 free(buf);
602 }
603 else
604 fclose(infile);
605
606 { TRACE_RETURN(err_code); }
607 }
608
609 /*****************************************************************************
610 FUNCTION : kr_npui_saveNewPatterns
611
612 PURPOSE : The given pattern set <set_no> is written to file
613 <filename> in new style format. No side effects.
614
615 RETURNS : kernel error code
616 NOTES :
617
618 UPDATE :
619 ******************************************************************************/
kr_npui_saveNewPatterns(char * filename,int set_no)620 krui_err kr_npui_saveNewPatterns(char *filename, int set_no)
621 {
622 FILE *outfile;
623 krui_err err_code;
624
625 TRACE_IN();
626
627 if (set_no<0 || set_no>=npui_number_pat_sets)
628 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
629
630 outfile = fopen(filename, "w");
631 if (outfile == (FILE *) NULL)
632 { TRACE_RETURN(KRERR_FILE_OPEN); }
633
634 err_code = kr_np_SavePatternFile(outfile, npui_pat_sets[set_no]);
635
636 fclose(outfile);
637
638 { TRACE_RETURN(err_code); }
639 }
640
641 /*****************************************************************************
642 FUNCTION : kr_npui_GetShapeOfSubPat
643
644 PURPOSE : Get the shape of a sub pattern which is specified by a
645 number:
646 After kr_npui_DefTrainSubPat has been called for the
647 current pattern set and a current pattern is defined,
648 this function retrieves the <n_pos>th valid sub pattern
649 pair which matches the defined training scheme. Size and
650 position of the sub pattern pair is returned in <insize>
651 <inpos> <outsize> and <outpos> which are all pointer to
652 integer arrays.
653
654 RETURNS : kernel error code
655 NOTES :
656
657 UPDATE :
658 ******************************************************************************/
kr_npui_GetShapeOfSubPat(int * insize,int * outsize,int * inpos,int * outpos,int n_pos)659 krui_err kr_npui_GetShapeOfSubPat(int *insize, int *outsize,
660 int *inpos, int *outpos, int n_pos)
661 {
662 int sp[MAX_NO_OF_VAR_DIM];
663 np_pattern_descriptor *p;
664 krui_err err_code;
665 int n;
666 int i;
667
668 TRACE_IN();
669
670 if (npui_curr_pat_set == -1)
671 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN_SET); }
672
673 if (npui_curr_pattern == -1)
674 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN); }
675
676 if (!npui_train_defined)
677 { TRACE_RETURN(KRERR_NP_NO_TRAIN_SCHEME); }
678
679 err_code = kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
680 kr_np_virtual_to_physical(npui_curr_pattern-1), &p);
681 if (err_code != KRERR_NO_ERROR)
682 { TRACE_RETURN(err_code); }
683
684 n = n_pos-1;
685 if (!kr_np_gen_sub_pos(p->pub.input_dim, &n, p->pub.input_dim_sizes,
686 npui_insize, npui_instep, sp, FALSE))
687 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN); }
688
689 memcpy((char *) inpos, (char *) sp, p->pub.input_dim * sizeof(int));
690 for (i=0; i<p->pub.input_dim; i++)
691 inpos[i]++;
692
693 if (!kr_np_gen_sub_pos(p->pub.output_dim, &n, p->pub.output_dim_sizes,
694 npui_outsize, npui_outstep, sp, FALSE))
695 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN); }
696
697 memcpy((char *) outpos, (char *) sp, p->pub.output_dim *sizeof(int));
698 for (i=0; i<p->pub.output_dim; i++)
699 outpos[i]++;
700
701 memcpy((char *) insize, (char *) npui_insize, p->pub.input_dim *sizeof(int));
702 memcpy((char *) outsize, (char *) npui_outsize, p->pub.input_dim *sizeof(int));
703
704 { TRACE_RETURN(KRERR_NO_ERROR); }
705 }
706
707 /*****************************************************************************
708 FUNCTION : kr_npui_setRemapFunction
709
710 PURPOSE :
711
712 Set the remap function for the current pattern set and use the given
713 parameters.
714 <name> points to a remap function name, provided by the user interface. The
715 function name is checked and the pointer for this function is looked up in the
716 function table. If no function name is given (NULL pointer) or if the default
717 remaping function is given the default remap function is used
718 (no remaping of patterns occurs). The name of the remap function is stored in
719 the pattern set description for future access by the interface.
720 <params> points to an array of function parameters of size NO_OF_REMAP_PARAMS
721 provided by the user interface. The parameters used for the given remap
722 function are read out of the array and copied to the local pattern set
723 description.
724
725 RETURNS : kernel error code
726 NOTES :
727
728 UPDATE :
729 ******************************************************************************/
kr_npui_setRemapFunction(char * name,float * params)730 krui_err kr_npui_setRemapFunction(char *name, float *params)
731 {
732 krui_err err_code = KRERR_NO_ERROR;
733 krui_err err_code_2 = KRERR_NO_ERROR;
734 int pattern_set;
735 int use_default = 0;
736 int i;
737 struct FuncInfoDescriptor func_descr;
738 int has_changed = 0;
739
740 TRACE_IN();
741
742 #ifdef DEBUG_REMAP
743 TRACE_INDENT();
744 printf("%s(%s, %s)\n", __FUNCTION__,
745 name ? name : "<default>",
746 params ? "float[]" : "NULL");
747 #endif
748
749 if (npui_curr_pat_set == -1)
750 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN_SET); }
751
752 pattern_set = npui_pat_sets[npui_curr_pat_set];
753
754 if (name == NULL)
755 use_default = 1;
756 else
757 {
758 func_descr.func_type = REMAP_FUNC;
759 err_code = krf_getFuncInfo(GET_DEFAULT_FUNC, &func_descr);
760 if (err_code != KRERR_NO_ERROR ||
761 strcmp(func_descr.func_name, name) == 0)
762 use_default = 1;
763 else
764 {
765 func_descr.func_type = REMAP_FUNC;
766 strcpy(func_descr.func_name, name);
767 err_code = krf_getFuncInfo(SEARCH_FUNC, &func_descr);
768 if (err_code == KRERR_NO_ERROR)
769 {
770 if (np_info[pattern_set].rmf_ptr !=
771 (RemapFuncPtr) func_descr.function)
772 has_changed++;
773
774 np_info[pattern_set].rmf_ptr =
775 (RemapFuncPtr) func_descr.function;
776 for (i=0; i<func_descr.no_of_input_parameters; i++)
777 np_info[pattern_set].pub.remap_params[i] = params[i];
778 np_info[pattern_set].pub.no_of_remap_params =
779 func_descr.no_of_input_parameters;
780 if (np_info[pattern_set].pub.remap_function != NULL)
781 free(np_info[pattern_set].pub.remap_function);
782 np_info[pattern_set].pub.remap_function = strdup(name);
783 if (np_info[pattern_set].pub.remap_function == NULL)
784 err_code = KRERR_INSUFFICIENT_MEM;
785 }
786 else
787 {
788 use_default = 1;
789 }
790 }
791 }
792
793 if (use_default)
794 {
795 if (np_info[pattern_set].rmf_ptr != NULL)
796 has_changed++;
797 np_info[pattern_set].rmf_ptr = NULL;
798 if (np_info[pattern_set].pub.remap_function != NULL)
799 free(np_info[pattern_set].pub.remap_function);
800 np_info[pattern_set].pub.remap_function = NULL;
801 np_info[pattern_set].pub.no_of_remap_params = 0;
802 }
803
804 if (has_changed>0)
805 {
806 /* everything is done already, so I don't have to do this (?): */
807 /*
808 np_info_valid[npui_pat_sets[npui_curr_pat_set]] = FALSE;
809 err_code_2 = kr_np_ValidateInfo(npui_pat_sets[npui_curr_pat_set]);
810 */
811 }
812
813 { TRACE_RETURN(err_code != KRERR_NO_ERROR ? err_code : err_code_2); }
814 }
815
816
817 /*****************************************************************************
818 FUNCTION : kr_npui_setClassDistribution
819
820 PURPOSE :
821
822 Set the class distribution for the current pattern set.
823 This function may only be called if the current pattern set provides class
824 information. If <class_sizes> is not NULL it must locate an integer array of
825 size that matches the number of classes in the current set. The values of
826 this array are copied to the pattern set area. If <class_sizes> is the NULL
827 pointer, then the real distribution of classes in the pattern set is
828 computed and stored in the class distribution area of the pattern set. So the
829 interface may retrieve default values for the class distribution which match
830 the real distribution of the pattern set.
831
832 RETURNS : kernel error code
833 NOTES :
834
835 UPDATE :
836 ******************************************************************************/
kr_npui_setClassDistribution(unsigned int * class_sizes)837 krui_err kr_npui_setClassDistribution(unsigned int *class_sizes)
838 {
839 int has_changed = 0;
840 krui_err err_code = KRERR_NO_ERROR;
841 struct np_symtab *list;
842 int index;
843 int chunk_sum;
844
845 TRACE_IN();
846
847 #ifdef DEBUG_CLASSES
848 TRACE_INDENT();
849 printf("%s(%s)\n", __FUNCTION__, class_sizes ? "unsigned int[]" : "NULL");
850 #endif
851
852 if (npui_curr_pat_set == -1)
853 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN_SET); }
854
855 if (np_info[npui_pat_sets[npui_curr_pat_set]].pub.classes <= 0)
856 { TRACE_RETURN(KRERR_NO_CLASSES); }
857
858 list = np_st[npui_pat_sets[npui_curr_pat_set]];
859 if (class_sizes == NULL)
860 {
861 while (list)
862 {
863 if (list->chunk_amount != list->set_amount)
864 {
865 list->chunk_amount = list->set_amount;
866 has_changed++;
867 }
868 list = list->next;
869 }
870 }
871 else
872 {
873 chunk_sum = 0;
874 for (index=0; index<np_info[npui_pat_sets[npui_curr_pat_set]].pub.classes;
875 index++)
876 chunk_sum += class_sizes[index];
877 if (chunk_sum == 0)
878 { TRACE_RETURN(KRERR_ILL_CLASS_DISTRIB); }
879
880 index = 0;
881 while (list)
882 {
883 if (list->chunk_amount != class_sizes[index])
884 {
885 list->chunk_amount = class_sizes[index];
886 has_changed++;
887 }
888 list = list->next;
889 index++;
890 }
891 if (index != np_info[npui_pat_sets[npui_curr_pat_set]].pub.classes)
892 fprintf(stderr, "internal error, file %s, line %d", __FILE__, __LINE__);
893 }
894
895 if (has_changed > 0)
896 {
897 np_pat_mapping_valid = FALSE;
898 np_abs_count_valid = FALSE;
899 err_code = kr_np_ValidateInfo(npui_pat_sets[npui_curr_pat_set]);
900 }
901
902 { TRACE_RETURN(err_code); }
903 }
904
905 /*****************************************************************************
906 FUNCTION : kr_npui_useChunk
907
908 PURPOSE :
909
910 Switch on or off the class distribution process.
911 If <active> is TRUE, the distribution process is activated. Therefore the
912 internal representation of the pattern set is virtually reorganized to match
913 the requested values of <class_sizes>. After that step the number of patterns
914 in the set virtually increases or decreases because each epoch must cover
915 every pattern of all classes that have a requested distribution amount bigger
916 than 0. This also implies that several patterns from a specific class are
917 reused several times during one epoch.
918
919 RETURNS : kernel error code
920 NOTES :
921
922 UPDATE :
923 ******************************************************************************/
kr_npui_useChunk(bool active)924 krui_err kr_npui_useChunk(bool active)
925 {
926 krui_err err_code = KRERR_NO_ERROR;
927
928 TRACE_IN();
929
930 #ifdef DEBUG_CLASSES
931 TRACE_INDENT();
932 printf("%s(%s)\n", __FUNCTION__, active ? "TRUE" : "FALSE");
933 #endif
934
935 if (npui_curr_pat_set == -1)
936 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN_SET); }
937
938 if (np_info[npui_pat_sets[npui_curr_pat_set]].pub.classes <= 0)
939 { TRACE_RETURN(KRERR_NO_CLASSES); }
940
941 if (np_info[npui_pat_sets[npui_curr_pat_set]].pub.class_distrib_active !=
942 active)
943 {
944 np_info[npui_pat_sets[npui_curr_pat_set]].pub.class_distrib_active =
945 active;
946
947 np_pat_mapping_valid = FALSE;
948 np_abs_count_valid = FALSE;
949 err_code = kr_np_ValidateInfo(npui_pat_sets[npui_curr_pat_set]);
950 }
951
952 { TRACE_RETURN(err_code); }
953 }
954
955 /*****************************************************************************
956 FUNCTION : kr_npui_setClass
957
958 PURPOSE :
959
960 Set the class name for the current pattern.
961 If the pattern set already contains class information, only the
962 current pattern is affected. If there are no classes in the pattern
963 set so far, all patterns of the current set are set to the given class
964 name, since every pattern must belong to a class in that case.
965 If the given class name is the NULL pointer, nothing happens at all.
966
967 RETURNS : kernel error code
968 NOTES :
969
970 UPDATE :
971 ******************************************************************************/
kr_npui_setClass(char * classname)972 krui_err kr_npui_setClass(char *classname)
973 {
974 np_pattern_descriptor *p;
975 krui_err err_code = KRERR_NO_ERROR;
976 struct np_symtab *old_entry;
977 struct np_symtab *new_entry;
978 int phys_num;
979
980 TRACE_IN();
981
982 #ifdef DEBUG_CLASSES
983 TRACE_INDENT();
984 printf("%s(%s)\n", __FUNCTION__, classname ? classname : "NULL");
985 #endif
986
987 if (!classname)
988 { TRACE_RETURN(KRERR_NO_ERROR); }
989
990 if (npui_curr_pat_set == -1)
991 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN_SET); }
992
993 if (npui_curr_pattern == -1)
994 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN); }
995
996 phys_num = kr_np_virtual_to_physical(npui_curr_pattern-1);
997 err_code = kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
998 phys_num, &p);
999 if (err_code != KRERR_NO_ERROR)
1000 { TRACE_RETURN(err_code); }
1001
1002 old_entry = p->mysym;
1003 err_code = kr_np_lookupSym(npui_pat_sets[npui_curr_pat_set],
1004 classname, &new_entry);
1005 if (err_code != KRERR_NO_ERROR)
1006 { TRACE_RETURN(err_code); }
1007
1008 if (old_entry == NULL)
1009 {
1010 int num, i;
1011
1012 /* all physical patterns are used here! */
1013 num = np_info[npui_pat_sets[npui_curr_pat_set]].pub.number_of_pattern;
1014
1015 p = np_pat_sets[npui_pat_sets[npui_curr_pat_set]];
1016 for (i=0; i<num; i++)
1017 {
1018 p->mysym = new_entry;
1019 p++;
1020 new_entry->set_amount++;
1021 }
1022 new_entry->chunk_amount = new_entry->set_amount;
1023 np_info[npui_pat_sets[npui_curr_pat_set]].pub.classes++;
1024 }
1025 else
1026 {
1027 if (new_entry == old_entry)
1028 { TRACE_RETURN(KRERR_NO_ERROR); }
1029 else
1030 {
1031 old_entry->set_amount--;
1032 if (old_entry->set_amount < old_entry->chunk_amount)
1033 old_entry->chunk_amount = old_entry->set_amount;
1034 if (old_entry->set_amount <= 0)
1035 {
1036 old_entry->chunk_amount = 0;
1037 np_info[npui_pat_sets[npui_curr_pat_set]].pub.classes--;
1038 kr_np_delSym(npui_pat_sets[npui_curr_pat_set], old_entry);
1039 }
1040
1041 if (new_entry->set_amount == 0)
1042 np_info[npui_pat_sets[npui_curr_pat_set]].pub.classes++;
1043 new_entry->set_amount++;
1044 if (new_entry->chunk_amount == 0)
1045 new_entry->chunk_amount = 1;
1046 }
1047 }
1048 p->mysym = new_entry;
1049 np_pat_mapping_valid = FALSE;
1050 np_abs_count_valid = FALSE;
1051 err_code = kr_np_ValidateInfo(npui_pat_sets[npui_curr_pat_set]);
1052
1053 npui_curr_pattern = 1 + kr_np_physical_to_virtual(phys_num);
1054
1055 { TRACE_RETURN(err_code); }
1056 }
1057
1058 /*****************************************************************************
1059 FUNCTIONS WHICH ARE CALLED BY OTHER KERNEL FUNCTIONS LIKE TRAINING
1060 AND INITIALIZATION FUNCTIONS:
1061 ******************************************************************************/
1062
1063 /*****************************************************************************
1064 FUNCTION : kr_np_pattern
1065
1066 PURPOSE : multiple pattern handling functions depending on mode and mode1
1067 RETURNS : result, depending on operation or kernel error code
1068 NOTES : KernelErrorCode is set to the valid kernel error code
1069
1070 UPDATE :
1071 ******************************************************************************/
kr_np_pattern(int mode,int mode1,int pattern_no)1072 int kr_np_pattern(int mode ,int mode1 ,int pattern_no)
1073 {
1074 int return_code;
1075 int new_pattern;
1076 np_pattern_set_info info;
1077 np_pattern_descriptor *pattern;
1078 np_pattern_descriptor *c_pattern;
1079
1080
1081 TRACE_IN();
1082
1083 #ifdef DEBUG_PATTERN
1084 TRACE_INDENT();
1085 printf("%s(", __FUNCTION__);
1086 switch (mode)
1087 {
1088 case PATTERN_SET: printf("PATTERN_SET"); break;
1089 case PATTERN_GET: printf("PATTERN_GET"); break;
1090 case PATTERN_DELETE: printf("PATTERN_DELETE"); break;
1091 case PATTERN_MODIFY: printf("PATTERN_MODIFY"); break;
1092 case PATTERN_SHOW: printf("PATTERN_SHOW"); break;
1093 case PATTERN_NEW: printf("PATTERN_NEW"); break;
1094 case PATTERN_DELETE_ALL: printf("PATTERN_DELETE_ALL"); break;
1095 case PATTERN_SHUFFLE_ON: printf("PATTERN_SHUFFLE_ON"); break;
1096 case PATTERN_SHUFFLE_OFF: printf("PATTERN_SHUFFLE_OFF"); break;
1097 case PATTERN_VECTOR_NEW: printf("PATTERN_VECTOR_NEW"); break;
1098 case PATTERN_ARRAY_ALLOC: printf("PATTERN_ARRAY_ALLOC"); break;
1099 case PATTERN_SET_NUMBER: printf("PATTERN_SET_NUMBER"); break;
1100 case PATTERN_GET_NUMBER: printf("PATTERN_GET_NUMBER"); break;
1101 case PATTERN_SUB_SHUFFLE_ON: printf("PATTERN_SUB_SHUFFLE_ON"); break;
1102 case PATTERN_SUB_SHUFFLE_OFF: printf("PATTERN_SUB_SHUFFLE_OFF"); break;
1103 case GET_SHUFFLE_FLAG: printf("GET_SHUFFLE_FLAG"); break;
1104 case GET_SUB_SHUFFLE_FLAG: printf("GET_SUB_SHUFFLE_FLAG"); break;
1105 case SUBPATTERN_GET_NUMBER: printf("SUBPATTERN_GET_NUMBER"); break;
1106 default: printf("%d", mode); break;
1107 }
1108 printf(", %d, %d)\n", mode1, pattern_no);
1109 #endif
1110
1111 return_code = (int) (KernelErrorCode = KRERR_NO_ERROR);
1112
1113 if (npui_curr_pat_set == -1)
1114 {
1115 KernelErrorCode = KRERR_NP_NO_CURRENT_PATTERN_SET;
1116 TRACE_RETURN((int) KernelErrorCode);
1117 }
1118
1119 /* for some modes, test current pattern definition */
1120 switch (mode)
1121 {
1122 case PATTERN_GET: /* returns the current pattern */
1123 case PATTERN_DELETE: /* delete the current pattern pair */
1124 case PATTERN_MODIFY: /* modify the current pattern pair */
1125 case PATTERN_SHOW: /* show pattern */
1126 if (npui_curr_pattern == -1 && mode != PATTERN_SET)
1127 {
1128 KernelErrorCode = KRERR_NP_NO_CURRENT_PATTERN;
1129 TRACE_RETURN((int) KernelErrorCode);
1130 }
1131 default:
1132 break;
1133 }
1134
1135 switch (mode)
1136 {
1137 case PATTERN_SET: /* set the current pattern */
1138 if (pattern_no < 1 || pattern_no >
1139 np_info[npui_pat_sets[npui_curr_pat_set]].pub.virtual_no_of_pattern)
1140 {
1141 return_code = (int) (KernelErrorCode = KRERR_PATTERN_NO);
1142 npui_curr_pattern = -1;
1143 }
1144 else
1145 npui_curr_pattern = pattern_no;
1146 break;
1147
1148 case PATTERN_GET: /* returns the current pattern */
1149 return_code = npui_curr_pattern;
1150 break;
1151
1152 case PATTERN_DELETE: /* delete the current pattern pair */
1153 return_code = kr_np_DeletePattern(npui_pat_sets[npui_curr_pat_set],
1154 kr_np_virtual_to_physical(npui_curr_pattern-1));
1155 npui_curr_pattern = -1;
1156
1157 np_info_valid[npui_pat_sets[npui_curr_pat_set]] = FALSE;
1158 np_pat_mapping_valid = FALSE;
1159 np_abs_count_valid = FALSE;
1160 return_code = kr_np_ValidateInfo(npui_pat_sets[npui_curr_pat_set]);
1161
1162 break;
1163
1164 case PATTERN_MODIFY: /* modify the current pattern pair */
1165 return_code = (int) (KernelErrorCode = kr_np_modifyPattern());
1166 break;
1167
1168 case PATTERN_SHOW: /* show pattern */
1169 return_code = (int) (KernelErrorCode = kr_np_showPatternSTD(mode1));
1170 break;
1171
1172 case PATTERN_NEW: /* new pattern */
1173 /* before creating a new pattern, first ensure that new pattern */
1174 /* fits into existing set */
1175 return_code = kr_np_GetInfo(npui_pat_sets[npui_curr_pat_set], &info);
1176 if (return_code != KRERR_NO_ERROR)
1177 break;
1178 (void) kr_IOCheck();
1179 if (NoOfInputUnits == 0)
1180 {
1181 return_code = KernelErrorCode = KRERR_NO_INPUT_UNITS;
1182 break;
1183 }
1184
1185 if (info.pub.number_of_pattern > 0)
1186 {
1187 if (info.pub.in_number_of_dims != 0 ||
1188 info.pub.out_number_of_dims != 0 ||
1189 info.pub.in_fixsize != NoOfInputUnits ||
1190 info.pub.out_fixsize != NoOfOutputUnits)
1191 {
1192 /* creation of variable sized patterns is not possible */
1193 /* also the new pattern must be of equal size compared to */
1194 /* existing pattern */
1195 return_code = KRERR_NP_INCOMPATIBLE_NEW;
1196 break;
1197 }
1198 }
1199
1200 if (npui_curr_pattern != -1)
1201 (void) kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
1202 kr_np_virtual_to_physical(npui_curr_pattern-1),
1203 &c_pattern);
1204 else
1205 c_pattern = NULL;
1206
1207 return_code = KernelErrorCode =
1208 kr_np_AddPattern(npui_pat_sets[npui_curr_pat_set], &new_pattern);
1209 if (return_code != KRERR_NO_ERROR)
1210 break;
1211
1212 (void) kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
1213 new_pattern, &pattern);
1214
1215 if (np_info[npui_pat_sets[npui_curr_pat_set]].pub.classes > 0)
1216 {
1217 /* the new pattern gets a symbol which is in use for the
1218 current chunk composition */
1219 if (c_pattern != NULL)
1220 pattern->mysym = c_pattern->mysym;
1221 else
1222 {
1223 pattern->mysym = np_st[npui_pat_sets[npui_curr_pat_set]];
1224 while (pattern->mysym && pattern->mysym->chunk_amount <= 0)
1225 pattern->mysym = pattern->mysym->next;
1226 if (pattern->mysym == NULL)
1227 {
1228 pattern->mysym = np_st[npui_pat_sets[npui_curr_pat_set]];
1229 pattern->mysym->chunk_amount = 1;
1230 }
1231 }
1232 pattern->mysym->set_amount++;
1233 }
1234
1235
1236 /* update internal information which is used to compute the new
1237 current pattern. To do this, the right pattern sizes must be set.
1238 They must be reset to 0 to allow allocation of memory space
1239 during later pattern modifikation */
1240 pattern->pub.input_fixsize = NoOfInputUnits;
1241 pattern->pub.output_fixsize = NoOfOutputUnits;
1242 np_info_valid[npui_pat_sets[npui_curr_pat_set]] = FALSE;
1243 np_pat_mapping_valid = FALSE;
1244 np_abs_count_valid = FALSE;
1245 return_code = kr_np_ValidateInfo(npui_pat_sets[npui_curr_pat_set]);
1246 npui_curr_pattern = 1 + kr_np_physical_to_virtual(new_pattern);
1247 pattern->pub.input_fixsize = 0;
1248 pattern->pub.output_fixsize = 0;
1249
1250 return_code = (int) (KernelErrorCode = kr_np_modifyPattern());
1251 if (return_code != KRERR_NO_ERROR)
1252 {
1253 (void) kr_np_DeletePattern(npui_pat_sets[npui_curr_pat_set],
1254 new_pattern);
1255 npui_curr_pattern = -1;
1256
1257 np_info_valid[npui_pat_sets[npui_curr_pat_set]] = FALSE;
1258 np_pat_mapping_valid = FALSE;
1259 np_abs_count_valid = FALSE;
1260 (void) kr_np_ValidateInfo(npui_pat_sets[npui_curr_pat_set]);
1261 break;
1262 }
1263
1264 break;
1265
1266 case PATTERN_DELETE_ALL: /* delete all pattern */
1267 break;
1268
1269 case PATTERN_SHUFFLE_ON: /* shuffle pattern */
1270 npui_shuffle_pattern = TRUE;
1271 break;
1272
1273 case PATTERN_SHUFFLE_OFF: /* shuffle pattern off */
1274 npui_shuffle_pattern = FALSE;
1275 break;
1276
1277 case PATTERN_SET_NUMBER:
1278 break;
1279
1280 case PATTERN_GET_NUMBER:
1281 return_code =
1282 np_info[npui_pat_sets[npui_curr_pat_set]].pub.virtual_no_of_pattern;
1283 break;
1284
1285 case SUBPATTERN_GET_NUMBER:
1286 return_code =
1287 kr_TotalNoOfSubPatPairs();
1288 break;
1289
1290
1291 case PATTERN_SUB_SHUFFLE_ON:
1292 npui_shuffle_sub_pattern = TRUE;
1293 break;
1294
1295 case PATTERN_SUB_SHUFFLE_OFF:
1296 npui_shuffle_sub_pattern = FALSE;
1297 break;
1298
1299 case GET_SHUFFLE_FLAG:
1300 return_code = npui_shuffle_pattern;
1301 break;
1302
1303 case GET_SUB_SHUFFLE_FLAG:
1304 return_code = npui_shuffle_sub_pattern;
1305 break;
1306
1307 default:
1308 KernelErrorCode = KRERR_PARAMETERS;
1309 }
1310
1311 { TRACE_RETURN(return_code); }
1312 }
1313
1314 /*****************************************************************************
1315 FUNCTION : kr_initSubPatternOrder
1316
1317 PURPOSE : The sub pattern ordering for the current pattern set is
1318 reset for the next training or initialization run. During
1319 this run all sub patterns from pattern <start> up to
1320 pattern <end> are generated according to current shuffle
1321 flags for patterns and sub patterns.
1322 kr_getSubPatByOrder is to be called to get the next sub
1323 pattern number during the run (see below)
1324
1325 RETURNS : kernel error code
1326 NOTES :
1327
1328 UPDATE :
1329 ******************************************************************************/
kr_initSubPatternOrder(int start,int end)1330 krui_err kr_initSubPatternOrder(int start, int end)
1331 {
1332 int pat_set;
1333 int n_sub;
1334
1335 TRACE_IN();
1336
1337 if (!npui_train_defined)
1338 { TRACE_RETURN(KRERR_NP_NO_TRAIN_SCHEME); }
1339
1340 pat_set = npui_pat_sets[npui_curr_pat_set];
1341
1342 if (npui_shuffle_pattern && npui_shuffle_sub_pattern)
1343 {
1344 np_random_train_number = kr_TotalNoOfSubPatPairs();
1345 np_next_train_random = 0;
1346 { TRACE_RETURN(KRERR_NO_ERROR); }
1347 }
1348
1349 if (!kr_np_allocate_pat_train_entries(np_info[pat_set].pub.virtual_no_of_pattern))
1350 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
1351
1352 if (np_info[pat_set].pub.class_distrib_active)
1353 {
1354 kr_np_order_chunk_arrays(npui_shuffle_pattern, pat_set);
1355 kr_np_order_chunked_pat_entries(pat_set, start, end);
1356 }
1357 else
1358 {
1359 kr_np_order_pat_entries(start, end);
1360 }
1361
1362 np_current_pattern =
1363 &(np_pat_sets[pat_set][np_pat_train_order[0]]);
1364 np_next_train_pat = 0;
1365
1366 kr_np_gen_sub_pos(np_current_pattern -> pub.input_dim, &n_sub,
1367 np_current_pattern -> pub.input_dim_sizes, np_t_insize,
1368 np_t_instep, NULL, TRUE);
1369
1370 if (!kr_np_allocate_sub_pat_train_entries(n_sub))
1371 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
1372
1373 kr_np_order_sub_pat_entries(0, n_sub-1);
1374 np_next_train_sub_pat = 0;
1375
1376 { TRACE_RETURN(KRERR_NO_ERROR); }
1377 }
1378
1379 /*****************************************************************************
1380 FUNCTION : kr_getSubPatternByOrder
1381
1382 PURPOSE : According to the last call to kr_initSubPatternOrder, the
1383 last call to this function and the shuffle flags, the next position
1384 of pattern and sub pattern is determined. This numbers are returned
1385 in <pattern> and <sub> (beginning with 0).
1386
1387 RETURNS : If there are no more sub pattern avaliable the return
1388 value is FALSE, otherwise TRUE.
1389 NOTES :
1390
1391 UPDATE :
1392 ******************************************************************************/
kr_getSubPatternByOrder(int * pattern,int * sub)1393 bool kr_getSubPatternByOrder(int *pattern, int *sub)
1394 {
1395 int n_sub;
1396
1397 TRACE_IN();
1398
1399 if (npui_shuffle_pattern && npui_shuffle_sub_pattern)
1400 {
1401 if (np_next_train_random == -1)
1402 { TRACE_RETURN(FALSE); }
1403
1404 if (++np_next_train_random >= np_random_train_number)
1405 np_next_train_random = -1;
1406
1407 TRACE_RETURN((kr_getSubPatternByNo(pattern, sub,
1408 lrand48() % np_random_train_number)));
1409 }
1410
1411 if (np_next_train_pat == -1)
1412 { TRACE_RETURN(FALSE); }
1413
1414 *pattern = np_pat_train_order[np_next_train_pat];
1415 *sub = np_sub_pat_train_order[np_next_train_sub_pat];
1416
1417 np_next_train_sub_pat++;
1418 if (np_next_train_sub_pat >= np_sub_pat_train_number)
1419 {
1420 np_next_train_pat++;
1421 if (np_next_train_pat >= np_pat_train_number)
1422 {
1423 np_next_train_pat = -1;
1424 { TRACE_RETURN(TRUE); }
1425 }
1426
1427 np_current_pattern =
1428 &(np_pat_sets[npui_pat_sets[npui_curr_pat_set]]
1429 [np_pat_train_order[np_next_train_pat]]);
1430
1431 kr_np_gen_sub_pos(np_current_pattern -> pub.input_dim, &n_sub,
1432 np_current_pattern -> pub.input_dim_sizes, np_t_insize,
1433 np_t_instep, NULL, TRUE);
1434
1435 if (!kr_np_allocate_sub_pat_train_entries(n_sub))
1436 {
1437 KernelErrorCode = KRERR_INSUFFICIENT_MEM;
1438 { TRACE_RETURN(FALSE); }
1439 }
1440
1441 kr_np_order_sub_pat_entries(0, n_sub-1);
1442 np_next_train_sub_pat = 0;
1443 }
1444
1445 { TRACE_RETURN(TRUE); }
1446 }
1447
1448 /*****************************************************************************
1449 FUNCTION : kr_getSubPatternByNo
1450
1451 PURPOSE : According to the current pattern set, the position of the
1452 <n>th sub pattern is determined and returned in <pattern> (the
1453 pattern which includes the subpattern) and <sub> (the sub pattern
1454 inside the pattern) (beginning with 0).
1455 This function does not effect the ordering of the function
1456 kr_getSubPatByOrder. <n> ranges from 0 to kr_TotalNoOfSubPatPairs()-1.
1457
1458 RETURNS : If the sub pattern is available, TRUE is returned,
1459 otherwise FALSE.
1460
1461 NOTES :
1462
1463 UPDATE :
1464 ******************************************************************************/
kr_getSubPatternByNo(int * pattern,int * sub,int n)1465 bool kr_getSubPatternByNo(int *pattern, int *sub, int n)
1466 {
1467 register int ts;
1468 register int tp;
1469 register int low, high, mid;
1470
1471 TRACE_IN();
1472
1473 ts = kr_TotalNoOfSubPatPairs();
1474 if (n<0 || n>=ts)
1475 { TRACE_RETURN(FALSE); }
1476
1477 tp = np_info[npui_pat_sets[npui_curr_pat_set]].pub.virtual_no_of_pattern;
1478
1479 if (tp == 1)
1480 /* only one pattern present, sub pattern must be here */
1481 high = 0;
1482 else
1483 {
1484 /* more than one pattern present.... */
1485 /* first try to find the right position by a direct jump */
1486 high = (int)(((double)n*(double)tp)/(double)ts);
1487
1488 if (np_abs_count[high] <= n || (high != 0 && np_abs_count[high-1] > n))
1489 {
1490 /* direct jump was not sucessfull, now perform binary search */
1491 low = 0;
1492 high = tp-1;
1493 while (low < high)
1494 {
1495 mid = (high+low)/2;
1496 if (np_abs_count[mid] > n)
1497 high = mid;
1498 else
1499 low = mid+1;
1500 }
1501 }
1502 }
1503
1504 /* now high gives the index of the pattern where the sub pattern is in */
1505 /* but np_abs_count is based on virtual pattern, while this function must
1506 return a physical pattern number: */
1507 *pattern = kr_np_virtual_to_physical(high);
1508
1509 /* calculate the position of the sub pattern inside the found pattern */
1510 if (high != 0)
1511 *sub = n - np_abs_count[high-1];
1512 else
1513 *sub = n;
1514
1515 { TRACE_RETURN(TRUE); }
1516 }
1517
1518 /*****************************************************************************
1519 FUNCTION : kr_TotalNoOfSubPatPairs
1520
1521 PURPOSE : This function returns the total number of available sub
1522 patterns for the current pattern set or 0 if no pattern set is
1523 defined. The result is the sum of the numbers of subpattern for all
1524 patterns in the current set.
1525
1526 RETURNS : number of sub pattern or 0
1527 NOTES :
1528
1529 UPDATE :
1530 ******************************************************************************/
kr_TotalNoOfSubPatPairs(void)1531 int kr_TotalNoOfSubPatPairs(void)
1532 {
1533 int n;
1534 int i;
1535 int sum;
1536 int n_sub;
1537 np_pattern_descriptor *pat;
1538
1539 TRACE_IN();
1540
1541 if (np_abs_count_valid)
1542 { TRACE_RETURN(np_abs_count_No); }
1543
1544 if (npui_curr_pat_set == -1)
1545 { TRACE_RETURN(0); }
1546
1547 n = np_info[npui_pat_sets[npui_curr_pat_set]].pub.virtual_no_of_pattern;
1548
1549 if (n > np_abs_count_size)
1550 {
1551 if (np_abs_count != (int *) NULL)
1552 free(np_abs_count);
1553 np_abs_count_size = 0;
1554 np_abs_count = (int *) malloc(n * sizeof(int));
1555 if (np_abs_count == (int *) NULL && n != 0)
1556 { TRACE_RETURN(0); }
1557 np_abs_count_size = n;
1558 }
1559
1560 sum = 0;
1561 for (i=0; i<n; i++)
1562 {
1563 kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
1564 kr_np_virtual_to_physical(i), &pat);
1565 kr_np_gen_sub_pos(pat -> pub.input_dim, &n_sub,
1566 pat -> pub.input_dim_sizes, np_t_insize,
1567 np_t_instep, NULL, TRUE);
1568 sum += n_sub;
1569 np_abs_count[i] = sum;
1570 }
1571 np_abs_count_No = sum;
1572 np_abs_count_valid = TRUE;
1573
1574 { TRACE_RETURN(np_abs_count_No); }
1575 }
1576
1577 /*****************************************************************************
1578 FUNCTION : kr_NoOfSubPatPairs
1579
1580 PURPOSE : This function returns the number of available sub patterns
1581 for the pattern <pattern> of the current pattern set or 0 if this
1582 pattern is not defined.
1583
1584 RETURNS :
1585 NOTES :
1586
1587 UPDATE :
1588 ******************************************************************************/
kr_NoOfSubPatPairs(int pattern)1589 int kr_NoOfSubPatPairs(int pattern)
1590 {
1591 register int ps;
1592
1593 TRACE_IN();
1594
1595 if (!np_abs_count_valid)
1596 {
1597 if (kr_TotalNoOfSubPatPairs() == 0)
1598 { TRACE_RETURN(0); }
1599 }
1600
1601 if (pattern<0 ||
1602 pattern > np_info[npui_pat_sets[npui_curr_pat_set]].pub.virtual_no_of_pattern)
1603 { TRACE_RETURN(0); }
1604
1605 ps = np_abs_count[pattern];
1606
1607 if (pattern == 0)
1608 { TRACE_RETURN(ps); }
1609 else
1610 TRACE_RETURN((ps - np_abs_count[pattern-1]));
1611 }
1612
1613 /*****************************************************************************
1614 FUNCTION : kr_AbsPosOfFirstSubPat
1615
1616 PURPOSE : This function returns the absolute position of the first
1617 sub pattern of pattern <pattern> in the current pattern set. This
1618 position is defined as the Sum of kr_NoOfSubPatPairs(i) where i runs
1619 from 0 to <pattern>-1. The absolute position of the first sub
1620 pattern of pattern 0 is 0. The returned value may be used as
1621 argument for the function kr_getSubPatternByNo.
1622
1623 RETURNS :
1624 NOTES :
1625
1626 UPDATE :
1627 ******************************************************************************/
kr_AbsPosOfFirstSubPat(int pattern)1628 int kr_AbsPosOfFirstSubPat(int pattern)
1629 {
1630 TRACE_IN();
1631
1632 if (!np_abs_count_valid)
1633 {
1634 if (kr_TotalNoOfSubPatPairs() == 0)
1635 { TRACE_RETURN(0); }
1636 }
1637
1638 if (pattern <= 0 ||
1639 pattern > np_info[npui_pat_sets[npui_curr_pat_set]].pub.virtual_no_of_pattern)
1640 { TRACE_RETURN(0); }
1641
1642 { TRACE_RETURN(np_abs_count[pattern-1]); }
1643 }
1644
1645 /*****************************************************************************
1646 FUNCTION : kr_TotalNoOfPattern
1647
1648 PURPOSE : This function returns the total number of available
1649 patterns for the current pattern set or 0 if no pattern set is
1650 defined.
1651
1652 RETURNS : number of pattern or 0
1653 NOTES :
1654
1655 UPDATE :
1656 ******************************************************************************/
kr_TotalNoOfPattern(void)1657 int kr_TotalNoOfPattern(void)
1658 {
1659 TRACE_IN();
1660
1661 if (npui_curr_pat_set == -1)
1662 { TRACE_RETURN(0); }
1663
1664 { TRACE_RETURN(np_info[npui_pat_sets[npui_curr_pat_set]].pub.virtual_no_of_pattern); }
1665 }
1666
1667 /*****************************************************************************
1668 FUNCTION : kr_getSubPatData
1669
1670 PURPOSE : For the current pattern set and the specified sub pattern
1671 size, the data array of the <sub_no>th sub pattern of the <pat_no>th
1672 pattern is returned. io_type spcifies whether the input (INPUT) or
1673 output (OUTPUT) data is requested. If <size> is != NULL the size of
1674 the data array is returned is this parameter.
1675
1676 RETURNS : The function returns a pointer to the data array (type
1677 Patterns) or NULL if an error occured.
1678 NOTES : KernelErrorCode is set if an error occured
1679
1680 UPDATE :
1681 ******************************************************************************/
kr_getSubPatData(int pat_no,int sub_no,int io_type,int * size)1682 Patterns kr_getSubPatData(int pat_no, int sub_no, int io_type, int *size)
1683 {
1684 int set;
1685 np_pattern_descriptor *pat;
1686 int subpos[MAX_NO_OF_VAR_DIM];
1687 float *data;
1688 krui_err err;
1689 static float dummy_data = 0.0;
1690 int intsize;
1691
1692 TRACE_IN();
1693
1694 #ifdef DEBUG_PATTERN
1695 TRACE_INDENT();
1696 fprintf(stderr, "pattern %d, sub %d, %s\n", pat_no, sub_no, io_type == INPUT ? "INPUT" : "OUTPUT");
1697 #endif
1698
1699 set = npui_pat_sets[npui_curr_pat_set];
1700 pat = np_pat_sets[set];
1701
1702 if (pat_no >= np_info[set].pub.number_of_pattern)
1703 TRACE_RETURN((Patterns) NULL);
1704
1705 pat += pat_no;
1706 np_current_pattern = pat;
1707 switch (io_type)
1708 {
1709 case INPUT:
1710 if (!kr_np_gen_sub_pos(pat->pub.input_dim, &sub_no, pat->pub.input_dim_sizes,
1711 np_t_insize, np_t_instep, subpos, FALSE))
1712 {
1713 KernelErrorCode = KRERR_NP_NO_SUCH_PATTERN;
1714 TRACE_RETURN((Patterns) NULL);
1715 }
1716 if ((err = kr_np_GetSubPat(TRUE, subpos, np_t_insize, &data, &intsize))
1717 != KRERR_NO_ERROR)
1718 {
1719 KernelErrorCode = err;
1720 TRACE_RETURN((Patterns) NULL);
1721 }
1722 if (size != NULL)
1723 *size = intsize;
1724
1725 #ifdef PRINT_USED_PATTERNS
1726 {
1727 int ind;
1728 printf("I %d %d '%s' ", pat_no, sub_no,
1729 pat->mysym != NULL && pat->mysym->symname ?
1730 pat->mysym->symname : "");
1731 for (ind=0; ind<intsize; ind++)
1732 printf("%g ", data[ind]);
1733 printf("\n");
1734 }
1735 #endif
1736
1737 TRACE_RETURN((Patterns) data);
1738 break;
1739 case OUTPUT:
1740 if (!kr_np_gen_sub_pos(pat->pub.output_dim, &sub_no, pat->pub.output_dim_sizes,
1741 np_t_outsize, np_t_outstep, subpos, FALSE))
1742 {
1743 KernelErrorCode = KRERR_NP_NO_SUCH_PATTERN;
1744 TRACE_RETURN((Patterns) NULL);
1745 }
1746 if ((err = kr_np_GetSubPat(FALSE, subpos, np_t_outsize, &data, &intsize))
1747 != KRERR_NO_ERROR)
1748 {
1749 KernelErrorCode = err;
1750 TRACE_RETURN((Patterns) NULL);
1751 }
1752 if (size != NULL)
1753 *size = intsize;
1754
1755 #ifdef PRINT_USED_PATTERNS
1756 {
1757 int ind;
1758 printf("O %d %d '%s' ", pat_no, sub_no,
1759 pat->mysym != NULL && pat->mysym->symname ?
1760 pat->mysym->symname : "");
1761 for (ind=0; ind<intsize; ind++)
1762 printf("%g ", data[ind]);
1763 printf("\n");
1764 }
1765 #endif
1766
1767 /* kr_np_GetSubPat reports no error if a zero length output sub */
1768 /* pattern is requested. Instead a NULL pointer is returned but */
1769 /* must be exchanged by a dummy non NULL pointer because this */
1770 /* function reports errors by NULL pointers */
1771 if (data == 0)
1772 TRACE_RETURN((Patterns) &dummy_data);
1773
1774 TRACE_RETURN((Patterns) data);
1775 break;
1776 default:
1777 KernelErrorCode = KRERR_PARAMETERS;
1778 TRACE_RETURN((Patterns) NULL);
1779 }
1780 }
1781
1782 /*****************************************************************************
1783 FUNCTION : kr_getPatClass
1784
1785 PURPOSE : For the current pattern set and the specified sub pattern,
1786 the class index (>=0) is returned. If the pattern set does not
1787 provide class information, the return value is -1
1788 RETURNS : class index or -1, if no classes available
1789 NOTES : sub_no is of no effect, since class information only refers
1790 to patterns and not to sub patterns
1791 The parameter is kept for future improvements.
1792
1793 UPDATE :
1794 *****************************************************************************/
kr_getSubPatClass(int pat_no,int sub_no)1795 extern int kr_getSubPatClass(int pat_no, int sub_no)
1796 {
1797 int set;
1798 np_pattern_descriptor *pat;
1799
1800 TRACE_IN();
1801
1802 set = npui_pat_sets[npui_curr_pat_set];
1803 pat = np_pat_sets[set];
1804
1805 if (pat_no < 0 || pat_no >= np_info[set].pub.number_of_pattern)
1806 TRACE_RETURN(-1);
1807
1808 pat += pat_no;
1809 TRACE_RETURN(pat->pub.my_class);
1810 }
1811
1812 /*****************************************************************************
1813 FUNCTION : kr_SizeOfInputSubPat
1814
1815 PURPOSE : For the current pattern set and the specified sub pattern size,
1816 the size of the input part of the first sub pattern of the first pattern is
1817 returned. Negative return values indicate KernelErrorCode. Size 0 is a valid
1818 return value since the pattern may contain no data.
1819 RETURNS : negative Kernel Error Codes or positive valid value
1820 NOTES :
1821
1822 UPDATE :
1823 ******************************************************************************/
kr_SizeOfInputSubPat(void)1824 int kr_SizeOfInputSubPat(void)
1825 {
1826 krui_err err;
1827
1828 TRACE_IN();
1829
1830 if (np_sub_pat_sizes_valid)
1831 { TRACE_RETURN(np_sub_pat_input_size); }
1832
1833 err = kr_np_GetSubPatSizes(&np_sub_pat_input_size,
1834 &np_sub_pat_output_size);
1835
1836 if (err == KRERR_NO_ERROR)
1837 {
1838 np_sub_pat_sizes_valid = TRUE;
1839 { TRACE_RETURN(np_sub_pat_input_size); }
1840 }
1841
1842 { TRACE_RETURN(err); }
1843 }
1844
1845 /*****************************************************************************
1846 FUNCTION : kr_SizeOfOutputSubPat
1847
1848 PURPOSE : For the current pattern set and the specified sub pattern size,
1849 the size of the output part of the first sub pattern of the first pattern is
1850 returned. Negative return values indicate KernelErrorCode. Size 0 is a valid
1851 return value since the pattern may contain no data.
1852 RETURNS : negative Kernel Error Codes or positive valid value
1853 NOTES :
1854
1855 UPDATE :
1856 ******************************************************************************/
kr_SizeOfOutputSubPat(void)1857 int kr_SizeOfOutputSubPat(void)
1858 {
1859 krui_err err;
1860
1861 TRACE_IN();
1862
1863 if (np_sub_pat_sizes_valid)
1864 { TRACE_RETURN(np_sub_pat_output_size); }
1865
1866 err = kr_np_GetSubPatSizes(&np_sub_pat_input_size,
1867 &np_sub_pat_output_size);
1868
1869 if (err == KRERR_NO_ERROR)
1870 {
1871 np_sub_pat_sizes_valid = TRUE;
1872 { TRACE_RETURN(np_sub_pat_output_size); }
1873 }
1874
1875 { TRACE_RETURN(err); }
1876 }
1877
1878 /*****************************************************************************
1879 FUNCTIONS WHICH ARE CALLED BY THE PATTERN PARSER OR FROM INSIDE THIS
1880 MODULE. DON'T USE THESE FUNCTIONS FOR OTHER PURPOSES !!!!!
1881 ******************************************************************************/
1882
1883 /*****************************************************************************
1884 FUNCTION : kr_np_AllocatePatternSet
1885
1886 PURPOSE : looks for a free slot in pattern set array and allocates <number>
1887 of free pattern descriptors
1888
1889 RETURNS : kernel error code
1890 NOTES : don't call this function. This function is only to be
1891 called by the parser or by functions inside this module
1892
1893 UPDATE :
1894 ******************************************************************************/
kr_np_AllocatePatternSet(int * pat_set,int number)1895 krui_err kr_np_AllocatePatternSet(int *pat_set, int number)
1896 {
1897 krui_err err_code;
1898 int i;
1899 int set = -1;
1900
1901 TRACE_IN();
1902
1903 if (np_used_pat_set_entries == 0)
1904 {
1905 /* never patterns allocated */
1906 err_code = kr_np_InitPattern();
1907 if (err_code != KRERR_NO_ERROR)
1908 { TRACE_RETURN(err_code); }
1909 }
1910
1911 /* check for free pattern set entry */
1912 for (i=0; i<np_used_pat_set_entries; i++)
1913 {
1914 if (!np_pat_set_used[i])
1915 {
1916 set = i;
1917 break;
1918 }
1919 }
1920 if (set == -1)
1921 {
1922 /* no more free entries */
1923 { TRACE_RETURN(KRERR_NP_NO_MORE_ENTRIES); }
1924 }
1925
1926 /* allocate array of pattern descriptors */
1927 np_pat_sets[set] =
1928 (np_pattern_descriptor *) malloc(number * sizeof(np_pattern_descriptor));
1929 if (np_pat_sets[set] == (np_pattern_descriptor *) NULL && number != 0)
1930 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
1931
1932 /* initialize part of the pattern descriptors */
1933 for (i=0; i<number; i++)
1934 {
1935 np_pat_sets[set][i].pub.input_fixsize = 0;
1936 np_pat_sets[set][i].pub.output_fixsize = 0;
1937 np_pat_sets[set][i].pub.my_class = -1;
1938
1939 np_pat_sets[set][i].input_pattern = (float *) NULL;
1940 np_pat_sets[set][i].output_pattern = (float *) NULL;
1941
1942 np_pat_sets[set][i].mysym = (struct np_symtab *) NULL;
1943 }
1944
1945 /* store number of allocated descriptors */
1946 np_info[set].pub.number_of_pattern = number;
1947 np_info[set].pub.virtual_no_of_pattern = number;
1948 np_info[set].pub.classes = 0;
1949 np_info[set].pub.class_names = NULL;
1950 np_info[set].pub.class_distrib_active = FALSE;
1951 np_info[set].pub.class_redistribution = NULL;
1952 np_info[set].pub.remap_function = NULL;
1953 np_info[set].pub.no_of_remap_params = 0;
1954 np_info[set].rmf_ptr = NULL;
1955 np_info_valid[set] = FALSE; /* only number_of_pattern is valid */
1956
1957 /* sucessfull return */
1958 np_pat_set_used[set] = TRUE;
1959 *pat_set = set;
1960 { TRACE_RETURN(KRERR_NO_ERROR); }
1961 }
1962
1963 /*****************************************************************************
1964 FUNCTION : kr_np_AllocatePattern
1965
1966 PURPOSE : uses the information provided in given pattern descriptor to
1967 allocate memory for pattern data
1968
1969 RETURNS : kernel error code
1970 NOTES : don't call this function. This function is only to be
1971 called by the parser or by functions inside this module
1972
1973 UPDATE :
1974 ******************************************************************************/
kr_np_AllocatePattern(np_pattern_descriptor * pattern,bool input)1975 krui_err kr_np_AllocatePattern(np_pattern_descriptor *pattern,
1976 bool input)
1977 {
1978 int i;
1979 int size;
1980
1981 TRACE_IN();
1982
1983 if (np_used_pat_set_entries == 0)
1984 { TRACE_RETURN(KRERR_NO_PATTERNS); }
1985
1986 if (input)
1987 {
1988 size = pattern -> pub.input_fixsize;
1989 for (i=0; i<pattern -> pub.input_dim; i++)
1990 size *= (pattern -> pub.input_dim_sizes)[i];
1991
1992 if (pattern -> pub.input_dim > 0)
1993 pattern -> input_pattern = (float *) malloc(size * sizeof(float));
1994 else
1995 pattern -> input_pattern = kr_np_floatmalloc(size);
1996
1997 if (pattern -> input_pattern == (float *) NULL && size != 0)
1998 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
1999 else
2000 { TRACE_RETURN(KRERR_NO_ERROR); }
2001 }
2002 else
2003 {
2004 size = pattern -> pub.output_fixsize;
2005 for (i=0; i<pattern -> pub.output_dim; i++)
2006 size *= (pattern -> pub.output_dim_sizes)[i];
2007
2008 if (pattern -> pub.output_dim > 0)
2009 pattern -> output_pattern = (float *) malloc(size * sizeof(float));
2010 else
2011 pattern -> output_pattern = kr_np_floatmalloc(size);
2012
2013 if (pattern -> output_pattern == (float *) NULL && size != 0)
2014 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
2015 else
2016 { TRACE_RETURN(KRERR_NO_ERROR); }
2017 }
2018 }
2019
2020 /*****************************************************************************
2021 FUNCTION : kr_np_freePattern
2022
2023 PURPOSE : frees the area of the pattern data for this pattern
2024
2025 RETURNS :
2026 NOTES : don't call this function. This function is only to be
2027 called by the parser or by functions inside this module
2028
2029 UPDATE :
2030 ******************************************************************************/
kr_np_FreePattern(np_pattern_descriptor * pattern)2031 void kr_np_FreePattern(np_pattern_descriptor *pattern)
2032 {
2033 if (pattern -> input_pattern)
2034 {
2035 if (pattern -> pub.input_dim > 0)
2036 free(pattern -> input_pattern);
2037 else
2038 kr_np_floatfree(pattern -> input_pattern);
2039 }
2040
2041 if (pattern -> output_pattern)
2042 {
2043 if (pattern -> pub.output_dim > 0)
2044 free(pattern -> output_pattern);
2045 else
2046 kr_np_floatfree(pattern -> output_pattern);
2047 }
2048 }
2049
2050 /*****************************************************************************
2051 FUNCTION : kr_np_GetDescriptor
2052
2053 PURPOSE : determine a pointer to a specified pattern descriptor
2054 and make this pattern to be the current pattern
2055
2056 RETURNS : kernel error code
2057 NOTES : don't call this function. This function is only to be
2058 called by the parser or by functions inside this module
2059
2060 <number> is a physical pattern number!
2061
2062 UPDATE :
2063 ******************************************************************************/
kr_np_GetDescriptor(int pat_set,int number,np_pattern_descriptor ** pattern)2064 krui_err kr_np_GetDescriptor(int pat_set, int number,
2065 np_pattern_descriptor **pattern)
2066 {
2067 TRACE_IN();
2068
2069 if (np_used_pat_set_entries == 0)
2070 { TRACE_RETURN(KRERR_NO_PATTERNS); }
2071
2072 if (pat_set < 0 || pat_set >= np_used_pat_set_entries ||
2073 !np_pat_set_used[pat_set])
2074 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2075
2076 if (number >= np_info[pat_set].pub.number_of_pattern)
2077 { TRACE_RETURN(KRERR_PATTERN_NO); }
2078
2079 *pattern = np_current_pattern = &(np_pat_sets[pat_set][number]);
2080
2081 { TRACE_RETURN(KRERR_NO_ERROR); }
2082 }
2083
2084 /*****************************************************************************
2085 FUNCTION : kr_np_lookupSym
2086
2087 PURPOSE : Find an entry in the set specific symbol table or create a
2088 new entry. If a new entry is created, also the numbering of symbols
2089 must be re-updated.
2090
2091 RETURNS : kernel error code
2092 NOTES : don't call this function. This function is only to be
2093 called by the parser or by functions inside this module
2094
2095 UPDATE :
2096 ******************************************************************************/
kr_np_lookupSym(int pat_set,char * symbol,struct np_symtab ** entry)2097 krui_err kr_np_lookupSym(int pat_set, char *symbol, struct np_symtab **entry)
2098 {
2099 struct np_symtab *list;
2100 struct np_symtab *newsym;
2101 struct np_symtab *last = NULL;
2102 int list_cmp;
2103 int last_cmp;
2104 int i;
2105
2106 TRACE_IN();
2107
2108 list = np_st[pat_set];
2109 while (list != NULL && (list_cmp = strcmp(symbol, list->symname)) > 0)
2110 {
2111 last = list;
2112 last_cmp = list_cmp;
2113 list = list->next;
2114 }
2115
2116 if (list != NULL && list_cmp == 0)
2117 *entry = list;
2118 else
2119 {
2120 newsym = (struct np_symtab *) malloc(sizeof(struct np_symtab));
2121 if (!newsym)
2122 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
2123 newsym->symname = strdup(symbol);
2124 if (!newsym->symname)
2125 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
2126 newsym->set_amount = 0;
2127 newsym->chunk_amount = 0;
2128 newsym->symnum = 0;
2129 newsym->my_chunks_per_set = 0;
2130 newsym->global_chunks = 0;
2131 newsym->pat_nums_size = 0;
2132 newsym->pat_nums_valid = 0;
2133 newsym->pat_nums = NULL;
2134 newsym->within_chunk_pos = -1;
2135 newsym->pat_num_pos = -1;
2136 newsym->next = list;
2137 if (last)
2138 last->next = newsym;
2139 else
2140 np_st[pat_set] = newsym;
2141 *entry = newsym;
2142
2143 list = np_st[pat_set];
2144 i = 0;
2145 while (list)
2146 {
2147 list->symnum = i++;
2148 list = list->next;
2149 }
2150 }
2151
2152 { TRACE_RETURN(KRERR_NO_ERROR); }
2153 }
2154
2155 /*****************************************************************************
2156 INTERNAL FUNCTIONS OF THIS MODULE. IMPOSSIBLE TO CALL THESE FUNCTIONS
2157 FROM OUTSIDE THE MODULE (IF NOBODY CHANGES THE STATIC DECLARATION) !!!!!!!
2158 ******************************************************************************/
2159
2160 #ifdef DEBUG_PATTERN
print_page_info(struct patternpage * page)2161 static print_page_info(struct patternpage *page)
2162 {
2163 int fl;
2164 int cnt;
2165
2166 if (!page)
2167 printf("empty page\n");
2168 else
2169 {
2170 printf("id: %0lx, size: %d, slots: %d, free_slots: %d, list: ",
2171 (long) page, page->slotsize, page->no_of_slots, page->no_of_free_slots);
2172 fl = page->firstfree;
2173 cnt = 0;
2174 do
2175 {
2176 printf("%d ", fl);
2177 fl = *((int *) ((float *) page->data + fl));
2178 cnt++;
2179 } while (fl != -1 && cnt < 20);
2180 if (fl != -1)
2181 printf("...");
2182 printf("\n");
2183 }
2184 }
2185 #endif
2186
2187 /*****************************************************************************
2188 FUNCTION : kr_np_floatmalloc
2189
2190 PURPOSE : allocate pattern memory within a private memory page
2191 <size> is based on sizeof(float) !!!
2192 RETURNS : float* pointer or NULL if
2193 NOTES : internal use only
2194
2195 UPDATE :
2196 ******************************************************************************/
kr_np_floatmalloc(int size)2197 static float *kr_np_floatmalloc(int size)
2198 {
2199 struct patternpage *page;
2200 int no_of_slots;
2201 int i;
2202 float *retval;
2203
2204 /* size must be >= 0 */
2205 if (size < 0)
2206 return NULL;
2207
2208 /* size must be at least big enough to hold the index free list */
2209 if (size*sizeof(float) < sizeof(int))
2210 size = ((sizeof(int)-1)/sizeof(float) + 1);
2211
2212 /* check for page with requested slotsize */
2213 page = np_pages;
2214 while (page != NULL && (page->slotsize != size || page->no_of_free_slots == 0))
2215 page = page->next;
2216
2217 if (!page)
2218 {
2219 /* we need to allocate a new page */
2220 no_of_slots = KRNP_FIXED_PAGESIZE/(size * sizeof(float));
2221 if (no_of_slots < 1)
2222 no_of_slots = 1;
2223
2224 page = (struct patternpage *) malloc(sizeof(struct patternpage));
2225 if (!page)
2226 return NULL;
2227 #ifdef DEBUG_PATTERN
2228 printf("allocating 0x%lx bytes for new pattern page\n",
2229 size * no_of_slots * sizeof(float));
2230 #endif
2231 page->data = (float *) malloc(size * no_of_slots * sizeof(float));
2232 if (!page->data)
2233 return NULL;
2234
2235 page->slotsize = size;
2236 page->no_of_slots = page->no_of_free_slots = no_of_slots;
2237
2238 /* this is tricky:
2239 one slot is at least big enough to hold one integer value.
2240 To optimize memory consumption, free list management is done
2241 in place: each empty slot stores the index (based on float *) to
2242 the next free slot.
2243 */
2244 for (i=0; i<no_of_slots-1; i++)
2245 {
2246 *((int *) ((float *) (page->data + i*size))) = (i+1)*size;
2247 }
2248 *((int *) ((float *) (page->data + (no_of_slots-1)*size))) = -1;
2249
2250 page->firstfree = 0;
2251 page->next = np_pages;
2252 np_pages = page;
2253 }
2254
2255 /* here we have a page with at least one empty slot of right size: */
2256 page->no_of_free_slots--;
2257 retval = page->data + page->firstfree;
2258 page->firstfree = *((int *) retval);
2259
2260 #ifdef DEBUG_PATTERN
2261 print_page_info(page);
2262 #endif
2263
2264 return retval;
2265 }
2266
2267 /*****************************************************************************
2268 FUNCTION : kr_np_floatfree
2269
2270 PURPOSE : free the pattern memory within a private memory page
2271 RETURNS : nothing
2272 NOTES : internal use only
2273
2274 UPDATE :
2275 ******************************************************************************/
kr_np_floatfree(float * ptr)2276 static void kr_np_floatfree(float *ptr)
2277 {
2278 struct patternpage *page;
2279 struct patternpage *prev;
2280
2281 /* look for the page which includes the given address */
2282 prev = NULL;
2283 page = np_pages;
2284 while (page != NULL &&
2285 (ptr < page->data ||
2286 ptr >= (page->data + page->no_of_slots*page->slotsize)))
2287 {
2288 prev = page;
2289 page = page->next;
2290 }
2291
2292 if (!page)
2293 /* we have not allocated this memory slot !
2294 gracefull return but print out error */
2295 {
2296 fprintf(stderr,
2297 "kr_np_floatfree: function called with illegal argument\n");
2298 return;
2299 }
2300
2301 *((int *) ptr) = page->firstfree;
2302 page->firstfree = (ptr - page->data);
2303 page->no_of_free_slots++;
2304
2305 if (page->no_of_free_slots == page->no_of_slots)
2306 {
2307 /* page is no longer used, give it back to the OS */
2308 free(page->data);
2309 if (prev != NULL)
2310 prev->next = page->next;
2311 else
2312 np_pages = page->next;
2313 free(page);
2314 page = NULL;
2315 }
2316
2317 #ifdef DEBUG_PATTERN
2318 print_page_info(page);
2319 #endif
2320 }
2321
2322 /*****************************************************************************
2323 FUNCTION : kr_np_InitPattern
2324
2325 PURPOSE : initialization of pattern descriptor array
2326 RETURNS : kernel error code
2327 NOTES : internal use only
2328
2329 UPDATE :
2330 ******************************************************************************/
kr_np_InitPattern(void)2331 static krui_err kr_np_InitPattern(void)
2332 {
2333 int i;
2334
2335 TRACE_IN();
2336
2337 np_pat_sets = (np_pattern_descriptor **)
2338 malloc(NO_OF_PAT_SETS * sizeof(np_pattern_descriptor *));
2339
2340 np_pat_set_used = (bool *)
2341 malloc(NO_OF_PAT_SETS * sizeof(bool));
2342
2343 np_info = (np_pattern_set_info *)
2344 malloc(NO_OF_PAT_SETS * sizeof(np_pattern_set_info));
2345
2346 np_info_valid = (bool *)
2347 malloc(NO_OF_PAT_SETS * sizeof(bool));
2348
2349 np_st = (struct np_symtab **)
2350 malloc(NO_OF_PAT_SETS * sizeof(struct np_symtab *));
2351
2352 if (np_pat_sets == (np_pattern_descriptor **) NULL ||
2353 np_info == (np_pattern_set_info *) NULL ||
2354 np_info_valid == (bool *) NULL ||
2355 np_st == (struct np_symtab **) NULL)
2356 {
2357 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
2358 }
2359 else
2360 {
2361 np_used_pat_set_entries = NO_OF_PAT_SETS;
2362 for (i=0; i<NO_OF_PAT_SETS; i++)
2363 {
2364 np_pat_sets[i] = (np_pattern_descriptor *) NULL;
2365 np_pat_set_used[i] = FALSE;
2366 np_info_valid[i] = FALSE;
2367 np_st[i] = NULL;
2368 }
2369
2370 { TRACE_RETURN(KRERR_NO_ERROR); }
2371 }
2372 }
2373
2374
2375 /*****************************************************************************
2376 FUNCTION : kr_np_ReallocatePatternSet
2377
2378 PURPOSE : reallocates the pattern set <pat_set> to contain <new_number>
2379 of pattern entries.
2380
2381 RETURNS : kernel error code
2382 NOTES : internal use only
2383
2384 UPDATE :
2385 ******************************************************************************/
kr_np_ReallocatePatternSet(int pat_set,int new_number)2386 static krui_err kr_np_ReallocatePatternSet(int pat_set, int new_number)
2387 {
2388 np_pattern_descriptor *new_mem;
2389
2390 TRACE_IN();
2391
2392 /* check whether patterns are allocated */
2393 if (np_used_pat_set_entries == 0)
2394 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2395
2396 /* check whether the pattern set is present */
2397 if (!np_pat_set_used[pat_set])
2398 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2399
2400 /* reallocate array of pattern descriptors */
2401 if (np_pat_sets[pat_set] != (np_pattern_descriptor *) NULL)
2402 {
2403 new_mem = (np_pattern_descriptor *)
2404 realloc(np_pat_sets[pat_set],
2405 new_number * sizeof(np_pattern_descriptor));
2406 }
2407 else
2408 {
2409 new_mem = (np_pattern_descriptor *)
2410 malloc(new_number * sizeof(np_pattern_descriptor));
2411 }
2412
2413 if (new_mem == (np_pattern_descriptor *) NULL && new_number != 0)
2414 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
2415
2416 np_pat_sets[pat_set] = new_mem;
2417
2418 /* store number of allocated descriptors */
2419 np_info[pat_set].pub.number_of_pattern = new_number;
2420 np_info[pat_set].pub.virtual_no_of_pattern = new_number;
2421 np_info_valid[pat_set] = FALSE; /* only number_of_pattern is valid */
2422 /* do not revalidate here, since this done by the calling function! */
2423
2424 /* sucessfull return */
2425 { TRACE_RETURN(KRERR_NO_ERROR); }
2426 }
2427
2428 /*****************************************************************************
2429 FUNCTION : kr_np_DeletePatternSet
2430
2431 PURPOSE : delete a pattern set and free all memory
2432 RETURNS : kernel error code
2433 NOTES : internal use only
2434
2435 UPDATE :
2436 ******************************************************************************/
kr_np_DeletePatternSet(int pat_set)2437 static krui_err kr_np_DeletePatternSet(int pat_set)
2438 {
2439 int i;
2440 np_pattern_descriptor *p;
2441
2442 TRACE_IN();
2443
2444 /* check for valid number of pattern set */
2445 if (np_used_pat_set_entries == 0)
2446 { TRACE_RETURN(KRERR_NO_PATTERNS); }
2447
2448 if (pat_set<0 || pat_set>=np_used_pat_set_entries)
2449 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2450
2451 p = np_pat_sets[pat_set];
2452 if (!np_pat_set_used[pat_set])
2453 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2454
2455 /* free all pattern */
2456 for (i=0; i<np_info[pat_set].pub.number_of_pattern; i++)
2457 {
2458 kr_np_FreePattern(p);
2459 p++;
2460 }
2461
2462 /* free the pattern descriptors */
2463 if (np_pat_sets[pat_set] != (np_pattern_descriptor *) NULL)
2464 free(np_pat_sets[pat_set]);
2465 np_pat_sets[pat_set] = (np_pattern_descriptor *) NULL;
2466 np_pat_set_used[pat_set] = FALSE;
2467
2468 np_info[pat_set].pub.number_of_pattern = 0;
2469 np_info[pat_set].pub.virtual_no_of_pattern = 0;
2470 np_info_valid[pat_set] = FALSE;
2471 np_current_pattern = (np_pattern_descriptor *) NULL;
2472
2473 /* free the symbol table */
2474 while (np_st[pat_set])
2475 {
2476 struct np_symtab *help;
2477
2478 free(np_st[pat_set]->symname);
2479 help = np_st[pat_set]->next;
2480 free(np_st[pat_set]);
2481 np_st[pat_set] = help;
2482 }
2483
2484 { TRACE_RETURN(KRERR_NO_ERROR); }
2485 }
2486
2487 /*****************************************************************************
2488 FUNCTION : kr_np_DeletePattern
2489
2490 PURPOSE : delete a specific pattern form a pattern set
2491 RETURNS : kernel error code
2492 NOTES : internal use only
2493
2494 <pattern> is a physical pattern number
2495
2496 UPDATE :
2497 ******************************************************************************/
kr_np_DeletePattern(int pat_set,int pattern)2498 static krui_err kr_np_DeletePattern(int pat_set, int pattern)
2499 {
2500 np_pattern_descriptor *p;
2501 int i;
2502
2503 TRACE_IN();
2504
2505 /* check for valid number of pattern set */
2506 if (np_used_pat_set_entries == 0)
2507 { TRACE_RETURN(KRERR_NO_PATTERNS); }
2508
2509 if (pat_set<0 || pat_set>=np_used_pat_set_entries)
2510 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2511
2512 p = np_pat_sets[pat_set];
2513 if (!np_pat_set_used[pat_set])
2514 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2515
2516 if (pattern < 0 || pattern >= np_info[pat_set].pub.number_of_pattern)
2517 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN); }
2518
2519 /* free memory for the specified pattern */
2520 p += pattern;
2521 kr_np_FreePattern(p);
2522
2523 /* if classes available fix class information */
2524 if (p->mysym != NULL)
2525 {
2526 p->mysym->set_amount--;
2527 if (p->mysym->set_amount < p->mysym->chunk_amount)
2528 p->mysym->chunk_amount = p->mysym->set_amount;
2529 if (p->mysym->set_amount <= 0)
2530 {
2531 p->mysym->chunk_amount = 0;
2532 np_info[pat_set].pub.classes--;
2533 kr_np_delSym(pat_set, p->mysym);
2534 }
2535 }
2536
2537 /* move tail of array one position to fill up the empty entry */
2538 for (i=pattern+1; i<np_info[pat_set].pub.number_of_pattern; i++)
2539 {
2540 (void) memcpy((char *) p, (char *) (p+1), sizeof(np_pattern_descriptor));
2541 p++;
2542 }
2543
2544 np_info_valid[pat_set] = FALSE;
2545 /* do not revalidate here, since this done by the calling function */
2546
2547 /* last entry of the array is no longer active */
2548 TRACE_RETURN(kr_np_ReallocatePatternSet(pat_set,
2549 np_info[pat_set].pub.number_of_pattern-1));
2550 }
2551
2552 /*****************************************************************************
2553 FUNCTION : kr_np_delSym
2554
2555 PURPOSE : Delete the symbol table entry from the given pattern set.
2556
2557 RETURNS :
2558 NOTES : don't call this function. This function is only to be
2559 called by the parser or by functions inside this module
2560
2561 UPDATE :
2562 ******************************************************************************/
kr_np_delSym(int pat_set,struct np_symtab * entry)2563 static void kr_np_delSym(int pat_set, struct np_symtab *entry)
2564 {
2565 struct np_symtab *list;
2566 struct np_symtab *last = NULL;
2567 int i;
2568
2569 TRACE_IN();
2570
2571 list = np_st[pat_set];
2572 while (list != NULL && list != entry)
2573 {
2574 last = list;
2575 list = list->next;
2576 }
2577
2578 if (list != NULL && list == entry)
2579 {
2580 if (last != NULL)
2581 last -> next = list->next;
2582 else
2583 np_st[pat_set] = list->next;
2584
2585 if (list->symname != NULL)
2586 free(list->symname);
2587 if (list->pat_nums != NULL)
2588 free(list->pat_nums);
2589 free(list);
2590 }
2591 else
2592 {
2593 /* symbol must be in the list of the given pattern
2594 set. Otherwise an error inside the pattern handling occured
2595 at some other place.... */
2596
2597 fprintf(stderr, "internal error, file %s, line %d", __FILE__, __LINE__);
2598 }
2599
2600 list = np_st[pat_set];
2601 i = 0;
2602 while (list)
2603 {
2604 list->symnum = i++;
2605 list = list->next;
2606 }
2607
2608 { TRACE_RETURN_VOID(); }
2609 }
2610
2611 /*****************************************************************************
2612 FUNCTION : kr_np_AddPattern
2613
2614 PURPOSE : Add an empty pattern descriptor to the specified pattern set.
2615 The position of the pattern inside the set is returned
2616 in <pattern>.
2617 RETURNS : kernel error code
2618 NOTES : internal use only
2619
2620 UPDATE :
2621 ******************************************************************************/
kr_np_AddPattern(int pat_set,int * pattern)2622 static krui_err kr_np_AddPattern(int pat_set, int *pattern)
2623 {
2624 krui_err err;
2625 np_pattern_descriptor *p;
2626 int number;
2627
2628 TRACE_IN();
2629
2630 /* check for valid number of pattern set */
2631 if (np_used_pat_set_entries == 0)
2632 { TRACE_RETURN(KRERR_NO_PATTERNS); }
2633
2634 if (pat_set<0 || pat_set>=np_used_pat_set_entries)
2635 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2636
2637 p = np_pat_sets[pat_set];
2638 if (!np_pat_set_used[pat_set])
2639 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2640
2641 number = np_info[pat_set].pub.number_of_pattern + 1;
2642 err = kr_np_ReallocatePatternSet(pat_set, number);
2643
2644 if (err != KRERR_NO_ERROR)
2645 { TRACE_RETURN(err); }
2646
2647 p = np_pat_sets[pat_set];
2648 p += (number-1);
2649
2650 /* initialize part of the new pattern descriptors */
2651 {
2652 p -> pub.input_fixsize = 0;
2653 p -> pub.output_fixsize = 0;
2654 p -> pub.input_dim = 0;
2655 p -> pub.output_dim = 0;
2656 p -> pub.my_class = -1;
2657 p -> input_pattern = (float *) NULL;
2658 p -> output_pattern = (float *) NULL;
2659 p -> mysym = (struct np_symtab *) NULL;
2660 }
2661
2662 *pattern = (number-1);
2663 { TRACE_RETURN(KRERR_NO_ERROR); }
2664 }
2665
2666 /*****************************************************************************
2667 FUNCTION : kr_np_LoadPatternFile
2668
2669 PURPOSE : loads new or old pattern file from pat_file. The number of the
2670 associated pattern set is returned in pat_set.
2671 RETURNS : kernel error code
2672 NOTES : internal use only
2673
2674 UPDATE :
2675 ******************************************************************************/
kr_np_LoadPatternFile(FILE * pat_file,int * pat_set)2676 static krui_err kr_np_LoadPatternFile(FILE *pat_file, int *pat_set)
2677 {
2678 int i;
2679 bool free;
2680 krui_err err_code = KRERR_NO_ERROR;
2681 int pattern_set;
2682 np_pattern_set_info set_info;
2683
2684 TRACE_IN();
2685
2686 /* be sure to have a place where to put the patterns */
2687 if (np_used_pat_set_entries == 0)
2688 {
2689 /* never patterns allocated */
2690 err_code = kr_np_InitPattern();
2691 if (err_code != KRERR_NO_ERROR)
2692 { TRACE_RETURN(err_code); }
2693 }
2694 else
2695 {
2696 free = FALSE;
2697
2698 /* check for free entry before starting parser */
2699 for (i=0; i<np_used_pat_set_entries; i++)
2700 {
2701 if (!np_pat_set_used[i])
2702 {
2703 free = TRUE;
2704 break;
2705 }
2706 }
2707
2708 if (!free)
2709 { TRACE_RETURN(KRERR_NP_NO_MORE_ENTRIES); }
2710 }
2711
2712 /* reset the scanner and the parser */
2713 scanner_init_scanner(pat_file);
2714
2715 /* parse pattern file and check for errors */
2716 if (parse_pattern_file(&pattern_set, &set_info) != 0)
2717 {
2718 (void) kr_np_DeletePatternSet(pattern_set);
2719 { TRACE_RETURN(KRERR_FILE_FORMAT); }
2720 }
2721 else
2722 {
2723 int i;
2724 struct np_symtab *list;
2725
2726 *pat_set = pattern_set;
2727 np_info[pattern_set].pub.classes = set_info.pub.classes;
2728 np_info[pattern_set].pub.class_names = set_info.pub.class_names;
2729 np_info[pattern_set].pub.class_distrib_active = set_info.pub.class_distrib_active;
2730 np_info[pattern_set].pub.class_redistribution = set_info.pub.class_redistribution;
2731
2732 list = np_st[pattern_set];
2733 i = 0;
2734 while (list)
2735 {
2736 if (np_info[pattern_set].pub.class_distrib_active)
2737 list->chunk_amount =
2738 np_info[pattern_set].pub.class_redistribution[i];
2739 else
2740 list->chunk_amount = list->set_amount;
2741 i++;
2742 list = list -> next;
2743 }
2744
2745 np_info[pattern_set].pub.remap_function = set_info.pub.remap_function;
2746 np_info[pattern_set].pub.no_of_remap_params = set_info.pub.no_of_remap_params;
2747 for (i=0; i<NO_OF_REMAP_PARAMS; i++)
2748 np_info[pattern_set].pub.remap_params[i] = set_info.pub.remap_params[i];
2749
2750 if (np_info[pattern_set].pub.remap_function != NULL)
2751 {
2752 struct FuncInfoDescriptor func_descr;
2753
2754 func_descr.func_type = REMAP_FUNC;
2755 strcpy(func_descr.func_name, np_info[pattern_set].pub.remap_function);
2756 err_code = krf_getFuncInfo(SEARCH_FUNC, &func_descr);
2757
2758 if (err_code == KRERR_NO_ERROR)
2759 {
2760 np_info[pattern_set].rmf_ptr = (RemapFuncPtr) func_descr.function;
2761 if (np_info[pattern_set].pub.no_of_remap_params
2762 != func_descr.no_of_input_parameters)
2763 {
2764 np_info[pattern_set].rmf_ptr = NULL;
2765 np_info[pattern_set].pub.remap_function = NULL;
2766 np_info[pattern_set].pub.no_of_remap_params = 0;
2767 err_code = KRERR_PARAMETERS;
2768 }
2769 }
2770 else
2771 {
2772 np_info[pattern_set].rmf_ptr = NULL;
2773 np_info[pattern_set].pub.remap_function = NULL;
2774 np_info[pattern_set].pub.no_of_remap_params = 0;
2775 }
2776 }
2777 { TRACE_RETURN(err_code); }
2778 }
2779 }
2780
2781 /*****************************************************************************
2782 FUNCTION : kr_np_SavePatternFile
2783
2784 PURPOSE : save the pattern set pat_set to out_file
2785 RETURNS : kernel error code
2786 NOTES : internal use only
2787
2788 UPDATE :
2789 ******************************************************************************/
kr_np_SavePatternFile(FILE * out_file,int pat_set)2790 static krui_err kr_np_SavePatternFile(FILE *out_file, int pat_set)
2791 {
2792 np_pattern_set_info info;
2793 krui_err err_code;
2794 int i, j, n;
2795 int with_classes = 0;
2796 float *in_pat, *out_pat;
2797 time_t clock;
2798
2799 TRACE_IN();
2800
2801 if (np_used_pat_set_entries == 0)
2802 { TRACE_RETURN(KRERR_NO_PATTERNS); }
2803
2804 if (pat_set<0 || pat_set>=np_used_pat_set_entries)
2805 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2806
2807 if (!np_pat_set_used[pat_set])
2808 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2809
2810 err_code = kr_np_GetInfo(pat_set, &info);
2811 if (err_code != KRERR_NO_ERROR)
2812 { TRACE_RETURN(err_code); }
2813
2814 if (info.pub.number_of_pattern == 0)
2815 { TRACE_RETURN(KRERR_NO_PATTERNS); }
2816
2817 fprintf(out_file, "SNNS pattern definition file V%d.%d\n",
2818 CURRENT_VERSION_V, CURRENT_VERSION_R);
2819 clock = time((time_t *) NULL);
2820 fprintf(out_file, "generated at %s\n\n", (char *) ctime(&clock));
2821 fprintf(out_file, "No. of patterns : %d\n", info.pub.number_of_pattern);
2822 fprintf(out_file, "No. of input units : %d\n", info.pub.in_fixsize);
2823 if (info.pub.out_fixsize != 0)
2824 fprintf(out_file, "No. of output units : %d\n", info.pub.out_fixsize);
2825 if (info.pub.in_number_of_dims != 0)
2826 {
2827 fprintf(out_file, "No. of variable input dimensions : %d\n",
2828 info.pub.in_number_of_dims);
2829 fprintf(out_file, "Maximum input dimensions : [ ");
2830 for (i=0; i<info.pub.in_number_of_dims; i++)
2831 {
2832 fprintf(out_file, "%d ", info.pub.in_max_dim_sizes[i]);
2833 }
2834 fprintf(out_file, "]\n");
2835 }
2836 if (info.pub.out_fixsize != 0 && info.pub.out_number_of_dims != 0)
2837 {
2838 fprintf(out_file, "No. of variable output dimensions : %d\n",
2839 info.pub.out_number_of_dims);
2840 fprintf(out_file, "Maximum output dimensions : [ ");
2841 for (i=0; i<info.pub.out_number_of_dims; i++)
2842 {
2843 fprintf(out_file, "%d ", info.pub.out_max_dim_sizes[i]);
2844 }
2845 fprintf(out_file, "]\n");
2846 }
2847 if (info.pub.classes > 0)
2848 {
2849 with_classes = 1;
2850 fprintf(out_file, "No. of classes : %d\n", info.pub.classes);
2851 if (info.pub.class_distrib_active)
2852 {
2853 fprintf(out_file, "Class redistribution : [ ");
2854 for (i=0; i<info.pub.classes; i++)
2855 fprintf(out_file, "%d ", info.pub.class_redistribution[i]);
2856 fprintf(out_file, "]\n");
2857 }
2858 }
2859 if (info.pub.remap_function)
2860 {
2861 fprintf(out_file, "Remap function : %s\n",
2862 info.pub.remap_function);
2863 if (info.pub.no_of_remap_params > 0)
2864 {
2865 fprintf(out_file, "Remap parameters : [ ");
2866 for (i=0; i<info.pub.no_of_remap_params; i++)
2867 fprintf(out_file, "%g ", info.pub.remap_params[i]);
2868 fprintf(out_file, "]\n");
2869 }
2870 }
2871 fprintf(out_file, "\n");
2872
2873 for (j=0; j<info.pub.number_of_pattern; j++)
2874 {
2875 if (np_pat_sets[pat_set][j].pub.input_fixsize > 0)
2876 {
2877 fprintf(out_file, "# Input pattern %d:\n", j+1);
2878 n = info.pub.in_fixsize;
2879 if (info.pub.in_number_of_dims != 0)
2880 {
2881 fprintf(out_file, "[ ");
2882 for (i=0; i<np_pat_sets[pat_set][j].pub.input_dim; i++)
2883 {
2884 fprintf(out_file, "%d ",
2885 np_pat_sets[pat_set][j].pub.input_dim_sizes[i]);
2886 n *= np_pat_sets[pat_set][j].pub.input_dim_sizes[i];
2887 }
2888 fprintf(out_file, "]\n");
2889 }
2890 in_pat = np_pat_sets[pat_set][j].input_pattern;
2891 for (i=0; i<n; i++)
2892 {
2893 fprintf(out_file, "%g ", *in_pat++);
2894 if (i == n - 1 || i%10 == 9)
2895 fprintf(out_file, "\n");
2896 }
2897 }
2898
2899 if (np_pat_sets[pat_set][j].pub.output_fixsize > 0)
2900 {
2901 fprintf(out_file, "# Output pattern %d:\n", j+1);
2902 n = info.pub.out_fixsize;
2903 if (info.pub.out_number_of_dims != 0)
2904 {
2905 fprintf(out_file, "[ ");
2906 for (i=0; i<np_pat_sets[pat_set][j].pub.output_dim; i++)
2907 {
2908 fprintf(out_file, "%d ",
2909 np_pat_sets[pat_set][j].pub.output_dim_sizes[i]);
2910 n *= np_pat_sets[pat_set][j].pub.output_dim_sizes[i];
2911 }
2912 fprintf(out_file, "]\n");
2913 }
2914 out_pat = np_pat_sets[pat_set][j].output_pattern;
2915 for (i=0; i<n; i++)
2916 {
2917 fprintf(out_file, "%g ", *out_pat++);
2918 if (i == n - 1 || i%10 == 9)
2919 fprintf(out_file, "\n");
2920 }
2921 }
2922
2923 if (with_classes)
2924 {
2925 fprintf(out_file, "# Class:\n");
2926 fprintf(out_file, "%s\n", np_pat_sets[pat_set][j].mysym->symname);
2927 }
2928 }
2929
2930 { TRACE_RETURN(KRERR_NO_ERROR); }
2931 }
2932
2933 /*****************************************************************************
2934 FUNCTION : kr_np_GetInfo
2935
2936 PURPOSE : get some information about the specified pattern set
2937 RETURNS : kernel error code
2938 NOTES : internal use only
2939
2940 UPDATE :
2941 ******************************************************************************/
kr_np_GetInfo(int pat_set,np_pattern_set_info * info)2942 static krui_err kr_np_GetInfo(int pat_set, np_pattern_set_info *info)
2943 {
2944 krui_err err_code;
2945
2946 TRACE_IN();
2947
2948 err_code = kr_np_ValidateInfo(pat_set);
2949 if (err_code == KRERR_NO_ERROR)
2950 *info = np_info[pat_set];;
2951
2952 { TRACE_RETURN(err_code); }
2953 }
2954
2955 /*****************************************************************************
2956 FUNCTION : kr_np_ValidateInfo
2957
2958 PURPOSE : update pattern set information if necessary
2959 RETURNS : kernel error code
2960 NOTES : internal use only
2961
2962 UPDATE :
2963 ******************************************************************************/
kr_np_ValidateInfo(int pat_set)2964 static krui_err kr_np_ValidateInfo(int pat_set)
2965 {
2966 int i, j;
2967 np_pattern_descriptor *p;
2968
2969 TRACE_IN();
2970
2971 if (np_used_pat_set_entries == 0)
2972 { TRACE_RETURN(KRERR_NO_PATTERNS); }
2973
2974 if (pat_set < 0 || pat_set >= np_used_pat_set_entries ||
2975 !np_pat_set_used[pat_set])
2976 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
2977
2978 if (np_info_valid[pat_set] && np_abs_count_valid && np_pat_mapping_valid)
2979 {
2980 { TRACE_RETURN(KRERR_NO_ERROR); }
2981 }
2982
2983 /* controlled by np_info_valid flag: */
2984 if (!np_info_valid[pat_set])
2985 {
2986 p = np_pat_sets[pat_set];
2987 np_info[pat_set].pub.fixed_fixsizes = TRUE;
2988 if (np_info[pat_set].pub.number_of_pattern > 0 && p != (np_pattern_descriptor *) NULL)
2989 {
2990 np_info[pat_set].pub.output_present = p-> pub.output_fixsize != 0;
2991 np_info[pat_set].pub.in_fixsize = p -> pub.input_fixsize;
2992 np_info[pat_set].pub.out_fixsize = p-> pub.output_fixsize;
2993 np_info[pat_set].pub.in_number_of_dims = p->pub.input_dim;
2994 np_info[pat_set].pub.out_number_of_dims = p->pub.output_dim;
2995
2996 for (j=0; j < p->pub.input_dim; j++)
2997 {
2998 (np_info[pat_set].pub.in_max_dim_sizes)[j] = (np_info[pat_set].pub.in_min_dim_sizes)[j] =
2999 (p -> pub.input_dim_sizes)[j];
3000 }
3001 for (j=0; j < p->pub.output_dim; j++)
3002 {
3003 (np_info[pat_set].pub.out_max_dim_sizes)[j] = (np_info[pat_set].pub.out_min_dim_sizes)[j] =
3004 (p -> pub.output_dim_sizes)[j];
3005 }
3006 }
3007
3008 p = np_pat_sets[pat_set];
3009 for (i=0; i<np_info[pat_set].pub.number_of_pattern; i++)
3010 {
3011 if (p -> pub.input_fixsize != np_info[pat_set].pub.in_fixsize)
3012 {
3013 np_info[pat_set].pub.fixed_fixsizes = FALSE;
3014 np_info[pat_set].pub.in_fixsize = -1;
3015 }
3016 if (p -> pub.output_fixsize != np_info[pat_set].pub.out_fixsize)
3017 {
3018 np_info[pat_set].pub.fixed_fixsizes = FALSE;
3019 np_info[pat_set].pub.out_fixsize = -1;
3020 }
3021
3022 for (j=0; j < p->pub.input_dim; j++)
3023 {
3024 if ((p -> pub.input_dim_sizes)[j] > (np_info[pat_set].pub.in_max_dim_sizes)[j])
3025 (np_info[pat_set].pub.in_max_dim_sizes)[j] = p -> pub.input_dim_sizes[j];
3026 if ((p -> pub.input_dim_sizes)[j] < (np_info[pat_set].pub.in_min_dim_sizes)[j])
3027 (np_info[pat_set].pub.in_min_dim_sizes)[j] = p -> pub.input_dim_sizes[j];
3028 }
3029 for (j=0; j < p->pub.output_dim; j++)
3030 {
3031 if ((p -> pub.output_dim_sizes)[j] > (np_info[pat_set].pub.out_max_dim_sizes)[j])
3032 (np_info[pat_set].pub.out_max_dim_sizes)[j] = p -> pub.output_dim_sizes[j];
3033 if ((p -> pub.output_dim_sizes)[j] < (np_info[pat_set].pub.out_min_dim_sizes)[j])
3034 (np_info[pat_set].pub.out_min_dim_sizes)[j] = p -> pub.output_dim_sizes[j];
3035 }
3036 p++;
3037 }
3038 np_info[pat_set].pub.virtual_no_of_pattern = np_info[pat_set].pub.number_of_pattern;
3039 np_info_valid[pat_set] = TRUE;
3040 }
3041
3042 if (!np_pat_mapping_valid)
3043 {
3044 /* reallocate and refill class information */
3045 if (np_info[pat_set].pub.classes > 0)
3046 {
3047 struct np_symtab *list;
3048 int count=0;
3049 int global_chunks = 0;
3050 int total_virtual = 0;
3051
3052 p = np_pat_sets[pat_set];
3053 for (i=0; i<np_info[pat_set].pub.number_of_pattern; i++)
3054 {
3055 p->pub.my_class = p->mysym ? p->mysym->symnum : -1;
3056 p++;
3057 }
3058
3059 #ifdef DEBUG_CLASSES
3060 TRACE_INDENT();
3061 printf("%s: there are now %d classes:\n", __FUNCTION__, np_info[pat_set].pub.classes);
3062 #endif
3063
3064 np_info[pat_set].chunk_order_valid = FALSE;
3065
3066 if (np_info[pat_set].pub.class_names)
3067 np_info[pat_set].pub.class_names =
3068 (char **) realloc(np_info[pat_set].pub.class_names,
3069 np_info[pat_set].pub.classes * sizeof(char *));
3070 else
3071 np_info[pat_set].pub.class_names =
3072 (char **) malloc(np_info[pat_set].pub.classes * sizeof(char *));
3073
3074 if (np_info[pat_set].pub.class_redistribution)
3075 np_info[pat_set].pub.class_redistribution =
3076 (int *) realloc(np_info[pat_set].pub.class_redistribution,
3077 np_info[pat_set].pub.classes * sizeof(int));
3078 else
3079 np_info[pat_set].pub.class_redistribution =
3080 (int *) malloc(np_info[pat_set].pub.classes * sizeof(int));
3081
3082 if (!(np_info[pat_set].pub.class_names) || !(np_info[pat_set].pub.class_redistribution))
3083 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
3084
3085 list = np_st[pat_set];
3086 while (count < np_info[pat_set].pub.classes && list != NULL)
3087 {
3088 np_info[pat_set].pub.class_names[count] = list->symname;
3089 np_info[pat_set].pub.class_redistribution[count] = list->chunk_amount;
3090
3091 list->my_chunks_per_set = (list->chunk_amount > 0) ?
3092 (list->set_amount-1)/list->chunk_amount + 1 : 0;
3093
3094 if (list->my_chunks_per_set > global_chunks)
3095 global_chunks = list->my_chunks_per_set;
3096
3097 count++;
3098 list = list->next;
3099 }
3100 if (count != np_info[pat_set].pub.classes || list != NULL)
3101 {
3102 fprintf(stderr, "internal error, file %s, line %d\n",
3103 __FILE__, __LINE__);
3104 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
3105 }
3106 list = np_st[pat_set];
3107 count = 0;
3108 while (list != NULL)
3109 {
3110 int n;
3111
3112 list->global_chunks = global_chunks;
3113
3114 #ifdef DEBUG_CLASSES
3115 TRACE_INDENT();
3116 printf("%s: index %d, name %s, set amount %d, chunk amount %d\n",
3117 __FUNCTION__, count, list->symname,
3118 list->set_amount, list->chunk_amount);
3119 #endif
3120
3121 n = list->global_chunks * list->chunk_amount;
3122 if (n < list->set_amount)
3123 n = list->set_amount;
3124 if (n > list->pat_nums_size)
3125 {
3126 if (list->pat_nums != NULL)
3127 free(list->pat_nums);
3128 list->pat_nums_size = 0;
3129 list->pat_nums = (int *) malloc(n * sizeof(int));
3130 if (list->pat_nums == NULL && n != 0)
3131 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
3132 list->pat_nums_size = n;
3133 }
3134
3135 #ifdef DEBUG_CLASSES
3136 TRACE_INDENT();
3137 printf("%s: epoch chunks %d, pat nums table %d\n",
3138 __FUNCTION__, list->global_chunks, list->pat_nums_size);
3139 #endif
3140
3141 total_virtual += list->global_chunks * list->chunk_amount;
3142 count++;
3143 list = list->next;
3144 }
3145 if (np_info[pat_set].pub.class_distrib_active)
3146 {
3147 np_info[pat_set].pub.virtual_no_of_pattern = total_virtual;
3148 kr_np_order_chunk_arrays(FALSE, pat_set);
3149 }
3150 else
3151 np_info[pat_set].pub.virtual_no_of_pattern =
3152 np_info[pat_set].pub.number_of_pattern;
3153 }
3154
3155 #ifdef DEBUG_CLASSES
3156 TRACE_INDENT();
3157 printf("%s: physical %d, virtual %d, chunk active %s\n",
3158 __FUNCTION__,
3159 np_info[pat_set].pub.number_of_pattern,
3160 np_info[pat_set].pub.virtual_no_of_pattern,
3161 np_info[pat_set].pub.class_distrib_active ? "TRUE" : "FALSE");
3162 #endif
3163
3164 if (!kr_np_allocate_pat_mapping_entries(np_info[pat_set].pub.virtual_no_of_pattern))
3165 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
3166 kr_np_fill_virtual_to_void_mapping(pat_set);
3167 }
3168
3169 { TRACE_RETURN(KRERR_NO_ERROR); }
3170 }
3171
3172 /*****************************************************************************
3173 FUNCTION : kr_np_GetSubPatSizes
3174
3175 PURPOSE : Depending on the current pattern set and the sub pattern
3176 training scheme, which must be defined, the size of the first input sub
3177 pattern and the size of the first output sub pattern is computed.
3178 RETURNS : kernel error code
3179 NOTES : internal use only
3180
3181 UPDATE :
3182 ******************************************************************************/
kr_np_GetSubPatSizes(int * input_size,int * output_size)3183 static krui_err kr_np_GetSubPatSizes(int *input_size, int *output_size)
3184 {
3185 int pat_set;
3186 np_pattern_descriptor *pattern;
3187 int i;
3188
3189 TRACE_IN();
3190
3191 if (!npui_train_defined)
3192 { TRACE_RETURN(KRERR_NP_NO_TRAIN_SCHEME); }
3193
3194 pat_set = npui_pat_sets[npui_curr_pat_set];
3195 pattern = &(np_pat_sets[pat_set][0]);
3196
3197 *input_size = pattern -> pub.input_fixsize;
3198 for (i=0; i<pattern -> pub.input_dim; i++)
3199 {
3200 *input_size *= np_t_insize[i];
3201 }
3202
3203 *output_size = pattern -> pub.output_fixsize;
3204 for (i=0; i<pattern -> pub.output_dim; i++)
3205 {
3206 *output_size *= np_t_outsize[i];
3207 }
3208
3209 { TRACE_RETURN(KRERR_NO_ERROR); }
3210 }
3211
3212 /*****************************************************************************
3213 FUNCTION : kr_np_GetSubPat
3214
3215 PURPOSE : copy a sub pattern into another area
3216
3217 A sub pattern is cut out of the current pattern at position
3218 <pos_coord> with size <size_coord>. According to <input> the input
3219 part or the output part of the current pattern is used. A pointer to
3220 an array of float which contains the cut part is returned in <data>.
3221 <pos_coord> is an array of int which defines the position of the sub
3222 pattern inside the variable sized dimensions of the pattern.
3223 <size_coord> is an array of int which defines the size of the sub
3224 pattern in each dimensional direction. Both arrays must contain
3225 <input_dim> (or <output_dim>) entries (see pattern descriptor).
3226
3227 Example: pattern with input_fixsize 2, input_dim 2, input_dim_sizes [4 5]
3228 (hint: the values of the pattern represent the position)
3229
3230 {
3231 0.00, 0.01, 0.10, 0.11, 0.20, 0.21, 0.30, 0.31, 0.40, 0.41,
3232 1.00, 1.01, 1.10, 1.11, 1.20, 1.21, 1.30, 1.31, 1.40, 1.41,
3233 2.00, 2.01, 2.10, 2.11, 2.20, 2.21, 2.30, 2.31, 2.40, 2.41,
3234 3.00, 3.01, 3.10, 3.11, 3.20, 3.21, 3.30, 3.31, 3.40, 3.41,
3235 }
3236
3237 the sub pattern with <pos_coord> [1 2], <size_coord> [3 2] looks like
3238 this:
3239
3240 {
3241 1.20, 1.21, 1.30, 1.31,
3242 2.20, 2.21, 2.30, 2.31,
3243 3.20, 3.21, 3.30, 3.31,
3244 }
3245
3246 The parameter entries returns the number of entries in the data field.
3247
3248 RETURNS : kernel error code
3249 NOTES : internal use only
3250
3251 UPDATE :
3252 ******************************************************************************/
kr_np_GetSubPat(bool input,int * pos_coord,int * size_coord,float ** data,int * entries)3253 static krui_err kr_np_GetSubPat(bool input, int *pos_coord, int *size_coord,
3254 float **data, int *entries)
3255 {
3256 int u_dim; /* copy of all necessary variables from */
3257 int u_size; /* pattern descriptor, depending on */
3258 int *u_dim_sizes; /* <input> */
3259 float *u_pattern;
3260 int npu_subpatsize;
3261 float *npu_subpat;
3262
3263 int f_size; /* size of copy area */
3264 int i;
3265 int c[MAX_NO_OF_VAR_DIM]; /* counter for the dimensions */
3266 int copy_size; /* size of copy block for each memcpy */
3267 float *cf; /* pointer into pattern (copy source) */
3268 float *cdest; /* copy destination */
3269 bool stop; /* TRUE if all done */
3270 int offset; /* offset in multidimensional array */
3271
3272 krui_err err;
3273
3274 int set = npui_pat_sets[npui_curr_pat_set];
3275
3276 TRACE_IN();
3277
3278 /* check for valid pattern */
3279 if (np_used_pat_set_entries == 0)
3280 { TRACE_RETURN(KRERR_NO_PATTERNS); }
3281
3282 if (np_current_pattern == (np_pattern_descriptor *) NULL)
3283 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN); }
3284
3285 /* make a copy of all pattern info to work with */
3286 if (input)
3287 {
3288 u_dim = np_current_pattern -> pub.input_dim;
3289 u_size = np_current_pattern -> pub.input_fixsize;
3290 u_dim_sizes = np_current_pattern -> pub.input_dim_sizes;
3291 u_pattern = np_current_pattern -> input_pattern;
3292 npu_subpatsize = np_i_subpatsize;
3293 npu_subpat = np_i_subpat;
3294 }
3295 else
3296 {
3297 u_dim = np_current_pattern -> pub.output_dim;
3298 u_size = np_current_pattern -> pub.output_fixsize;
3299 u_dim_sizes = np_current_pattern -> pub.output_dim_sizes;
3300 u_pattern = np_current_pattern -> output_pattern;
3301 npu_subpatsize = np_o_subpatsize;
3302 npu_subpat = np_o_subpat;
3303 }
3304
3305 /* check whether this pattern exists */
3306 if (u_size == 0)
3307 {
3308 if (input)
3309 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN); }
3310 else
3311 {
3312 /* this may be a network without output neurons, so don't */
3313 /* produce an error but set the data pointer to NULL */
3314
3315 *data = (float *) NULL;
3316 if (entries != (int *) NULL)
3317 *entries = 0;
3318 { TRACE_RETURN(KRERR_NO_ERROR); }
3319 }
3320 }
3321
3322 /* calculate size of the sub pattern and check dimensions */
3323 f_size = u_size;
3324 for (i=0; i<u_dim; i++)
3325 {
3326 f_size *= size_coord[i];
3327 if (pos_coord[i] + size_coord[i] > u_dim_sizes[i])
3328 { TRACE_RETURN(KRERR_NP_DIMENSION); }
3329 c[i] = 0;
3330 }
3331
3332 /* allocate space for sub pattern if necessary */
3333 if (f_size > npu_subpatsize)
3334 {
3335 if (npu_subpat != (float *) NULL)
3336 free(npu_subpat);
3337 npu_subpat = (float *) malloc(f_size * sizeof(float));
3338 if (npu_subpat == (float *) NULL && f_size != 0)
3339 {
3340 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
3341 }
3342 npu_subpatsize = f_size;
3343
3344 /* copy back new address and size */
3345 if (input)
3346 {
3347 np_i_subpatsize = npu_subpatsize;
3348 np_i_subpat = npu_subpat;
3349 }
3350 else
3351 {
3352 np_o_subpatsize = npu_subpatsize;
3353 np_o_subpat = npu_subpat;
3354 }
3355 }
3356
3357
3358 /* calculate size of one copy block. this includes the size of the */
3359 /* dimension with highest index (least significant dimension) */
3360 copy_size = u_size;
3361 if (u_dim>0)
3362 copy_size *= size_coord[u_dim-1];
3363
3364 /* copy the sub pattern */
3365 cdest = npu_subpat;
3366 do
3367 {
3368 /* calculate offset in source pattern */
3369 offset = 0;
3370 for (i=0; i<u_dim; i++)
3371 {
3372 offset *= u_dim_sizes[i];
3373 offset += pos_coord[i] + c[i];
3374 }
3375 offset *= u_size;
3376 cf = u_pattern + offset;
3377
3378 /* copy part of the pattern. this inlcudes the least significant */
3379 /* dimension */
3380 (void) memcpy((char *) cdest, (char *) cf, copy_size * sizeof(float));
3381 cdest += copy_size;
3382
3383 /* count the dimensions and check whether we have to go on. */
3384 /* the least significant dimension is omitted, because it is already */
3385 /* copied */
3386 stop = TRUE;
3387 for (i=u_dim-2; i>=0; i--)
3388 {
3389 c[i]++;
3390 if (c[i] == size_coord[i])
3391 c[i] = 0;
3392 else
3393 {
3394 stop = FALSE;
3395 break;
3396 }
3397 }
3398 } while (!stop);
3399
3400 /* remaping if necessary */
3401 if (!input && np_info[set].rmf_ptr != NULL)
3402 {
3403 err = np_info[set].rmf_ptr(npu_subpat, f_size,
3404 np_info[set].pub.remap_params,
3405 np_info[set].pub.no_of_remap_params);
3406 if (err != KRERR_NO_ERROR)
3407 { TRACE_RETURN(err); }
3408 }
3409
3410 /* all done, return results */
3411 *data = npu_subpat;
3412 if (entries != (int *) NULL)
3413 *entries = f_size;
3414 { TRACE_RETURN(KRERR_NO_ERROR); }
3415 }
3416
3417 /*****************************************************************************
3418 FUNCTION : kr_np_SetSubPat
3419
3420 PURPOSE : copy another area into a sub pattern
3421
3422 A sub pattern is cut out of the current pattern at position
3423 <pos_coord> with size <size_coord>. According to <input> the input
3424 part or the output part of the current pattern is used.
3425 <pos_coord> is an array of int which defines the position of the sub
3426 pattern inside the variable sized dimensions of the pattern.
3427 <size_coord> is an array of int which defines the size of the sub
3428 pattern in each dimensional direction. Both arrays must contain
3429 <input_dim> (or <output_dim>) entries (see pattern descriptor).
3430
3431 Example: pattern with input_fixsize 2, input_dim 2, input_dim_sizes [4 5]
3432 (hint: the values of the pattern represent the position)
3433
3434 {
3435 0.00, 0.01, 0.10, 0.11, 0.20, 0.21, 0.30, 0.31, 0.40, 0.41,
3436 1.00, 1.01, 1.10, 1.11, 1.20, 1.21, 1.30, 1.31, 1.40, 1.41,
3437 2.00, 2.01, 2.10, 2.11, 2.20, 2.21, 2.30, 2.31, 2.40, 2.41,
3438 3.00, 3.01, 3.10, 3.11, 3.20, 3.21, 3.30, 3.31, 3.40, 3.41,
3439 }
3440
3441 the sub pattern with <pos_coord> [1 2], <size_coord> [3 2] looks like
3442 this:
3443
3444 {
3445 1.20, 1.21, 1.30, 1.31,
3446 2.20, 2.21, 2.30, 2.31,
3447 3.20, 3.21, 3.30, 3.31,
3448 }
3449
3450 The parameter entries returns the number of entries in the data field.
3451
3452 RETURNS : kernel error code
3453 NOTES : internal use only
3454
3455 UPDATE :
3456 ******************************************************************************/
kr_np_SetSubPat(bool input,int * pos_coord,int * size_coord,float * data,int entries)3457 static krui_err kr_np_SetSubPat(bool input, int *pos_coord, int *size_coord,
3458 float *data, int entries)
3459 {
3460 int u_dim; /* copy of all necessary variables from */
3461 int u_size; /* pattern descriptor, depending on */
3462 int *u_dim_sizes; /* <input> */
3463 float *u_pattern;
3464
3465 int f_size; /* size of copy area */
3466 int i;
3467 int c[MAX_NO_OF_VAR_DIM]; /* counter for the dimensions */
3468 int copy_size; /* size of copy block for each memcpy */
3469 float *cf; /* pointer into pattern (copy destination) */
3470 float *csource; /* copy source */
3471 bool stop; /* TRUE if all done */
3472 int offset; /* offset in multidimensional array */
3473
3474 TRACE_IN();
3475
3476 /* check for valid pattern */
3477 if (np_used_pat_set_entries == 0)
3478 { TRACE_RETURN(KRERR_NO_PATTERNS); }
3479
3480 if (np_current_pattern == (np_pattern_descriptor *) NULL)
3481 { TRACE_RETURN(KRERR_NP_NO_CURRENT_PATTERN); }
3482
3483 /* make a copy of all pattern info to work with */
3484 if (input)
3485 {
3486 u_dim = np_current_pattern -> pub.input_dim;
3487 u_size = np_current_pattern -> pub.input_fixsize;
3488 u_dim_sizes = np_current_pattern -> pub.input_dim_sizes;
3489 u_pattern = np_current_pattern -> input_pattern;
3490 }
3491 else
3492 {
3493 u_dim = np_current_pattern -> pub.output_dim;
3494 u_size = np_current_pattern -> pub.output_fixsize;
3495 u_dim_sizes = np_current_pattern -> pub.output_dim_sizes;
3496 u_pattern = np_current_pattern -> output_pattern;
3497 }
3498
3499 /* check whether this pattern exists or whether all is done */
3500 if (u_size == 0)
3501 {
3502 if (entries == 0)
3503 { TRACE_RETURN(KRERR_NO_ERROR); }
3504 else
3505 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN); }
3506 }
3507
3508 /* calculate size of the sub pattern and check dimensions */
3509 f_size = u_size;
3510 for (i=0; i<u_dim; i++)
3511 {
3512 f_size *= size_coord[i];
3513 if (pos_coord[i] + size_coord[i] > u_dim_sizes[i])
3514 { TRACE_RETURN(KRERR_NP_DIMENSION); }
3515 c[i] = 0;
3516 }
3517
3518 /* check whether calculated space fits the delievered data block */
3519 if (f_size != entries)
3520 { TRACE_RETURN(KRERR_NP_DOES_NOT_FIT); }
3521
3522 /* calculate size of one copy block. this includes the size of the */
3523 /* dimension with highest index (least significant dimension) */
3524 copy_size = u_size;
3525 if (u_dim>0)
3526 copy_size *= size_coord[u_dim-1];
3527
3528 /* copy the sub pattern */
3529 csource = data;
3530 do
3531 {
3532 /* calculate offset in destination pattern */
3533 offset = 0;
3534 for (i=0; i<u_dim; i++)
3535 {
3536 offset *= u_dim_sizes[i];
3537 offset += pos_coord[i] + c[i];
3538 }
3539 offset *= u_size;
3540 cf = u_pattern + offset;
3541
3542 /* copy part of the pattern. this inlcudes the least significant */
3543 /* dimension */
3544 (void) memcpy((char *) cf, (char *)csource, copy_size * sizeof(float));
3545 csource += copy_size;
3546
3547 /* count the dimensions and check whether we have to go on. */
3548 /* the least significant dimension is omitted, because it is already */
3549 /* copied */
3550 stop = TRUE;
3551 for (i=u_dim-2; i>=0; i--)
3552 {
3553 c[i]++;
3554 if (c[i] == size_coord[i])
3555 c[i] = 0;
3556 else
3557 {
3558 stop = FALSE;
3559 break;
3560 }
3561 }
3562 } while (!stop);
3563
3564 /* all done, return results */
3565 { TRACE_RETURN(KRERR_NO_ERROR); }
3566 }
3567
3568 /*****************************************************************************
3569 FUNCTION : kr_np_align_sub_pos
3570
3571 PURPOSE : For a given pattern dimension size <psize> of <dim>
3572 dimensions and a given sub pattern size <ssize> the position
3573 <spos> of the sub pattern is alligned to a valid position
3574 and the ordering number of this sub pattern is returned
3575 in <n>. The shift pattern given in <sstep> is used to
3576 find valid allignment positions
3577
3578 RETURNS : TRUE if succesfull, FALSE if inconsistent parameters
3579
3580 <n> starts with 0 and ends with <number of possible
3581 positions> - 1
3582 <spos> gives the new aligned position
3583
3584 NOTES : internal function
3585
3586 UPDATE :
3587 ******************************************************************************/
kr_np_align_sub_pos(int dim,int * n,int * psize,int * ssize,int * sstep,int * spos)3588 static bool kr_np_align_sub_pos(int dim, int *n, int *psize, int *ssize,
3589 int *sstep, int *spos)
3590 {
3591 int ns[MAX_NO_OF_VAR_DIM];
3592 register int i;
3593 register int ts = 0;
3594
3595 TRACE_IN();
3596
3597 for (i=0; i<dim; i++)
3598 {
3599 /* calculate how much steps could be made in each dimension */
3600 ns[i] = (psize[i] - ssize[i] + sstep[i]) / sstep[i];
3601 if (ns[i] == 0)
3602 { TRACE_RETURN(FALSE); }
3603
3604 /* align the position of this dimension */
3605 spos[i] -= spos[i] % sstep[i];
3606 if (spos[i]+ssize[i] >= psize[i]+1)
3607 spos[i] = 0;
3608
3609 /* add the position of this dimension to the absolute position */
3610 ts *= ns[i];
3611 ts += spos[i]/sstep[i];
3612 }
3613
3614 *n = ts;
3615 { TRACE_RETURN(TRUE); }
3616 }
3617
3618 /*****************************************************************************
3619 FUNCTION : kr_np_gen_sub_pos
3620
3621 PURPOSE : For a given pattern dimension size <psize> of <dim>
3622 dimensions and a given sub pattern size <ssize> the position
3623 <spos> of the <n>th sub pattern is calculated. The shift
3624 pattern given in <sstep> is used to move sub pattern over
3625 the pattern.
3626
3627 If <count> is TRUE, only the number of possible positions
3628 is determined and returned in <n> if at least 1 valid
3629 position exists. <spos> is of no effect and may be NULL.
3630
3631 RETURNS : TRUE if the <n>th subpattern exists or if <count> is TRUE
3632 and at least 1 valid position exists, FALSE if <n> < 0.
3633 If <n> is higher than the available number of subpattern, a
3634 wraparound occurs.
3635
3636 <n> starts with 0 and ends with <number of possible
3637 positions> - 1 or returns number of possible positions.
3638
3639 NOTES : internal function
3640
3641 UPDATE :
3642 ******************************************************************************/
kr_np_gen_sub_pos(int dim,int * n,int * psize,int * ssize,int * sstep,int * spos,bool count)3643 static bool kr_np_gen_sub_pos(int dim, int *n, int *psize, int *ssize,
3644 int *sstep, int *spos, bool count)
3645 {
3646 int ns[MAX_NO_OF_VAR_DIM];
3647 int i;
3648 int ts;
3649 int nn;
3650
3651 TRACE_IN();
3652
3653 nn = *n;
3654
3655 /* calculate how much steps could be made in each dimension */
3656 /* and the total number of positions ts (define the bases of a */
3657 /* multi base numerative system and determine the highest */
3658 /* representable number) */
3659 ts = 1;
3660 for (i=dim-1; i>=0; i--)
3661 {
3662 ns[i] = (psize[i] - ssize[i] + sstep[i]) / sstep[i];
3663 if (ns[i] == 0)
3664 { TRACE_RETURN(FALSE); }
3665 ts *= ns[i];
3666 }
3667
3668 /* check whether this is all what we want to do now */
3669 if (count)
3670 {
3671 *n = ts;
3672 { TRACE_RETURN(TRUE); }
3673 }
3674
3675 /* check range of requested step position */
3676 if (nn<0)
3677 { TRACE_RETURN(FALSE); }
3678
3679 /* if requested position is higher than available positions, perform */
3680 /* wraparaound (this is usefull/necessary for pattern without subpattern */
3681 nn = nn%ts;
3682
3683 /* calculate step position of the <n>th sub pattern (like counting */
3684 /* in a multi base numerative system) */
3685 for (i=dim-1; i>=0; i--)
3686 {
3687 spos[i] = (nn % ns[i]) * sstep[i];
3688 nn /= ns[i];
3689 }
3690
3691 { TRACE_RETURN(TRUE); }
3692 }
3693
3694 /*****************************************************************************
3695 FUNCTION : kr_np_allocate_pat_train_entries
3696
3697 PURPOSE : allocate or reallocate an array which will later include
3698 the sorted or shuffled pattern order (during training)
3699 RETURNS : FALSE if malloc fails
3700 NOTES : internal use only
3701
3702 UPDATE :
3703 ******************************************************************************/
kr_np_allocate_pat_train_entries(int n)3704 static bool kr_np_allocate_pat_train_entries(int n)
3705 {
3706 TRACE_IN();
3707
3708 if (n > np_pat_train_size)
3709 {
3710 if (np_pat_train_order != (int *) NULL)
3711 free(np_pat_train_order);
3712 np_pat_train_size = 0;
3713 np_pat_train_order = (int *) malloc(n * sizeof(int));
3714 if (np_pat_train_order == (int *) NULL && n != 0)
3715 { TRACE_RETURN(FALSE); }
3716 np_pat_train_size = n;
3717 np_pat_train_valid = FALSE;
3718 }
3719 { TRACE_RETURN(TRUE); }
3720 }
3721
3722 /*****************************************************************************
3723 FUNCTION : kr_np_allocate_sub_pat_train_entries
3724
3725 PURPOSE : allocate or reallocate an array which will later include
3726 the sorted or shuffled order of the sub pattern of the
3727 current pattern
3728 RETURNS : FALSE if malloc fails
3729 NOTES : internal use only
3730
3731 UPDATE :
3732 ******************************************************************************/
kr_np_allocate_sub_pat_train_entries(int n)3733 static bool kr_np_allocate_sub_pat_train_entries(int n)
3734 {
3735 TRACE_IN();
3736
3737 if (n > np_sub_pat_train_size)
3738 {
3739 if (np_sub_pat_train_order != (int *) NULL)
3740 free(np_sub_pat_train_order);
3741 np_sub_pat_train_size = 0;
3742 np_sub_pat_train_order = (int *) malloc(n * sizeof(int));
3743 if (np_sub_pat_train_order == (int *) NULL && n != 0)
3744 { TRACE_RETURN(FALSE); }
3745 np_sub_pat_train_size = n;
3746 np_sub_pat_train_valid = FALSE;
3747 }
3748 { TRACE_RETURN(TRUE); }
3749 }
3750
3751 /*****************************************************************************
3752 FUNCTION : kr_np_allocate_pat_mapping_entries
3753
3754 PURPOSE : allocate or reallocate an array which will later include
3755 the virtual to physical pattern number mapping
3756 RETURNS : FALSE if malloc fails
3757 NOTES : internal use only
3758
3759 UPDATE :
3760 ******************************************************************************/
kr_np_allocate_pat_mapping_entries(int n)3761 static bool kr_np_allocate_pat_mapping_entries(int n)
3762 {
3763 TRACE_IN();
3764
3765 if (n > np_pat_mapping_size)
3766 {
3767 if (np_pat_mapping_order != (int *) NULL)
3768 free(np_pat_mapping_order);
3769 np_pat_mapping_size = 0;
3770 np_pat_mapping_order = (int *) malloc(n * sizeof(int));
3771 if (np_pat_mapping_order == (int *) NULL && n != 0)
3772 { TRACE_RETURN(FALSE); }
3773 np_pat_mapping_size = n;
3774 np_pat_mapping_valid = FALSE;
3775 }
3776 { TRACE_RETURN(TRUE); }
3777 }
3778
3779 /*****************************************************************************
3780 FUNCTION : kr_np_order_pat_entries
3781
3782 PURPOSE : Fills the allocated array for the pattern ordering with
3783 increasing numbers if patterns are sorted or with a
3784 random permutation if patterns are shuffled.
3785 <start> and <end> define the first and last pattern
3786 number to be used
3787 RETURNS : nothing
3788 NOTES : internal use only
3789
3790 UPDATE :
3791 ******************************************************************************/
kr_np_order_pat_entries(int start,int end)3792 static void kr_np_order_pat_entries(int start, int end)
3793 {
3794 static bool shuffle;
3795 static int c_start;
3796 static int c_end;
3797
3798 register int i;
3799 register int *fp;
3800 register int h;
3801 register int s;
3802 register int n;
3803
3804 TRACE_IN();
3805
3806 if (!np_pat_train_valid || c_start != start || c_end != end
3807 || shuffle != npui_shuffle_pattern)
3808 {
3809 fp = np_pat_train_order;
3810 for (i=start; i<=end; i++)
3811 *fp++ = i;
3812 np_pat_train_valid = TRUE;
3813 np_pat_train_number = end - start + 1;
3814 c_start = start;
3815 c_end = end;
3816 shuffle = npui_shuffle_pattern;
3817 }
3818
3819 if (shuffle)
3820 {
3821 n = np_pat_train_number;
3822 fp = np_pat_train_order;
3823 for (i=0; i<n; i++)
3824 {
3825 s = lrand48() % (n-i);
3826 h = *fp;
3827 *fp++ = np_pat_train_order[s+i];
3828 np_pat_train_order[s+i] = h;
3829 }
3830 }
3831
3832 { TRACE_RETURN_VOID(); }
3833 }
3834
3835 /*****************************************************************************
3836 FUNCTION : kr_np_order_sub_pat_entries
3837
3838 PURPOSE : Fills the allocated array for the sub pattern ordering with
3839 increasing numbers if sub patterns are sorted or with a
3840 random permutation if sub patterns are shuffled.
3841 <start> and <end> define the first and last sub pattern
3842 number to be used
3843 RETURNS : nothing
3844 NOTES : internal use only
3845
3846 UPDATE :
3847 ******************************************************************************/
kr_np_order_sub_pat_entries(int start,int end)3848 static void kr_np_order_sub_pat_entries(int start, int end)
3849 {
3850 static bool shuffle;
3851 static int c_start;
3852 static int c_end;
3853
3854 register int i;
3855 register int *fp;
3856 register int h;
3857 register int s;
3858 register int n;
3859
3860 TRACE_IN();
3861
3862 if (!np_sub_pat_train_valid || c_start != start || c_end != end
3863 || shuffle != npui_shuffle_sub_pattern)
3864 {
3865 fp = np_sub_pat_train_order;
3866 for (i=start; i<=end; i++)
3867 *fp++ = i;
3868 np_sub_pat_train_valid = TRUE;
3869 np_sub_pat_train_number = end - start + 1;
3870 c_start = start;
3871 c_end = end;
3872 shuffle = npui_shuffle_sub_pattern;
3873 }
3874
3875 if (shuffle)
3876 {
3877 n = np_sub_pat_train_number;
3878 fp = np_sub_pat_train_order;
3879 for (i=0; i<n; i++)
3880 {
3881 s = lrand48() % (n-i);
3882 h = *fp;
3883 *fp++ = np_sub_pat_train_order[s+i];
3884 np_sub_pat_train_order[s+i] = h;
3885 }
3886 }
3887
3888 { TRACE_RETURN_VOID(); }
3889 }
3890
3891 /*****************************************************************************
3892 FUNCTION : kr_np_order_chunk_arrays
3893
3894 PURPOSE : Fills the allocated array for the pattern ordering with
3895 increasing numbers if patterns are sorted or with a
3896 random permutation if patterns are shuffled.
3897 RETURNS : nothing
3898 NOTES : internal use only
3899
3900 ordering within pat_nums list after finishing this function:
3901
3902 s_a s_a s_a p s_a
3903 | | | | |
3904 -------------------------------------------------------------
3905 | | | | | | | | | | |
3906 c_a c_a c_a c_a c_a c_a c_a c_a c_a c_a
3907
3908
3909 c_a: chunk_amount
3910 s_a: set_amount
3911 p s_a: partial set_amount
3912
3913 global_chunks = number of c_a repetitions
3914 pat_nums_valid = global_chunks * chunk_amount
3915 pat_num_pos = 0
3916
3917 algorithm:
3918 1: fill in first s_a section
3919 2: (partially) copy this section to further positions while
3920 shuffling if necessary
3921
3922 UPDATE :
3923 ******************************************************************************/
kr_np_order_chunk_arrays(bool shuffle,int pattern_set)3924 static void kr_np_order_chunk_arrays(bool shuffle, int pattern_set)
3925 {
3926 struct np_symtab *list;
3927 np_pattern_descriptor *pattern;
3928 int no_of_pattern;
3929 int i;
3930 int sc, ps;
3931 int total = 0;
3932
3933 TRACE_IN();
3934
3935 list = np_st[pattern_set];
3936 while (list != NULL)
3937 {
3938 list->pat_num_pos = 0;
3939 list = list->next;
3940 }
3941
3942 if (np_info[pattern_set].chunk_order_valid &&
3943 !np_info[pattern_set].chunk_shuffle &&
3944 !shuffle)
3945 { TRACE_RETURN_VOID(); }
3946
3947 /* fill first set amount */
3948 if (!np_info[pattern_set].chunk_order_valid)
3949 {
3950 no_of_pattern = np_info[pattern_set].pub.number_of_pattern;
3951
3952 list = np_st[pattern_set];
3953 while (list != NULL)
3954 {
3955 list->pat_nums_valid = 0;
3956 list = list->next;
3957 }
3958
3959 pattern = np_pat_sets[pattern_set];
3960 for (i=0; i<no_of_pattern; i++, pattern++)
3961 pattern->mysym->pat_nums[pattern->mysym->pat_nums_valid++] = i;
3962 }
3963
3964 /* copy set amounts without shuffling */
3965 if (!np_info[pattern_set].chunk_order_valid && !shuffle)
3966 {
3967 list = np_st[pattern_set];
3968 while (list != NULL)
3969 {
3970 if (list->chunk_amount > 0)
3971 {
3972 sc = 1 + (list->global_chunks * list->chunk_amount - 1) /
3973 list->set_amount;
3974 ps = list->global_chunks * list->chunk_amount -
3975 (sc-1) * list->set_amount;
3976 for (i=1; i<sc; i++)
3977 {
3978 if (i!=(sc-1))
3979 memcpy(list->pat_nums + i*list->set_amount,
3980 list->pat_nums, list->set_amount * sizeof(int));
3981 else
3982 memcpy(list->pat_nums + i*list->set_amount,
3983 list->pat_nums, ps * sizeof(int));
3984 }
3985
3986 total += list->global_chunks * list->chunk_amount;
3987 }
3988 list = list->next;
3989 }
3990
3991 if (total != np_info[pattern_set].pub.virtual_no_of_pattern)
3992 fprintf(stderr, "internal error, file %s, line %d", __FILE__, __LINE__);
3993 }
3994
3995 /* copy set amounts with shuffling */
3996 np_info[pattern_set].chunk_shuffle = shuffle;
3997 if (shuffle)
3998 {
3999 int n,j,s,h;
4000 int *fp;
4001
4002 list = np_st[pattern_set];
4003 while (list != NULL)
4004 {
4005 if (list->chunk_amount > 0)
4006 {
4007 sc = 1 + (list->global_chunks * list->chunk_amount - 1) /
4008 list->set_amount;
4009 ps = list->global_chunks * list->chunk_amount -
4010 (sc-1) * list->set_amount;
4011 for (i=1; i<sc; i++)
4012 {
4013 /* shuffle first copy of set */
4014 n = list->set_amount;
4015 fp = list->pat_nums;
4016 for (j=0; j<n; j++)
4017 {
4018 s = lrand48() % (n-j);
4019 h = *fp;
4020 *fp++ = list->pat_nums[s+j];
4021 list->pat_nums[s+j] = h;
4022 }
4023
4024 /* copy shuffled set */
4025 if (i!=(sc-1))
4026 memcpy(list->pat_nums + i*list->set_amount,
4027 list->pat_nums, list->set_amount * sizeof(int));
4028 else
4029 memcpy(list->pat_nums + i*list->set_amount,
4030 list->pat_nums, ps * sizeof(int));
4031 }
4032
4033 /* reshuffle first copy of set, because part of it has been copied */
4034 n = list->set_amount;
4035 fp = list->pat_nums;
4036 for (j=0; j<n; j++)
4037 {
4038 s = lrand48() % (n-j);
4039 h = *fp;
4040 *fp++ = list->pat_nums[s+j];
4041 list->pat_nums[s+j] = h;
4042 }
4043 }
4044 list = list->next;
4045 }
4046 }
4047
4048 np_info[pattern_set].chunk_order_valid = TRUE;
4049
4050 { TRACE_RETURN_VOID(); }
4051 }
4052
4053 /*****************************************************************************
4054 FUNCTION : kr_np_order_chunked_pat_entries
4055
4056 PURPOSE : Fills the allocated array for the pattern ordering with
4057 the contents of all chunk arrays.
4058 <start> and <end> define the first and last pattern
4059 number to be used
4060 RETURNS : nothing
4061 NOTES : internal use only
4062
4063 UPDATE :
4064 ******************************************************************************/
kr_np_order_chunked_pat_entries(int pat_set,int start,int end)4065 static void kr_np_order_chunked_pat_entries(int pat_set, int start, int end)
4066 {
4067 static int c_start;
4068 static int c_end;
4069
4070 struct np_symtab *list;
4071 int insert_pos;
4072 int total_pos;
4073 int within_chunk_count;
4074 int chunk_size;
4075
4076 TRACE_IN();
4077
4078 if (np_pat_train_valid && c_start == start && c_end == end
4079 && !npui_shuffle_pattern)
4080 { TRACE_RETURN_VOID(); }
4081
4082 /* chunk lists are already prepared and shuffled if necessary */
4083
4084 list = np_st[pat_set];
4085 chunk_size = 0;
4086 while (list != NULL)
4087 {
4088 chunk_size += list->chunk_amount;
4089 list = list->next;
4090 }
4091 if (chunk_size == 0)
4092 fprintf(stderr, "internal error, file %s, line %d", __FILE__, __LINE__);
4093
4094 list = np_st[pat_set];
4095 while (list != NULL)
4096 {
4097 list->chunk_comp_base = (list->chunk_amount > 0) ?
4098 chunk_size / list->chunk_amount : 0;
4099 list = list->next;
4100 }
4101
4102 insert_pos = 0;
4103 total_pos = 0;
4104 list = NULL;
4105 within_chunk_count = 0;
4106 while (total_pos <= end)
4107 {
4108 if (within_chunk_count == 0)
4109 {
4110 list = np_st[pat_set];
4111 while (list != NULL)
4112 {
4113 list->chunk_comp_count = list->chunk_comp_base;
4114 list->within_chunk_pos = 0;
4115 list = list->next;
4116 }
4117 within_chunk_count = chunk_size;
4118 }
4119 if (list == NULL)
4120 list = np_st[pat_set];
4121 if (list->within_chunk_pos < list->chunk_amount &&
4122 --(list->chunk_comp_count) == 0)
4123 {
4124 if (total_pos >= start)
4125 {
4126 np_pat_train_order[insert_pos++] =
4127 list->pat_nums[list->pat_num_pos];
4128 }
4129 list->chunk_comp_count = list->chunk_comp_base;
4130 list->within_chunk_pos++;
4131 list->pat_num_pos++;
4132 total_pos++;
4133 within_chunk_count--;
4134 }
4135 list = list->next;
4136 }
4137
4138 /*
4139 while (total_pos <= end)
4140 {
4141 list = np_st[pat_set];
4142 while (list != NULL && total_pos <= end)
4143 {
4144 list->within_chunk_pos = 0;
4145 while (list->within_chunk_pos < list->chunk_amount && total_pos <= end)
4146 {
4147 if (total_pos >= start)
4148 {
4149 np_pat_train_order[insert_pos++] =
4150 list->pat_nums[list->pat_num_pos];
4151 }
4152 list->within_chunk_pos++;
4153 list->pat_num_pos++;
4154 total_pos++;
4155 }
4156 list = list->next;
4157 }
4158 }
4159 */
4160
4161 c_start = start;
4162 c_end = end;
4163 np_pat_train_valid = TRUE;
4164 np_pat_train_number = end - start + 1;
4165
4166 { TRACE_RETURN_VOID(); }
4167 }
4168
4169 /*****************************************************************************
4170 FUNCTION : kr_np_fill_virtual_to_void_mapping
4171
4172 PURPOSE : Fills the allocated mapping array for the pattern ordering with
4173 the contents of all chunk arrays.
4174 RETURNS : nothing
4175 NOTES : internal use only
4176
4177 UPDATE :
4178 ******************************************************************************/
kr_np_fill_virtual_to_void_mapping(int pat_set)4179 static void kr_np_fill_virtual_to_void_mapping(int pat_set)
4180 {
4181 struct np_symtab *list;
4182 int insert_pos;
4183 int chunk_size;
4184 int within_chunk_count;
4185
4186 TRACE_IN();
4187
4188 if (np_pat_mapping_valid)
4189 { TRACE_RETURN_VOID(); }
4190
4191 if (np_info[pat_set].pub.class_distrib_active)
4192 {
4193 /* chunk lists are already prepared (not shuffled!) */
4194 list = np_st[pat_set];
4195 chunk_size = 0;
4196 while (list != NULL)
4197 {
4198 chunk_size += list->chunk_amount;
4199 list = list->next;
4200 }
4201 if (chunk_size == 0)
4202 fprintf(stderr, "internal error, file %s, line %d", __FILE__, __LINE__);
4203
4204 list = np_st[pat_set];
4205 while (list != NULL)
4206 {
4207 list->chunk_comp_base = (list->chunk_amount > 0) ?
4208 chunk_size / list->chunk_amount : 0;
4209 list = list->next;
4210 }
4211
4212 insert_pos = 0;
4213 list = NULL;
4214 within_chunk_count = 0;
4215 while (insert_pos < np_info[pat_set].pub.virtual_no_of_pattern)
4216 {
4217 if (within_chunk_count == 0)
4218 {
4219 list = np_st[pat_set];
4220 while (list != NULL)
4221 {
4222 list->chunk_comp_count = list->chunk_comp_base;
4223 list->within_chunk_pos = 0;
4224 list = list->next;
4225 }
4226 within_chunk_count = chunk_size;
4227 }
4228 if (list == NULL)
4229 list = np_st[pat_set];
4230 if (list->within_chunk_pos < list->chunk_amount &&
4231 --(list->chunk_comp_count) == 0)
4232 {
4233 np_pat_mapping_order[insert_pos++] =
4234 list->pat_nums[list->pat_num_pos++];
4235 list->chunk_comp_count = list->chunk_comp_base;
4236 list->within_chunk_pos++;
4237 within_chunk_count--;
4238 }
4239 list = list->next;
4240 }
4241
4242 /*
4243 insert_pos = 0;
4244 list = NULL;
4245
4246 while (insert_pos < np_info[pat_set].pub.virtual_no_of_pattern)
4247 {
4248 list = np_st[pat_set];
4249 while (list != NULL)
4250 {
4251 list->within_chunk_pos = 0;
4252 while (list->within_chunk_pos < list->chunk_amount)
4253 {
4254 np_pat_mapping_order[insert_pos++] =
4255 list->pat_nums[list->pat_num_pos++];
4256 list->within_chunk_pos++;
4257 }
4258 list = list->next;
4259 }
4260 }
4261 */
4262
4263 if (insert_pos != np_info[pat_set].pub.virtual_no_of_pattern)
4264 fprintf(stderr, "internal error, file %s, line %d\n", __FILE__, __LINE__);
4265 }
4266 else
4267 {
4268 /* no class distribution, virtual numbers = physical numbers */
4269 for (insert_pos=0; insert_pos < np_info[pat_set].pub.virtual_no_of_pattern;
4270 insert_pos++)
4271 np_pat_mapping_order[insert_pos] = insert_pos;
4272 }
4273
4274 np_pat_mapping_valid = TRUE;
4275
4276 { TRACE_RETURN_VOID(); }
4277 }
4278
4279
4280 /*****************************************************************************
4281 FUNCTION : kr_np_virtual_to_physical
4282
4283 PURPOSE : mapping of virtual pattern numbers to physically stored patterns
4284
4285 RETURNS : kernel error code
4286 NOTES : internal use only
4287
4288 UPDATE :
4289 ******************************************************************************/
kr_np_virtual_to_physical(int vnum)4290 static int kr_np_virtual_to_physical(int vnum)
4291 {
4292 TRACE_IN();
4293
4294 { TRACE_RETURN(np_pat_mapping_order[vnum]); }
4295 }
4296
4297 /*****************************************************************************
4298 FUNCTION : kr_np_physical_to_virtual
4299
4300 PURPOSE : mapping of physical pattern number to a virtual number
4301
4302 RETURNS : kernel error code
4303 NOTES : internal use only
4304
4305 UPDATE :
4306 ******************************************************************************/
kr_np_physical_to_virtual(int pnum)4307 static int kr_np_physical_to_virtual(int pnum)
4308 {
4309 int vnum;
4310 TRACE_IN();
4311
4312 if (np_pat_mapping_order[pnum] == pnum)
4313 /* first guess: if no chunks are defined, virtual numbers are
4314 equal to physical numbers */
4315 vnum = pnum;
4316 else
4317 {
4318 /* we need to search for a virtual number.
4319 The field is only partially sorted, so it is not possible
4320 to perform a binary search. There is no other way than to
4321 start at the beginning and find the first occurence of pnum
4322 */
4323 vnum = 0;
4324 while (np_pat_mapping_order[vnum] != pnum)
4325 vnum++;
4326 }
4327
4328 { TRACE_RETURN(vnum); }
4329 }
4330
4331 /*****************************************************************************
4332 FUNCTION : kr_np_DefineSubPatternOrdering
4333
4334 PURPOSE : definition of generation of sub pattern during training
4335
4336 The shape and ordering of sub patterns for training and display is
4337 defined. <pat_set> specifies the pattern set to use. The flag
4338 <input> determines whether input or output sub patterns are to be
4339 defined. The array size_coord spezifies the shape of the sub pattern
4340 like in kr_np_GetSubPat. The array incr_coord specifies how sub
4341 patterns are generated from the whole pattern by shifting the shape
4342 over this pattern. Each value in this array gives an incremental
4343 offset for one dimensional direction. The start position is at [0 0
4344 0 ...]. New positions are generated by adding the rightmost value of
4345 incr_coord to the old position. If an overflow in this dimension
4346 occurs, this coordinate is reset to 0 and the next position to the
4347 left is incremented (and so on ...). After all sub patterns of one
4348 pattern are generated the next pattern is used. Depending on
4349 npui_shuffle_pattern and npui_shuffle_sub_pattern shuffling is
4350 activated.
4351
4352 RETURNS : kernel error code
4353 NOTES : internal use only
4354
4355 UPDATE :
4356 ******************************************************************************/
kr_np_DefineSubPatternOrdering(int pat_set,bool input,int * size_coord,int * incr_coord)4357 static krui_err kr_np_DefineSubPatternOrdering(int pat_set, bool input,
4358 int *size_coord,
4359 int *incr_coord)
4360 {
4361 krui_err err_code;
4362 np_pattern_descriptor *p;
4363
4364 TRACE_IN();
4365
4366 if (np_used_pat_set_entries == 0)
4367 { TRACE_RETURN(KRERR_NO_PATTERNS); }
4368
4369 if (pat_set < 0 || pat_set >= np_used_pat_set_entries ||
4370 !np_pat_set_used[pat_set])
4371 { TRACE_RETURN(KRERR_NP_NO_SUCH_PATTERN_SET); }
4372
4373 err_code = kr_np_GetDescriptor(pat_set, 0, &p);
4374 if (err_code != KRERR_NO_ERROR)
4375 { TRACE_RETURN(err_code); }
4376
4377 if (input)
4378 {
4379 memcpy((char *) np_t_insize, (char *) size_coord,
4380 p->pub.input_dim * sizeof(int));
4381 memcpy((char *) np_t_instep, (char *) incr_coord,
4382 p->pub.input_dim * sizeof(int));
4383 }
4384 else
4385 {
4386 memcpy((char *) np_t_outsize, (char *) size_coord,
4387 p->pub.input_dim * sizeof(int));
4388 memcpy((char *) np_t_outstep, (char *) incr_coord,
4389 p->pub.input_dim * sizeof(int));
4390 }
4391
4392 np_pat_train_valid = FALSE;
4393 np_sub_pat_train_valid = FALSE;
4394 np_pat_mapping_valid = FALSE;
4395
4396 { TRACE_RETURN(KRERR_NO_ERROR); }
4397 }
4398
4399 /*****************************************************************************
4400 FUNCTION : kr_np_showPatternSTD
4401
4402 PURPOSE : According to the mode kr_np_showPatternSTD stores the current
4403 Pattern/sub Pattern into the units activation (and/or output)
4404 values.
4405 The modes are:
4406 - OUTPUT_NOTHING
4407 store input pattern into input units activations
4408 - OUTPUT_ACT
4409 store input pattern into input units activations and
4410 store output pattern into output units activations
4411 - OUTPUT_OUT
4412 store input pattern into input units activations,
4413 store output pattern into output units activations and
4414 update output units output
4415 RETURNS : kernel error code
4416 NOTES : See include file glob_typ.h for mode constants.
4417 internal use only
4418 UPDATE :
4419 ******************************************************************************/
kr_np_showPatternSTD(int mode)4420 static krui_err kr_np_showPatternSTD(int mode)
4421 {
4422 register struct Unit *unit_ptr;
4423 float *in_pat, *out_pat;
4424 np_pattern_descriptor *pattern;
4425 int in_pat_size, out_pat_size;
4426
4427 TRACE_IN();
4428
4429 /* make the pattern to become the current pattern */
4430 if ((KernelErrorCode =
4431 kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
4432 kr_np_virtual_to_physical(npui_curr_pattern-1), &pattern))
4433 != KRERR_NO_ERROR)
4434 { TRACE_RETURN(KernelErrorCode); }
4435
4436 /* calc. startaddress of patterns */
4437 if ((KernelErrorCode =
4438 kr_np_GetSubPat(TRUE, npui_inpos, npui_insize, &in_pat,
4439 &in_pat_size))
4440 != KRERR_NO_ERROR)
4441 { TRACE_RETURN(KernelErrorCode); }
4442
4443 if ((KernelErrorCode =
4444 kr_np_GetSubPat(FALSE, npui_outpos, npui_outsize, &out_pat,
4445 &out_pat_size))
4446 != KRERR_NO_ERROR)
4447 { TRACE_RETURN(KernelErrorCode); }
4448
4449 /* calculate the units, ignore error code concerning old pattern format */
4450 (void) kr_IOCheck();
4451 KernelErrorCode = KRERR_NO_ERROR;
4452
4453 /* check whether pattern fits the network, do not complain about */
4454 /* missing output pattern */
4455 if (NoOfInputUnits != in_pat_size ||
4456 (NoOfOutputUnits != out_pat_size && out_pat_size != 0))
4457 { TRACE_RETURN(KernelErrorCode = KRERR_NP_DOES_NOT_FIT); }
4458
4459 switch (mode)
4460 {
4461 case OUTPUT_NOTHING:
4462 FOR_ALL_UNITS( unit_ptr )
4463 if ( IS_INPUT_UNIT( unit_ptr ) && UNIT_IN_USE( unit_ptr ))
4464 if (in_pat_size--)
4465 unit_ptr->act = *in_pat++;
4466 break;
4467
4468 case OUTPUT_ACT:
4469 FOR_ALL_UNITS( unit_ptr )
4470 if UNIT_IN_USE( unit_ptr )
4471 {
4472 if IS_INPUT_UNIT( unit_ptr )
4473 unit_ptr->act = *in_pat++;
4474 if (IS_OUTPUT_UNIT( unit_ptr ) && out_pat_size != 0)
4475 unit_ptr->act = *out_pat++;
4476 }
4477 break;
4478
4479 case OUTPUT_OUT:
4480 FOR_ALL_UNITS( unit_ptr )
4481 if UNIT_IN_USE( unit_ptr )
4482 {
4483 if IS_INPUT_UNIT( unit_ptr )
4484 unit_ptr->act = *in_pat++;
4485 if (IS_OUTPUT_UNIT( unit_ptr ) && out_pat_size != 0)
4486 {
4487 unit_ptr->act = *out_pat++;
4488 if (unit_ptr->out_func == NULL)
4489 /* Identity Function */
4490 unit_ptr->Out.output = unit_ptr->act;
4491 else
4492 unit_ptr->Out.output =
4493 (*unit_ptr->out_func) (unit_ptr->act);
4494 }
4495 }
4496 break;
4497
4498 default:
4499 KernelErrorCode = KRERR_PARAMETERS;
4500 }
4501
4502 { TRACE_RETURN(KernelErrorCode); }
4503 }
4504
4505 /*****************************************************************************
4506 FUNCTION : kr_np_modifyPattern
4507
4508 PURPOSE : The current activation of the input and output units is used to
4509 modify the current sub pattern.
4510
4511 RETURNS : kernel error code
4512 NOTES : internal use only
4513 UPDATE :
4514 ******************************************************************************/
kr_np_modifyPattern(void)4515 static krui_err kr_np_modifyPattern(void)
4516 {
4517 register struct Unit *unit_ptr;
4518 float *in_pat, *out_pat;
4519 float *ip, *op;
4520 np_pattern_descriptor *pattern;
4521
4522 TRACE_IN();
4523
4524 /* make the pattern to become the current pattern */
4525 if ((KernelErrorCode =
4526 kr_np_GetDescriptor(npui_pat_sets[npui_curr_pat_set],
4527 kr_np_virtual_to_physical(npui_curr_pattern-1), &pattern))
4528 != KRERR_NO_ERROR)
4529 { TRACE_RETURN(KernelErrorCode); }
4530
4531 /* calculate the units, ignore error code concerning old pattern format */
4532 (void) kr_IOCheck();
4533 KernelErrorCode = KRERR_NO_ERROR;
4534
4535 /* allocate memory to hold the sub pattern */
4536 in_pat = (float *) malloc(NoOfInputUnits * sizeof(float));
4537 out_pat = (float *) malloc(NoOfOutputUnits * sizeof(float));
4538 if ((in_pat == (float *) NULL && NoOfInputUnits != 0)
4539 || (out_pat == (float *) NULL && NoOfOutputUnits != 0))
4540 { TRACE_RETURN(KRERR_INSUFFICIENT_MEM); }
4541
4542 /* copy unit activations into sub pattern area */
4543 ip = in_pat;
4544 op = out_pat;
4545
4546 FOR_ALL_UNITS(unit_ptr)
4547 if (UNIT_IN_USE(unit_ptr))
4548 {
4549 if (IS_INPUT_UNIT(unit_ptr))
4550 *ip++ = unit_ptr->act;
4551 if (IS_OUTPUT_UNIT(unit_ptr))
4552 *op++ = unit_ptr->act;
4553 }
4554
4555 KernelErrorCode = KRERR_NO_ERROR;
4556
4557 /* test whether pattern already contains data. */
4558 /* allocate space if necessary (for new allocated patterns) */
4559 if (pattern -> pub.input_fixsize == 0)
4560 {
4561 pattern -> pub.input_fixsize = NoOfInputUnits;
4562 pattern -> pub.output_fixsize = NoOfOutputUnits;
4563 pattern -> pub.input_dim = 0;
4564 pattern -> pub.output_dim = 0;
4565 KernelErrorCode = kr_np_AllocatePattern(pattern, TRUE);
4566 if (KernelErrorCode == KRERR_NO_ERROR)
4567 KernelErrorCode = kr_np_AllocatePattern(pattern, FALSE);
4568 }
4569
4570 /* modify the copied sub pattern */
4571 if (KernelErrorCode == KRERR_NO_ERROR)
4572 {
4573 KernelErrorCode = kr_np_SetSubPat(TRUE, npui_inpos, npui_insize,
4574 in_pat, NoOfInputUnits);
4575 }
4576
4577 if (KernelErrorCode == KRERR_NO_ERROR)
4578 {
4579 KernelErrorCode = kr_np_SetSubPat(FALSE, npui_outpos, npui_outsize,
4580 out_pat, NoOfOutputUnits);
4581 }
4582
4583 /* free the memory */
4584 if (in_pat != (float *) NULL)
4585 free(in_pat);
4586 if (out_pat != (float *) NULL)
4587 free(out_pat);
4588
4589 { TRACE_RETURN(KernelErrorCode); }
4590 }
4591
4592 /*****************************************************************************
4593 END OF FILE
4594 ******************************************************************************/
4595