Related
so Im supposed to make a game an assignment for class.
Essentially, I decided to re-create a heads up Poker game, running different functions such as int deal(a, b, x, y) where a and b are the hero's cards, and x and y are the villan's.
This function in particular, has me a bit stumped. Effectively, I loop through the array deck, and assign random numbers to a, b, x and y. Then, I will translate each assigned value into a real, unique card, and return that to int main().
The part that I am stuck at is "as each card is selected, it is deleted from the array. It seems that there is no easy way in C to simply remove an element from deck array.
int deal (a, b, x, y)
{
int deck[52] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52};
int heroFirst;
int heroSecond;
int villainFirst;
int villainSecond;
srand(0);
}
Any thoughts?
You don't have to delete anything.
Shuffle your deck array (using a Fisher-Yates shuffle or similar algorithm). Deal each card from the "top" of the deck:
int top = 0;
card1 = deck[top++];
card2 = deck[top++];
card3 = deck[top++];
...
etc. The top variable is the index of the next available card in the deck.
The general outline of your code will be something like
#define DECKSIZE 52
#define HANDSIZE 5
int main( void )
{
int deck[DECKSIZE] = { ... }; // initial deck;
size_t top = 0; // points to next available card
shuffle( deck, DECKSIZE );
int hero[HANDSIZE] = {0}; // 0 means no card has been drawn for
int villan[HANDSIZE] = {0}; // that element.
if ( deal( hero, HANDSIZE, deck, DECKSIZE, &top ) &&
deal( villan, HANDSIZE, deck, DECKSIZE, &top ) )
{
/**
* do stuff with hero and villan hands
*/
}
else
{
/**
* Not enough cards available in deck for two hands.
*/
}
};
Your deal function would look something like
int deal( int *hand, size_t handsize, int *deck, size_t decksize, size_t *top )
{
size_t i;
for ( i = 0; i < handsize && *top < decksize; i++ )
hand[i] = deck[(*top)++];
return i == handsize;
}
This function will return 0 if we run out of cards in deck before we've dealt the hand, in which case you'll need to do...something. Good luck!
If you want to deal a partial hand (such as to replace 3 cards), you'd do something like
if ( deal( &hero[2], 3, deck, DECKSIZE, &top) )
...
This call will overwrite hero[2] through hero[4] with three new cards drawn from deck. With each call to deal, top will be advanced to point to the next available card in the deck.
You can write a discard function that returns cards to the deck. It means keeping a separate bottom variable and updating that:
int discard( int card, int *deck, size_t decksize, size_t *top, size_t *bottom )
{
int result = *bottom < *top && *bottom < decksize;
if ( result )
deck[(*bottom)++] = card;
return result;
}
Obviously, bottom should be strictly less than the deck size and strictly less than top on a discard; otherwise, we haven't managed our deck or hands properly. With a little work, you could make your array "circular", such that top and bottom "wrap around" as necessary. If you exhaust the deck, you can reshuffle (minus the cards in hand, which will be the deck entries between bottom and top) and reset top and bottom as necessary.
Play with this on paper for a little while, and it should become obvious.
EDIT
Addressing questions here:
At which point do you assign deck[5] to a card, for instance
That happens in the deal function, in the for loop. The first time we call deal, we tell it to deal to the hero hand:
deal( hero, HANDSIZE, deck, DECKSIZE, &top )
At this point, top is 0. Assuming we're dealing 5 cards at a time, the first call to deal effectively does this:
Loop iteration 0: hero[0] = deck[0]
Loop iteration 1: hero[1] = deck[1]
Loop iteration 2: hero[2] = deck[2]
Loop iteration 3: hero[3] = deck[3]
Loop iteration 4: hero[4] = deck[4]
When the function returns, the top variable has been updated to 5. The next time we call deal, we tell it to deal to the villain hand:
deal( villain, HANDSIZE, deck, DECKSIZE, &top )
Again, assuming we're dealing 5 cards at a time, the loop effectively does this:
Loop iteration 0: villain[0] = deck[5];
Loop iteration 1: villain[1] = deck[6];
Loop iteration 2: villain[2] = deck[7];
Loop iteration 3: villain[3] = deck[8];
Loop iteration 4: villain[4] = deck[9];
After the second call to deal, top has been updated to 10.
Each time you call deal with the top variable, it will start dealing from deck at the position specified by top, and each time through the loop it will add 1 to top. The loop will exit if one of two conditions is true:
i == handsize - we've dealt all the cards necessary for this hand
*top == decksize - we've reached the end of the array, nor more cards may be dealt.
So, suppose you've dealt a number of hands, and there are only 3 cards left in the deck - if you try to deal 5 more cards, the loop will exit before you've dealt all 5 cards, and we'll return a 0 to indicate that no more cards are left in the deck.
at which point is the desk shuffled randomly?
You would call a shuffle function to do that before the first call to deal:
int deck[DECKSIZE] = { ... };
...
shuffle( deck, DECKSIZE );
...
if ( deal( hero, HANDSIZE, deck, DECKSIZE, &top ) &&
deal( villain, HANDSIZE, deck, DECKSIZE, &top ) )
{
...
}
A simplistic (and not terribly good) implementation of the shuffle function would be:
void shuffle( int *deck, size_t decksize )
{
for ( size_t i = 0; i < decksize; i++ )
{
int r = rand() % (decksize - i)
int tmp = deck[i+r];
deck[i+r] = deck[i];
deck[i] = tmp;
}
}
Basically, what this does is swap each deck[i] with a randomly chosen element from deck[i] through deck[decksize-1] (meaning the element may remain in place). Assume we have 5 cards. The first time through the loop, i points to the first card. We pick an offset from i at random and call it r:
i --> 1
2
3
4 <-- r
5
We then swap the contents of deck[i] and deck[i+r], and then advance i:
4
i --> 2
3
1
5
We pick another r at random from the remaining elements:
4
i --> 2
3
1
5 <-- r
and do another swap and advance i:
4
5
i --> 3
1
2
Lather, rinse, repeat - by the end of the loop, the array is more-or-less randomly shuffled.
No, there is no way in C to delete an element from an array. Indeed, as far as I know there is no way to delete an element from an array in C++, C# or Java either.
Now, that being the case, you have a few options. You can use a sentinel value in your code to mark an element as absent. You can resize your array to actually shrink it by one and relocate all elements backwards one place whenever an element is deleted.
In your example, either 0 or -1 should serve fine as sentinel values.
First at all, make the array deck static.
Next, introduce another static variable initially equal to the lenght of array=52.
Now when a card at a random position is dealt, it can be swapped with the last card in the deck, indexed with arraysize-1, and the arraysize being decreased.
Making these two variables static allows the function to maintain a state between calls. Of course better techniques would encapsulate these variables in a struct (allowing eg multiple games / resetting the deck).
In short, the problem you're really trying to solve isn't one of deleting an entry in an array.. Rather, it is a more encompassing issue: How to perform repeated random selection from a fixed domain without repeating selected values. The method described above is one way to do that. An example of the latter technique using a 20-slot array is below (the value 20 was chosen for short output lines (easy to read). It could just as easily be 52, 1000, etc.):
Code
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DECK_SIZE 20
typedef struct Deck
{
int cards[DECK_SIZE];
size_t size;
} Deck;
Deck init_deck()
{
// no shuffle is needed. each selection in draw_card will
// pick a random location in the remaining cards.
Deck deck;
for (int i=0; i<DECK_SIZE; ++i)
deck.cards[i] = i+1;
deck.size = DECK_SIZE;
return deck;
}
int draw_card(Deck *deck)
{
// reset when we run out of cards.
if (deck->size == 0)
{
printf("- reset \n");
deck->size = DECK_SIZE;
}
// generate random location in remaining cards.
// note: susceptible to modulo bias
size_t idx = rand() % deck->size;
// decrement size to consume card and index where
// the card will be swap-stored.
--deck->size;
// swap with last card in remaining cards
int tmp = deck->cards[deck->size];
deck->cards[deck->size] = deck->cards[idx];
deck->cards[idx] = tmp;
// return the drawn card
return deck->cards[deck->size];
}
int main()
{
Deck deck = init_deck();
srand((unsigned)time(NULL));
// draw 300 times. this should reset 15 times, and
// each time a new set of 1..20 should result
for (int i=0; i<300; ++i)
printf("%d ", draw_card(&deck));
fputc('\n', stdout);
}
Output (obviously varies)
7 16 3 20 9 13 6 4 1 12 18 10 14 2 8 17 11 5 15 19 - reset
6 20 14 16 11 2 10 13 4 12 18 5 3 7 19 9 17 8 15 1 - reset
14 1 8 15 13 2 19 16 11 17 5 18 9 12 7 6 3 20 4 10 - reset
18 17 12 2 15 19 1 4 14 10 20 16 9 5 11 13 6 8 3 7 - reset
4 18 5 1 19 16 8 10 9 14 13 17 12 20 7 2 15 6 11 3 - reset
14 16 18 1 5 10 17 3 19 9 8 2 7 13 12 20 4 15 11 6 - reset
16 15 12 13 6 1 17 10 9 7 11 20 8 19 2 18 3 4 14 5 - reset
7 1 8 16 17 5 2 12 13 6 18 20 9 11 14 19 15 3 4 10 - reset
20 13 4 18 7 17 12 15 5 14 2 16 11 3 9 10 1 19 8 6 - reset
5 19 4 17 18 13 8 2 12 7 9 1 11 10 3 14 6 15 16 20 - reset
3 5 10 7 1 15 19 13 16 12 9 8 6 20 4 11 17 18 14 2 - reset
11 14 4 7 15 9 16 18 8 13 12 5 10 19 2 6 20 1 3 17 - reset
10 18 2 4 12 20 14 11 16 13 3 9 8 6 5 7 17 1 15 19 - reset
19 12 20 11 13 9 5 1 10 15 7 2 17 6 3 4 8 14 16 18 - reset
10 3 19 4 6 14 18 11 1 7 9 16 8 13 17 20 2 5 15 12
Notive that on each line, there are twenty selections, and each number in 1..20 appears exactly once per line. How this technique serves you is up to you. A worthy challenge will be how to enumerate the hands held by existing players when a reset (often called a deck-flip) happens. That's an interesting problem to solve, and not one that is as intuitive as it may seem.
Hope it helps.
There are a couple of solutions you could use to solve your problem:
First, is using the vector class, especially the insert and remove functions. here's a good explanation on how it works:
C++ Vectors
Second, which is also my favorite is to use numbers or booleans as indicators. for example, declare a simple boolean array of the same length as your deck. the initial value of all elements would be true. for each card, you'd like to remove from the deck simply change its value to false to indicate it's gone.
This program takes as an input the following lines:
23 12 33 19 10 8
5
23 19 8 12 60 18
14 60 12 44 54 10
8 3 12 19 33 10
33 15 7 60 12 10
22 12 19 23 33 11
23 12 33 19 10 8 ( The first line ) are the lottery results.
n ( in this specific case, 5 ) informs how many lines will follow below.
Each line has 6 numbers. The number order doesn't matter.
The rules are: numbers range from 1 to 60 ( including 1 and 60 ) and they never repeat themselves in the same line.
The variable "quadra" stores how many lines have got 4 numbers right.
The variable "quina" stores how many lines have got 5 numbers right.
The variable "sena" stores how many lines have got 6 numbers right.
So, a computer program is running some tests over my code below and it's claiming that it goes wrong for most of them, but I can't see what's the problem here. Does anybody have a clue? Is this code wrong, or is there something wrong with the software that's testing this code?
#include <stdio.h>
int main(){
int mega[6];
int v[50500][6];
int n,swap;
int i,j,k; //counters
int quadra,quina,sena;
quadra = 0;
quina = 0;
sena = 0;
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
scanf("%i",&n);
for(i=0;i<n;++i){
for(j=0;j<6;++j){
scanf("%i",&v[i][j]);
}
}
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=0;k<6;++k){
if(v[i][j] == mega[k]){
v[i][j] = 61;
}
}
}
}
//reverse bubble sort
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=j+1;k<6;++k){
if(v[i][j] < v[i][k]){
swap = v[i][k];
v[i][k] = v[i][j];
v[i][j] = swap;
}
}
}
}
for(i=0;i<n;++i){
for(j=0;v[i][j] == 61 && j<6;++j);
if(j == 4) ++quadra;
else if(j == 5) ++quina;
else if(j == 6) ++sena;
}
return 0;
}
Your code is true, I understood and tried the flow of it. Looks fine but if you dont need to sort everyline (and use j as a counter in this loop for(j=0;v[i][j] == 61 && j<6;++j); ), you can use simpler ifstatements to compare real lottery results with the ones that entered. What I mean is that your algorithm is a little complex. Try a simple one and see how it works.
Yes, there are a couple of noteworthy issues with your code:
Compile time indicates possibility of uninitialized variable:
But, run-time results in fatal run-time at unknown source location. Stack overflow. It is likely due to this line:
int v[50500][6];
Increase your stack size. It needs to be about 2.5Mbytes for v alone.
Also, this line may not be what you intended:
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
^
If you meant to loop around the remainder of the code, remove the ; after the for() statement, and use curly braces:
for(i=0;i<6;++i) scanf("%i",&mega[i]) //first line, lottery results
{
scanf("%i",&n);
....
I'm using AVX2 instructions in some C code.
The VPERMD instruction takes two 8-integer vectors a and idx and generates a third one, dst, by permuting a based on idx. This seems equivalent to dst[i] = a[idx[i]] for i in 0..7. I'm calling this source based, because the move is indexed based on the source.
However, I have my calculated indices in destination based form. This is natural for setting an array, and is equivalent to dst[idx[i]] = a[i] for i in 0..7.
How can I convert from source-based form to destination-based form? An example test case is:
{2 1 0 5 3 4 6 7} source-based form.
{2 1 0 4 5 3 6 7} destination-based equivalent
For this conversion, I'm staying in ymm registers, so that means that destination-based solutions don't work. Even if I were to insert each separately, since it only operates on constant indexes, you can't just set them.
I guess you're implicitly saying that you can't modify your code to calculate source-based indices in the first place? I can't think of anything you can do with x86 SIMD, other than AVX512 scatter instructions that take dst-based indices. (But those are not very fast on current CPUs, even compared to gather loads. https://uops.info/)
Storing to memory, inverting, and reloading a vector might actually be best. (Or transferring to integer registers directly, not through memory, maybe after a vextracti128 / packusdw so you only need two 64-bit transfers from vector to integer regs: movq and pextrq).
But anyway, then use them as indices to store a counter into an array in memory, and reload that as a vector. This is still slow and ugly, and includes a store-forwarding failure delay. So it's probably worth your while to change your index-generating code to generate source-based shuffle vectors if at all possible.
To benchmark the solution, I modified the code from my other answer to compare the performance of the scatter instruction (USE_SCATTER defined) with a store and sequential permute (USE_SCATTER undefined). I had to copy the result back to the permutation pattern perm in order to prevent the compiler from optimizing the loop body away:
#ifdef TEST_SCATTER
#define REPEATS 1000000001
#define USE_SCATTER
__m512i ident = _mm512_set_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0);
__m512i perm = _mm512_set_epi32(7,9,3,0,5,8,13,11,4,2,15,1,12,6,10,14);
uint32_t outA[16] __attribute__ ((aligned(64)));
uint32_t id[16], in[16];
_mm512_storeu_si512(id, ident);
for (int i = 0; i < 16; i++) printf("%2d ", id[i]); puts("");
_mm512_storeu_si512(in, perm);
for (int i = 0; i < 16; i++) printf("%2d ", in[i]); puts("");
#ifdef USE_SCATTER
puts("scatter");
for (long t = 0; t < REPEATS; t++) {
_mm512_i32scatter_epi32(outA, perm, ident, 4);
perm = _mm512_load_si512(outA);
}
#else
puts("store & permute");
uint32_t permA[16] __attribute__ ((aligned(64)));
for (long t = 0; t < REPEATS; t++) {
_mm512_store_si512(permA, perm);
for (int i = 0; i < 16; i++) outA[permA[i]] = i;
perm = _mm512_load_si512(outA);
}
#endif
for (int i = 0; i < 16; i++) printf("%2d ", outA[i]); puts("");
#endif
Here's the output for the two cases (using the builtin time command of tcsh, the u output is user-space time in seconds):
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
14 10 6 12 1 15 2 4 11 13 8 5 0 3 9 7
store & permute
12 4 6 13 7 11 2 15 10 14 1 8 3 9 0 5
10.765u 0.001s 0:11.22 95.9% 0+0k 0+0io 0pf+0w
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
14 10 6 12 1 15 2 4 11 13 8 5 0 3 9 7
scatter
12 4 6 13 7 11 2 15 10 14 1 8 3 9 0 5
10.740u 0.000s 0:11.19 95.9% 0+0k 40+0io 0pf+0w
The runtime is about the same (Intel(R) Xeon(R) W-2125 CPU # 4.00GHz, clang++-6.0, -O3 -funroll-loops -march=native). I checked the assembly code generated. With USE_SCATTER defined, the compiler generates vpscatterdd instructions, without it generates complex code using vpextrd, vpextrq, and vpextracti32x4.
Edit: I was worried that the compiler may have found a specific solution for the fixed permutation pattern I used. So I replaced it with a randomly generated pattern from std::random_shuffe(), but the time measurements are about the same.
Edit: Following the comment by Peter Cordes, I wrote a modified benchmark that hopefully measures something like throughput:
#define REPEATS 1000000
#define ARRAYSIZE 1000
#define USE_SCATTER
std::srand(unsigned(std::time(0)));
// build array with random permutations
uint32_t permA[ARRAYSIZE][16] __attribute__ ((aligned(64)));
for (int i = 0; i < ARRAYSIZE; i++)
_mm512_store_si512(permA[i], randPermZMM());
// vector register
__m512i perm;
#ifdef USE_SCATTER
puts("scatter");
__m512i ident = _mm512_set_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0);
for (long t = 0; t < REPEATS; t++)
for (long i = 0; i < ARRAYSIZE; i++) {
perm = _mm512_load_si512(permA[i]);
_mm512_i32scatter_epi32(permA[i], perm, ident, 4);
}
#else
uint32_t permAsingle[16] __attribute__ ((aligned(64)));
puts("store & permute");
for (long t = 0; t < REPEATS; t++)
for (long i = 0; i < ARRAYSIZE; i++) {
perm = _mm512_load_si512(permA[i]);
_mm512_store_si512(permAsingle, perm);
uint32_t *permAVec = permA[i];
for (int e = 0; e < 16; e++)
permAVec[permAsingle[e]] = e;
}
#endif
FILE *f = fopen("testperm.dat", "w");
fwrite(permA, ARRAYSIZE, 64, f);
fclose(f);
I use an array of permutation patterns which are modified sequentially without dependencies.
These are the results:
scatter
4.241u 0.002s 0:04.26 99.5% 0+0k 80+128io 0pf+0w
store & permute
5.956u 0.002s 0:05.97 99.6% 0+0k 80+128io 0pf+0w
So throughput is better when using the scatter command.
I had the same problem, but in the opposite direction: destination indices were easy to compute, but source indices were required for the application of SIMD permute instructions. Here's a solution for AVX-512 using a scatter instruction as suggested by Peter Cordes; it should also apply to the opposite direction:
__m512i ident = _mm512_set_epi32(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0);
__m512i perm = _mm512_set_epi32(7,9,3,0,5,8,13,11,4,2,15,1,12,6,10,14);
uint32_t id[16], in[16], out[16];
_mm512_storeu_si512(id, ident);
for (int i = 0; i < 16; i++) printf("%2d ", id[i]); puts("");
_mm512_storeu_si512(in, perm);
for (int i = 0; i < 16; i++) printf("%2d ", in[i]); puts("");
_mm512_i32scatter_epi32(out, perm, ident, 4);
for (int i = 0; i < 16; i++) printf("%2d ", out[i]); puts("");
An identity mapping ident is distributed to the out array according to the index pattern perm. The idea is basically the same as the one described for inverting a permutation. Here's the output:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
14 10 6 12 1 15 2 4 11 13 8 5 0 3 9 7
12 4 6 13 7 11 2 15 10 14 1 8 3 9 0 5
Note that I have permutations in the mathematical sense (no duplicates). With duplicates, the out store needs to be initialized since some elements could remain unwritten.
I also see no easy way to accomplish this within registers. I thought about cycling through the given permutation by repeatedly applying a permute instruction. As soon as the identity pattern is reached, the one before is the inverse permutation (this goes back to the idea by EOF on unzip operations). However, the cycles can be long. The maximum number of cycles that may be required is given by Landau's function which for 16 elements is 140, see this table. I could show that it possible to shorten this to a maximum of 16 if the individual permutation subcycles are frozen as soon as they coincide with the identity elements. The shortens the average from 28 to 9 permute instructions for a test on random permutation patterns. However, it is still not an efficient solution (much slower than the scatter instruction in the throughput benchmark described in my other answer).
I'm recently checking out C for a friend having problems with it for school. As I only have learned java and C#, though it would be easy. But currently stuck on this.
I have a project reading a small bmp (512x512) image. I've managed to change some colors on it and have it rotated (both horizontal as vertical). Though I'm stuck with the -90° rotation.
1. ROTATION (512x512)
Currently I have this code (both getPixel and setPixel are my own functions):
typedef struct _bitmap {
char file_path[PATH_MAX+1];
char magic_number[3];
unsigned int size;
unsigned char application[5];
unsigned int start_offset;
unsigned int bitmapHeaderSize;
unsigned int width;
unsigned int height;
unsigned short int depth;
unsigned char* header;
PIXEL* raster;
} BITMAP;
void rotate(BITMAP* bmp) {
int i;
int j;
PIXEL* originalPixel;
BITMAP* originalBmp;
deepCopyBitmap(bmp, originalBmp);
for(j=1; j <= bmp->height; j++) {
for(i=1; i <= bmp->width; i++) {
originalPixel=getPixel(originalBmp->raster, bmp->width, bmp->height, j, i);
setPixel(bmp->raster, bmp->width, bmp->height, (bmp->width + 1 - i), j, originalPixel);
}
}
}
void deepCopyBitmap(BITMAP* bmp, BITMAP* copy) {
*copy = *bmp;
if (copy->raster) {
copy->raster = malloc(copy->height * sizeof(*copy->raster));
for (int i = 0; i < copy->height; i++) {
copy->raster[i] = malloc(copy->width * sizeof(*copy->raster[i]));
memcpy(copy->raster[i], bmp->raster[i], copy->width * sizeof(*copy->raster[i]));
}
}
}
indirection requires pointer operand ('PIXEL' (aka 'struct _pixel') invalid)
copy->raster[i] = malloc(copy->width * sizeof(*copy->raster[i]));
^~~~~~~~~~~~~~~~
indirection requires pointer operand ('PIXEL' (aka 'struct _pixel') invalid)
memcpy(copy->raster[i], bmp->raster[i], copy->width * sizeof(*copy->raster[i]));
^~~~~~~~~~~~~~~~
expanded from macro 'memcpy' __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))
This correctly rotates the first diagonal part of the image, but the second part is totally wrong (having two times a part of the first diagonal).
I think the problem is, swapping pixels around and halfway I'm starting to swap already swapped pixels. So I tried to duplicate my bmp, to a original bitmap (originalBmp) and one rotated (rotatedBmp). Though I think it just copies the reference. Anyone has an idea how I create a duplicate bmp?
As example (sorry for the flue img): I want the vertical lines (left), to turn -90deg, so it becomes horizontal lines (right). Though the left diagonal part is correct. But the right part of the diagonal is incorrect copying a piece of the left diagonal. I think because it swaps pixels that are already swapped in the bmp file.
2. ROTATION (512x1024)
What happens if the height or width is the double of the other? Anyone knows how to start on this?
3. ZOOM (200%)
Anyone know how to do this? Get the center pixels of the bitmap, and make them twice at the start of the image, or is there a better/cleaner solution?
1 2 3 4 5 6 7 8 3 3 4 4 5 5 6 6
2 2 3 4 5 6 7 8 3 3 4 4 5 5 6 6
3 3 3 4 5 6 7 8 4 4 4 4 5 5 6 6
4 4 4 4 5 6 7 8 4 4 4 4 5 5 6 6
5 5 5 5 5 6 7 8 5 5 5 5 5 5 6 6
6 6 6 6 6 6 7 8 5 5 5 5 5 5 6 6
7 7 7 7 7 7 7 8 6 6 6 6 6 6 6 6
8 8 8 8 8 8 8 8 6 6 6 6 6 6 6 6
From your code it seems clear that both originalBmpand bmp are pointers to some BMP-type. So when you do originalBmp=bmp;, you just get two pointers pointing to the same BMP, i.e. they operate on the same data.
I assume you have something like
struct BMP
{
// ....
};
If that is the case you can make a copy like this:
struct BMP originalBmp = *bmp;
When using originalBmp you must use the . notation, e.g. originalBmp.raster
EDIT An alternative approach
Instead of making a copy of the original bmp you could do the rotation directly on the original. Each rotation will involve 4 locations. You can copy the 4 locations into temp variables first and then write them to their final location.
For a simple matrix it could be something like this:
#include <stdio.h>
#define WIDTH 4
// display function
void d(int t[WIDTH][WIDTH])
{
int i, j;
for (i=0; i<WIDTH;i++)
{
for (j=0; j<WIDTH; j++)
{
printf("%d ", t[i][j]);
}
printf("\n");
}
}
int main(void) {
int org[WIDTH][WIDTH];
int i, j;
// Just initialize the matrix
for (i=0; i<WIDTH;i++)
{
for (j=0; j<WIDTH; j++)
{
org[i][j] = 10 + i*5 + j;
}
}
printf("Original\n");
d(org);
// Rotate the matrix
for (j=0; j < (WIDTH/2); j++)
{
for (i=0; i < ((WIDTH+1)/2); i++)
{
int t1 = org[j][i];
int t2 = org[i][WIDTH-1-j];
int t3 = org[WIDTH-1-j][WIDTH-1-i];
int t4 = org[WIDTH-1-i][j];
org[j][i] = t2;
org[i][WIDTH-1-j] = t3;
org[WIDTH-1-j][WIDTH-1-i] = t4;
org[WIDTH-1-i][j] = t1;
}
}
printf("Rotated\n");
d(org);
return 0;
}
This will output:
Original
10 11 12 13
15 16 17 18
20 21 22 23
25 26 27 28
Rotated
13 18 23 28
12 17 22 27
11 16 21 26
10 15 20 25
Change to #define WIDTH 5 and it will output:
Original
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
25 26 27 28 29
30 31 32 33 34
Rotated
14 19 24 29 34
13 18 23 28 33
12 17 22 27 32
11 16 21 26 31
10 15 20 25 30
Update. Now the junk is removed from the end of the shared file, but ther is still som "junk" in the middle of the file where process 0 ends writing and process 1 starts writing:
10 4 16 16 0 2 2 3 1 3 4 2 4 5 1 0 4 6 2 8 5 3 8 10 4 9 5 4 ^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#10 4 16 16 1 2 6 0 3 5 2 2 2 8 1 5 6 5 6 6 4 8 9 7 6 2 1 3 6 4 10 2 5 7 7 6 10 6 5 9 9 10 6 7 5 8
However if i count the the jiberish, i get to 40. When i try to do;
offset = (length-40)*my_rank;
It works, but it is not a very scalable and robust solution. Therfor i need to compute this number for a more generell solution. Does anybody see how can be done, here is my current function:
#define MAX_BUFF 50
int write_parallel(Context *context, int num_procs, int my_rank, MPI_Status status){
int written_chars = 0;
int written_chars_accumulator = 0;
int n = context->n;
void * charbuffer = malloc(n*MAX_BUFF);
if (charbuffer == NULL) {
exit(1);
}
MPI_File file;
MPI_Offset offset;
MPI_File_open(MPI_COMM_WORLD,"test_write.txt",
MPI_MODE_CREATE|MPI_MODE_WRONLY,
MPI_INFO_NULL, &file);
written_chars = snprintf((char *)charbuffer, n*MAX_BUFF, "%d %d %d %d\n", n, context->BOX_SIDE, context->MAX_X, context->MAX_Y);
if (written_chars < 0){ exit(1); }
written_chars_accumulator += written_chars;
int i,j;
for(i=0;i<n;i++){
if(context->allNBfrom[i]>0){
written_chars = snprintf((char *)charbuffer+written_chars_accumulator, (n*MAX_BUFF - written_chars_accumulator), "%d %d %d ", i, context->x[i], context->y[i]);
if (written_chars < 0){ exit(1); }
written_chars_accumulator += written_chars;
for(j=0;j<context->allNBfrom[i];j++){
written_chars = snprintf((char *)charbuffer+written_chars_accumulator, (n*MAX_BUFF - written_chars_accumulator), "%d ", context->delaunayEdges[i][j]);
if (written_chars < 0){ exit(1); }
written_chars_accumulator += written_chars;
}
written_chars = snprintf((char *)charbuffer+written_chars_accumulator, (n*MAX_BUFF - written_chars_accumulator), "\n");
if (written_chars < 0){ exit(1); }
written_chars_accumulator += written_chars;
}
}
int length = strlen((char*)charbuffer);
offset = (length-40)*my_rank; //Why is this correct? the constant = 40 needs to be computet in some way...
//printf("proc=%d:\n%s",my_rank,charbuffer);
MPI_File_seek(file,offset,MPI_SEEK_SET);
MPI_File_write(file,charbuffer,length,MPI_CHAR,&status);
MPI_File_close(&file);
return 0;
}
Her is my current result, with this solution which is also correct: 10 4 16 16 0 2 2 3 1 3 4 2 4 5 1 0 4 6 2 8 5 3 8 10 4 9 5 4 10 4 16 16 1 2 6 0 3 5 2 2 2 8 1 5 6 5 6 6 4 8 9 7 6 2 1 3 6 4 10 2 5 7 7 6 10 6 5 9 9 10 6 7 5 8
But it will not scale because, I dont know how to compute number of jiberish elemtens. Does anybody have a clue ?
If I understand your code your goal is to remove the NULL-chars in between your text blocks. In this parallel writing approach there is no way to solve this without violating the safe boundaries of your buffers. None of the threads now how long the output of the other threads is going to be in advance. This makes it hard (/impossible) to have dynamic ranges for the write offset.
If you shift your offset then you will be writing in a aria not reserved for that thread and the program could overwrite data.
In my opinion there are two solutions to your problem of removing the nulls from the file:
Write separate files and concatenate them after the program is finished.
Post-process your output-file with a program that reads/copy chars form your output-file and skips NULL-bytes (and saves the result as a new file).
offset = (length-40)*my_rank; //Why is this correct? the constant = 40 needs to be computet in some way...
The way you compute this is with MPI_Scan. As others have pondered, you need to know how much data each process will contribute.
I'm pretty sure I've answered this before. Adapted to your code, where each process has computed a 'length' of some string:
length = strlen(charbuffer);
MPI_Scan(&length, &new_offset, 1, MPI_LONG_LONG_INT,
MPI_SUM, MPI_COMM_WORLD);
new_offset -=length; /* MPI_Scan is inclusive, but that
also means it has a defined value on rank 0 */
MPI_File_write_at_all(fh, new_offset, charbuffer, length, MPI_CHAR, &status);
The important feature of MPI_Scan is that it runs through your ranks and applies an operation (in this case, SUM) over all the preceding ranks. Afte r the call, Rank 0 is itself. Rank 1 holds the sum of itself and rank 0; rank 2 holds the sum of itself, rank 1 and rank 0... and so on.