📄 matvec.cpp
字号:
// $mat\matvec.cpp 1.5 milbo$// Warning: this is raw research code -- expect it to be quite messy.//// This originally used C arrays and was ported to use STL vectors//// milbo dec05 durban#include <stdio.h>#include <float.h>#include "mcommon.hpp"#include "mat.hpp"#include "matview.hpp"using namespace GslMat;#include "mchol.hpp"#include "mathutil.hpp"#include "matvec.hpp"#include "regex.h"#include "util.hpp"#include "err.hpp"#include "memstate.hpp"#include "mfile.hpp"//-----------------------------------------------------------------------------// If fClear is false the contents of the matrices will be unspecifiedvoid AllocMatVec (MatVec &MatV, size_t nMats, size_t nrows, size_t ncols, bool fClear){MatV.resize(0); // get rid of old matrices if necessaryMatV.resize(nMats, Mat(nrows, ncols, fClear)); // resize to what we want}//-----------------------------------------------------------------------------// Return true if CompiledRegExp matches the stringstatic bool fRegExpMatch (regex_t &CompiledRegExp, const char s[]){regmatch_t pmatch[1];return 0 == regexec(&CompiledRegExp, s, 0, pmatch, 0);}//-----------------------------------------------------------------------------// Like Mat::sread but only reads the matrix tagstatic char *sReadMatTag (const char *sFile, FILE *pFile, char sTag[], bool fVerbose, bool fExitOnErr){static char sErr[256];if (sTag) sTag[0] = 0;bool fCloseFile = false;ASSERT(!(pFile && !sFile)); // must give a file name for error reporting if pFile is givenif (pFile == NULL) { DASSERT(sFile); pFile = fopen(sFile, "r"); if (!pFile) if (fExitOnErr) Err("Can't open %s", sFile); else return "Can't open file"; fCloseFile = true; }if (!sFile) // make sure we have something to print for user messages sFile = "file";if (fVerbose) lprintf("Read %s ", sFile);// search for first delimiter '{', collecting lines prefixed by "char sLine[SLEN];do { if (NULL == fgets(sLine, SLEN-1, pFile)) { sprintf(sErr, "Can't read matrix header from %s (no '{')", sFile); if (fExitOnErr) Err(sErr); else { if (fCloseFile) fclose(pFile); return sErr; } } if (sLine[0] == '"') // tag? { char *pDest = strchr(&sLine[1], '"'); // there may or may not be a terminating ", be lenient int iLen = strlen(sLine)-1; if (pDest) { iLen--; *pDest = 0; } else sLine[iLen] = 0; strcpy(sTag, &sLine[1]); } }while (sLine[0] != '{');if (fCloseFile) fclose(pFile);return NULL; // success}//-----------------------------------------------------------------------------// Read a vector of matrices from a file.//// On Return// ---------//// *pMatV is the vector of matrices.// If passed in pMatV is NULL then we don;t actually ready and matrices.//// If pStringV is not null then the matrix tag strings will be copied// into the corresponding slot in pStringV. A matrix tag string is// an optional string (without the backquote ` char) in quotes before// the opening brace { of the matrix.// If there is no tag string, then that slot in pStringV is set to "".//// Parameters// ----------//// If pFile is NULL then it is opened. If pFile is already open then we read// from it (and sFile isn't used except for user messages).//// nWantedMats 0 means read ALL that match sTagRegExp, n means read up to n.// We may read less than n because we only load matrices whose header matches sTagRegExp//// If fCheckSameDim is true, we check that each matrix has the same dimension.//// fVerboseAtVecLev and fVerboseAtMatLev control printing.//// Matrix vector file format://// # Optional comments prefixed by #// Matrices one after each other, in standard format (see Mat::write function header)//// Actually comments can appear anywhere except within the { and } of a matrix.// The starting character # must always be in the FIRST COLUMN.void ReadMatVec (MatVec *pMatV, StringVec *pStringV, // out const char *sFile, FILE *pFile, // in const char *sTagRegExp, // in: only read matrices whose tag strings match this regular expression (default is null) unsigned Mask1, unsigned Mask2, // in: only read matrices where Attr&Mask1 == Mask2 (Attr is hex part of tag string) int nWantedMats, // in: 0 means read all, n means read up to n matrices bool fCheckSameDim, bool fVerboseAtVecLev, bool fVerboseAtMatLev) // in{#define MAX_VEC 5000 // somewhat arbitrary upper limit, try not to use too much temporary memory// regcomp flags: egrep style expression (supports |), ignore case, use simple failure reporting in regexecregex_t CompiledRegExp;if (sTagRegExp) { if (strchr(sTagRegExp, '~')) // this is a mistake I sometimes make: confusing ^ and ~ because I use ~ in filenames to stand in for ^ { static bool fWarned = false; if (!fWarned) { //TODO Warn("'~' in regular expression, is that intentional?"); Err("'~' in regular expression, is that intentional?"); fWarned = true; } } if (0 != regcomp(&CompiledRegExp, sTagRegExp, REG_EXTENDED|REG_ICASE|REG_NOSUB)) Err("Invalid regular expression %s", sTagRegExp); }bool fCloseFile = false;if (pFile == NULL) { DASSERT(sFile); pFile = Fopen(sFile, "r") ; fCloseFile = true; }if (!sFile) // make sure we have something to print in user messages sFile = "file";if (fVerboseAtVecLev || fVerboseAtMatLev) lprintf("Read %s ", sFile);if (pMatV) pMatV->clear(); // erase what's currently in MatVif (pStringV) pStringV->clear(); // erase what's currently in StringV// read the actual matricesif (fVerboseAtVecLev || fVerboseAtMatLev) lprintf("\nsTagRegExp %s Mask1 %x Mask2 %x\n", (sTagRegExp? sTagRegExp: "none"), Mask1, Mask2);int iMat = 0; // index of matrices accepted so far (nMat is index of ALL matrices read so far)while (nWantedMats == 0 || iMat < nWantedMats) { if (fVerboseAtVecLev) lprintf("%d: ", iMat); char sTag[SLEN]; Mat TempMat; if (pMatV) { bool fGetTag = (pStringV || sTagRegExp || Mask1 || Mask2); if (TempMat.sread(sFile, pFile, (fGetTag? sTag: NULL), fVerboseAtMatLev, NO_EXIT_ON_ERR)) { // sread returned an error string if (nWantedMats == 0) break; // succesful completion else SysErr("Could read only %d of %d matrices", iMat, nWantedMats); } if (fCheckSameDim) CheckSameDim(TempMat, (*pMatV)[0], sFile); if (fVerboseAtVecLev) { lprintf("%dx%d ", TempMat.nrows(), TempMat.ncols()); if (fGetTag) lprintf("%s ", sTag); } } else if (pStringV) { if (sReadMatTag(sFile, pFile, sTag, fVerboseAtMatLev, NO_EXIT_ON_ERR)) { // sReadMatTag returned an error string if (nWantedMats == 0) break; // succesful completion else SysErr("Could read only %d of %d matrix strings", iMat, nWantedMats); } } else SysErr("ReadMatVec neither pMatV nor pStringV"); bool fKeep = true; if (sTagRegExp) { // match matrix tag string against regular expression to decide if we want to keep the matrix if (fVerboseAtVecLev && sTag[0]) lprintf("%s ", sTag); if (!fRegExpMatch(CompiledRegExp, sTag)) { fKeep = false; // unsuccessful match if (fVerboseAtVecLev) lprintf("discarded sTagRegExp=%s", sTagRegExp); } } if (fKeep && (Mask1 || Mask2)) { // match attribute in matrix tag string against Mask1 and Mask2 to decide if we want to keep the matrix unsigned Attr; if (1 != sscanf(sTag, "%x", &Attr)) SysErr("Can't convert first part of tag %s to a hex number", sTag); if ((Attr & Mask1) != Mask2) { fKeep = false; // unsuccessful match if (fVerboseAtVecLev) lprintf("discarded Mask1&Attr=%x Mask2=%x ", (Attr & Mask1), Mask2); } } if (fKeep) { if (fVerboseAtVecLev) lprintf("keep "); if (pMatV) pMatV->push_back(TempMat); if (pStringV) pStringV->push_back(sTag); iMat++; } DASSERT(iMat < CONF_nMaxMatVec); if (fVerboseAtVecLev) lprintf("\n"); }if (fVerboseAtVecLev) lprintf("%d of %d matrices used\n", iMat, (nWantedMats == 0? iMat: nWantedMats));if (fCloseFile) fclose(pFile);if (sTagRegExp && sTagRegExp[0]) regfree(&CompiledRegExp);}//-----------------------------------------------------------------------------// Read one matrix embedded in a matrix vector file, given its index.// If sTag is not null and we copy the string associated with the vector to sTag too.// We use a brute force method for now. Read them all, pick one, throw them all away.void ReadSelectedMat (Mat &M, char sTag[], // out const char sMatFile[], FILE *pMatFile, int iWantedMat, // in bool fCheckSameDim, bool fVerbose, bool fPrintAssociatedString) // in{MatVec MatV;StringVec StringV; // tag strings preceding each matrix in fileif (fVerbose) lprintf("Reading %s", sMatFile);ReadMatVec(&MatV, &StringV, sMatFile, pMatFile, NULL, 0, 0, 0, fCheckSameDim, fVerbose, fVerbose);if (iWantedMat < 0 || iWantedMat >= MatV.size()) SysErr("ReadSelectedMat: %s iWantedMat %d out of range", sMatFile, iWantedMat);M = MatV[iWantedMat];if (StringV[iWantedMat][0]) strcpy(sTag, StringV[iWantedMat].c_str());else sTag[0] = 0;if (fVerbose) { lprintf(", extracted matrix %d", iWantedMat, sTag); if (fPrintAssociatedString) lprintf(": %s", sTag); lprintf("\n"); }}//-----------------------------------------------------------------------------typedef struct IndexTabStruct { char s[FLEN+1]; long iPos; }IndexTabStruct;static IndexTabStruct gIndexTab[CONF_nMaxMatVec];//-----------------------------------------------------------------------------// Auxilary function for qsortstatic int __cdecl CompareTab (const void *pArg1, const void *pArg2){char *s1 = ((IndexTabStruct *)pArg1)->s;char *s2 = ((IndexTabStruct *)pArg2)->s;int diff = strcmp(s1, s2);if (diff < 0) return -1;else if (diff > 0) return 1;else return 0;}//-----------------------------------------------------------------------------// If sIndexFile is null, we create an index file name from sMatFilevoid BuildMatIndexFile (const char sMatFile[], const char *sIndexFile, bool fVerbose){char sIndexFile1[SLEN];if (sIndexFile) strcpy(sIndexFile1, sIndexFile);else { char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sFname[_MAX_FNAME], sExt[_MAX_EXT]; _splitpath(sMatFile, sDrive, sDir, sFname, sExt); _makepath(sIndexFile1, sDrive, sDir, sFname, ".index"); }if (fVerbose) lprintf("Building %s from %s\n", sIndexFile1, sMatFile);FILE *pFile = Fopen(sMatFile, "r");long iPos = 0;int iMat = 0;char sLine[SLEN];bool fLastLineIsTag = false;while (fgets(sLine, SLEN-1, pFile)) { if (sLine[0] == '"') { int iLen = strlen(sLine); if (iLen >= FLEN) SysErr("BuildMatIndexFile %s is too long, max is %d", sLine, FLEN); if (iLen > 0) // remove terminating \n sLine[--iLen] = 0; if (iLen > 0 && sLine[iLen-1] == '"') // remove possible terminating quote sLine[--iLen] = 0; if (sLine[0] != 0) // ignore null tags { if (fLastLineIsTag) iMat--; // consecutive tags: last tag overwrites previous tag(s) strcpy(gIndexTab[iMat].s, sLine + 1); gIndexTab[iMat].iPos = iPos; if (++iMat >= CONF_nMaxMatVec) SysErr("Too many matrices in %s, max allowed is %d", sMatFile, CONF_nMaxMatVec); } fLastLineIsTag = true; } else fLastLineIsTag = false; iPos = ftell(pFile); }fclose(pFile);qsort((void *)gIndexTab, (size_t)iMat, sizeof(gIndexTab[0]), CompareTab);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -