⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gfq_ldpc_ntt.c

📁 LDPC编解码器程序
💻 C
📖 第 1 页 / 共 2 页
字号:
// GFq_LDPC_NTT.c, a GF(q>2) LDPC encoding/decoding simulator,
// powered by NTT (NumberTheoretic Transform, i.e., FFT over GF)
// Only allows GF(2^p), 2<=p<=8
// based on paper of M. C. Davey et al. "Low-Density...over GF(q)" June 1998
// (c) 2005-2006 by Seishi Takamura @ Stanford University / NTT (Nippon Telegraph and Telephone)
// Absolutely no warranty.
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#include <errno.h>

#ifndef Log2Q
  #define Log2Q	5               // GF(2^5)
#endif
#if Log2Q < 1 || Log2Q > 8 
  #error "Log2Q must be 1..8"
#endif

#define Q	(1<<Log2Q)      // GF(Q)

#if Q==4
const int logq[4] = {0,0,1,2};
const int expq[3] = {1,2,3};
#elif Q==8
const int logq[8] = {0,0,1,3,2,6,4,5};
const int expq[7] = {1,2,4,3,6,7,5};
#elif Q==16
const int logq[16] = {0,0,1,4,2,8,5,10,3,14,9,7,6,13,11,12};
const int expq[15] = {1,2,4,8,3,6,12,11,5,10,7,14,15,13,9};
#elif Q==32
const int logq[32] = {0,0,1,18,2,5,19,11,3,29,6,27,20,8,12,23,4,
  10,30,17,7,22,28,26,21,25,9,16,13,14,24,15};
const int expq[31] = {1,2,4,8,16,5,10,20,13,26,17,7,14,28,29,31,
  27,19,3,6,12,24,21,15,30,25,23,11,22,9,18};
#elif Q==64
const int logq[64] = {0,0,1,6,2,12,7,26,3,32,13,35,8,48,27,18,4,24,
  33,16,14,52,36,54,9,45,49,38,28,41,19,56,5,62,
  25,11,34,31,17,47,15,23,53,51,37,44,55,40,10,
  61,46,30,50,22,39,43,29,60,42,21,20,59,57,58};
const int expq[63] = {1,2,4,8,16,32,3,6,12,24,48,35,5,10,20,40,19,
  38,15,30,60,59,53,41,17,34,7,14,28,56,51,37,
  9,18,36,11,22,44,27,54,47,29,58,55,45,25,50,
  39,13,26,52,43,21,42,23,46,31,62,63,61,57,49,33};
#elif Q==128
const int logq[128] = {0,0,1,31,2,62,32,103,3,7,63,15,33,84,104,
  93, 4,124,8,121,64,79,16,115,34,11,85,38,105,46,94,51,
  5,82,125,60,9,44,122,77,65,67,80,42,17,69,116,23,35,118,
  12,28,86,25,39,57,106,19,47,89,95,71,52,110,6,14,83,92,126,
  30,61,102,10,37,45,50,123,120,78,114,66,41,68,22,81,59,43,76,
  18,88,70,109,117,27,24,56,36,49,119,113,13,91,29,101,87,108,
  26,55,40,21,58,75,107,54,20,74,48,112,90,100,96,97,72,98,53,73,111,99};
const int expq[127] = {1,2,4,8,16,32,64,9,18,36,72,25,50,100,65,11,
  22,44,88,57,114,109,83,47,94,53,106,93,51,102,69,3,6,12,24,
  48,96,73,27,54,108,81,43,86,37,74,29,58,116,97,75,31,62,124,
  113,107,95,55,110,85,35,70,5,10,20,40,80,41,82,45,90,61,122,
  125,115,111,87,39,78,21,42,84,33,66,13,26,52,104,89,59,118,101,
  67,15,30,60,120,121,123,127,119,103,71,7,14,28,56,112,105,91,63,
  126,117,99,79,23,46,92,49,98,77,19,38,76,17,34,68};
#elif Q==256
const int logq[256] = {0,0,1,25,2,50,26,198,3,223,51,238,27,104,199,75,4,100,
  224,14,52,141,239,129,28,193,105,248,200,8,76,113,5,138,101,47,225,
  36,15,33,53,147,142,218,240,18,130,69,29,181,194,125,106,39,249,185,
  201,154,9,120,77,228,114,166,6,191,139,98,102,221,48,253,226,152,37,
  179,16,145,34,136,54,208,148,206,143,150,219,189,241,210,19,92,131,
  56,70,64,30,66,182,163,195,72,126,110,107,58,40,84,250,133,186,61,202,
  94,155,159,10,21,121,43,78,212,229,172,115,243,167,87,7,112,192,247,
  140,128,99,13,103,74,222,237,49,197,254,24,227,165,153,119,38,184,180,
  124,17,68,146,217,35,32,137,46,55,63,209,91,149,188,207,205,144,135,151,
  178,220,252,190,97,242,86,211,171,20,42,93,158,132,60,57,83,71,109,65,
  162,31,45,67,216,183,123,164,118,196,23,73,236,127,12,111,246,108,161,59,
  82,41,157,85,170,251,96,134,177,187,204,62,90,203,89,95,176,156,169,160,
  81,11,245,22,235,122,117,44,215,79,174,213,233,230,231,173,232,116,214,
  244,234,168,80,88,175};
