Blame liba52/imdct.c

Packit 64f477
/*
Packit 64f477
 * imdct.c
Packit 64f477
 * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
Packit 64f477
 * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
Packit 64f477
 *
Packit 64f477
 * The ifft algorithms in this file have been largely inspired by Dan
Packit 64f477
 * Bernstein's work, djbfft, available at http://cr.yp.to/djbfft.html
Packit 64f477
 *
Packit 64f477
 * This file is part of a52dec, a free ATSC A-52 stream decoder.
Packit 64f477
 * See http://liba52.sourceforge.net/ for updates.
Packit 64f477
 *
Packit 64f477
 * a52dec is free software; you can redistribute it and/or modify
Packit 64f477
 * it under the terms of the GNU General Public License as published by
Packit 64f477
 * the Free Software Foundation; either version 2 of the License, or
Packit 64f477
 * (at your option) any later version.
Packit 64f477
 *
Packit 64f477
 * a52dec is distributed in the hope that it will be useful,
Packit 64f477
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 64f477
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 64f477
 * GNU General Public License for more details.
Packit 64f477
 *
Packit 64f477
 * You should have received a copy of the GNU General Public License
Packit 64f477
 * along with this program; if not, write to the Free Software
Packit 64f477
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit 64f477
 */
Packit 64f477
Packit 64f477
#include "config.h"
Packit 64f477
Packit 64f477
#include <math.h>
Packit 64f477
#include <stdio.h>
Packit 64f477
#ifdef LIBA52_DJBFFT
Packit 64f477
#include <fftc4.h>
Packit 64f477
#endif
Packit 64f477
#ifndef M_PI
Packit 64f477
#define M_PI 3.1415926535897932384626433832795029
Packit 64f477
#endif
Packit 64f477
#include <inttypes.h>
Packit 64f477
Packit 64f477
#include "a52.h"
Packit 64f477
#include "a52_internal.h"
Packit 64f477
#include "mm_accel.h"
Packit 64f477
Packit 64f477
typedef struct complex_s {
Packit 64f477
    sample_t real;
Packit 64f477
    sample_t imag;
Packit 64f477
} complex_t;
Packit 64f477
Packit 64f477
static uint8_t fftorder[] = {
Packit 64f477
      0,128, 64,192, 32,160,224, 96, 16,144, 80,208,240,112, 48,176,
Packit 64f477
      8,136, 72,200, 40,168,232,104,248,120, 56,184, 24,152,216, 88,
Packit 64f477
      4,132, 68,196, 36,164,228,100, 20,148, 84,212,244,116, 52,180,
Packit 64f477
    252,124, 60,188, 28,156,220, 92, 12,140, 76,204,236,108, 44,172,
Packit 64f477
      2,130, 66,194, 34,162,226, 98, 18,146, 82,210,242,114, 50,178,
Packit 64f477
     10,138, 74,202, 42,170,234,106,250,122, 58,186, 26,154,218, 90,
Packit 64f477
    254,126, 62,190, 30,158,222, 94, 14,142, 78,206,238,110, 46,174,
Packit 64f477
      6,134, 70,198, 38,166,230,102,246,118, 54,182, 22,150,214, 86
Packit 64f477
};
Packit 64f477
Packit 64f477
/* Root values for IFFT */
Packit 64f477
static sample_t roots16[3];
Packit 64f477
static sample_t roots32[7];
Packit 64f477
static sample_t roots64[15];
Packit 64f477
static sample_t roots128[31];
Packit 64f477
Packit 64f477
/* Twiddle factors for IMDCT */
Packit 64f477
static complex_t pre1[128];
Packit 64f477
static complex_t post1[64];
Packit 64f477
static complex_t pre2[64];
Packit 64f477
static complex_t post2[32];
Packit 64f477
Packit 64f477
static sample_t a52_imdct_window[256];
Packit 64f477
Packit 64f477
static void (* ifft128) (complex_t * buf);
Packit 64f477
static void (* ifft64) (complex_t * buf);
Packit 64f477
Packit 64f477
static inline void ifft2 (complex_t * buf)
Packit 64f477
{
Packit 64f477
    double r, i;
Packit 64f477
Packit 64f477
    r = buf[0].real;
Packit 64f477
    i = buf[0].imag;
Packit 64f477
    buf[0].real += buf[1].real;
Packit 64f477
    buf[0].imag += buf[1].imag;
Packit 64f477
    buf[1].real = r - buf[1].real;
Packit 64f477
    buf[1].imag = i - buf[1].imag;
Packit 64f477
}
Packit 64f477
Packit 64f477
static inline void ifft4 (complex_t * buf)
Packit 64f477
{
Packit 64f477
    double tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
Packit 64f477
Packit 64f477
    tmp1 = buf[0].real + buf[1].real;
Packit 64f477
    tmp2 = buf[3].real + buf[2].real;
Packit 64f477
    tmp3 = buf[0].imag + buf[1].imag;
Packit 64f477
    tmp4 = buf[2].imag + buf[3].imag;
Packit 64f477
    tmp5 = buf[0].real - buf[1].real;
Packit 64f477
    tmp6 = buf[0].imag - buf[1].imag;
Packit 64f477
    tmp7 = buf[2].imag - buf[3].imag;
Packit 64f477
    tmp8 = buf[3].real - buf[2].real;
Packit 64f477
Packit 64f477
    buf[0].real = tmp1 + tmp2;
Packit 64f477
    buf[0].imag = tmp3 + tmp4;
Packit 64f477
    buf[2].real = tmp1 - tmp2;
Packit 64f477
    buf[2].imag = tmp3 - tmp4;
Packit 64f477
    buf[1].real = tmp5 + tmp7;
Packit 64f477
    buf[1].imag = tmp6 + tmp8;
Packit 64f477
    buf[3].real = tmp5 - tmp7;
Packit 64f477
    buf[3].imag = tmp6 - tmp8;
Packit 64f477
}
Packit 64f477
Packit 64f477
/* the basic split-radix ifft butterfly */
Packit 64f477
Packit 64f477
#define BUTTERFLY(a0,a1,a2,a3,wr,wi) do {	\
Packit 64f477
    tmp5 = a2.real * wr + a2.imag * wi;		\
