/* ** Title: MMXMatrix ** SCCSid: %W% %E% %U% ** CCid: %W% %E% %U% ** Author: Informix Software, Inc. ** Created: 06/11/1998 14:52 ** Description: This is the generated 'C' file for the MMXMatrix DataBlade. ** Comments: Generated for project MMXMatrix.3.6 */ /* ** The following is placed here to insure ** that name "mangling" does not occur. */ #ifdef __cplusplus extern "C" { #endif /* Standard library includes. */ /* #include */ #include #include #include #include #include /* Used by Informix GLS routines. */ #include /* Include when accessing the Informix API. */ #include /* This is the project include file. */ #include "MMXMatrix.h" /* OPCODE DEFINITIONS ////////////////////////////////////////*/ #define CPU_ID _asm _emit 0x0f _asm _emit 0xa2 /* PROGRAMMER's NOTE: Matrix Structure - This structure will be used to store the MxN matrix */ typedef struct { int noOfRows; int noOfCols; _int16 data[1]; } Matrix2d; /* PROGRAMMER's NOTE: Vector Structure - This structure will be used to store a 1xN matrix. */ typedef struct { int Length; _int16 data[1]; } Vector1d; /* PROGRAMMER's NOTE: These are the prototypes for the matrix multiplication functions. /* PROGRAMMER's NOTE: The MMX Version. This version is restricted in its use by the dimensions of the input matrix. The input matrix has to have 16 or multiples of 16 columns and even number of rows. Any other dimension will be delegated to the c version of the function. */ void VxMmmx (_int16 *vect, _int16 *matr, _int16 *res, int x_size, int y_size); /* PROGRAMMER's NOTE: The C Version */ void VxMc (_int16 *vect, _int16 *matr, _int16 *res, int x_size, int y_size); /* Function to parse the string containing the matrix into the Matrix2d structure */ Matrix2d *Matrix2dParse (char * Gen_param1); /* Function to parse the string containing the vector into the Vector1d structure */ Vector1d *VectorParse (char * chVector); /* Function to convert the vector2d structure into a string. */ mi_string * VectorOut(Vector1d *vector); /* Outputs a vector to a string */ int clone_flag; DWORD wincpufeatures(void); void dbException( char *msg) { mi_db_error_raise((MI_CONNECTION *)NULL, MI_EXCEPTION, msg); /* not reached */ } /* {{FUNCTION(ae699d60-248f-11d1-a42d-00a0c9220c70) (MergeSection) */ /**************************************************************** ** ** Function name: ** ** MatrixMultiply ** ** Description: ** ** Special Comments: ** ** Entrypoint for the SQL routine MatrixMultiply (lvarchar,lvarchar) returns lvarchar. ** ** Parameters: ** ** Return value: ** ** mi_lvarchar ** ** History: ** ** 06/30/1998 - Generated by BladeSmith Version 3.60.630 . ** ** Identification: ** ** NOTE: ** ** BladeSmith will add and remove parameters from the function ** prototype, and will generate tracing calls. ONLY EDIT code ** in blocks marked Your_
. Any other modifications ** will require manual merging. ** ***************************************************************** */ UDREXPORT mi_lvarchar *MatrixMultiply ( mi_lvarchar * matrix, mi_lvarchar * vector, MI_FPARAM * Gen_fparam /* Standard info - see DBDK docs.*/ ) { mi_lvarchar* Gen_RetVal; /* The return value. */ MI_CONNECTION * Gen_Con; /* The connection handle. */ /* ------ {{Your_Declarations (PreserveSection) BEGIN ------ */ Matrix2d *matrix_struct; Vector1d *vect_struct, *result_struct; mi_string *tmpmatrix; mi_string *tmpvector; /* ------ }}Your_Declarations (#0000) END ------ */ /* Use the NULL connection. */ Gen_Con = NULL; /* ------ {{Your_Code (PreserveSection) BEGIN ------ */ /* ** Write to the trace file indicating ** that MatrixMultiply has been called. */ DBDK_TRACE_ENTER( "MatrixMultiply" ); tmpmatrix = mi_lvarchar_to_string(matrix); tmpvector = mi_lvarchar_to_string(vector); /* Convert Matrix string to Matrix structure */ /* Note that the matrix is laid out in row major order. */ matrix_struct = Matrix2dParse(tmpmatrix); /* Convert vector string to Vector structure */ vect_struct = VectorParse(tmpvector); if (vect_struct->Length != matrix_struct->noOfRows) dbException ("Incompatible Matrices"); /* We allocate noOfCols - 1 elements in addition to Vector1d because Vector1d already has the required space for 1 element. */ result_struct = mi_alloc(sizeof(Vector1d) + (sizeof(_int16) * (matrix_struct->noOfCols-1))); if( Gen_IsMMXMachine() ) { /* MMX CODE ASSUMES 16n columns x 2m rows, if otherwise use the C multiply function */ if( ( matrix_struct->noOfCols % 16 == 0 ) && ( matrix_struct->noOfRows % 2 == 0 ) ) VxMmmx (&(vect_struct->data[0]),&(matrix_struct->data[0]),&(result_struct->data[0]), matrix_struct->noOfCols, matrix_struct->noOfRows); else VxMc (&(vect_struct->data[0]),&(matrix_struct->data[0]),&(result_struct->data[0]), matrix_struct->noOfCols, matrix_struct->noOfRows); } else { /* No MMX support, calling C routine instead. */ VxMc (&(vect_struct->data[0]),&(matrix_struct->data[0]),&(result_struct->data[0]), matrix_struct->noOfCols, matrix_struct->noOfRows); } result_struct->Length = matrix_struct->noOfCols; /* Convert resultant vector into string. */ Gen_RetVal = (mi_lvarchar *) mi_string_to_lvarchar(VectorOut(result_struct)); mi_free( matrix_struct ); mi_free( vect_struct ); mi_free( result_struct ); /* ** Write to the trace file indicating ** that MatrixMultiply has successfully exited. */ DBDK_TRACE_EXIT( "MatrixMultiply" ); /* ------ }}Your_Code (#O0PL) END ------ */ /* Return the function's return value. */ return Gen_RetVal; } /* }}FUNCTION (#HHCVI50G) */ /**************************************************************** ** Function name: ** ** matrix_sscanf -- Returns ptr to the new position ** after sscanf for integers... ** ** Description: ** ** This is a support routine used by the matrix input code to ** parse the user-supplied matrix string. ** ***************************************************************** */ /* This function has been specialized to scan for integers. */ static char * matrix_sscanf( char *ps, _int16 *pb ) { if( 1 != sscanf( ps, "%d", pb) ) dbException( "Input data format error" ); ps += (int) log10 ((double)*pb) + 1; /* Increment by number of digits in the found integer.. */ return ps; } /**************************************************************** ** Function name: ** ** _noOfRowsAndCols -- Compute the number of rows and ** columns in an input matrix. ** ** Description: ** ** Parses the textual representation of the matrix and counts ** the number of rows and columns. This is a support routine for ** the matrix input code. On error, it raises an exception and ** aborts the command. ** ***************************************************************** */ static void _noOfRowsAndCols( char *ps, int *pNoOfRows, int *pNoOfCols ) { int nRows, nCols, nCurrCols; enum { START, BEGINMATRIX, BEGINCOL, ENDROW, NUMBER, DECIMAL, ENDNUMBER, ENDMATRIX } state; nRows = 0; nCols = 0; nCurrCols = 0; state = START; do { switch( state ) { case START: if( isspace( *ps ) ) state = START; else if ('(' == (*ps)) state = BEGINMATRIX; else dbException("Invalid character"); break; case BEGINMATRIX: if( isspace( *ps ) ) state = BEGINMATRIX; else if ('(' == (*ps)) state = BEGINCOL; else dbException("Invalid character"); break; case BEGINCOL: if( isspace( *ps ) ) state = BEGINCOL; else if (isdigit(*ps) || '+' == (*ps) || '-' == (*ps) ) state = NUMBER; else if ('.' == (*ps)) state = DECIMAL; else dbException("Invalid character"); break; case NUMBER: if (isdigit(*ps) || '+' == (*ps) || '-' == (*ps) || 'E' == (*ps)) state = NUMBER; else if ('.' == (*ps)) state = DECIMAL; else if( ')' == (*ps) ) { nCurrCols++; if ((nCols) && (nCurrCols != nCols)) dbException("Incorrect number of columns"); else { nCols = nCurrCols; nCurrCols = 0; nRows++; } state = ENDROW; } else if( isspace( *ps ) ) state = ENDNUMBER; else if (',' == (*ps)) {nCurrCols++; state = BEGINCOL;} else dbException("Invalid character"); break; case DECIMAL: if (isdigit(*ps) || '+' == (*ps) || '-' == (*ps) || 'E' == (*ps)) state = DECIMAL; else if( ')' == (*ps) ) { nCurrCols++; if ((nCols) && (nCurrCols != nCols)) dbException("Incorrect number of columns"); else { nCols = nCurrCols; nCurrCols = 0; nRows++; } state = ENDROW; } else if( isspace( *ps ) ) state = ENDNUMBER; else if (',' == (*ps)) {nCurrCols++; state = BEGINCOL;} else dbException("Invalid character"); break; case ENDNUMBER: if( ')' == (*ps) ) { nCurrCols++; if ((nCols) && (nCurrCols != nCols)) dbException("Incorrect number of columns"); else { nCols = nCurrCols; nCurrCols = 0; nRows++; } state = ENDROW; } else if( isspace( *ps ) ) state = ENDNUMBER; else if (',' == (*ps)) {nCurrCols++; state = BEGINCOL;} else dbException("Invalid character"); break; case ENDROW: if( ')' == (*ps) ) state = ENDMATRIX; else if( isspace( *ps ) || (',' == (*ps)) ) state = ENDROW; else if ('(' == (*ps)) state = BEGINCOL; else dbException("Invalid character"); break; case ENDMATRIX: if( (isspace( *ps )) || !(*ps) ) state = ENDMATRIX; else dbException("Invalid character"); break; } } while (*(ps++)); *pNoOfRows = nRows; *pNoOfCols = nCols; } /**************************************************************** ** ** Function name: ** ** VectorParse ** ** Description: ** ** Special Comments: ** ** Function takes a string and Parses it into a Vector1d Data Structure. ** String is a comma separated list of integers, surrounded by double round ** parentheses. ((x,y,z...)) ** ** Parameters: ** ** Return value: ** ** Vector1d * ** ** History: ** ** Sep 03, 1997 - Generated by BladeSmith Version 3.60.TC1B1. ** ** Identification: ** ** ***************************************************************** */ Vector1d * VectorParse ( char * chVector /* Pointer to the input text. */ ) { Vector1d *Gen_OutData; /* The return value. */ char *tempStr; int i; int noOfRows; /* Number of rows */ int noOfCols; /* Number of columns */ _int16 tempNo; // tempStr = chVector; /* Point to the input data. */ /* Compute the number of rows and columns in the vector */ _noOfRowsAndCols( chVector, &noOfRows, &noOfCols ); if( noOfRows != 1 ) { dbException("Vector contains more than one row" ); } Gen_OutData = mi_alloc (sizeof( Vector1d ) + (noOfCols - 1)* sizeof( Gen_OutData->data)); if( Gen_OutData == 0 ) { dbException("VectorParse MemAlloc ERROR"); /* not reached */ } tempStr = (char *) chVector; for (i=0;i data[i] = tempNo; } Gen_OutData -> Length = noOfCols; /* Return the UDT value. */ return Gen_OutData; } /**************************************************************** ** ** Function name: ** ** Matrix2dParse ** ** Description: ** ** This function converts from the external representation of the ** UDT type Matrix2d to its internal representation. ** The external representation is a comma seperated list sourrounded ** by round parenthesis. Each row itself is a comma seperated ** list surrounded by round parenthesis: ** ((x1,y1),(x2,y2),...) ** The internal representation is a 'C' structure of type Matrix2d as ** defined in the header file. ** ** Data may be inserted into a table using an SQL insert statment: ** ** insert into tablename values ( 'value-list' ); ** ** value-list is a space-delimited list of values. ** ** Special Comments: ** ** Support routine for opaque type Matrix2d. ** */ Matrix2d * Matrix2dParse ( char * Gen_InData /* Pointer to the input text. */ ) { Matrix2d *Gen_OutData; /* The return value. */ int Gen_DataLen; /* Length of the data in bytes. */ Matrix2d *Gen_RetVal; /* The return value. */ int Gen_vl_nitems; /* Number of variable length items. */ int Gen_vl_itemno; /* Index through the items. */ int noOfRows; /* Number of rows */ int noOfCols; /* Number of columns */ char *tempStr; /* Point to the input data. */ /* Compute the number of repetitions in the variable length input. */ _noOfRowsAndCols( (char*)Gen_InData, &noOfRows, &noOfCols ); Gen_vl_nitems = noOfRows*noOfCols; /* Compute the amount of memory required for the data. */ Gen_DataLen = sizeof( Matrix2d ) + (Gen_vl_nitems - 1 ) * sizeof( Gen_OutData->data ); /* Allocate sufficient memory to build the UDT in. */ Gen_RetVal = malloc( Gen_DataLen ); if( Gen_RetVal == 0 ) { /* ** Memory allocation has failed so issue ** the following message and quit. ** ** "Memory allocation has failed in Matrix2dInput." */ dbException("Matrix2dInput Allocation Error"); /* not reached */ } /* Point to the output data. */ Gen_OutData = Gen_RetVal; /* Handle the fixed part of the UDT. */ /* Get the data value for Gen_OutData->noOfRows. */ Gen_OutData->noOfRows = noOfRows; /* Get the data value for Gen_OutData->noOfCols. */ Gen_OutData->noOfCols = noOfCols; /* Handle the variable part of the UDT. */ tempStr = (char *)Gen_InData; for( Gen_vl_itemno = 0; Gen_vl_itemno < Gen_vl_nitems; Gen_vl_itemno++ ) { while ( (!isdigit(*tempStr)) && ((*tempStr) != '.') && ((*tempStr) != '+') && ((*tempStr) != '-') ) { tempStr++; } tempStr = matrix_sscanf( tempStr, &Gen_OutData->data[Gen_vl_itemno] ); } /* Return the UDT value. */ return Gen_RetVal; } /**************************************************************** ** ** Function name: ** ** VectorOut ** ** Description: ** ** Special Comments: ** ** Function takes a Vector1d and represents it as a string. ** ** Parameters: ** ** Return value: ** ** mi_lvarchar * ** ** History: ** ** Sep 03, 1997 - Generated by BladeSmith Version 3.60.TC1B1. ** ** Identification: ** ** Warning: Do not remove or modify this comment: ** MatrixMultiply FunctionId: ae699d60-248f-11d1-a42d-00a0c9220c70 ** ***************************************************************** */ mi_string * VectorOut(Vector1d *vector) { char tempbuff[1000] = ""; mi_string *vectorbuff = NULL; int i; // Assuming maximum length of an integer represented as string is 32 characters. vectorbuff = ( mi_string * ) mi_alloc( sizeof( mi_string ) * 32 * vector->Length ); strcpy(vectorbuff, "(("); for (i=0; iLength; i++) { sprintf (tempbuff, "%d", vector->data[i]); if (i != vector->Length-1) strcat(tempbuff, ", "); strcat(vectorbuff, tempbuff); } strcat(vectorbuff, "))"); return vectorbuff; } /**************************************************************** ** ** Function name: ** ** VxMc, VxMmmx ** ** Description: ** ** Special Comments: ** ** Calculate the product of a vector and a matrix. Arithmetic Intensive ** Dramatic performance gain on MMX Machines. ** ** Parameters: ** ** Return value: ** ** mi_lvarchar * ** ** History: ** ** Sep 03, 1997 - Generated by BladeSmith Version 3.60.TC1B1. ** ** Identification: ** ** Warning: Do not remove or modify this comment: ** MatrixMultiply FunctionId: ae699d60-248f-11d1-a42d-00a0c9220c70 ** ***************************************************************** */ void VxMc ( _int16 *vect, _int16 *matr, _int16 *res, int x_size, //No of Columns int y_size //No of Rows ) { int i,j; _int16 accum; for (i=0; i