Bit array in CUDA - c

Am implementing Sieve of Eratosthenes in CUDA and am having a very weird output. Am using unsigned char* as the data structure and using the following macros to manipulate the bits.
#define ISBITSET(x,i) ((x[i>>3] & (1<<(i&7)))!=0)
#define SETBIT(x,i) x[i>>3]|=(1<<(i&7));
#define CLEARBIT(x,i) x[i>>3]&=(1<<(i&7))^0xFF;
I set the bit to denote it's a prime number, otherwise it's = 0.
Here is where i call my kernel
size_t p=3;
size_t primeTill = 30;
while(p*p<=primeTill)
{
if(ISBITSET(h_a, p) == 1){
int dimA = 30;
int numBlocks = 1;
int numThreadsPerBlock = dimA;
dim3 dimGrid(numBlocks);
dim3 dimBlock(numThreadsPerBlock);
cudaMemcpy( d_a, h_a, memSize, cudaMemcpyHostToDevice );
cudaThreadSynchronize();
reverseArrayBlock<<< dimGrid, dimBlock >>>( d_a, primeTill, p );
cudaThreadSynchronize();
cudaMemcpy( h_a, d_a, memSize, cudaMemcpyDeviceToHost );
cudaThreadSynchronize();
printf("This is after removing multiples of %d\n", p);
//Loop
for(size_t i = 0; i < primeTill +1; i++)
{
printf("Bit %d is %d\n", i, ISBITSET(h_a, i));
}
}
p++;
}
Here is my kernel
__global__ void reverseArrayBlock(unsigned char *d_out, int size, size_t p)
{
int id = blockIdx.x*blockDim.x + threadIdx.x;
int r = id*p;
if(id >= p && r <= size )
{
while(ISBITSET(d_out, r ) == 1 ){
CLEARBIT(d_out, r);
}
// if(r == 9)
// {
// /* code */
// CLEARBIT(d_out, 9);
// }
}
}
The output should be:
2, 3, 5, 7, 11, 13, 17, 19, 23, 29
while my output is:
2, 3, 5, 9, 7, 11, 13, 17, 19, 23, 29
If you take a look at the kernel code, if i uncomment those lines i will get the correct answer, which means that there is nothing wrong with my loops or my checking!

Multiple threads are accessing the same word (char) in global memory simultaneously and thus the written result gets corrupted.
You could use atomic operations to prevent this but the better solution would be to alter your algorithm: Instead of letting every thread sieve out multiples of 2, 3, 4, 5, ... let every thread check a range like [0..7], [8..15], ... so that every range's length is a multiple of 8 bits and no collisions occur.

I would suggest replacing the macros with methods to start with. You can use methods preceded by __host__ and __device__ to generate cpp and cu specific versions where necessary. That will eradicate the possibility of the pre-processor doing something unexpected.
Now just debug the particular code branch that is causing the wrong output, checking that each stage is correct in turn and you'll find the problem.

Related

Finding integer divisors of a set of numbers in C language

