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