LISTING 2 - Matrix.library Functions in C /* * Matrix.c * * Contains the standard library and user functions * for Matrix.library * * This code is FREELY DISTRIBUTABLE but NOT PUBLIC DOMAIN. * (Written by Randy Finch) */ #include #include #include #include #include #include #include /* Useful definitions for allocating vectors and matrices */ #define ChkLVector(v,els) \ {if(!v) { v = AllocLVector(els); if(!v) return NULL; } } #define ChkDVector(v,els) \ {if(!v) { v = AllocDVector(els); if(!v) return NULL; } } #define ChkLMatrix(m,rows,cols) \ {if(!m) { m = AllocLMatrix(rows,cols); if(!m) return NULL; } } #define ChkDMatrix(m,rows,cols) \ {if(!m) { m = AllocDMatrix(rows,cols); if(!m) return NULL; } } /* The Extended Library structure is equivalent to the one in MatrixLib.a. Since a pointer is passed from assembly to the C routines, the same data can be manipulated from C or assembly. Make sure the two structures are EQUIVALENT!!! */ typedef struct Library LIB; struct ExtLibrary { LIB lib; /* User data can go here */ LONG seglist; LONG SysBase; LIB *MathIeeeDoubBasBase; }; typedef struct ExtLibrary ELIB; extern LIB *MathIeeeDoubBasBase; #define VERSION 1 #define REVISION 0 /* * The Initialization routine is given only the library pointer. * Since we are NOT AUTOINIT we must add the library ourself * and return the library pointer. Exec has Forbid() * for us during the call. * */ ELIB *CInit(lib) ELIB *lib; { /* Here is where other libraries are opened and internal data * structures are initialized */ MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library",0L); if(!MathIeeeDoubBasBase) return (ELIB *)NULL; lib->MathIeeeDoubBasBase = MathIeeeDoubBasBase; AddLibrary((LIB *)lib); /* Add ourself because we are not auto init*/ return(lib); } /* * Open is given the library pointer and the version request. Either * return the library pointer or NULL. Remove the DELAYED-EXPUNGE flag. * OpenLibrary() will check the version for us; we do not need to check. * Exec has Forbid() for us during the call. */ ELIB *LibOpen(lib,version) ELIB *lib; long version; { ++(lib->lib.lib_OpenCnt); lib->lib.lib_Flags &= ~LIBF_DELEXP; /* Here is where you can do whatever is needed each time the library * is opened. */ return(lib); } /* * Close is given the library pointer. Be sure * not to decrement the open count if already zero. If the open count * is or becomes zero AND there is a LIBF_DELEXP, we expunge the library * and return the seglist. Otherwise we return NULL. * * Note that this routine never sets LIBF_DELEXP on its own. * * Exec has Forbid() for us during the call. */ LibClose(lib) ELIB *lib; { if (lib->lib.lib_OpenCnt) { --(lib->lib.lib_OpenCnt); return(NULL); } if (lib->lib.lib_Flags & LIBF_DELEXP) return(LibExpunge(lib)); return(NULL); } /* * We expunge the library and return the Seglist ONLY if the open count * is zero. If the open count is not zero we set the DELAYED-EXPUNGE * flag and return NULL. * * Exec has Forbid() for us during the call. NOTE ALSO that Expunge * might be called from the memory allocator and thus we CANNOT DO A * Wait() or otherwise take a long time to complete (straight from RKM). * * Apparently RemLibrary(lib) calls our expunge routine and would * therefore freeze if we called it ourselves. It appears that * LibExpunge(lib) must remove the library itself as shown below. */ LibExpunge(lib) ELIB *lib; { long seg; if (lib->lib.lib_OpenCnt) { lib->lib.lib_Flags |= LIBF_DELEXP; return(NULL); } /* Clean up yourself here */ CloseLibrary(MathIeeeDoubBasBase); seg = lib->seglist; Remove((struct Node *)lib); return(seg); } /*----------------------------------------------------------------------*/ /* And now it is time to put in the USER FUNCTIONS */ /*----------------------------------------------------------------------*/ /*--------------------------------------------------- Routines for LONG INTEGER vectors and matrices -----------------------------------------------------*/ /* Allocate a long integer vector with numels number of elements */ LONG *AllocLVector(numels) LONG numels; { LONG *v; if (numels <= 0L) return NULL; /* Number of elements must be > zero */ v = (LONG *)AllocMem(numels*sizeof(LONG),MEMF_CLEAR); return v; /* v will be NULL if allocation failed */ } /* AllocLVector */ /* Allocate a long integer matrix */ LONG **AllocLMatrix (numrows, numcols) LONG numrows, numcols; { LONG i, j; LONG **m; /* Number of rows and columns must be > zero */ if ( (numrows <= 0L) || (numcols <= 0L) ) return NULL; /* Allocate row pointers */ m = (LONG **)AllocMem(numrows*sizeof(LONG *),MEMF_CLEAR); if (!m) return NULL; /* allocation failed */ /* Allocate row vectors and equate row pointers to them */ for (i=0L ; i=0L ; i--) { FreeMem((void *)m[i], numcols*sizeof(LONG)); /* Free elements */ } FreeMem((void *)m, numrows*sizeof(LONG *)); /* Free row pointers */ return TRUE; } return FALSE; } /* FreeLMatrix () */ /* Add two long integer vectors */ LONG *AddLVectors (v1, v2, vr, numels) LONG *v1, *v2, *vr; LONG numels; { LONG i; ChkLVector(vr,numels); for (i=0L ; i zero */ v = (DOUBLE *)AllocMem(numels*sizeof(DOUBLE),MEMF_CLEAR); return v; /* v will be NULL if allocation failed */ } /* AllocDVector */ /* Allocate a double matrix */ DOUBLE **AllocDMatrix (numrows, numcols) LONG numrows, numcols; { LONG i, j; DOUBLE **m; /* Number of rows and columns must be > zero */ if ( (numrows == 0L) || (numcols == 0L) ) return NULL; /* Allocate row pointers */ m = (DOUBLE **)AllocMem(numrows*sizeof(DOUBLE *),MEMF_CLEAR); if (!m) return NULL; /* AllocMem failed */ /* Allocate row vectors and equate row pointers to them */ for (i=0L ; i=0L ; i--) { FreeMem((void *)m[i], numcols*sizeof(DOUBLE)); /* Free elements */ } FreeMem ((void *)m, numrows*sizeof(DOUBLE *)); /* Free row pointers */ return TRUE; } return FALSE; } /* FreeDMatrix () */ /* Add two double vectors */ DOUBLE *AddDVectors (v1, v2, vr, numels) DOUBLE *v1, *v2, *vr; LONG numels; { LONG i; ChkDVector(vr,numels); for (i=0L ; i biggest) biggest=temp; } /* for */ if (biggest == 0.0) return FALSE; /* Singular matrix */ rowscale[i] = 1.0/biggest; /* Store the scale factor */ } /* for */ for (j=0 ; j= biggest) { biggest = dummy; imax = i; } /* if */ } /* for */ if (j != imax) { for (k=0 ; k=0 ; i--) { sum = b[i]; for (j=i+1 ; j