from vector of pairs to a map

M

ma740988

Hopefully I'm not asking too much here, nontheless consider the test
source:

#include <vector>
#include <utility>

using std::vector;
using std::pair;

#define INVALID_ID -1

struct lsp_input_def
{
int segment;
lsp_input_def(void):
segment(INVALID_ID)
{
}
};

typedef vector<int> proccessor_vec;
typedef pair< unsigned int, proccessor_vec > segment_proc_pair;
typedef vector< segment_proc_pair > vec_pair;

// Transform the input to the output in sorted form.
void Transform(lsp_input_def* pStruct, unsigned int waveformCount,
unsigned int procCount, vec_pair& rsVect)
{
rsVect.resize(waveformCount);
size_t curOff = waveformCount * procCount;
unsigned int i = waveformCount;
while(i--)
{
rsVect.first = i;
unsigned int j = procCount;
while(j--)
{
const lsp_input_def& curStruct = pStruct[--curOff];
if(curStruct.segment != INVALID_ID) // ID number is valid. Add
it to the vector.
rsVect[curStruct.segment].second.push_back(j);
}
}
}

int main()
{
typedef unsigned int uint_type;
uint_type const max_segments = 7;
uint_type const max_processors = 24;

lsp_input_def wf[max_segments][max_processors];

wf[0][0].segment = 1; // element first is the segment / element
second processor
wf[1][0].segment = 0;
wf[2][0].segment = 3;
//wf[3][0].segment = 2;
//wf[0][1].segment = 3;

wf[0][1].segment = 1;
//wf[1][1].segment = 2;
wf[1][1].segment = 0;

// Transform the input to the output.
vec_pair sampleVect;
Transform((lsp_input_def*)wf, max_segments, max_processors,
sampleVect);

printf(" segment processor\n");
printf("-------------------------------\n");
for(size_t i = 0; i < sampleVect.size(); i++)
{
proccessor_vec& curVect = sampleVect.second;
if(curVect.size())
{
printf("\t%i\t", sampleVect.first);
printf("%i", curVect[0]);
for(size_t j = 1; j < curVect.size(); j++)
printf(", %i", curVect[j]);
printf("\n");
}
}

printf("\n");

return 0;
}

I'm trying to work my way through understanding how I could achieve the
same results using a map:

typedef std::map< unsigned int, proccessor_vec > id_vec_map;
Source snippet appreaciated.

Thanks
 
L

Luke Meyers

Yikes... I tried for about a half hour but gave up on deciphering this
spaghetti. No question that you can get the job done using std::map,
but without a clear specification of the intended behavior, it's hard
to provide more specific help. Your code is clearly influenced by some
very dated C idioms -- I'd recommend reading up on more modern C++
practices, and just getting exposure to code that uses the STL as
intended. If you can manage the paradigm shift, you'll find that
problems like the one you're posting become much more approachable, or
even moot.

Luke
 
M

Mike Wahler

ma740988 said:
Hopefully I'm not asking too much here, nontheless consider the test
source:

#include <vector>
#include <utility>

using std::vector;
using std::pair;

#define INVALID_ID -1

struct lsp_input_def
{
int segment;
lsp_input_def(void):
segment(INVALID_ID)
{
}
};

typedef vector<int> proccessor_vec;
typedef pair< unsigned int, proccessor_vec > segment_proc_pair;
typedef vector< segment_proc_pair > vec_pair;

// Transform the input to the output in sorted form.
void Transform(lsp_input_def* pStruct, unsigned int waveformCount,
unsigned int procCount, vec_pair& rsVect)
{
rsVect.resize(waveformCount);
size_t curOff = waveformCount * procCount;
unsigned int i = waveformCount;
while(i--)
{
rsVect.first = i;
unsigned int j = procCount;
while(j--)
{
const lsp_input_def& curStruct = pStruct[--curOff];
if(curStruct.segment != INVALID_ID) // ID number is valid. Add
it to the vector.
rsVect[curStruct.segment].second.push_back(j);
}
}
}