const int expq[255] = {1,2,4,8,16,32,64,128,29,58,116,232,205,135,19,38,76,
  152,45,90,180,117,234,201,143,3,6,12,24,48,96,192,157,39,78,156,
  37,74,148,53,106,212,181,119,238,193,159,35,70,140,5,10,20,40,80,
  160,93,186,105,210,185,111,222,161,95,190,97,194,153,47,94,188,101,
  202,137,15,30,60,120,240,253,231,211,187,107,214,177,127,254,
  225,223,163,91,182,113,226,217,175,67,134,17,34,68,136,13,26,52,104,
  208,189,103,206,129,31,62,124,248,237,199,147,59,118,236,197,151,51,
  102,204,133,23,46,92,184,109,218,169,79,158,33,66,132,21,42,84,168,
  77,154,41,82,164,85,170,73,146,57,114,228,213,183,115,230,209,191,99,
  198,145,63,126,252,229,215,179,123,246,241,255,227,219,171,75,150,49,
  98,196,149,55,110,220,165,87,174,65,130,25,50,100,200,141,7,14,28,56,
  112,224,221,167,83,166,81,162,89,178,121,242,249,239,195,155,43,86,172,
  69,138,9,18,36,72,144,61,122,244,245,247,243,251,235,203,139,11,22,44,
  88,176,125,250,233,207,131,27,54,108,216,173,71,142};
#endif


#if Q==2                        // please do not try this (i.e., Log2Q=1)
  #define GF_mul(a, b) ((a)&(b))
#else
int GF_mul(int a, int b)
{
  if (a == 0 || b == 0) return 0;
  if (a == 1) return b;
  if (b == 1) return a;
  return expq[(logq[a] + logq[b]) % (Q-1)];
}
#endif

#define GF_add(a, b) ((a)^(b))
#define GF_sub(a, b) ((a)^(b))

#ifdef LONGLONG
  typedef long long int NTT;    // 8-byte int (for both VC and gcc)
#else
  typedef int NTT;
#endif

// Followings are based on Prof. MacKay's FFT code, but do not work
// in my program, so I changed a little bit (see comments below)
void ntt(NTT p[Q])
{
  int b, factor = 1, rest;
  for (b = 0; b < Log2Q; b++) {
    for (rest = 0; rest < Q/2; rest++) {
      int restH = rest >> b;
      int restL = rest & (factor-1);
      int rest0 = (restH << (b+1)) + restL;
      NTT rest1 = rest0 + factor;
      NTT prest0 = p[rest0];
//      p[rest0] = p[rest1] - p[rest0];
//      p[rest1] += prest0;
      p[rest0] += p[rest1];
      p[rest1] = prest0 - p[rest1];
    }
    factor += factor;
  }
}

int n, m;
int rmax, cmax;
int *row_weight, *col_weight;
int **row_col, **row_N;
int **col_row, **col_N;
int **H;
int ***logra;
int ***logqa;
int ***logracol;
int ***logqacol;
NTT **fQa;
int **isnegative;
int *tmp_z;
int *tmp_x;

#define exp2(x) pow(2.0,x)
#define log2(x) (log(x)/log(2.0))

static unsigned int rndm = 2815UL;
void SRand(int n) {
  rndm = n;
//  srand(n);
}

#define RandMax 0x7fffffffUL
//#define RandMax RAND_MAX
unsigned int Rand(void)
{
//  return rand();
  return rndm = (77UL * rndm + 1243UL) & RandMax; // 31bit
}

#define INT	6/*8*/              // int part
#define DECI	14/*13*/              // fraction part
#define FMUL	(1<<DECI)       // multiplier
#define PREC	(1.0/FMUL)      // precision
#define LEVELS	(1<<(INT+DECI))
static int flog[LEVELS];
static unsigned int _fexp[LEVELS*2], *fexp = &_fexp[LEVELS];

int float2fix(double x)
{
  if (x >= 0) {
    return (int)(x * FMUL + 0.5);
  } else {
    return -(int)((-x) * FMUL + 0.5);
  }
}

unsigned int float2fixu(double x)
{
  return (unsigned int)(x * FMUL + 0.5);
}

#define fix2float(x) ((x)*PREC)

#define exp(x) pow(2, x)
#define log(x) (log(x)/log(2.0))