Packit 64f477
    tmp6 = a2.imag * wr - a2.real * wi;		\
Packit 64f477
    tmp7 = a3.real * wr - a3.imag * wi;		\
Packit 64f477
    tmp8 = a3.imag * wr + a3.real * wi;		\
Packit 64f477
    tmp1 = tmp5 + tmp7;				\
Packit 64f477
    tmp2 = tmp6 + tmp8;				\
Packit 64f477
    tmp3 = tmp6 - tmp8;				\
Packit 64f477
    tmp4 = tmp7 - tmp5;				\
Packit 64f477
    a2.real = a0.real - tmp1;			\
Packit 64f477
    a2.imag = a0.imag - tmp2;			\
Packit 64f477
    a3.real = a1.real - tmp3;			\
Packit 64f477
    a3.imag = a1.imag - tmp4;			\
Packit 64f477
    a0.real += tmp1;				\
Packit 64f477
    a0.imag += tmp2;				\
Packit 64f477
    a1.real += tmp3;				\
Packit 64f477
    a1.imag += tmp4;				\
Packit 64f477
} while (0)
Packit 64f477
Packit 64f477
/* split-radix ifft butterfly, specialized for wr=1 wi=0 */
Packit 64f477
Packit 64f477
#define BUTTERFLY_ZERO(a0,a1,a2,a3) do {	\
Packit 64f477
    tmp1 = a2.real + a3.real;			\
Packit 64f477
    tmp2 = a2.imag + a3.imag;			\
Packit 64f477
    tmp3 = a2.imag - a3.imag;			\
Packit 64f477
    tmp4 = a3.real - a2.real;			\
Packit 64f477
    a2.real = a0.real - tmp1;			\
Packit 64f477
    a2.imag = a0.imag - tmp2;			\
Packit 64f477
    a3.real = a1.real - tmp3;			\
Packit 64f477
    a3.imag = a1.imag - tmp4;			\
Packit 64f477
    a0.real += tmp1;				\
Packit 64f477
    a0.imag += tmp2;				\
Packit 64f477
    a1.real += tmp3;				\
Packit 64f477
    a1.imag += tmp4;				\
Packit 64f477
} while (0)
Packit 64f477
Packit 64f477
/* split-radix ifft butterfly, specialized for wr=wi */
Packit 64f477
Packit 64f477
#define BUTTERFLY_HALF(a0,a1,a2,a3,w) do {	\
Packit 64f477
    tmp5 = (a2.real + a2.imag) * w;		\
Packit 64f477
    tmp6 = (a2.imag - a2.real) * w;		\
Packit 64f477
    tmp7 = (a3.real - a3.imag) * w;		\
Packit 64f477
    tmp8 = (a3.imag + a3.real) * w;		\
Packit 64f477
    tmp1 = tmp5 + tmp7;				\
Packit 64f477
    tmp2 = tmp6 + tmp8;				\
Packit 64f477
    tmp3 = tmp6 - tmp8;				\
Packit 64f477
    tmp4 = tmp7 - tmp5;				\
Packit 64f477
    a2.real = a0.real - tmp1;			\
Packit 64f477
    a2.imag = a0.imag - tmp2;			\
Packit 64f477
    a3.real = a1.real - tmp3;			\
Packit 64f477
    a3.imag = a1.imag - tmp4;			\
Packit 64f477
    a0.real += tmp1;				\
Packit 64f477
    a0.imag += tmp2;				\
Packit 64f477
    a1.real += tmp3;				\
Packit 64f477
    a1.imag += tmp4;				\
