aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/vasp/source/opvecs.cpp
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2002-12-02 19:21:08 +0000
committerThomas Grill <xovo@users.sourceforge.net>2002-12-02 19:21:08 +0000
commit9815096db22c73cacdbb65512d1b61d633db7fa8 (patch)
tree4a6582ead85b8efd031f68e717fbc8a5b3a3df3f /externals/grill/vasp/source/opvecs.cpp
parent0a109da279e9df66fb5ea7d6bdaeffed16592f02 (diff)
"version 0.1.1"
svn path=/trunk/; revision=267
Diffstat (limited to 'externals/grill/vasp/source/opvecs.cpp')
-rw-r--r--externals/grill/vasp/source/opvecs.cpp630
1 files changed, 630 insertions, 0 deletions
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;
+}
+
+
+