void initlogexptab2(void)
{
  int i = 1;
  double right = log(fix2float(i) - 0.5*PREC);
  flog[0] = -FMUL*14;//-115000;
  for ( ; i < LEVELS; i++) {
    double d = fix2float(i);
    double left = log(d+0.5*PREC);
    flog[i] = float2fix((4*log(d)+right+left) / 6.0); // Simpson's law
    right = left;
  }
  i = -LEVELS;
  right = exp(fix2float(i) - 0.5*PREC);
  for ( ; i < LEVELS; i++) {
    double d = fix2float(i);
    double expd = exp(d);
    double left = exp(d+0.5*PREC);
    if (expd > (1UL<<(31-DECI)))
      fexp[i] = 1UL<<31;
    else
      fexp[i] = float2fixu((4*expd+right+left) / 6.0); // Simpson's law
    right = left;
  }
}

#if 0
unsigned int Fexp(int x)
{
  if (x < -LEVELS) return 0;
  else if (x >= LEVELS) {
    int i = 0;
    do {
      x -= FMUL;
      i++;
    } while (x >= LEVELS);
    return fexp[x] << i;
  }
  return fexp[x];
}
#else
  #define Fexp(x) fexp[x]
#endif

#if 1
int Flog(int x)
{
  int i;
  if (x <= 0) return -FMUL*14; //-115000
  for (i = 0; x >= LEVELS; i++)
    x >>= 1;
  return flog[x] + (i<<DECI);
}
#else
  #define Flog(x) flog[x]
#endif


int HamDist(int x[], int y[], int len)
{
  int i, j, sum = 0;
  for (i = 0; i < len; i++) {
    int xy = *x++ ^ *y++;
    for (j = 1; j < Q; j <<= 1)
      if ((xy & j) != 0) sum++;
  }
  return sum;
}

double mse(int x[], int y[], int len)
{
  int i;
  double sum = 0;
  for (i = 0; i < len; i++) {
    int s = *x++ - *y++;
    sum += (double)(s*s);
  }
  return sum / len;
}

// y[n] := x[n] + BSC_noise
// logfna[a][n]: log(Prob(x[n]=a | y[n]))
// can only be used for GF(2^b) case
void bsc(int x[], int y[], double p, int **logfna)
{
  int i, len = Log2Q * n;
  int modify = (int)(len * p + 0.5);
  int *err = malloc(sizeof(int) * n);
  double lp, l1p;
  p = modify / (double)len; // correct error probability
  printf("m/n=%g, ", (double)m/n);
  printf("BSC channel capacity(rate) = %g (bits)\n",
         -p*log2(p)-(1-p)*log2(1-p));
  memset(err, 0, sizeof(int) * n);
  // make sure p errors in err[]
  while (modify) {
    i = Rand() % len;
    if ((err[i/Log2Q] & (1<<(i%Log2Q))) != 0) continue;
    err[i/Log2Q] |= (1<<(i%Log2Q));
    modify--;
  }
  memcpy(y, x, sizeof(int) * n);
  for (i = 0; i < n; i++) {
    y[i] ^= err[i];
  }
  free(err);

  lp = log2(p);
  l1p = log2(1-p);
  for (i = 0; i < n; i++) {
    int a, j;
    for (a = 0; a < Q; a++) {
      double logprod = 0;
      for (j = 1; j < Q; j <<= 1) {
        if ((a&j) == (y[i]&j)) logprod += l1p;
        else logprod += lp;
      }
      logfna[i][a] = float2fix(logprod);
    }
  }
}

// y[n] := x[n] + Laplacian_noise
// logfna[n][a]: log(Prob(x[n]=a | y[n]))
// stddev: noise level
void lap(int x[], int y[], double stddev, int **logfna)
{
  int i;
  int count[Q];
  double _logfna[Q];
  double sum;
  memset(count, 0, sizeof(count));
  for (i = 0; i < n; i++) {
    double u2 = (Rand()+1) * (1.0 / (RandMax+1.0)); // uniform(0,1]
    int logu2 = (int)floor(log(u2) * stddev + .5);
    int a;
    sum = 0;
    if ((Rand() & 1) == 0) {
      y[i] = x[i] - logu2;
    } else {
      y[i] = x[i] + logu2;
    }
    // clipping
    if (y[i] < 0) y[i] = 0;
    else if (y[i] >= Q) y[i] = Q-1;
    //
    count[abs(x[i] - y[i])]++;
    //fna
    for (a = 0; a < Q; a++) {
      double dfna;
      //logfna[i][a] = -(abs(y[i] - a))/stddev;
      if (y[i] == a) _logfna[a] = -0.5/*0.2396*//stddev; //l((1-e(-0.5))*2)
      else _logfna[a] = -(abs(y[i] - a)-/*+*/0.0413)/stddev; //l(e(0.5)-e(-0.5))
      dfna = exp2(_logfna[a]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -