132 int i, j,
new, index, persist = 0, initializer = 0;
138 size_t concatenated_argv_len;
139 char *concatenated_argv;
140 const char *const_concatenated_argv;
146 Tcl_AppendResult(
interp,
"wrong # args: should be \"",
argv[0],
147 " ?-persist? var type dim1 ?dim2? ?dim3? ...\"", (
char *) NULL );
156 Tcl_InitHashTable( &
matTable, TCL_STRING_KEYS );
161 for ( i = 1; i <
argc; i++ )
164 argv0_length = strlen(
argv[i] );
168 if ( ( c ==
'-' ) && ( strncmp(
argv[i],
"-persist", argv0_length ) == 0 ) )
172 for ( j = i; j <
argc; j++ )
181 matPtr->
fdata = NULL;
182 matPtr->
idata = NULL;
201 if ( Tcl_GetCommandInfo(
interp,
argv[0], &infoPtr ) )
203 Tcl_AppendResult(
interp,
"Matrix operator \"",
argv[0],
204 "\" already in use", (
char *) NULL );
205 free( (
void *) matPtr );
209 if ( Tcl_GetVar(
interp,
argv[0], 0 ) != NULL )
211 Tcl_AppendResult(
interp,
"Illegal name for Matrix operator \"",
212 argv[0],
"\": local variable of same name is active",
214 free( (
void *) matPtr );
218 matPtr->
name = (
char *) malloc( strlen(
argv[0] ) + 1 );
225 argv0_length = strlen(
argv[0] );
227 if ( ( c ==
'f' ) && ( strncmp(
argv[0],
"float", argv0_length ) == 0 ) )
233 else if ( ( c ==
'i' ) && ( strncmp(
argv[0],
"int", argv0_length ) == 0 ) )
241 Tcl_AppendResult(
interp,
"Matrix type \"",
argv[0],
242 "\" not supported, should be \"float\" or \"int\"",
256 if ( strcmp(
argv[0],
"=" ) == 0 )
269 "too many dimensions specified for Matrix operator \"",
270 matPtr->
name,
"\"", (
char *) NULL );
278 index = matPtr->
dim - 1;
279 matPtr->
n[index] =
MAX( 0, atoi(
argv[0] ) );
280 matPtr->
len *= matPtr->
n[index];
283 if ( matPtr->
dim < 1 )
286 "insufficient dimensions given for Matrix operator \"",
287 matPtr->
name,
"\"", (
char *) NULL );
294 switch ( matPtr->
type )
298 for ( i = 0; i < matPtr->
len; i++ )
299 matPtr->
fdata[i] = 0.0;
304 for ( i = 0; i < matPtr->
len; i++ )
305 matPtr->
idata[i] = 0;
316 "no initialization data given after \"=\" for Matrix operator \"",
317 matPtr->
name,
"\"", (
char *) NULL );
325 concatenated_argv_len = 3;
326 for ( i = 0; i <
argc; i++ )
328 concatenated_argv_len += strlen(
argv[i] ) + 1;
329 concatenated_argv = (
char *) malloc( concatenated_argv_len *
sizeof (
char ) );
332 concatenated_argv[0] =
'\0';
333 strcat( concatenated_argv,
"{" );
334 for ( i = 0; i <
argc; i++ )
336 strcat( concatenated_argv,
argv[i] );
337 strcat( concatenated_argv,
" " );
339 strcat( concatenated_argv,
"}" );
341 const_concatenated_argv = (
const char *) concatenated_argv;
347 if (
MatrixAssign(
interp, matPtr, 0, &offset, 1, &const_concatenated_argv ) != TCL_OK )
350 free( (
void *) concatenated_argv );
353 free( (
void *) concatenated_argv );
359 if ( ( matPtr->
indices = (
int *) malloc( (
size_t) ( matPtr->
len ) * sizeof (
int ) ) ) == NULL )
362 "memory allocation failed for indices vector associated with Matrix operator \"",
363 matPtr->
name,
"\"", (
char *) NULL );
373 "old_bogus_syntax_please_upgrade", 0 ) == NULL )
375 Tcl_AppendResult(
interp,
"unable to schedule Matrix operator \"",
376 matPtr->
name,
"\" for automatic deletion", (
char *) NULL );
381 Tcl_TraceVar(
interp, matPtr->
name, TCL_TRACE_UNSETS,
388 fprintf( stderr,
"Creating Matrix operator of name %s\n", matPtr->
name );
401 hPtr = Tcl_CreateHashEntry( &
matTable, matPtr->
name, &
new );
405 "Unable to create hash table entry for Matrix operator \"",
406 matPtr->
name,
"\"", (
char *) NULL );
409 Tcl_SetHashValue( hPtr, matPtr );
411 Tcl_SetResult(
interp, matPtr->
name, TCL_VOLATILE );
517 int level,
int *offset,
int nargs,
const char** args )
519 static int verbose = 0;
521 const char ** newargs;
527 fprintf( stderr,
"level %d offset %d nargs %d\n", level, *offset, nargs );
528 for ( i = 0; i < nargs; i++ )
530 fprintf( stderr,
"i = %d, args[i] = %s\n", i, args[i] );
536 Tcl_AppendResult(
interp,
"too many list levels", (
char *) NULL );
540 for ( i = 0; i < nargs; i++ )
542 if ( Tcl_SplitList(
interp, args[i], &numnewargs, &newargs )
551 if ( numnewargs == 1 && strlen( args[i] ) == strlen( newargs[0] ) && strcmp( args[i], newargs[0] ) == 0 )
561 fprintf( stderr,
"\ta[%d] = %s\n", *offset, args[i] );
563 ( m->
put )( (ClientData) m,
interp, *offset, args[i] );
565 ( m->put )( (ClientData) m,
interp, m->indices[*offset], args[i] );
572 Tcl_Free( (
char *) newargs );
575 Tcl_Free( (
char *) newargs );
610 int char_converted, change_default_start, change_default_stop;
619 Tcl_AppendResult(
interp,
"wrong # args, type: \"",
620 argv[0],
" help\" for more info", (
char *) NULL );
627 stop[i] = matPtr->
n[i];
636 argv0_length = strlen(
argv[0] );
641 if ( ( c ==
'd' ) && ( strncmp(
argv[0],
"dump", argv0_length ) == 0 ) )
643 for ( i = start[0]; i < stop[0]; i++ )
645 for ( j = start[1]; j < stop[1]; j++ )
647 for ( k = start[2]; k < stop[2]; k++ )
649 ( *matPtr->
get )( (ClientData) matPtr,
interp,
I3D( i, j, k ), tmp );
650 printf(
"%s ", tmp );
652 if ( matPtr->
dim > 2 )
655 if ( matPtr->
dim > 1 )
664 else if ( ( c ==
'd' ) && ( strncmp(
argv[0],
"delete", argv0_length ) == 0 ) )
667 fprintf( stderr,
"Deleting array %s\n",
name );
676 else if ( ( c ==
'f' ) && ( strncmp(
argv[0],
"filter", argv0_length ) == 0 ) )
683 Tcl_AppendResult(
interp,
"wrong # args: should be \"",
684 name,
" ",
argv[0],
" num-passes\"",
691 Tcl_AppendResult(
interp,
"can only filter a 1d float matrix",
696 nfilt = atoi(
argv[1] );
699 for ( ifilt = 0; ifilt < nfilt; ifilt++ )
703 j = 0; tmpMat[j] = matPtr->
fdata[0];
704 for ( i = 0; i < matPtr->
len; i++ )
706 j++; tmpMat[j] = matPtr->
fdata[i];
708 j++; tmpMat[j] = matPtr->
fdata[matPtr->
len - 1];
712 for ( i = 0; i < matPtr->
len; i++ )
715 matPtr->
fdata[i] = 0.25 * ( tmpMat[j - 1] + 2 * tmpMat[j] + tmpMat[j + 1] );
719 free( (
void *) tmpMat );
725 else if ( ( c ==
'h' ) && ( strncmp(
argv[0],
"help", argv0_length ) == 0 ) )
728 "Available subcommands:\n\
729dump - return the values in the matrix as a string\n\
730delete - delete the matrix (including the matrix command)\n\
731filter - apply a three-point averaging (with a number of passes; ome-dimensional only)\n\
732help - this information\n\
733info - return the dimensions\n\
734max - return the maximum value for the entire matrix or for the first N entries\n\
735min - return the minimum value for the entire matrix or for the first N entries\n\
736redim - resize the matrix (for one-dimensional matrices only)\n\
737scale - scale the values by a given factor (for one-dimensional matrices only)\n\
739Set and get values:\n\
740matrix m f 3 3 3 - define matrix command \"m\", three-dimensional, floating-point data\n\
741m 1 2 3 - return the value of matrix element [1,2,3]\n\
742m 1 2 3 = 2.0 - set the value of matrix element [1,2,3] to 2.0 (do not return the value)\n\
743m * 2 3 = 2.0 - set a slice consisting of all elements with second index 2 and third index 3 to 2.0",
750 else if ( ( c ==
'i' ) && ( strncmp(
argv[0],
"info", argv0_length ) == 0 ) )
752 for ( i = 0; i < matPtr->
dim; i++ )
754 sprintf( tmp,
"%d", matPtr->
n[i] );
756 if ( i < matPtr->dim - 1 )
757 Tcl_AppendResult(
interp, tmp,
" ", (
char *) NULL );
759 Tcl_AppendResult(
interp, tmp, (
char *) NULL );
766 else if ( ( c ==
'm' ) && ( strncmp(
argv[0],
"max", argv0_length ) == 0 ) )
771 Tcl_AppendResult(
interp,
"wrong # args: should be \"",
779 len = atoi(
argv[1] );
780 if ( len < 0 || len > matPtr->
len )
782 Tcl_AppendResult(
interp,
"specified length out of valid range",
792 Tcl_AppendResult(
interp,
"attempt to find maximum of array with zero elements",
797 switch ( matPtr->
type )
801 for ( i = 1; i < len; i++ )
805 Tcl_AppendResult(
interp, tmp, (
char *) NULL );
810 for ( i = 1; i < len; i++ )
812 sprintf( tmp,
"%d",
max );
813 Tcl_AppendResult(
interp, tmp, (
char *) NULL );
822 else if ( ( c ==
'm' ) && ( strncmp(
argv[0],
"min", argv0_length ) == 0 ) )
827 Tcl_AppendResult(
interp,
"wrong # args: should be \"",
835 len = atoi(
argv[1] );
836 if ( len < 0 || len > matPtr->
len )
838 Tcl_AppendResult(
interp,
"specified length out of valid range",
848 Tcl_AppendResult(
interp,
"attempt to find minimum of array with zero elements",
853 switch ( matPtr->
type )
857 for ( i = 1; i < len; i++ )
861 Tcl_AppendResult(
interp, tmp, (
char *) NULL );
866 for ( i = 1; i < len; i++ )
868 sprintf( tmp,
"%d",
min );
869 Tcl_AppendResult(
interp, tmp, (
char *) NULL );
879 else if ( ( c ==
'r' ) && ( strncmp(
argv[0],
"redim", argv0_length ) == 0 ) )
886 Tcl_AppendResult(
interp,
"wrong # args: should be \"",
892 if ( matPtr->
dim != 1 )
894 Tcl_AppendResult(
interp,
"can only redim a 1d matrix",
899 newlen = atoi(
argv[1] );
900 switch ( matPtr->
type )
903 data = realloc( matPtr->
fdata, (
size_t) newlen * sizeof (
Mat_float ) );
904 if ( newlen != 0 && data == NULL )
906 Tcl_AppendResult(
interp,
"redim failed!",
911 for ( i = matPtr->
len; i < newlen; i++ )
912 matPtr->
fdata[i] = 0.0;
916 data = realloc( matPtr->
idata, (
size_t) newlen * sizeof (
Mat_int ) );
917 if ( newlen != 0 && data == NULL )
919 Tcl_AppendResult(
interp,
"redim failed!",
924 for ( i = matPtr->
len; i < newlen; i++ )
925 matPtr->
idata[i] = 0;
928 matPtr->
n[0] = matPtr->
len = newlen;
932 data = realloc( matPtr->
indices, (
size_t) ( matPtr->
len ) * sizeof (
int ) );
933 if ( newlen != 0 && data == NULL )
935 Tcl_AppendResult(
interp,
"redim failed!", (
char *) NULL );
938 matPtr->
indices = (
int *) data;
945 else if ( ( c ==
's' ) && ( strncmp(
argv[0],
"scale", argv0_length ) == 0 ) )
951 Tcl_AppendResult(
interp,
"wrong # args: should be \"",
952 name,
" ",
argv[0],
" scale-factor\"",
957 if ( matPtr->
dim != 1 )
959 Tcl_AppendResult(
interp,
"can only scale a 1d matrix",
964 scale = atof(
argv[1] );
965 switch ( matPtr->
type )
968 for ( i = 0; i < matPtr->
len; i++ )
969 matPtr->
fdata[i] *= scale;
973 for ( i = 0; i < matPtr->
len; i++ )
984 for (; p; p = p->
next )
986 if ( ( c == p->
cmd[0] ) && ( strncmp(
argv[0], p->
cmd, argv0_length ) == 0 ) )
989 fprintf( stderr,
"found a match, invoking %s\n", p->
cmd );
1008 Tcl_AppendResult(
interp,
"not enough dimensions specified for \"",
1009 name,
"\"", (
char *) NULL );
1013 for ( i = 0; i < matPtr->
dim; i++ )
1022 argv0_length = strlen(
argv[0] );
1030 stop[i] = matPtr->
n[i];
1032 change_default_start = 0;
1033 change_default_stop = 0;
1035 if ( sscanf(
argv[0],
"%d%1[:]%d%1[:]%d%n", start + i, c1, stop + i, c2, step + i, &char_converted ) >= 5 )
1039 else if ( sscanf(
argv[0],
"%d%1[:]%d%1[:]%n", start + i, c1, stop + i, c2, &char_converted ) >= 4 )
1043 else if ( sscanf(
argv[0],
"%d%1[:]%d%n", start + i, c1, stop + i, &char_converted ) >= 3 )
1047 else if ( sscanf(
argv[0],
"%d%1[:]%1[:]%d%n", start + i, c1, c2, step + i, &char_converted ) >= 4 )
1051 change_default_stop = 1;
1055 else if ( sscanf(
argv[0],
"%d%1[:]%1[:]%n", start + i, c1, c2, &char_converted ) >= 3 )
1059 else if ( sscanf(
argv[0],
"%d%1[:]%n", start + i, c1, &char_converted ) >= 2 )
1063 else if ( sscanf(
argv[0],
"%1[:]%d%1[:]%d%n", c1, stop + i, c2, step + i, &char_converted ) >= 4 )
1067 change_default_start = 1;
1071 else if ( sscanf(
argv[0],
"%1[:]%d%1[:]%n", c1, stop + i, c2, &char_converted ) >= 3 )
1075 else if ( sscanf(
argv[0],
"%1[:]%d%n", c1, stop + i, &char_converted ) >= 2 )
1079 else if ( sscanf(
argv[0],
"%1[:]%1[:]%d%n", c1, c2, step + i, &char_converted ) >= 3 )
1083 change_default_start = 1;
1084 change_default_stop = 1;
1088 else if ( strcmp(
argv[0],
"::" ) == 0 )
1091 else if ( strcmp(
argv[0],
":" ) == 0 )
1094 else if ( strcmp(
argv[0],
"*" ) == 0 )
1097 else if ( sscanf(
argv[0],
"%d%n", start + i, &char_converted ) >= 1 )
1101 start[i] += matPtr->
n[i];
1102 if ( start[i] < 0 || start[i] > matPtr->
n[i] - 1 )
1104 sprintf( tmp,
"Array index %d out of bounds: original string = \"%s\"; transformed = %d; min = 0; max = %d\n",
1105 i,
argv[0], start[i], matPtr->
n[i] - 1 );
1106 Tcl_AppendResult(
interp, tmp, (
char *) NULL );
1109 stop[i] = start[i] + 1;
1113 sprintf( tmp,
"Array slice for index %d with original string = \"%s\" could not be parsed\n",
1115 Tcl_AppendResult(
interp, tmp, (
char *) NULL );
1122 Tcl_AppendResult(
interp,
"step part of slice must be non-zero",
1126 sign_step[i] = ( step[i] > 0 ) ? 1 : -1;
1127 if ( (
size_t) char_converted > argv0_length )
1129 Tcl_AppendResult(
interp,
"MatrixCmd, internal logic error",
1133 if ( (
size_t) char_converted < argv0_length )
1135 sprintf( tmp,
"Array slice for index %d with original string = \"%s\" "
1136 "had trailing unparsed characters\n", i,
argv[0] );
1137 Tcl_AppendResult(
interp, tmp, (
char *) NULL );
1141 start[i] += matPtr->
n[i];
1142 start[i] =
MAX( 0,
MIN( matPtr->
n[i] - 1, start[i] ) );
1143 if ( change_default_start )
1144 start[i] = matPtr->
n[i] - 1;
1146 stop[i] += matPtr->
n[i];
1148 stop[i] =
MAX( 0,
MIN( matPtr->
n[i], stop[i] ) );
1150 stop[i] =
MAX( -1,
MIN( matPtr->
n[i], stop[i] ) );
1151 if ( change_default_stop )
1174 fprintf( stderr,
"Array slice for index %d with original string = \"%s\" "
1175 "yielded start[i], stop[i], transformed stop[i], and step[i] = "
1176 "%d, %d, ", i,
argv[0], start[i], stop[i] );
1178 stop[i] = sign_step[i] * stop[i];
1180 fprintf( stderr,
"%d, %d\n", stop[i], step[i] );
1190 if ( strcmp(
argv[0],
"=" ) == 0 )
1195 Tcl_AppendResult(
interp,
"no value specified",
1202 Tcl_AppendResult(
interp,
"extra characters after indices: \"",
1203 argv[0],
"\"", (
char *) NULL );
1211 for ( i = start[0]; sign_step[0] * i < stop[0]; i += step[0] )
1213 for ( j = start[1]; sign_step[1] * j < stop[1]; j += step[1] )
1215 for ( k = start[2]; sign_step[2] * k < stop[2]; k += step[2] )
1229 switch ( matPtr->
type )
1232 strtod(
argv[0], &endptr );
1235 strtol(
argv[0], &endptr, 10 );
1238 if (
argc == 1 && *
argv[0] !=
'\0' && *endptr ==
'\0' )
1244 for ( i = 0; i < matPtr->
nindices; i++ )
1257 size_t concatenated_argv_len;
1258 char *concatenated_argv;
1259 const char *const_concatenated_argv;
1266 concatenated_argv_len = 3;
1267 for ( i = 0; i <
argc; i++ )
1269 concatenated_argv_len += strlen(
argv[i] ) + 1;
1270 concatenated_argv = (
char *) malloc( concatenated_argv_len *
sizeof (
char ) );
1273 concatenated_argv[0] =
'\0';
1274 strcat( concatenated_argv,
"{" );
1275 for ( i = 0; i <
argc; i++ )
1277 strcat( concatenated_argv,
argv[i] );
1278 strcat( concatenated_argv,
" " );
1280 strcat( concatenated_argv,
"}" );
1282 const_concatenated_argv = (
const char *) concatenated_argv;
1286 if (
MatrixAssign(
interp, matPtr, 0, &offset, 1, &const_concatenated_argv ) != TCL_OK )
1288 free( (
void *) concatenated_argv );
1291 free( (
void *) concatenated_argv );
1297 for ( i = 0; i < matPtr->
nindices; i++ )
1299 ( *matPtr->
get )( (ClientData) matPtr,
interp, matPtr->indices[i], tmp );
1300 if ( i < matPtr->nindices - 1 )
1301 Tcl_AppendResult(
interp, tmp,
" ", (
char *) NULL );
1303 Tcl_AppendResult(
interp, tmp, (
char *) NULL );
char * strcpy(char *dst, const char *src)
static Tcl_Interp * interp