int main()
{
typedef unsigned int uint_type;
uint_type const max_segments = 7;
uint_type const max_processors = 24;

lsp_input_def wf[max_segments][max_processors];

wf[0][0].segment = 1; // element first is the segment / element
second processor
wf[1][0].segment = 0;
wf[2][0].segment = 3;
//wf[3][0].segment = 2;
//wf[0][1].segment = 3;

wf[0][1].segment = 1;
//wf[1][1].segment = 2;
wf[1][1].segment = 0;

// Transform the input to the output.
vec_pair sampleVect;
Transform((lsp_input_def*)wf, max_segments, max_processors,
sampleVect);

printf(" segment processor\n");
printf("-------------------------------\n");
for(size_t i = 0; i < sampleVect.size(); i++)
{
proccessor_vec& curVect = sampleVect.second;
if(curVect.size())
{
printf("\t%i\t", sampleVect.first);
printf("%i", curVect[0]);
for(size_t j = 1; j < curVect.size(); j++)
printf(", %i", curVect[j]);
printf("\n");
}
}

printf("\n");

return 0;
}

I'm trying to work my way through understanding how I could achieve the
same results using a map:

typedef std::map< unsigned int, proccessor_vec > id_vec_map;
Source snippet appreaciated.


Rather than letting us try to untangle that to see what it
does (or is supposed to do), and possibly/probably misunderstand
your meaning, I suggest you state your objective in English.
Include small code snippets if you feel they help clarify.

-Mike
 
E

Earl Purple

ma740988 said:
Hopefully I'm not asking too much here, nontheless consider the test
source:

#include <vector>
#include <utility>

using std::vector;
using std::pair;

#define INVALID_ID -1

Not good to do that. Better to put it here:
struct lsp_input_def
{

const int INVALID_ID = -1; // here
int segment;
lsp_input_def(): // don't put void inside the brackets
segment(INVALID_ID)
{
}
};

(and would be better not to use all caps).
typedef vector<int> proccessor_vec;
typedef pair< unsigned int, proccessor_vec > segment_proc_pair;
typedef vector< segment_proc_pair > vec_pair;

// Transform the input to the output in sorted form.
void Transform(lsp_input_def* pStruct, unsigned int waveformCount,
unsigned int procCount, vec_pair& rsVect)
{
rsVect.resize(waveformCount);
size_t curOff = waveformCount * procCount;
unsigned int i = waveformCount;

while(i--) // will loop from i-1 to 1 (will never populate rsVect[0] )
{
rsVect.first = i;
unsigned int j = procCount;
while(j--) // see comment above
{

const lsp_input_def& curStruct = pStruct[--curOff]; // notable not modifying pStruct
// or what it points to. Therefore parameter above should be const
lsp_input_def * ...
if(curStruct.segment != INVALID_ID) // ID number is valid. Add
it to the vector.

// now I made INVALID_ID part of the class but we could have a member
function that
// returns bool to determine whether our curStruct is valid.
rsVect[curStruct.segment].second.push_back(j);
}
}
}

I'm going to give up at this point.
 
M

ma740988

Howdy, Mike,
I'm going to deviate from my initial post here for a minute. Here's
my 'dilema' in a nutshell. I've got 24 sources ( call them 0 .. 23 )
sending me ( call me 'X' ) data. The data from each source has
what's called an 'id' (call it segment id) assosciated with it.
There's two id's ( 0 and 1 ). X will receive said from all sources and
perform some processing on them. X knows (via a structure that was
sent to it) that the processing order is 0 and 1. i.e process segment
0 first followed by segment 1.
So on X, I have a table that tells me

segment what_to_do
0 IFFT
1 FFT
The trouble on X is all the 'required house keeping that goes along
with receipt of the segments' from the 24 sources. Having said that I
need to track three things.
1. The size of the segment per source
2. The address where I store the segment - for _each_ source on X
3. A count parameter to keep track of things.

In it's simplest form. Lets assume source 0 transmits segment 0, with
a size of 0x10000; Upon receipt of the segment (i.e 0) the code
executing on "X' will. Increment the count parameter associated for
_that_ source (i.e source 0), store the size of data from source 0 and
the offset in memory where I stored source 0's data.

