From d782d439519a4a5487f6f351604eaebedd52ebd1 Mon Sep 17 00:00:00 2001 From: cvs Date: Wed, 12 Jul 2000 12:01:19 +0000 Subject: [PATCH] - added backwards calculation of hkl from four circle angles. This required inclusion of a matrix package. - modified counter error handling to send a Stop when the _BAD_BUSY error is received. - added an environment interface to the general controller stuff in choco.* Also added setting a parameter directly at the controller object. - Added a driver for the ETH High Temperature Furnace to be used at SANS. --- Makefile | 7 +- SCinter.c | 9 +- chadapter.c | 189 ++++++++++++ chadapter.h | 1 + choco.c | 28 ++ choco.tex | 1 + choco.w | 3 +- countdriv.c | 13 +- counter.c | 11 +- counter.h | 1 + danu.dat | 2 +- drive.c | 2 +- evcontroller.c | 16 +- hkl.c | 80 +++++- hkl.i | 1 + hkl.tex | 1 + hkl.w | 1 + hklscan.c | 1 + matrix/DEMO.DAT | 20 ++ matrix/DEMO.EXE | Bin 0 -> 33384 bytes matrix/MAKEFILE.MSC | 62 ++++ matrix/MAKEFILE.TC | 74 +++++ matrix/MAKEFILE.UX | 54 ++++ matrix/MATRIX.DOC | 482 +++++++++++++++++++++++++++++++ matrix/READ.ME | 112 ++++++++ matrix/demo.c | 92 ++++++ matrix/matadd.c | 43 +++ matrix/matcreat.c | 198 +++++++++++++ matrix/matdet.c | 115 ++++++++ matrix/matdump.c | 78 +++++ matrix/matdurbn.c | 133 +++++++++ matrix/materr.c | 46 +++ matrix/matinv.c | 77 +++++ matrix/matmul.c | 60 ++++ matrix/matrix.h | 136 +++++++++ matrix/matsolve.c | 182 ++++++++++++ matrix/matsub.c | 42 +++ matrix/matsubx.c | 48 ++++ matrix/mattoepz.c | 43 +++ matrix/mattran.c | 45 +++ sanscook.c | 682 ++++++++++++++++++++++++++++++++++++++++++++ sicsstatus.tcl | 6 +- stptok.c | 13 +- test.tcl | 14 +- 44 files changed, 3199 insertions(+), 25 deletions(-) create mode 100644 matrix/DEMO.DAT create mode 100644 matrix/DEMO.EXE create mode 100644 matrix/MAKEFILE.MSC create mode 100644 matrix/MAKEFILE.TC create mode 100644 matrix/MAKEFILE.UX create mode 100644 matrix/MATRIX.DOC create mode 100644 matrix/READ.ME create mode 100644 matrix/demo.c create mode 100644 matrix/matadd.c create mode 100644 matrix/matcreat.c create mode 100644 matrix/matdet.c create mode 100644 matrix/matdump.c create mode 100644 matrix/matdurbn.c create mode 100644 matrix/materr.c create mode 100644 matrix/matinv.c create mode 100644 matrix/matmul.c create mode 100644 matrix/matrix.h create mode 100644 matrix/matsolve.c create mode 100644 matrix/matsub.c create mode 100644 matrix/matsubx.c create mode 100644 matrix/mattoepz.c create mode 100644 matrix/mattran.c create mode 100644 sanscook.c diff --git a/Makefile b/Makefile index 552d6446..78255448 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ sanswave.o faverage.o bruker.o rmtrail.o fowrite.o ltc11.o \ simchop.o choco.o chadapter.o docho.o trim.o eurodriv.o scaldate.o \ hklscan.o xytable.o amor2t.o nxamor.o amorscan.o amorstat.o \ - circular.o el755driv.o maximize.o sicscron.o tecsdriv.o + circular.o el755driv.o maximize.o sicscron.o tecsdriv.o sanscook.o MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o COUNTEROBJ = countdriv.o simcter.o counter.o @@ -53,8 +53,9 @@ CC=cc EXTRA= CFLAGS = -I$(HDFROOT)/include -Ihardsup -I. -std1 -g -warnprotos -c #CFLAGS = -I$(HDFROOT)/include -DFORTIFY -Ihardsup -g -std1 -warnprotos -c -LIBS = -L$(HDFROOT)/lib -Lhardsup -lhlib -Ltecs -ltecsl -ltcl8.0 -lfor -lmfhdf -ldf \ - $(HDFROOT)/lib/libjpeg.a -lz -lm -ll -lc +LIBS = -L$(HDFROOT)/lib -Lhardsup -lhlib -Lmatrix -lmatrix -Ltecs \ + -ltecsl -ltcl8.0 -lfor -lmfhdf -ldf $(HDFROOT)/lib/libjpeg.a \ + -lz -lm -ll -lc #------- for cygnus #HDFROOT=../HDF411 diff --git a/SCinter.c b/SCinter.c index e6d0738f..0fb57c4c 100644 --- a/SCinter.c +++ b/SCinter.c @@ -302,10 +302,13 @@ extern char *SkipSpace(char *pPtr); pCurrent = self->pCList; while(pCurrent) { - if(strcmp(pCurrent->pName, pBueffel) == 0 ) + if(pCurrent->pName != NULL) { - return pCurrent; - } + if(strcmp(pCurrent->pName, pBueffel) == 0 ) + { + return pCurrent; + } + } pCurrent = pCurrent->pNext; } return NULL; diff --git a/chadapter.c b/chadapter.c index 33f806f3..3e5753d6 100644 --- a/chadapter.c +++ b/chadapter.c @@ -14,10 +14,15 @@ #include #include "fortify.h" #include "sics.h" +#define CHOCOINTERNAL #include "choco.h" +#include "evcontroller.h" +#include "evdriver.i" #define CHADAINTERNAL #include "chadapter.h" +#define NOTIMPLEMENTED -11555 + /*-------------------------------------------------------------------------*/ static void *AdapterGetInterface(void *pData, int iID) { @@ -313,6 +318,190 @@ return 1; } +/*========================================================================= + An environment driver based on top of a controller object. + -------------------------------------------------------------------------*/ + static int AVEVSetValue(pEVDriver self, float fNew) + { + pCHev myData; + + assert(self); + myData = (pCHev)self->pPrivate; + assert(myData); + myData->iLastError = 0; + + return myData->pDriv->SetPar(myData->pDriv,myData->pParName,fNew); + } +/*-----------------------------------------------------------------------*/ + static int AVEVGetValue(pEVDriver self, float *fNew) + { + pCHev myData; + int iRet; + char pBueffel[80]; + + assert(self); + myData = (pCHev)self->pPrivate; + assert(myData); + + iRet = myData->pDriv->GetPar(myData->pDriv,myData->pParName, + pBueffel,79); + sscanf(pBueffel,"%f",fNew); + return iRet; + } +/*-----------------------------------------------------------------------*/ + static int AVEVSend(pEVDriver self, char *pCommand, + char *pReply, int iLen) + { + pCHev myData; + + assert(self); + myData = (pCHev)self->pPrivate; + assert(myData); + myData->iLastError = NOTIMPLEMENTED; + + return 0; + } +/*-----------------------------------------------------------------------*/ + static int AVEVGetError(pEVDriver self, int *iCode, + char *pReply, int iLen) + { + pCHev myData; + + assert(self); + myData = (pCHev)self->pPrivate; + assert(myData); + + if(myData->iLastError == NOTIMPLEMENTED) + { + strncpy(pReply,"ERROR: Not Implemented here!", iLen); + *iCode = NOTIMPLEMENTED; + myData->iLastError = 0; + return 1; + } + else + { + return myData->pDriv->GetError(myData->pDriv, iCode, + pReply, iLen); + } + } +/*------------------------------------------------------------------------*/ + static int AVEVTryFixIt(pEVDriver self, int iCode) + { + pCHev myData; + + assert(self); + myData = (pCHev)self->pPrivate; + assert(myData); + + if(iCode == NOTIMPLEMENTED) + { + return DEVFAULT; + } + else + { + return myData->pDriv->TryFixIt(myData->pDriv, iCode); + } + } +/*---------------------------------------------------------------------*/ + static int AVEVInit(pEVDriver self) + { + pCHev myData; + + assert(self); + myData = (pCHev)self->pPrivate; + assert(myData); + + return myData->pDriv->Init(myData->pDriv); + } +/*---------------------------------------------------------------------*/ + static int AVEVClose(pEVDriver self) + { + pCHev myData; + + assert(self); + myData = (pCHev)self->pPrivate; + assert(myData); + + return myData->pDriv->Close(myData->pDriv); + } +/*----------------------------------------------------------------------*/ + static void AVEVKillPrivate(void *pData) + { + pCHev myData; + + if(pData != NULL) + { + myData = (pCHev)pData; + if(myData != NULL) + { + if(myData->pParName) + free(myData->pParName); + free(myData); + } + } + } +/*---------------------------------------------------------------------*/ + pEVDriver MakeControllerEnvironmentDriver(int argc, char *argv[]) + { + pEVDriver pNew = NULL; + pCHev myData = NULL; + CommandList *pCom = NULL; + pDummy pDum = NULL; + pChoco pChop; + + /* + Two arguments are needed: the name of the controller and the + name of the parameter + */ + if(argc < 2) + { + return NULL; + } + pCom = FindCommand(pServ->pSics,argv[0]); + if(!pCom) + { + return NULL; + } + pDum = pCom->pData; + if(!pDum) + { + return NULL; + } + if(strcmp(pDum->pDescriptor->name,"Chopper") != 0) + { + return NULL; + } + + /* alright: I think we got a controller now, let us create our + act + */ + pNew = CreateEVDriver(argc,argv); + if(!pNew) + { + return NULL; + } + myData = (pCHev)malloc(sizeof(CHev)); + if(!myData) + { + return NULL; + } + + pChop = (pChoco)pCom->pData; + myData->iLastError = 0; + myData->pDriv = pChop->pDriv; + myData->pParName = strdup(argv[1]); + pNew->pPrivate = myData; + pNew->SetValue =AVEVSetValue; + pNew->GetValue =AVEVGetValue; + pNew->Send = AVEVSend; + pNew->GetError =AVEVGetError; + pNew->TryFixIt =AVEVTryFixIt; + pNew->Init =AVEVInit; + pNew->Close =AVEVClose; + pNew->KillPrivate =AVEVKillPrivate; + + return pNew; + } diff --git a/chadapter.h b/chadapter.h index abaaa445..ec3319f8 100644 --- a/chadapter.h +++ b/chadapter.h @@ -40,6 +40,7 @@ typedef struct __CHEV { char *pParName; pCodri pDriv; + int iLastError; }CHev, *pCHev; #endif diff --git a/choco.c b/choco.c index e2064edb..fdf02d52 100644 --- a/choco.c +++ b/choco.c @@ -175,6 +175,7 @@ extern pCodri MakeSimChopper(void); extern pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel); +extern pCodri MakeCookerDriver(char *pHost, int iPort, int iChannel); /*-----------------------------------------------------------------------*/ int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -230,6 +231,33 @@ extern pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel); } pDriv = MakeDoChoDriver(argv[3],iPort,iChannel); } + else if(strcmp(argv[2],"sanscook") == 0) + { + if(argc < 6) + { + SCWrite(pCon, + "ERROR: Insufficient number of arguments to install SANS Cooker driver", + eError); + return 0; + } + iRet = Tcl_GetInt(pSics->pTcl,argv[4],&iPort); + if(iRet != TCL_OK) + { + sprintf(pBueffel,"ERROR: expected integer as port number, got %s", + argv[4]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + iRet = Tcl_GetInt(pSics->pTcl,argv[5],&iChannel); + if(iRet != TCL_OK) + { + sprintf(pBueffel,"ERROR: expected integer as channel number, got %s", + argv[4]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + pDriv = MakeCookerDriver(argv[3],iPort,iChannel); + } else { sprintf(pBueffel,"ERROR: Driver %s NOT supported for MakeController", diff --git a/choco.tex b/choco.tex index 9b543f6e..af1f8bbe 100644 --- a/choco.tex +++ b/choco.tex @@ -270,6 +270,7 @@ $\langle$evada {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ typedef struct __CHEV {@\\ \mbox{}\verb@ char *pParName;@\\ \mbox{}\verb@ pCodri pDriv;@\\ +\mbox{}\verb@ int iLastError;@\\ \mbox{}\verb@ }CHev, *pCHev;@\\ \mbox{}\verb@@$\diamond$ \end{list} diff --git a/choco.w b/choco.w index d61ffaea..10b6be55 100644 --- a/choco.w +++ b/choco.w @@ -92,7 +92,7 @@ the error can be ignored or was fully resolved. \item[pParList] is text string containing a comma separated list of all parameters understood by this driver. \item[pPrivate] Is a pointer to a driver specific specific data -structure. This data structure will not be messed with by upper level code. +structure. This data structure shall not be messed with by upper level code. \end{description} \subsubsection{The Controller Object} @@ -200,6 +200,7 @@ controller driver: typedef struct __CHEV { char *pParName; pCodri pDriv; + int iLastError; }CHev, *pCHev; @} diff --git a/countdriv.c b/countdriv.c index a42a0778..f19527d6 100644 --- a/countdriv.c +++ b/countdriv.c @@ -455,13 +455,24 @@ case EL737__BAD_ILLG: case EL737__BAD_ADR: case EL737__BAD_PAR: - case EL737__BAD_BSY: case EL737__BAD_TMO: case EL737__BAD_REPLY: case EL737__BAD_SNTX: case EL737__BAD_OVFL: return COREDO; break; + case EL737__BAD_BSY: + strcpy(pCommand,"S \r"); + iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49); + if(iRet < 0) + { + return COTERM; + } + else + { + return COREDO; + } + break; case EL737__BAD_LOC: strcpy(pCommand,"rmt 1\r"); iRet = EL737_SendCmnd(&pEL737->pData,pCommand,pReply,49); diff --git a/counter.c b/counter.c index 25e3486b..283dbe29 100644 --- a/counter.c +++ b/counter.c @@ -233,7 +233,15 @@ sMon.fCurrent = fControl; sMon.fPreset = self->pDriv->fPreset; sMon.pName = self->name; - InvokeCallBack(self->pCall,MONITOR,&sMon); + if(self->iCallbackCounter > 20) + { + InvokeCallBack(self->pCall,MONITOR,&sMon); + self->iCallbackCounter = 0; + } + else + { + self->iCallbackCounter++; + } self->pDriv->fLastCurrent = fControl; return eCt; } @@ -357,6 +365,7 @@ pRes->pCountInt->Halt = Halt; pRes->pCountInt->Pause = PauseCount; pRes->pCountInt->Continue = ContinueCount; + pRes->iCallbackCounter = 20; pRes->pCall = CreateCallBackInterface(); diff --git a/counter.h b/counter.h index 06f56923..bdefc49c 100644 --- a/counter.h +++ b/counter.h @@ -22,6 +22,7 @@ pCounterDriver pDriv; pICallBack pCall; unsigned long tStart; + int iCallbackCounter; } Counter, *pCounter; /*----------------------------- birth & death -----------------------------*/ diff --git a/danu.dat b/danu.dat index b399ab11..d338d9b0 100644 --- a/danu.dat +++ b/danu.dat @@ -1,3 +1,3 @@ - 5798 + 5829 NEVER, EVER modify or delete this file You'll risk eternal damnation and a reincarnation as a cockroach!|n \ No newline at end of file diff --git a/drive.c b/drive.c index 7a336df6..c11d8083 100644 --- a/drive.c +++ b/drive.c @@ -358,7 +358,7 @@ /* check the completion status */ if(iRet == DEVERROR) { - sprintf(pBueffel,"Driving finished with problem",argv[0]); + sprintf(pBueffel,"Driving finished with problem"); SCWrite(pCon,pBueffel,eError); ClearExecutor(GetExecutor()); SetStatus(eOld); diff --git a/evcontroller.c b/evcontroller.c index a509bc7e..340253dd 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -61,6 +61,7 @@ #include "eurodriv.h" #include "el755driv.h" #include "tecsdriv.h" +#include "chadapter.h" /*--------------------- Functions needed to implement interfaces -----------*/ static long EVIDrive(void *pData, SConnection *pCon, float fVal) { @@ -1239,7 +1240,8 @@ SCSendOK(pCon); return 1; } - else if(strcmp(argv[3],"ltc11") == 0) /* Neocera LTC-11 temperature controller*/ + else if(strcmp(argv[3],"ltc11") == 0) + /* Neocera LTC-11 temperature controller*/ { /* Create a driver */ pDriv = CreateLTC11Driver(argc-4,&argv[4]); @@ -1340,6 +1342,18 @@ return 0; } } + else if(strcmp(argv[3],"gencon") == 0) /* general controller */ + { + /* Create a driver */ + pDriv = MakeControllerEnvironmentDriver(argc-4,&argv[4]); + if(!pDriv) + { + SCWrite(pCon, + "ERROR: failed to create Controller Environment driver", + eError); + return 0; + } + } else if(strcmp(argv[3],"euro") == 0) /* dillution driver */ { /* Create a driver */ diff --git a/hkl.c b/hkl.c index 2e8dec89..bc525eeb 100644 --- a/hkl.c +++ b/hkl.c @@ -18,6 +18,7 @@ #include "motor.h" #include "selector.h" #include "selvar.h" +#include "matrix/matrix.h" #include "hkl.h" #include "hkl.i" /*-------------------------------------------------------------------------*/ @@ -79,6 +80,7 @@ pNew->fUB[0] = 1.; pNew->fUB[4] = 1.; pNew->fUB[8] = 1.; + pNew->UBinv = NULL; return pNew; } @@ -306,6 +308,7 @@ int SetUB(pHKL self, float fUB[9]) { int i; + MATRIX m; assert(self); @@ -313,6 +316,21 @@ { self->fUB[i] = fUB[i]; } + /* invert UB matrix for use in backwards calculation */ + if(self->UBinv != NULL) + { + mat_free(self->UBinv); + } + m = mat_creat(3,3,ZERO_MATRIX); + for(i = 0; i < 3; i++) + { + m[0][i] = self->fUB[i]; + m[1][i] = self->fUB[3+i]; + m[2][i] = self->fUB[6+i]; + } + self->UBinv = mat_inv(m); + mat_free(m); + return 1; } /*-------------------------------------------------------------------------*/ @@ -1183,6 +1201,42 @@ ente: return iResult; } +/*------------------------------------------------------------------------- + For the conversion from angles to HKL. + -------------------------------------------------------------------------*/ + static int angle2HKL(pHKL self ,double tth, double om, + double chi, double phi, float fHKL[3]) + { + double dTh, dOm, dChi, dPhi, dHM; + MATRIX res, rez; + int i; + + /* conversion to radians */ + dTh = tth/(2*RD); + dOm = (om - tth/2.)/RD; + dChi = chi/RD; + dPhi = phi/RD; + dHM = 2* sin(dTh)/self->fLambda; + + /* angles to XYZ, stolen from DIFRAC code in PRPXYZ */ + res = mat_creat(3,1,ZERO_MATRIX); + res[0][0] = dHM*(cos(dChi)*cos(dPhi)*cos(dOm) - + sin(dPhi)*sin(dOm)); + res[1][0] = dHM*(cos(dChi)*sin(dPhi)*cos(dOm) + + cos(dPhi)*sin(dOm)); + res[2][0] = dHM*sin(dChi)*cos(dOm); + + /* multiply with UBinv in order to yield HKL */ + rez = mat_mul(self->UBinv,res); + for(i = 0; i < 3; i++) + { + fHKL[i] = rez[i][0]; + } + mat_free(res); + mat_free(rez); + + return 1; + } /*--------------------------------------------------------------------------*/ int isNumeric(char *pText) { @@ -1312,10 +1366,28 @@ ente: /*----------- current */ else if(strcmp(argv[1],"current") == 0) { - sprintf(pBueffel,"Last HKL: %8.4f %8.4f %8.4f ", - self->fLastHKL[0], self->fLastHKL[1],self->fLastHKL[2]); - SCWrite(pCon,pBueffel,eValue); - return 1; + if(self->iNOR) + { + sprintf(pBueffel,"Last HKL: %8.4f %8.4f %8.4f ", + self->fLastHKL[0], self->fLastHKL[1],self->fLastHKL[2]); + SCWrite(pCon,pBueffel,eValue); + return 1; + } + else + { + /* do a serious calculation based on angles */ + iRet = GetCurrentPosition(self,pCon,fSet); + if(iRet == 0) + { + return; + } + angle2HKL(self,(double)fSet[0],(double)fSet[1], + (double)fSet[2],(double)fSet[3],fHKL); + sprintf(pBueffel,"Current HKL: %8.4f %8.4f %8.4f ", + fHKL[0], fHKL[1],fHKL[2]); + SCWrite(pCon,pBueffel,eValue); + return 1; + } } /*------------- lambda */ else if(strcmp(argv[1],"lambda") == 0) diff --git a/hkl.i b/hkl.i index 80666e91..56ef03da 100644 --- a/hkl.i +++ b/hkl.i @@ -10,6 +10,7 @@ typedef struct __HKL { pObjectDescriptor pDes; double fUB[9]; + MATRIX UBinv; double fLambda; int iManual; double fLastHKL[5]; diff --git a/hkl.tex b/hkl.tex index 764637d1..f34f82d9 100644 --- a/hkl.tex +++ b/hkl.tex @@ -18,6 +18,7 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ typedef struct __HKL {@\\ \mbox{}\verb@ pObjectDescriptor pDes;@\\ \mbox{}\verb@ double fUB[9];@\\ +\mbox{}\verb@ MATRIX UBinv;@\\ \mbox{}\verb@ double fLambda;@\\ \mbox{}\verb@ int iManual;@\\ \mbox{}\verb@ double fLastHKL[5];@\\ diff --git a/hkl.w b/hkl.w index 3384c8f2..e26baff2 100644 --- a/hkl.w +++ b/hkl.w @@ -13,6 +13,7 @@ The object uses the following object data structure: typedef struct __HKL { pObjectDescriptor pDes; double fUB[9]; + MATRIX UBinv; double fLambda; int iManual; double fLastHKL[5]; diff --git a/hklscan.c b/hklscan.c index 00bd4cb4..34d81c28 100644 --- a/hklscan.c +++ b/hklscan.c @@ -17,6 +17,7 @@ #include "scan.h" #include "hkl.h" #include "scan.i" +#include "matrix/matrix.h" #include "hkl.i" #include "hklscan.i" #include "hklscan.h" diff --git a/matrix/DEMO.DAT b/matrix/DEMO.DAT new file mode 100644 index 00000000..b566d75c --- /dev/null +++ b/matrix/DEMO.DAT @@ -0,0 +1,20 @@ +1.1 2 3 4 5 6 7 8 9 9 +2 3.1 4 5 6 7 8 9 9 8 +3 4 5.1 6 7 8 9 9 8 7 +3 4 5 6.1 7 8 9 9 8 7 +1 2 3 4 5 7.2 7 8 9 9 +1 2 3 4 1 6 7 8.3 9 9 +6 2 3 4 5 6 7 8 9.8 9 +1 2 3 3 5 6 7 8 9 9.8 +1 2 3 4 6 6 7 8 9 9 +6 2 3 4 5 4 7 8 9 9 +3 +1 +4 +1 +2 +3 +1 +1 +2 +6 diff --git a/matrix/DEMO.EXE b/matrix/DEMO.EXE new file mode 100644 index 0000000000000000000000000000000000000000..1dc7e4ca2b78b00763b27ea9012a76f3cd5a724b GIT binary patch literal 33384 zcmeFadt6l2`Ukvb&z?QQ%mAYxUIR2Q6>0`$8X#mib}<}pfH$mj%sL%UrvrP?%5Z2p z%FI@yyJg3dS!QZwCr<~ngTN?wi3BZ0%^RTZaeG0e8AP1@e%IbJfOYzP-hbcE=apt= z?R9z9v!3;==Xut%p0#^?)-z;0i6HUBNn|<9Kn#S~q6mp4glI@EQbVH&$-sw@tL$`U ziGF`?LY_kUulQ8q^D{oFnyc)5e3s$!JwCMd|Nrm*ixik4Tr3?##J#<;vP)&zR%#^5 zNBn_t?&4h5i%O;@n7LieY$_d(j0|EEi({O-SeLael@MO*?L$f*M?ooL6P>i66s#qF z67Af@$OUb3!9}r$j^@rs?pG*hN_k?V*=uR`O6xhBc$j9ptmj-=A}#nS439#6%~*ZS z*xcrt)RoqgHt}C-os+Jt(}MM+kaar2dai$#=(1jx3w&}xt6b0`7c`f?j9wl?Rb%N2 zq#mS=lrHjb?cy!H(qn@HI{WuPw>t|P=m^6}>3e{7trr@3c~bfn9YBM4f~Dj779~e% ziPDehmVRih*XS@^)()ksi?pK4`rA=lDBVwic8J9kC{1L8>Y!kQn5iZ}$|kW&OS}9L zT`r)IN}Fh-CUKgA$t7e@R`vO-#6()bCTdks?WJ0cO&pA>=;?ClLwM+|K3pjM zJ06Vc!$t9sM!}&;+@~hm#4n?eGcQ*-JJ&;b$UwxuM`dLTR<`c6jz#~`ccHwKH9$Bp zk=Tb$sQ1sL+S);g_W>eUxw_Nz&n7nAiK6W+5pvtKM}@48x(4krmtJM8VC!QB+Ij?W zT01o8Xsos4WvzFIj3gSl^!Nfi*F>fiP%_)JdxQ!vAu5U`6i1ebXL@F3%LSZVz={vc z7&WE?UD&nWohbjV0dxBvqC%q&c!Wv}`$5Lx(t7#%MsSTgC*M)bz;8b{4Xf zztu5k{O-tlp?yc)X^LXKe7_iZ2c3|ka%qPwWU|^lQ^cFYkb|kdr4R7NpU?*tC1@!x z3Mk(l;y%=wqCoTj@>BVqMS?3(07nNV>bc0{FQ-1C2PT@jV2~c!yWuyZWr(;x60@_Fv6cQn8?fRGtO4#;98v3& zV6EW#8Ffn~x;{{+2z5|idQb&q{!Jawb}s6uB>nBunfJTHypK398h$;Oom8eX@Uya3 z6zmKlV{z^>gV?2qDJBN7C6X@d*KQ#`#n}k{j|lN5*TtJZ+)#MarwSmIH?RHf>>T