Packit 64f477
} while (0)
Packit 64f477
Packit 64f477
static inline void ifft8 (complex_t * buf)
Packit 64f477
{
Packit 64f477
    double tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
Packit 64f477
Packit 64f477
    ifft4 (buf);
Packit 64f477
    ifft2 (buf + 4);
Packit 64f477
    ifft2 (buf + 6);
Packit 64f477
    BUTTERFLY_ZERO (buf[0], buf[2], buf[4], buf[6]);
Packit 64f477
    BUTTERFLY_HALF (buf[1], buf[3], buf[5], buf[7], roots16[1]);
Packit 64f477
}
Packit 64f477
Packit 64f477
static void ifft_pass (complex_t * buf, sample_t * weight, int n)
Packit 64f477
{
Packit 64f477
    complex_t * buf1;
Packit 64f477
    complex_t * buf2;
Packit 64f477
    complex_t * buf3;
Packit 64f477
    double tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8;
Packit 64f477
    int i;
Packit 64f477
Packit 64f477
    buf++;
Packit 64f477
    buf1 = buf + n;
Packit 64f477
    buf2 = buf + 2 * n;
Packit 64f477
    buf3 = buf + 3 * n;
Packit 64f477
Packit 64f477
    BUTTERFLY_ZERO (buf[-1], buf1[-1], buf2[-1], buf3[-1]);
Packit 64f477
Packit 64f477
    i = n - 1;
Packit 64f477
Packit 64f477
    do {
Packit 64f477
	BUTTERFLY (buf[0], buf1[0], buf2[0], buf3[0], weight[n], weight[2*i]);
Packit 64f477
	buf++;
Packit 64f477
	buf1++;
Packit 64f477
	buf2++;
Packit 64f477
	buf3++;
Packit 64f477
	weight++;
Packit 64f477
    } while (--i);
Packit 64f477
}
Packit 64f477
Packit 64f477
static void ifft16 (complex_t * buf)
Packit 64f477
{
Packit 64f477
    ifft8 (buf);
Packit 64f477
    ifft4 (buf + 8);
Packit 64f477
    ifft4 (buf + 12);
Packit 64f477
    ifft_pass (buf, roots16 - 4, 4);
Packit 64f477
}
Packit 64f477
Packit 64f477
static void ifft32 (complex_t * buf)
Packit 64f477
{
Packit 64f477
    ifft16 (buf);
Packit 64f477
    ifft8 (buf + 16);
Packit 64f477
    ifft8 (buf + 24);
Packit 64f477
    ifft_pass (buf, roots32 - 8, 8);
Packit 64f477
}
Packit 64f477
Packit 64f477
static void ifft64_c (complex_t * buf)
Packit 64f477
{
Packit 64f477
    ifft32 (buf);
Packit 64f477
    ifft16 (buf + 32);
Packit 64f477
    ifft16 (buf + 48);
Packit 64f477
    ifft_pass (buf, roots64 - 16, 16);
Packit 64f477
}
Packit 64f477
Packit 64f477
static void ifft128_c (complex_t * buf)
Packit 64f477
{
Packit 64f477
    ifft32 (buf);
Packit 64f477
    ifft16 (buf + 32);
Packit 64f477
    ifft16 (buf + 48);
Packit 64f477
    ifft_pass (buf, roots64 - 16, 16);
Packit 64f477
Packit 64f477
    ifft32 (buf + 64);
Packit 64f477
    ifft32 (buf + 96);
Packit 64f477
    ifft_pass (buf, roots128 - 32, 32);
Packit 64f477
}
Packit 64f477
Packit 64f477
void a52_imdct_512 (sample_t * data, sample_t * delay, sample_t bias)
Packit 64f477
{
Packit 64f477
    int i, k;
Packit 64f477
    sample_t t_r, t_i, a_r, a_i, b_r, b_i, w_1, w_2;
Packit 64f477
    const sample_t * window = a52_imdct_window;
Packit 64f477
    complex_t buf[128];
Packit 64f477
	
Packit 64f477
    for (i = 0; i < 128; i++) {
Packit 64f477
	k = fftorder[i];
Packit 64f477
	t_r = pre1[i].real;
Packit 64f477
	t_i = pre1[i].imag;
Packit 64f477
Packit 64f477
	buf[i].real = t_i * data[255-k] + t_r * data[k];
Packit 64f477
	buf[i].imag = t_r * data[255-k] - t_i * data[k];
Packit 64f477
    }
Packit 64f477
Packit 64f477
    ifft128 (buf);
Packit 64f477
Packit 64f477
    /* Post IFFT complex multiply plus IFFT complex conjugate*/
Packit 64f477
    /* Window and convert to real valued signal */
Packit 64f477
    for (i = 0; i < 64; i++) {
Packit 64f477
	/* y[n] = z[n] * (xcos1[n] + j * xsin1[n]) ; */
Packit 64f477
	t_r = post1[i].real;
Packit 64f477
	t_i = post1[i].imag;
Packit 64f477
Packit 64f477
	a_r = t_r * buf[i].real     + t_i * buf[i].imag;
Packit 64f477
	a_i = t_i * buf[i].real     - t_r * buf[i].imag;
Packit 64f477
	b_r = t_i * buf[127-i].real + t_r * buf[127-i].imag;
Packit 64f477
	b_i = t_r * buf[127-i].real - t_i * buf[127-i].imag;
Packit 64f477
Packit 64f477
	w_1 = window[2*i];
Packit 64f477
	w_2 = window[255-2*i];
Packit 64f477
	data[2*i]     = delay[2*i] * w_2 - a_r * w_1 + bias;
Packit 64f477
	data[255-2*i] = delay[2*i] * w_1 + a_r * w_2 + bias;
Packit 64f477
	delay[2*i] = a_i;
Packit 64f477
Packit 64f477
	w_1 = window[2*i+1];
Packit 64f477
	w_2 = window[254-2*i];
Packit 64f477
	data[2*i+1]   = delay[2*i+1] * w_2 + b_r * w_1 + bias;
Packit 64f477
	data[254-2*i] = delay[2*i+1] * w_1 - b_r * w_2 + bias;
Packit 64f477
	delay[2*i+1] = b_i;
Packit 64f477
    }
Packit 64f477
}
Packit 64f477
Packit 64f477
void a52_imdct_256(sample_t * data, sample_t * delay, sample_t bias)
Packit 64f477
{
Packit 64f477
    int i, k;
Packit 64f477
    sample_t t_r, t_i, a_r, a_i, b_r, b_i, c_r, c_i, d_r, d_i, w_1, w_2;
Packit 64f477
    const sample_t * window = a52_imdct_window;
Packit 64f477
    complex_t buf1[64], buf2[64];
Packit 64f477
Packit 64f477
    /* Pre IFFT complex multiply plus IFFT cmplx conjugate */
Packit 64f477
    for (i = 0; i < 64; i++) {
Packit 64f477
	k = fftorder[i];
Packit 64f477
	t_r = pre2[i].real;
Packit 64f477
	t_i = pre2[i].imag;
Packit 64f477
Packit 64f477
	buf1[i].real = t_i * data[254-k] + t_r * data[k];
Packit 64f477
	buf1[i].imag = t_r * data[254-k] - t_i * data[k];
Packit 64f477
Packit 64f477
	buf2[i].real = t_i * data[255-k] + t_r * data[k+1];
Packit 64f477
	buf2[i].imag = t_r * data[255-k] - t_i * data[k+1];
Packit 64f477
    }
Packit 64f477
Packit 64f477
    ifft64 (buf1);
Packit 64f477
    ifft64 (buf2);
Packit 64f477
Packit 64f477
    /* Post IFFT complex multiply */
Packit 64f477
    /* Window and convert to real valued signal */
Packit 64f477
    for (i = 0; i < 32; i++) {
Packit 64f477
	/* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */ 
Packit 64f477
	t_r = post2[i].real;
Packit 64f477
	t_i = post2[i].imag;
Packit 64f477
Packit 64f477
	a_r = t_r * buf1[i].real    + t_i * buf1[i].imag;
Packit 64f477
	a_i = t_i * buf1[i].real    - t_r * buf1[i].imag;
Packit 64f477
	b_r = t_i * buf1[63-i].real + t_r * buf1[63-i].imag;
Packit 64f477
	b_i = t_r * buf1[63-i].real - t_i * buf1[63-i].imag;
Packit 64f477
Packit 64f477
	c_r = t_r * buf2[i].real    + t_i * buf2[i].imag;
Packit 64f477
	c_i = t_i * buf2[i].real    - t_r * buf2[i].imag;
Packit 64f477
	d_r = t_i * buf2[63-i].real + t_r * buf2[63-i].imag;
Packit 64f477
	d_i = t_r * buf2[63-i].real - t_i * buf2[63-i].imag;
Packit 64f477
Packit 64f477
	w_1 = window[2*i];
Packit 64f477
	w_2 = window[255-2*i];
Packit 64f477
	data[2*i]     = delay[2*i] * w_2 - a_r * w_1 + bias;
Packit 64f477
	data[255-2*i] = delay[2*i] * w_1 + a_r * w_2 + bias;
Packit 64f477
	delay[2*i] = c_i;
Packit 64f477
Packit 64f477
	w_1 = window[128+2*i];
Packit 64f477
	w_2 = window[127-2*i];
Packit 64f477
	data[128+2*i] = delay[127-2*i] * w_2 + a_i * w_1 + bias;
Packit 64f477
	data[127-2*i] = delay[127-2*i] * w_1 - a_i * w_2 + bias;
Packit 64f477
	delay[127-2*i] = c_r;
Packit 64f477
Packit 64f477
	w_1 = window[2*i+1];
Packit 64f477
	w_2 = window[254-2*i];
Packit 64f477
	data[2*i+1]   = delay[2*i+1] * w_2 - b_i * w_1 + bias;
Packit 64f477
	data[254-2*i] = delay[2*i+1] * w_1 + b_i * w_2 + bias;
Packit 64f477
	delay[2*i+1] = d_r;
Packit 64f477
Packit 64f477
	w_1 = window[129+2*i];
Packit 64f477
	w_2 = window[126-2*i];
Packit 64f477
	data[129+2*i] = delay[126-2*i] * w_2 + b_r * w_1 + bias;
Packit 64f477
	data[126-2*i] = delay[126-2*i] * w_1 - b_r * w_2 + bias;
Packit 64f477
	delay[126-2*i] = d_i;
Packit 64f477
    }
Packit 64f477
}
Packit 64f477
Packit 64f477
static double besselI0 (double x)
Packit 64f477
{
Packit 64f477
    double bessel = 1;
Packit 64f477
    int i = 100;
Packit 64f477
Packit 64f477
    do
Packit 64f477
	bessel = bessel * x / (i * i) + 1;
Packit 64f477
    while (--i);
Packit 64f477
    return bessel;
Packit 64f477
}
Packit 64f477
Packit 64f477
void a52_imdct_init (uint32_t mm_accel)
Packit 64f477
{
Packit 64f477
    int i, k;
Packit 64f477
    double sum;
Packit 64f477
Packit 64f477
    /* compute imdct window - kaiser-bessel derived window, alpha = 5.0 */
Packit 64f477
    sum = 0;
Packit 64f477
    for (i = 0; i < 256; i++) {
Packit 64f477
	sum += besselI0 (i * (256 - i) * (5 * M_PI / 256) * (5 * M_PI / 256));
Packit 64f477
	a52_imdct_window[i] = sum;
Packit 64f477
    }
Packit 64f477
    sum++;
Packit 64f477
    for (i = 0; i < 256; i++)
Packit 64f477
	a52_imdct_window[i] = sqrt (a52_imdct_window[i] / sum);
Packit 64f477
Packit 64f477
    for (i = 0; i < 3; i++)
Packit 64f477
	roots16[i] = cos ((M_PI / 8) * (i + 1));
Packit 64f477
Packit 64f477
    for (i = 0; i < 7; i++)
Packit 64f477
	roots32[i] = cos ((M_PI / 16) * (i + 1));
Packit 64f477
Packit 64f477
    for (i = 0; i < 15; i++)
Packit 64f477
	roots64[i] = cos ((M_PI / 32) * (i + 1));
Packit 64f477
Packit 64f477
    for (i = 0; i < 31; i++)
Packit 64f477
	roots128[i] = cos ((M_PI / 64) * (i + 1));
Packit 64f477
Packit 64f477
    for (i = 0; i < 64; i++) {
Packit 64f477
	k = fftorder[i] / 2 + 64;
Packit 64f477
	pre1[i].real = cos ((M_PI / 256) * (k - 0.25));
Packit 64f477
	pre1[i].imag = sin ((M_PI / 256) * (k - 0.25));
Packit 64f477
    }
Packit 64f477
Packit 64f477
    for (i = 64; i < 128; i++) {
Packit 64f477
	k = fftorder[i] / 2 + 64;
Packit 64f477
	pre1[i].real = -cos ((M_PI / 256) * (k - 0.25));
Packit 64f477
	pre1[i].imag = -sin ((M_PI / 256) * (k - 0.25));
Packit 64f477
    }
Packit 64f477
Packit 64f477
    for (i = 0; i < 64; i++) {
Packit 64f477
	post1[i].real = cos ((M_PI / 256) * (i + 0.5));
Packit 64f477
	post1[i].imag = sin ((M_PI / 256) * (i + 0.5));
Packit 64f477
    }
Packit 64f477
Packit 64f477
    for (i = 0; i < 64; i++) {
Packit 64f477
	k = fftorder[i] / 4;
Packit 64f477
	pre2[i].real = cos ((M_PI / 128) * (k - 0.25));
Packit 64f477
	pre2[i].imag = sin ((M_PI / 128) * (k - 0.25));
Packit 64f477
    }
Packit 64f477
Packit 64f477
    for (i = 0; i < 32; i++) {
Packit 64f477
	post2[i].real = cos ((M_PI / 128) * (i + 0.5));
Packit 64f477
	post2[i].imag = sin ((M_PI / 128) * (i + 0.5));
Packit 64f477
    }
Packit 64f477
Packit 64f477
#ifdef LIBA52_DJBFFT
Packit 64f477
    if (mm_accel & MM_ACCEL_DJBFFT) {
Packit 64f477
	fprintf (stderr, "Using djbfft for IMDCT transform\n");
Packit 64f477
	ifft128 = (void (*) (complex_t *)) fftc4_un128;
Packit 64f477
	ifft64 = (void (*) (complex_t *)) fftc4_un64;
Packit 64f477
    } else
Packit 64f477
#endif
Packit 64f477
    {
Packit 64f477
	fprintf (stderr, "No accelerated IMDCT transform found\n");
Packit 64f477
	ifft128 = ifft128_c;
Packit 64f477
	ifft64 = ifft64_c;
Packit 64f477
    }
Packit 64f477
}