1

I've been looking for an answer for this but could not find it. I'm not trying to use ^ as a power operator.

Here's my problem. I'm trying to reproduce an interleaver from a digital TV standard (physical layer protocol). It is a project for school. Here's the code I have so far in C:

#include <sys/io.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <complex.h>
#include <math.h>

int main()
{
    int Mmax = 32768; 
    int Nr = log10(Mmax)/log10(2);
    printf("Nr = %i \n",Nr);

    int Lfm = 42; 

    int i,j,k,l; 

    // Create array R'i 
    unsigned char Rli[Mmax][Nr];
    for (i = 0; i < Mmax; i++)
        memset(Rli[i], 0, sizeof(unsigned char)*(Nr));

    for (i = 0; i < Mmax; i++)
    {
        for(j = 1; j < Nr; j++)
        {
            if(i == 0 || i == 1)
            {
                Rli[i][j] = 0;
            }

            else if(i == 2)
            { 
                Rli[i][j] = 0;
                if(j == Nr - 2)
                    Rli[i][j] = 1;
            }

            else
            {
                Rli[i][j+1] = Rli[i-1][j]; 
            }
        }

        if(i > 2)
        {
            Rli[i][1] = (((Rli[i-1][14] ^ Rli[i-1][13] ) ^ Rli[i-1][12] ) ^ Rli[i-1][2]);
        }
        Rli[i][0] = 0;
    }

    // wire permutation for array R'i - creates array Ri

    unsigned char Ri[Mmax][Nr];
    for (i = 0; i < Mmax; i++)
        memset(Ri[i], 0, sizeof(unsigned char)*(Nr));   

    for (i = 0; i < Mmax; i++)
    {
        Ri[i][1] = Rli[i][8]; //Rli[i][7];
        Ri[i][2] = Rli[i][9]; //Rli[i][8];
        Ri[i][3] = Rli[i][14]; //Rli[i][13];
        Ri[i][4] = Rli[i][4]; //Rli[i][3];
        Ri[i][5] = Rli[i][6]; //Rli[i][5];
        Ri[i][6] = Rli[i][13]; //Rli[i][12];
        Ri[i][7] = Rli[i][3]; //Rli[i][2];
        Ri[i][8] = Rli[i][2]; //Rli[i][1];
        Ri[i][9] = Rli[i][12]; //Rli[i][11];
        Ri[i][10] = Rli[i][5]; //Rli[i][4];
        Ri[i][11] = Rli[i][10]; //Rli[i][9];
        Ri[i][12] = Rli[i][11]; //Rli[i][10];
        Ri[i][13] = Rli[i][1]; //Rli[i][0];
        Ri[i][14] = Rli[i][7]; //Rli[i][6];
    }

    // Offset generator Gk

    int Gmax = floor(Lfm/2);
    unsigned char Gk[Gmax][Nr];
    for (i = 0; i < Gmax; i++)
        memset(Gk[i], 0, sizeof(unsigned char)*Nr-1);

    for (k = 0; k < Gmax; k++)
    {
        for(j = 0; j < Nr; j++)
        {
            if(k == 0)
            { 
                Gk[k][j] = 1; 
            }

            else
            { 
                Gk[k][j+1] = Gk[k-1][j];
            }
        } 

        if(k > 0)
        { 
            Gk[k][0] = ( Gk[k-1][14] ^ Gk[k-1][13] );
        }

    }

    // interleaving sequence

    int Ndata = 26303; // numero de data 
    unsigned char Hl[Ndata];
    double H1[Ndata], H2[Ndata];
    memset(Hl, 0, sizeof(unsigned char)*Ndata);
    memset(H1, 0, sizeof(double)*Ndata);
    memset(H2, 0, sizeof(double)*Ndata);

    int p,indice;

    // loop from page 107 of the physical layer protocol.
    for (i = 0; i < Lfm; i++) 
    {
        for (k = 0; k < Mmax; k++) 
        {
            p = 0;
            for (j = 0; j < Nr; j++) // sum
            {
                if(j >= 0 && j <= Nr - 2)
                    H1[p] += Ri[k][j]*pow(2,j);
                else if(j >= 0 && j <= Nr - 1)
                    {
                    indice = floor(i/2);
                    H2[p] += Gk[indice][j]*pow(2,j);
                    }
            }
    /*****/ Hl[p] = ((i % 2)*pow(2,Nr-1) + H1[p] ) ^ H2[p]; /*****/
            if (Hl[p] < Ndata)
                p += 1;
        }
    }

the line between the /*****/ in the end generates an error when I try to compile.

freqint.c:146:43: error: invalid operands to binary ^ (have ‘double’ and ‘double’)

        Hl[p] = ((i % 2)*pow(2,Nr-1) + H1[p] ) ^ H2[p];

I want to do the XOR operation there, but I can't get it right.

I'm taking this from here.

the interleaving sequence is on the bottom of page 107

How do I write my code to avoid that error message and still do an XOR?

iehrlich
  • 3,572
  • 4
  • 34
  • 43
  • 1
    That one the guy wants to use the operand ^ as a power operator. Not what I need :( – Victor Morales Dionisio Nov 30 '16 at 19:28
  • 1
    Why not cast the values to integer types before performing the XOR operation? Are you expecting them to have non-zero fractional components? – eddiem Nov 30 '16 at 19:28
  • 1
    you're being pretty sloppy with mixing floating point and integer operations. Did you get Nr=15 like it's supposed to? If so, you got lucky, because `log10(Mmax)/log10(2)` is inexact and will round down. At the bottom, don't say `pow(2,Nr-1)` -- that produces a double and is pretty expensive. Say `1<<(Nr-1)`, which produces an int and is very fast. – Matt Timmermans Nov 30 '16 at 19:30
  • 3
    And throughout the whole thing you don't need to use any doubles at all. floor(i/2) == (i>>1). pow(2,j) == 1< – Matt Timmermans Nov 30 '16 at 19:34
  • You could avoid being harmed by rounding error in your computation of `Nr` by computing it like so: `log10(Mmax + 0.5) / log10(2)`, at least as long as the expected result is not more than about 50. On the other hand, in your particular code there's no reason to *compute* `Nr` at all; if `Mmax` is always 32768 then you might as well just write `Nr = 15`. – John Bollinger Nov 30 '16 at 19:49
  • Thank you guys! I was able to undestand with your comments! – Victor Morales Dionisio Nov 30 '16 at 20:11

1 Answers1

5

As was stated in the comments, the ^ operator can't be used on a double, however you don't need to use double.

You're using two functions which return a double, namely pow and floor.

Each time you call pow, you pass 2 for the base. Raising 2 to a power can be done much more efficiently by left shifting the value 1 by the exponent.

Similarly, each time you call floor you're dividing an integer value by 2. Since integer division automatically drops the remainder of division (assuming you're working only with positive values), the call to floor doesn't buy you anything.

So change all instances of pow(2,x) to (1 << x), and change all instances of floor(x/2) to (x/2). Then you can declare H1 and H2 as arrays of unsigned int and you will be able to use the XOR operator ^.

dbush
  • 205,898
  • 23
  • 218
  • 273