a4gGvjU|ehO83kdU0^OGE*Hi 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 literal 0 HcmV?d00001 diff --git a/matrix/MAKEFILE.MSC b/matrix/MAKEFILE.MSC new file mode 100644 index 00000000..107df78b --- /dev/null +++ b/matrix/MAKEFILE.MSC @@ -0,0 +1,62 @@ +#------------------------------------------------------------------------------ +# file: makefile.msc +# desc: makefile for matrix library package under Microsoft C/C++ v7.0 +# by: patrick ko +# date: 16 Apr 94 +# +# note: a slim matrix library matrix.lib will be generated +#------------------------------------------------------------------------------ + +OBJS = matcreat.obj matdump.obj materr.obj matadd.obj matsub.obj \ +matmul.obj matinv.obj matsolve.obj matdet.obj mattran.obj matdurbn.obj \ +mattoepz.obj matsubx.obj + +CC = cl -c +C = cl + +demo.exe: demo.c matrix.lib + $(C) demo.c matrix.lib + +matrix.lib: $(OBJS) + lib matrix +matcreat +matdump +materr +matadd.obj ,, + lib matrix +matsub +matmul +matinv +matsolve +matdet.obj ,, + lib matrix +mattran +matdurbn +mattoepz +matsubx ,, + +matcreat.obj: matcreat.c matrix.h + $(CC) matcreat.c + +matdump.obj: matdump.c matrix.h + $(CC) matdump.c + +materr.obj: materr.c matrix.h + $(CC) materr.c + +matadd.obj: matadd.c matrix.h + $(CC) matadd.c + +matsub.obj: matsub.c matrix.h + $(CC) matsub.c + +matmul.obj: matmul.c matrix.h + $(CC) matmul.c + +matinv.obj: matinv.c matrix.h + $(CC) matinv.c + +matsolve.obj: matsolve.c matrix.h + $(CC) matsolve.c + +mattran.obj: mattran.c matrix.h + $(CC) mattran.c + +matdet.obj: matdet.c matrix.h + $(CC) matdet.c + +matdurbn.obj: matdurbn.c matrix.h + $(CC) matdurbn.c + +mattoepz.obj: mattoepz.c matrix.h + $(CC) mattoepz.c + +matsubx.obj: matsubx.c matrix.h + $(CC) matsubx.c diff --git a/matrix/MAKEFILE.TC b/matrix/MAKEFILE.TC new file mode 100644 index 00000000..0823ac6b --- /dev/null +++ b/matrix/MAKEFILE.TC @@ -0,0 +1,74 @@ +#------------------------------------------------------------------------------ +# file: makefile.tc +# desc: makefile for matrix library package under Turbo C v2.0 +# by: patrick ko +# date: 16 Apr 94 +# +# note: a slim matrix library matrix.lib will be generated +#------------------------------------------------------------------------------ +DRIVE = C: + +OBJS = matcreat.obj matdump.obj materr.obj matadd.obj matsub.obj \ +matmul.obj matinv.obj matsolve.obj matdet.obj mattran.obj matdurbn.obj \ +mattoepz.obj matsubx.obj + +LIB = -L$(DRIVE)\TC\LIB +INC = -I$(DRIVE)\TC\INCLUDE +CC = tcc -c -mh $(INC) +C = tcc -mh $(LIB) $(INC) +LL = tlib matrix.lib + +demo.exe: demo.c $(OBJS) + $(C) demo.c matrix.lib + +matcreat.obj: matcreat.c matrix.h + $(CC) matcreat.c + $(LL) -+matcreat.obj + +matdump.obj: matdump.c matrix.h + $(CC) matdump.c + $(LL) -+matdump.obj + +materr.obj: materr.c matrix.h + $(CC) materr.c + $(LL) -+materr.obj + +matadd.obj: matadd.c matrix.h + $(CC) matadd.c + $(LL) -+matadd.obj + +matsub.obj: matsub.c matrix.h + $(CC) matsub.c + $(LL) -+matsub.obj + +matmul.obj: matmul.c matrix.h + $(CC) matmul.c + $(LL) -+matmul.obj + +matinv.obj: matinv.c matrix.h + $(CC) matinv.c + $(LL) -+matinv.obj + +matsolve.obj: matsolve.c matrix.h + $(CC) matsolve.c + $(LL) -+matsolve.obj + +mattran.obj: mattran.c matrix.h + $(CC) mattran.c + $(LL) -+mattran.obj + +matdet.obj: matdet.c matrix.h + $(CC) matdet.c + $(LL) -+matdet.obj + +matdurbn.obj: matdurbn.c matrix.h + $(CC) matdurbn.c + $(LL) -+matdurbn.obj + +mattoepz.obj: mattoepz.c matrix.h + $(CC) mattoepz.c + $(LL) -+mattoepz.obj + +matsubx.obj: matsubx.c matrix.h + $(CC) matsubx.c + $(LL) -+matsubx.obj diff --git a/matrix/MAKEFILE.UX b/matrix/MAKEFILE.UX new file mode 100644 index 00000000..a5f58ce5 --- /dev/null +++ b/matrix/MAKEFILE.UX @@ -0,0 +1,54 @@ +#------------------------------------------------------------------------------ +# file: makefile.ux +# desc: makefile for matrix library package under Unix +# by: patrick ko +# date: 16 Apr 94 +#------------------------------------------------------------------------------ +OBJS = matcreat.o matdump.o materr.o matadd.o matsub.o \ +matmul.o matinv.o matsolve.o mattran.o matdet.o mattoepz.o matdurbn.o + +CC = cc -c +C = cc +CO = -lm -g + +demo: demo.c $(OBJS) + $(C) demo.c -o demo $(OBJS) $(CO) + +matcreat.o: matcreat.c matrix.h + $(CC) matcreat.c + +matdump.o: matdump.c matrix.h + $(CC) matdump.c + +materr.o: materr.c matrix.h + $(CC) materr.c + +matadd.o: matadd.c matrix.h + $(CC) matadd.c + +matsub.o: matsub.c matrix.h + $(CC) matsub.c + +matmul.o: matmul.c matrix.h + $(CC) matmul.c + +matinv.o: matinv.c matrix.h + $(CC) matinv.c + +matsolve.o: matsolve.c matrix.h + $(CC) matsolve.c + +mattran.o: mattran.c matrix.h + $(CC) mattran.c + +matdet.o: matdet.c matrix.h + $(CC) matdet.c + +mattoepz.o: mattoepz.c matrix.h + $(CC) mattoepz.c + +matdurbn.o: matdurbn.c matrix.h + $(CC) matdurbn.c + +matsubx.o: matsubx.c matrix.h + $(CC) matsubx.c diff --git a/matrix/MATRIX.DOC b/matrix/MATRIX.DOC new file mode 100644 index 00000000..edaf9f48 --- /dev/null +++ b/matrix/MATRIX.DOC @@ -0,0 +1,482 @@ +/* +*----------------------------------------------------------------------------- +* file: matrix.doc +* desc: document for matrix toolbox function calls +* by: KO shu pui, patrick +* date: 24 may 92 v0.4 +* 23 sep 93 v0.41 +* 16 apr 94 v0.42 +*----------------------------------------------------------------------------- +*/ + +=============================================================================== +0. INTRODUCTION +=============================================================================== +This document only provides you the following information: + + 0.1 How to create and free a matrix + 0.2 Description of each matrix function call + 0.3 Some hints to use this toolbox + +Remember that this document will NOT describe the data structure and +any technical details of the toolbox - just because this document is +aimed at to be a sort-of "User's Guide" for programmers. + + + + +=============================================================================== +1. OUR MATRIX OF REFERENCE +=============================================================================== +In order to avoid terms confusion, here is our matrix of reference +(matrix A) which is of size m x n. + + Column + Row 0 1 2 n-1 + 0 [ a0,0 a0,1 a0,2 ... a0,n-1 ] + A = 1 [ a1,0 a1,1 a1,2 ... a1,n-1 ] + 2 [ a2,0 a2,1 a2,2 ... a2,n-1 ] + [ ... ... ... ... ... ] + m-1 [ am-1,0 am-1,1 am-1,2 ... am-1,n-1 ] + + + +=============================================================================== +2. BASIC MATRIX OBJECT OPERATION +=============================================================================== +------------------------------------------------------------------------------- +Function : MATRIX mat_creat (int m, int n, int type) +Synopsis : creation of a matrix which can be used by the matrix toolbox + functions; memory is allocated for this object; and some + initialization is performed. +Parameter: m: number of rows + n: number of columns + type: matrix initialization type where + + type= + + UNDEFINED do not initialize the matrix + ZERO_MATRIX fill zero to all matrix elements + UNIT_MATRIX fill a one to all matrix element ai,j + where i=j + +Return Value: the matrix object +Example: + + MATRIX A; + + /* + * create a 15 x 15 matrix; + * do not initialize the elements + */ + A = mat_creat( 15, 15, UNDEFINED); + + /* + * put a 4 in element A(0,14) of matrix A, + * put a 2 in element A(3,5) of matrix A + */ + A[0][14] = 4.0; + A[3][5] = 2.0; + +See Also: mat_free(), for Accessing a matrix, see this example. +------------------------------------------------------------------------------- +Function: MATRIX mat_fill ( MATRIX A, int type ) +Synopsis: initialize a matrix will a simple type +Parameter: A: the matrix object for which mat_creat() has been called + type: matrix initialization type where + + type= + + UNDEFINED do not initialize the matrix + ZERO_MATRIX fill zero to all matrix elements + UNIT_MATRIX fill a one to all matrix element ai,j + where i=j +Return Value: MATRIX A +Example: + + MATRIX A; + + ... + /* + * fill the matrix A will zeroes + */ + mat_fill( A, ZERO_MATRIX ); + +See Also: mat_creat() +------------------------------------------------------------------------------- +Function : int mat_free ( MATRIX A ) +Synopsis : free all memory occupied by the matrix object A +Parameter: A: the matrix object for which mat_creat() was called +Return Value: None +Example: + + MATRIX A; + + A = mat_creat(...); + ... + mat_free(A); + +Note: since memory may be a very scarce resource in a computer, + as a C programmer you are advised to free up the matrix as + soon as that matrix will not be used any more in future. + +See Also: mat_creat() +------------------------------------------------------------------------------- +Function: MatCol ( A ) +Synopsis: find out the number of columns of a matrix object A +Parameter: A: the matrix object for which mat_creat() was called +Return Value: number of columns +Example: + int i; + + ... + i = MatCol(A); + +Note: this is a macro +See Also: MatRow() +------------------------------------------------------------------------------- +Function: MatRow ( A ) +Synopsis: find out the number of rows of a matrix object A +Parameter: A: the matrix object for which mat_creat() was called +Return Value: number of rows +Example: + int i; + + ... + i = MatRow(A); + +Note: this is a macro +See Also: MatCol() + +------------------------------------------------------------------------------- +Function: MATRIX mat_colcopy1 ( MATRIX A, MATRIX B, int j1, int j2 ) +Synopsis: copy a column from a matrix A to a column at matrix B +Parameter: A, B: the matrix objects for which mat_creat() was called + column j1 of A is copied to column j2 of B; +Return Value: MATRIX A +Example: + MATRIX A, B; + + A = mat_creat( 5, 4, ZERO_MATRIX ); + B = mat_creat( 5, 4, UNDEFINED ); + + /* + * copy column 2 of A to column 0 of B + */ + mat_colcopy1( A, 2, B, 0 ); + +Note: the sizes of rows of A, B must be the same +See Also: mat_copy() +------------------------------------------------------------------------------- +Function: MATRIX mat_copy ( MATRIX A ) +Synopsis: duplicate a matrix +Parameter: A: the matrix object for which mat_creat() was called +Return Value: Another allocated matrix object whose contents are same + as A +Example: + MATRIX A, B; + + A = mat_creat( 5, 4, ZERO_MATRIX ); + + /* + * B is also a 5 x 4 zero matrix now + */ + B = mat_copy( A ); + ... + mat_free( B ); + +See Also: mat_colcopy1() +------------------------------------------------------------------------------- + + + + +=============================================================================== +3. BASIC MATRIX OBJECT INPUT/OUTPUT OPERATION +=============================================================================== +------------------------------------------------------------------------------- +Function: int fgetmat (MATRIX A, FILE * fp) +Synopsis: read a matrix from stream +Parameter: A: allocated matrix + fp: a stream pointer obtained from fopen() or predefined + pointer in standard library such as stdin +Return Value: number of matrix elements read +Example: + MATRIX A; + FILE *fp; + + A = mat_creat(3, 3, UNDEFINED); + fp = fopen("mymatrix.dat", "r"); + fgetmat( A, fp ); + +See Also: mat_dumpf(), mat_dump(), mat_fdump(), mat_fdumpf() +------------------------------------------------------------------------------- +Function: MATRIX mat_dump (MATRIX A) + MATRIX mat_dumpf (MATRIX A, char * format) + MATRIX mat_fdump (MATRIX A, FILE * fp) + MATRIX mat_fdumpf (MATRIX A, char * format, FILE * fp) + +Synopsis: mat_dump: dump a matrix to std output with default format + mat_dumpf: dump a matrix to std output with specified format + mat_fdump: dump a matrix to a file with default format + mat_fdumpf:dump a matrix to a file with specified format + +Parameter: A: allocated matrix + format: same as printf() 's format parameter, but can only + be floating point type, such as "%.2f ", etc. + fp: file pointer obtained via fopen() + +Return Value: matrix A + +Example: + MATRIX A; + + A = mat_creat( ... ); + ... + /* + * dump the matrix to standard output and each element + * is restricted to 2 precision format + */ + mat_dumpf( A, "%.2f "); + +See Also: fgetmat() +------------------------------------------------------------------------------- + + + + +=============================================================================== +4. BASIC MATRIX OBJECT MATHEMATICAL OPERATION +=============================================================================== +------------------------------------------------------------------------------- +Function: MATRIX mat_add (MATRIX A, MATRIX B); + MATRIX mat_sub (MATRIX A, MATRIX B); +Synopsis: mat_add: addition of 2 matrices + mat_sub: substraction of 2 matrices +Parameter: A, B: allocated matrices +Return Value: a newly allocated matrix which is the result of the operation +Example: + + MATRIX A, B, C; + + A = mat_creat( 5, 5, UNIT_MATRIX ); + B = mat_creat( 5, 5, UNIT_MATRIX ); + + C = mat_add( A, B ); + + mat_dump( C ); + + mat_free( A ); + mat_free( B ); + mat_free( C ); + +Note: A, B must be of the same dimensions +See Also: mat_mul, mat_inv +------------------------------------------------------------------------------- +Function: MATRIX mat_mul (MATRIX A, MATRIX B); +Synopsis: multiplication of 2 matrices +Parameter: A, B: allocated matrix +Return Value: a newly allocated matrix which is the result of the operation +Example: + MATRIX A, B, C; + + A = mat_creat( 5, 3, UNIT_MATRIX ); + B = mat_creat( 3, 6, UNIT_MATRIX ); + + /* + * C is now a 5 x 6 matrix + */ + C = mat_add( A, B ); + + mat_dump( C ); + ... + +Note: the column dimension of A must equal row dimension of B +See Also: mat_add, mat_sub +------------------------------------------------------------------------------- +Function: MATRIX mat_inv (MATRIX A) +Synopsis: find the inverse of a matrix +Parameter: A: allocated square matrix +Return Value: a newly allocated square matrix which is the inverse of A +Example: + MATRIX A, AI; + + /* + * A must be a square matrix + */ + A = mat_creat( 7, 7, UNIT_MATRIX ); + ... + /* + * find the inverse of A + */ + AI = mat_inv( A ); + ... + +See Also: mat_tran, mat_add, mat_sub +------------------------------------------------------------------------------- +Function: MATRIX mat_tran( MATRIX A ) +Synopsis: find the transpose of a matrix +Parameter: A: allocated matrix +Return Value: a newly allocated matrix which is the transpose of A +Example: + MATRIX A, T; + + A = mat_creat( 3, 5, UNDEFINED ); + ... + T = mat_tran( A ); + ... + +See Also: mat_inv +------------------------------------------------------------------------------- + + + + +=============================================================================== +5. DETERMINANT OPERATIONS +=============================================================================== +------------------------------------------------------------------------------- +Function: MATRIX mat_submat (MATRIX A, int i, int j) +Synopsis: form a new matrix by deleting a row and a column of A +Parameter: A: allocated matrix + i, j: row and column of A which will not appear in the + resulting matrix +Return Value: a new matrix whose dimensions are 1 less than A +Example: + MATRIX A, B + + A = mat_creat( 3, 4, UNDEFINED ); + ... + B = mat_submat( A, 2, 2 ); + /* + * suppose A = [ 1 2 3 4 ] + * [ 3 3 4 5 ] + * [ 6 7 9 9 ] + * + * then B = [ 1 2 4 ] + * [ 3 3 5 ] + */ + +Note: Do not be misled -- the contents in A will NOT be changed +See Also: mat_det, mat_cofact, mat_minor +------------------------------------------------------------------------------- +Function: double mat_cofact (MATRIX A, int i, int j) +Synopsis: find out the cofactor of A(i,j) +Parameter: A: allocated square matrix + i,j: row, column position of A for the cofactor +Return Value: the value of cofactor of A(i,j) +Example: + MATRIX A; + + A = mat_creat( 5, 5, UNIT_MATRIX ); + ... + printf( "cofactor of A(0,2) = %f\n", mat_cofact( A, 0, 2 )); + +See Also: mat_det, mat_minor +------------------------------------------------------------------------------- +Function: double mat_minor (MATRIX A, int i, int j) +Synopsis: find out the minor of A(i,j) +Parameter: A: allocated square matrix + i,j: row, column position of A for the minor +Return Value: the value of minor of A(i,j) +Example: + MATRIX A; + + A = mat_creat( 5, 5, UNIT_MATRIX ); + ... + printf( "minor of A(0,2) = %f\n", mat_minor( A, 0, 2 )); + +See Also: mat_det, mat_cofact +------------------------------------------------------------------------------- +Function: double mat_det (MATRIX A) +Synopsis: find the determinant of a matrix +Parameter: A: allocated square matrix +Return Value: the determinant value of |A| +Example: + MATRIX A; + double det; + + A = mat_creat( 5, 5, UNIT_MATRIX ); + det = mat_det( A ); + +See Also: mat_cofact, mat_minor, mat_submat +------------------------------------------------------------------------------- + + + + +=============================================================================== +6. ADVANCED MATRIX OBJECT MATHEMATICAL OPERATION +=============================================================================== +------------------------------------------------------------------------------- +Function: MATRIX mat_lsolve (MATRIX A, MATRIX B) +Synopsis: solve simultaneous linear equation AX = B given A, B +Parameter: A, B: allocated matrix +Return Value: newly allocated matrix X in AX = B +Example: + MATRIX A, B, X; + + A = mat_creat( 5, 5, UNDEFINED ); + fgetmat( A, stdin ); + ... + B = mat_creat( 5, 1, UNDEFINED ); + fgetmat( B, stdin ); + ... + X = mat_lsolve( A, B ); + mat_dump( X ); + +Note: number of rows in A and B must be equal +See Also: mat_lsolve_durbin +------------------------------------------------------------------------------- +Function: MATRIX mat_lsolve_durbin (MATRIX A, MATRIX B) +Synopsis: simultaneous linear equations wtih Levinson-Durbin method +Parameter: A, B: allocated matrix where A is an autocorrelated matrix and + B is derived from A + + A, B must be the following forms: + + | a0 a1 a2 .. an-1 | | x1 | | a1 | + | a1 a0 a1 .. an-2 | | x2 | | a2 | + | a2 a1 a0 .. an-3 | | x3 | = | .. | + | ... | | .. | | .. | + | an-1 an-2 .. .. a0 | | xn | | an | + + where A is a symmetric Toeplitz matrix and B + in the above format (related to A) + +Return Value: a newly allocated matrix X which is the solution of AX = B + +Example: this method only applies to certain A, B only. + e.g. + + A = [1 3 9] B = [3] + [3 1 3] [9] + [9 3 1] [12] <- the last one is unrelated to A + +See Also: mat_SymToeplz +------------------------------------------------------------------------------- +Function: MATRIX mat_SymToeplz (MATRIX R); +Synopsis: create a symmetric Toeplitz matrix from a + Autocorrelation vector +Parameter: R: allocated matrix of dimension n x 1 +Return Value: a newly allocated symmetrical Toeplitz matrix +Example: + e.g. + + MATRIX A, R; + + R = mat_creat( 3, 1, UNDEFINED ); + ... + A = mat_SymToeplz( R ); + + /* + * if + * + * R = [1 3 9] A = [1 3 9] + * [3 1 3] + * [9 3 1] + * + */ + +See Also: mat_lsolve_durbin +------------------------------------------------------------------------------- diff --git a/matrix/READ.ME b/matrix/READ.ME new file mode 100644 index 00000000..89521113 --- /dev/null +++ b/matrix/READ.ME @@ -0,0 +1,112 @@ +------------------------------------------------------------------------------- + Small Matrix Toolbox for C programmers + version 0.42 + (Support Unix and DOS) + + by Patrick KO Shu-pui + + Copyright (c) 1992, 1993, 1994 All Rights Reserved. +------------------------------------------------------------------------------- +ADDRESS TO CONTACT: + + fidonet: 6:700/132 BiG Programming Club + [852] 663-0223 19.2 kbps + [852] 663-0236 16.8 kbps + + internet: pko@hk.super.net + + mailing: Patrick Ko + G.P.O. Box 7468 + Hong Kong +------------------------------------------------------------------------------- +MATRX042.ZIP contains + +READ .ME - this file +DEMO .C - demo how to use this package +DEMO .DAT - demo data +DEMO .EXE - demo executable for DOS +MAKEFILE.MSC - makefile for Microsoft C/C++ 7.0 on DOS +MAKEFILE.TC - makefile for Turbo C 2.0 on DOS +MAKEFILE.UX - makefile for Unix +MATRIX .DOC - matrix toolbox interface document +MATRIX .H - matrix header file (must include it) +MATADD .C - matrix addition +MATCREAT.C - matrix creation +MATDET .C - find minor, cofactor, determinant +MATDUMP .C - matrix dump +MATERR .C - matrix error handling routine +MATINV .C - matrix inversion +MATMUL .C - matrix multiplication +MATSOLVE.C - linear equations solver +MATSUB .C - matrix substraction +MATSUBX .C - submatrix operation +MATTOEPZ.C - create symmetric Toeplitz matrix +MATDURBN.C - Symmetrix Toeplitz matrix fast solving algorithm +MATTRAN .C - matrix transpose + +------------------------------------------------------------------------------- +WHATS NEW in v0.1: + - +, -, *, inverse matrix operations + +WHATS NEW in v0.2: + - Linear equation solver + - C-programmer-friendly C sources + +WHATS NEW in v0.3: + - better data structure (more Object-Oriented) + - finding minors, cofactors, determinants + - Levinson-Durbin algorithm for symmetric Toeplitz matrix + +WHATS NEW in v0.4: + - Revised method for minors, cofactors and determinants + whose time complexity is T(n^3) instead of nearly T(n!). + This is important when you want to find the determinant + of a matrix whose size is over 10 x 10. + - submatrix operator + - matrix formmated dump function + - brief matrix toolbox interface document included + +WHATS NEW in v0.41: + - bug fix for unit matrix creation + +WHATS NEW in v0.42: + - support Microsoft C/C++ 7.0 + +HOW TO COMPILE: + + 1. All Unix environment - make -f makefile.ux + 2. DOS (Turbo C v2.0) - make -fmakefile.tc + 3. DOS (Microsoft C/C++ v7.0) - nmake -fmakefile.msc + +REFERENCES + + [1] Mary L.Boas, "Mathematical Methods in the Physical Sciene," + John Wiley & Sons, 2nd Ed., 1983. Chap 3. + + [2] Kendall E.Atkinson, "An Introduction to Numberical Analysis," + John Wiley & Sons, 1978. + + [3] Shuzo Saito, Kazuo Nakata, "Fundamentals of Speech Signal + Processing," Academic Press, 1985. + + [4] Alfred V.Aho, John E.Hopcroft, Jeffrey D.Ullman, "The Design + and Analysis of Computer Algorithms," 1974. + +AUTHOR +All the sources are written by Patrick KO Shu Pui +BiG Programming Club (6:700/132, fidonet) + +=============================================================================== +AUTHORIZATION NOTICE + +This C source package MATRX042.ZIP is FREE for ACADEMIC purpose only. + +For COMMERCIAL use, authorization is required from the author. +Please send US$25 for registration. +=============================================================================== +DISCLAIMER (I hate this but I have to do that) + +You are on your own risk - the author is not responsible for any lost due +to the use of this toolbox. +=============================================================================== + diff --git a/matrix/demo.c b/matrix/demo.c new file mode 100644 index 00000000..8658ce01 --- /dev/null +++ b/matrix/demo.c @@ -0,0 +1,92 @@ +/* +*----------------------------------------------------------------------------- +* file: demo.c +* desc: demostrate how to use Patrick's matrix toolbox +* by: ko shu pui, patrick +* date: 24 nov 91 v0.1 +* revi: 14 may 92 v0.2 +* 24 may 92 v0.4 +* ref: +* [1] Mary L.Boas, "Mathematical Methods in the Physical Sciene," +* John Wiley & Sons, 2nd Ed., 1983. Chap 3. +* +* [2] Kendall E.Atkinson, "An Introduction to Numberical Analysis," +* John Wiley & Sons, 1978. +* +* [3] Alfred V.Aho, John E.Hopcroft, Jeffrey D.Ullman, "The Design +* and Analysis of Computer Algorithms," 1974. +* +*----------------------------------------------------------------------------- +*/ +#include +#include +#include "matrix.h" + +int main() +{ + MATRIX A, B, X, M; + FILE *fp; + double result; + time_t t1, t2; + int tinv, tdet, tmul; + + A = mat_creat( 10, 10, UNDEFINED ); + B = mat_creat( 10, 1, UNDEFINED ); + + if ((fp = fopen( "demo.dat", "r" )) == NULL) + { + fprintf( stderr, "file cannot be opened\n" ); + exit (0); + } + + fgetmat( A, fp ); + printf( "|- Matrix A -|\n"); + mat_dumpf( A, "%+06.1f " ); + + t1 = time(&t1); + result = mat_det(A); + t2 = time(&t2); + tdet = t2 - t1; + printf( "\n\nDet(A) = %f\n", result ); + + printf( "|- Inv A -|\n"); + t1 = time(&t1); + X = mat_inv( A ); + t2 = time(&t2); + tinv = t2 - t1; + + if (X == NULL) + printf( "A is a singular matrix\n" ); + else + { + mat_dumpf(X, "%+06.1f "); + + printf( "|- A x Inv A -|\n"); + t1 = time(&t1); + M = mat_mul( X, A ); + t2 = time(&t2); + tmul = t2 - t1; + mat_dumpf( M, "%+06.1f " ); + + mat_free(M); + mat_free(X); + } + + fgetmat( B, fp ); + printf( "|- Matrix B -|\n"); + mat_dumpf( B, "%+06.1f " ); + + printf( "|- A x B -|\n"); + mat_free(mat_dumpf(mat_mul(A, B), "%+06.1f ")); + + printf( "time for finding 10 x 10 matrix inversion is less than %d secs\n", tinv ); + printf( "time for finding 10 x 10 matrix determinant is less than %d secs\n", tdet ); + printf( "time for finding 10 x 10 matrix multiplication is less than %d secs\n", tmul ); + + mat_free( A ); + mat_free( B ); + + fclose(fp); + +} + \ No newline at end of file diff --git a/matrix/matadd.c b/matrix/matadd.c new file mode 100644 index 00000000..ff1e9bf9 --- /dev/null +++ b/matrix/matadd.c @@ -0,0 +1,43 @@ +/* +*----------------------------------------------------------------------------- +* file: matadd.c +* desc: matrix addition +* by: ko shu pui, patrick +* date: 24 nov 91 v0.1 +* revi: +* ref: +* [1] Mary L.Boas, "Mathematical Methods in the Physical Sciene," +* John Wiley & Sons, 2nd Ed., 1983. Chap 3. +* +*----------------------------------------------------------------------------- +*/ +#include +#include "matrix.h" + +/* +*----------------------------------------------------------------------------- +* funct: mat_add +* desct: addition of two matrice +* given: A, B = Compatible matrice to be added +* retrn: NULL if malloc() fails +* else allocated matrix of A + B +* comen: +*----------------------------------------------------------------------------- +*/ +MATRIX mat_add( A, B ) +MATRIX A, B; +{ + int i, j; + MATRIX C; + + if ((C = mat_creat( MatRow(A), MatCol(A), UNDEFINED )) == NULL) + return (NULL); + + for (i=0; i + +#ifdef __TURBOC__ +#include +#else +#include +#endif + +#include "matrix.h" + +MATRIX _mat_creat( row, col ) +int row, col; +{ + MATBODY *mat; + int i, j; + + if ((mat = (MATBODY *)malloc( sizeof(MATHEAD) + sizeof(double *) * row)) == NULL) + return (mat_error( MAT_MALLOC )); + + for (i=0; imatrix) + i) = (double *)malloc(sizeof(double) * col)) == NULL) + return (mat_error( MAT_MALLOC )); + } + + mat->head.row = row; + mat->head.col = col; + + return (&(mat->matrix)); +} + +/* +*----------------------------------------------------------------------------- +* funct: mat_creat +* desct: create a matrix +* given: row, col = dimension, type = which kind of matrix +* retrn: allocated matrix (use mat_free() to free memory) +*----------------------------------------------------------------------------- +*/ +MATRIX mat_creat( row, col, type ) +int row, col, type; +{ + MATRIX A; + + if ((A =_mat_creat( row, col )) != NULL) + { + return (mat_fill(A, type)); + } + else + return (NULL); +} + +/* +*----------------------------------------------------------------------------- +* funct: mat_fill +* desct: form a special matrix +* given: A = matrix, type = which kind of matrix +* retrn: A +*----------------------------------------------------------------------------- +*/ +MATRIX mat_fill( A, type ) +MATRIX A; +int type; +{ + int i, j; + + switch (type) + { + case UNDEFINED: + break; + case ZERO_MATRIX: + case UNIT_MATRIX: + for (i=0; i +*----------------------------------------------------------------------------- +*/ +int mat_free( A ) +MATRIX A; +{ + int i; + + if (A == NULL) + return (0); + for (i=0; i +#include "matrix.h" + +static double signa[2] = {1.0, -1.0}; + +/* +*----------------------------------------------------------------------------- +* funct: mat_minor +* desct: find minor +* given: A = a square matrix, +* i=row, j=col +* retrn: the minor of Aij +*----------------------------------------------------------------------------- +*/ +double mat_minor( A, i, j ) +MATRIX A; +int i, j; +{ + MATRIX S; + double result; + + S = mat_submat(A, i, j); + result = mat_det( S ); + mat_free(S); + + return (result); + +} + +/* +*----------------------------------------------------------------------------- +* funct: mat_cofact +* desct: find cofactor +* given: A = a square matrix, +* i=row, j=col +* retrn: the cofactor of Aij +*----------------------------------------------------------------------------- +*/ +double mat_cofact( A, i, j ) +MATRIX A; +int i, j; +{ + double result; + + result = signa[(i+j)%2] * A[i][j] * mat_minor(A, i, j); + + return (result); +} + +/* +*----------------------------------------------------------------------------- +* funct: mat_det +* desct: find determinant +* given: A = matrix +* retrn: the determinant of A +* comen: +*----------------------------------------------------------------------------- +*/ +double mat_det( a ) +MATRIX a; +{ + MATRIX A, P; + int i, j, n; + double result; + + n = MatRow(a); + A = mat_copy(a); + P = mat_creat(n, 1, UNDEFINED); + + /* + * take a LUP-decomposition + */ + i = mat_lu(A, P); + switch (i) + { + /* + * case for singular matrix + */ + case -1: + result = 0.0; + break; + + /* + * normal case: |A| = |L||U||P| + * |L| = 1, + * |U| = multiplication of the diagonal + * |P| = +-1 + */ + default: + result = 1.0; + for (j=0; j +#include "matrix.h" + +/* +*----------------------------------------------------------------------------- +* funct: mat_dump +* desct: dump a matrix +* given: A = matrice to dumped +* retrn: nothing +* comen: matrix a dumped to standard output +*----------------------------------------------------------------------------- +*/ +MATRIX mat_dump( A ) +MATRIX A; +{ + return(mat_fdumpf(A, "%f ", stdout)); +} + +/* +*----------------------------------------------------------------------------- +* funct: mat_dumpf +* desct: dump a matrix with format string to standard output +* given: A = matrice to dumped +* retrn: nothing +* comen: matrix a dumped to standard output +*----------------------------------------------------------------------------- +*/ +MATRIX mat_dumpf( A, s ) +MATRIX A; +char *s; +{ + return (mat_fdumpf(A, s, stdout)); +} + +MATRIX mat_fdump( A, fp ) +MATRIX A; +FILE *fp; +{ + return (mat_fdumpf(A, "%f ", fp)); +} + +MATRIX mat_fdumpf( A, s, fp ) +MATRIX A; +char *s; +FILE *fp; +{ + int i, j; + + for (i=0; i + +#include "matrix.h" + +/* +*----------------------------------------------------------------------------- +* funct: mat_durbin +* desct: Levinson-Durbin algorithm +* +* This function solve the linear eqns Ax = B: +* +* | v0 v1 v2 .. vn-1 | | a1 | | v1 | +* | v1 v0 v1 .. vn-2 | | a2 | | v2 | +* | v2 v1 v0 .. vn-3 | | a3 | = | .. | +* | ... | | .. | | .. | +* | vn-1 vn-2 .. .. v0 | | an | | vn | +* +* where A is a symmetric Toeplitz matrix and B +* in the above format (related to A) +* +* given: R = autocorrelated matrix (v0, v1, ... vn) (dim (n+1) x 1) +* retrn: x (of Ax = B) +*----------------------------------------------------------------------------- +*/ +MATRIX mat_durbin( R ) +MATRIX R; +{ + int i, i1, j, ji, p, n; + MATRIX W, E, K, A, X; + + p = MatRow(R) - 1; + W = mat_creat( p+2, 1, UNDEFINED ); + E = mat_creat( p+2, 1, UNDEFINED ); + K = mat_creat( p+2, 1, UNDEFINED ); + A = mat_creat( p+2, p+2, UNDEFINED ); + + W[0][0] = R[1][0]; + E[0][0] = R[0][0]; + + for (i=1; i<=p; i++) + { + K[i][0] = W[i-1][0] / E[i-1][0]; + E[i][0] = E[i-1][0] * (1.0 - K[i][0] * K[i][0]); + + A[i][i] = -K[i][0]; + + i1 = i-1; + if (i1 >= 1) + { + for (j=1; j<=i1; j++) + { + ji = i - j; + A[j][i] = A[j][i1] - K[i][0] * A[ji][i1]; + } + } + + if (i != p) + { + W[i][0] = R[i+1][0]; + for (j=1; j<=i; j++) + W[i][0] += A[j][i] * R[i-j+1][0]; + } + } + + X = mat_creat( p, 1, UNDEFINED ); + for (i=0; i + +#ifdef __TURBOC__ +#include +#else +#include +#endif + +#include "matrix.h" + +MATRIX mat_error( errno ) +int errno; +{ + switch( errno ) + { + case MAT_MALLOC: + fprintf(stderr, "mat: malloc error\n" ); + break; + case MAT_FNOTOPEN: + fprintf(stderr, "mat: fileopen error\n" ); + break; + case MAT_FNOTGETMAT: + fprintf(stderr, "fgetmat: matrix read error\n"); + break; + } + + return (NULL); +} + + \ No newline at end of file diff --git a/matrix/matinv.c b/matrix/matinv.c new file mode 100644 index 00000000..1c134e01 --- /dev/null +++ b/matrix/matinv.c @@ -0,0 +1,77 @@ +/* +*----------------------------------------------------------------------------- +* file: matinv.c +* desc: matrix inversion +* by: ko shu pui, patrick +* date: 24 nov 91 v0.1 +* revi: 14 may 92 v0.2 +* ref: +* [1] Mary L.Boas, "Mathematical Methods in the Physical Sciene," +* John Wiley & Sons, 2nd Ed., 1983. Chap 3. +* +* [2] Kendall E.Atkinson, "An Introduction to Numberical Analysis," +* John Wiley & Sons, 1978. +* +*----------------------------------------------------------------------------- +*/ +#include +#include + +#ifdef __TURBOC__ +#include +#else +#include +#endif + +#include "matrix.h" + + +/* +*----------------------------------------------------------------------------- +* funct: mat_inv +* desct: find inverse of a matrix +* given: a = square matrix a +* retrn: square matrix Inverse(A) +* NULL = fails, singular matrix, or malloc() fails +*----------------------------------------------------------------------------- +*/ +MATRIX mat_inv( a ) +MATRIX a; +{ + MATRIX A, B, C, P; + int i, j, n; + double temp; + + n = MatCol(a); + A = mat_copy(a); + B = mat_creat( n, 1, UNDEFINED ); + C = mat_creat( n, n, UNDEFINED ); + P = mat_creat( n, 1, UNDEFINED ); + + /* + * - LU-decomposition - + * also check for singular matrix + */ + if (mat_lu(A, P) == -1) + { + mat_free(A); + mat_free(B); + mat_free(C); + mat_free(P); + + return (NULL); + } + + for (i=0; i +#include "matrix.h" + +/* +*----------------------------------------------------------------------------- +* funct: mat_mul +* desct: multiplication of two matrice +* given: A, B = compatible matrice to be multiplied +* retrn: NULL if malloc() fails +* else allocated matrix of A * B +* comen: +*----------------------------------------------------------------------------- +*/ +MATRIX mat_mul( A, B ) +MATRIX A, B; +{ + int i, j, k; + MATRIX C; + + if ((C = mat_creat( MatRow(A), MatCol(B), UNDEFINED )) == NULL) + return (NULL); + + for (i=0; irow) +#define MatCol(a) (Mathead(a)->col) + +/* +*---------------------------------------------------------------------------- +* mat_errors definitions +*---------------------------------------------------------------------------- +*/ +#define MAT_MALLOC 1 +#define MAT_FNOTOPEN 2 +#define MAT_FNOTGETMAT 3 + +/* +*---------------------------------------------------------------------------- +* matrice types +*---------------------------------------------------------------------------- +*/ +#define UNDEFINED -1 +#define ZERO_MATRIX 0 +#define UNIT_MATRIX 1 + + +/* prototypes of matrix package */ +#ifndef NOPROTO + +MATRIX mat_error (int); +MATRIX _mat_creat (int, int); +MATRIX mat_creat (int, int, int); +MATRIX mat_fill (MATRIX, int); +int mat_free (MATRIX); +MATRIX mat_copy (MATRIX); +MATRIX mat_colcopy1 (MATRIX, MATRIX, int, int); +int fgetmat (MATRIX, FILE *); +MATRIX mat_dump (MATRIX); +MATRIX mat_dumpf (MATRIX, char *); +MATRIX mat_fdump (MATRIX, FILE *); +MATRIX mat_fdumpf (MATRIX, char *, FILE *); + +MATRIX mat_add (MATRIX, MATRIX); +MATRIX mat_sub (MATRIX, MATRIX); +MATRIX mat_mul (MATRIX, MATRIX); +double mat_diagmul (MATRIX); +MATRIX mat_tran (MATRIX); +MATRIX mat_inv (MATRIX); +MATRIX mat_SymToeplz (MATRIX); + +int mat_lu (MATRIX, MATRIX); +MATRIX mat_backsubs1 (MATRIX, MATRIX, MATRIX, MATRIX, int); +MATRIX mat_lsolve (MATRIX, MATRIX); + +MATRIX mat_submat (MATRIX, int, int); +double mat_cofact (MATRIX, int, int); +double mat_det (MATRIX); +double mat_minor (MATRIX, int, int); + +MATRIX mat_durbin (MATRIX); +MATRIX mat_lsolve_durbin(MATRIX, MATRIX); +#else + +MATRIX mat_error (); +MATRIX _mat_creat (); +MATRIX mat_creat (); +MATRIX mat_fill (); +int mat_free (); +MATRIX mat_copy (); +MATRIX mat_colcopy1 (); +int fgetmat (); +MATRIX mat_dumpf (); +MATRIX mat_dump (); +MATRIX mat_fdump (); +MATRIX mat_fdumpf (); + +MATRIX mat_add (); +MATRIX mat_sub (); +MATRIX mat_mul (); +double mat_diagmul (); +MATRIX mat_tran (); +MATRIX mat_inv (); +MATRIX mat_SymToeplz (); + +int mat_lu (); +MATRIX mat_backsubs1 (); +MATRIX mat_lsolve (); + +MATRIX mat_submat (); +double mat_cofact (); +double mat_det (); +double mat_minor (); + +MATRIX mat_durbin (); +MATRIX mat_lsolve_durbin(); +#endif + +#endif + + + + diff --git a/matrix/matsolve.c b/matrix/matsolve.c new file mode 100644 index 00000000..9a2f61e8 --- /dev/null +++ b/matrix/matsolve.c @@ -0,0 +1,182 @@ +/* +*----------------------------------------------------------------------------- +* file: matsolve.c +* desc: solve linear equations +* by: ko shu pui, patrick +* date: 24 nov 91 v0.1 +* revi: 14 may 92 v0.2 +* ref: +* [1] Mary L.Boas, "Mathematical Methods in the Physical Sciene," +* John Wiley & Sons, 2nd Ed., 1983. Chap 3. +* +* [2] Kendall E.Atkinson, "An Introduction to Numberical Analysis," +* John Wiley & Sons, 1978. +* +*----------------------------------------------------------------------------- +*/ +#include +#include + +#ifdef __TURBOC__ +#include +#else +#include +#endif + +#include "matrix.h" + +/* +*----------------------------------------------------------------------------- +* funct: mat_lu +* desct: in-place LU decomposition with partial pivoting +* given: !! A = square matrix (n x n) !ATTENTION! see commen +* P = permutation vector (n x 1) +* retrn: number of permutation performed +* -1 means suspected singular matrix +* comen: A will be overwritten to be a LU-composite matrix +* +* note: the LU decomposed may NOT be equal to the LU of +* the orignal matrix a. But equal to the LU of the +* rows interchanged matrix. +*----------------------------------------------------------------------------- +*/ +int mat_lu( A, P ) +MATRIX A; +MATRIX P; +{ + int i, j, k, n; + int maxi, tmp; + double c, c1; + int p; + + n = MatCol(A); + + for (p=0,i=0; i c) + { + c = c1; + maxi = i; + } + } + + /* + * row exchange, update permutation vector + */ + if (k != maxi) + { + p++; + tmp = P[k][0]; + P[k][0] = P[maxi][0]; + P[maxi][0] = tmp; + } + + /* + * suspected singular matrix + */ + if ( A[(int)P[k][0]][k] == 0.0 ) + return (-1); + + for (i=k+1; i=0; k--) + { + sum = 0.0; + for (j=k+1; j +#include "matrix.h" + +/* +*----------------------------------------------------------------------------- +* funct: mat_sub +* desct: subtraction of two matrice +* given: A, B = compatible matrice to be added +* retrn: NULL if malloc() fails +* else allocated matrix of A - B +* comen: +*----------------------------------------------------------------------------- +*/ +MATRIX mat_sub( A, B ) +MATRIX A, B; +{ + int i, j; + MATRIX C; + + if ((C = mat_creat( MatRow(A), MatCol(A), UNDEFINED )) == NULL) + return (NULL); + + for (i=0; i +#include "matrix.h" + +/* +*----------------------------------------------------------------------------- +* funct: mat_submat +* desct: return a submatrix S of A +* given: A = main matrix, +* i,j = row and column of A to be deleted to obtained S +* retrn: S +*----------------------------------------------------------------------------- +*/ +MATRIX mat_submat( A, i, j ) +MATRIX A; +int i,j; +{ + int m, m1, p, p1; + MATRIX S; + + S = mat_creat(MatRow(A)-1, MatCol(A)-1, UNDEFINED); + + for (m=m1=0; m + +#include "matrix.h" + +/* +*----------------------------------------------------------------------------- +* funct: mat_SymToeplz +* desct: create a n x n symmetric Toeplitz matrix from +* a n x 1 correlation matrix +* given: R = correlation matrix (n x 1) +* retrn: the symmetric Toeplitz matrix +*----------------------------------------------------------------------------- +*/ +MATRIX mat_SymToeplz( R ) +MATRIX R; +{ + int i, j, n; + MATRIX T; + + n = MatRow(R); + T = mat_creat(n, n, UNDEFINED); + + for (i=0; i +#include "matrix.h" + +/* +*----------------------------------------------------------------------------- +* funct: mat_tran +* desct: transpose of a matrix +* given: A = matrix A to be transposed +* retrn: allocated matrix for A^t +* comen: +*----------------------------------------------------------------------------- +*/ +MATRIX mat_tran( A ) +MATRIX A; +{ + int i, j; + MATRIX At; + + if ((At = mat_creat( MatCol(A), MatRow(A), UNDEFINED )) == NULL) + return (NULL); + + /* + * Transposing ... + */ + for (i=0; i +#include +#include +#include "fortify.h" +#include "sics.h" +#include "stringdict.h" +#include "hardsup/serialsinq.h" +#include "hardsup/el734_errcodes.h" +#include "hardsup/el734fix.h" +#include "codri.h" + +/*----------------------------------------------------------------------- + A private data structure for the SANS cooker +-------------------------------------------------------------------------*/ + typedef struct { + char *pHost; + int iPort; + int iChannel; + void *pData; + int iStop; + int iError; + } SANSCook, *pSANSCook; +/* + pHost, iPort and iChannel combined are the adress of the cooker + controller at the Macintosh terminal server. pData is the serial + port connection data structure needed and managed by the SerialIO + functions. + + iError is the last error reported on this device. If no error: 0 + +-----------------------------------------------------------------------*/ + +/* + ERROR CODES: +*/ + +#define NOTINIT -9001 +#define POWEROFF -9002 +#define LOWRANGE -9003 +#define HIGHRANGE -9004 +#define CONTIMEOUT -9005 +#define BADCOMMAND -9006 +#define NOANSWER -9007 +#define BADINPUT -9008 +#define MOTERROR -9009 +#define CONBUSY -9010 +#define BADREPLY -9011 + +/*-------------------------------------------------------------------------*/ + static int CookerInit(pCodri self) + { + pSANSCook pPriv = NULL; + int iRet; + char pReply[131]; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + pPriv->iError = 0; + + /* first open the connection to the serial port server and channel */ + iRet = SerialOpen(&(pPriv->pData),pPriv->pHost,pPriv->iPort, + pPriv->iChannel); + if(iRet <= 0) + { + pPriv->iError = iRet; + return 0; + } + /* configure the connection */ + SerialATerm(&(pPriv->pData),"1\r\n"); + SerialSendTerm(&(pPriv->pData),"\r"); + + pPriv->iStop = 0; + + /* switch everything on, but do not deal with errors here */ + /* + SerialWriteRead(&(pPriv->pData),"mpon",pReply,131); + SerialWriteRead(&(pPriv->pData),"mzon",pReply,131); + SerialWriteRead(&(pPriv->pData),"ton",pReply,131); + */ + + return 1; + } +/*------------------------------------------------------------------------*/ + static int CookerClose(pCodri self) + { + pSANSCook pPriv = NULL; + int iRet; + long lVal; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + + if(pPriv->pData) + { + SerialClose(&(pPriv->pData)); + pPriv->pData = NULL; + } + return 1; + } +/*-----------------------------------------------------------------------*/ + static int CookerDelete(pCodri self) + { + pSANSCook pPriv = NULL; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + + if(pPriv->pData) + { + SerialClose(&(pPriv->pData)); + pPriv->pData = NULL; + } + + if(pPriv->pHost) + free(pPriv->pHost); + + free(pPriv); + + return 1; + } +/*-----------------------------------------------------------------------*/ + static int CookerSetPar(pCodri self, char *parname, float fValue) + { + pSANSCook pPriv = NULL; + char pCommand[80], pReply[132]; + int iRet, iValue; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + pPriv->iError = 0; + + /* handle the numeric parameters */ + iValue = (int)fValue; + + if(strcmp(parname,"mp") == 0) + { + sprintf(pCommand,"mps%3.3d",iValue); + } + else if(strcmp(parname,"mz") == 0) + { + sprintf(pCommand,"mzs%3.3d",iValue); + } + else if(strcmp(parname,"ts") == 0) + { + sprintf(pCommand,"ts%3.3d",iValue); + } + else + { + pPriv->iError = BADINPUT; + return 0; + } + /* send command and check for errors right here */ + iRet = SerialWriteRead(&(pPriv->pData),pCommand,pReply,131); + if(iRet != 1) + { + pPriv->iError = iRet; + return 0; + } + else + { + if(strstr(pReply,"Error") != NULL) + { + pPriv->iError = MOTERROR; + return 0; + } + if(strstr(pReply,"Power OFF") != NULL) + { + pPriv->iError = POWEROFF; + return 0; + } + if(strstr(pReply,"not init.") != NULL) + { + pPriv->iError = NOTINIT ; + return 0; + } + if(strstr(pReply,"Timeout") != NULL) + { + pPriv->iError = CONTIMEOUT ; + return 0; + } + if(strstr(pReply,"Busy") != NULL) + { + pPriv->iError = CONBUSY ; + return 0; + } + if( (strstr(pReply,"Max") != NULL) || (strstr(pReply,"high") != NULL) ) + { + pPriv->iError = HIGHRANGE; + return 0; + } + if( (strstr(pReply,"Min") != NULL) || (strstr(pReply,"down") != NULL) ) + { + pPriv->iError = LOWRANGE; + return 0; + } + return 1; + } + + + } +/*------------------------------------------------------------------------*/ + static int CookerSetPar2(pCodri self, char *parname, char *pValue) + { + pSANSCook pPriv = NULL; + char pCommand[80], pReply[132]; + int iRet, iAct = 0; + float fValue; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + pPriv->iError = 0; + + /* handle our parameters. The first set is the power settings */ + if(strcmp(parname,"mp.power") == 0) + { + if(strstr(pValue,"on") != NULL) + { + strcpy(pCommand,"mpon"); + iAct = 1; + } + else if(strstr(pValue,"off") != NULL) + { + strcpy(pCommand,"mpoff"); + iAct = 1; + } + else + { + pPriv->iError = BADINPUT; + return 0; + } + } + else if(strcmp(parname,"mz.power") == 0) + { + if(strstr(pValue,"on") != NULL) + { + strcpy(pCommand,"mzon"); + iAct = 1; + } + else if(strstr(pValue,"off") != NULL) + { + strcpy(pCommand,"mzoff"); + iAct = 1; + } + else + { + pPriv->iError = BADINPUT; + return 0; + } + } + else if(strcmp(parname,"ts.power") == 0) + { + if(strstr(pValue,"on") != NULL) + { + iAct = 1; + strcpy(pCommand,"ton"); + } + else if(strstr(pValue,"off") != NULL) + { + iAct = 1; + strcpy(pCommand,"toff"); + } + else + { + pPriv->iError = BADINPUT; + return 0; + } + } + if(iAct == 1) + { + /* send command and check for errors right here */ + iRet = SerialWriteRead(&(pPriv->pData),pCommand,pReply,131); + if(iRet != 1) + { + pPriv->iError = iRet; + return 0; + } + else + { + if(strstr(pReply,"Error") != NULL) + { + pPriv->iError = MOTERROR; + return 0; + } + return 1; + } + } + + + /* second set: init */ + if(strcmp(parname,"mp.init") == 0) + { + strcpy(pCommand,"mpi"); + iAct = 1; + } + else if(strcmp(parname,"mz.init") == 0) + { + strcpy(pCommand,"mzi"); + iAct = 1; + } + if(iAct) + { + /* send command and check for errors right here */ + iRet = SerialWriteRead(&(pPriv->pData),pCommand,pReply,131); + if(iRet != 1) + { + pPriv->iError = iRet; + return 0; + } + else + { + if(strstr(pReply,"Error") != NULL) + { + pPriv->iError = MOTERROR; + return 0; + } + return 1; + } + } + + /* + what is left here is either the para's themselves which will be + handled in the second function after convertion to float or an + error + */ + iRet = sscanf(pValue,"%f",&fValue); + if(iRet != 1) + { + pPriv->iError = BADINPUT; + return; + } + + return CookerSetPar(self,parname,fValue); + } +/*-----------------------------------------------------------------------*/ + static int CookerHalt(pCodri self) + { + pSANSCook pPriv = NULL; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + pPriv->iError = 0; + + /* no commands are defined to halt a thing! */ + return 1; + } +/*----------------------------------------------------------------------*/ +extern char *stptok(const char *s, char *tok, size_t toklen, char *brk); + + static int CookerGetPar(pCodri self, char *parname, + char *pBuffer, int iLen) + { + pSANSCook pPriv = NULL; + char pBueffel[256], pCommand[80], pReply[80]; + float fVal; + char *pPtr; + int iAct = 0, iRet; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + pPriv->iError = 0; + + /* first the power stuff */ + if(strcmp(parname,"mp.power") == 0 || strcmp(parname,"mp.init") == 0) + { + strcpy(pBueffel,parname); + strcpy(pCommand,"mps"); + iAct = 1; + } + else if(strcmp(parname,"mz.power") == 0 || strcmp(parname,"mz.init") ==0 ) + { + strcpy(pBueffel,parname); + strcpy(pCommand,"mzs"); + iAct = 1; + } + else if(strcmp(parname,"ts.power") == 0) + { + strcpy(pBueffel,parname); + strcpy(pCommand,"ts"); + iAct = 1; + } + if(iAct) + { + iRet = SerialWriteRead(&(pPriv->pData),pCommand,pReply,80); + if(iRet != 1) + { + pPriv->iError = iRet; + return 0; + } + else + { + if( strstr(pReply,"OFF") != NULL || strstr(pReply,"Off") != NULL) + { + strcat(pBueffel," off"); + } + else if(strstr(pReply,"not init") != NULL) + { + strcat(pBueffel," not"); + } + else + { + strcat(pBueffel," on"); + } + + } + strncpy(pBuffer,pBueffel,iLen); + return 1; + } + + /* now request values for the parameter */ + if(strcmp(parname,"mp") == 0) + { + strcpy(pCommand,"mps"); + } + else if(strcmp(parname,"mz") == 0) + { + strcpy(pCommand,"mzs"); + } + else if(strcmp(parname,"ts") == 0) + { + strcpy(pCommand,"ts"); + } + else + { + pPriv->iError = BADINPUT; + return 0; + } + iRet = SerialWriteRead(&(pPriv->pData),pCommand,pReply,80); + if(iRet != 1) + { + pPriv->iError = iRet; + return 0; + } + /* decode value */ + pPtr = pReply; + pPtr = stptok(pPtr,pBueffel,255,"/\0"); + pPtr = stptok(pPtr,pBueffel,255,"/\0"); + iRet = sscanf(pBueffel,"%f",&fVal); + if(iRet != 1) + { + pPriv->iError = BADREPLY; + return 0; + } + sprintf(pBueffel,"%f",fVal); + strncpy(pBuffer,pBueffel,iLen); + return 1; + } +/*-----------------------------------------------------------------------*/ + static int CookerCheckPar(pCodri self, char *parname) + { + pSANSCook pPriv = NULL; + char pCommand[80], pReply[80]; + int iRet; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + + if(strcmp(parname,"mp") == 0) + { + strcpy(pCommand,"mps"); + } + else if(strcmp(parname,"mz")) + { + strcpy(pCommand,"mzs"); + } + else + { + pPriv->iError = BADINPUT; + return 0; + } + + /* get a status reply */ + iRet = SerialWriteRead(&(pPriv->pData),pCommand,pReply,80); + if(iRet != 1) + { + pPriv->iError = iRet; + return HWFault; + } + + if( strstr(pReply,"Start") != NULL || strstr(pReply,"Move") != NULL ) + { + return HWBusy; + } + else + { + return HWIdle; + } + return HWIdle; + } +/*---------------------------------------------------------------------*/ + static int CookerError(pCodri self, int *iCode, char *pError, int iLen) + { + pSANSCook pPriv = NULL; + char pCommand[80], pReply[80]; + int iRet; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + + *iCode = pPriv->iError; + switch(pPriv->iError) + { + case NOTINIT: + strncpy(pError,"ERROR: NOT Initialized!",iLen); + break; + case POWEROFF: + strncpy(pError,"ERROR: Power is OFF",iLen); + break; + case LOWRANGE: + strncpy(pError,"ERROR: Lower limit violated",iLen); + break; + case HIGHRANGE: + strncpy(pError,"ERROR: Upper limit violated",iLen); + break; + case CONTIMEOUT: + strncpy(pError,"ERROR: Internal controller timeout ",iLen); + break; + case BADCOMMAND: + strncpy(pError,"ERROR: Controller did not understand command",iLen); + break; + case BADINPUT: + strncpy(pError,"A bad parameter was entered",iLen); + break; + case MOTERROR: + strncpy(pError,"ERROR: Iternal motor error in controller",iLen); + break; + case CONBUSY: + strncpy(pError,"ERROR: Controller is busy",iLen); + break; + default: + SerialError(pPriv->iError,pError,iLen); + break; + } + pPriv->iError = 0; + return 1; + } +/*----------------------------------------------------------------------*/ + static int CookerFix(pCodri self, int iCode) + { + pSANSCook pPriv = NULL; + int iRet; + + assert(self); + pPriv = (pSANSCook)self->pPrivate; + assert(pPriv); + + switch(iCode) + { + case NOTINIT: + case POWEROFF: + case LOWRANGE: + case HIGHRANGE: + case BADCOMMAND: + case BADINPUT: + case MOTERROR: + return CHFAIL; + case CONTIMEOUT: + case CONBUSY: + return CHREDO; + /* network errors */ + case EL734__BAD_FLUSH: + case EL734__BAD_RECV: + case EL734__BAD_RECV_NET: + case EL734__BAD_RECV_UNKN: + case EL734__BAD_RECVLEN: + case EL734__BAD_RECV1: + case EL734__BAD_RECV1_PIPE: + case EL734__BAD_RNG: + case EL734__BAD_SEND: + case EL734__BAD_SEND_PIPE: + case EL734__BAD_SEND_NET: + case EL734__BAD_SEND_UNKN: + case EL734__BAD_SENDLEN: + case NOCONNECTION: + SerialForceClose(&(pPriv->pData)); + pPriv->pData = NULL; + iRet = SerialOpen(&(pPriv->pData),pPriv->pHost, + pPriv->iPort,pPriv->iChannel); + if(iRet == 1 ) + { + return CHREDO; + } + else + { + return CHFAIL; + } + break; + case EL734__FORCED_CLOSED: + iRet = CookerInit(self); + if(iRet) + { + return CHREDO; + } + else + { + return CHFAIL; + } + break; + default: + return CHFAIL; + break; + + } + } +/*------------------------------------------------------------------------*/ + pCodri MakeCookerDriver(char *pHost, int iPort, int iChannel) + { + pCodri pNew = NULL; + pSANSCook pPriv = NULL; + char *pText; + + /* allocate memory */ + pText = (char *)malloc(1024*sizeof(char)); + pNew = (pCodri)malloc(sizeof(Codri)); + pPriv = (pSANSCook)malloc(sizeof(SANSCook)); + if( !pText || !pNew || !pPriv) + { + return NULL; + } + memset(pText,0,1024); + memset(pNew,0,sizeof(Codri)); + memset(pPriv,0,sizeof(SANSCook)); + + /* initialize private data structure */ + pPriv->pHost = strdup(pHost); + pPriv->iPort = iPort; + pPriv->iChannel = iChannel; + pPriv->pData = NULL; + + /* set known parameter names */ + strcpy(pText,"mp"); + strcat(pText,",mp.power"); + strcat(pText,",mp.init"); + strcat(pText,",mz"); + strcat(pText,",mz.power"); + strcat(pText,",mz.init"); + strcat(pText,",ts"); + strcat(pText,",ts.power"); + + + /* install codri */ + pNew->Init = CookerInit; + pNew->Close = CookerClose; + pNew->Delete = CookerDelete; + pNew->SetPar = CookerSetPar; + pNew->SetPar2 = CookerSetPar2; + pNew->GetPar = CookerGetPar; + pNew->CheckPar = CookerCheckPar; + pNew->GetError = CookerError; + pNew->TryFixIt = CookerFix; + pNew->Halt = CookerHalt; + pNew->pParList = pText; + pNew->pPrivate = pPriv; + + return pNew; + } + + + + + diff --git a/sicsstatus.tcl b/sicsstatus.tcl index 2a13e85b..4267fa8f 100644 --- a/sicsstatus.tcl +++ b/sicsstatus.tcl @@ -22,8 +22,8 @@ th sign 1.000000 th InterruptMode 0.000000 th AccessCode 2.000000 #Crystallographic Settings -hkl lambda 0.703790 -hkl setub -0.124702 0.001618 -0.041357 -0.104448 -0.001326 0.049388 0.000751 0.084094 0.001574 +hkl lambda 1.179000 +hkl setub -0.019370 0.077484 -0.004944 0.077493 0.019386 0.002155 0.001034 -0.001344 -0.254040 det1dist 300. det1dist setAccess 1 det1zeroy 128. @@ -401,5 +401,5 @@ sample shit at 10.000000 sample setAccess 2 title TopsiTupsiTapsi title setAccess 2 -starttime 2000-06-29 15:01:07 +starttime 2000-06-29 15:01:07 starttime setAccess 2 diff --git a/stptok.c b/stptok.c index 508016be..7000e83b 100644 --- a/stptok.c +++ b/stptok.c @@ -28,7 +28,7 @@ char *stptok(const char *s, char *tok, size_t toklen, char *brk) if ( *s == *b ) { *tok = 0; - return (char *)s; + return (char *)(s+1); } } *tok++ = *s++; @@ -52,4 +52,13 @@ char *stptok(const char *s, char *tok, size_t toklen, char *brk) } return NULL; } - \ No newline at end of file + + + + + + + + + + diff --git a/test.tcl b/test.tcl index d6f49304..9e347bb1 100644 --- a/test.tcl +++ b/test.tcl @@ -355,15 +355,21 @@ MakeFocusAverager average hm FocusInstall hm focus.dic $shome/sics/focusmerge.dat #MakeChopper choco docho lnsp20 4000 8 -#MakeChopper choco sim +MakeChopper choco sim #ChopperAdapter fermispeed choco chopper1.nspee 0 20000 #ChopperAdapter diskspeed choco chopper2.nspee 0 20000 #ChopperAdapter phase choco chopper2.nphas 0 90. #ChopperAdapter ratio choco chopper2.ratio 0 6. -#ChopperAdapter diskspeed choco speed 0 20000 -#ChopperAdapter phase choco phase 0 90. -#ChopperAdapter ratio choco ratio 0 6. +ChopperAdapter diskspeed choco speed 0 20000 +ChopperAdapter phase choco phase 0 90. +ChopperAdapter ratio choco ratio 0 6. +#-------- SANS Cooker +MakeChopper cooker sanscook lnsa10 4000 11 +ChopperAdapter cookp cooker mp 0 400 +ChopperAdapter cookz cooker mz 0 400 + + source chosta.tcl Publish chosta Spy