From 9815096db22c73cacdbb65512d1b61d633db7fa8 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Mon, 2 Dec 2002 19:21:08 +0000 Subject: "version 0.1.1" svn path=/trunk/; revision=267 --- externals/grill/vasp/source/opvecs.cpp | 630 +++++++++++++++++++++++++++++++++ 1 file changed, 630 insertions(+) create mode 100644 externals/grill/vasp/source/opvecs.cpp (limited to 'externals/grill/vasp/source/opvecs.cpp') diff --git a/externals/grill/vasp/source/opvecs.cpp b/externals/grill/vasp/source/opvecs.cpp new file mode 100644 index 00000000..0e476682 --- /dev/null +++ b/externals/grill/vasp/source/opvecs.cpp @@ -0,0 +1,630 @@ +/* + +VASP modular - vector assembling signal processor / objects for Max/MSP and PD + +Copyright (c) 2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file vasp__ctrl.cpp + \brief Methods for handling of vector data for real, complex and multi-vector cases. + +*/ + +#include "opbase.h" +#include "classes.h" +#include "vecblk.h" +#include "util.h" + +/*! \brief Corrects for the common vector frame count + \param frms frame count to correct + \param bl new frame count + \return true if a correction was made +*/ +static BL corrlen(I &frms,I bl,I bf = -1,I bo = 0) +{ + if(bf < 0) bf = bl; + + BL corr = false; + BL all = frms < 0; + if(all) + frms = bl; + else if(frms > bl) { + // longer than vector length -> correct + frms = bl; + corr = true; + } + + if(bo+frms > bf) { + // now check if buffer size is exceeded +// post("%s - %s vector (%s) exceeds buffer size: cropped",op,bli == 0?"src":"dst",bref->Name()); + frms = bf-bo; + if(frms < 0) frms = 0; + corr = true; + } + + return corr; +} + + +inline BL corrlen(I &frms,VBuffer &b) +{ + return corrlen(frms,b.Length(),b.Frames(),b.Offset()); +} + + +/*! \brief Make real vector block for unary operations. + + \param op operation name + \param src source vasp + \param dst optional destination vasp + \return struct with vector data + + \remark working size is maximum common vector size +*/ +RVecBlock *VaspOp::GetRVecs(const C *op,Vasp &src,Vasp *dst) +{ + I nvecs = src.Vectors(); + if(dst && dst->Ok() && dst->Vectors() != nvecs) { + nvecs = min(nvecs,dst->Vectors()); + post("%s - src/dst vector number not equal -> taking minimum",op); + } + + RVecBlock *ret = new RVecBlock(nvecs); + + BL ok = true,dlens = false; + I tfrms = -1; + + Vasp *vbl[2] = {&src,dst}; + + for(I bli = 0; bli < 2; ++bli) + for(I ci = 0; ok && ci < nvecs; ++ci) { + VBuffer *bref = NULL; + if(vbl[bli] && vbl[bli]->Ok()) { + bref = vbl[bli]->Buffer(ci); + if(!bref->Data()) { + post("%s - %s vector (%s) is invalid",op,bli == 0?"src":"dst",bref->Name()); + delete bref; bref = NULL; + ok = false; + } + else + dlens = dlens || corrlen(tfrms,*bref); + } + + if(bli == 0) + ret->Src(ci,bref); + else + ret->Dst(ci,bref); + } + + if(dlens) post("%s - vector length has been limited to maximum common length (%i)",op,tfrms); + + ret->Frames(tfrms < 0?0:tfrms); + + if(ok) return ret; + else { delete ret; return NULL; } +} + +/*! \brief Make real vector block for unary operations. + + \param op operation name + \param src source vasp + \param dst optional destination vasp + \param full true if imaginary part is compulsory + \return struct with vector data +*/ +CVecBlock *VaspOp::GetCVecs(const C *op,Vasp &src,Vasp *dst,BL full) +{ + I nvecs = src.Vectors(); + if(dst && dst->Ok() && dst->Vectors() != nvecs) { + nvecs = min(nvecs,dst->Vectors()); + post("%s - src/dst vector number not equal -> taking minimum",op); + } + + I pairs = nvecs/2; + if(nvecs != pairs*2) + if(full) { + post("%s - number of vectors is odd - not allowed",op); + return NULL; + } + else { + post("%s - number of vectors is odd - omitting last vector",op); + } + + CVecBlock *ret = new CVecBlock(pairs); + BL ok = true,dlens = false; + I tfrms = -1; + + Vasp *vbl[2] = {&src,dst}; + + for(I bli = 0; bli < 2; ++bli) + for(I ci = 0; ci < pairs; ++ci) { + VBuffer *bre = NULL,*bim = NULL; // complex channels + if(vbl[bli] && vbl[bli]->Ok()) { + const C *vnm = bli == 0?"src":"dst"; + bre = vbl[bli]->Buffer(ci*2); + bim = vbl[bli]->Buffer(ci*2+1); // complex channels + + if(!bre->Data()) { + post("%s - real %s vector (%s) is invalid",op,vnm,bre->Name()); + delete bre; bre = NULL; + ok = false; + } + if(bim && !bim->Data()) { + post("%s - imag %s vector (%s) is invalid",op,vnm,bim->Name()); + delete bim; bim = NULL; + ok = false; + } + + // check against common vector length + if(bre) { + dlens = dlens || corrlen(tfrms,*bre); + } + if(bim) { + dlens = dlens || corrlen(tfrms,*bim); + } + + } + + if(bli == 0) + ret->Src(ci,bre,bim); + else + ret->Dst(ci,bre,bim); + } + + if(dlens) post("%s - vector src/dst length has been limited to maximum common length (%i)",op,tfrms); + + ret->Frames(tfrms < 0?0:tfrms); + + if(ok) return ret; + else { delete ret; return NULL; } +} + + +/*! \brief Make real vector block for binary operations. + + \param op operation name + \param src source vasp + \param arg argument vasp + \param dst optional destination vasp + \param multi 0 off/1 on/-1 auto... controls whether argument vector is single- or multi-vectored + \return struct with vector data +*/ +RVecBlock *VaspOp::GetRVecs(const C *op,Vasp &src,const Vasp &arg,Vasp *dst,I multi,BL ssize) +{ + if(!arg.Ok()) { + post("%s - invalid argument vasp detected and ignored",op); + return NULL; + } + + I nvecs = src.Vectors(); + if(dst && dst->Ok() && dst->Vectors() != nvecs) { + nvecs = min(nvecs,dst->Vectors()); + post("%s - src/dst vector number not equal -> taking minimum",op); + } + + RVecBlock *ret; + + if(multi < 0) { // auto mode + multi = arg.Vectors() > 1; + } + + if(multi) { + if(arg.Vectors() < nvecs) { + nvecs = arg.Vectors(); + post("%s - too few arg vectors, operating on only first %i vectors",op,nvecs); + } + ret = new RVecBlock(nvecs,nvecs,1); + for(I i = 0; i < nvecs; ++i) + ret->Arg(i,arg.Buffer(i)); + } + else { + if(arg.Vectors() > 1) { + post("%s - using only first arg vector for all operations",op); + } + ret = new RVecBlock(nvecs,nvecs,1); + for(I i = 0; i < nvecs; ++i) + ret->Arg(i,arg.Buffer(0)); + } + + BL ok = true,dlens = false,dalens = false; + I tfrms = -1,afrms = -1; + + for(I ci = 0; ok && ci < nvecs; ++ci) { + VBuffer *bref = src.Buffer(ci); + VBuffer *barg = ret->Arg(multi?ci:0); + VBuffer *bdst = dst && dst->Ok()?dst->Buffer(ci):NULL; + + if(barg && (multi || ci == 0) && !barg->Data()) { + post("%s - arg vector (%s) is invalid",op,barg->Name()); + ok = false; break; // really break? + } + else if(!bref->Data()) { + post("%s - src vector (%s) is invalid",op,bref->Name()); + ok = false; break; // really break? + } + + // check src/dst frame lengths + dlens = dlens || corrlen(tfrms,*bref); + if(bdst) dlens = dlens || corrlen(tfrms,*bdst); + + // check arg frame length + if(barg) dalens = dalens || corrlen(afrms,*barg); + + ret->Src(ci,bref); + if(bdst) ret->Dst(ci,bdst); + } + + if(dlens) post("%s - vector src/dst length has been limited to maximum common length (%i)",op,tfrms); + if(dalens) post("%s - vector arg length has been limited to maximum common length (%i)",op,afrms); + + if(ssize) { + if(corrlen(tfrms,afrms)) + post("%s - vector src/dst and arg lengths are unequal -> set to max. common length (%i)",op,tfrms); + afrms = tfrms; + } + + ret->Frames(tfrms < 0?0:tfrms); + ret->ArgFrames(afrms < 0?0:afrms); + + if(ok) return ret; + else { delete ret; return NULL; } +} + + +/*! \brief Make real complex block for binary operations. + + \param op operation name + \param src source vasp + \param arg argument vasp + \param dst optional destination vasp + \param multi 0 off/1 on/-1 auto... controls whether argument vector is single- or multi-vectored + \param full true if imaginary part is compulsory + \return struct with vector data +*/ +CVecBlock *VaspOp::GetCVecs(const C *op,Vasp &src,const Vasp &arg,Vasp *dst,I multi,BL ssize,BL full) +{ + if(!arg.Ok()) { + post("%s - invalid argument vasp detected and ignored",op); + return NULL; + } + + I nvecs = src.Vectors(); + if(dst && dst->Ok() && dst->Vectors() != nvecs) { + nvecs = min(nvecs,dst->Vectors()); + post("%s - src/dst vector number not equal -> taking minimum",op); + } + + I pairs = nvecs/2; + CVecBlock *ret; + + if(multi < 0) { // auto mode + multi = arg.Vectors() > 2; // more than one argument pair -> multi + } + + if(multi) { + I apairs = arg.Vectors()/2; + if(arg.Vectors() != apairs*2) + if(full) { + post("%s - number of arg vectors is odd - not allowed",op); + return NULL; + } + else { + post("%s - number of arg vectors is odd - assuming complex part as 0",op); + ++apairs; + } + + if(apairs < pairs) { + pairs = apairs; + post("%s - too few arg vectors, operating on only first %i vector pairs",op,pairs); + } + ret = new CVecBlock(pairs,pairs,1); + for(I i = 0; i < pairs; ++i) + ret->Arg(i,arg.Buffer(i*2),arg.Buffer(i*2+1)); + } + else { + if(arg.Vectors() > 2) { + post("%s - using only first arg vector pair for all operations",op); + } + ret = new CVecBlock(pairs,pairs,1); + for(I i = 0; i < pairs; ++i) + ret->Arg(i,arg.Buffer(0),arg.Buffer(1)); + } + + BL ok = true,dlens = false,dalens = false; + I tfrms = -1,afrms = -1; + + { + if(nvecs != pairs*2) { + post("%s - number of src vectors is odd - omitting last vector",op); + // clear superfluous vector? + } + + for(I ci = 0; ok && ci < pairs; ++ci) { + // --- arg stuff ---------------- + + VBuffer *brarg = ret->ReArg(ci),*biarg = ret->ImArg(ci); + + if(multi || ci == 0) { + if(!brarg->Data()) { + post("%s - real arg vector (%s) is invalid",op,brarg->Name()); + ok = false; break; + } + else if(biarg && !biarg->Data()) { + post("%s - imag arg vector (%s) is invalid",op,biarg->Name()); + ok = false; break; + } + } + + // check against common arg length + if(brarg) dalens = dalens || corrlen(afrms,*brarg); + if(biarg) dalens = dalens || corrlen(afrms,*biarg); + + // --- src/dst stuff ---------------- + + VBuffer *brref = src.Buffer(ci*2),*biref = src.Buffer(ci*2+1); + VBuffer *brdst,*bidst; + if(dst && dst->Ok()) brdst = dst->Buffer(ci*2),bidst = dst->Buffer(ci*2+1); + else brdst = bidst = NULL; + + if(!brref->Data()) { + post("%s - real src vector (%s) is invalid",op,brref->Name()); + ok = false; break; // really break? + } + else if(biref && !biref->Data()) { + post("%s - imag src vector (%s) is invalid",op,biref->Name()); + ok = false; break; // really break? + } + else { + dlens = dlens || corrlen(tfrms,*brref); + if(biref) dlens = dlens || corrlen(tfrms,*biref); + if(brdst) dlens = dlens || corrlen(tfrms,*brdst); + if(bidst) dlens = dlens || corrlen(tfrms,*bidst); + } + + ret->Src(ci,brref,biref); + if(brdst) ret->Dst(ci,brdst,bidst); + } + } + + if(dlens) post("%s - vector src/dst length has been limited to maximum common length (%i)",op,tfrms); + if(dalens) post("%s - vector arg length has been limited to maximum common length (%i)",op,afrms); + + if(ssize) { + if(corrlen(tfrms,afrms)) + post("%s - vector src/dst and arg lengths are unequal -> set to max. common length (%i)",op,tfrms); + afrms = tfrms; + } + + ret->Frames(tfrms < 0?0:tfrms); + ret->ArgFrames(afrms < 0?0:afrms); + + if(ok) return ret; + else { delete ret; return NULL; } +} + + +/*! \brief Run the operation on the various real vectors. + + \param vecs src/arg/dst vector block + \param fun operative function + \param p parameter block for operative function + \return normalized vasp or NULL on error + + \todo set overlap flag + + \remark operative function must be capable of handling reversed direction +*/ +Vasp *VaspOp::DoOp(RVecBlock *vecs,VecOp::opfun *fun,OpParam &p,BL symm) +{ + BL ok = true; + + if(vecs->ArgBlks() && (!p.arg || p.args < vecs->ArgBlks())) { + post("%s - not enough argument blocks",p.opname); + ok = false; + } + + const I scnt = symm?2:1; + for(I i = 0; ok && i < vecs->Vecs(); ++i) + for(I si = 0; ok && si < scnt; ++si) { + p.frames = vecs->Frames(); + + VBuffer *s = vecs->Src(i),*d = vecs->Dst(i); + p.rsdt = s->Pointer(),p.rss = s->Channels(); + + if(d) p.rddt = d->Pointer(),p.rds = d->Channels(); + else p.rddt = p.rsdt,p.rds = p.rss; + + for(I bi = 0; bi < vecs->ArgBlks(); ++bi) { + VBuffer *a = vecs->Arg(i,bi); + p.arg[bi].SetV(a?a->Pointer():NULL,a?a->Channels():0); + } + + if(!symm) + p.symm = -1; + else { + const I hcnt = p.frames/2; + p.oddrem = p.frames != 2*hcnt; + + if((p.symm = si) == 0) { + p.frames = hcnt+(p.oddrem?1:0); + } + else { + const I r = p.frames-hcnt; + p.frames = hcnt; + p.rsdt += r*p.rss,p.rddt += r*p.rds; + + // What to do with arguments in symmetric mode? + // let the object decide!! + } + } + + { // ---- Check out and try to resolve overlap situation ------------ + + BL sovr = p.SR_In(); // check whether dst is before src + if(p.HasArg()) { + // has argument + if(sovr) { + // src/dst needs reversal -> check if ok for arg/dst + p.ovrlap = true; + + if(p.AR_Can()) + p.R_Rev(); // Revert vectors + else { + post("%s - vector overlap situation can't be resolved",p.opname); + ok = false; + } + } + else if(p.AR_In()) { + // arg/dst needs reversal -> check if ok for src/dst + p.ovrlap = true; + + if(p.SR_Can()) + p.R_Rev(); // Revert vectors + else { + post("%s - vector overlap situation can't be resolved",p.opname); + ok = false; + } + } + } + else { // No arg + if(sovr) { + p.ovrlap = true; + p.R_Rev(); // if overlapping revert vectors + } + else + p.ovrlap = p.SR_Ovr(); + } + } + + ok = fun(p); + +#ifdef FLEXT_THREAD + flext_base::ThrYield(); +#endif + } + return ok?vecs->ResVasp():NULL; +} + + +/*! \brief Run the operation on the various complex vector pairs. + + \param vecs src/arg/dst vector block + \param fun operative function + \param p parameter block for operative function + \return normalized vasp or NULL on error + + \todo set overlap flag + + \remark operative function must be capable of handling reversed direction +*/ +Vasp *VaspOp::DoOp(CVecBlock *vecs,VecOp::opfun *fun,OpParam &p,BL symm) +{ + BL ok = true; + + if(vecs->ArgBlks() && (!p.arg || p.args < vecs->ArgBlks())) { + post("%s - not enough argument blocks",p.opname); + ok = false; + } + + const I scnt = symm?2:1; + for(I i = 0; ok && i < vecs->Pairs(); ++i) + for(I si = 0; ok && si < scnt; ++si) { + p.frames = vecs->Frames(); + + VBuffer *rsv = vecs->ReSrc(i),*isv = vecs->ImSrc(i); + p.rsdt = rsv->Pointer(),p.rss = rsv->Channels(); + p.isdt = isv->Pointer(),p.iss = isv->Channels(); + + VBuffer *rdv = vecs->ReDst(i),*idv = vecs->ImDst(i); + if(rdv) { + p.rddt = rdv->Pointer(),p.rds = rdv->Channels(); + if(idv) p.iddt = idv->Pointer(),p.ids = idv->Channels(); + else p.iddt = NULL; //,p.ids = 0; // Can that be NULL?? + } + else { + p.rddt = p.rsdt,p.rds = p.rss,p.iddt = p.isdt,p.ids = p.iss; + } + + for(I bi = 0; bi < vecs->ArgBlks(); ++bi) { + VBuffer *rav = vecs->ReArg(i,bi),*iav = vecs->ImArg(i,bi); + p.arg[bi].SetV(rav?rav->Pointer():NULL,rav?rav->Channels():0,iav?iav->Pointer():NULL,iav?iav->Channels():0); + } + + if(!symm) + p.symm = -1; + else { + const I hcnt = p.frames/2; + p.oddrem = p.frames != 2*hcnt; + + if((p.symm = si) == 0) { + p.frames = hcnt+(p.oddrem?1:0); + } + else { + const I r = p.frames-hcnt; + p.frames = hcnt; + p.rsdt += r*p.rss,p.isdt += r*p.iss; + p.rddt += r*p.rds; + if(p.iddt) p.iddt += r*p.ids; // Can that be NULL?? + + // What to do with arguments? + // let objects decide!! + } + } + + { // ---- Check out and try to resolve overlap situation ------------ + + BL sovr = p.SR_In(); // check whether dst is before src + if(sovr && !p.SI_Can()) { + post("%s - src/dst overlap of re/im vectors not resolvable",p.opname); + ok = false; + } + + if(ok && p.HasArg()) { + // has argument + if(sovr) { + // src/dst needs reversal -> check if ok for arg/dst + p.ovrlap = true; + + if(p.AR_Can() && p.AI_Can()) + p.C_Rev(); // Revert vectors + else { + post("%s - vector overlap situation can't be resolved",p.opname); + ok = false; + } + } + else if(p.AR_In() || p.AI_In()) { + // arg/dst needs reversal -> check if ok for src/dst + p.ovrlap = true; + + if(p.AR_Can() && p.AI_Can() && p.SR_Can() && p.SI_Can()) + p.C_Rev(); // Revert vectors + else { + post("%s - vector overlap situation can't be resolved",p.opname); + ok = false; + } + } + } + else { // No arg + if(sovr) { + p.ovrlap = true; + p.C_Rev(); // if overlapping revert vectors + } + else + p.ovrlap = p.SR_Ovr() || p.SI_Ovr(); + } + } + + ok = fun(p); + +#ifdef FLEXT_THREAD + flext_base::ThrYield(); +#endif + } + return ok?vecs->ResVasp():NULL; +} + + + -- cgit v1.2.1