I want to do this in a function: How do I find out in a C program if a number is divisible by 2, 3, 4, 5, 6, 8, 9, 25 and 125 without using the % operator and using the divisibility rules? the base should be 10*
To use divisibility rules, you have to work with digits. Perhaps task assumes no division (at least in explicit form - you can extract digits from string representation)
For divisibility by 2, check whether the last digit is in set 0,2,4,6,8
For divisibility by 4, check whether the last digit + doubled previous one is in set 0,4,8. If result is larger than 10, repeat (88=>2*8+8=24=>2*2+4=8)
Similar situation for 8, but sum last + 2*previous + 4*second_from_the_end (512 => 4*5+2*1+2=24=>2*2+4=8)
For divisibility by 5, check whether the last digit is in set 0,5, similar situation for 25, 125
For divisibility by 3, sum all digits, repeat process until result becomes < 10. So-called "digit root" should be in set 0,3,6,9, similar situation for divisibility by 9.
For 6 check divisibilty by both 2 and by 3
I am not strong in C, so my example perhaps is very weird (ideone check)
#include <stdio.h>
int divby3(int n) {
char s[10];
do {
sprintf(s, "%d", n); //transform 72 to char buffer "72"
n = 0;
int i = 0;
while(s[i]) //until nil (end of string) found, we can also use for loop
n += s[i++] - 0x30; //get difference of current char and char "0"
}
while (n >= 10); //until 1-digit value
return (n==0) || (n==3) || (n==6) || (n==9);
}
int divby5(int n) {
char s[10];
int len = sprintf(s, "%d", n);
n = s[len - 1] - 0x30; //last digit
return (n==0) || (n==5);
}
int main(void) {
printf("%d", divby3(72)); //try 71
return 0;
}
A function that uses the a - (a / b * b) implementation of the modulus operator: (credit #MikeCat)
bool isDivisible(int a, int b)
{
if((a - (a / b * b)) == 0) return true;
return false;
}
Usage:
int main(void)
{
int a = 8;
int b = 4;
int c = 3;
bool res = isDivisible(a,b);
bool res2 = isDivisible(a,c);
return 0;
}
EDIT - to address question in comments:
"how can i represent such a program with the divisibility rules? Thank you for your code, i forgott to mention that i have to use the divisibility rules in each function"
The following shows how to pass in divisibility rules as an argument...
const int div_1[] = {2, 3, 4, 5, 6, 8, 9, 25, 125};
const int div_2[] = {7, 5, 17, 12, 11};
int main()
{
size_t size = 0;
size = sizeof div_1/sizeof div_1[0];
bool res = isDivisible(2*3*4*5*6*8*9*25*125, div_1, size);
size = sizeof div_2/sizeof div_2[0];
bool res2 = isDivisible(125, div_2, size);
return 0;
}
// numerator divisor array array size
bool isDivisible(long a, long div_rules[], size_t size)
{
//divisibility rules
const int divisors[] = {2, 3, 4, 5, 6, 8, 9, 25, 125};
for(int i = 0; i<size;i++)
{
if((a - (a / div_rules[i] * div_rules[i])) != 0) return false;
}
return true;
}

Failed add up elements in the array in parallel with several strides MPI

I am trying to parallelly add up the elements from the array. I got an example for the algorithm that I follow to add up the elements with different strides in the array:
input = [3,10,1,22,8,28,4,53,4,4,0,4,0,0,0,57]
First Stride (Add every N/2^1 to N/2^1 + N/2^(1+1):
input = [ 3,10,1,22,8,28,4,53,4,4,0,57,0,0,0,57]
Second Stride (Add every N/2^2 to N/2^2 + +N/2^(2+1):
input = [3,10,1,22,8,50,4,53,4,57,0,57,0,57,0,57]
Third Stride (Add every N/2^3 to N/2^3 + N/2^(3+1):
input = [3,10,11,22,30,50,54,53,57,57,57,57,57,57,57,57]
I wrote the code to distribute the adding work equally to my processors. (To be noted that I am trying to avoid using MPI_Scan)
The processor each has a temp value which means the changed array value and MPI_Gather it back to root, then the root will change the whole input array and MPI_cast the input to each processor to do the adding work again before entering the next stride.
However, my result does not seem to work as I want. I would appreciate if anyone can tell me what I did wrong in my codes.
Here is my code: (Updated)
int DownPhaseFunction(int* input, int size_per_process, int rank, int totalarray, int size, int* Temp0)
{
//rank is the id of processor
//size is the total number of processors
int temp =0;
int index = 0;
int index0 = 0;
//First Stride
if(rank == 0)
{
input[(totalarray)-(totalarray/2)+(totalarray/4)-1] += input[(totalarray)-(totalarray/2)-1];
}
MPI_Bcast(input,totalarray,MPI_INT,0,MPI_COMM_WORLD);
//Start with Second Stride to the end
for (int i=4 ; i<totalarray ; i*=2)
{
//if the number of elements to be changed is larger than total size of processors, do a few more strides
for(int j=0;j<=i;j+=(size*totalarray/i))
{
index = ( (rank+1)*totalarray/i) + j;
if (index != totalarray)
{
temp = input[(index+(totalarray/i)/2)-1] + input[index-1];
}
else
{
temp = input[index-1];
}
//Gather the changed elements back to root
MPI_Gather (&temp, size , MPI_INT, Temp0, size, MPI_INT,0,MPI_COMM_WORLD );
//Let root change the changed elements in the input array
if(rank == 0)
{
for(int r=0; r<size; r++)
{
index0 = ((r+1)*totalarray/i)+j;
if( (index0) != totalarray)
{
input[(index0+(totalarray/i)/2-1)] = Temp0[r];
}
}
}
//send it back to every processor to do the next stride
MPI_Bcast(input,totalarray,MPI_INT,0,MPI_COMM_WORLD);
}
}
return(*input);
}
The processor each has a temp value which means the changed array
value and MPI_Gather it back to root, then the root will change the
whole input array and MPI_Bcast the input to each processor to do the
adding work again before entering the next stride.
IMO this design complicates matters. I would suggest to first explicitly set boundaries of the input array range that each process is allowed to work. For an input of 16 it would be as follows:
Process 0 works from [0 to 4[
Process 1 works from [4 to 8[
Process 2 works from [8 to 12[
Process 3 works from [12 to 16[
to calculate those ranges one can use the following formula:
int begin = rank * size_per_process;
int end = (rank + 1) * size_per_process;
To implement the remains logic we start by having a loop that begins by splitting the array in half, and for each iteration we keep splitting in halves.
int split_size = totalarray/2;
while(split_size > 1){
//....
split_size = split_size/2;
}
We need an additional loop to iterate over input array using the current split size, namely:
for(int i = split_size; i < totalarray; i+= split_size){
//...
}
Each rank will only be allowed to work on the array interception assigned to that process, namely:
for(int i = split_size; i < totalarray; i+= split_size){
int dest = i + (split_size/2) - 1;
if(begin <= dest && dest < end)
input[dest] += input[i -1];
}
A more improved (but less readable) version:
int shift = (split_size/2) - 1;
int dest = ((begin == 0) ? split_size : (split_size/begin) * split_size) + shift;
for(; dest < end; dest += split_size)
input[dest] += input[dest - shift -1];
After each stride all processes send their array interception to the other processes:
MPI_Allgather(MPI_IN_PLACE, size_per_process, MPI_INT, input, size_per_process, MPI_INT, MPI_COMM_WORLD);
The MPI_IN_PLACE ensures that the new input array (resulted from gathering the work done by all processes) replaces the old input array. For an input of 16 elements and 4 processes, the process 0, 1, 2, and 3 will send the elements [0 to 4[, [4 to 8[, [8 to 12[, and [12 to 16[ of their input arrays to all the other processes, respectively. Consequently, at the end of the MPI_Allgather call, every process has the most update input array with all the part that were changed by the processes during the current iteration.
So for the input = [3,10,1,22,8,28,4,53,4,4,0,4,0,0,0,57] with 4 processes the iterations will look like the following:
First stride:
Process 2 input[11] += input[7] (input[11] = 4 + 53)
input array: [3, 10, 1, 22, 8, 28, 4, 53, 4, 4, 0, 57, 0, 0, 0, 57]
Second stride:
Process 1 input[5] += input[3] (input[5] = 28 + 22)
Process 2 input[9] += input[7] (input[9] = 4 + 53)
Process 3 input[13] += input[11] (input[13] = 0 + 57)
input array: [3, 10, 1, 22, 8, 50, 4, 53, 4, 57, 0, 57, 0, 57, 0, 57]
Third stride:
2, Process 0 input[2] += input[1] (input[2] = 1 + 10)
2, Process 1 input[4] += input[3] (input[4] = 8 + 22)
2, Process 1 input[6] += input[5] (input[6] = 4 + 50)
2, Process 2 input[8] += input[7] (input[8] = 4 + 53)
2, Process 2 input[10] += input[9] (input[10] = 0 + 57)
2, Process 3 input[12] += input[11] (input[12] = 0 + 57)
2, Process 3 input[14] += input[13] (input[14] = 0 + 57)
input = [3, 10, 11, 22, 30, 50, 54, 53, 57, 57, 57, 57, 57, 57, 57, 57]
A complete running example:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void printArray(int *array, int size){
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if(rank == 0){
for(int i = 0; i < size; i++)
printf("%2d ", array[i]);
printf("\n");
}
}
int main(int argc, char **argv){
int totalarray = 16;
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int input[16] = {3,10,1,22,8,28,4,53,4,4,0,4,0,0,0,57};
printArray(input, totalarray);
int size_per_process = totalarray/size;
int begin = rank * size_per_process;
int end = (rank + 1) * size_per_process;
int split_size = totalarray/2;
while(split_size > 1){
int shift = (split_size/2) - 1;
int dest = ((begin == 0) ? split_size : (split_size/begin) * split_size) + shift;
for(; dest < end; dest += split_size)
input[dest] += input[dest - shift -1];
MPI_Allgather(MPI_IN_PLACE, size_per_process, MPI_INT, input, size_per_process, MPI_INT, MPI_COMM_WORLD);
split_size = split_size/2;
}
printArray(input, totalarray);
MPI_Finalize();
return 0;
}
Input : {3,10,1,22,8,28,4,53,4,4,0,4,0,0,0,57}
Output: {3,10,11,22,30,50,54,53,57,57,57,57,57,57,57,57}
Bear in mind that this is a toy example of the proposed design; not bulletproof ready to use in production type of code.

Interview Question: Longest Prefix That Contains An Equal Number Of Two Integers

I attempted to solve the following question in an online assessment for a technical interview, and failed. I have been thinking about the problem for a while now, and can't seem to find an answer that satisfies me:
You are looking for the longest leading fragment (prefix) of an array A in which there is an equal number of occurrences of X, and Y, where X and Y are integers.
For example, where X=7 and Y=42, the longest prefix where A=[6, 42, 11, 7, 1, 42] would be 4, because A[0]-A[4] contain the same number of X and Y.
Another example, X=6 and Y=13.
A=[13,13,1,6]. The function should return -1, because there is no prefix.
X=100, Y=63, and A=[100,63,1,6,2,13] should return 5.
My attempt at an answer in C:
int solution(int X, int Y, int A[], int N){
int result=-1;
int nX=0; //number of occurrences of X
int nY=0; //number of occurrences of Y
int i;
for(i=0;i<N;i++){//loop through the input array
if(A[i]==X)//occurrence of X
nX += 1;
/*
EDGE CASE BELOW: this should have been an if
statement, because X and Y could be the same
number. I know I missed this in the assessment,
but believe there is another issue, because I
failed almost all the test cases generated by the
assessment.
*/
else if(A[i]==Y)//occurrence of Y
nY += 1;
if((nX!=0)&& (nX==nY))//same number of X and Y
//and there is at least one occurence of each
result=i;//longest prefix is the index
}
return result;
}
Unfortunately, I was not able to generate a test case myself that failed, and the failure test cases are hidden on the assessment. Thus I can't provide much information that would be helpful.
I do know, that every time I failed, my program returned a -1 instead of the correct answer.
If any of you can see something wrong just through thinking through it, I would love to see what I am missing. Thanks!
If you've accurately described the requirements, then they don't specify an equal positive number of occurrences of X and Y. Zero is valid.
So this:
if((nX!=0)&& (nX==nY))//same number of X and Y
//and there is at least one occurence of each
result=i;//longest prefix is the index
}
should be this:
if(nX==nY)//same number of X and Y
result=i;//longest prefix is the index
}
without the check for nX!=0. So if X doesn't appear in the array and/or Y doesn't appear in the array, your code returns āˆ’1 unnecessarily.
Additionally, the requirements don't seem to guarantee that X and Y are distinct; if they're not, then your code returns āˆ’1, but according to a literal reading of the requirements, the answer would be Nāˆ’1.
After seeing your requirements and answers there is another change required to your code #Joshua.
The answer from #ruakh is also right but need one more change to handle other test cases.
You have to replace the "else if" condition to "if" condition for the occurrence of Y as shown in below code:
for(i=0;i<N;i++){
if(A[i]==X)
nX += 1;
if(A[i]==Y) //occurrence of Y
nY += 1;
Because, if "X" and "Y" have the same values and only "nX" will be counted, and "nY" is ignored with the "else if" condition. To tackle this situation you have to replace the "else if" condition with the "if" condition.
Sample: X=42, Y=42, and A=[42,63,42,6,2,13]
then with my condition, the above sample is handled perfectly.
I hope my answer solved or added more accuracy to your answer.
For starters never do any assignments in an interview. Interview is not an exam. It is a conversation of two equal participants. Ignore all firms that try to manipulate you and your time such a way.
Secondly, this function declaration
int solution(int X, int Y, int A[], int N);
is a declaration of a beginner.
First of all do not use upper case letters to name parameters.
Secondly the size of the array shall have the type size_t as and the return type of the function.
Thirdly the array should be the first parameter of the function and shall have the qualifier const.
Fourthly, declare variables in the smallest scope where they are used.
The function can be declared as it is shown in the demonstrative program. The function returns 0 if there is no such a prefix. You can change the return value either to the size of the array if there is no the prefix ot to ( size_t ) -1 as you like.
#include <stdio.h>
size_t largest_balanced_seq( const int a[], size_t n, int x, int y )
{
size_t last_index = 0;
for ( size_t i = 0, x_count = 0, y_count = 0; i < n; i++ )
{
x_count += a[i] == x;
y_count += a[i] == y;
if ( x_count != 0 && x_count == y_count )
{
last_index = i;
}
}
return last_index;
}
int main(void)
{
int a[] = { 6, 42, 11, 7, 1, 42 };
printf( "%zu\n", largest_balanced_seq( a, sizeof( a ) / sizeof( *a ), 7, 42 ) );
int b[] = { 100, 63, 1, 6, 2, 13 };
printf( "%zu\n", largest_balanced_seq( b, sizeof( b ) / sizeof( *b ), 100, 63 ) );
return 0;
}
The program output is
4
5
Take into account that it is much better when the function returns the length of the sub-sequence, that is when it specifiers a range like [0, N). For example such an approach is used throughout C++. So who gave you this assignment is not a very high qualified.:)
int solution(int X, int Y, int A[], int N){
int result=-1;
int nX=0; //number of occurrences of X
int nY=0; //number of occurrences of Y
int i;
for(i=0;i<N;i++){//loop through the input array
if(A[i]==X)//occurrence of X
nX += 1;
/*
EDGE CASE BELOW: this should have been an if
statement, because X and Y could be the same
number. I know I missed this in the assessment,
but believe there is another issue, because I
failed almost all the test cases generated by the
assessment.
*/
else if(A[i]==Y)//occurrence of Y
nY += 1;
if((nX!=0)&& (nX==nY))//same number of X and Y
//and there is at least one occurence of each
result=i;//longest prefix is the index
if (X==Y)
result =i;
}---this two lines of code is needed for the code correction
return result;
}
def solution(X, Y, A):
N = len(A)
result = -1
nX = 0
nY = 0
for i in range(N):
if A[i] == X:
nX += 1
if A[i] == Y:
nY += 1
if nX == nY:
result = i
if (X == Y and nX != 0):
break
return result
print( solution(7, 42, [6, 42, 11, 7, 1, 42]) )
print( solution(6, 13, [13, 13, 1, 6]) )
print( solution(100, 63, [100, 63, 1, 6, 2, 13]) )
print( solution(1, 1, [1]) )
print( solution(1, 1, [1, 1, 1]) )
print( solution(1, 1, [1, 2, 1]) )
print( solution(1, 1, [2, 2, 1]) )
print( solution(1, 1, [2, 1, 2]) )
def solution(X, Y, A):
N = len(A)
result = -1
nX = 0
nY = 0
for i in range(N):
if X==Y:
if A[i]==X:
nX += 1
if nX%2==0:
result=i
else:
if A[i] == X:
nX += 1
elif A[i] == Y:
nY += 1
if nX == nY:
result = i
return result
print( solution(7, 42, [6, 42, 11, 7, 1, 42]))
print( solution(6, 13, [13, 13, 1, 6]) )
print( solution(100, 63, [100, 63, 1, 6, 2, 13]) )
print( solution(1, 1, [1]) )
print( solution(1, 1, [1, 1, 1]) )
utput:
4
-1
5
-1
1

Trying to write a program that counts the amount of even numbers in an array and returns the value

I am trying to make a program that will count the number of even numbers in the provided arrays. When I run the program now, it will return the amount of numbers in the array, but not the amount of even numbers. For some reason my count_even function doesn't work. Can anyone help?
#include <stdio.h>
int main()
{
int data_array_1[] = { 1, 3, 5, 7, 9, 11 };
int data_array_2[] = { 2, -4, 6, -8, 10, -12, 14, -16 };
int data_array_3[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
int data_array_4[] = { 6, 2, 4, 5, 1, -9 };
int data_array_5[] = { 1, 3, 9, 23, 5, -2, 4 };
int result_1 = count_even(data_array_1, 6);
printf("data_array_1 has %d even numbers.\n", result_1);
int result_2 = count_even(data_array_2, 8);
printf("data_array_2 has %d even numbers.\n", result_2);
int result_3 = count_even(data_array_3, 11);
printf("data_array_3 has %d even numbers.\n", result_3);
int result_4 = count_even(data_array_4, 6);
printf("data_array_4 has %d even numbers.\n", result_4);
int result_5 = count_even(data_array_5, 7);
printf("data_array_5 has %d even numbers.\n", result_5);
return 0;
}
int count_even(int* data_array, int size)
{
int even_num = 0;
for (int i = 0; i == size; i++)
{
if (data_array[size] % 2 == 0)
{
even_num++;
}
}
return even_num;
}
The condition in your for loop is wrong.
The correct condition should say "as long as the index is smaller than size", but yours say "as long as the index equal to to size".
The condition should be i < size.
As for the result, it seems like it should return 0 (for the non-working code), not size.
Also, you are using size as an index, when you should use i.
In your count_even function, you are using the size attribute as the array index, when it should be i
int count_even(int* data_array, int size)
{
int even_num = 0
for(int i = 0; i <= size, ++i)
{
if(data_array[i] % 2 == 0)
{
even_num++;
}
}
return even_num;
}
these two lines are the root of the problems in the code:
for (int i = 0; i == size; i++)
{
if (data_array[size] % 2 == 0)
the for() statement, should be:
for (int i = 0; i < size; i++)
so the loop exits when reaching the end of the array
the if() statement is always looking at the same entry beyond the end of the array, This is undefined behaviour
The if() statement should be:
if (data_array[i] % 2 == 0)
However, the modulo operator & is not a good choice for negative numbers
a better choice would be:
if ( !(data_array[i] & 1 ) )

How can I average a subset of an array and store the result in another array?

I have a C array fftArray[64] that contains values that I want averaged and placed into another array frequencyBar[8]. Getting the average of the entire array would be easy enough using a for statement.
int average, sum = 0;
for (i = 0; i < 64; i++)
{
sum += fftArray[i];
}
average = sum/64;
But I just can't seem to figure out how to get the average from fftArray[0] through fftArray[8] and store this in frequencyBar[0], the average of fftArray[9] through fftArray[16] and store this in frequencyBar[1], etc. Can anyone help me out with this? Thanks
This looks like a homework assignment, so, rather than give you the outright answer, I'd rather just point you in the right direction...
use a nested loop (one inside the other). One loop cycles 0-7, the other one 0 - 63. Use the smaller one to populate your sliced averages.
or better yet use the % operator to see when you've gone through 8 elements and do an average of your total, then reset the total for the next set. Then you'll have learned how to use the % operator too! :)
[EDIT]
ok, if not homework then something like this... I haven't written C in 5 years, so treat this as pseudo code:
//assuming you have a fftArray[64] with data, as per your question
int i,sum,avCounter,total;
int averages[8];
for(i=0 , avCounter=0, total=0 ; i<64; ){
total += fftArray[i];
if(++i % 8 == 0){ //%gives you the remainder which will be 0 every 8th cycle
averages[avCounter++] = total / 8
total = 0; //reset for next cycle
}
}
I think this will work better than a nested loop... but I'm not sure since % is division which is more processor heavy than addition... however... I doubt anyone would notice :)
int i, j;
for (i = 0; i < 8; i++) {
int sum = 0;
for (j = 0; j < 8; j++) {
sum += fftArray[ 8*i + j ];
}
frequencyBar[i] = sum / 8;
}
Bonus exercise: Optimize this code for speed on your chosen platform.
TF,
DISCLAIMER: This code is just off the top of my head... it hasn't even been compiled, let alone tested.
// returns the average of array[first..last] inclusive.
int average(int[] array, int first, int last) {
int sum = 0;
for (i = first; i <= last; i++)
sum += array[i];
return sum / (last - first + 1); // not sure about the +1
}
Then what you'd do is loop through the indexes of your frequencyBar array [0..7], setting frequencyBar[i] = average(array, first, last);... the tricky bit is calculating the first and last indexes... try i*8 and (i+1)*8 respectively... that may not be exactly right, but it'll be close ;-)
Cheers. Keith.
EDIT: Bored... waiting for my test results to come back. No news is good news, right? ;-)
It turns out that passing the length is a fair bit simpler than passing the last index.
#include <stdio.h>
int sum(int array[], int first, int length) {
int sum = 0;
for (int i = first; i < first+length; i++)
sum += array[i];
return sum;
}
double average(int array[], int first, int length) {
double total = sum(array, first, length);
#ifdef DEBUG
printf("DEBUG: [%2d..%2d] %d", first, first+length-1, array[first]);
for (int i = first+1; i < first+length; i++)
printf(" + %d", array[i]);
printf(" = %d / %d = %f\n", (int)total, length, total/length);
#endif
return total / length;
}
int main(int argc, char* argv[]) {
int array[] = { // average
1, 2, 3, 4, 5, 1, 2, 3, // 2.625
4, 5, 1, 2, 3, 4, 5, 1, // 3.125
2, 3, 4, 5, 1, 2, 3, 4, // 3
5, 1, 2, 3, 4, 5, 1, 2, // 2.875
3, 4, 5, 1, 2, 3, 4, 5, // 3.375
1, 2, 3, 4, 5, 1, 2, 3, // 2.625
4, 5, 1, 2, 3, 4, 5, 1, // 3.125
2, 3, 4, 5, 1, 2, 3, 4 // 3
};
double frequency[8];
for (int i = 0; i < 8; i++)
frequency[i] = average(array, i*8, 8);
for (int i = 0; i < 8; i++)
printf("%f ", frequency[i]);
printf("\n");
}
Watch your sum doesn't wrap around if fftArray has large value in!

Resources