#ifndef DECOMPOSITION_H
 #define DECOMPOSITION_H

// 依存: vmul

////////////////////////////////////////////////////////
// 加法的シェアを最下位ビットのシェアとそれ以外のシェアに変換する
// 位数 q は2のべき乗とする
// それ以外のシェアの位数は q/2 となる
// 最下位ビットのシェアの位数は qb になる
////////////////////////////////////////////////////////
_pair share_A2QB_channel(_ a, share_t q, share_t qb, int channel)
{
  if (_party >  2) {
    _pair ans = {NULL, NULL};
    return ans;
  }
  int k = blog(q-1)+1;
  if ((1 << k) != q) {
    printf("share_A2QB: %d is not a power of two\n", (int)q);
  }

  int n = len(a);
  //printf("share_A2QB q = %d qb = %d\n", q, qb);
  _ b = _const(n, 0, qb);
  for (int i=0; i<n; i++) {
    pa_set(b->A, i, (q+pa_get(a->A,i)) % 2); // 加法的シェアの最下位ビット
  }
  _ b1 = _const(n, 0, qb);
  if (_party == 2) {
    for (int i=0; i<n; i++) {
      pa_set(b1->A, i, (q+pa_get(a->A, i)) % 2); // 加法的シェアの最下位ビット
    }
  }
  _ b2 = _const(n, 0, qb);
  if (_party != 2) {
    for (int i=0; i<n; i++) {
      pa_set(b2->A, i, (q+pa_get(a->A, i)) % 2); // 加法的シェアの最下位ビット
    }
  }
  _ bp = vmul_channel(b1, b2, channel);
  //printf("b  "); _print(b);
  //printf("b1 "); _print(b1);
  //printf("b2 "); _print(b2);
  //printf("bp "); _print(bp);
  for (int i=0; i<n; i++) {
    pa_set(b->A, i, (10*qb + pa_get(b->A, i) - 2*pa_get(bp->A, i)) % qb); // b のシェアが両方 1 だと本来は 0 なのに 2 になってしまう
  }


  q = q/2;
  _ x;
  if (q > 1) {

    _ c1 = _const(n, 0, q);
    if (_party == 2) {
      for (int i=0; i<n; i++) {
        pa_set(c1->A, i, (q*4+pa_get(a->A, i)) % 2); // 加法的シェアの最下位ビット !!!
      }
    }
    _ c2 = _const(n, 0, q);
    if (_party != 2) {
      for (int i=0; i<n; i++) {
        pa_set(c2->A, i, (q*4+pa_get(a->A, i)) % 2); // 加法的シェアの最下位ビット
      }
    }
    _ c = vmul_channel(c1, c2, channel);


    x = _const(n, 0, q);

    for (int i=0; i<n; i++) {
      pa_set(x->A, i, ((q*4+pa_get(a->A, i)) / 2) % q); // !!!
    }
    vadd_(x, c);

    _free(c1); _free(c2); _free(c);
  } else {
    x = _const(n, 0, 2);
  }

  _pair ans = {x, b};
  _free(b1); _free(b2); _free(bp);


  return ans;
}
#define _A2QB share_A2QB

_pair share_A2QB_xor(_ a)
{
  share_t q = order(a);
  if (_party >  2) {
    _pair ans = {NULL, NULL};
    return ans;
  }
  int k = blog(q-1)+1;
  if ((1 << k) != q) {
    printf("share_A2QB_xor: %d is not a power of two\n", (int)q);
  }

  int n = len(a);
  _ b = _const(n, 0, 2);
  for (int i=0; i<n; i++) {
    pa_set(b->A, i, (q+pa_get(a->A,i)) % 2); // xor シェアの最下位ビット
  }


  q = q/2;
  _ x;
  if (q > 1) {
    x = _const(n, 0, q);
    for (int i=0; i<n; i++) {
      pa_set(x->A, i, ((q*4+pa_get(a->A, i)) / 2) % q); // !!!
    }
  } else {
    x = _const(n, 0, 2);
  }

  _pair ans = {x, b};

  return ans;
}

#define share_A2QB(a, q, qb) share_A2QB_channel(a, q, qb, 0)

////////////////////////////////////////////////////////
// 加法的シェアをビットごとのシェア（位数 qb）に変換する
// 位数 q は2のべき乗とする
////////////////////////////////////////////////////////
_bits share_A2B(_ a, share_t qb)
{
  if (_party >  2) return NULL;
  NEWT(_bits, ans);

  share_t q = order(a);
  int k = blog(q-1)+1;
  if ((1 << k) != q) {
    printf("share_A2B: %d is not a power of two\n", (int)q);
  }
  ans->d = k;
//  int n = len(a);

  NEWA(ans->a, share_array, k);
  _ x = _dup(a);
  for (int i = 0; i<k; i++) {
    _pair tmp = share_A2QB(x, order(x), qb);
    ans->a[i] = tmp.y;
    _move_(x, tmp.x);
  }
  _free(x);

  return ans;
}
//#define _A2B share_A2B


#endif