Now do that for the remainder. If the count == 24, then X has
received results from every source - for segment 0. The X will do an
IFFT on the data. Once 'X' is complete with segment 0. X will
'request' segment 1 from the sources. I'm executing in a
multi-threaded environment but enviornment 'details' aside, that's it
in a nutshell.

Now here's where it gets tricky for me - the design aspect of this.
Pictorially my thoughts were a map where first would be the
'what_to_do', second is a struct that entails - segment id, sources,
source counts, source data size, offset in memory. So now:

__ what_to_do_ segment_id
IFFT 0
0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 10 .... 24 -- (24) sources
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, ..... 0 -- (24) counts ( zero initially )

-- (24) data size - this we'll get from
every source

-- address in memory - this part is tricky
but doable.



So a map perhaps:

enum algo { IFFT, FFT };
struct holder {
unsigned int segment_id;
unsigned int source;
unsigned int count;
unsigned int data_size;
unsigned char* ptr_addr_in_mem;
};

typedef std::vector<holder> holder_vec;
typedef std::map < unsigned int, holder_vec > the_map;
^ ^
| |
what_to_do here's all the
information

Trouble is, something just doesn't seem right about the use of map
here. This seem like I need a better design which will perhaps include
a class. Trouble is, does this require for me to create 24 instances
of said class or ..... Confused. Your thoughts!
I chose the map because I thought perhaps I could iterate through map
second - check count. Count 24, yes. Everything I need to do is in
the remainder of the struct. 'what_to_do' is the first element of the
map.

Thanks in advance
 
E

Earl Purple

ma740988 said:
Howdy, Mike,
I'm going to deviate from my initial post here for a minute. Here's
my 'dilema' in a nutshell.

Far from deviating, this is the correct way to go. Have a look at the
spec.

I've got 24 sources ( call them 0 .. 23 )
sending me ( call me 'X' ) data. The data from each source has
what's called an 'id' (call it segment id) assosciated with it.

Now break it down a bit at a time. You have multiple sources that do
things. A "source" is a class (it has attributes and methods). You have
multiple ones so that suggests some kind of collection. The only
question is choosing which collection to use.

If they are numbered 0 to 23 then your best bet is vector.
There's two id's ( 0 and 1 ). X will receive said from all sources and
perform some processing on them. X knows (via a structure that was
sent to it) that the processing order is 0 and 1. i.e process segment
0 first followed by segment 1.
So on X, I have a table that tells me

segment what_to_do
0 IFFT
1 FFT

X "knows" that there are two so you could have some hard-coded table.
If you are not certain that there will always be two then you might
want some kind of abstract base class indicating an "id" and have a
virtual method "whatToDo" (probably not exactly with that name). Might
be an idea for you to do that even with 2. Your Id0 will implement
"whatToDo()" with IFFT, and Id1 will implement with FFT.
The trouble on X is all the 'required house keeping that goes along
with receipt of the segments' from the 24 sources. Having said that I
need to track three things.
1. The size of the segment per source
2. The address where I store the segment - for _each_ source on X
3. A count parameter to keep track of things.

In it's simplest form. Lets assume source 0 transmits segment 0, with
a size of 0x10000; Upon receipt of the segment (i.e 0) the code
executing on "X' will. Increment the count parameter associated for
_that_ source (i.e source 0), store the size of data from source 0 and
the offset in memory where I stored source 0's data.

Put that in the source class. Remember that the source class you have
on your side is a source from your perspective, i.e. how X uses a
source.

That's probably enough to be getting on with for now.

As for using a map, a map is used when:
1. You have a collection
2. You need to look up by an id.

However when the ids are numeric and not too sparse you should consider
using a vector.

Incidentally, although vector is copyable, it is recommended to avoid
copying them too much because it is generally a major overhead. You
could use shared_ptr<vector> or shared_ptr<Wrapper> where Wrapper is a
class that contains a vector (and probably has some other methods as
well). shared_ptr is part of the boost library and is also part of
std::tr1. Although they are not standard they are pretty much in common
use and you can download the source free. (It is likely that a version
will be included in the next standard, thus it has already been
promoted to std::tr1).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,434
Messages
2,571,691
Members
48,796
Latest member
Greg L.

Latest Threads

Top