Add wasm tacle-bench targets

This commit is contained in:
2026-06-12 20:06:22 +02:00
parent 30daa8a00c
commit 08c2e9c13d
1122 changed files with 520422 additions and 0 deletions

View File

@ -0,0 +1,25 @@
# ~~~
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2026, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
# ~~~
cmake_minimum_required(VERSION 3.20)
project(adpcm_dec)
set(TACLEBENCH_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../..")
set(REPOSITORY_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../..")
set(APP_TARGET_NAME "${CMAKE_PROJECT_NAME}")
if(DEFINED TACLEBENCH_VARIANT AND "${TACLEBENCH_VARIANT}" STREQUAL "inline")
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/inline/adpcm_dec.c")
else()
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/default/adpcm_dec.c")
endif()
include(${REPOSITORY_ROOT_PATH}/cmake/taclebench_wasm.cmake)

View File

@ -0,0 +1,32 @@
File: minver.c
Original provenience: SNU-RT Benchmark Suite for Worst Case Timing Analysis
2016-02-26:
- Added TACLeBench header to line 1
- Rename global variable a to minver_a
- Rename global variable b to minver_b
- Rename global variable c to minver_c
- Rename global variable aa to minver_aa
- Rename global variable a_i to minver_a_i
- Rename global variable e to minver_e
- Rename global variable det to minver_det
- Renamed function minver to minver_minver
- Renamed function mmul to minver_mmul
- Renamed function fabs to minver_fabs
- Renamed function main to minver_main
- Created new function main, calling minver_init, minver_main and
returning minver_return
- Reordered functions in source code: initialization- and
return-value-related functions first, followed by algorithm core
functions, followed by main functions
- Applied code formatting with astyle as in the example
2016-03-09:
- Removed static keyword for global variables
- Renamed global variables, prepended adpcm_dec
2016-05-23:
- Check sum added and checked against the expected value
2016-05-25:
- Corrected expected value

View File

@ -0,0 +1,710 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: adpcm_dec
Author: Sung-Soo Lim
Function:
CCITT G.722 ADPCM (Adaptive Differential Pulse Code Modulation)
algorithm.
16khz sample rate data is stored in the array test_data[ SIZE ].
Results are stored in the array compressed[ SIZE ] and result[ SIZE ].
Execution time is determined by the constant SIZE (default value
is 2000).
Source: SNU-RT Benchmark Suite
Changes: adpcm benchmark was split into decode and encode benchmark
License: may be used, modified, and re-distributed freely, but
the SNU-RT Benchmark Suite must be acknowledged
*/
/*
This program is derived from the SNU-RT Benchmark Suite for Worst
Case Timing Analysis by Sung-Soo Lim
Original source: C Algorithms for Real-Time DSP by P. M. Embree
*/
/*
Forward declaration of functions
*/
void adpcm_dec_decode( int );
int adpcm_dec_filtez( int *bpl, int *dlt );
void adpcm_dec_upzero( int dlt, int *dlti, int *bli );
int adpcm_dec_filtep( int rlt1, int al1, int rlt2, int al2 );
int adpcm_dec_logscl( int il, int nbl );
int adpcm_dec_scalel( int nbl, int shift_constant );
int adpcm_dec_uppol2( int al1, int al2, int plt, int plt1, int plt2 );
int adpcm_dec_uppol1( int al1, int apl2, int plt, int plt1 );
int adpcm_dec_logsch( int ih, int nbh );
void adpcm_dec_reset();
int adpcm_dec_fabs( int n );
int adpcm_dec_cos( int n );
int adpcm_dec_sin( int n );
void adpcm_dec_init();
int adpcm_dec_return();
void adpcm_dec_main();
int main( void );
/*
Declaration of macros
*/
/* common sampling rate for sound cards on IBM/PC */
#define SAMPLE_RATE 11025
#define PI 3141
#define SIZE 3
#define IN_END 4
/*
Declaration of global variables
*/
int adpcm_dec_test_data[ SIZE * 2 ], adpcm_dec_result[ SIZE * 2 ];
/* Input data for the decoder usually generated by the encoder. */
int adpcm_dec_compressed[ SIZE ] = { 0, 253, 32 };
/* G722 C code */
/* QMF filter coefficients:
scaled by a factor of 4 compared to G722 CCITT recommendation */
int adpcm_dec_h[ 24 ] = {
12, -44, -44, 212, 48, -624, 128, 1448,
-840, -3220, 3804, 15504, 15504, 3804, -3220, -840,
1448, 128, -624, 48, 212, -44, -44, 12
};
//int xl,xh;
/* variables for receive quadrature mirror filter here */
int adpcm_dec_accumc[ 11 ], adpcm_dec_accumd[ 11 ];
/* outputs of decode() */
int adpcm_dec_xout1, adpcm_dec_xout2;
int adpcm_dec_xs, adpcm_dec_xd;
/* variables for encoder (hi and lo) here */
int adpcm_dec_il, adpcm_dec_szl, adpcm_dec_spl, adpcm_dec_sl, adpcm_dec_el;
int adpcm_dec_qq4_code4_table[ 16 ] = {
0, -20456, -12896, -8968, -6288, -4240, -2584, -1200,
20456, 12896, 8968, 6288, 4240, 2584, 1200, 0
};
int adpcm_dec_qq6_code6_table[ 64 ] = {
-136, -136, -136, -136, -24808, -21904, -19008, -16704,
-14984, -13512, -12280, -11192, -10232, -9360, -8576, -7856,
-7192, -6576, -6000, -5456, -4944, -4464, -4008, -3576,
-3168, -2776, -2400, -2032, -1688, -1360, -1040, -728,
24808, 21904, 19008, 16704, 14984, 13512, 12280, 11192,
10232, 9360, 8576, 7856, 7192, 6576, 6000, 5456,
4944, 4464, 4008, 3576, 3168, 2776, 2400, 2032,
1688, 1360, 1040, 728, 432, 136, -432, -136
};
int adpcm_dec_wl_code_table[ 16 ] = {
-60, 3042, 1198, 538, 334, 172, 58, -30,
3042, 1198, 538, 334, 172, 58, -30, -60
};
int adpcm_dec_ilb_table[ 32 ] = {
2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383,
2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834,
2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371,
3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008
};
int adpcm_dec_nbl; /* delay line */
int adpcm_dec_al1, adpcm_dec_al2;
int adpcm_dec_plt, adpcm_dec_plt1, adpcm_dec_plt2;
int adpcm_dec_rs;
int adpcm_dec_dlt;
int adpcm_dec_rlt, adpcm_dec_rlt1, adpcm_dec_rlt2;
int adpcm_dec_detl;
int adpcm_dec_deth;
int adpcm_dec_sh; /* this comes from adaptive predictor */
int adpcm_dec_eh;
int adpcm_dec_qq2_code2_table[ 4 ] = {
-7408, -1616, 7408, 1616
};
int adpcm_dec_wh_code_table[ 4 ] = {
798, -214, 798, -214
};
int adpcm_dec_dh, adpcm_dec_ih;
int adpcm_dec_nbh, adpcm_dec_szh;
int adpcm_dec_sph, adpcm_dec_ph, adpcm_dec_yh, adpcm_dec_rh;
int adpcm_dec_delay_dhx[ 6 ];
int adpcm_dec_delay_bph[ 6 ];
int adpcm_dec_ah1, adpcm_dec_ah2;
int adpcm_dec_ph1, adpcm_dec_ph2;
int adpcm_dec_rh1, adpcm_dec_rh2;
/* variables for decoder here */
int adpcm_dec_ilr, adpcm_dec_yl, adpcm_dec_rl;
int adpcm_dec_dec_deth, adpcm_dec_dec_detl, adpcm_dec_dec_dlt;
int adpcm_dec_dec_del_bpl[ 6 ];
int adpcm_dec_dec_del_dltx[ 6 ];
int adpcm_dec_dec_plt, adpcm_dec_dec_plt1, adpcm_dec_dec_plt2;
int adpcm_dec_dec_szl, adpcm_dec_dec_spl, adpcm_dec_dec_sl;
int adpcm_dec_dec_rlt1, adpcm_dec_dec_rlt2, adpcm_dec_dec_rlt;
int adpcm_dec_dec_al1, adpcm_dec_dec_al2;
int adpcm_dec_dl;
int adpcm_dec_dec_nbl, adpcm_dec_dec_yh, adpcm_dec_dec_dh, adpcm_dec_dec_nbh;
/* variables used in filtez */
int adpcm_dec_dec_del_bph[ 6 ];
int adpcm_dec_dec_del_dhx[ 6 ];
int adpcm_dec_dec_szh;
/* variables used in filtep */
int adpcm_dec_dec_rh1, adpcm_dec_dec_rh2;
int adpcm_dec_dec_ah1, adpcm_dec_dec_ah2;
int adpcm_dec_dec_ph, adpcm_dec_dec_sph;
int adpcm_dec_dec_sh, adpcm_dec_dec_rh;
int adpcm_dec_dec_ph1, adpcm_dec_dec_ph2;
/*
Arithmetic math functions
*/
/* MAX: 1 */
int adpcm_dec_fabs( int n )
{
int f;
if ( n >= 0 )
f = n;
else
f = -n;
return f;
}
int adpcm_dec_sin( int rad )
{
int diff;
int app = 0;
int inc = 1;
/* MAX dependent on rad's value, say 50 */
_Pragma( "loopbound min 0 max 0" )
while ( rad > 2 * PI )
rad -= 2 * PI;
_Pragma( "loopbound min 0 max 1999" )
while ( rad < -2 * PI )
rad += 2 * PI;
diff = rad;
app = diff;
diff = ( diff * ( -( rad * rad ) ) ) / ( ( 2 * inc ) * ( 2 * inc + 1 ) );
app = app + diff;
inc++;
/* REALLY: while(my_fabs(diff) >= 0.00001) { */
/* MAX: 1000 */
_Pragma( "loopbound min 849 max 2424" )
while ( adpcm_dec_fabs( diff ) >= 1 ) {
diff = ( diff * ( -( rad * rad ) ) ) / ( ( 2 * inc ) * ( 2 * inc + 1 ) );
app = app + diff;
inc++;
}
return app;
}
int adpcm_dec_cos( int rad )
{
return ( adpcm_dec_sin( PI / 2 - rad ) );
}
/*
Algorithm core functions
*/
/* decode function, result in xout1 and xout2 */
void adpcm_dec_decode( int input )
{
int i;
long int xa1, xa2; /* qmf accumulators */
int *h_ptr, *ac_ptr, *ac_ptr1, *ad_ptr, *ad_ptr1;
/* split transmitted word from input into ilr and ih */
adpcm_dec_ilr = input & 0x3f;
adpcm_dec_ih = input >> 6;
/* LOWER SUB_BAND DECODER */
/* filtez: compute predictor output for zero section */
adpcm_dec_dec_szl = adpcm_dec_filtez( adpcm_dec_dec_del_bpl,
adpcm_dec_dec_del_dltx );
/* filtep: compute predictor output signal for pole section */
adpcm_dec_dec_spl = adpcm_dec_filtep( adpcm_dec_dec_rlt1, adpcm_dec_dec_al1,
adpcm_dec_dec_rlt2, adpcm_dec_dec_al2 );
adpcm_dec_dec_sl = adpcm_dec_dec_spl + adpcm_dec_dec_szl;
/* invqxl: compute quantized difference signal for adaptive predic */
adpcm_dec_dec_dlt = ( ( long )adpcm_dec_dec_detl *
adpcm_dec_qq4_code4_table[ adpcm_dec_ilr
>> 2 ] ) >> 15;
/* invqxl: compute quantized difference signal for decoder output */
adpcm_dec_dl = ( ( long )adpcm_dec_dec_detl *
adpcm_dec_qq6_code6_table[ adpcm_dec_il ] ) >>
15;
adpcm_dec_rl = adpcm_dec_dl + adpcm_dec_dec_sl;
/* logscl: quantizer scale factor adaptation in the lower sub-band */
adpcm_dec_dec_nbl = adpcm_dec_logscl( adpcm_dec_ilr, adpcm_dec_dec_nbl );
/* scalel: computes quantizer scale factor in the lower sub band */
adpcm_dec_dec_detl = adpcm_dec_scalel( adpcm_dec_dec_nbl, 8 );
/* parrec - add pole predictor output to quantized diff. signal */
/* for partially reconstructed signal */
adpcm_dec_dec_plt = adpcm_dec_dec_dlt + adpcm_dec_dec_szl;
/* upzero: update zero section predictor coefficients */
adpcm_dec_upzero( adpcm_dec_dec_dlt, adpcm_dec_dec_del_dltx,
adpcm_dec_dec_del_bpl );
/* uppol2: update second predictor coefficient apl2 and delay it as al2 */
adpcm_dec_dec_al2 = adpcm_dec_uppol2( adpcm_dec_dec_al1, adpcm_dec_dec_al2,
adpcm_dec_dec_plt, adpcm_dec_dec_plt1,
adpcm_dec_dec_plt2 );
/* uppol1: update first predictor coef. (pole setion) */
adpcm_dec_dec_al1 = adpcm_dec_uppol1( adpcm_dec_dec_al1, adpcm_dec_dec_al2,
adpcm_dec_dec_plt, adpcm_dec_dec_plt1 );
/* recons : compute recontructed signal for adaptive predictor */
adpcm_dec_dec_rlt = adpcm_dec_dec_sl + adpcm_dec_dec_dlt;
/* done with lower sub band decoder, implement delays for next time */
adpcm_dec_dec_rlt2 = adpcm_dec_dec_rlt1;
adpcm_dec_dec_rlt1 = adpcm_dec_dec_rlt;
adpcm_dec_dec_plt2 = adpcm_dec_dec_plt1;
adpcm_dec_dec_plt1 = adpcm_dec_dec_plt;
/* HIGH SUB-BAND DECODER */
/* filtez: compute predictor output for zero section */
adpcm_dec_dec_szh = adpcm_dec_filtez( adpcm_dec_dec_del_bph,
adpcm_dec_dec_del_dhx );
/* filtep: compute predictor output signal for pole section */
adpcm_dec_dec_sph = adpcm_dec_filtep( adpcm_dec_dec_rh1, adpcm_dec_dec_ah1,
adpcm_dec_dec_rh2, adpcm_dec_dec_ah2 );
/* predic:compute the predictor output value in the higher sub_band decoder */
adpcm_dec_dec_sh = adpcm_dec_dec_sph + adpcm_dec_dec_szh;
/* invqah: in-place compute the quantized difference signal */
adpcm_dec_dec_dh = ( ( long )adpcm_dec_dec_deth *
adpcm_dec_qq2_code2_table[ adpcm_dec_ih ] ) >> 15L ;
/* logsch: update logarithmic quantizer scale factor in hi sub band */
adpcm_dec_dec_nbh = adpcm_dec_logsch( adpcm_dec_ih, adpcm_dec_dec_nbh );
/* scalel: compute the quantizer scale factor in the higher sub band */
adpcm_dec_dec_deth = adpcm_dec_scalel( adpcm_dec_dec_nbh, 10 );
/* parrec: compute partially recontructed signal */
adpcm_dec_dec_ph = adpcm_dec_dec_dh + adpcm_dec_dec_szh;
/* upzero: update zero section predictor coefficients */
adpcm_dec_upzero( adpcm_dec_dec_dh, adpcm_dec_dec_del_dhx,
adpcm_dec_dec_del_bph );
/* uppol2: update second predictor coefficient aph2 and delay it as ah2 */
adpcm_dec_dec_ah2 = adpcm_dec_uppol2( adpcm_dec_dec_ah1, adpcm_dec_dec_ah2,
adpcm_dec_dec_ph, adpcm_dec_dec_ph1, adpcm_dec_dec_ph2 );
/* uppol1: update first predictor coef. (pole setion) */
adpcm_dec_dec_ah1 = adpcm_dec_uppol1( adpcm_dec_dec_ah1, adpcm_dec_dec_ah2,
adpcm_dec_dec_ph, adpcm_dec_dec_ph1 );
/* recons : compute recontructed signal for adaptive predictor */
adpcm_dec_rh = adpcm_dec_dec_sh + adpcm_dec_dec_dh;
/* done with high band decode, implementing delays for next time here */
adpcm_dec_dec_rh2 = adpcm_dec_dec_rh1;
adpcm_dec_dec_rh1 = adpcm_dec_rh;
adpcm_dec_dec_ph2 = adpcm_dec_dec_ph1;
adpcm_dec_dec_ph1 = adpcm_dec_dec_ph;
/* end of higher sub_band decoder */
/* end with receive quadrature mirror filters */
adpcm_dec_xd = adpcm_dec_rl - adpcm_dec_rh;
adpcm_dec_xs = adpcm_dec_rl + adpcm_dec_rh;
/* receive quadrature mirror filters implemented here */
h_ptr = adpcm_dec_h;
ac_ptr = adpcm_dec_accumc;
ad_ptr = adpcm_dec_accumd;
xa1 = ( long ) adpcm_dec_xd * ( *h_ptr++ );
xa2 = ( long ) adpcm_dec_xs * ( *h_ptr++ );
/* main multiply accumulate loop for samples and coefficients */
_Pragma( "loopbound min 10 max 10" )
for ( i = 0; i < 10; i++ ) {
xa1 += ( long )( *ac_ptr++ ) * ( *h_ptr++ );
xa2 += ( long )( *ad_ptr++ ) * ( *h_ptr++ );
}
/* final mult/accumulate */
xa1 += ( long )( *ac_ptr ) * ( *h_ptr++ );
xa2 += ( long )( *ad_ptr ) * ( *h_ptr++ );
/* scale by 2^14 */
adpcm_dec_xout1 = xa1 >> 14;
adpcm_dec_xout2 = xa2 >> 14;
/* update delay lines */
ac_ptr1 = ac_ptr - 1;
ad_ptr1 = ad_ptr - 1;
_Pragma( "loopbound min 10 max 10" )
for ( i = 0; i < 10; i++ ) {
*ac_ptr-- = *ac_ptr1--;
*ad_ptr-- = *ad_ptr1--;
}
*ac_ptr = adpcm_dec_xd;
*ad_ptr = adpcm_dec_xs;
return;
}
/* filtez - compute predictor output signal (zero section) */
/* input: bpl1-6 and dlt1-6, output: szl */
int adpcm_dec_filtez( int *bpl, int *dlt )
{
int i;
long int zl;
zl = ( long )( *bpl++ ) * ( *dlt++ );
/* MAX: 5 */
_Pragma( "loopbound min 5 max 5" )
for ( i = 1; i < 6; i++ )
zl += ( long )( *bpl++ ) * ( *dlt++ );
return ( ( int )( zl >> 14 ) ); /* x2 here */
}
/* filtep - compute predictor output signal (pole section) */
/* input rlt1-2 and al1-2, output spl */
int adpcm_dec_filtep( int rlt1, int al1, int rlt2, int al2 )
{
long int pl, pl2;
pl = 2 * rlt1;
pl = ( long ) al1 * pl;
pl2 = 2 * rlt2;
pl += ( long ) al2 * pl2;
return ( ( int )( pl >> 15 ) );
}
/* logscl - update log quantizer scale factor in lower sub-band */
/* note that nbl is passed and returned */
int adpcm_dec_logscl( int il, int nbl )
{
long int wd;
wd = ( ( long )nbl * 127L ) >> 7L; /* leak factor 127/128 */
nbl = ( int )wd + adpcm_dec_wl_code_table[ il >> 2 ];
if ( nbl < 0 )
nbl = 0;
if ( nbl > 18432 )
nbl = 18432;
return ( nbl );
}
/* scalel: compute quantizer scale factor in lower or upper sub-band*/
int adpcm_dec_scalel( int nbl, int shift_constant )
{
int wd1, wd2, wd3;
wd1 = ( nbl >> 6 ) & 31;
wd2 = nbl >> 11;
wd3 = adpcm_dec_ilb_table[ wd1 ] >> ( shift_constant + 1 - wd2 );
return ( wd3 << 3 );
}
/* upzero - inputs: dlt, dlti[ 0-5 ], bli[ 0-5 ], outputs: updated bli[ 0-5 ] */
/* also implements delay of bli and update of dlti from dlt */
void adpcm_dec_upzero( int dlt, int *dlti, int *bli )
{
int i, wd2, wd3;
/*if dlt is zero, then no sum into bli */
if ( dlt == 0 ) {
_Pragma( "loopbound min 6 max 6" )
for ( i = 0; i < 6; i++ ) {
bli[ i ] = ( int )( ( 255L * bli[ i ] ) >> 8L ); /* leak factor of 255/256 */
}
} else {
_Pragma( "loopbound min 6 max 6" )
for ( i = 0; i < 6; i++ ) {
if ( ( long )dlt * dlti[ i ] >= 0 )
wd2 = 128;
else
wd2 = -128;
wd3 = ( int )( ( 255L * bli[ i ] ) >> 8L ); /* leak factor of 255/256 */
bli[ i ] = wd2 + wd3;
}
}
/* implement delay line for dlt */
dlti[ 5 ] = dlti[ 4 ];
dlti[ 4 ] = dlti[ 3 ];
dlti[ 3 ] = dlti[ 2 ];
dlti[ 1 ] = dlti[ 0 ];
dlti[ 0 ] = dlt;
return;
}
/* uppol2 - update second predictor coefficient (pole section) */
/* inputs: al1, al2, plt, plt1, plt2. outputs: apl2 */
int adpcm_dec_uppol2( int al1, int al2, int plt, int plt1, int plt2 )
{
long int wd2, wd4;
int apl2;
wd2 = 4L * ( long )al1;
if ( ( long )plt * plt1 >= 0L )
wd2 = -wd2; /* check same sign */
wd2 = wd2 >> 7; /* gain of 1/128 */
if ( ( long )plt * plt2 >= 0L ) {
wd4 = wd2 + 128; /* same sign case */
} else
wd4 = wd2 - 128;
apl2 = wd4 + ( 127L * ( long )al2 >> 7L ); /* leak factor of 127/128 */
/* apl2 is limited to +-.75 */
if ( apl2 > 12288 )
apl2 = 12288;
if ( apl2 < -12288 )
apl2 = -12288;
return ( apl2 );
}
/* uppol1 - update first predictor coefficient (pole section) */
/* inputs: al1, apl2, plt, plt1. outputs: apl1 */
int adpcm_dec_uppol1( int al1, int apl2, int plt, int plt1 )
{
long int wd2;
int wd3, apl1;
wd2 = ( ( long )al1 * 255L ) >> 8L; /* leak factor of 255/256 */
if ( ( long )plt * plt1 >= 0L ) {
apl1 = ( int )wd2 + 192; /* same sign case */
} else
apl1 = ( int )wd2 - 192;
/* note: wd3= .9375-.75 is always positive */
wd3 = 15360 - apl2; /* limit value */
if ( apl1 > wd3 )
apl1 = wd3;
if ( apl1 < -wd3 )
apl1 = -wd3;
return ( apl1 );
}
/* logsch - update log quantizer scale factor in higher sub-band */
/* note that nbh is passed and returned */
int adpcm_dec_logsch( int ih, int nbh )
{
int wd;
wd = ( ( long )nbh * 127L ) >> 7L; /* leak factor 127/128 */
nbh = wd + adpcm_dec_wh_code_table[ ih ];
if ( nbh < 0 )
nbh = 0;
if ( nbh > 22528 )
nbh = 22528;
return ( nbh );
}
/*
Initialization- and return-value-related functions
*/
/* clear all storage locations */
void adpcm_dec_reset()
{
int i;
adpcm_dec_detl = adpcm_dec_dec_detl = 32; /* reset to min scale factor */
adpcm_dec_deth = adpcm_dec_dec_deth = 8;
adpcm_dec_nbl = adpcm_dec_al1 = adpcm_dec_al2 = adpcm_dec_plt1 = adpcm_dec_plt2
= adpcm_dec_rlt1 = adpcm_dec_rlt2 = 0;
adpcm_dec_nbh = adpcm_dec_ah1 = adpcm_dec_ah2 = adpcm_dec_ph1 = adpcm_dec_ph2 =
adpcm_dec_rh1 = adpcm_dec_rh2 = 0;
adpcm_dec_dec_nbl = adpcm_dec_dec_al1 = adpcm_dec_dec_al2 = adpcm_dec_dec_plt1 =
adpcm_dec_dec_plt2 = adpcm_dec_dec_rlt1 = adpcm_dec_dec_rlt2 = 0;
adpcm_dec_dec_nbh = adpcm_dec_dec_ah1 = adpcm_dec_dec_ah2 = adpcm_dec_dec_ph1 =
adpcm_dec_dec_ph2 = adpcm_dec_dec_rh1 = adpcm_dec_dec_rh2 = 0;
_Pragma( "loopbound min 6 max 6" )
for ( i = 0; i < 6; i++ ) {
////delay_dltx[ i ] = 0;
adpcm_dec_delay_dhx[ i ] = 0;
adpcm_dec_dec_del_dltx[ i ] = 0;
adpcm_dec_dec_del_dhx[ i ] = 0;
}
_Pragma( "loopbound min 6 max 6" )
for ( i = 0; i < 6; i++ ) {
//delay_bpl[ i ] = 0;
adpcm_dec_delay_bph[ i ] = 0;
adpcm_dec_dec_del_bpl[ i ] = 0;
adpcm_dec_dec_del_bph[ i ] = 0;
}
_Pragma( "loopbound min 11 max 11" )
for ( i = 0; i < 11; i++ ) {
adpcm_dec_accumc[ i ] = 0;
adpcm_dec_accumd[ i ] = 0;
}
return;
}
void adpcm_dec_init()
{
int i, j, f;
volatile int x = 0;
/* read in amplitude and frequency for test data */
j = 10;
f = 2000;
/* reset, initialize required memory */
adpcm_dec_reset();
/* 16 KHz sample rate */
/* XXmain_0, MAX: 2 */
/* Since the number of times we loop in adpcm_dec_sin depends on the
argument we add the fact: xxmain_0:[ ]: */
_Pragma( "loopbound min 3 max 3" )
for ( i = 0 ; i < SIZE ; i++ ) {
adpcm_dec_test_data[ i ] = ( int ) j * adpcm_dec_cos( f * PI * i );
/* avoid constant-propagation optimizations */
adpcm_dec_test_data[ i ] += x;
}
}
int adpcm_dec_return()
{
int i;
int check_sum = 0;
_Pragma( "loopbound min 2 max 2" )
for ( i = 0; i < IN_END; i += 2 )
check_sum += ( adpcm_dec_result[ i ] + adpcm_dec_result[ i + 1 ] );
return check_sum != -2;
}
/*
Main functions
*/
void _Pragma( "entrypoint" ) adpcm_dec_main( void )
{
int i;
_Pragma( "loopbound min 2 max 2" )
for ( i = 0 ; i < IN_END ; i += 2 ) {
adpcm_dec_decode( adpcm_dec_compressed[ i / 2 ] );
adpcm_dec_result[ i ] = adpcm_dec_xout1;
adpcm_dec_result[ i + 1 ] = adpcm_dec_xout2;
}
}
int main( void )
{
adpcm_dec_init();
adpcm_dec_main();
return ( adpcm_dec_return() );
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,674 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: adpcm_dec
Author: Sung-Soo Lim
Function:
CCITT G.722 ADPCM (Adaptive Differential Pulse Code Modulation)
algorithm.
16khz sample rate data is stored in the array test_data[ SIZE ].
Results are stored in the array compressed[ SIZE ] and result[ SIZE ].
Execution time is determined by the constant SIZE (default value
is 2000).
Source: SNU-RT Benchmark Suite
Changes: adpcm benchmark was split into decode and encode benchmark
License: may be used, modified, and re-distributed freely, but
the SNU-RT Benchmark Suite must be acknowledged
*/
/*
This program is derived from the SNU-RT Benchmark Suite for Worst
Case Timing Analysis by Sung-Soo Lim
Original source: C Algorithms for Real-Time DSP by P. M. Embree
*/
/*
Forward declaration of functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
void adpcm_dec_decode(int);
int adpcm_dec_filtez(int *bpl, int *dlt);
void adpcm_dec_upzero(int dlt, int *dlti, int *bli);
int adpcm_dec_filtep(int rlt1, int al1, int rlt2, int al2);
int adpcm_dec_logscl(int il, int nbl);
int adpcm_dec_scalel(int nbl, int shift_constant);
int adpcm_dec_uppol2(int al1, int al2, int plt, int plt1, int plt2);
int adpcm_dec_uppol1(int al1, int apl2, int plt, int plt1);
int adpcm_dec_logsch(int ih, int nbh);
void adpcm_dec_reset();
int adpcm_dec_fabs(int n);
int adpcm_dec_cos(int n);
int adpcm_dec_sin(int n);
void adpcm_dec_init();
int adpcm_dec_return();
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
adpcm_dec_main();
__attribute__((noinline)) __attribute__((export_name("main"))) int main(void);
/*
Declaration of macros
*/
/* common sampling rate for sound cards on IBM/PC */
#define SAMPLE_RATE 11025
#define PI 3141
#define SIZE 3
#define IN_END 4
/*
Declaration of global variables
*/
int adpcm_dec_test_data[SIZE * 2], adpcm_dec_result[SIZE * 2];
/* Input data for the decoder usually generated by the encoder. */
int adpcm_dec_compressed[SIZE] = {0, 253, 32};
/* G722 C code */
/* QMF filter coefficients:
scaled by a factor of 4 compared to G722 CCITT recommendation */
int adpcm_dec_h[24] = {12, -44, -44, 212, 48, -624, 128, 1448,
-840, -3220, 3804, 15504, 15504, 3804, -3220, -840,
1448, 128, -624, 48, 212, -44, -44, 12};
// int xl,xh;
/* variables for receive quadrature mirror filter here */
int adpcm_dec_accumc[11], adpcm_dec_accumd[11];
/* outputs of decode() */
int adpcm_dec_xout1, adpcm_dec_xout2;
int adpcm_dec_xs, adpcm_dec_xd;
/* variables for encoder (hi and lo) here */
int adpcm_dec_il, adpcm_dec_szl, adpcm_dec_spl, adpcm_dec_sl, adpcm_dec_el;
int adpcm_dec_qq4_code4_table[16] = {0, -20456, -12896, -8968, -6288, -4240,
-2584, -1200, 20456, 12896, 8968, 6288,
4240, 2584, 1200, 0};
int adpcm_dec_qq6_code6_table[64] = {
-136, -136, -136, -136, -24808, -21904, -19008, -16704,
-14984, -13512, -12280, -11192, -10232, -9360, -8576, -7856,
-7192, -6576, -6000, -5456, -4944, -4464, -4008, -3576,
-3168, -2776, -2400, -2032, -1688, -1360, -1040, -728,
24808, 21904, 19008, 16704, 14984, 13512, 12280, 11192,
10232, 9360, 8576, 7856, 7192, 6576, 6000, 5456,
4944, 4464, 4008, 3576, 3168, 2776, 2400, 2032,
1688, 1360, 1040, 728, 432, 136, -432, -136};
int adpcm_dec_wl_code_table[16] = {-60, 3042, 1198, 538, 334, 172, 58, -30,
3042, 1198, 538, 334, 172, 58, -30, -60};
int adpcm_dec_ilb_table[32] = {2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383,
2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834,
2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371,
3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008};
int adpcm_dec_nbl; /* delay line */
int adpcm_dec_al1, adpcm_dec_al2;
int adpcm_dec_plt, adpcm_dec_plt1, adpcm_dec_plt2;
int adpcm_dec_rs;
int adpcm_dec_dlt;
int adpcm_dec_rlt, adpcm_dec_rlt1, adpcm_dec_rlt2;
int adpcm_dec_detl;
int adpcm_dec_deth;
int adpcm_dec_sh; /* this comes from adaptive predictor */
int adpcm_dec_eh;
int adpcm_dec_qq2_code2_table[4] = {-7408, -1616, 7408, 1616};
int adpcm_dec_wh_code_table[4] = {798, -214, 798, -214};
int adpcm_dec_dh, adpcm_dec_ih;
int adpcm_dec_nbh, adpcm_dec_szh;
int adpcm_dec_sph, adpcm_dec_ph, adpcm_dec_yh, adpcm_dec_rh;
int adpcm_dec_delay_dhx[6];
int adpcm_dec_delay_bph[6];
int adpcm_dec_ah1, adpcm_dec_ah2;
int adpcm_dec_ph1, adpcm_dec_ph2;
int adpcm_dec_rh1, adpcm_dec_rh2;
/* variables for decoder here */
int adpcm_dec_ilr, adpcm_dec_yl, adpcm_dec_rl;
int adpcm_dec_dec_deth, adpcm_dec_dec_detl, adpcm_dec_dec_dlt;
int adpcm_dec_dec_del_bpl[6];
int adpcm_dec_dec_del_dltx[6];
int adpcm_dec_dec_plt, adpcm_dec_dec_plt1, adpcm_dec_dec_plt2;
int adpcm_dec_dec_szl, adpcm_dec_dec_spl, adpcm_dec_dec_sl;
int adpcm_dec_dec_rlt1, adpcm_dec_dec_rlt2, adpcm_dec_dec_rlt;
int adpcm_dec_dec_al1, adpcm_dec_dec_al2;
int adpcm_dec_dl;
int adpcm_dec_dec_nbl, adpcm_dec_dec_yh, adpcm_dec_dec_dh, adpcm_dec_dec_nbh;
/* variables used in filtez */
int adpcm_dec_dec_del_bph[6];
int adpcm_dec_dec_del_dhx[6];
int adpcm_dec_dec_szh;
/* variables used in filtep */
int adpcm_dec_dec_rh1, adpcm_dec_dec_rh2;
int adpcm_dec_dec_ah1, adpcm_dec_dec_ah2;
int adpcm_dec_dec_ph, adpcm_dec_dec_sph;
int adpcm_dec_dec_sh, adpcm_dec_dec_rh;
int adpcm_dec_dec_ph1, adpcm_dec_dec_ph2;
/*
Arithmetic math functions
*/
/* MAX: 1 */
int
adpcm_dec_fabs(int n) {
int f;
if (n >= 0)
f = n;
else
f = -n;
return f;
}
int
adpcm_dec_sin(int rad) {
int diff;
int app = 0;
int inc = 1;
/* MAX dependent on rad's value, say 50 */
__pragma_loopbound(0, 0);
while (rad > 2 * PI)
rad -= 2 * PI;
__pragma_loopbound(0, 1999);
while (rad < -2 * PI)
rad += 2 * PI;
diff = rad;
app = diff;
diff = (diff * (-(rad * rad))) / ((2 * inc) * (2 * inc + 1));
app = app + diff;
inc++;
/* REALLY: while(my_fabs(diff) >= 0.00001) { */
/* MAX: 1000 */
__pragma_loopbound(849, 2424);
while (adpcm_dec_fabs(diff) >= 1) {
diff = (diff * (-(rad * rad))) / ((2 * inc) * (2 * inc + 1));
app = app + diff;
inc++;
}
return app;
}
int
adpcm_dec_cos(int rad) {
return (adpcm_dec_sin(PI / 2 - rad));
}
/*
Algorithm core functions
*/
/* decode function, result in xout1 and xout2 */
void
adpcm_dec_decode(int input) {
int i;
long int xa1, xa2; /* qmf accumulators */
int *h_ptr, *ac_ptr, *ac_ptr1, *ad_ptr, *ad_ptr1;
/* split transmitted word from input into ilr and ih */
adpcm_dec_ilr = input & 0x3f;
adpcm_dec_ih = input >> 6;
/* LOWER SUB_BAND DECODER */
/* filtez: compute predictor output for zero section */
adpcm_dec_dec_szl =
adpcm_dec_filtez(adpcm_dec_dec_del_bpl, adpcm_dec_dec_del_dltx);
/* filtep: compute predictor output signal for pole section */
adpcm_dec_dec_spl = adpcm_dec_filtep(adpcm_dec_dec_rlt1, adpcm_dec_dec_al1,
adpcm_dec_dec_rlt2, adpcm_dec_dec_al2);
adpcm_dec_dec_sl = adpcm_dec_dec_spl + adpcm_dec_dec_szl;
/* invqxl: compute quantized difference signal for adaptive predic */
adpcm_dec_dec_dlt = ((long) adpcm_dec_dec_detl *
adpcm_dec_qq4_code4_table[adpcm_dec_ilr >> 2]) >>
15;
/* invqxl: compute quantized difference signal for decoder output */
adpcm_dec_dl =
((long) adpcm_dec_dec_detl * adpcm_dec_qq6_code6_table[adpcm_dec_il]) >>
15;
adpcm_dec_rl = adpcm_dec_dl + adpcm_dec_dec_sl;
/* logscl: quantizer scale factor adaptation in the lower sub-band */
adpcm_dec_dec_nbl = adpcm_dec_logscl(adpcm_dec_ilr, adpcm_dec_dec_nbl);
/* scalel: computes quantizer scale factor in the lower sub band */
adpcm_dec_dec_detl = adpcm_dec_scalel(adpcm_dec_dec_nbl, 8);
/* parrec - add pole predictor output to quantized diff. signal */
/* for partially reconstructed signal */
adpcm_dec_dec_plt = adpcm_dec_dec_dlt + adpcm_dec_dec_szl;
/* upzero: update zero section predictor coefficients */
adpcm_dec_upzero(adpcm_dec_dec_dlt, adpcm_dec_dec_del_dltx,
adpcm_dec_dec_del_bpl);
/* uppol2: update second predictor coefficient apl2 and delay it as al2 */
adpcm_dec_dec_al2 = adpcm_dec_uppol2(adpcm_dec_dec_al1, adpcm_dec_dec_al2,
adpcm_dec_dec_plt, adpcm_dec_dec_plt1,
adpcm_dec_dec_plt2);
/* uppol1: update first predictor coef. (pole setion) */
adpcm_dec_dec_al1 = adpcm_dec_uppol1(adpcm_dec_dec_al1, adpcm_dec_dec_al2,
adpcm_dec_dec_plt, adpcm_dec_dec_plt1);
/* recons : compute recontructed signal for adaptive predictor */
adpcm_dec_dec_rlt = adpcm_dec_dec_sl + adpcm_dec_dec_dlt;
/* done with lower sub band decoder, implement delays for next time */
adpcm_dec_dec_rlt2 = adpcm_dec_dec_rlt1;
adpcm_dec_dec_rlt1 = adpcm_dec_dec_rlt;
adpcm_dec_dec_plt2 = adpcm_dec_dec_plt1;
adpcm_dec_dec_plt1 = adpcm_dec_dec_plt;
/* HIGH SUB-BAND DECODER */
/* filtez: compute predictor output for zero section */
adpcm_dec_dec_szh =
adpcm_dec_filtez(adpcm_dec_dec_del_bph, adpcm_dec_dec_del_dhx);
/* filtep: compute predictor output signal for pole section */
adpcm_dec_dec_sph = adpcm_dec_filtep(adpcm_dec_dec_rh1, adpcm_dec_dec_ah1,
adpcm_dec_dec_rh2, adpcm_dec_dec_ah2);
/* predic:compute the predictor output value in the higher sub_band decoder
*/
adpcm_dec_dec_sh = adpcm_dec_dec_sph + adpcm_dec_dec_szh;
/* invqah: in-place compute the quantized difference signal */
adpcm_dec_dec_dh =
((long) adpcm_dec_dec_deth * adpcm_dec_qq2_code2_table[adpcm_dec_ih]) >>
15L;
/* logsch: update logarithmic quantizer scale factor in hi sub band */
adpcm_dec_dec_nbh = adpcm_dec_logsch(adpcm_dec_ih, adpcm_dec_dec_nbh);
/* scalel: compute the quantizer scale factor in the higher sub band */
adpcm_dec_dec_deth = adpcm_dec_scalel(adpcm_dec_dec_nbh, 10);
/* parrec: compute partially recontructed signal */
adpcm_dec_dec_ph = adpcm_dec_dec_dh + adpcm_dec_dec_szh;
/* upzero: update zero section predictor coefficients */
adpcm_dec_upzero(adpcm_dec_dec_dh, adpcm_dec_dec_del_dhx,
adpcm_dec_dec_del_bph);
/* uppol2: update second predictor coefficient aph2 and delay it as ah2 */
adpcm_dec_dec_ah2 =
adpcm_dec_uppol2(adpcm_dec_dec_ah1, adpcm_dec_dec_ah2, adpcm_dec_dec_ph,
adpcm_dec_dec_ph1, adpcm_dec_dec_ph2);
/* uppol1: update first predictor coef. (pole setion) */
adpcm_dec_dec_ah1 = adpcm_dec_uppol1(adpcm_dec_dec_ah1, adpcm_dec_dec_ah2,
adpcm_dec_dec_ph, adpcm_dec_dec_ph1);
/* recons : compute recontructed signal for adaptive predictor */
adpcm_dec_rh = adpcm_dec_dec_sh + adpcm_dec_dec_dh;
/* done with high band decode, implementing delays for next time here */
adpcm_dec_dec_rh2 = adpcm_dec_dec_rh1;
adpcm_dec_dec_rh1 = adpcm_dec_rh;
adpcm_dec_dec_ph2 = adpcm_dec_dec_ph1;
adpcm_dec_dec_ph1 = adpcm_dec_dec_ph;
/* end of higher sub_band decoder */
/* end with receive quadrature mirror filters */
adpcm_dec_xd = adpcm_dec_rl - adpcm_dec_rh;
adpcm_dec_xs = adpcm_dec_rl + adpcm_dec_rh;
/* receive quadrature mirror filters implemented here */
h_ptr = adpcm_dec_h;
ac_ptr = adpcm_dec_accumc;
ad_ptr = adpcm_dec_accumd;
xa1 = (long) adpcm_dec_xd * (*h_ptr++);
xa2 = (long) adpcm_dec_xs * (*h_ptr++);
/* main multiply accumulate loop for samples and coefficients */
__pragma_loopbound(10, 10);
for (i = 0; i < 10; i++) {
xa1 += (long) (*ac_ptr++) * (*h_ptr++);
xa2 += (long) (*ad_ptr++) * (*h_ptr++);
}
/* final mult/accumulate */
xa1 += (long) (*ac_ptr) * (*h_ptr++);
xa2 += (long) (*ad_ptr) * (*h_ptr++);
/* scale by 2^14 */
adpcm_dec_xout1 = xa1 >> 14;
adpcm_dec_xout2 = xa2 >> 14;
/* update delay lines */
ac_ptr1 = ac_ptr - 1;
ad_ptr1 = ad_ptr - 1;
__pragma_loopbound(10, 10);
for (i = 0; i < 10; i++) {
*ac_ptr-- = *ac_ptr1--;
*ad_ptr-- = *ad_ptr1--;
}
*ac_ptr = adpcm_dec_xd;
*ad_ptr = adpcm_dec_xs;
return;
}
/* filtez - compute predictor output signal (zero section) */
/* input: bpl1-6 and dlt1-6, output: szl */
int
adpcm_dec_filtez(int *bpl, int *dlt) {
int i;
long int zl;
zl = (long) (*bpl++) * (*dlt++);
/* MAX: 5 */
__pragma_loopbound(5, 5);
for (i = 1; i < 6; i++)
zl += (long) (*bpl++) * (*dlt++);
return ((int) (zl >> 14)); /* x2 here */
}
/* filtep - compute predictor output signal (pole section) */
/* input rlt1-2 and al1-2, output spl */
int
adpcm_dec_filtep(int rlt1, int al1, int rlt2, int al2) {
long int pl, pl2;
pl = 2 * rlt1;
pl = (long) al1 * pl;
pl2 = 2 * rlt2;
pl += (long) al2 * pl2;
return ((int) (pl >> 15));
}
/* logscl - update log quantizer scale factor in lower sub-band */
/* note that nbl is passed and returned */
int
adpcm_dec_logscl(int il, int nbl) {
long int wd;
wd = ((long) nbl * 127L) >> 7L; /* leak factor 127/128 */
nbl = (int) wd + adpcm_dec_wl_code_table[il >> 2];
if (nbl < 0)
nbl = 0;
if (nbl > 18432)
nbl = 18432;
return (nbl);
}
/* scalel: compute quantizer scale factor in lower or upper sub-band*/
int
adpcm_dec_scalel(int nbl, int shift_constant) {
int wd1, wd2, wd3;
wd1 = (nbl >> 6) & 31;
wd2 = nbl >> 11;
wd3 = adpcm_dec_ilb_table[wd1] >> (shift_constant + 1 - wd2);
return (wd3 << 3);
}
/* upzero - inputs: dlt, dlti[ 0-5 ], bli[ 0-5 ], outputs: updated bli[ 0-5 ] */
/* also implements delay of bli and update of dlti from dlt */
void
adpcm_dec_upzero(int dlt, int *dlti, int *bli) {
int i, wd2, wd3;
/*if dlt is zero, then no sum into bli */
if (dlt == 0) {
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
bli[i] = (int) ((255L * bli[i]) >> 8L); /* leak factor of 255/256 */
}
} else {
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
if ((long) dlt * dlti[i] >= 0)
wd2 = 128;
else
wd2 = -128;
wd3 = (int) ((255L * bli[i]) >> 8L); /* leak factor of 255/256 */
bli[i] = wd2 + wd3;
}
}
/* implement delay line for dlt */
dlti[5] = dlti[4];
dlti[4] = dlti[3];
dlti[3] = dlti[2];
dlti[1] = dlti[0];
dlti[0] = dlt;
return;
}
/* uppol2 - update second predictor coefficient (pole section) */
/* inputs: al1, al2, plt, plt1, plt2. outputs: apl2 */
int
adpcm_dec_uppol2(int al1, int al2, int plt, int plt1, int plt2) {
long int wd2, wd4;
int apl2;
wd2 = 4L * (long) al1;
if ((long) plt * plt1 >= 0L)
wd2 = -wd2; /* check same sign */
wd2 = wd2 >> 7; /* gain of 1/128 */
if ((long) plt * plt2 >= 0L) {
wd4 = wd2 + 128; /* same sign case */
} else
wd4 = wd2 - 128;
apl2 = wd4 + (127L * (long) al2 >> 7L); /* leak factor of 127/128 */
/* apl2 is limited to +-.75 */
if (apl2 > 12288)
apl2 = 12288;
if (apl2 < -12288)
apl2 = -12288;
return (apl2);
}
/* uppol1 - update first predictor coefficient (pole section) */
/* inputs: al1, apl2, plt, plt1. outputs: apl1 */
int
adpcm_dec_uppol1(int al1, int apl2, int plt, int plt1) {
long int wd2;
int wd3, apl1;
wd2 = ((long) al1 * 255L) >> 8L; /* leak factor of 255/256 */
if ((long) plt * plt1 >= 0L) {
apl1 = (int) wd2 + 192; /* same sign case */
} else
apl1 = (int) wd2 - 192;
/* note: wd3= .9375-.75 is always positive */
wd3 = 15360 - apl2; /* limit value */
if (apl1 > wd3)
apl1 = wd3;
if (apl1 < -wd3)
apl1 = -wd3;
return (apl1);
}
/* logsch - update log quantizer scale factor in higher sub-band */
/* note that nbh is passed and returned */
int
adpcm_dec_logsch(int ih, int nbh) {
int wd;
wd = ((long) nbh * 127L) >> 7L; /* leak factor 127/128 */
nbh = wd + adpcm_dec_wh_code_table[ih];
if (nbh < 0)
nbh = 0;
if (nbh > 22528)
nbh = 22528;
return (nbh);
}
/*
Initialization- and return-value-related functions
*/
/* clear all storage locations */
void
adpcm_dec_reset() {
int i;
adpcm_dec_detl = adpcm_dec_dec_detl = 32; /* reset to min scale factor */
adpcm_dec_deth = adpcm_dec_dec_deth = 8;
adpcm_dec_nbl = adpcm_dec_al1 = adpcm_dec_al2 = adpcm_dec_plt1 =
adpcm_dec_plt2 = adpcm_dec_rlt1 = adpcm_dec_rlt2 = 0;
adpcm_dec_nbh = adpcm_dec_ah1 = adpcm_dec_ah2 = adpcm_dec_ph1 =
adpcm_dec_ph2 = adpcm_dec_rh1 = adpcm_dec_rh2 = 0;
adpcm_dec_dec_nbl = adpcm_dec_dec_al1 = adpcm_dec_dec_al2 =
adpcm_dec_dec_plt1 = adpcm_dec_dec_plt2 = adpcm_dec_dec_rlt1 =
adpcm_dec_dec_rlt2 = 0;
adpcm_dec_dec_nbh = adpcm_dec_dec_ah1 = adpcm_dec_dec_ah2 =
adpcm_dec_dec_ph1 = adpcm_dec_dec_ph2 = adpcm_dec_dec_rh1 =
adpcm_dec_dec_rh2 = 0;
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
////delay_dltx[ i ] = 0;
adpcm_dec_delay_dhx[i] = 0;
adpcm_dec_dec_del_dltx[i] = 0;
adpcm_dec_dec_del_dhx[i] = 0;
}
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
// delay_bpl[ i ] = 0;
adpcm_dec_delay_bph[i] = 0;
adpcm_dec_dec_del_bpl[i] = 0;
adpcm_dec_dec_del_bph[i] = 0;
}
__pragma_loopbound(11, 11);
for (i = 0; i < 11; i++) {
adpcm_dec_accumc[i] = 0;
adpcm_dec_accumd[i] = 0;
}
return;
}
void
adpcm_dec_init() {
int i, j, f;
volatile int x = 0;
/* read in amplitude and frequency for test data */
j = 10;
f = 2000;
/* reset, initialize required memory */
adpcm_dec_reset();
/* 16 KHz sample rate */
/* XXmain_0, MAX: 2 */
/* Since the number of times we loop in adpcm_dec_sin depends on the
argument we add the fact: xxmain_0:[ ]: */
__pragma_loopbound(3, 3);
for (i = 0; i < SIZE; i++) {
adpcm_dec_test_data[i] = (int) j * adpcm_dec_cos(f * PI * i);
/* avoid constant-propagation optimizations */
adpcm_dec_test_data[i] += x;
}
}
int
adpcm_dec_return() {
int i;
int check_sum = 0;
__pragma_loopbound(2, 2);
for (i = 0; i < IN_END; i += 2)
check_sum += (adpcm_dec_result[i] + adpcm_dec_result[i + 1]);
return check_sum != -2;
}
/*
Main functions
*/
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
adpcm_dec_main(void) {
int i;
__pragma_loopbound(2, 2);
for (i = 0; i < IN_END; i += 2) {
adpcm_dec_decode(adpcm_dec_compressed[i / 2]);
adpcm_dec_result[i] = adpcm_dec_xout1;
adpcm_dec_result[i + 1] = adpcm_dec_xout2;
}
}
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
adpcm_dec_init();
adpcm_dec_main();
return (adpcm_dec_return());
}

View File

@ -0,0 +1,690 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 1.x
Name: adpcm_dec
Author: Sung-Soo Lim
Function:
CCITT G.722 ADPCM (Adaptive Differential Pulse Code Modulation)
algorithm.
16khz sample rate data is stored in the array test_data[ SIZE ].
Results are stored in the array compressed[ SIZE ] and result[ SIZE ].
Execution time is determined by the constant SIZE (default value
is 2000).
Source: SNU-RT Benchmark Suite
Changes: adpcm benchmark was split into decode and encode benchmark
License: may be used, modified, and re-distributed freely, but
the SNU-RT Benchmark Suite must be acknowledged
*/
/*
This program is derived from the SNU-RT Benchmark Suite for Worst
Case Timing Analysis by Sung-Soo Lim
Original source: C Algorithms for Real-Time DSP by P. M. Embree
*/
/*
Forward declaration of functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline void adpcm_dec_decode(int);
__attribute__((always_inline)) static inline int adpcm_dec_filtez(int *bpl,
int *dlt);
__attribute__((always_inline)) static inline void
adpcm_dec_upzero(int dlt, int *dlti, int *bli);
__attribute__((always_inline)) static inline int
adpcm_dec_filtep(int rlt1, int al1, int rlt2, int al2);
__attribute__((always_inline)) static inline int adpcm_dec_logscl(int il,
int nbl);
__attribute__((always_inline)) static inline int
adpcm_dec_scalel(int nbl, int shift_constant);
__attribute__((always_inline)) static inline int
adpcm_dec_uppol2(int al1, int al2, int plt, int plt1, int plt2);
__attribute__((always_inline)) static inline int
adpcm_dec_uppol1(int al1, int apl2, int plt, int plt1);
__attribute__((always_inline)) static inline int adpcm_dec_logsch(int ih,
int nbh);
__attribute__((always_inline)) static inline void adpcm_dec_reset();
__attribute__((always_inline)) static inline int adpcm_dec_fabs(int n);
__attribute__((always_inline)) static inline int adpcm_dec_cos(int n);
__attribute__((always_inline)) static inline int adpcm_dec_sin(int n);
__attribute__((always_inline)) static inline void adpcm_dec_init();
__attribute__((always_inline)) static inline int adpcm_dec_return();
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
adpcm_dec_main();
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void);
/*
Declaration of macros
*/
/* common sampling rate for sound cards on IBM/PC */
#define SAMPLE_RATE 11025
#define PI 3141
#define SIZE 3
#define IN_END 4
/*
Declaration of global variables
*/
int adpcm_dec_test_data[SIZE * 2], adpcm_dec_result[SIZE * 2];
/* Input data for the decoder usually generated by the encoder. */
int adpcm_dec_compressed[SIZE] = {0, 253, 32};
/* G722 C code */
/* QMF filter coefficients:
scaled by a factor of 4 compared to G722 CCITT recommendation */
int adpcm_dec_h[24] = {12, -44, -44, 212, 48, -624, 128, 1448,
-840, -3220, 3804, 15504, 15504, 3804, -3220, -840,
1448, 128, -624, 48, 212, -44, -44, 12};
// int xl,xh;
/* variables for receive quadrature mirror filter here */
int adpcm_dec_accumc[11], adpcm_dec_accumd[11];
/* outputs of decode() */
int adpcm_dec_xout1, adpcm_dec_xout2;
int adpcm_dec_xs, adpcm_dec_xd;
/* variables for encoder (hi and lo) here */
int adpcm_dec_il, adpcm_dec_szl, adpcm_dec_spl, adpcm_dec_sl, adpcm_dec_el;
int adpcm_dec_qq4_code4_table[16] = {0, -20456, -12896, -8968, -6288, -4240,
-2584, -1200, 20456, 12896, 8968, 6288,
4240, 2584, 1200, 0};
int adpcm_dec_qq6_code6_table[64] = {
-136, -136, -136, -136, -24808, -21904, -19008, -16704,
-14984, -13512, -12280, -11192, -10232, -9360, -8576, -7856,
-7192, -6576, -6000, -5456, -4944, -4464, -4008, -3576,
-3168, -2776, -2400, -2032, -1688, -1360, -1040, -728,
24808, 21904, 19008, 16704, 14984, 13512, 12280, 11192,
10232, 9360, 8576, 7856, 7192, 6576, 6000, 5456,
4944, 4464, 4008, 3576, 3168, 2776, 2400, 2032,
1688, 1360, 1040, 728, 432, 136, -432, -136};
int adpcm_dec_wl_code_table[16] = {-60, 3042, 1198, 538, 334, 172, 58, -30,
3042, 1198, 538, 334, 172, 58, -30, -60};
int adpcm_dec_ilb_table[32] = {2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383,
2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834,
2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371,
3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008};
int adpcm_dec_nbl; /* delay line */
int adpcm_dec_al1, adpcm_dec_al2;
int adpcm_dec_plt, adpcm_dec_plt1, adpcm_dec_plt2;
int adpcm_dec_rs;
int adpcm_dec_dlt;
int adpcm_dec_rlt, adpcm_dec_rlt1, adpcm_dec_rlt2;
int adpcm_dec_detl;
int adpcm_dec_deth;
int adpcm_dec_sh; /* this comes from adaptive predictor */
int adpcm_dec_eh;
int adpcm_dec_qq2_code2_table[4] = {-7408, -1616, 7408, 1616};
int adpcm_dec_wh_code_table[4] = {798, -214, 798, -214};
int adpcm_dec_dh, adpcm_dec_ih;
int adpcm_dec_nbh, adpcm_dec_szh;
int adpcm_dec_sph, adpcm_dec_ph, adpcm_dec_yh, adpcm_dec_rh;
int adpcm_dec_delay_dhx[6];
int adpcm_dec_delay_bph[6];
int adpcm_dec_ah1, adpcm_dec_ah2;
int adpcm_dec_ph1, adpcm_dec_ph2;
int adpcm_dec_rh1, adpcm_dec_rh2;
/* variables for decoder here */
int adpcm_dec_ilr, adpcm_dec_yl, adpcm_dec_rl;
int adpcm_dec_dec_deth, adpcm_dec_dec_detl, adpcm_dec_dec_dlt;
int adpcm_dec_dec_del_bpl[6];
int adpcm_dec_dec_del_dltx[6];
int adpcm_dec_dec_plt, adpcm_dec_dec_plt1, adpcm_dec_dec_plt2;
int adpcm_dec_dec_szl, adpcm_dec_dec_spl, adpcm_dec_dec_sl;
int adpcm_dec_dec_rlt1, adpcm_dec_dec_rlt2, adpcm_dec_dec_rlt;
int adpcm_dec_dec_al1, adpcm_dec_dec_al2;
int adpcm_dec_dl;
int adpcm_dec_dec_nbl, adpcm_dec_dec_yh, adpcm_dec_dec_dh, adpcm_dec_dec_nbh;
/* variables used in filtez */
int adpcm_dec_dec_del_bph[6];
int adpcm_dec_dec_del_dhx[6];
int adpcm_dec_dec_szh;
/* variables used in filtep */
int adpcm_dec_dec_rh1, adpcm_dec_dec_rh2;
int adpcm_dec_dec_ah1, adpcm_dec_dec_ah2;
int adpcm_dec_dec_ph, adpcm_dec_dec_sph;
int adpcm_dec_dec_sh, adpcm_dec_dec_rh;
int adpcm_dec_dec_ph1, adpcm_dec_dec_ph2;
/*
Arithmetic math functions
*/
/* MAX: 1 */
__attribute__((always_inline)) static inline int
adpcm_dec_fabs(int n) {
int f;
if (n >= 0)
f = n;
else
f = -n;
return f;
}
__attribute__((always_inline)) static inline int
adpcm_dec_sin(int rad) {
int diff;
int app = 0;
int inc = 1;
/* MAX dependent on rad's value, say 50 */
__pragma_loopbound(0, 0);
while (rad > 2 * PI)
rad -= 2 * PI;
__pragma_loopbound(0, 1999);
while (rad < -2 * PI)
rad += 2 * PI;
diff = rad;
app = diff;
diff = (diff * (-(rad * rad))) / ((2 * inc) * (2 * inc + 1));
app = app + diff;
inc++;
/* REALLY: while(my_fabs(diff) >= 0.00001) { */
/* MAX: 1000 */
__pragma_loopbound(849, 2424);
while (adpcm_dec_fabs(diff) >= 1) {
diff = (diff * (-(rad * rad))) / ((2 * inc) * (2 * inc + 1));
app = app + diff;
inc++;
}
return app;
}
__attribute__((always_inline)) static inline int
adpcm_dec_cos(int rad) {
return (adpcm_dec_sin(PI / 2 - rad));
}
/*
Algorithm core functions
*/
/* decode function, result in xout1 and xout2 */
__attribute__((always_inline)) static inline void
adpcm_dec_decode(int input) {
int i;
long int xa1, xa2; /* qmf accumulators */
int *h_ptr, *ac_ptr, *ac_ptr1, *ad_ptr, *ad_ptr1;
/* split transmitted word from input into ilr and ih */
adpcm_dec_ilr = input & 0x3f;
adpcm_dec_ih = input >> 6;
/* LOWER SUB_BAND DECODER */
/* filtez: compute predictor output for zero section */
adpcm_dec_dec_szl =
adpcm_dec_filtez(adpcm_dec_dec_del_bpl, adpcm_dec_dec_del_dltx);
/* filtep: compute predictor output signal for pole section */
adpcm_dec_dec_spl = adpcm_dec_filtep(adpcm_dec_dec_rlt1, adpcm_dec_dec_al1,
adpcm_dec_dec_rlt2, adpcm_dec_dec_al2);
adpcm_dec_dec_sl = adpcm_dec_dec_spl + adpcm_dec_dec_szl;
/* invqxl: compute quantized difference signal for adaptive predic */
adpcm_dec_dec_dlt = ((long) adpcm_dec_dec_detl *
adpcm_dec_qq4_code4_table[adpcm_dec_ilr >> 2]) >>
15;
/* invqxl: compute quantized difference signal for decoder output */
adpcm_dec_dl =
((long) adpcm_dec_dec_detl * adpcm_dec_qq6_code6_table[adpcm_dec_il]) >>
15;
adpcm_dec_rl = adpcm_dec_dl + adpcm_dec_dec_sl;
/* logscl: quantizer scale factor adaptation in the lower sub-band */
adpcm_dec_dec_nbl = adpcm_dec_logscl(adpcm_dec_ilr, adpcm_dec_dec_nbl);
/* scalel: computes quantizer scale factor in the lower sub band */
adpcm_dec_dec_detl = adpcm_dec_scalel(adpcm_dec_dec_nbl, 8);
/* parrec - add pole predictor output to quantized diff. signal */
/* for partially reconstructed signal */
adpcm_dec_dec_plt = adpcm_dec_dec_dlt + adpcm_dec_dec_szl;
/* upzero: update zero section predictor coefficients */
adpcm_dec_upzero(adpcm_dec_dec_dlt, adpcm_dec_dec_del_dltx,
adpcm_dec_dec_del_bpl);
/* uppol2: update second predictor coefficient apl2 and delay it as al2 */
adpcm_dec_dec_al2 = adpcm_dec_uppol2(adpcm_dec_dec_al1, adpcm_dec_dec_al2,
adpcm_dec_dec_plt, adpcm_dec_dec_plt1,
adpcm_dec_dec_plt2);
/* uppol1: update first predictor coef. (pole setion) */
adpcm_dec_dec_al1 = adpcm_dec_uppol1(adpcm_dec_dec_al1, adpcm_dec_dec_al2,
adpcm_dec_dec_plt, adpcm_dec_dec_plt1);
/* recons : compute recontructed signal for adaptive predictor */
adpcm_dec_dec_rlt = adpcm_dec_dec_sl + adpcm_dec_dec_dlt;
/* done with lower sub band decoder, implement delays for next time */
adpcm_dec_dec_rlt2 = adpcm_dec_dec_rlt1;
adpcm_dec_dec_rlt1 = adpcm_dec_dec_rlt;
adpcm_dec_dec_plt2 = adpcm_dec_dec_plt1;
adpcm_dec_dec_plt1 = adpcm_dec_dec_plt;
/* HIGH SUB-BAND DECODER */
/* filtez: compute predictor output for zero section */
adpcm_dec_dec_szh =
adpcm_dec_filtez(adpcm_dec_dec_del_bph, adpcm_dec_dec_del_dhx);
/* filtep: compute predictor output signal for pole section */
adpcm_dec_dec_sph = adpcm_dec_filtep(adpcm_dec_dec_rh1, adpcm_dec_dec_ah1,
adpcm_dec_dec_rh2, adpcm_dec_dec_ah2);
/* predic:compute the predictor output value in the higher sub_band decoder
*/
adpcm_dec_dec_sh = adpcm_dec_dec_sph + adpcm_dec_dec_szh;
/* invqah: in-place compute the quantized difference signal */
adpcm_dec_dec_dh =
((long) adpcm_dec_dec_deth * adpcm_dec_qq2_code2_table[adpcm_dec_ih]) >>
15L;
/* logsch: update logarithmic quantizer scale factor in hi sub band */
adpcm_dec_dec_nbh = adpcm_dec_logsch(adpcm_dec_ih, adpcm_dec_dec_nbh);
/* scalel: compute the quantizer scale factor in the higher sub band */
adpcm_dec_dec_deth = adpcm_dec_scalel(adpcm_dec_dec_nbh, 10);
/* parrec: compute partially recontructed signal */
adpcm_dec_dec_ph = adpcm_dec_dec_dh + adpcm_dec_dec_szh;
/* upzero: update zero section predictor coefficients */
adpcm_dec_upzero(adpcm_dec_dec_dh, adpcm_dec_dec_del_dhx,
adpcm_dec_dec_del_bph);
/* uppol2: update second predictor coefficient aph2 and delay it as ah2 */
adpcm_dec_dec_ah2 =
adpcm_dec_uppol2(adpcm_dec_dec_ah1, adpcm_dec_dec_ah2, adpcm_dec_dec_ph,
adpcm_dec_dec_ph1, adpcm_dec_dec_ph2);
/* uppol1: update first predictor coef. (pole setion) */
adpcm_dec_dec_ah1 = adpcm_dec_uppol1(adpcm_dec_dec_ah1, adpcm_dec_dec_ah2,
adpcm_dec_dec_ph, adpcm_dec_dec_ph1);
/* recons : compute recontructed signal for adaptive predictor */
adpcm_dec_rh = adpcm_dec_dec_sh + adpcm_dec_dec_dh;
/* done with high band decode, implementing delays for next time here */
adpcm_dec_dec_rh2 = adpcm_dec_dec_rh1;
adpcm_dec_dec_rh1 = adpcm_dec_rh;
adpcm_dec_dec_ph2 = adpcm_dec_dec_ph1;
adpcm_dec_dec_ph1 = adpcm_dec_dec_ph;
/* end of higher sub_band decoder */
/* end with receive quadrature mirror filters */
adpcm_dec_xd = adpcm_dec_rl - adpcm_dec_rh;
adpcm_dec_xs = adpcm_dec_rl + adpcm_dec_rh;
/* receive quadrature mirror filters implemented here */
h_ptr = adpcm_dec_h;
ac_ptr = adpcm_dec_accumc;
ad_ptr = adpcm_dec_accumd;
xa1 = (long) adpcm_dec_xd * (*h_ptr++);
xa2 = (long) adpcm_dec_xs * (*h_ptr++);
/* main multiply accumulate loop for samples and coefficients */
__pragma_loopbound(10, 10);
for (i = 0; i < 10; i++) {
xa1 += (long) (*ac_ptr++) * (*h_ptr++);
xa2 += (long) (*ad_ptr++) * (*h_ptr++);
}
/* final mult/accumulate */
xa1 += (long) (*ac_ptr) * (*h_ptr++);
xa2 += (long) (*ad_ptr) * (*h_ptr++);
/* scale by 2^14 */
adpcm_dec_xout1 = xa1 >> 14;
adpcm_dec_xout2 = xa2 >> 14;
/* update delay lines */
ac_ptr1 = ac_ptr - 1;
ad_ptr1 = ad_ptr - 1;
__pragma_loopbound(10, 10);
for (i = 0; i < 10; i++) {
*ac_ptr-- = *ac_ptr1--;
*ad_ptr-- = *ad_ptr1--;
}
*ac_ptr = adpcm_dec_xd;
*ad_ptr = adpcm_dec_xs;
return;
}
/* filtez - compute predictor output signal (zero section) */
/* input: bpl1-6 and dlt1-6, output: szl */
__attribute__((always_inline)) static inline int
adpcm_dec_filtez(int *bpl, int *dlt) {
int i;
long int zl;
zl = (long) (*bpl++) * (*dlt++);
/* MAX: 5 */
__pragma_loopbound(5, 5);
for (i = 1; i < 6; i++)
zl += (long) (*bpl++) * (*dlt++);
return ((int) (zl >> 14)); /* x2 here */
}
/* filtep - compute predictor output signal (pole section) */
/* input rlt1-2 and al1-2, output spl */
__attribute__((always_inline)) static inline int
adpcm_dec_filtep(int rlt1, int al1, int rlt2, int al2) {
long int pl, pl2;
pl = 2 * rlt1;
pl = (long) al1 * pl;
pl2 = 2 * rlt2;
pl += (long) al2 * pl2;
return ((int) (pl >> 15));
}
/* logscl - update log quantizer scale factor in lower sub-band */
/* note that nbl is passed and returned */
__attribute__((always_inline)) static inline int
adpcm_dec_logscl(int il, int nbl) {
long int wd;
wd = ((long) nbl * 127L) >> 7L; /* leak factor 127/128 */
nbl = (int) wd + adpcm_dec_wl_code_table[il >> 2];
if (nbl < 0)
nbl = 0;
if (nbl > 18432)
nbl = 18432;
return (nbl);
}
/* scalel: compute quantizer scale factor in lower or upper sub-band*/
__attribute__((always_inline)) static inline int
adpcm_dec_scalel(int nbl, int shift_constant) {
int wd1, wd2, wd3;
wd1 = (nbl >> 6) & 31;
wd2 = nbl >> 11;
wd3 = adpcm_dec_ilb_table[wd1] >> (shift_constant + 1 - wd2);
return (wd3 << 3);
}
/* upzero - inputs: dlt, dlti[ 0-5 ], bli[ 0-5 ], outputs: updated bli[ 0-5 ] */
/* also implements delay of bli and update of dlti from dlt */
__attribute__((always_inline)) static inline void
adpcm_dec_upzero(int dlt, int *dlti, int *bli) {
int i, wd2, wd3;
/*if dlt is zero, then no sum into bli */
if (dlt == 0) {
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
bli[i] = (int) ((255L * bli[i]) >> 8L); /* leak factor of 255/256 */
}
} else {
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
if ((long) dlt * dlti[i] >= 0)
wd2 = 128;
else
wd2 = -128;
wd3 = (int) ((255L * bli[i]) >> 8L); /* leak factor of 255/256 */
bli[i] = wd2 + wd3;
}
}
/* implement delay line for dlt */
dlti[5] = dlti[4];
dlti[4] = dlti[3];
dlti[3] = dlti[2];
dlti[1] = dlti[0];
dlti[0] = dlt;
return;
}
/* uppol2 - update second predictor coefficient (pole section) */
/* inputs: al1, al2, plt, plt1, plt2. outputs: apl2 */
__attribute__((always_inline)) static inline int
adpcm_dec_uppol2(int al1, int al2, int plt, int plt1, int plt2) {
long int wd2, wd4;
int apl2;
wd2 = 4L * (long) al1;
if ((long) plt * plt1 >= 0L)
wd2 = -wd2; /* check same sign */
wd2 = wd2 >> 7; /* gain of 1/128 */
if ((long) plt * plt2 >= 0L) {
wd4 = wd2 + 128; /* same sign case */
} else
wd4 = wd2 - 128;
apl2 = wd4 + (127L * (long) al2 >> 7L); /* leak factor of 127/128 */
/* apl2 is limited to +-.75 */
if (apl2 > 12288)
apl2 = 12288;
if (apl2 < -12288)
apl2 = -12288;
return (apl2);
}
/* uppol1 - update first predictor coefficient (pole section) */
/* inputs: al1, apl2, plt, plt1. outputs: apl1 */
__attribute__((always_inline)) static inline int
adpcm_dec_uppol1(int al1, int apl2, int plt, int plt1) {
long int wd2;
int wd3, apl1;
wd2 = ((long) al1 * 255L) >> 8L; /* leak factor of 255/256 */
if ((long) plt * plt1 >= 0L) {
apl1 = (int) wd2 + 192; /* same sign case */
} else
apl1 = (int) wd2 - 192;
/* note: wd3= .9375-.75 is always positive */
wd3 = 15360 - apl2; /* limit value */
if (apl1 > wd3)
apl1 = wd3;
if (apl1 < -wd3)
apl1 = -wd3;
return (apl1);
}
/* logsch - update log quantizer scale factor in higher sub-band */
/* note that nbh is passed and returned */
__attribute__((always_inline)) static inline int
adpcm_dec_logsch(int ih, int nbh) {
int wd;
wd = ((long) nbh * 127L) >> 7L; /* leak factor 127/128 */
nbh = wd + adpcm_dec_wh_code_table[ih];
if (nbh < 0)
nbh = 0;
if (nbh > 22528)
nbh = 22528;
return (nbh);
}
/*
Initialization- and return-value-related functions
*/
/* clear all storage locations */
__attribute__((always_inline)) static inline void
adpcm_dec_reset() {
int i;
adpcm_dec_detl = adpcm_dec_dec_detl = 32; /* reset to min scale factor */
adpcm_dec_deth = adpcm_dec_dec_deth = 8;
adpcm_dec_nbl = adpcm_dec_al1 = adpcm_dec_al2 = adpcm_dec_plt1 =
adpcm_dec_plt2 = adpcm_dec_rlt1 = adpcm_dec_rlt2 = 0;
adpcm_dec_nbh = adpcm_dec_ah1 = adpcm_dec_ah2 = adpcm_dec_ph1 =
adpcm_dec_ph2 = adpcm_dec_rh1 = adpcm_dec_rh2 = 0;
adpcm_dec_dec_nbl = adpcm_dec_dec_al1 = adpcm_dec_dec_al2 =
adpcm_dec_dec_plt1 = adpcm_dec_dec_plt2 = adpcm_dec_dec_rlt1 =
adpcm_dec_dec_rlt2 = 0;
adpcm_dec_dec_nbh = adpcm_dec_dec_ah1 = adpcm_dec_dec_ah2 =
adpcm_dec_dec_ph1 = adpcm_dec_dec_ph2 = adpcm_dec_dec_rh1 =
adpcm_dec_dec_rh2 = 0;
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
////delay_dltx[ i ] = 0;
adpcm_dec_delay_dhx[i] = 0;
adpcm_dec_dec_del_dltx[i] = 0;
adpcm_dec_dec_del_dhx[i] = 0;
}
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
// delay_bpl[ i ] = 0;
adpcm_dec_delay_bph[i] = 0;
adpcm_dec_dec_del_bpl[i] = 0;
adpcm_dec_dec_del_bph[i] = 0;
}
__pragma_loopbound(11, 11);
for (i = 0; i < 11; i++) {
adpcm_dec_accumc[i] = 0;
adpcm_dec_accumd[i] = 0;
}
return;
}
__attribute__((always_inline)) static inline void
adpcm_dec_init() {
int i, j, f;
volatile int x = 0;
/* read in amplitude and frequency for test data */
j = 10;
f = 2000;
/* reset, initialize required memory */
adpcm_dec_reset();
/* 16 KHz sample rate */
/* XXmain_0, MAX: 2 */
/* Since the number of times we loop in adpcm_dec_sin depends on the
argument we add the fact: xxmain_0:[ ]: */
__pragma_loopbound(3, 3);
for (i = 0; i < SIZE; i++) {
adpcm_dec_test_data[i] = (int) j * adpcm_dec_cos(f * PI * i);
/* avoid constant-propagation optimizations */
adpcm_dec_test_data[i] += x;
}
}
__attribute__((always_inline)) static inline int
adpcm_dec_return() {
int i;
int check_sum = 0;
__pragma_loopbound(2, 2);
for (i = 0; i < IN_END; i += 2)
check_sum += (adpcm_dec_result[i] + adpcm_dec_result[i + 1]);
return check_sum != -2;
}
/*
Main functions
*/
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
adpcm_dec_main(void) {
int i;
__pragma_loopbound(2, 2);
for (i = 0; i < IN_END; i += 2) {
adpcm_dec_decode(adpcm_dec_compressed[i / 2]);
adpcm_dec_result[i] = adpcm_dec_xout1;
adpcm_dec_result[i + 1] = adpcm_dec_xout2;
}
}
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
adpcm_dec_init();
adpcm_dec_main();
return (adpcm_dec_return());
}

View File

@ -0,0 +1,25 @@
# ~~~
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2026, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
# ~~~
cmake_minimum_required(VERSION 3.20)
project(adpcm_enc)
set(TACLEBENCH_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../..")
set(REPOSITORY_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../..")
set(APP_TARGET_NAME "${CMAKE_PROJECT_NAME}")
if(DEFINED TACLEBENCH_VARIANT AND "${TACLEBENCH_VARIANT}" STREQUAL "inline")
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/inline/adpcm_enc.c")
else()
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/default/adpcm_enc.c")
endif()
include(${REPOSITORY_ROOT_PATH}/cmake/taclebench_wasm.cmake)

View File

@ -0,0 +1,34 @@
File: adpcm_enc.c
Original provenience: C Algorithms for Real-Time DSP by P. M. Embree
2016-03-07:
- Rename adpcm_encode to adpcm_enc
- Add generic TACLeBench header
- Remove #define Seoul_Mate around main
- Remove swedish comment after setting frequency to 2000
- Introduce adpcm_enc_init, adpcm_main, adpcm_return
- Make test_data and compressed global variables
2016-04-26:
- Remove forward declarations of functions gaussian, iir_filter, fir_filter,
fft, setup_codec, key_down, int_enable, int_disable, flags, getinput,
sendout, which are never defined
- Remove commented declarations of invqxl and invqah
- Remove unused structure COMPLEX
- Remove prefix my_ from functions names my_fabs, my_cos, my_sin, my_abs
- Prefix all global symbols with benchmark name
- Remove variables accumc and accumd together with their initialization loop,
since they are never read
- Remove unused variables xs and xd
- Remove unused array wl_table
- Remove unused variable rs and rh
- Remove unused variables and their initializations (only required for decoder):
ilr, yl, rl, dec_deth, dec_del_bpl, dec_plt, dec_plt1, dec_plt2, dec_szl,
dec_spl, dec_sl, dec_rlt1, dec_rlt2, dec_rlt, dec_al1, dec_al2, dl, dec_nbl,
dec_yh, dec_dh, dec_nbh, dec_rh2, dec_ah1, dec_ah2, dec_ph, dec_sph, dec_sh,
dec_rh, dec_ph1, dec_ph2,
- Add addition on each element of input data with volatile variable to
avoid constant-propagation optimizations through the compoiler
- Add computation of check sum
- Add return return statement: zero if check sum is correct
2016-05-20:
- Apply code formatting with astyle

View File

@ -0,0 +1,756 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: adpcm_enc
Author: Sung-Soo Lim
Function: CCITT G.722 ADPCM (Adaptive Differential Pulse Code Modulation)
algorithm. 16khz sample rate data is stored in the array test_data[ SIZE ].
Results are stored in the array compressed[ SIZE ].
Execution time is determined by the constant SIZE (default value is 2000).
Source: C Algorithms for Real-Time DSP by P. M. Embree
and SNU-RT Benchmark Suite for Worst Case Timing Analysis
collected and modified by S.-S. Lim <sslim@archi.snu.ac.kr>
Original name: adpcm_encoder
Changes: no major functional changes
License: may be used, modified, and re-distributed freely, but the
SNU-RT Benchmark Suite must be acknowledged
*/
/* common sampling rate for sound cards on IBM/PC */
#define SAMPLE_RATE 11025
#define PI 3141
#define SIZE 3
#define IN_END 4
/*
Forward declaration of functions
*/
int adpcm_enc_encode( int, int );
int adpcm_enc_filtez( int *bpl, int *dlt );
void adpcm_enc_upzero( int dlt, int *dlti, int *bli );
int adpcm_enc_filtep( int rlt1, int al1, int rlt2, int al2 );
int adpcm_enc_quantl( int el, int detl );
int adpcm_enc_logscl( int il, int nbl );
int adpcm_enc_scalel( int nbl, int shift_constant );
int adpcm_enc_uppol2( int al1, int al2, int plt, int plt1, int plt2 );
int adpcm_enc_uppol1( int al1, int apl2, int plt, int plt1 );
int adpcm_enc_logsch( int ih, int nbh );
void adpcm_enc_reset();
int adpcm_enc_fabs( int n );
int adpcm_enc_cos( int n );
int adpcm_enc_sin( int n );
int adpcm_enc_abs( int n );
void adpcm_enc_init( void );
void adpcm_enc_main( void );
int adpcm_enc_return( void );
int main( void );
/*
Forward declaration of global variables
*/
int adpcm_enc_test_data[ SIZE * 2 ], adpcm_enc_compressed[ SIZE ];
/* G722 C code */
/* variables for transimit quadrature mirror filter here */
int adpcm_enc_tqmf[ 24 ];
/* QMF filter coefficients:
scaled by a factor of 4 compared to G722 CCITT recommendation */
int adpcm_enc_h[ 24 ] = {
12, -44, -44, 212, 48, -624, 128, 1448,
-840, -3220, 3804, 15504, 15504, 3804, -3220, -840,
1448, 128, -624, 48, 212, -44, -44, 12
};
int adpcm_enc_xl, adpcm_enc_xh;
/* variables for encoder (hi and lo) here */
int adpcm_enc_il, adpcm_enc_szl, adpcm_enc_spl, adpcm_enc_sl, adpcm_enc_el;
int adpcm_enc_qq4_code4_table[ 16 ] = {
0, -20456, -12896, -8968, -6288, -4240, -2584, -1200,
20456, 12896, 8968, 6288, 4240, 2584, 1200, 0
};
int adpcm_enc_qq5_code5_table[ 32 ] = {
-280, -280, -23352, -17560, -14120, -11664, -9752, -8184,
-6864, -5712, -4696, -3784, -2960, -2208, -1520, -880,
23352, 17560, 14120, 11664, 9752, 8184, 6864, 5712,
4696, 3784, 2960, 2208, 1520, 880, 280, -280
};
int adpcm_enc_qq6_code6_table[ 64 ] = {
-136, -136, -136, -136, -24808, -21904, -19008, -16704,
-14984, -13512, -12280, -11192, -10232, -9360, -8576, -7856,
-7192, -6576, -6000, -5456, -4944, -4464, -4008, -3576,
-3168, -2776, -2400, -2032, -1688, -1360, -1040, -728,
24808, 21904, 19008, 16704, 14984, 13512, 12280, 11192,
10232, 9360, 8576, 7856, 7192, 6576, 6000, 5456,
4944, 4464, 4008, 3576, 3168, 2776, 2400, 2032,
1688, 1360, 1040, 728, 432, 136, -432, -136
};
int adpcm_enc_delay_bpl[ 6 ];
int adpcm_enc_delay_dltx[ 6 ];
int adpcm_enc_wl_code_table[ 16 ] = {
-60, 3042, 1198, 538, 334, 172, 58, -30,
3042, 1198, 538, 334, 172, 58, -30, -60
};
int adpcm_enc_ilb_table[ 32 ] = {
2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383,
2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834,
2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371,
3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008
};
int adpcm_enc_nbl; /* delay line */
int adpcm_enc_al1, adpcm_enc_al2;
int adpcm_enc_plt, adpcm_enc_plt1, adpcm_enc_plt2;
int adpcm_enc_dlt;
int adpcm_enc_rlt, adpcm_enc_rlt1, adpcm_enc_rlt2;
/* decision levels - pre-multiplied by 8, 0 to indicate end */
int adpcm_enc_decis_levl[ 30 ] = {
280, 576, 880, 1200, 1520, 1864, 2208, 2584,
2960, 3376, 3784, 4240, 4696, 5200, 5712, 6288,
6864, 7520, 8184, 8968, 9752, 10712, 11664, 12896,
14120, 15840, 17560, 20456, 23352, 32767
};
int adpcm_enc_detl;
/* quantization table 31 long to make quantl look-up easier,
last entry is for mil=30 case when wd is max */
int adpcm_enc_quant26bt_pos[ 31 ] = {
61, 60, 59, 58, 57, 56, 55, 54,
53, 52, 51, 50, 49, 48, 47, 46,
45, 44, 43, 42, 41, 40, 39, 38,
37, 36, 35, 34, 33, 32, 32
};
/* quantization table 31 long to make quantl look-up easier,
last entry is for mil=30 case when wd is max */
int adpcm_enc_quant26bt_neg[ 31 ] = {
63, 62, 31, 30, 29, 28, 27, 26,
25, 24, 23, 22, 21, 20, 19, 18,
17, 16, 15, 14, 13, 12, 11, 10,
9, 8, 7, 6, 5, 4, 4
};
int adpcm_enc_deth;
int adpcm_enc_sh; /* this comes from adaptive predictor */
int adpcm_enc_eh;
int adpcm_enc_qq2_code2_table[ 4 ] = {
-7408, -1616, 7408, 1616
};
int adpcm_enc_wh_code_table[ 4 ] = {
798, -214, 798, -214
};
int adpcm_enc_dh, adpcm_enc_ih;
int adpcm_enc_nbh, adpcm_enc_szh;
int adpcm_enc_sph, adpcm_enc_ph, adpcm_enc_yh;
int adpcm_enc_delay_dhx[ 6 ];
int adpcm_enc_delay_bph[ 6 ];
int adpcm_enc_ah1, adpcm_enc_ah2;
int adpcm_enc_ph1, adpcm_enc_ph2;
int adpcm_enc_rh1, adpcm_enc_rh2;
/* G722 encode function two ints in, one 8 bit output */
/* put input samples in xin1 = first value, xin2 = second value */
/* returns il and ih stored together */
/* MAX: 1 */
int adpcm_enc_abs( int n )
{
int m;
if ( n >= 0 )
m = n;
else
m = -n;
return m;
}
/* MAX: 1 */
int adpcm_enc_fabs( int n )
{
int f;
if ( n >= 0 )
f = n;
else
f = -n;
return f;
}
#pragma GCC push_options
#pragma GCC optimize "-fwrapv"
int adpcm_enc_sin( int rad )
{
int diff;
int app = 0;
int inc = 1;
/* MAX dependent on rad's value, say 50 */
_Pragma( "loopbound min 0 max 0" )
while ( rad > 2 * PI )
rad -= 2 * PI;
/* MAX dependent on rad's value, say 50 */
_Pragma( "loopbound min 0 max 1999" )
while ( rad < -2 * PI )
rad += 2 * PI;
diff = rad;
app = diff;
diff = ( diff * ( -( rad * rad ) ) ) / ( ( 2 * inc ) * ( 2 * inc + 1 ) );
app = app + diff;
inc++;
/* REALLY: while(my_fabs(diff) >= 0.00001) { */
/* MAX: 1000 */
_Pragma( "loopbound min 849 max 2424" )
while ( adpcm_enc_fabs( diff ) >= 1 ) {
diff = ( diff * ( -( rad * rad ) ) ) / ( ( 2 * inc ) * ( 2 * inc + 1 ) );
app = app + diff;
inc++;
}
return app;
}
#pragma GCC pop_options
int adpcm_enc_cos( int rad )
{
return ( adpcm_enc_sin( PI / 2 - rad ) );
}
/* MAX: 1 */
int adpcm_enc_encode( int xin1, int xin2 )
{
int i;
int *h_ptr, *tqmf_ptr, *tqmf_ptr1;
long long int xa, xb;
int decis;
/* transmit quadrature mirror filters implemented here */
h_ptr = adpcm_enc_h;
tqmf_ptr = adpcm_enc_tqmf;
xa = ( long long )( *tqmf_ptr++ ) * ( *h_ptr++ );
xb = ( long long )( *tqmf_ptr++ ) * ( *h_ptr++ );
/* main multiply accumulate loop for samples and coefficients */
/* MAX: 10 */
_Pragma( "loopbound min 10 max 10" )
for ( i = 0; i < 10; i++ ) {
xa += ( long long )( *tqmf_ptr++ ) * ( *h_ptr++ );
xb += ( long long )( *tqmf_ptr++ ) * ( *h_ptr++ );
}
/* final mult/accumulate */
xa += ( long long )( *tqmf_ptr++ ) * ( *h_ptr++ );
xb += ( long long )( *tqmf_ptr ) * ( *h_ptr++ );
/* update delay line tqmf */
tqmf_ptr1 = tqmf_ptr - 2;
/* MAX: 22 */
_Pragma( "loopbound min 22 max 22" )
for ( i = 0; i < 22; i++ )
*tqmf_ptr-- = *tqmf_ptr1--;
*tqmf_ptr-- = xin1;
*tqmf_ptr = xin2;
/* scale outputs */
adpcm_enc_xl = ( xa + xb ) >> 15;
adpcm_enc_xh = ( xa - xb ) >> 15;
/* end of quadrature mirror filter code */
/* starting with lower sub band encoder */
/* filtez - compute predictor output section - zero section */
adpcm_enc_szl = adpcm_enc_filtez( adpcm_enc_delay_bpl, adpcm_enc_delay_dltx );
/* filtep - compute predictor output signal (pole section) */
adpcm_enc_spl = adpcm_enc_filtep( adpcm_enc_rlt1, adpcm_enc_al1, adpcm_enc_rlt2,
adpcm_enc_al2 );
/* compute the predictor output value in the lower sub_band encoder */
adpcm_enc_sl = adpcm_enc_szl + adpcm_enc_spl;
adpcm_enc_el = adpcm_enc_xl - adpcm_enc_sl;
/* quantl: quantize the difference signal */
adpcm_enc_il = adpcm_enc_quantl( adpcm_enc_el, adpcm_enc_detl );
/* invqxl: computes quantized difference signal */
/* for invqbl, truncate by 2 lsbs, so mode = 3 */
adpcm_enc_dlt = ( ( long long ) adpcm_enc_detl *
adpcm_enc_qq4_code4_table[ adpcm_enc_il >> 2 ] ) >> 15;
/* logscl: updates logarithmic quant. scale factor in low sub band */
adpcm_enc_nbl = adpcm_enc_logscl( adpcm_enc_il, adpcm_enc_nbl );
/* scalel: compute the quantizer scale factor in the lower sub band */
/* calling parameters nbl and 8 (constant such that scalel can be scaleh) */
adpcm_enc_detl = adpcm_enc_scalel( adpcm_enc_nbl, 8 );
/* parrec - simple addition to compute recontructed signal for adaptive pred */
adpcm_enc_plt = adpcm_enc_dlt + adpcm_enc_szl;
/* upzero: update zero section predictor coefficients (sixth order)*/
/* calling parameters: dlt, dlt1, dlt2, ..., dlt6 from dlt */
/* bpli (linear_buffer in which all six values are delayed */
/* return params: updated bpli, delayed dltx */
adpcm_enc_upzero( adpcm_enc_dlt, adpcm_enc_delay_dltx, adpcm_enc_delay_bpl );
/* uppol2- update second predictor coefficient apl2 and delay it as al2 */
/* calling parameters: al1, al2, plt, plt1, plt2 */
adpcm_enc_al2 = adpcm_enc_uppol2( adpcm_enc_al1, adpcm_enc_al2, adpcm_enc_plt,
adpcm_enc_plt1, adpcm_enc_plt2 );
/* uppol1 :update first predictor coefficient apl1 and delay it as al1 */
/* calling parameters: al1, apl2, plt, plt1 */
adpcm_enc_al1 = adpcm_enc_uppol1( adpcm_enc_al1, adpcm_enc_al2, adpcm_enc_plt,
adpcm_enc_plt1 );
/* recons : compute recontructed signal for adaptive predictor */
adpcm_enc_rlt = adpcm_enc_sl + adpcm_enc_dlt;
/* done with lower sub_band encoder; now implement delays for next time*/
adpcm_enc_rlt2 = adpcm_enc_rlt1;
adpcm_enc_rlt1 = adpcm_enc_rlt;
adpcm_enc_plt2 = adpcm_enc_plt1;
adpcm_enc_plt1 = adpcm_enc_plt;
/* high band encode */
adpcm_enc_szh = adpcm_enc_filtez( adpcm_enc_delay_bph, adpcm_enc_delay_dhx );
adpcm_enc_sph = adpcm_enc_filtep( adpcm_enc_rh1, adpcm_enc_ah1, adpcm_enc_rh2,
adpcm_enc_ah2 );
/* predic: sh = sph + szh */
adpcm_enc_sh = adpcm_enc_sph + adpcm_enc_szh;
/* subtra: eh = xh - sh */
adpcm_enc_eh = adpcm_enc_xh - adpcm_enc_sh;
/* quanth - quantization of difference signal for higher sub-band */
/* quanth: in-place for speed params: eh, deth (has init. value) */
if ( adpcm_enc_eh >= 0 )
adpcm_enc_ih = 3; /* 2,3 are pos codes */
else
adpcm_enc_ih = 1; /* 0,1 are neg codes */
decis = ( 564L * ( long long )adpcm_enc_deth ) >> 12L;
if ( adpcm_enc_abs( adpcm_enc_eh ) > decis )
adpcm_enc_ih--; /* mih = 2 case */
/* invqah: compute the quantized difference signal, higher sub-band*/
adpcm_enc_dh = ( ( long long )adpcm_enc_deth *
adpcm_enc_qq2_code2_table[ adpcm_enc_ih ] ) >> 15L ;
/* logsch: update logarithmic quantizer scale factor in hi sub-band*/
adpcm_enc_nbh = adpcm_enc_logsch( adpcm_enc_ih, adpcm_enc_nbh );
/* note : scalel and scaleh use same code, different parameters */
adpcm_enc_deth = adpcm_enc_scalel( adpcm_enc_nbh, 10 );
/* parrec - add pole predictor output to quantized diff. signal */
adpcm_enc_ph = adpcm_enc_dh + adpcm_enc_szh;
/* upzero: update zero section predictor coefficients (sixth order) */
/* calling parameters: dh, dhi, bphi */
/* return params: updated bphi, delayed dhx */
adpcm_enc_upzero( adpcm_enc_dh, adpcm_enc_delay_dhx, adpcm_enc_delay_bph );
/* uppol2: update second predictor coef aph2 and delay as ah2 */
/* calling params: ah1, ah2, ph, ph1, ph2 */
adpcm_enc_ah2 = adpcm_enc_uppol2( adpcm_enc_ah1, adpcm_enc_ah2, adpcm_enc_ph,
adpcm_enc_ph1, adpcm_enc_ph2 );
/* uppol1: update first predictor coef. aph2 and delay it as ah1 */
adpcm_enc_ah1 = adpcm_enc_uppol1( adpcm_enc_ah1, adpcm_enc_ah2, adpcm_enc_ph,
adpcm_enc_ph1 );
/* recons for higher sub-band */
adpcm_enc_yh = adpcm_enc_sh + adpcm_enc_dh;
/* done with higher sub-band encoder, now Delay for next time */
adpcm_enc_rh2 = adpcm_enc_rh1;
adpcm_enc_rh1 = adpcm_enc_yh;
adpcm_enc_ph2 = adpcm_enc_ph1;
adpcm_enc_ph1 = adpcm_enc_ph;
/* multiplex ih and il to get signals together */
return ( adpcm_enc_il | ( adpcm_enc_ih << 6 ) );
}
/* filtez - compute predictor output signal (zero section) */
/* input: bpl1-6 and dlt1-6, output: szl */
int adpcm_enc_filtez( int *bpl, int *dlt )
{
int i;
long long int zl;
zl = ( long long )( *bpl++ ) * ( *dlt++ );
/* MAX: 5 */
_Pragma( "loopbound min 5 max 5" )
for ( i = 1; i < 6; i++ )
zl += ( long long )( *bpl++ ) * ( *dlt++ );
return ( ( int )( zl >> 14 ) ); /* x2 here */
}
/* filtep - compute predictor output signal (pole section) */
/* input rlt1-2 and al1-2, output spl */
int adpcm_enc_filtep( int rlt1, int al1, int rlt2, int al2 )
{
long long int pl, pl2;
pl = 2 * rlt1;
pl = ( long long ) al1 * pl;
pl2 = 2 * rlt2;
pl += ( long long ) al2 * pl2;
return ( ( int )( pl >> 15 ) );
}
/* quantl - quantize the difference signal in the lower sub-band */
int adpcm_enc_quantl( int el, int detl )
{
int ril, mil;
long long int wd, decis;
/* abs of difference signal */
wd = adpcm_enc_abs( el );
/* determine mil based on decision levels and detl gain */
/* MAX: 30 */
_Pragma( "loopbound min 1 max 30" )
for ( mil = 0; mil < 30; mil++ ) {
decis = ( adpcm_enc_decis_levl[ mil ] * ( long long )detl ) >> 15L;
if ( wd <= decis )
break;
}
/* if mil=30 then wd is less than all decision levels */
if ( el >= 0 )
ril = adpcm_enc_quant26bt_pos[ mil ];
else
ril = adpcm_enc_quant26bt_neg[ mil ];
return ( ril );
}
/* invqxl is either invqbl or invqal depending on parameters passed */
/* returns dlt, code table is pre-multiplied by 8 */
/* int invqxl(int il,int detl,int *code_table,int mode) */
/* { */
/* long long int dlt; */
/* dlt = (long long)detl*code_table[ il >> (mode-1) ]; */
/* return((int)(dlt >> 15)); */
/* } */
/* logscl - update log quantizer scale factor in lower sub-band */
/* note that nbl is passed and returned */
int adpcm_enc_logscl( int il, int nbl )
{
long long int wd;
wd = ( ( long long )nbl * 127L ) >> 7L; /* leak factor 127/128 */
nbl = ( int )wd + adpcm_enc_wl_code_table[ il >> 2 ];
if ( nbl < 0 )
nbl = 0;
if ( nbl > 18432 )
nbl = 18432;
return ( nbl );
}
/* scalel: compute quantizer scale factor in lower or upper sub-band*/
int adpcm_enc_scalel( int nbl, int shift_constant )
{
int wd1, wd2, wd3;
wd1 = ( nbl >> 6 ) & 31;
wd2 = nbl >> 11;
wd3 = adpcm_enc_ilb_table[ wd1 ] >> ( shift_constant + 1 - wd2 );
return ( wd3 << 3 );
}
/* upzero - inputs: dlt, dlti[ 0-5 ], bli[ 0-5 ], outputs: updated bli[ 0-5 ] */
/* also implements delay of bli and update of dlti from dlt */
void adpcm_enc_upzero( int dlt, int *dlti, int *bli )
{
int i, wd2, wd3;
/*if dlt is zero, then no sum into bli */
if ( dlt == 0 ) {
_Pragma( "loopbound min 6 max 6" )
for ( i = 0; i < 6; i++ ) {
bli[ i ] = ( int )( ( 255L * bli[ i ] ) >> 8L ); /* leak factor of 255/256 */
}
} else {
_Pragma( "loopbound min 6 max 6" )
for ( i = 0; i < 6; i++ ) {
if ( ( long long )dlt * dlti[ i ] >= 0 )
wd2 = 128;
else
wd2 = -128;
wd3 = ( int )( ( 255L * bli[ i ] ) >> 8L ); /* leak factor of 255/256 */
bli[ i ] = wd2 + wd3;
}
}
/* implement delay line for dlt */
dlti[ 5 ] = dlti[ 4 ];
dlti[ 4 ] = dlti[ 3 ];
dlti[ 3 ] = dlti[ 2 ];
dlti[ 1 ] = dlti[ 0 ];
dlti[ 0 ] = dlt;
return;
}
/* uppol2 - update second predictor coefficient (pole section) */
/* inputs: al1, al2, plt, plt1, plt2. outputs: apl2 */
int adpcm_enc_uppol2( int al1, int al2, int plt, int plt1, int plt2 )
{
long long int wd2, wd4;
int apl2;
wd2 = 4L * ( long long )al1;
if ( ( long long )plt * plt1 >= 0L )
wd2 = -wd2; /* check same sign */
wd2 = wd2 >> 7; /* gain of 1/128 */
if ( ( long long )plt * plt2 >= 0L ) {
wd4 = wd2 + 128; /* same sign case */
} else
wd4 = wd2 - 128;
apl2 = wd4 + ( 127L * ( long long )al2 >> 7L ); /* leak factor of 127/128 */
/* apl2 is limited to +-.75 */
if ( apl2 > 12288 )
apl2 = 12288;
if ( apl2 < -12288 )
apl2 = -12288;
return ( apl2 );
}
/* uppol1 - update first predictor coefficient (pole section) */
/* inputs: al1, apl2, plt, plt1. outputs: apl1 */
int adpcm_enc_uppol1( int al1, int apl2, int plt, int plt1 )
{
long long int wd2;
int wd3, apl1;
wd2 = ( ( long long )al1 * 255L ) >> 8L; /* leak factor of 255/256 */
if ( ( long long )plt * plt1 >= 0L ) {
apl1 = ( int )wd2 + 192; /* same sign case */
} else
apl1 = ( int )wd2 - 192;
/* note: wd3= .9375-.75 is always positive */
wd3 = 15360 - apl2; /* limit value */
if ( apl1 > wd3 )
apl1 = wd3;
if ( apl1 < -wd3 )
apl1 = -wd3;
return ( apl1 );
}
/* INVQAH: inverse adaptive quantizer for the higher sub-band */
/* returns dh, code table is pre-multiplied by 8 */
/* int invqah(int ih,int deth) */
/* { */
/* long long int rdh; */
/* rdh = ((long long)deth*qq2_code2_table[ ih ]) >> 15L ; */
/* return((int)(rdh )); */
/* } */
/* logsch - update log quantizer scale factor in higher sub-band */
/* note that nbh is passed and returned */
int adpcm_enc_logsch( int ih, int nbh )
{
int wd;
wd = ( ( long long )nbh * 127L ) >> 7L; /* leak factor 127/128 */
nbh = wd + adpcm_enc_wh_code_table[ ih ];
if ( nbh < 0 )
nbh = 0;
if ( nbh > 22528 )
nbh = 22528;
return ( nbh );
}
/*
Initialization- and return-value-related functions
*/
/* clear all storage locations */
void adpcm_enc_reset( void )
{
int i;
adpcm_enc_detl = 32; /* reset to min scale factor */
adpcm_enc_deth = 8;
adpcm_enc_nbl = adpcm_enc_al1 = adpcm_enc_al2 = adpcm_enc_plt1 = adpcm_enc_plt2
= adpcm_enc_rlt1 = adpcm_enc_rlt2 = 0;
adpcm_enc_nbh = adpcm_enc_ah1 = adpcm_enc_ah2 = adpcm_enc_ph1 = adpcm_enc_ph2 =
adpcm_enc_rh1 = adpcm_enc_rh2 = 0;
_Pragma( "loopbound min 6 max 6" )
for ( i = 0; i < 6; i++ ) {
adpcm_enc_delay_dltx[ i ] = 0;
adpcm_enc_delay_dhx[ i ] = 0;
}
_Pragma( "loopbound min 6 max 6" )
for ( i = 0; i < 6; i++ ) {
adpcm_enc_delay_bpl[ i ] = 0;
adpcm_enc_delay_bph[ i ] = 0;
}
_Pragma( "loopbound min 23 max 23" )
for ( i = 0; i < 23; i++ )
adpcm_enc_tqmf[ i ] = 0;
return;
}
void adpcm_enc_init( void )
{
int i, j, f;
volatile int x = 0;
/* reset, initialize required memory */
adpcm_enc_reset();
/* read in amplitude and frequency for test data */
j = 10;
f = 2000;
/* 16 KHz sample rate */
/* XXmain_0, MAX: 2 */
/* Since the number of times we loop in my_sin depends on the argument we
add the fact: xxmain_0:[ ]: */
_Pragma( "loopbound min 3 max 3" )
for ( i = 0 ; i < SIZE ; i++ ) {
adpcm_enc_test_data[ i ] = ( int ) j * adpcm_enc_cos( f * PI * i );
/* avoid constant-propagation optimizations */
adpcm_enc_test_data[ i ] += x;
}
}
int adpcm_enc_return( void )
{
int i;
int check_sum = 0;
_Pragma( "loopbound min 2 max 2" )
for ( i = 0 ; i < IN_END ; i += 2 )
check_sum += adpcm_enc_compressed[ i / 2 ];
return check_sum != 385;
}
/*
Main functions
*/
void _Pragma( "entrypoint" ) adpcm_enc_main( void )
{
int i;
/* MAX: 2 */
_Pragma( "loopbound min 2 max 2" )
for ( i = 0 ; i < IN_END ; i += 2 )
adpcm_enc_compressed[ i / 2 ] = adpcm_enc_encode( adpcm_enc_test_data[ i ],
adpcm_enc_test_data[ i + 1 ] );
}
int main( void )
{
adpcm_enc_init();
adpcm_enc_main();
return adpcm_enc_return();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,706 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: adpcm_enc
Author: Sung-Soo Lim
Function: CCITT G.722 ADPCM (Adaptive Differential Pulse Code Modulation)
algorithm. 16khz sample rate data is stored in the array test_data[ SIZE ].
Results are stored in the array compressed[ SIZE ].
Execution time is determined by the constant SIZE (default value is 2000).
Source: C Algorithms for Real-Time DSP by P. M. Embree
and SNU-RT Benchmark Suite for Worst Case Timing Analysis
collected and modified by S.-S. Lim <sslim@archi.snu.ac.kr>
Original name: adpcm_encoder
Changes: no major functional changes
License: may be used, modified, and re-distributed freely, but the
SNU-RT Benchmark Suite must be acknowledged
*/
/* common sampling rate for sound cards on IBM/PC */
#define SAMPLE_RATE 11025
#define PI 3141
#define SIZE 3
#define IN_END 4
/*
Forward declaration of functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
int adpcm_enc_encode(int, int);
int adpcm_enc_filtez(int *bpl, int *dlt);
void adpcm_enc_upzero(int dlt, int *dlti, int *bli);
int adpcm_enc_filtep(int rlt1, int al1, int rlt2, int al2);
int adpcm_enc_quantl(int el, int detl);
int adpcm_enc_logscl(int il, int nbl);
int adpcm_enc_scalel(int nbl, int shift_constant);
int adpcm_enc_uppol2(int al1, int al2, int plt, int plt1, int plt2);
int adpcm_enc_uppol1(int al1, int apl2, int plt, int plt1);
int adpcm_enc_logsch(int ih, int nbh);
void adpcm_enc_reset();
int adpcm_enc_fabs(int n);
int adpcm_enc_cos(int n);
int adpcm_enc_sin(int n);
int adpcm_enc_abs(int n);
void adpcm_enc_init(void);
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
adpcm_enc_main(void);
int adpcm_enc_return(void);
__attribute__((noinline)) __attribute__((export_name("main"))) int main(void);
/*
Forward declaration of global variables
*/
int adpcm_enc_test_data[SIZE * 2], adpcm_enc_compressed[SIZE];
/* G722 C code */
/* variables for transimit quadrature mirror filter here */
int adpcm_enc_tqmf[24];
/* QMF filter coefficients:
scaled by a factor of 4 compared to G722 CCITT recommendation */
int adpcm_enc_h[24] = {12, -44, -44, 212, 48, -624, 128, 1448,
-840, -3220, 3804, 15504, 15504, 3804, -3220, -840,
1448, 128, -624, 48, 212, -44, -44, 12};
int adpcm_enc_xl, adpcm_enc_xh;
/* variables for encoder (hi and lo) here */
int adpcm_enc_il, adpcm_enc_szl, adpcm_enc_spl, adpcm_enc_sl, adpcm_enc_el;
int adpcm_enc_qq4_code4_table[16] = {0, -20456, -12896, -8968, -6288, -4240,
-2584, -1200, 20456, 12896, 8968, 6288,
4240, 2584, 1200, 0};
int adpcm_enc_qq5_code5_table[32] = {
-280, -280, -23352, -17560, -14120, -11664, -9752, -8184,
-6864, -5712, -4696, -3784, -2960, -2208, -1520, -880,
23352, 17560, 14120, 11664, 9752, 8184, 6864, 5712,
4696, 3784, 2960, 2208, 1520, 880, 280, -280};
int adpcm_enc_qq6_code6_table[64] = {
-136, -136, -136, -136, -24808, -21904, -19008, -16704,
-14984, -13512, -12280, -11192, -10232, -9360, -8576, -7856,
-7192, -6576, -6000, -5456, -4944, -4464, -4008, -3576,
-3168, -2776, -2400, -2032, -1688, -1360, -1040, -728,
24808, 21904, 19008, 16704, 14984, 13512, 12280, 11192,
10232, 9360, 8576, 7856, 7192, 6576, 6000, 5456,
4944, 4464, 4008, 3576, 3168, 2776, 2400, 2032,
1688, 1360, 1040, 728, 432, 136, -432, -136};
int adpcm_enc_delay_bpl[6];
int adpcm_enc_delay_dltx[6];
int adpcm_enc_wl_code_table[16] = {-60, 3042, 1198, 538, 334, 172, 58, -30,
3042, 1198, 538, 334, 172, 58, -30, -60};
int adpcm_enc_ilb_table[32] = {2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383,
2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834,
2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371,
3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008};
int adpcm_enc_nbl; /* delay line */
int adpcm_enc_al1, adpcm_enc_al2;
int adpcm_enc_plt, adpcm_enc_plt1, adpcm_enc_plt2;
int adpcm_enc_dlt;
int adpcm_enc_rlt, adpcm_enc_rlt1, adpcm_enc_rlt2;
/* decision levels - pre-multiplied by 8, 0 to indicate end */
int adpcm_enc_decis_levl[30] = {
280, 576, 880, 1200, 1520, 1864, 2208, 2584, 2960, 3376,
3784, 4240, 4696, 5200, 5712, 6288, 6864, 7520, 8184, 8968,
9752, 10712, 11664, 12896, 14120, 15840, 17560, 20456, 23352, 32767};
int adpcm_enc_detl;
/* quantization table 31 long to make quantl look-up easier,
last entry is for mil=30 case when wd is max */
int adpcm_enc_quant26bt_pos[31] = {61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51,
50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40,
39, 38, 37, 36, 35, 34, 33, 32, 32};
/* quantization table 31 long to make quantl look-up easier,
last entry is for mil=30 case when wd is max */
int adpcm_enc_quant26bt_neg[31] = {63, 62, 31, 30, 29, 28, 27, 26, 25, 24, 23,
22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
11, 10, 9, 8, 7, 6, 5, 4, 4};
int adpcm_enc_deth;
int adpcm_enc_sh; /* this comes from adaptive predictor */
int adpcm_enc_eh;
int adpcm_enc_qq2_code2_table[4] = {-7408, -1616, 7408, 1616};
int adpcm_enc_wh_code_table[4] = {798, -214, 798, -214};
int adpcm_enc_dh, adpcm_enc_ih;
int adpcm_enc_nbh, adpcm_enc_szh;
int adpcm_enc_sph, adpcm_enc_ph, adpcm_enc_yh;
int adpcm_enc_delay_dhx[6];
int adpcm_enc_delay_bph[6];
int adpcm_enc_ah1, adpcm_enc_ah2;
int adpcm_enc_ph1, adpcm_enc_ph2;
int adpcm_enc_rh1, adpcm_enc_rh2;
/* G722 encode function two ints in, one 8 bit output */
/* put input samples in xin1 = first value, xin2 = second value */
/* returns il and ih stored together */
/* MAX: 1 */
int
adpcm_enc_abs(int n) {
int m;
if (n >= 0)
m = n;
else
m = -n;
return m;
}
/* MAX: 1 */
int
adpcm_enc_fabs(int n) {
int f;
if (n >= 0)
f = n;
else
f = -n;
return f;
}
#pragma GCC push_options
#pragma GCC optimize "-fwrapv"
int
adpcm_enc_sin(int rad) {
int diff;
int app = 0;
int inc = 1;
/* MAX dependent on rad's value, say 50 */
__pragma_loopbound(0, 0);
while (rad > 2 * PI)
rad -= 2 * PI;
/* MAX dependent on rad's value, say 50 */
__pragma_loopbound(0, 1999);
while (rad < -2 * PI)
rad += 2 * PI;
diff = rad;
app = diff;
diff = (diff * (-(rad * rad))) / ((2 * inc) * (2 * inc + 1));
app = app + diff;
inc++;
/* REALLY: while(my_fabs(diff) >= 0.00001) { */
/* MAX: 1000 */
__pragma_loopbound(849, 2424);
while (adpcm_enc_fabs(diff) >= 1) {
diff = (diff * (-(rad * rad))) / ((2 * inc) * (2 * inc + 1));
app = app + diff;
inc++;
}
return app;
}
#pragma GCC pop_options
int
adpcm_enc_cos(int rad) {
return (adpcm_enc_sin(PI / 2 - rad));
}
/* MAX: 1 */
int
adpcm_enc_encode(int xin1, int xin2) {
int i;
int *h_ptr, *tqmf_ptr, *tqmf_ptr1;
long long int xa, xb;
int decis;
/* transmit quadrature mirror filters implemented here */
h_ptr = adpcm_enc_h;
tqmf_ptr = adpcm_enc_tqmf;
xa = (long long) (*tqmf_ptr++) * (*h_ptr++);
xb = (long long) (*tqmf_ptr++) * (*h_ptr++);
/* main multiply accumulate loop for samples and coefficients */
/* MAX: 10 */
__pragma_loopbound(10, 10);
for (i = 0; i < 10; i++) {
xa += (long long) (*tqmf_ptr++) * (*h_ptr++);
xb += (long long) (*tqmf_ptr++) * (*h_ptr++);
}
/* final mult/accumulate */
xa += (long long) (*tqmf_ptr++) * (*h_ptr++);
xb += (long long) (*tqmf_ptr) * (*h_ptr++);
/* update delay line tqmf */
tqmf_ptr1 = tqmf_ptr - 2;
/* MAX: 22 */
__pragma_loopbound(22, 22);
for (i = 0; i < 22; i++)
*tqmf_ptr-- = *tqmf_ptr1--;
*tqmf_ptr-- = xin1;
*tqmf_ptr = xin2;
/* scale outputs */
adpcm_enc_xl = (xa + xb) >> 15;
adpcm_enc_xh = (xa - xb) >> 15;
/* end of quadrature mirror filter code */
/* starting with lower sub band encoder */
/* filtez - compute predictor output section - zero section */
adpcm_enc_szl = adpcm_enc_filtez(adpcm_enc_delay_bpl, adpcm_enc_delay_dltx);
/* filtep - compute predictor output signal (pole section) */
adpcm_enc_spl = adpcm_enc_filtep(adpcm_enc_rlt1, adpcm_enc_al1,
adpcm_enc_rlt2, adpcm_enc_al2);
/* compute the predictor output value in the lower sub_band encoder */
adpcm_enc_sl = adpcm_enc_szl + adpcm_enc_spl;
adpcm_enc_el = adpcm_enc_xl - adpcm_enc_sl;
/* quantl: quantize the difference signal */
adpcm_enc_il = adpcm_enc_quantl(adpcm_enc_el, adpcm_enc_detl);
/* invqxl: computes quantized difference signal */
/* for invqbl, truncate by 2 lsbs, so mode = 3 */
adpcm_enc_dlt = ((long long) adpcm_enc_detl *
adpcm_enc_qq4_code4_table[adpcm_enc_il >> 2]) >>
15;
/* logscl: updates logarithmic quant. scale factor in low sub band */
adpcm_enc_nbl = adpcm_enc_logscl(adpcm_enc_il, adpcm_enc_nbl);
/* scalel: compute the quantizer scale factor in the lower sub band */
/* calling parameters nbl and 8 (constant such that scalel can be scaleh) */
adpcm_enc_detl = adpcm_enc_scalel(adpcm_enc_nbl, 8);
/* parrec - simple addition to compute recontructed signal for adaptive pred
*/
adpcm_enc_plt = adpcm_enc_dlt + adpcm_enc_szl;
/* upzero: update zero section predictor coefficients (sixth order)*/
/* calling parameters: dlt, dlt1, dlt2, ..., dlt6 from dlt */
/* bpli (linear_buffer in which all six values are delayed */
/* return params: updated bpli, delayed dltx */
adpcm_enc_upzero(adpcm_enc_dlt, adpcm_enc_delay_dltx, adpcm_enc_delay_bpl);
/* uppol2- update second predictor coefficient apl2 and delay it as al2 */
/* calling parameters: al1, al2, plt, plt1, plt2 */
adpcm_enc_al2 =
adpcm_enc_uppol2(adpcm_enc_al1, adpcm_enc_al2, adpcm_enc_plt,
adpcm_enc_plt1, adpcm_enc_plt2);
/* uppol1 :update first predictor coefficient apl1 and delay it as al1 */
/* calling parameters: al1, apl2, plt, plt1 */
adpcm_enc_al1 = adpcm_enc_uppol1(adpcm_enc_al1, adpcm_enc_al2,
adpcm_enc_plt, adpcm_enc_plt1);
/* recons : compute recontructed signal for adaptive predictor */
adpcm_enc_rlt = adpcm_enc_sl + adpcm_enc_dlt;
/* done with lower sub_band encoder; now implement delays for next time*/
adpcm_enc_rlt2 = adpcm_enc_rlt1;
adpcm_enc_rlt1 = adpcm_enc_rlt;
adpcm_enc_plt2 = adpcm_enc_plt1;
adpcm_enc_plt1 = adpcm_enc_plt;
/* high band encode */
adpcm_enc_szh = adpcm_enc_filtez(adpcm_enc_delay_bph, adpcm_enc_delay_dhx);
adpcm_enc_sph = adpcm_enc_filtep(adpcm_enc_rh1, adpcm_enc_ah1,
adpcm_enc_rh2, adpcm_enc_ah2);
/* predic: sh = sph + szh */
adpcm_enc_sh = adpcm_enc_sph + adpcm_enc_szh;
/* subtra: eh = xh - sh */
adpcm_enc_eh = adpcm_enc_xh - adpcm_enc_sh;
/* quanth - quantization of difference signal for higher sub-band */
/* quanth: in-place for speed params: eh, deth (has init. value) */
if (adpcm_enc_eh >= 0)
adpcm_enc_ih = 3; /* 2,3 are pos codes */
else
adpcm_enc_ih = 1; /* 0,1 are neg codes */
decis = (564L * (long long) adpcm_enc_deth) >> 12L;
if (adpcm_enc_abs(adpcm_enc_eh) > decis)
adpcm_enc_ih--; /* mih = 2 case */
/* invqah: compute the quantized difference signal, higher sub-band*/
adpcm_enc_dh = ((long long) adpcm_enc_deth *
adpcm_enc_qq2_code2_table[adpcm_enc_ih]) >>
15L;
/* logsch: update logarithmic quantizer scale factor in hi sub-band*/
adpcm_enc_nbh = adpcm_enc_logsch(adpcm_enc_ih, adpcm_enc_nbh);
/* note : scalel and scaleh use same code, different parameters */
adpcm_enc_deth = adpcm_enc_scalel(adpcm_enc_nbh, 10);
/* parrec - add pole predictor output to quantized diff. signal */
adpcm_enc_ph = adpcm_enc_dh + adpcm_enc_szh;
/* upzero: update zero section predictor coefficients (sixth order) */
/* calling parameters: dh, dhi, bphi */
/* return params: updated bphi, delayed dhx */
adpcm_enc_upzero(adpcm_enc_dh, adpcm_enc_delay_dhx, adpcm_enc_delay_bph);
/* uppol2: update second predictor coef aph2 and delay as ah2 */
/* calling params: ah1, ah2, ph, ph1, ph2 */
adpcm_enc_ah2 = adpcm_enc_uppol2(adpcm_enc_ah1, adpcm_enc_ah2, adpcm_enc_ph,
adpcm_enc_ph1, adpcm_enc_ph2);
/* uppol1: update first predictor coef. aph2 and delay it as ah1 */
adpcm_enc_ah1 = adpcm_enc_uppol1(adpcm_enc_ah1, adpcm_enc_ah2, adpcm_enc_ph,
adpcm_enc_ph1);
/* recons for higher sub-band */
adpcm_enc_yh = adpcm_enc_sh + adpcm_enc_dh;
/* done with higher sub-band encoder, now Delay for next time */
adpcm_enc_rh2 = adpcm_enc_rh1;
adpcm_enc_rh1 = adpcm_enc_yh;
adpcm_enc_ph2 = adpcm_enc_ph1;
adpcm_enc_ph1 = adpcm_enc_ph;
/* multiplex ih and il to get signals together */
return (adpcm_enc_il | (adpcm_enc_ih << 6));
}
/* filtez - compute predictor output signal (zero section) */
/* input: bpl1-6 and dlt1-6, output: szl */
int
adpcm_enc_filtez(int *bpl, int *dlt) {
int i;
long long int zl;
zl = (long long) (*bpl++) * (*dlt++);
/* MAX: 5 */
__pragma_loopbound(5, 5);
for (i = 1; i < 6; i++)
zl += (long long) (*bpl++) * (*dlt++);
return ((int) (zl >> 14)); /* x2 here */
}
/* filtep - compute predictor output signal (pole section) */
/* input rlt1-2 and al1-2, output spl */
int
adpcm_enc_filtep(int rlt1, int al1, int rlt2, int al2) {
long long int pl, pl2;
pl = 2 * rlt1;
pl = (long long) al1 * pl;
pl2 = 2 * rlt2;
pl += (long long) al2 * pl2;
return ((int) (pl >> 15));
}
/* quantl - quantize the difference signal in the lower sub-band */
int
adpcm_enc_quantl(int el, int detl) {
int ril, mil;
long long int wd, decis;
/* abs of difference signal */
wd = adpcm_enc_abs(el);
/* determine mil based on decision levels and detl gain */
/* MAX: 30 */
__pragma_loopbound(1, 30);
for (mil = 0; mil < 30; mil++) {
decis = (adpcm_enc_decis_levl[mil] * (long long) detl) >> 15L;
if (wd <= decis)
break;
}
/* if mil=30 then wd is less than all decision levels */
if (el >= 0)
ril = adpcm_enc_quant26bt_pos[mil];
else
ril = adpcm_enc_quant26bt_neg[mil];
return (ril);
}
/* invqxl is either invqbl or invqal depending on parameters passed */
/* returns dlt, code table is pre-multiplied by 8 */
/* int invqxl(int il,int detl,int *code_table,int mode) */
/* { */
/* long long int dlt; */
/* dlt = (long long)detl*code_table[ il >> (mode-1) ]; */
/* return((int)(dlt >> 15)); */
/* } */
/* logscl - update log quantizer scale factor in lower sub-band */
/* note that nbl is passed and returned */
int
adpcm_enc_logscl(int il, int nbl) {
long long int wd;
wd = ((long long) nbl * 127L) >> 7L; /* leak factor 127/128 */
nbl = (int) wd + adpcm_enc_wl_code_table[il >> 2];
if (nbl < 0)
nbl = 0;
if (nbl > 18432)
nbl = 18432;
return (nbl);
}
/* scalel: compute quantizer scale factor in lower or upper sub-band*/
int
adpcm_enc_scalel(int nbl, int shift_constant) {
int wd1, wd2, wd3;
wd1 = (nbl >> 6) & 31;
wd2 = nbl >> 11;
wd3 = adpcm_enc_ilb_table[wd1] >> (shift_constant + 1 - wd2);
return (wd3 << 3);
}
/* upzero - inputs: dlt, dlti[ 0-5 ], bli[ 0-5 ], outputs: updated bli[ 0-5 ] */
/* also implements delay of bli and update of dlti from dlt */
void
adpcm_enc_upzero(int dlt, int *dlti, int *bli) {
int i, wd2, wd3;
/*if dlt is zero, then no sum into bli */
if (dlt == 0) {
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
bli[i] = (int) ((255L * bli[i]) >> 8L); /* leak factor of 255/256 */
}
} else {
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
if ((long long) dlt * dlti[i] >= 0)
wd2 = 128;
else
wd2 = -128;
wd3 = (int) ((255L * bli[i]) >> 8L); /* leak factor of 255/256 */
bli[i] = wd2 + wd3;
}
}
/* implement delay line for dlt */
dlti[5] = dlti[4];
dlti[4] = dlti[3];
dlti[3] = dlti[2];
dlti[1] = dlti[0];
dlti[0] = dlt;
return;
}
/* uppol2 - update second predictor coefficient (pole section) */
/* inputs: al1, al2, plt, plt1, plt2. outputs: apl2 */
int
adpcm_enc_uppol2(int al1, int al2, int plt, int plt1, int plt2) {
long long int wd2, wd4;
int apl2;
wd2 = 4L * (long long) al1;
if ((long long) plt * plt1 >= 0L)
wd2 = -wd2; /* check same sign */
wd2 = wd2 >> 7; /* gain of 1/128 */
if ((long long) plt * plt2 >= 0L) {
wd4 = wd2 + 128; /* same sign case */
} else
wd4 = wd2 - 128;
apl2 = wd4 + (127L * (long long) al2 >> 7L); /* leak factor of 127/128 */
/* apl2 is limited to +-.75 */
if (apl2 > 12288)
apl2 = 12288;
if (apl2 < -12288)
apl2 = -12288;
return (apl2);
}
/* uppol1 - update first predictor coefficient (pole section) */
/* inputs: al1, apl2, plt, plt1. outputs: apl1 */
int
adpcm_enc_uppol1(int al1, int apl2, int plt, int plt1) {
long long int wd2;
int wd3, apl1;
wd2 = ((long long) al1 * 255L) >> 8L; /* leak factor of 255/256 */
if ((long long) plt * plt1 >= 0L) {
apl1 = (int) wd2 + 192; /* same sign case */
} else
apl1 = (int) wd2 - 192;
/* note: wd3= .9375-.75 is always positive */
wd3 = 15360 - apl2; /* limit value */
if (apl1 > wd3)
apl1 = wd3;
if (apl1 < -wd3)
apl1 = -wd3;
return (apl1);
}
/* INVQAH: inverse adaptive quantizer for the higher sub-band */
/* returns dh, code table is pre-multiplied by 8 */
/* int invqah(int ih,int deth) */
/* { */
/* long long int rdh; */
/* rdh = ((long long)deth*qq2_code2_table[ ih ]) >> 15L ; */
/* return((int)(rdh )); */
/* } */
/* logsch - update log quantizer scale factor in higher sub-band */
/* note that nbh is passed and returned */
int
adpcm_enc_logsch(int ih, int nbh) {
int wd;
wd = ((long long) nbh * 127L) >> 7L; /* leak factor 127/128 */
nbh = wd + adpcm_enc_wh_code_table[ih];
if (nbh < 0)
nbh = 0;
if (nbh > 22528)
nbh = 22528;
return (nbh);
}
/*
Initialization- and return-value-related functions
*/
/* clear all storage locations */
void
adpcm_enc_reset(void) {
int i;
adpcm_enc_detl = 32; /* reset to min scale factor */
adpcm_enc_deth = 8;
adpcm_enc_nbl = adpcm_enc_al1 = adpcm_enc_al2 = adpcm_enc_plt1 =
adpcm_enc_plt2 = adpcm_enc_rlt1 = adpcm_enc_rlt2 = 0;
adpcm_enc_nbh = adpcm_enc_ah1 = adpcm_enc_ah2 = adpcm_enc_ph1 =
adpcm_enc_ph2 = adpcm_enc_rh1 = adpcm_enc_rh2 = 0;
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
adpcm_enc_delay_dltx[i] = 0;
adpcm_enc_delay_dhx[i] = 0;
}
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
adpcm_enc_delay_bpl[i] = 0;
adpcm_enc_delay_bph[i] = 0;
}
__pragma_loopbound(23, 23);
for (i = 0; i < 23; i++)
adpcm_enc_tqmf[i] = 0;
return;
}
void
adpcm_enc_init(void) {
int i, j, f;
volatile int x = 0;
/* reset, initialize required memory */
adpcm_enc_reset();
/* read in amplitude and frequency for test data */
j = 10;
f = 2000;
/* 16 KHz sample rate */
/* XXmain_0, MAX: 2 */
/* Since the number of times we loop in my_sin depends on the argument we
add the fact: xxmain_0:[ ]: */
__pragma_loopbound(3, 3);
for (i = 0; i < SIZE; i++) {
adpcm_enc_test_data[i] = (int) j * adpcm_enc_cos(f * PI * i);
/* avoid constant-propagation optimizations */
adpcm_enc_test_data[i] += x;
}
}
int
adpcm_enc_return(void) {
int i;
int check_sum = 0;
__pragma_loopbound(2, 2);
for (i = 0; i < IN_END; i += 2)
check_sum += adpcm_enc_compressed[i / 2];
return check_sum != 385;
}
/*
Main functions
*/
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
adpcm_enc_main(void) {
int i;
/* MAX: 2 */
__pragma_loopbound(2, 2);
for (i = 0; i < IN_END; i += 2)
adpcm_enc_compressed[i / 2] = adpcm_enc_encode(
adpcm_enc_test_data[i], adpcm_enc_test_data[i + 1]);
}
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
adpcm_enc_init();
adpcm_enc_main();
return adpcm_enc_return();
}

View File

@ -0,0 +1,723 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: adpcm_enc
Author: Sung-Soo Lim
Function: CCITT G.722 ADPCM (Adaptive Differential Pulse Code Modulation)
algorithm. 16khz sample rate data is stored in the array test_data[ SIZE ].
Results are stored in the array compressed[ SIZE ].
Execution time is determined by the constant SIZE (default value is 2000).
Source: C Algorithms for Real-Time DSP by P. M. Embree
and SNU-RT Benchmark Suite for Worst Case Timing Analysis
collected and modified by S.-S. Lim <sslim@archi.snu.ac.kr>
Original name: adpcm_encoder
Changes: no major functional changes
License: may be used, modified, and re-distributed freely, but the
SNU-RT Benchmark Suite must be acknowledged
*/
/* common sampling rate for sound cards on IBM/PC */
#define SAMPLE_RATE 11025
#define PI 3141
#define SIZE 3
#define IN_END 4
/*
Forward declaration of functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline int adpcm_enc_encode(int, int);
__attribute__((always_inline)) static inline int adpcm_enc_filtez(int *bpl,
int *dlt);
__attribute__((always_inline)) static inline void
adpcm_enc_upzero(int dlt, int *dlti, int *bli);
__attribute__((always_inline)) static inline int
adpcm_enc_filtep(int rlt1, int al1, int rlt2, int al2);
__attribute__((always_inline)) static inline int adpcm_enc_quantl(int el,
int detl);
__attribute__((always_inline)) static inline int adpcm_enc_logscl(int il,
int nbl);
__attribute__((always_inline)) static inline int
adpcm_enc_scalel(int nbl, int shift_constant);
__attribute__((always_inline)) static inline int
adpcm_enc_uppol2(int al1, int al2, int plt, int plt1, int plt2);
__attribute__((always_inline)) static inline int
adpcm_enc_uppol1(int al1, int apl2, int plt, int plt1);
__attribute__((always_inline)) static inline int adpcm_enc_logsch(int ih,
int nbh);
__attribute__((always_inline)) static inline void adpcm_enc_reset();
__attribute__((always_inline)) static inline int adpcm_enc_fabs(int n);
__attribute__((always_inline)) static inline int adpcm_enc_cos(int n);
__attribute__((always_inline)) static inline int adpcm_enc_sin(int n);
__attribute__((always_inline)) static inline int adpcm_enc_abs(int n);
__attribute__((always_inline)) static inline void adpcm_enc_init(void);
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
adpcm_enc_main(void);
__attribute__((always_inline)) static inline int adpcm_enc_return(void);
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void);
/*
Forward declaration of global variables
*/
int adpcm_enc_test_data[SIZE * 2], adpcm_enc_compressed[SIZE];
/* G722 C code */
/* variables for transimit quadrature mirror filter here */
int adpcm_enc_tqmf[24];
/* QMF filter coefficients:
scaled by a factor of 4 compared to G722 CCITT recommendation */
int adpcm_enc_h[24] = {12, -44, -44, 212, 48, -624, 128, 1448,
-840, -3220, 3804, 15504, 15504, 3804, -3220, -840,
1448, 128, -624, 48, 212, -44, -44, 12};
int adpcm_enc_xl, adpcm_enc_xh;
/* variables for encoder (hi and lo) here */
int adpcm_enc_il, adpcm_enc_szl, adpcm_enc_spl, adpcm_enc_sl, adpcm_enc_el;
int adpcm_enc_qq4_code4_table[16] = {0, -20456, -12896, -8968, -6288, -4240,
-2584, -1200, 20456, 12896, 8968, 6288,
4240, 2584, 1200, 0};
int adpcm_enc_qq5_code5_table[32] = {
-280, -280, -23352, -17560, -14120, -11664, -9752, -8184,
-6864, -5712, -4696, -3784, -2960, -2208, -1520, -880,
23352, 17560, 14120, 11664, 9752, 8184, 6864, 5712,
4696, 3784, 2960, 2208, 1520, 880, 280, -280};
int adpcm_enc_qq6_code6_table[64] = {
-136, -136, -136, -136, -24808, -21904, -19008, -16704,
-14984, -13512, -12280, -11192, -10232, -9360, -8576, -7856,
-7192, -6576, -6000, -5456, -4944, -4464, -4008, -3576,
-3168, -2776, -2400, -2032, -1688, -1360, -1040, -728,
24808, 21904, 19008, 16704, 14984, 13512, 12280, 11192,
10232, 9360, 8576, 7856, 7192, 6576, 6000, 5456,
4944, 4464, 4008, 3576, 3168, 2776, 2400, 2032,
1688, 1360, 1040, 728, 432, 136, -432, -136};
int adpcm_enc_delay_bpl[6];
int adpcm_enc_delay_dltx[6];
int adpcm_enc_wl_code_table[16] = {-60, 3042, 1198, 538, 334, 172, 58, -30,
3042, 1198, 538, 334, 172, 58, -30, -60};
int adpcm_enc_ilb_table[32] = {2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383,
2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834,
2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371,
3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008};
int adpcm_enc_nbl; /* delay line */
int adpcm_enc_al1, adpcm_enc_al2;
int adpcm_enc_plt, adpcm_enc_plt1, adpcm_enc_plt2;
int adpcm_enc_dlt;
int adpcm_enc_rlt, adpcm_enc_rlt1, adpcm_enc_rlt2;
/* decision levels - pre-multiplied by 8, 0 to indicate end */
int adpcm_enc_decis_levl[30] = {
280, 576, 880, 1200, 1520, 1864, 2208, 2584, 2960, 3376,
3784, 4240, 4696, 5200, 5712, 6288, 6864, 7520, 8184, 8968,
9752, 10712, 11664, 12896, 14120, 15840, 17560, 20456, 23352, 32767};
int adpcm_enc_detl;
/* quantization table 31 long to make quantl look-up easier,
last entry is for mil=30 case when wd is max */
int adpcm_enc_quant26bt_pos[31] = {61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51,
50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40,
39, 38, 37, 36, 35, 34, 33, 32, 32};
/* quantization table 31 long to make quantl look-up easier,
last entry is for mil=30 case when wd is max */
int adpcm_enc_quant26bt_neg[31] = {63, 62, 31, 30, 29, 28, 27, 26, 25, 24, 23,
22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
11, 10, 9, 8, 7, 6, 5, 4, 4};
int adpcm_enc_deth;
int adpcm_enc_sh; /* this comes from adaptive predictor */
int adpcm_enc_eh;
int adpcm_enc_qq2_code2_table[4] = {-7408, -1616, 7408, 1616};
int adpcm_enc_wh_code_table[4] = {798, -214, 798, -214};
int adpcm_enc_dh, adpcm_enc_ih;
int adpcm_enc_nbh, adpcm_enc_szh;
int adpcm_enc_sph, adpcm_enc_ph, adpcm_enc_yh;
int adpcm_enc_delay_dhx[6];
int adpcm_enc_delay_bph[6];
int adpcm_enc_ah1, adpcm_enc_ah2;
int adpcm_enc_ph1, adpcm_enc_ph2;
int adpcm_enc_rh1, adpcm_enc_rh2;
/* G722 encode function two ints in, one 8 bit output */
/* put input samples in xin1 = first value, xin2 = second value */
/* returns il and ih stored together */
/* MAX: 1 */
__attribute__((always_inline)) static inline int
adpcm_enc_abs(int n) {
int m;
if (n >= 0)
m = n;
else
m = -n;
return m;
}
/* MAX: 1 */
__attribute__((always_inline)) static inline int
adpcm_enc_fabs(int n) {
int f;
if (n >= 0)
f = n;
else
f = -n;
return f;
}
#pragma GCC push_options
#pragma GCC optimize "-fwrapv"
__attribute__((always_inline)) static inline int
adpcm_enc_sin(int rad) {
int diff;
int app = 0;
int inc = 1;
/* MAX dependent on rad's value, say 50 */
__pragma_loopbound(0, 0);
while (rad > 2 * PI)
rad -= 2 * PI;
/* MAX dependent on rad's value, say 50 */
__pragma_loopbound(0, 1999);
while (rad < -2 * PI)
rad += 2 * PI;
diff = rad;
app = diff;
diff = (diff * (-(rad * rad))) / ((2 * inc) * (2 * inc + 1));
app = app + diff;
inc++;
/* REALLY: while(my_fabs(diff) >= 0.00001) { */
/* MAX: 1000 */
__pragma_loopbound(849, 2424);
while (adpcm_enc_fabs(diff) >= 1) {
diff = (diff * (-(rad * rad))) / ((2 * inc) * (2 * inc + 1));
app = app + diff;
inc++;
}
return app;
}
#pragma GCC pop_options
__attribute__((always_inline)) static inline int
adpcm_enc_cos(int rad) {
return (adpcm_enc_sin(PI / 2 - rad));
}
/* MAX: 1 */
__attribute__((always_inline)) static inline int
adpcm_enc_encode(int xin1, int xin2) {
int i;
int *h_ptr, *tqmf_ptr, *tqmf_ptr1;
long long int xa, xb;
int decis;
/* transmit quadrature mirror filters implemented here */
h_ptr = adpcm_enc_h;
tqmf_ptr = adpcm_enc_tqmf;
xa = (long long) (*tqmf_ptr++) * (*h_ptr++);
xb = (long long) (*tqmf_ptr++) * (*h_ptr++);
/* main multiply accumulate loop for samples and coefficients */
/* MAX: 10 */
__pragma_loopbound(10, 10);
for (i = 0; i < 10; i++) {
xa += (long long) (*tqmf_ptr++) * (*h_ptr++);
xb += (long long) (*tqmf_ptr++) * (*h_ptr++);
}
/* final mult/accumulate */
xa += (long long) (*tqmf_ptr++) * (*h_ptr++);
xb += (long long) (*tqmf_ptr) * (*h_ptr++);
/* update delay line tqmf */
tqmf_ptr1 = tqmf_ptr - 2;
/* MAX: 22 */
__pragma_loopbound(22, 22);
for (i = 0; i < 22; i++)
*tqmf_ptr-- = *tqmf_ptr1--;
*tqmf_ptr-- = xin1;
*tqmf_ptr = xin2;
/* scale outputs */
adpcm_enc_xl = (xa + xb) >> 15;
adpcm_enc_xh = (xa - xb) >> 15;
/* end of quadrature mirror filter code */
/* starting with lower sub band encoder */
/* filtez - compute predictor output section - zero section */
adpcm_enc_szl = adpcm_enc_filtez(adpcm_enc_delay_bpl, adpcm_enc_delay_dltx);
/* filtep - compute predictor output signal (pole section) */
adpcm_enc_spl = adpcm_enc_filtep(adpcm_enc_rlt1, adpcm_enc_al1,
adpcm_enc_rlt2, adpcm_enc_al2);
/* compute the predictor output value in the lower sub_band encoder */
adpcm_enc_sl = adpcm_enc_szl + adpcm_enc_spl;
adpcm_enc_el = adpcm_enc_xl - adpcm_enc_sl;
/* quantl: quantize the difference signal */
adpcm_enc_il = adpcm_enc_quantl(adpcm_enc_el, adpcm_enc_detl);
/* invqxl: computes quantized difference signal */
/* for invqbl, truncate by 2 lsbs, so mode = 3 */
adpcm_enc_dlt = ((long long) adpcm_enc_detl *
adpcm_enc_qq4_code4_table[adpcm_enc_il >> 2]) >>
15;
/* logscl: updates logarithmic quant. scale factor in low sub band */
adpcm_enc_nbl = adpcm_enc_logscl(adpcm_enc_il, adpcm_enc_nbl);
/* scalel: compute the quantizer scale factor in the lower sub band */
/* calling parameters nbl and 8 (constant such that scalel can be scaleh) */
adpcm_enc_detl = adpcm_enc_scalel(adpcm_enc_nbl, 8);
/* parrec - simple addition to compute recontructed signal for adaptive pred
*/
adpcm_enc_plt = adpcm_enc_dlt + adpcm_enc_szl;
/* upzero: update zero section predictor coefficients (sixth order)*/
/* calling parameters: dlt, dlt1, dlt2, ..., dlt6 from dlt */
/* bpli (linear_buffer in which all six values are delayed */
/* return params: updated bpli, delayed dltx */
adpcm_enc_upzero(adpcm_enc_dlt, adpcm_enc_delay_dltx, adpcm_enc_delay_bpl);
/* uppol2- update second predictor coefficient apl2 and delay it as al2 */
/* calling parameters: al1, al2, plt, plt1, plt2 */
adpcm_enc_al2 =
adpcm_enc_uppol2(adpcm_enc_al1, adpcm_enc_al2, adpcm_enc_plt,
adpcm_enc_plt1, adpcm_enc_plt2);
/* uppol1 :update first predictor coefficient apl1 and delay it as al1 */
/* calling parameters: al1, apl2, plt, plt1 */
adpcm_enc_al1 = adpcm_enc_uppol1(adpcm_enc_al1, adpcm_enc_al2,
adpcm_enc_plt, adpcm_enc_plt1);
/* recons : compute recontructed signal for adaptive predictor */
adpcm_enc_rlt = adpcm_enc_sl + adpcm_enc_dlt;
/* done with lower sub_band encoder; now implement delays for next time*/
adpcm_enc_rlt2 = adpcm_enc_rlt1;
adpcm_enc_rlt1 = adpcm_enc_rlt;
adpcm_enc_plt2 = adpcm_enc_plt1;
adpcm_enc_plt1 = adpcm_enc_plt;
/* high band encode */
adpcm_enc_szh = adpcm_enc_filtez(adpcm_enc_delay_bph, adpcm_enc_delay_dhx);
adpcm_enc_sph = adpcm_enc_filtep(adpcm_enc_rh1, adpcm_enc_ah1,
adpcm_enc_rh2, adpcm_enc_ah2);
/* predic: sh = sph + szh */
adpcm_enc_sh = adpcm_enc_sph + adpcm_enc_szh;
/* subtra: eh = xh - sh */
adpcm_enc_eh = adpcm_enc_xh - adpcm_enc_sh;
/* quanth - quantization of difference signal for higher sub-band */
/* quanth: in-place for speed params: eh, deth (has init. value) */
if (adpcm_enc_eh >= 0)
adpcm_enc_ih = 3; /* 2,3 are pos codes */
else
adpcm_enc_ih = 1; /* 0,1 are neg codes */
decis = (564L * (long long) adpcm_enc_deth) >> 12L;
if (adpcm_enc_abs(adpcm_enc_eh) > decis)
adpcm_enc_ih--; /* mih = 2 case */
/* invqah: compute the quantized difference signal, higher sub-band*/
adpcm_enc_dh = ((long long) adpcm_enc_deth *
adpcm_enc_qq2_code2_table[adpcm_enc_ih]) >>
15L;
/* logsch: update logarithmic quantizer scale factor in hi sub-band*/
adpcm_enc_nbh = adpcm_enc_logsch(adpcm_enc_ih, adpcm_enc_nbh);
/* note : scalel and scaleh use same code, different parameters */
adpcm_enc_deth = adpcm_enc_scalel(adpcm_enc_nbh, 10);
/* parrec - add pole predictor output to quantized diff. signal */
adpcm_enc_ph = adpcm_enc_dh + adpcm_enc_szh;
/* upzero: update zero section predictor coefficients (sixth order) */
/* calling parameters: dh, dhi, bphi */
/* return params: updated bphi, delayed dhx */
adpcm_enc_upzero(adpcm_enc_dh, adpcm_enc_delay_dhx, adpcm_enc_delay_bph);
/* uppol2: update second predictor coef aph2 and delay as ah2 */
/* calling params: ah1, ah2, ph, ph1, ph2 */
adpcm_enc_ah2 = adpcm_enc_uppol2(adpcm_enc_ah1, adpcm_enc_ah2, adpcm_enc_ph,
adpcm_enc_ph1, adpcm_enc_ph2);
/* uppol1: update first predictor coef. aph2 and delay it as ah1 */
adpcm_enc_ah1 = adpcm_enc_uppol1(adpcm_enc_ah1, adpcm_enc_ah2, adpcm_enc_ph,
adpcm_enc_ph1);
/* recons for higher sub-band */
adpcm_enc_yh = adpcm_enc_sh + adpcm_enc_dh;
/* done with higher sub-band encoder, now Delay for next time */
adpcm_enc_rh2 = adpcm_enc_rh1;
adpcm_enc_rh1 = adpcm_enc_yh;
adpcm_enc_ph2 = adpcm_enc_ph1;
adpcm_enc_ph1 = adpcm_enc_ph;
/* multiplex ih and il to get signals together */
return (adpcm_enc_il | (adpcm_enc_ih << 6));
}
/* filtez - compute predictor output signal (zero section) */
/* input: bpl1-6 and dlt1-6, output: szl */
__attribute__((always_inline)) static inline int
adpcm_enc_filtez(int *bpl, int *dlt) {
int i;
long long int zl;
zl = (long long) (*bpl++) * (*dlt++);
/* MAX: 5 */
__pragma_loopbound(5, 5);
for (i = 1; i < 6; i++)
zl += (long long) (*bpl++) * (*dlt++);
return ((int) (zl >> 14)); /* x2 here */
}
/* filtep - compute predictor output signal (pole section) */
/* input rlt1-2 and al1-2, output spl */
__attribute__((always_inline)) static inline int
adpcm_enc_filtep(int rlt1, int al1, int rlt2, int al2) {
long long int pl, pl2;
pl = 2 * rlt1;
pl = (long long) al1 * pl;
pl2 = 2 * rlt2;
pl += (long long) al2 * pl2;
return ((int) (pl >> 15));
}
/* quantl - quantize the difference signal in the lower sub-band */
__attribute__((always_inline)) static inline int
adpcm_enc_quantl(int el, int detl) {
int ril, mil;
long long int wd, decis;
/* abs of difference signal */
wd = adpcm_enc_abs(el);
/* determine mil based on decision levels and detl gain */
/* MAX: 30 */
__pragma_loopbound(1, 30);
for (mil = 0; mil < 30; mil++) {
decis = (adpcm_enc_decis_levl[mil] * (long long) detl) >> 15L;
if (wd <= decis)
break;
}
/* if mil=30 then wd is less than all decision levels */
if (el >= 0)
ril = adpcm_enc_quant26bt_pos[mil];
else
ril = adpcm_enc_quant26bt_neg[mil];
return (ril);
}
/* invqxl is either invqbl or invqal depending on parameters passed */
/* returns dlt, code table is pre-multiplied by 8 */
/* int invqxl(int il,int detl,int *code_table,int mode) */
/* { */
/* long long int dlt; */
/* dlt = (long long)detl*code_table[ il >> (mode-1) ]; */
/* return((int)(dlt >> 15)); */
/* } */
/* logscl - update log quantizer scale factor in lower sub-band */
/* note that nbl is passed and returned */
__attribute__((always_inline)) static inline int
adpcm_enc_logscl(int il, int nbl) {
long long int wd;
wd = ((long long) nbl * 127L) >> 7L; /* leak factor 127/128 */
nbl = (int) wd + adpcm_enc_wl_code_table[il >> 2];
if (nbl < 0)
nbl = 0;
if (nbl > 18432)
nbl = 18432;
return (nbl);
}
/* scalel: compute quantizer scale factor in lower or upper sub-band*/
__attribute__((always_inline)) static inline int
adpcm_enc_scalel(int nbl, int shift_constant) {
int wd1, wd2, wd3;
wd1 = (nbl >> 6) & 31;
wd2 = nbl >> 11;
wd3 = adpcm_enc_ilb_table[wd1] >> (shift_constant + 1 - wd2);
return (wd3 << 3);
}
/* upzero - inputs: dlt, dlti[ 0-5 ], bli[ 0-5 ], outputs: updated bli[ 0-5 ] */
/* also implements delay of bli and update of dlti from dlt */
__attribute__((always_inline)) static inline void
adpcm_enc_upzero(int dlt, int *dlti, int *bli) {
int i, wd2, wd3;
/*if dlt is zero, then no sum into bli */
if (dlt == 0) {
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
bli[i] = (int) ((255L * bli[i]) >> 8L); /* leak factor of 255/256 */
}
} else {
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
if ((long long) dlt * dlti[i] >= 0)
wd2 = 128;
else
wd2 = -128;
wd3 = (int) ((255L * bli[i]) >> 8L); /* leak factor of 255/256 */
bli[i] = wd2 + wd3;
}
}
/* implement delay line for dlt */
dlti[5] = dlti[4];
dlti[4] = dlti[3];
dlti[3] = dlti[2];
dlti[1] = dlti[0];
dlti[0] = dlt;
return;
}
/* uppol2 - update second predictor coefficient (pole section) */
/* inputs: al1, al2, plt, plt1, plt2. outputs: apl2 */
__attribute__((always_inline)) static inline int
adpcm_enc_uppol2(int al1, int al2, int plt, int plt1, int plt2) {
long long int wd2, wd4;
int apl2;
wd2 = 4L * (long long) al1;
if ((long long) plt * plt1 >= 0L)
wd2 = -wd2; /* check same sign */
wd2 = wd2 >> 7; /* gain of 1/128 */
if ((long long) plt * plt2 >= 0L) {
wd4 = wd2 + 128; /* same sign case */
} else
wd4 = wd2 - 128;
apl2 = wd4 + (127L * (long long) al2 >> 7L); /* leak factor of 127/128 */
/* apl2 is limited to +-.75 */
if (apl2 > 12288)
apl2 = 12288;
if (apl2 < -12288)
apl2 = -12288;
return (apl2);
}
/* uppol1 - update first predictor coefficient (pole section) */
/* inputs: al1, apl2, plt, plt1. outputs: apl1 */
__attribute__((always_inline)) static inline int
adpcm_enc_uppol1(int al1, int apl2, int plt, int plt1) {
long long int wd2;
int wd3, apl1;
wd2 = ((long long) al1 * 255L) >> 8L; /* leak factor of 255/256 */
if ((long long) plt * plt1 >= 0L) {
apl1 = (int) wd2 + 192; /* same sign case */
} else
apl1 = (int) wd2 - 192;
/* note: wd3= .9375-.75 is always positive */
wd3 = 15360 - apl2; /* limit value */
if (apl1 > wd3)
apl1 = wd3;
if (apl1 < -wd3)
apl1 = -wd3;
return (apl1);
}
/* INVQAH: inverse adaptive quantizer for the higher sub-band */
/* returns dh, code table is pre-multiplied by 8 */
/* int invqah(int ih,int deth) */
/* { */
/* long long int rdh; */
/* rdh = ((long long)deth*qq2_code2_table[ ih ]) >> 15L ; */
/* return((int)(rdh )); */
/* } */
/* logsch - update log quantizer scale factor in higher sub-band */
/* note that nbh is passed and returned */
__attribute__((always_inline)) static inline int
adpcm_enc_logsch(int ih, int nbh) {
int wd;
wd = ((long long) nbh * 127L) >> 7L; /* leak factor 127/128 */
nbh = wd + adpcm_enc_wh_code_table[ih];
if (nbh < 0)
nbh = 0;
if (nbh > 22528)
nbh = 22528;
return (nbh);
}
/*
Initialization- and return-value-related functions
*/
/* clear all storage locations */
__attribute__((always_inline)) static inline void
adpcm_enc_reset(void) {
int i;
adpcm_enc_detl = 32; /* reset to min scale factor */
adpcm_enc_deth = 8;
adpcm_enc_nbl = adpcm_enc_al1 = adpcm_enc_al2 = adpcm_enc_plt1 =
adpcm_enc_plt2 = adpcm_enc_rlt1 = adpcm_enc_rlt2 = 0;
adpcm_enc_nbh = adpcm_enc_ah1 = adpcm_enc_ah2 = adpcm_enc_ph1 =
adpcm_enc_ph2 = adpcm_enc_rh1 = adpcm_enc_rh2 = 0;
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
adpcm_enc_delay_dltx[i] = 0;
adpcm_enc_delay_dhx[i] = 0;
}
__pragma_loopbound(6, 6);
for (i = 0; i < 6; i++) {
adpcm_enc_delay_bpl[i] = 0;
adpcm_enc_delay_bph[i] = 0;
}
__pragma_loopbound(23, 23);
for (i = 0; i < 23; i++)
adpcm_enc_tqmf[i] = 0;
return;
}
__attribute__((always_inline)) static inline void
adpcm_enc_init(void) {
int i, j, f;
volatile int x = 0;
/* reset, initialize required memory */
adpcm_enc_reset();
/* read in amplitude and frequency for test data */
j = 10;
f = 2000;
/* 16 KHz sample rate */
/* XXmain_0, MAX: 2 */
/* Since the number of times we loop in my_sin depends on the argument we
add the fact: xxmain_0:[ ]: */
__pragma_loopbound(3, 3);
for (i = 0; i < SIZE; i++) {
adpcm_enc_test_data[i] = (int) j * adpcm_enc_cos(f * PI * i);
/* avoid constant-propagation optimizations */
adpcm_enc_test_data[i] += x;
}
}
__attribute__((always_inline)) static inline int
adpcm_enc_return(void) {
int i;
int check_sum = 0;
__pragma_loopbound(2, 2);
for (i = 0; i < IN_END; i += 2)
check_sum += adpcm_enc_compressed[i / 2];
return check_sum != 385;
}
/*
Main functions
*/
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
adpcm_enc_main(void) {
int i;
/* MAX: 2 */
__pragma_loopbound(2, 2);
for (i = 0; i < IN_END; i += 2)
adpcm_enc_compressed[i / 2] = adpcm_enc_encode(
adpcm_enc_test_data[i], adpcm_enc_test_data[i + 1]);
}
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
adpcm_enc_init();
adpcm_enc_main();
return adpcm_enc_return();
}

View File

@ -0,0 +1,28 @@
# ~~~
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2026, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
# ~~~
cmake_minimum_required(VERSION 3.20)
project(ammunition)
set(TACLEBENCH_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../..")
set(REPOSITORY_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../..")
set(APP_TARGET_NAME "${CMAKE_PROJECT_NAME}")
if(DEFINED TACLEBENCH_VARIANT AND "${TACLEBENCH_VARIANT}" STREQUAL "inline")
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/inline/ammunition.c")
else()
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/default/ammunition.c"
"generated/modified_sources/default/ammunition_libc.c"
"generated/modified_sources/default/arithm.c"
"generated/modified_sources/default/bits.c")
endif()
include(${REPOSITORY_ROOT_PATH}/cmake/taclebench_wasm.cmake)

View File

@ -0,0 +1,66 @@
File: ammunition.c
Original provenience: DINO programming language
2016-03-03:
- Add generic TACLeBench header
- Prefix global functions with benchmark name
- Introduce volatile result variable for return statements
- Split code into ammunition_init and ammunition_main
- Fix compiler warnings "array subscript is of type 'char'":
char => unsigned char
- Fix compiler warnings "'&&' within '||'":
Place additional parentheses
- Remove usages and comments related to the macros
HAVE_MEMMOVE, NDEBUG, HAVE_MEMCMP
- Remove comment related to unused NO_TEMPLATE macro
2016-05-02:
- Change C++ style comments to ISO C90 compliant comments
- Avoid mixing declarations and code: move declaration of variable writePos in
functions ammunition_sprintf_d and ammunition_sprintf_u
- Change datatype in function ammunition_bits_test of iteration variables i and
j from int to unsigned int to avoid comparison between signed and unsigned
integer expressions
- Add forward declarations to ammunition.c
- Introduce variable ammunition_result
- Parantheses around comparison in functions ammunition_isdigit and
ammunition_isspace
- Remove usage of limits.h, move definitions of limits into separate file
ammunition_limits.h
- Remove unconditional assignments of variable result to zero after each test in
functions ammunition_bits_test and ammunition_arithm_test
- Remove unused functions unsigned_integer_maximum, integer_minimum,
integer_maximum, integer_remainder
- Remove unused declaration of function default_arithmetic_overflow_reaction
- Remove unused variables zero_constant_itself, zero_constant
- Remove unused declarations of functions set_unsigned_integer_overflow_reaction
and set_integer_overflow_reaction
- Remove block #ifndef MAX_INTEGER_OPERAND_SIZE, set definition of
MAX_INTEGER_OPERAND_SIZE to 128, since this is default
2016-05-10:
- Integrate new version of arithm library from ammunition repository from
dino repository on github (commit: db9cfab042c332abb234ec8d72750103010981c1),
which hanles arithmetic shifts by negative numbers. This change now makes all
test cases in ammunition.c pass. Update headers unsigned int bits => int bits
- Remove assert statements
- Fix memcmp implementation: dereferencing pointer was missing
- Add loop-bound annotation to memcmp
- Fix strcmp implementation
- Integrate working versions of memcpy and memset from pm benchmark
- Update signature of ammunition_memcpy to original version:
void *memcpy(void *dest, const void *src, size_t n);
- Move functions from libc into separate file, introduce header files
ammunition_limits.h, ammunition_stdio.h, ammunition_stdlib.h,
ammunition_string.h
- Fix overflow in sprintf_d: change datatype of variable 'copyOfNumber' from int
to long, since the negative value of INT_MIN is undefined
2016-05-17:
- Remove all static declarations of global functions
- Rename variables 'digit_number' to digit_num to keep lines below 80 characters
- Rename op1_digit_number to op1_digit_number and op1_digit_num in function
'ammunition_multiply_unsigned_integer_without_overflow_reaction'
- Rename variable 'scaled_op1_digit_number' in function
'ammunition_divide_unsigned_integer_without_overflow_reaction'
- Apply code formatting with astyle
2017-08-18:
- Add explicit casts to silence g++ warnings.

View File

@ -0,0 +1,86 @@
This directory AMMUNITION contains reusable packages on C/C++:
`allocate', `vlobject', `objstack', `hashtab', `commline', `ticker',
`position', `errors', `bits', `arithm', `IEEE':
o allocate
Allocating and freeing memory with automatic fixing some
allocation errors.
o vlobject
Work with variable length objects (VLO). Any number of bytes
may be added to and removed from the end of VLO. If it is
needed the memory allocated for storing variable length object
may be expanded possibly with changing the object place. But
between any additions of the bytes (or tailoring) the object
place is not changed. To decrease number of changes of the
object place the memory being allocated for the object is
longer than the current object length.
o objstack
Work with stacks of objects (OS). Work with the object on the
stack top is analogous to one with a variable length object.
One motivation for the package is the problem of growing char
strings in symbol tables. Memory for OS is allocated by
segments. A segment may contain more one objects. The most
recently allocated segment contains object on the top of OS.
If there is not sufficient free memory for the top object than
new segment is created and the top object is transferred into
the new segment, i.e. there is not any memory reallocation.
Therefore the top object may change its address. But other
objects never change address.
o hashtab
Work with hash tables. The package permits to work
simultaneously with several expandable hash tables. Besides
insertion and search of elements the elements from the hash
tables can be also removed. The table element can be only a
pointer. The size of hash tables is not fixed. The hash
table will be automatically expanded when its occupancy will
became big.
o position
Work with source code positions. The package serves to
support information about source positions of compiled files
taking all included files into account.
o errors
Output of compiler messages. The package serves output
one-pass or multi-pass compiler messages of various modes
(errors, warnings, fatal, system errors and appended messages)
in Unix style or for traditional listing. The package also
permits adequate error reporting for included files.
o commline
Work with command line. The package implements features
analogous to ones of public domain function `getopt'. The
goal of the package creation is to use more readable language
of command line description and to use command line
description as help output of program.
o ticker
Simultaneous work with several tickers (timers).
o bits
Work with bit strings (copying, moving, setting, testing,
comparison).
o arithm
Implementing host machine-independently arbitrary precision
integer numbers arithmetic. The implementation of the package
functions are not sufficiently efficient in order to use for
run-time. The package functions are oriented to implement
constant-folding in compilers, cross-compilers.
o IEEE
Implementing host machine-independently IEEE floating point
arithmetic. The implementation of the package functions are
not sufficiently efficient in order to use for run-time. The
package functions are oriented to implement constant-folding
in compilers, cross-compilers.
There are files with corresponding names and extensions `.h'
(interface file for C/C++), `.c' (implementation file on C), and
`.cpp' (implementation file on C++).
To install AMMUNITION see file INSTALL in the current directory.
There are also shell scripts for testing the package with
corresponding names and extension `.tst'. Documentation of the
reusable packages is in files `ammunition.txt', `ammunition.dvi',
`ammunition.ps', `ammunition.info*', `ammunition*.html',
`ammunition*.rtf' for C and `ammunition++.txt', `ammunition++.dvi',
`ammunition++.ps', `ammunition++.info*', `ammunition++*.html',
`ammunition++*.rtf'.
Please send bug reports and comments to vmakarov@fnmail.com
Vladimir Makarov

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,166 @@
/*
Include section
*/
#include "ammunition_string.h"
#include "ammunition_stdio.h"
#include "ammunition_stdlib.h"
/*
Standard library functions
*/
char ammunition_isdigit( unsigned char c )
{
if ( ( c >= '0' ) & ( c <= '9' ) )
return 1;
else
return 0;
}
int ammunition_isspace( int c )
{
return ( c == ' ' ) | ( c == '\t' ) | ( c == '\n' ) | ( c == '\r' );
}
void *ammunition_memcpy( void *dest, const void *src, size_t size )
{
size_t i;
_Pragma( "loopbound min 2 max 6" )
for ( i = 0; i < size; i++ )
( ( unsigned char * )dest )[ i ] = ( ( unsigned char * )src )[ i ];
return dest;
}
void *ammunition_memset( void *s, int c, size_t n )
{
size_t i;
_Pragma( "loopbound min 0 max 4" )
for ( i = 0; i < n; i++ )
( ( unsigned char * )s )[ i ] = ( unsigned char )c;
return s;
}
int ammunition_memcmp ( const void *mem1, const void *mem2, size_t size )
{
const unsigned char *p1 = ( const unsigned char * ) mem1,
*p2 = ( const unsigned char * ) mem2;
_Pragma( "loopbound min 0 max 4" )
while ( size-- )
if ( *p1 != *p2 )
return ( *p1 - *p2 );
else
p1++, p2++;
return 0;
}
/* The following function is an analog of standard C function
`memmove'. The function returns the first operand. */
void *ammunition_memmove ( void *s1, const void *s2, size_t n )
{
int i;
if ( ( ( char * ) s1 < ( char * ) s2 && ( char * ) s1 + n <= ( char * ) s2 )
|| ( ( char * ) s2 < ( char * ) s1
&& ( char * ) s2 + n <= ( char * ) s1 ) )
return ( void * ) ammunition_memcpy ( s1, s2, n );
if ( ( char * ) s1 < ( char * ) s2 && ( char * ) s1 + n > ( char * ) s2 ) {
_Pragma( "loopbound min 0 max 4" )
for ( i = 0; ( size_t ) i < n; i++ )
( ( char * ) s1 ) [ i ] = ( ( char * ) s2 ) [ i ];
} else {
_Pragma( "loopbound min 0 max 4" )
for ( i = n - 1; i >= 0; i-- )
( ( char * ) s1 )[ i ] = ( ( char * ) s2 ) [ i ];
}
return s1;
}
int ammunition_strcmp ( const char *str1, const char *str2 )
{
_Pragma( "loopbound min 1 max 11" )
while ( *str1 && ( *str1 == *str2 ) )
str1++, str2++;
return *( const unsigned char * )str1 - *( const unsigned char * )str2;
}
int ammunition_atoi ( const char *str )
{
int result = 0;
int sign = ( str[ 0 ] == '-' ? -1 : 1 );
int readingPos = 0;
if ( str[ 0 ] == '-' || str[ 0 ] == '+' )
readingPos++;
_Pragma( "loopbound min 1 max 7" )
do {
result *= 10;
result += str[ readingPos++ ] - 48;
} while ( str[ readingPos ] != 0 );
return sign * result;
}
int ammunition_sprintf_d( char *s, int number )
{
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
long long copyOfNumber = number;
_Pragma( "loopbound min 1 max 10" )
do {
digits++;
copyOfNumber /= 10;
} while ( copyOfNumber != 0 );
writePos = digits;
if ( number < 0 ) {
writePos++;
s[ 0 ] = '-';
}
s[ writePos ] = 0;
copyOfNumber = number;
_Pragma( "loopbound min 1 max 10" )
do {
s[ --writePos ] = 48 + ( ( copyOfNumber >= 0 ?
copyOfNumber : -copyOfNumber ) % 10 );
copyOfNumber /= 10;
} while ( copyOfNumber != 0 );
return digits + ( number < 0 ? 1 : 0 );
}
int ammunition_sprintf_u( char *s, unsigned int number )
{
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
unsigned long long copyOfNumber = number;
_Pragma( "loopbound min 1 max 10" )
do {
digits++;
copyOfNumber /= 10;
} while ( copyOfNumber != 0 );
writePos = digits;
s[ writePos ] = 0;
copyOfNumber = number;
_Pragma( "loopbound min 1 max 10" )
do {
s[ --writePos ] = 48 + ( copyOfNumber % 10 );
copyOfNumber /= 10;
} while ( copyOfNumber != 0 );
return digits;
}

View File

@ -0,0 +1,35 @@
#ifndef AMMUNITION_LIMITS_H
#define AMMUNITION_LIMITS_H
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#ifndef UCHAR_MAX
#define UCHAR_MAX 255
#endif
#ifndef SCHAR_MAX
#define SCHAR_MAX 127
#endif
#ifndef SCHAR_MIN
#define SCHAR_MIN (-128)
#endif
#ifndef USHRT_MAX
#define USHRT_MAX 65535
#endif
#ifndef SHRT_MAX
#define SHRT_MAX 32767
#endif
#ifndef SHRT_MIN
#define SHRT_MIN (-32768)
#endif
#ifndef UINT_MAX
#define UINT_MAX (INT_MAX * 2U + 1)
#endif
#ifndef INT_MAX
#define INT_MAX 2147483647
#endif
#ifndef INT_MIN
#define INT_MIN (-INT_MAX-1)
#endif
#endif /* #ifndef AMMUNITION_LIMITS_H */

View File

@ -0,0 +1,8 @@
#ifndef AMMUNITION_STDIO_H
#define AMMUNITION_STDIO_H
int ammunition_sprintf_d( char *s, int number );
int ammunition_sprintf_u( char *s, unsigned int number );
#endif

View File

@ -0,0 +1,6 @@
#ifndef AMMUNITION_STDLIB_H
#define AMMUNITION_STDLIB_H
int ammunition_atoi ( const char *str );
#endif

View File

@ -0,0 +1,18 @@
#ifndef AMMUNITION_STRING_H
#define AMMUNITION_STRING_H
typedef unsigned int size_t;
/*
Forward declaration of functions
*/
void *ammunition_memcpy( void *, const void *, size_t );
void *ammunition_memset( void *, int, size_t );
int ammunition_memcmp ( const void *mem1, const void *mem2, size_t size );
void *ammunition_memmove ( void *s1, const void *s2, size_t n );
int ammunition_strcmp ( const char *str1, const char *str2 );
#endif /* AMMUNITION_STRING_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
/*
FILE NAME: arithm.h
TITLE: Include file of package for arbitrary precision integer
arithmetic
DESCRIPTION: This header file contains ANSI C prototype definitions of
the package functions and definitions of external
variable of the package and C++ classes for arbitrary
precision integer arithmetic.
*/
#ifndef __ARITHMETIC__
#define __ARITHMETIC__
#include "ammunition_limits.h"
/* This page contains definitions of variables and macros common for
all package functions. */
/* The value of macro is suggested to be maximum length of integer operands
The length of use integers should be not greater than this value. */
#define MAX_INTEGER_OPERAND_SIZE 128
/* The following macro value is sign of integer number (0 or 1) given
as macro parameter. */
#define INTEGER_SIGN(operand) (*(unsigned char *) (operand) >> (CHAR_BIT - 1))
extern int ammunition_overflow_bit;
extern void ammunition_add_unsigned_integer ( int size, const void *op1,
const void *op2,
void *result );
extern void ammunition_add_integer ( int size, const void *op1, const void *op2,
void *result );
extern void ammunition_subtract_unsigned_integer ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_subtract_integer ( int size, const void *op1,
const void *op2,
void *result );
extern void ammunition_multiply_unsigned_integer ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_multiply_integer ( int size, const void *op1,
const void *op2,
void *result );
extern void ammunition_divide_unsigned_integer ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_divide_integer ( int size, const void *op1,
const void *op2,
void *result );
extern void ammunition_unsigned_integer_remainder ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_unsigned_integer_shift_right ( int size,
const void *operand,
int bits, void *result );
extern void ammunition_integer_shift_right ( int size, const void *operand,
int bits, void *result );
extern void ammunition_integer_shift_left ( int size, const void *operand,
int bits, void *result );
extern void ammunition_unsigned_integer_shift_left ( int size,
const void *operand,
int bits, void *result );
extern void ammunition_integer_or ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_unsigned_integer_or ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_integer_and ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_unsigned_integer_and ( int size, const void *op1,
const void *op2, void *result );
extern void ammunition_integer_not ( int size, const void *operand,
void *result );
extern void ammunition_unsigned_integer_not ( int size, const void *operand,
void *result );
extern int ammunition_eq_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_eq_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_ne_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_ne_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_gt_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_gt_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_lt_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_lt_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_ge_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_ge_integer ( int size, const void *op1, const void *op2 );
extern int ammunition_le_unsigned_integer ( int size, const void *op1,
const void *op2 );
extern int ammunition_le_integer ( int size, const void *op1, const void *op2 );
extern void ammunition_change_unsigned_integer_size
( int operand_size, const void *operand, int result_size, void *result );
extern void ammunition_change_integer_size ( int operand_size,
const void *operand,
int result_size, void *result );
extern char *ammunition_unsigned_integer_to_string ( int size,
const void *operand,
char *result );
extern char *ammunition_integer_to_string ( int size, const void *operand,
char *result );
extern char *ammunition_unsigned_integer_from_string ( int size,
const char *operand,
void *result );
extern char *ammunition_integer_from_string ( int size, const char *operand,
void *result );
char ammunition_isdigit( unsigned char c );
int ammunition_isspace( int c );
#endif /* #ifndef __ARITHMETIC__ */

View File

@ -0,0 +1,313 @@
/*
FILE NAME: bits.c
TITLE: Package for work with bits
DESCRIPTION: This file implements functions of the package for work
with bit strings. A bit is given by address (start address) of
byte from which counting bits starts and its displacement which
is any non negative number of bit from the start address. The
most significant bit of the start address byte has number 0.
The bit string is given by its first bit and its length in
bits.
*/
#include "bits.h"
/* This function determines that given bit string contains only zero
bits. The function retruns TRUE if all bits of given bit string
are zero or `bit_length' <= 0. Value of `bit_displacement' must be
non-negative and can be greater than CHAR_BIT. */
int
ammunition_is_zero_bit_string ( const void *start_byte, int bit_displacement,
int bit_length )
{
const unsigned char *current_byte = ( unsigned const char * )start_byte;
if ( bit_length <= 0 )
return 1 /* TRUE */;
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if ( bit_length < CHAR_BIT - bit_displacement )
return ( ( ( *current_byte << bit_displacement )
& ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) )
& UCHAR_MAX ) == 0;
else
if ( bit_displacement != 0 ) {
if ( ( ( *current_byte << bit_displacement ) & UCHAR_MAX ) != 0 )
return 0 /* FALSE */;
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
_Pragma( "loopbound min 0 max 7" )
while ( bit_length >= CHAR_BIT ) {
if ( *current_byte != 0 )
return 0 /* FALSE */;
current_byte++;
bit_length -= CHAR_BIT;
}
if ( bit_length > 0 && ( *current_byte >> ( CHAR_BIT - bit_length ) ) != 0 )
return 0 /* FALSE */;
return 1 /* TRUE */;
}
/* This function sets up new value of all bits of given bit string.
This function is analog of standard C function `memset'. Value of
`bit_displacement' must be non-negative and can be greater than
CHAR_BIT. */
void
ammunition_bit_string_set ( void *start_byte, int bit_displacement, int bit,
int bit_length )
{
unsigned char *current_byte = ( unsigned char * )start_byte;
unsigned char filling_byte;
int mask;
if ( bit_length <= 0 )
return ;
bit = bit != 0; /* 1 or 0 */
filling_byte = ( bit ? UCHAR_MAX : 0 );
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if ( bit_displacement != 0 ) {
mask = UCHAR_MAX << ( CHAR_BIT - bit_displacement );
if ( bit_length < CHAR_BIT - bit_displacement )
mask |= UCHAR_MAX >> ( bit_displacement + bit_length );
*current_byte = ( *current_byte & mask ) | ( filling_byte & ~mask );
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
_Pragma( "loopbound min 0 max 8" )
while ( bit_length >= CHAR_BIT ) {
*current_byte = filling_byte;
current_byte++;
bit_length -= CHAR_BIT;
}
if ( bit_length > 0 )
*current_byte
= ( *current_byte & ~( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) )
| ( filling_byte & ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) );
}
/* This function copys a bit string to another bit string. This
function is analog of standard C function `memcpy'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
void
ammunition_bit_string_copy ( void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length )
{
unsigned char *current_to_byte = ( unsigned char * )to;
const unsigned char *current_from_byte = ( unsigned const char * )from;
int byte;
int mask;
if ( bit_length <= 0 )
return ;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
_Pragma( "loopbound min 0 max 7" )
while ( 1 ) {
byte = ( ( ( *current_from_byte << from_bit_displacement ) & UCHAR_MAX )
| ( from_bit_displacement != 0
&& bit_length > ( CHAR_BIT - from_bit_displacement )
? current_from_byte [ 1 ] >> ( CHAR_BIT - from_bit_displacement )
: 0 ) );
if ( bit_length <= CHAR_BIT )
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte
= ( *current_to_byte
& ( UCHAR_MAX << ( CHAR_BIT - to_bit_displacement ) ) )
| ( byte >> to_bit_displacement );
if ( to_bit_displacement != 0 )
current_to_byte [ 1 ]
= ( current_to_byte [ 1 ] & ( UCHAR_MAX >> to_bit_displacement ) )
| ( byte << ( CHAR_BIT - to_bit_displacement ) );
bit_length -= CHAR_BIT;
current_from_byte++;
current_to_byte++;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ( ( UCHAR_MAX << ( CHAR_BIT - to_bit_displacement ) )
| ( UCHAR_MAX >> ( to_bit_displacement + bit_length ) ) );
*current_to_byte
= ( *current_to_byte & mask ) | ( ( byte >> to_bit_displacement ) & ~mask );
bit_length -= CHAR_BIT - to_bit_displacement;
if ( bit_length > 0 )
current_to_byte [ 1 ]
= ( current_to_byte [ 1 ] & ( UCHAR_MAX >> bit_length ) )
| ( ( byte << ( CHAR_BIT - to_bit_displacement ) )
& ( UCHAR_MAX << ( CHAR_BIT - bit_length ) ) );
}
/* This function copys a bit string to another bit string. Copying
starts with the last bits of the bit strings. This function is
used by function `bit_string_move'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
void ammunition_reverse_bit_string_copy ( void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length )
{
unsigned char *current_to_byte = ( unsigned char * )to;
const unsigned char *current_from_byte = ( unsigned const char * )from;
int byte;
int mask;
if ( bit_length <= 0 )
return ;
to_bit_displacement += bit_length - 1;
current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */
to_bit_displacement %= CHAR_BIT; /* last bit */
from_bit_displacement += bit_length - 1;
current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */
from_bit_displacement %= CHAR_BIT; /* last bit */
_Pragma( "loopbound min 0 max 7" )
while ( 1 ) {
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
byte = ( ( *current_from_byte >> ( CHAR_BIT - 1 - from_bit_displacement ) )
| ( ( from_bit_displacement != CHAR_BIT - 1
&& bit_length > from_bit_displacement + 1
? current_from_byte [ -1 ] << ( from_bit_displacement + 1 )
: 0 )
& UCHAR_MAX ) );
if ( bit_length <= CHAR_BIT )
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte
= ( *current_to_byte & ( UCHAR_MAX >> ( to_bit_displacement + 1 ) ) )
| ( byte << ( CHAR_BIT - 1 - to_bit_displacement ) );
if ( to_bit_displacement != CHAR_BIT - 1 )
current_to_byte [ -1 ]
= ( current_to_byte [ -1 ]
& ( UCHAR_MAX << ( CHAR_BIT - 1 - to_bit_displacement ) ) )
| ( byte >> ( to_bit_displacement + 1 ) );
bit_length -= CHAR_BIT;
current_from_byte--;
current_to_byte--;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ( ( UCHAR_MAX >> ( to_bit_displacement + 1 ) ) |
( UCHAR_MAX << ( CHAR_BIT - 1 - to_bit_displacement
+ bit_length ) ) );
*current_to_byte
= ( *current_to_byte & mask )
| ( ( byte << ( CHAR_BIT - 1 - to_bit_displacement ) ) & ~mask );
bit_length -= to_bit_displacement + 1;
if ( bit_length > 0 )
current_to_byte [ -1 ]
= ( current_to_byte [ -1 ] & ( UCHAR_MAX << bit_length ) )
| ( byte >> ( to_bit_displacement + 1 )
& ( UCHAR_MAX >> ( CHAR_BIT - bit_length ) ) );
}
/* This function copys a bit string to another bit string with the aid
of functions `bit_string_copy' and `reverse_bit_string_copy'. This
function is analog of standard C function `memmove'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string can
be overlapped. */
void
ammunition_bit_string_move ( void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length )
{
unsigned char *current_to_byte = ( unsigned char * )to;
const unsigned char *current_from_byte = ( unsigned const char * )from;
if ( bit_length <= 0 )
return ;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
if ( current_from_byte > current_to_byte
|| ( current_from_byte == current_to_byte
&& from_bit_displacement > to_bit_displacement ) )
ammunition_bit_string_copy ( current_to_byte, to_bit_displacement,
current_from_byte, from_bit_displacement,
bit_length );
else
ammunition_reverse_bit_string_copy ( current_to_byte, to_bit_displacement,
current_from_byte,
from_bit_displacement, bit_length );
}
/* This function compares bit strings. This function is analog of
standard C function `memcmp'. The function returns 0 if the bit
strings are equal, 1 if the first bit string is greater than the
second, -1 if the first bit string is less than the first. Values
of `bit_displacement1' and `bit_displacement2' must be non-negative
and can be greater than CHAR_BIT. */
int
ammunition_bit_string_comparison ( const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length )
{
const unsigned char *current_byte1 = ( unsigned const char * )str1;
const unsigned char *current_byte2 = ( unsigned const char * )str2;
int byte1;
int byte2;
int mask;
if ( bit_length <= 0 )
return 0;
current_byte1 += bit_displacement1 / CHAR_BIT;
bit_displacement1 %= CHAR_BIT;
current_byte2 += bit_displacement2 / CHAR_BIT;
bit_displacement2 %= CHAR_BIT;
_Pragma( "loopbound min 0 max 7" )
while ( 1 ) {
byte1 = ( ( ( *current_byte1 << bit_displacement1 ) & UCHAR_MAX )
| ( bit_displacement1 != 0
/* Shift is correct when to_bit_displacement == 0
because its value is less than word bit size. */
&& bit_length > CHAR_BIT - bit_displacement1
? current_byte1 [ 1 ] >> ( CHAR_BIT - bit_displacement1 )
: 0 ) );
byte2 = ( ( ( *current_byte2 << bit_displacement2 ) & UCHAR_MAX )
| ( bit_displacement2 != 0
&& bit_length > CHAR_BIT - bit_displacement2
? current_byte2 [ 1 ] >> ( CHAR_BIT - bit_displacement2 )
: 0 ) );
if ( bit_length <= CHAR_BIT )
break;
if ( byte1 > byte2 )
return 1;
else
if ( byte1 < byte2 )
return -1;
bit_length -= CHAR_BIT;
current_byte2++;
current_byte1++;
}
/* Shift is correct when to_bit_displacement == 0 because its value
is less than word bit size. */
mask = UCHAR_MAX << ( CHAR_BIT - bit_length );
if ( ( byte1 & mask ) > ( byte2 & mask ) )
return 1;
else
if ( ( byte1 & mask ) < ( byte2 & mask ) )
return -1;
else
return 0;
}

View File

@ -0,0 +1,60 @@
/*
FILE NAME: bits.h
TITLE: Include file of package for work with bits
DESCRIPTION:
This is header file contains macros and the ANSI C prototype
definitions for the package for work with bits and bit strings
and C++ class for work with bits and bit strings. A bit is
given by address (start address) of byte from which counting
bits starts and its displacement which is any non negative
number of bit from the start address. The most significant bit
of the start address byte has number 0. The bit string is
given by its first bit and its length in bits.
*/
#ifndef __BITS__
#define __BITS__
#include "ammunition_limits.h"
/* This macro value returns bit vlaue (0 or 1) with given bit
displacement (0, 1, ...). The macro has side effects! Value of
`bit_displacement' must be nonegative and can be greater than
CHAR_BIT. */
#define BIT(start_byte, bit_displacement)\
((((const char *) (start_byte)) [(bit_displacement) / CHAR_BIT]\
>> (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)) & 1)
/* This macro value sets up new value (must be `0' or `1') of a given
bit (bit displacement starts with 0). The macro has side effects!
Value of `bit_displacement' must be nonegative and can be greater
than CHAR_BIT. */
#define SET_BIT(start_byte, bit_displacement, bit)\
(((char *) (start_byte)) [(bit_displacement) / CHAR_BIT]\
= (((char *) (start_byte)) [(bit_displacement) / CHAR_BIT]\
& ~(1 << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))\
| ((bit) << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))
int ammunition_is_zero_bit_string ( const void *start_byte,
int bit_displacement,
int bit_length );
void ammunition_bit_string_set ( void *start_byte, int bit_displacement,
int bit,
int bit_length );
void ammunition_bit_string_copy ( void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length );
void ammunition_bit_string_move ( void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length );
int ammunition_bit_string_comparison ( const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length );
#endif /* #ifndef __BITS__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
/*
Include section
*/
#include "ammunition_stdio.h"
#include "ammunition_stdlib.h"
#include "ammunition_string.h"
/*
Standard library functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
char
ammunition_isdigit(unsigned char c) {
if ((c >= '0') & (c <= '9'))
return 1;
else
return 0;
}
int
ammunition_isspace(int c) {
return (c == ' ') | (c == '\t') | (c == '\n') | (c == '\r');
}
void *
ammunition_memcpy(void *dest, const void *src, size_t size) {
size_t i;
__pragma_loopbound(2, 6);
for (i = 0; i < size; i++)
((unsigned char *) dest)[i] = ((unsigned char *) src)[i];
return dest;
}
void *
ammunition_memset(void *s, int c, size_t n) {
size_t i;
__pragma_loopbound(0, 4);
for (i = 0; i < n; i++)
((unsigned char *) s)[i] = (unsigned char) c;
return s;
}
int
ammunition_memcmp(const void *mem1, const void *mem2, size_t size) {
const unsigned char *p1 = (const unsigned char *) mem1,
*p2 = (const unsigned char *) mem2;
__pragma_loopbound(0, 4);
while (size--)
if (*p1 != *p2)
return (*p1 - *p2);
else
p1++, p2++;
return 0;
}
/* The following function is an analog of standard C function
`memmove'. The function returns the first operand. */
void *
ammunition_memmove(void *s1, const void *s2, size_t n) {
int i;
if (((char *) s1 < (char *) s2 && (char *) s1 + n <= (char *) s2) ||
((char *) s2 < (char *) s1 && (char *) s2 + n <= (char *) s1))
return (void *) ammunition_memcpy(s1, s2, n);
if ((char *) s1 < (char *) s2 && (char *) s1 + n > (char *) s2) {
__pragma_loopbound(0, 4);
for (i = 0; (size_t) i < n; i++)
((char *) s1)[i] = ((char *) s2)[i];
} else {
__pragma_loopbound(0, 4);
for (i = n - 1; i >= 0; i--)
((char *) s1)[i] = ((char *) s2)[i];
}
return s1;
}
int
ammunition_strcmp(const char *str1, const char *str2) {
__pragma_loopbound(1, 11);
while (*str1 && (*str1 == *str2))
str1++, str2++;
return *(const unsigned char *) str1 - *(const unsigned char *) str2;
}
int
ammunition_atoi(const char *str) {
int result = 0;
int sign = (str[0] == '-' ? -1 : 1);
int readingPos = 0;
if (str[0] == '-' || str[0] == '+')
readingPos++;
__pragma_loopbound(1, 7);
do {
result *= 10;
result += str[readingPos++] - 48;
} while (str[readingPos] != 0);
return sign * result;
}
int
ammunition_sprintf_d(char *s, int number) {
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
long long copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
digits++;
copyOfNumber /= 10;
} while (copyOfNumber != 0);
writePos = digits;
if (number < 0) {
writePos++;
s[0] = '-';
}
s[writePos] = 0;
copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
s[--writePos] =
48 + ((copyOfNumber >= 0 ? copyOfNumber : -copyOfNumber) % 10);
copyOfNumber /= 10;
} while (copyOfNumber != 0);
return digits + (number < 0 ? 1 : 0);
}
int
ammunition_sprintf_u(char *s, unsigned int number) {
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
unsigned long long copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
digits++;
copyOfNumber /= 10;
} while (copyOfNumber != 0);
writePos = digits;
s[writePos] = 0;
copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
s[--writePos] = 48 + (copyOfNumber % 10);
copyOfNumber /= 10;
} while (copyOfNumber != 0);
return digits;
}

View File

@ -0,0 +1,36 @@
#ifndef AMMUNITION_LIMITS_H
#define AMMUNITION_LIMITS_H
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#ifndef UCHAR_MAX
#define UCHAR_MAX 255
#endif
#ifndef SCHAR_MAX
#define SCHAR_MAX 127
#endif
#ifndef SCHAR_MIN
#define SCHAR_MIN (-128)
#endif
#ifndef USHRT_MAX
#define USHRT_MAX 65535
#endif
#ifndef SHRT_MAX
#define SHRT_MAX 32767
#endif
#ifndef SHRT_MIN
#define SHRT_MIN (-32768)
#endif
#ifndef UINT_MAX
#define UINT_MAX (INT_MAX * 2U + 1)
#endif
#ifndef INT_MAX
#define INT_MAX 2147483647
#endif
#ifndef INT_MIN
#define INT_MIN (-INT_MAX - 1)
#endif
#endif /* #ifndef AMMUNITION_LIMITS_H */

View File

@ -0,0 +1,9 @@
#ifndef AMMUNITION_STDIO_H
#define AMMUNITION_STDIO_H
int ammunition_sprintf_d(char *s, int number);
int ammunition_sprintf_u(char *s, unsigned int number);
#endif

View File

@ -0,0 +1,7 @@
#ifndef AMMUNITION_STDLIB_H
#define AMMUNITION_STDLIB_H
int ammunition_atoi(const char *str);
#endif

View File

@ -0,0 +1,17 @@
#ifndef AMMUNITION_STRING_H
#define AMMUNITION_STRING_H
typedef unsigned int size_t;
/*
Forward declaration of functions
*/
void *ammunition_memcpy(void *, const void *, size_t);
void *ammunition_memset(void *, int, size_t);
int ammunition_memcmp(const void *mem1, const void *mem2, size_t size);
void *ammunition_memmove(void *s1, const void *s2, size_t n);
int ammunition_strcmp(const char *str1, const char *str2);
#endif /* AMMUNITION_STRING_H */

View File

@ -0,0 +1,105 @@
/*
FILE NAME: arithm.h
TITLE: Include file of package for arbitrary precision integer
arithmetic
DESCRIPTION: This header file contains ANSI C prototype definitions of
the package functions and definitions of external
variable of the package and C++ classes for arbitrary
precision integer arithmetic.
*/
#ifndef __ARITHMETIC__
#define __ARITHMETIC__
#include "ammunition_limits.h"
/* This page contains definitions of variables and macros common for
all package functions. */
/* The value of macro is suggested to be maximum length of integer operands
The length of use integers should be not greater than this value. */
#define MAX_INTEGER_OPERAND_SIZE 128
/* The following macro value is sign of integer number (0 or 1) given
as macro parameter. */
#define INTEGER_SIGN(operand) (*(unsigned char *) (operand) >> (CHAR_BIT - 1))
extern int ammunition_overflow_bit;
void ammunition_add_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_add_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_subtract_unsigned_integer(int size, const void *op1,
const void *op2, void *result);
void ammunition_subtract_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_multiply_unsigned_integer(int size, const void *op1,
const void *op2, void *result);
void ammunition_multiply_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_divide_unsigned_integer(int size, const void *op1,
const void *op2, void *result);
void ammunition_divide_integer(int size, const void *op1, const void *op2,
void *result);
void ammunition_unsigned_integer_remainder(int size, const void *op1,
const void *op2, void *result);
void ammunition_unsigned_integer_shift_right(int size, const void *operand,
int bits, void *result);
void ammunition_integer_shift_right(int size, const void *operand, int bits,
void *result);
void ammunition_integer_shift_left(int size, const void *operand, int bits,
void *result);
void ammunition_unsigned_integer_shift_left(int size, const void *operand,
int bits, void *result);
void ammunition_integer_or(int size, const void *op1, const void *op2,
void *result);
void ammunition_unsigned_integer_or(int size, const void *op1, const void *op2,
void *result);
void ammunition_integer_and(int size, const void *op1, const void *op2,
void *result);
void ammunition_unsigned_integer_and(int size, const void *op1, const void *op2,
void *result);
void ammunition_integer_not(int size, const void *operand, void *result);
void ammunition_unsigned_integer_not(int size, const void *operand,
void *result);
int ammunition_eq_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_eq_integer(int size, const void *op1, const void *op2);
int ammunition_ne_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_ne_integer(int size, const void *op1, const void *op2);
int ammunition_gt_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_gt_integer(int size, const void *op1, const void *op2);
int ammunition_lt_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_lt_integer(int size, const void *op1, const void *op2);
int ammunition_ge_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_ge_integer(int size, const void *op1, const void *op2);
int ammunition_le_unsigned_integer(int size, const void *op1, const void *op2);
int ammunition_le_integer(int size, const void *op1, const void *op2);
void ammunition_change_unsigned_integer_size(int operand_size,
const void *operand,
int result_size, void *result);
void ammunition_change_integer_size(int operand_size, const void *operand,
int result_size, void *result);
char *ammunition_unsigned_integer_to_string(int size, const void *operand,
char *result);
char *ammunition_integer_to_string(int size, const void *operand, char *result);
char *ammunition_unsigned_integer_from_string(int size, const char *operand,
void *result);
char *ammunition_integer_from_string(int size, const char *operand,
void *result);
char ammunition_isdigit(unsigned char c);
int ammunition_isspace(int c);
#endif /* #ifndef __ARITHMETIC__ */

View File

@ -0,0 +1,305 @@
/*
FILE NAME: bits.c
TITLE: Package for work with bits
DESCRIPTION: This file implements functions of the package for work
with bit strings. A bit is given by address (start address) of
byte from which counting bits starts and its displacement which
is any non negative number of bit from the start address. The
most significant bit of the start address byte has number 0.
The bit string is given by its first bit and its length in
bits.
*/
#include "bits.h"
/* This function determines that given bit string contains only zero
bits. The function retruns TRUE if all bits of given bit string
are zero or `bit_length' <= 0. Value of `bit_displacement' must be
non-negative and can be greater than CHAR_BIT. */
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
int
ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
int bit_length) {
const unsigned char *current_byte = (unsigned const char *) start_byte;
if (bit_length <= 0)
return 1 /* TRUE */;
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if (bit_length < CHAR_BIT - bit_displacement)
return (((*current_byte << bit_displacement) &
(UCHAR_MAX << (CHAR_BIT - bit_length))) &
UCHAR_MAX) == 0;
else if (bit_displacement != 0) {
if (((*current_byte << bit_displacement) & UCHAR_MAX) != 0)
return 0 /* FALSE */;
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
__pragma_loopbound(0, 7);
while (bit_length >= CHAR_BIT) {
if (*current_byte != 0)
return 0 /* FALSE */;
current_byte++;
bit_length -= CHAR_BIT;
}
if (bit_length > 0 && (*current_byte >> (CHAR_BIT - bit_length)) != 0)
return 0 /* FALSE */;
return 1 /* TRUE */;
}
/* This function sets up new value of all bits of given bit string.
This function is analog of standard C function `memset'. Value of
`bit_displacement' must be non-negative and can be greater than
CHAR_BIT. */
void
ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
int bit_length) {
unsigned char *current_byte = (unsigned char *) start_byte;
unsigned char filling_byte;
int mask;
if (bit_length <= 0)
return;
bit = bit != 0; /* 1 or 0 */
filling_byte = (bit ? UCHAR_MAX : 0);
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if (bit_displacement != 0) {
mask = UCHAR_MAX << (CHAR_BIT - bit_displacement);
if (bit_length < CHAR_BIT - bit_displacement)
mask |= UCHAR_MAX >> (bit_displacement + bit_length);
*current_byte = (*current_byte & mask) | (filling_byte & ~mask);
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
__pragma_loopbound(0, 8);
while (bit_length >= CHAR_BIT) {
*current_byte = filling_byte;
current_byte++;
bit_length -= CHAR_BIT;
}
if (bit_length > 0)
*current_byte =
(*current_byte & ~(UCHAR_MAX << (CHAR_BIT - bit_length))) |
(filling_byte & (UCHAR_MAX << (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string. This
function is analog of standard C function `memcpy'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
void
ammunition_bit_string_copy(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
int byte;
int mask;
if (bit_length <= 0)
return;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
__pragma_loopbound(0, 7);
while (1) {
byte =
(((*current_from_byte << from_bit_displacement) & UCHAR_MAX) |
(from_bit_displacement != 0 &&
bit_length > (CHAR_BIT - from_bit_displacement)
? current_from_byte[1] >> (CHAR_BIT - from_bit_displacement)
: 0));
if (bit_length <= CHAR_BIT)
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte = (*current_to_byte &
(UCHAR_MAX << (CHAR_BIT - to_bit_displacement))) |
(byte >> to_bit_displacement);
if (to_bit_displacement != 0)
current_to_byte[1] =
(current_to_byte[1] & (UCHAR_MAX >> to_bit_displacement)) |
(byte << (CHAR_BIT - to_bit_displacement));
bit_length -= CHAR_BIT;
current_from_byte++;
current_to_byte++;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ((UCHAR_MAX << (CHAR_BIT - to_bit_displacement)) |
(UCHAR_MAX >> (to_bit_displacement + bit_length)));
*current_to_byte =
(*current_to_byte & mask) | ((byte >> to_bit_displacement) & ~mask);
bit_length -= CHAR_BIT - to_bit_displacement;
if (bit_length > 0)
current_to_byte[1] = (current_to_byte[1] & (UCHAR_MAX >> bit_length)) |
((byte << (CHAR_BIT - to_bit_displacement)) &
(UCHAR_MAX << (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string. Copying
starts with the last bits of the bit strings. This function is
used by function `bit_string_move'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
void
ammunition_reverse_bit_string_copy(void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
int byte;
int mask;
if (bit_length <= 0)
return;
to_bit_displacement += bit_length - 1;
current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */
to_bit_displacement %= CHAR_BIT; /* last bit */
from_bit_displacement += bit_length - 1;
current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */
from_bit_displacement %= CHAR_BIT; /* last bit */
__pragma_loopbound(0, 7);
while (1) {
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
byte = ((*current_from_byte >> (CHAR_BIT - 1 - from_bit_displacement)) |
((from_bit_displacement != CHAR_BIT - 1 &&
bit_length > from_bit_displacement + 1
? current_from_byte[-1] << (from_bit_displacement + 1)
: 0) &
UCHAR_MAX));
if (bit_length <= CHAR_BIT)
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte =
(*current_to_byte & (UCHAR_MAX >> (to_bit_displacement + 1))) |
(byte << (CHAR_BIT - 1 - to_bit_displacement));
if (to_bit_displacement != CHAR_BIT - 1)
current_to_byte[-1] =
(current_to_byte[-1] &
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement))) |
(byte >> (to_bit_displacement + 1));
bit_length -= CHAR_BIT;
current_from_byte--;
current_to_byte--;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ((UCHAR_MAX >> (to_bit_displacement + 1)) |
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement + bit_length)));
*current_to_byte = (*current_to_byte & mask) |
((byte << (CHAR_BIT - 1 - to_bit_displacement)) & ~mask);
bit_length -= to_bit_displacement + 1;
if (bit_length > 0)
current_to_byte[-1] =
(current_to_byte[-1] & (UCHAR_MAX << bit_length)) |
(byte >> (to_bit_displacement + 1) &
(UCHAR_MAX >> (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string with the aid
of functions `bit_string_copy' and `reverse_bit_string_copy'. This
function is analog of standard C function `memmove'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string can
be overlapped. */
void
ammunition_bit_string_move(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
if (bit_length <= 0)
return;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
if (current_from_byte > current_to_byte ||
(current_from_byte == current_to_byte &&
from_bit_displacement > to_bit_displacement))
ammunition_bit_string_copy(current_to_byte, to_bit_displacement,
current_from_byte, from_bit_displacement,
bit_length);
else
ammunition_reverse_bit_string_copy(current_to_byte, to_bit_displacement,
current_from_byte,
from_bit_displacement, bit_length);
}
/* This function compares bit strings. This function is analog of
standard C function `memcmp'. The function returns 0 if the bit
strings are equal, 1 if the first bit string is greater than the
second, -1 if the first bit string is less than the first. Values
of `bit_displacement1' and `bit_displacement2' must be non-negative
and can be greater than CHAR_BIT. */
int
ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length) {
const unsigned char *current_byte1 = (unsigned const char *) str1;
const unsigned char *current_byte2 = (unsigned const char *) str2;
int byte1;
int byte2;
int mask;
if (bit_length <= 0)
return 0;
current_byte1 += bit_displacement1 / CHAR_BIT;
bit_displacement1 %= CHAR_BIT;
current_byte2 += bit_displacement2 / CHAR_BIT;
bit_displacement2 %= CHAR_BIT;
__pragma_loopbound(0, 7);
while (1) {
byte1 = (((*current_byte1 << bit_displacement1) & UCHAR_MAX) |
(bit_displacement1 != 0
/* Shift is correct when to_bit_displacement == 0
because its value is less than word bit size. */
&& bit_length > CHAR_BIT - bit_displacement1
? current_byte1[1] >> (CHAR_BIT - bit_displacement1)
: 0));
byte2 = (((*current_byte2 << bit_displacement2) & UCHAR_MAX) |
(bit_displacement2 != 0 &&
bit_length > CHAR_BIT - bit_displacement2
? current_byte2[1] >> (CHAR_BIT - bit_displacement2)
: 0));
if (bit_length <= CHAR_BIT)
break;
if (byte1 > byte2)
return 1;
else if (byte1 < byte2)
return -1;
bit_length -= CHAR_BIT;
current_byte2++;
current_byte1++;
}
/* Shift is correct when to_bit_displacement == 0 because its value
is less than word bit size. */
mask = UCHAR_MAX << (CHAR_BIT - bit_length);
if ((byte1 & mask) > (byte2 & mask))
return 1;
else if ((byte1 & mask) < (byte2 & mask))
return -1;
else
return 0;
}

View File

@ -0,0 +1,58 @@
/*
FILE NAME: bits.h
TITLE: Include file of package for work with bits
DESCRIPTION:
This is header file contains macros and the ANSI C prototype
definitions for the package for work with bits and bit strings
and C++ class for work with bits and bit strings. A bit is
given by address (start address) of byte from which counting
bits starts and its displacement which is any non negative
number of bit from the start address. The most significant bit
of the start address byte has number 0. The bit string is
given by its first bit and its length in bits.
*/
#ifndef __BITS__
#define __BITS__
#include "ammunition_limits.h"
/* This macro value returns bit vlaue (0 or 1) with given bit
displacement (0, 1, ...). The macro has side effects! Value of
`bit_displacement' must be nonegative and can be greater than
CHAR_BIT. */
#define BIT(start_byte, bit_displacement) \
((((const char *) (start_byte))[(bit_displacement) / CHAR_BIT] >> \
(CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)) & \
1)
/* This macro value sets up new value (must be `0' or `1') of a given
bit (bit displacement starts with 0). The macro has side effects!
Value of `bit_displacement' must be nonegative and can be greater
than CHAR_BIT. */
#define SET_BIT(start_byte, bit_displacement, bit) \
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] = \
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] & \
~(1 << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT))) | \
((bit) << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))
int ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
int bit_length);
void ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
int bit_length);
void ammunition_bit_string_copy(void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length);
void ammunition_bit_string_move(void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length);
int ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length);
#endif /* #ifndef __BITS__ */

View File

@ -0,0 +1,164 @@
/*
Include section
*/
#include "ammunition_stdio.h"
#include "ammunition_stdlib.h"
#include "ammunition_string.h"
/*
Standard library functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline char
ammunition_isdigit(unsigned char c) {
if ((c >= '0') & (c <= '9'))
return 1;
else
return 0;
}
__attribute__((always_inline)) static inline int
ammunition_isspace(int c) {
return (c == ' ') | (c == '\t') | (c == '\n') | (c == '\r');
}
__attribute__((always_inline)) static inline void *
ammunition_memcpy(void *dest, const void *src, size_t size) {
size_t i;
__pragma_loopbound(2, 6);
for (i = 0; i < size; i++)
((unsigned char *) dest)[i] = ((unsigned char *) src)[i];
return dest;
}
__attribute__((always_inline)) static inline void *
ammunition_memset(void *s, int c, size_t n) {
size_t i;
__pragma_loopbound(0, 4);
for (i = 0; i < n; i++)
((unsigned char *) s)[i] = (unsigned char) c;
return s;
}
__attribute__((always_inline)) static inline int
ammunition_memcmp(const void *mem1, const void *mem2, size_t size) {
const unsigned char *p1 = (const unsigned char *) mem1,
*p2 = (const unsigned char *) mem2;
__pragma_loopbound(0, 4);
while (size--)
if (*p1 != *p2)
return (*p1 - *p2);
else
p1++, p2++;
return 0;
}
/* The following function is an analog of standard C function
`memmove'. The function returns the first operand. */
__attribute__((always_inline)) static inline void *
ammunition_memmove(void *s1, const void *s2, size_t n) {
int i;
if (((char *) s1 < (char *) s2 && (char *) s1 + n <= (char *) s2) ||
((char *) s2 < (char *) s1 && (char *) s2 + n <= (char *) s1))
return (void *) ammunition_memcpy(s1, s2, n);
if ((char *) s1 < (char *) s2 && (char *) s1 + n > (char *) s2) {
__pragma_loopbound(0, 4);
for (i = 0; (size_t) i < n; i++)
((char *) s1)[i] = ((char *) s2)[i];
} else {
__pragma_loopbound(0, 4);
for (i = n - 1; i >= 0; i--)
((char *) s1)[i] = ((char *) s2)[i];
}
return s1;
}
__attribute__((always_inline)) static inline int
ammunition_strcmp(const char *str1, const char *str2) {
__pragma_loopbound(1, 11);
while (*str1 && (*str1 == *str2))
str1++, str2++;
return *(const unsigned char *) str1 - *(const unsigned char *) str2;
}
__attribute__((always_inline)) static inline int
ammunition_atoi(const char *str) {
int result = 0;
int sign = (str[0] == '-' ? -1 : 1);
int readingPos = 0;
if (str[0] == '-' || str[0] == '+')
readingPos++;
__pragma_loopbound(1, 7);
do {
result *= 10;
result += str[readingPos++] - 48;
} while (str[readingPos] != 0);
return sign * result;
}
__attribute__((always_inline)) static inline int
ammunition_sprintf_d(char *s, int number) {
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
long long copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
digits++;
copyOfNumber /= 10;
} while (copyOfNumber != 0);
writePos = digits;
if (number < 0) {
writePos++;
s[0] = '-';
}
s[writePos] = 0;
copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
s[--writePos] =
48 + ((copyOfNumber >= 0 ? copyOfNumber : -copyOfNumber) % 10);
copyOfNumber /= 10;
} while (copyOfNumber != 0);
return digits + (number < 0 ? 1 : 0);
}
__attribute__((always_inline)) static inline int
ammunition_sprintf_u(char *s, unsigned int number) {
/* How many decimal digits do we need? */
char digits = 0;
unsigned char writePos = 0;
unsigned long long copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
digits++;
copyOfNumber /= 10;
} while (copyOfNumber != 0);
writePos = digits;
s[writePos] = 0;
copyOfNumber = number;
__pragma_loopbound(1, 10);
do {
s[--writePos] = 48 + (copyOfNumber % 10);
copyOfNumber /= 10;
} while (copyOfNumber != 0);
return digits;
}

View File

@ -0,0 +1,36 @@
#ifndef AMMUNITION_LIMITS_H
#define AMMUNITION_LIMITS_H
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
#ifndef UCHAR_MAX
#define UCHAR_MAX 255
#endif
#ifndef SCHAR_MAX
#define SCHAR_MAX 127
#endif
#ifndef SCHAR_MIN
#define SCHAR_MIN (-128)
#endif
#ifndef USHRT_MAX
#define USHRT_MAX 65535
#endif
#ifndef SHRT_MAX
#define SHRT_MAX 32767
#endif
#ifndef SHRT_MIN
#define SHRT_MIN (-32768)
#endif
#ifndef UINT_MAX
#define UINT_MAX (INT_MAX * 2U + 1)
#endif
#ifndef INT_MAX
#define INT_MAX 2147483647
#endif
#ifndef INT_MIN
#define INT_MIN (-INT_MAX - 1)
#endif
#endif /* #ifndef AMMUNITION_LIMITS_H */

View File

@ -0,0 +1,11 @@
#ifndef AMMUNITION_STDIO_H
#define AMMUNITION_STDIO_H
__attribute__((always_inline)) static inline int
ammunition_sprintf_d(char *s, int number);
__attribute__((always_inline)) static inline int
ammunition_sprintf_u(char *s, unsigned int number);
#endif

View File

@ -0,0 +1,8 @@
#ifndef AMMUNITION_STDLIB_H
#define AMMUNITION_STDLIB_H
__attribute__((always_inline)) static inline int
ammunition_atoi(const char *str);
#endif

View File

@ -0,0 +1,22 @@
#ifndef AMMUNITION_STRING_H
#define AMMUNITION_STRING_H
typedef unsigned int size_t;
/*
Forward declaration of functions
*/
__attribute__((always_inline)) static inline void *
ammunition_memcpy(void *, const void *, size_t);
__attribute__((always_inline)) static inline void *
ammunition_memset(void *, int, size_t);
__attribute__((always_inline)) static inline int
ammunition_memcmp(const void *mem1, const void *mem2, size_t size);
__attribute__((always_inline)) static inline void *
ammunition_memmove(void *s1, const void *s2, size_t n);
__attribute__((always_inline)) static inline int
ammunition_strcmp(const char *str1, const char *str2);
#endif /* AMMUNITION_STRING_H */

View File

@ -0,0 +1,139 @@
/*
FILE NAME: arithm.h
TITLE: Include file of package for arbitrary precision integer
arithmetic
DESCRIPTION: This header file contains ANSI C prototype definitions of
the package functions and definitions of external
variable of the package and C++ classes for arbitrary
precision integer arithmetic.
*/
#ifndef __ARITHMETIC__
#define __ARITHMETIC__
#include "ammunition_limits.h"
/* This page contains definitions of variables and macros common for
all package functions. */
/* The value of macro is suggested to be maximum length of integer operands
The length of use integers should be not greater than this value. */
#define MAX_INTEGER_OPERAND_SIZE 128
/* The following macro value is sign of integer number (0 or 1) given
as macro parameter. */
#define INTEGER_SIGN(operand) (*(unsigned char *) (operand) >> (CHAR_BIT - 1))
extern int ammunition_overflow_bit;
__attribute__((always_inline)) static inline void
ammunition_add_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_add_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_subtract_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_subtract_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_multiply_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_multiply_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_divide_unsigned_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_divide_integer(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_remainder(int size, const void *op1,
const void *op2, void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_shift_right(int size, const void *operand, int bits,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_shift_right(int size, const void *operand, int bits,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_shift_left(int size, const void *operand, int bits,
void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_shift_left(int size, const void *operand, int bits,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_or(int size, const void *op1, const void *op2, void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_or(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_and(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_and(int size, const void *op1, const void *op2,
void *result);
__attribute__((always_inline)) static inline void
ammunition_integer_not(int size, const void *operand, void *result);
__attribute__((always_inline)) static inline void
ammunition_unsigned_integer_not(int size, const void *operand, void *result);
__attribute__((always_inline)) static inline int
ammunition_eq_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_eq_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_ne_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_ne_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_gt_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_gt_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_lt_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_lt_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_ge_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_ge_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_le_unsigned_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline int
ammunition_le_integer(int size, const void *op1, const void *op2);
__attribute__((always_inline)) static inline void
ammunition_change_unsigned_integer_size(int operand_size, const void *operand,
int result_size, void *result);
__attribute__((always_inline)) static inline void
ammunition_change_integer_size(int operand_size, const void *operand,
int result_size, void *result);
__attribute__((always_inline)) static inline char *
ammunition_unsigned_integer_to_string(int size, const void *operand,
char *result);
__attribute__((always_inline)) static inline char *
ammunition_integer_to_string(int size, const void *operand, char *result);
__attribute__((always_inline)) static inline char *
ammunition_unsigned_integer_from_string(int size, const char *operand,
void *result);
__attribute__((always_inline)) static inline char *
ammunition_integer_from_string(int size, const char *operand, void *result);
__attribute__((always_inline)) static inline char
ammunition_isdigit(unsigned char c);
__attribute__((always_inline)) static inline int ammunition_isspace(int c);
#endif /* #ifndef __ARITHMETIC__ */

View File

@ -0,0 +1,305 @@
/*
FILE NAME: bits.c
TITLE: Package for work with bits
DESCRIPTION: This file implements functions of the package for work
with bit strings. A bit is given by address (start address) of
byte from which counting bits starts and its displacement which
is any non negative number of bit from the start address. The
most significant bit of the start address byte has number 0.
The bit string is given by its first bit and its length in
bits.
*/
#include "bits.h"
/* This function determines that given bit string contains only zero
bits. The function retruns TRUE if all bits of given bit string
are zero or `bit_length' <= 0. Value of `bit_displacement' must be
non-negative and can be greater than CHAR_BIT. */
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline int
ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
int bit_length) {
const unsigned char *current_byte = (unsigned const char *) start_byte;
if (bit_length <= 0)
return 1 /* TRUE */;
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if (bit_length < CHAR_BIT - bit_displacement)
return (((*current_byte << bit_displacement) &
(UCHAR_MAX << (CHAR_BIT - bit_length))) &
UCHAR_MAX) == 0;
else if (bit_displacement != 0) {
if (((*current_byte << bit_displacement) & UCHAR_MAX) != 0)
return 0 /* FALSE */;
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
__pragma_loopbound(0, 7);
while (bit_length >= CHAR_BIT) {
if (*current_byte != 0)
return 0 /* FALSE */;
current_byte++;
bit_length -= CHAR_BIT;
}
if (bit_length > 0 && (*current_byte >> (CHAR_BIT - bit_length)) != 0)
return 0 /* FALSE */;
return 1 /* TRUE */;
}
/* This function sets up new value of all bits of given bit string.
This function is analog of standard C function `memset'. Value of
`bit_displacement' must be non-negative and can be greater than
CHAR_BIT. */
__attribute__((always_inline)) static inline void
ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
int bit_length) {
unsigned char *current_byte = (unsigned char *) start_byte;
unsigned char filling_byte;
int mask;
if (bit_length <= 0)
return;
bit = bit != 0; /* 1 or 0 */
filling_byte = (bit ? UCHAR_MAX : 0);
current_byte += bit_displacement / CHAR_BIT;
bit_displacement %= CHAR_BIT;
if (bit_displacement != 0) {
mask = UCHAR_MAX << (CHAR_BIT - bit_displacement);
if (bit_length < CHAR_BIT - bit_displacement)
mask |= UCHAR_MAX >> (bit_displacement + bit_length);
*current_byte = (*current_byte & mask) | (filling_byte & ~mask);
current_byte += 1;
bit_length -= CHAR_BIT - bit_displacement;
}
__pragma_loopbound(0, 8);
while (bit_length >= CHAR_BIT) {
*current_byte = filling_byte;
current_byte++;
bit_length -= CHAR_BIT;
}
if (bit_length > 0)
*current_byte =
(*current_byte & ~(UCHAR_MAX << (CHAR_BIT - bit_length))) |
(filling_byte & (UCHAR_MAX << (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string. This
function is analog of standard C function `memcpy'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
__attribute__((always_inline)) static inline void
ammunition_bit_string_copy(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
int byte;
int mask;
if (bit_length <= 0)
return;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
__pragma_loopbound(0, 7);
while (1) {
byte =
(((*current_from_byte << from_bit_displacement) & UCHAR_MAX) |
(from_bit_displacement != 0 &&
bit_length > (CHAR_BIT - from_bit_displacement)
? current_from_byte[1] >> (CHAR_BIT - from_bit_displacement)
: 0));
if (bit_length <= CHAR_BIT)
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte = (*current_to_byte &
(UCHAR_MAX << (CHAR_BIT - to_bit_displacement))) |
(byte >> to_bit_displacement);
if (to_bit_displacement != 0)
current_to_byte[1] =
(current_to_byte[1] & (UCHAR_MAX >> to_bit_displacement)) |
(byte << (CHAR_BIT - to_bit_displacement));
bit_length -= CHAR_BIT;
current_from_byte++;
current_to_byte++;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ((UCHAR_MAX << (CHAR_BIT - to_bit_displacement)) |
(UCHAR_MAX >> (to_bit_displacement + bit_length)));
*current_to_byte =
(*current_to_byte & mask) | ((byte >> to_bit_displacement) & ~mask);
bit_length -= CHAR_BIT - to_bit_displacement;
if (bit_length > 0)
current_to_byte[1] = (current_to_byte[1] & (UCHAR_MAX >> bit_length)) |
((byte << (CHAR_BIT - to_bit_displacement)) &
(UCHAR_MAX << (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string. Copying
starts with the last bits of the bit strings. This function is
used by function `bit_string_move'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string must
be non-overlapped. */
__attribute__((always_inline)) static inline void
ammunition_reverse_bit_string_copy(void *to, int to_bit_displacement,
const void *from, int from_bit_displacement,
int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
int byte;
int mask;
if (bit_length <= 0)
return;
to_bit_displacement += bit_length - 1;
current_to_byte += to_bit_displacement / CHAR_BIT; /* last byte */
to_bit_displacement %= CHAR_BIT; /* last bit */
from_bit_displacement += bit_length - 1;
current_from_byte += from_bit_displacement / CHAR_BIT; /* last byte */
from_bit_displacement %= CHAR_BIT; /* last bit */
__pragma_loopbound(0, 7);
while (1) {
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
byte = ((*current_from_byte >> (CHAR_BIT - 1 - from_bit_displacement)) |
((from_bit_displacement != CHAR_BIT - 1 &&
bit_length > from_bit_displacement + 1
? current_from_byte[-1] << (from_bit_displacement + 1)
: 0) &
UCHAR_MAX));
if (bit_length <= CHAR_BIT)
break;
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
*current_to_byte =
(*current_to_byte & (UCHAR_MAX >> (to_bit_displacement + 1))) |
(byte << (CHAR_BIT - 1 - to_bit_displacement));
if (to_bit_displacement != CHAR_BIT - 1)
current_to_byte[-1] =
(current_to_byte[-1] &
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement))) |
(byte >> (to_bit_displacement + 1));
bit_length -= CHAR_BIT;
current_from_byte--;
current_to_byte--;
}
/* Shift is correct when to_bit_displacement == 0 because its
value is less than word bit size. */
mask = ((UCHAR_MAX >> (to_bit_displacement + 1)) |
(UCHAR_MAX << (CHAR_BIT - 1 - to_bit_displacement + bit_length)));
*current_to_byte = (*current_to_byte & mask) |
((byte << (CHAR_BIT - 1 - to_bit_displacement)) & ~mask);
bit_length -= to_bit_displacement + 1;
if (bit_length > 0)
current_to_byte[-1] =
(current_to_byte[-1] & (UCHAR_MAX << bit_length)) |
(byte >> (to_bit_displacement + 1) &
(UCHAR_MAX >> (CHAR_BIT - bit_length)));
}
/* This function copys a bit string to another bit string with the aid
of functions `bit_string_copy' and `reverse_bit_string_copy'. This
function is analog of standard C function `memmove'. Values of
`to_bit_displacement' and `from_bit_displacement' must be
non-negative and can be greater than CHAR_BIT. The bit string can
be overlapped. */
__attribute__((always_inline)) static inline void
ammunition_bit_string_move(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length) {
unsigned char *current_to_byte = (unsigned char *) to;
const unsigned char *current_from_byte = (unsigned const char *) from;
if (bit_length <= 0)
return;
current_to_byte += to_bit_displacement / CHAR_BIT;
to_bit_displacement %= CHAR_BIT;
current_from_byte += from_bit_displacement / CHAR_BIT;
from_bit_displacement %= CHAR_BIT;
if (current_from_byte > current_to_byte ||
(current_from_byte == current_to_byte &&
from_bit_displacement > to_bit_displacement))
ammunition_bit_string_copy(current_to_byte, to_bit_displacement,
current_from_byte, from_bit_displacement,
bit_length);
else
ammunition_reverse_bit_string_copy(current_to_byte, to_bit_displacement,
current_from_byte,
from_bit_displacement, bit_length);
}
/* This function compares bit strings. This function is analog of
standard C function `memcmp'. The function returns 0 if the bit
strings are equal, 1 if the first bit string is greater than the
second, -1 if the first bit string is less than the first. Values
of `bit_displacement1' and `bit_displacement2' must be non-negative
and can be greater than CHAR_BIT. */
__attribute__((always_inline)) static inline int
ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length) {
const unsigned char *current_byte1 = (unsigned const char *) str1;
const unsigned char *current_byte2 = (unsigned const char *) str2;
int byte1;
int byte2;
int mask;
if (bit_length <= 0)
return 0;
current_byte1 += bit_displacement1 / CHAR_BIT;
bit_displacement1 %= CHAR_BIT;
current_byte2 += bit_displacement2 / CHAR_BIT;
bit_displacement2 %= CHAR_BIT;
__pragma_loopbound(0, 7);
while (1) {
byte1 = (((*current_byte1 << bit_displacement1) & UCHAR_MAX) |
(bit_displacement1 != 0
/* Shift is correct when to_bit_displacement == 0
because its value is less than word bit size. */
&& bit_length > CHAR_BIT - bit_displacement1
? current_byte1[1] >> (CHAR_BIT - bit_displacement1)
: 0));
byte2 = (((*current_byte2 << bit_displacement2) & UCHAR_MAX) |
(bit_displacement2 != 0 &&
bit_length > CHAR_BIT - bit_displacement2
? current_byte2[1] >> (CHAR_BIT - bit_displacement2)
: 0));
if (bit_length <= CHAR_BIT)
break;
if (byte1 > byte2)
return 1;
else if (byte1 < byte2)
return -1;
bit_length -= CHAR_BIT;
current_byte2++;
current_byte1++;
}
/* Shift is correct when to_bit_displacement == 0 because its value
is less than word bit size. */
mask = UCHAR_MAX << (CHAR_BIT - bit_length);
if ((byte1 & mask) > (byte2 & mask))
return 1;
else if ((byte1 & mask) < (byte2 & mask))
return -1;
else
return 0;
}

View File

@ -0,0 +1,61 @@
/*
FILE NAME: bits.h
TITLE: Include file of package for work with bits
DESCRIPTION:
This is header file contains macros and the ANSI C prototype
definitions for the package for work with bits and bit strings
and C++ class for work with bits and bit strings. A bit is
given by address (start address) of byte from which counting
bits starts and its displacement which is any non negative
number of bit from the start address. The most significant bit
of the start address byte has number 0. The bit string is
given by its first bit and its length in bits.
*/
#ifndef __BITS__
#define __BITS__
#include "ammunition_limits.h"
/* This macro value returns bit vlaue (0 or 1) with given bit
displacement (0, 1, ...). The macro has side effects! Value of
`bit_displacement' must be nonegative and can be greater than
CHAR_BIT. */
#define BIT(start_byte, bit_displacement) \
((((const char *) (start_byte))[(bit_displacement) / CHAR_BIT] >> \
(CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)) & \
1)
/* This macro value sets up new value (must be `0' or `1') of a given
bit (bit displacement starts with 0). The macro has side effects!
Value of `bit_displacement' must be nonegative and can be greater
than CHAR_BIT. */
#define SET_BIT(start_byte, bit_displacement, bit) \
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] = \
(((char *) (start_byte))[(bit_displacement) / CHAR_BIT] & \
~(1 << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT))) | \
((bit) << (CHAR_BIT - 1 - (bit_displacement) % CHAR_BIT)))
__attribute__((always_inline)) static inline int
ammunition_is_zero_bit_string(const void *start_byte, int bit_displacement,
int bit_length);
__attribute__((always_inline)) static inline void
ammunition_bit_string_set(void *start_byte, int bit_displacement, int bit,
int bit_length);
__attribute__((always_inline)) static inline void
ammunition_bit_string_copy(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length);
__attribute__((always_inline)) static inline void
ammunition_bit_string_move(void *to, int to_bit_displacement, const void *from,
int from_bit_displacement, int bit_length);
__attribute__((always_inline)) static inline int
ammunition_bit_string_comparison(const void *str1, int bit_displacement1,
const void *str2, int bit_displacement2,
int bit_length);
#endif /* #ifndef __BITS__ */

View File

@ -0,0 +1,27 @@
# ~~~
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2026, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
# ~~~
cmake_minimum_required(VERSION 3.20)
project(anagram)
set(TACLEBENCH_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../..")
set(REPOSITORY_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../..")
set(APP_TARGET_NAME "${CMAKE_PROJECT_NAME}")
if(DEFINED TACLEBENCH_VARIANT AND "${TACLEBENCH_VARIANT}" STREQUAL "inline")
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/inline/anagram.c")
else()
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/default/anagram.c"
"generated/modified_sources/default/anagram_input.c"
"generated/modified_sources/default/anagram_stdlib.c")
endif()
include(${REPOSITORY_ROOT_PATH}/cmake/taclebench_wasm.cmake)

View File

@ -0,0 +1,125 @@
File: anagram.c
Original provenience: unknown
Source: unknown
2017-04-18:
- Annotated anagram_main as entry-point for timing analysis
2016-06-22:
- Fixed type signature of function anagram_main to conform to TACLeBench
standard, i.e. `void anagram_main (void)`.
2016-05-24:
- Changed type of global variables anagram_achPhrase and
anagram_dictionary to `char const *[]`.
- Changed parameter type of function anagram_BuildMask to
`char const *`.
2016-04-26:
- Fixed array out-of-bounds access introduced by earlier change.
2016-04-20:
- Fixed some compiler warnings.
- Return value of anagram_return depends on the computation inside
of anagram_main.
2016-03-22
- Added forward declarations for all functions.
- Renamed function main to anagram_main.
- Added function anagram_init that calls anagram_ReadDict, removed
call to anagram_ReadDict from anagram_main.
- Added function anagram_return that handles the return value.
- Added new function main that first calls anagram_init,
then anagram_main and finally returns the return value of
anagram_return.
- Added generic TACLeBench header to all files.
- Introduced comments to split file in sections for type
definitions, forward declarations, global variables,
initialization-related and return-value-related functions,
core benchmark functions, and main routine.
- Renamed ch2i, DICTWORDS, Quad, MASK_BITS, MAX_QUADS, MAXCAND,
MAXSOL, ALPHABET, Word, PWord, PPWord, apwCand, cpwCand, Letter,
PLetter, alPhrase, cchPhraseLength, aqMainMask, aqMainSign,
cchMinLength, auGlobalFrequency, achByFrequency, pchDictionary,
Reset, ReadDict, BuildMask, NewWord, NextWord, BuildWord,
AddWords, apwSol, cpwLast, OneStep, DumpWords, FindAnagram and
SortCandidates to anagram_ch2i, anagram_DICTWORDS, anagram_Quad,
anagram_MASK_BITS, anagram_MAX_QUADS, anagram_MAXCAND,
anagram_MAXSOL, anagram_ALPHABET, anagram_Word, anagram_PWord,
anagram_PPWord, anagram_apwCand, anagram_cpwCand, anagram_Letter,
anagram_PLetter, anagram_alPhrase, anagram_cchPhraseLength,
anagram_aqMainMask, anagram_aqMainSign, anagram_cchMinLength,
anagram_auGlobalFrequency, anagram_achByFrequency,
anagram_pchDictionary, anagram_Reset, anagram_ReadDict,
anagram_BuildMask, anagram_NewWord, anagram_NextWord,
anagram_BuildWord, anagram_AddWords, anagram_apwSol,
anagram_cpwLast, anagram_OneStep, anagram_DumpWords,
anagram_FindAnagram and anagram_SortCandidates.
- Renamed swapi, pivot, qsorts, simulated_heap and freeHeapPos to
anagram_swapi, anagram_pivot, anagram_qsorts,
anagram_simulated_heap and anagram_freeHeapPos.
- Renamed achPhrase and dictionary to anagram_achPhrase and
anagram_dictionary.
- Renamed CompareFrequency to anagram_CompareFrequency.
- Increased simulated heap in anagram_stdlib.c to 18000 bytes to
prevent segmentation fault.
- Changed header guard _WCCMALLOC_H to ANAGRAM_STRINGS_H.
- Renamed wccmalloc, wccbzero to anagram_malloc, anagram_bzero.
- Moved declaration of anagram_malloc to header anagram_stdlib.h.
- Introduced header guard ANAGRAM_CTYPE_H.
- Renamed wccislower, wccisupper, wccisalpha, wcctolower to
anagram_islower, anagram_isupper, anagram_isalpha,
anagram_tolower.
- Removed illegal keyword "inline".
- Changed header guard _WCCSTDLIB_H to ANAGRAM_STDLIB_H.
- Renamed wccqsort to anagram_qsort.
- Fixed compiler warning "no previous extern declaration for
non-static variable" for variables simulated_heap and
freeHeapPos by declaring them static.
- Renamed preprocessor define HEAP_SIZE to ANAGRAM_HEAP_SIZE.
- Fixed compiler warning "no previous prototype for function" by
moving includes to the top of the file.
- Fixed compiler warnings "implicit conversion changes signedness"
and "comparison of integers of different signs" by consistenly
using the type unsigned long in qsort helper functions.
- Moved function CompareFrequency to file anagram.c, added
declaration for it in file anagram_compare.h and included it in
anagram_stdlib.h.
- Fixed compiler warning "no previous extern declaration for
non-static variable" by adding forward declarations.
- Fixed compiler warning "macro is not used" by removing unused
macros MAXWORDS and i2ch.
- Replaced macro ch2i by proper function.
- Fixed compiler warning "array subscript is of type 'char' in
function CompareFrequency.
- Fixed compiler warning "unused variable" by removing variable i
in function Reset.
- Fixed compiler warning "no previous extern declaration for
non-static variable" by making global variables in file
anagram.c static.
- Replaced macro lPhrase by its expansion.
- Fixed compiler warnings "implicit conversion loses integer
precision" and "implicit conversion changes signedness" by
adding explicit casts or using the appropriate type for local
variables.
- Fixed compiler warning "array subscript is of type 'char'" by
changing type of some local variables as well as of global
variable achByFrequency to int.
- Changed all //-style comments to /* */-style comments.
- Moved contents of wccmalloc.c to anagram_stdlib.c.
- Renamed input.c to anagram_input.c.
- Renamed wccctype.h to anagram_ctype.h.
- Renamed wccstdlib.c to anagram_stdlib.c.
- Renamed wccstdlib.h to anagram_stdlib.h.
- Renamed wccmalloc.h to anagram_strings.h.
- Applied TACLeBench formatting rules via
astyle --options=doc/example/astylerc.txt
- Tested conformance to C99 via
clang -fsyntax-only -Weverything -Wno-unknown-pragmas -Wno-padded -pedantic -std=c99
2017-06-27
- Remove static declarations.
2017-07-10:
- Adjust alignment calculation in anagram_malloc to not add padding on already
aligned addresses. This prevents a buffer overflow of anagram_simulated_heap.

View File

@ -0,0 +1,661 @@
/*
This program is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram
Author: Raymond Chen
Function: A program that computes anagrams.
Source: See below.
Original name: anagram
Changes: See ChangeLog.txt
License: See below.
*/
/*
Anagram program by Raymond Chen,
inspired by a similar program by Brian Scearce
This program is Copyright 1991 by Raymond Chen.
(rjc@math.princeton.edu)
This program may be freely distributed provided all alterations
to the original are clearly indicated as such.
*/
/* There are two tricks. First is the Basic Idea:
When the user types in a phrase, the phrase is first preprocessed to
determine how many of each letter appears. A bit field is then constructed
dynamically, such that each field is large enough to hold the next power
of two larger than the number of times the character appears. For example,
if the phrase is hello, world, the bit field would be
00 00 00 000 000 00 00
d e h l o r w
The phrase hello, world, itself would be encoded as
01 01 01 011 010 01 01
d e h l o r w
and the word hollow would be encoded as
00 00 01 010 010 00 01
d e h l o r w
The top bit of each field is set in a special value called the sign.
Here, the sign would be
10 10 10 100 100 10 10
d e h l o r w
The reason for packing the values into a bit field is that the operation
of subtracting out the letters of a word from the current phrase can be
carried out in parallel. for example, subtracting the word hello from
the phrase hello, world, is merely
d e h l o r w
01 01 01 011 010 01 01 (dehllloorw)
- 00 00 01 010 010 00 01 (hlloow)
========================
01 01 00 001 000 01 00 (delr)
Since none of the sign bits is set, the word fits, and we can continue.
Suppose the next word we tried was hood.
d e h l o r w
01 01 00 001 000 01 00 (delr)
- 01 00 01 000 010 00 00 (hood)
========================
00 00 11 000 110 01 00
^ ^
A sign bit is set. (Two, actually.) This means that hood does not
fit in delr, so we skip it and try another word. (Observe that
when a sign bit becomes set, it screws up the values for the letters to
the left of that bit, but that's not important.)
The inner loop of an anagram program is testing to see if a
word fits in the collection of untried letters. Traditional methods
keep an array of 26 integers, which are then compared in turn. This
means that there are 26 comparisons per word.
This method reduces the number of comparisons to MAX_QUAD, typically 2.
Instead of looping through an array, we merely perform the indicated
subtraction and test if any of the sign bits is set.
*/
/* The nuts and bolts:
The dictionary is loaded and preprocessed. The preprocessed dictionary
is a concatenation of copies of the structure:
struct dictword {
char bStructureSize; -- size of this structure
char cLetters; -- number of letters in the word
char achWord[]; -- the word itself (0-terminated)
}
Since this is a variable-sized structure, we keep its size in the structure
itself for rapid stepping through the table.
When a phrase is typed in, it is first preprocessed as described in the
Basic Idea. We then go through the dictionary, testing each word. If
the word fits in our phrase, we build the bit field for its frequency
table and add it to the list of candidates.
*/
/*
The Second Trick:
Before diving into our anagram search, we then tabulate how many times
each letter appears in our list of candidates, and sort the table, with
the rarest letter first.
We then do our anagram search.
Like most anagram programs, this program does a depth-first search.
Although most anagram programs do some sort of heuristics to decide what
order to place words in the list_of_candidates, the search itself proceeds
according to a greedy algorithm. That is, once you find a word that fits,
subtract it and recurse.
This anagram program exercises some restraint and does not march down
every branch that shows itself. Instead, it only goes down branches
that use the rarest unused letter. This helps to find dead ends faster.
FindAnagram(unused_letters, list_of_candidates) {
l = the rarest letter as yet unused
For word in list_of_candidates {
if word does not fit in unused_letters, go on to the next word.
if word does not contain l, defer.
FindAnagram(unused_letters - word, list_of_candidates[word,...])
}
}
The heuristic of the Second Trick can probably be improved. I invite
anyone willing to improve it to do so.
*/
/* Before compiling, make sure Quad and MASK_BITS are set properly. For best
results, make Quad the largest integer size supported on your machine.
So if your machine has long longs, make Quad an unsigned long long.
(I called it Quad because on most machines, the largest integer size
supported is a four-byte unsigned long.)
If you need to be able to anagram larger phrases, increase MAX_QUADS.
If you increase it beyond 4, you'll have to add a few more loop unrolling
steps to FindAnagram.
*/
#include "anagram_ctype.h"
#include "anagram_stdlib.h"
#include "anagram_strings.h"
#include "anagram_compare.h"
/*
Defines
*/
#define anagram_DICTWORDS 2279
#define anagram_MASK_BITS 32 /* number of bits in a Quad */
#define anagram_MAX_QUADS 2 /* controls largest phrase */
#define anagram_MAXCAND 100 /* candidates */
#define anagram_MAXSOL 51 /* words in the solution */
#define anagram_ALPHABET 26 /* letters in the alphabet */
#define anagram_OneStep( i ) \
if ( ( aqNext[ i ] = pqMask[ i ] - pw->aqMask[ i ] ) & anagram_aqMainSign[ i ] ) { \
ppwStart ++; \
continue; \
}
/*
Type definitions
*/
typedef unsigned int anagram_Quad; /* for building our bit mask */
/* A Word remembers the information about a candidate word. */
typedef struct {
char *pchWord; /* the word itself */
anagram_Quad aqMask[ anagram_MAX_QUADS ]; /* the word's mask */
unsigned cchLength; /* letters in the word */
char padding[ 4 ];
} anagram_Word;
typedef anagram_Word *anagram_PWord;
typedef anagram_Word **anagram_PPWord;
/* A Letter remembers information about each letter in the phrase to
be anagrammed. */
typedef struct {
unsigned uFrequency; /* how many times it appears */
unsigned uShift; /* how to mask */
unsigned uBits; /* the bit mask itself */
unsigned iq; /* which Quad to inspect? */
} anagram_Letter;
typedef anagram_Letter *anagram_PLetter;
/*
Forward declaration of functions
*/
void anagram_init( void );
void anagram_main( void );
int anagram_return( void );
int anagram_ch2i( int ch );
void anagram_AddWords( void );
void anagram_BuildMask( char const *pchPhrase );
void anagram_BuildWord( char *pchWord );
void anagram_DumpWords( void );
void anagram_FindAnagram( anagram_Quad *pqMask,
anagram_PPWord ppwStart,
int iLetter );
anagram_PWord anagram_NewWord( void );
anagram_PWord anagram_NextWord( void );
void anagram_ReadDict( void );
void anagram_Reset( void );
void anagram_SortCandidates( void );
/*
Declaration of global variables
*/
extern char const *anagram_achPhrase[ 3 ];
extern char const *anagram_dictionary[ anagram_DICTWORDS ];
/* candidates we've found so far */
static anagram_PWord anagram_apwCand[ anagram_MAXCAND ];
/* how many of them? */
static unsigned anagram_cpwCand;
/* statistics on the current phrase */
static anagram_Letter anagram_alPhrase[ anagram_ALPHABET ];
/* number of letters in phrase */
static int anagram_cchPhraseLength;
/* the bit field for the full phrase */
static anagram_Quad anagram_aqMainMask[ anagram_MAX_QUADS ];
/* where the sign bits are */
static anagram_Quad anagram_aqMainSign[ anagram_MAX_QUADS ];
static const int anagram_cchMinLength = 3;
/* auGlobalFrequency counts the number of times each letter appears,
summed over all candidate words. This is used to decide which letter
to attack first. */
static unsigned anagram_auGlobalFrequency[ anagram_ALPHABET ];
static int anagram_achByFrequency[ anagram_ALPHABET ]; /* for sorting */
/* the dictionary is read here */
static char *anagram_pchDictionary;
/* the answers */
static anagram_PWord anagram_apwSol[ anagram_MAXSOL ];
static int anagram_cpwLast;
/* buffer to write an answer */
static char anagram_buffer[ 30 ];
/*
Initialization- and return-value-related functions
*/
/* ReadDict -- read the dictionary file into memory and preprocess it
A word of length cch in the dictionary is encoded as follows:
byte 0 = cch + 3
byte 1 = number of letters in the word
byte 2... = the word itself, null-terminated
Observe that cch+3 is the length of the total encoding. These
byte streams are concatenated, and terminated with a 0.
*/
void anagram_ReadDict( void )
{
char *pch;
char *pchBase;
unsigned len;
unsigned cWords = 0;
unsigned cLetters;
int i;
volatile char bitmask = 0;
len = 0;
_Pragma( "loopbound min 2279 max 2279" )
for ( i = 0; i < anagram_DICTWORDS; i ++ ) {
unsigned strlen = 0;
_Pragma( "loopbound min 1 max 5" )
while ( anagram_dictionary[ i ][ strlen ] != 0 )
strlen ++;
len += strlen + 3;
}
len ++;
pchBase = anagram_pchDictionary = ( char * )anagram_malloc( len );
_Pragma( "loopbound min 2279 max 2279" )
for ( i = 0; i < anagram_DICTWORDS; i ++ ) {
int index = 0;
pch = pchBase + 2; /* reserve for length */
cLetters = 0;
_Pragma( "loopbound min 1 max 5" )
while ( anagram_dictionary[ i ][ index ] != '\0' ) {
if ( anagram_isalpha( anagram_dictionary[ i ][ index ] ) )
cLetters ++;
*pch ++ = anagram_dictionary[ i ][ index ];
index ++;
*( pch - 1 ) ^= bitmask;
}
*pch ++ = '\0';
*pchBase = ( char )( pch - pchBase );
pchBase[ 1 ] = ( char )cLetters;
pchBase = pch;
cWords ++;
}
*pchBase ++ = 0;
}
void anagram_init( void )
{
anagram_ReadDict();
}
int anagram_return( void )
{
int i;
char const *answer = "duke yip arm";
_Pragma( "loopbound min 12 max 12" )
for ( i = 0; i < 12; i++ )
if ( answer[ i ] != anagram_buffer[ i ] )
return 1;
return 0;
}
/*
Core benchmark functions
*/
/* convert letter to index */
int anagram_ch2i( int ch )
{
return ch - 'a';
}
int anagram_CompareFrequency( char *pch1, char *pch2 )
{
return anagram_auGlobalFrequency[ ( *(int*) pch1 ) ] <
anagram_auGlobalFrequency[ ( *(int*) pch2 ) ]
? -1 :
anagram_auGlobalFrequency[ ( *(int*) pch1 ) ] ==
anagram_auGlobalFrequency[ ( *(int*) pch2 ) ]
? 0 : 1;
}
void anagram_Reset( void )
{
anagram_bzero( ( char * )anagram_alPhrase,
sizeof( anagram_Letter ) * anagram_ALPHABET );
anagram_bzero( ( char * )anagram_aqMainMask,
sizeof( anagram_Quad ) * anagram_MAX_QUADS );
anagram_bzero( ( char * )anagram_aqMainSign,
sizeof( anagram_Quad ) * anagram_MAX_QUADS );
anagram_bzero( ( char * )anagram_auGlobalFrequency,
sizeof( unsigned ) * anagram_ALPHABET );
anagram_bzero( ( char * )anagram_achByFrequency,
sizeof( int ) * anagram_ALPHABET );
anagram_bzero( ( char * )anagram_apwCand,
sizeof( anagram_PWord ) * anagram_MAXCAND );
anagram_cchPhraseLength = 0;
anagram_cpwCand = 0;
}
void anagram_BuildMask( char const *pchPhrase )
{
int i;
int ch;
unsigned iq; /* which Quad? */
unsigned int cbtUsed; /* bits used in the current Quad */
unsigned int cbtNeed; /* bits needed for current letter */
anagram_Quad qNeed; /* used to build the mask */
/* Tabulate letter frequencies in the phrase */
anagram_cchPhraseLength = 0;
_Pragma( "loopbound min 11 max 11" )
while ( ( ch = *pchPhrase ++ ) != '\0' ) {
if ( anagram_isalpha( ch ) ) {
ch = anagram_tolower( ch );
anagram_alPhrase[ anagram_ch2i( ch ) ].uFrequency ++;
anagram_cchPhraseLength ++;
}
}
/* Build masks */
iq = 0; /* which quad being used */
cbtUsed = 0; /* bits used so far */
_Pragma( "loopbound min 26 max 26" )
for ( i = 0; i < anagram_ALPHABET; i ++ ) {
if ( anagram_alPhrase[ i ].uFrequency == 0 ) {
anagram_auGlobalFrequency[ i ] = ~0u; /* to make it sort last */
} else {
anagram_auGlobalFrequency[ i ] = 0u;
_Pragma( "loopbound min 1 max 2" )
for ( cbtNeed = 1, qNeed = 1;
anagram_alPhrase[ i ].uFrequency >= qNeed;
cbtNeed ++, qNeed <<= 1 )
;
if ( cbtUsed + cbtNeed > anagram_MASK_BITS )
cbtUsed = 0;
anagram_alPhrase[ i ].uBits = qNeed - 1;
if ( cbtUsed )
qNeed <<= cbtUsed;
anagram_aqMainSign[ iq ] |= qNeed;
anagram_aqMainMask[ iq ] |=
( anagram_Quad )anagram_alPhrase[ i ].uFrequency << cbtUsed;
anagram_alPhrase[ i ].uShift = cbtUsed;
anagram_alPhrase[ i ].iq = iq;
cbtUsed += cbtNeed;
}
}
}
anagram_PWord anagram_NewWord( void )
{
anagram_PWord pw;
pw = ( anagram_Word * )anagram_malloc( sizeof( anagram_Word ) );
return pw;
}
/* NextWord -- get another candidate entry, creating if necessary */
anagram_PWord anagram_NextWord( void )
{
anagram_PWord pw;
pw = anagram_apwCand[ anagram_cpwCand ++ ];
if ( pw != 0 )
return pw;
anagram_apwCand[ anagram_cpwCand - 1 ] = anagram_NewWord();
return anagram_apwCand[ anagram_cpwCand - 1 ];
}
/* BuildWord -- build a Word structure from an ASCII word
If the word does not fit, then do nothing. */
void anagram_BuildWord( char *pchWord )
{
unsigned char cchFrequency[ anagram_ALPHABET ];
int i;
char *pch = pchWord;
anagram_PWord pw;
unsigned int cchLength = 0;
anagram_bzero( ( char * )cchFrequency,
sizeof( unsigned char ) * anagram_ALPHABET );
/* Build frequency table */
_Pragma( "loopbound min 3 max 5" )
while ( ( i = *pch ++ ) != '\0' ) {
if ( !anagram_isalpha( i ) )
continue;
i = anagram_ch2i( anagram_tolower( i ) );
if ( ++ cchFrequency[ i ] > anagram_alPhrase[ i ].uFrequency )
return ;
++ cchLength;
}
/* Update global count */
_Pragma( "loopbound min 26 max 26" )
for ( i = 0; i < anagram_ALPHABET; i ++ )
anagram_auGlobalFrequency[ i ] += cchFrequency[ i ];
/* Create a Word structure and fill it in, including building the
bitfield of frequencies. */
pw = anagram_NextWord();
anagram_bzero( ( char * )( pw->aqMask ),
sizeof( anagram_Quad ) * anagram_MAX_QUADS );
pw->pchWord = pchWord;
pw->cchLength = cchLength;
_Pragma( "loopbound min 26 max 26" )
for ( i = 0; i < anagram_ALPHABET; i ++ ) {
pw->aqMask[ anagram_alPhrase[i].iq ] |=
( anagram_Quad )cchFrequency[ i ] << anagram_alPhrase[ i ].uShift;
}
}
/* AddWords -- build the list of candidates */
void anagram_AddWords( void )
{
char *pch = anagram_pchDictionary; /* walk through the dictionary */
anagram_cpwCand = 0;
_Pragma( "loopbound min 1967 max 1967" )
while ( *pch ) {
if ( ( pch[ 1 ] >= anagram_cchMinLength &&
pch[ 1 ] + anagram_cchMinLength <= anagram_cchPhraseLength )
|| pch[ 1 ] == anagram_cchPhraseLength )
anagram_BuildWord( pch + 2 );
pch += *pch;
}
}
void anagram_DumpWords( void )
{
int i, j;
int offset = 0;
_Pragma( "loopbound min 3 max 3" )
for ( i = 0; i < anagram_cpwLast; i ++ ) {
_Pragma( "loopbound min 3 max 5" )
for ( j = 0; anagram_apwSol[ i ]->pchWord[ j ] != '\0'; j ++ )
anagram_buffer[ offset + j ] = anagram_apwSol[ i ]->pchWord[ j ];
offset += j;
anagram_buffer[ offset ++ ] = ' ';
}
anagram_buffer[ offset ++ ] = '\0';
}
void anagram_FindAnagram( anagram_Quad *pqMask, anagram_PPWord ppwStart,
int iLetter )
{
anagram_Quad aqNext[ anagram_MAX_QUADS ];
register anagram_PWord pw;
anagram_Quad qMask;
unsigned iq;
anagram_PPWord ppwEnd = &anagram_apwCand[ 0 ];
ppwEnd += anagram_cpwCand;
_Pragma( "loopbound min 0 max 6" )
while ( 1 ) {
iq = anagram_alPhrase[ anagram_achByFrequency[iLetter] ].iq;
qMask = anagram_alPhrase[ anagram_achByFrequency[iLetter] ].uBits <<
anagram_alPhrase[ anagram_achByFrequency[iLetter] ].uShift;
if ( pqMask[ iq ] & qMask )
break;
iLetter ++;
}
_Pragma( "loopbound min 0 max 11" )
while ( ppwStart < ppwEnd ) {
pw = *ppwStart;
#if anagram_MAX_QUADS > 0
anagram_OneStep( 0 );
#endif
#if anagram_MAX_QUADS > 1
anagram_OneStep( 1 );
#endif
#if anagram_MAX_QUADS > 2
anagram_OneStep( 2 );
#endif
#if anagram_MAX_QUADS > 3
anagram_OneStep( 3 );
#endif
#if anagram_MAX_QUADS > 4
@@"Add more unrolling steps here, please."@@
#endif
/* If the pivot letter isn't present, defer this word until later */
if ( ( pw->aqMask[ iq ] & qMask ) == 0 ) {
*ppwStart = *( -- ppwEnd );
*ppwEnd = pw;
continue;
}
/* If we get here, this means the word fits. */
anagram_apwSol[ anagram_cpwLast ++ ] = pw;
if ( anagram_cchPhraseLength -= pw->cchLength ) { /* recurse */
/* The recursive call scrambles the tail, so we have to be
pessimistic. */
ppwEnd = &anagram_apwCand[ 0 ];
ppwEnd += anagram_cpwCand;
anagram_FindAnagram( &aqNext[ 0 ], ppwStart, iLetter );
} else /* found one */
anagram_DumpWords();
anagram_cchPhraseLength += pw->cchLength;
-- anagram_cpwLast;
ppwStart ++;
continue;
}
}
void anagram_SortCandidates( void )
{
int i;
/* Sort the letters by frequency */
_Pragma( "loopbound min 26 max 26" )
for ( i = 0; i < anagram_ALPHABET; i ++ )
anagram_achByFrequency[ i ] = i;
anagram_qsort( anagram_achByFrequency, anagram_ALPHABET, sizeof( int ) );
}
void _Pragma( "entrypoint" ) anagram_main( void )
{
int i;
_Pragma( "loopbound min 3 max 3" )
for ( i = 0; i < 3; i ++ ) {
anagram_Reset();
anagram_BuildMask( anagram_achPhrase[ i ] );
anagram_AddWords();
if ( anagram_cpwCand == 0 || anagram_cchPhraseLength == 0 )
continue;
anagram_cpwLast = 0;
anagram_SortCandidates();
_Pragma( "marker call_find" )
anagram_FindAnagram( anagram_aqMainMask, anagram_apwCand, 0 );
_Pragma( "flowrestriction 1*anagram_FindAnagram <= 51*call_find" );
}
}
/*
Main function
*/
int main( void )
{
anagram_init();
anagram_main();
return anagram_return();
}

View File

@ -0,0 +1,27 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_compare.h
Author: Raymond Chen
Function: This header contains the comparison functions used by anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_COMPARE_H
#define ANAGRAM_COMPARE_H
int anagram_CompareFrequency( char *pch1, char *pch2 );
#endif

View File

@ -0,0 +1,45 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_ctype.h
Author: Raymond Chen
Function: This header contains some C library functions used by anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_CTYPE_H
#define ANAGRAM_CTYPE_H
int anagram_islower( int c )
{
return 'a' <= c && c <= 'z';
}
int anagram_isupper( int c )
{
return 'A' <= c && c <= 'Z';
}
int anagram_isalpha( int c )
{
return anagram_isupper( c ) || anagram_islower( c );
}
int anagram_tolower( int c )
{
return anagram_isupper( c ) ? c + ( 'a' - 'A' ) : c;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,149 @@
/*
This file is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_stdlib.c
Author: Raymond Chen
Function: This file contains the C standard library functions used by anagram.
Source: anagram
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#include "anagram_stdlib.h"
#include "anagram_strings.h"
/* Includes anagram_CompareFrequency */
/* This function is included here because the WCC does not */
/* support function pointers */
#include "anagram_compare.h"
void anagram_swapi( char *ii, char *ij, unsigned long es )
{
char *i, *j, c;
i = ( char * )ii;
j = ( char * )ij;
_Pragma( "loopbound min 4 max 4" )
do {
c = *i;
*i ++ = *j;
*j ++ = c;
es -= sizeof( char );
} while ( es != 0 );
}
char *anagram_pivot( char *a, unsigned long n, unsigned long es )
{
unsigned long j;
char *pi, *pj, *pk;
j = n / 6 * es;
pi = a + j; /* 1/6 */
j += j;
pj = pi + j; /* 1/2 */
pk = pj + j; /* 5/6 */
if ( anagram_CompareFrequency( pi, pj ) < 0 ) {
if ( anagram_CompareFrequency( pi, pk ) < 0 ) {
if ( anagram_CompareFrequency( pj, pk ) < 0 )
return pj;
return pk;
}
return pi;
}
if ( anagram_CompareFrequency( pj, pk ) < 0 ) {
if ( anagram_CompareFrequency( pi, pk ) < 0 )
return pi;
return pk;
}
return pj;
}
void anagram_qsorts( char *a, unsigned long n, unsigned long es )
{
unsigned long j;
char *pi, *pj, *pn;
volatile unsigned int flowfactdummy = 0;
_Pragma( "loopbound min 0 max 3" )
while ( n > 1 ) {
if ( n > 10 )
pi = anagram_pivot( a, n, es );
else
pi = a + ( n >> 1 ) * es;
anagram_swapi( a, pi, es );
pi = a;
pn = a + n * es;
pj = pn;
_Pragma( "loopbound min 0 max 10" )
while ( 1 ) {
/* wcc note: this assignment expression was added to avoid assignment of
multiple loop bound annotations to same loop (cf. Ticket #0002323). */
flowfactdummy ++;
_Pragma( "loopbound min 1 max 6" )
do {
pi += es;
} while ( pi < pn && anagram_CompareFrequency( pi, a ) < 0 );
_Pragma( "loopbound min 1 max 7" )
do {
pj -= es;
} while ( pj > a && anagram_CompareFrequency( pj, a ) > 0 );
if ( pj < pi )
break;
anagram_swapi( pi, pj, es );
}
anagram_swapi( a, pj, es );
j = ( unsigned long )( pj - a ) / es;
n = n - j - 1;
if ( j >= n ) {
anagram_qsorts( a, j, es );
a += ( j + 1 ) * es;
} else {
anagram_qsorts( a + ( j + 1 )*es, n, es );
n = j;
}
}
}
void anagram_qsort( void *va, unsigned long n, unsigned long es )
{
_Pragma( "marker call_qsorts" )
anagram_qsorts( ( char * )va, n, es );
_Pragma( "flowrestriction 1*anagram_qsorts <= 17*call_qsorts" );
}
/* This must be redefined for each new benchmark */
#define ANAGRAM_HEAP_SIZE 21000
static char anagram_simulated_heap[ANAGRAM_HEAP_SIZE];
static unsigned int anagram_freeHeapPos;
void *anagram_malloc( unsigned int numberOfBytes )
{
void *currentPos = ( void * )&anagram_simulated_heap[ anagram_freeHeapPos ];
/* Get a 4-byte address for alignment purposes */
//anagram_freeHeapPos += ( ( numberOfBytes + 4 ) & ( unsigned int )0xfffffffc );
unsigned int rem = ( numberOfBytes & ( unsigned int )0x3 );
unsigned int adjustment = rem ? 4 - rem : 0;
anagram_freeHeapPos += numberOfBytes + adjustment;
return currentPos;
}
void anagram_bzero( char *p, unsigned long len )
{
unsigned long i;
_Pragma( "loopbound min 8 max 800" )
for ( i = 0; i < len; ++ i ){
*p ++ = '\0';}
}

View File

@ -0,0 +1,29 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_stdlib.h
Author: Raymond Chen
Function: This header contains some C standard library functions used by anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_STDLIB_H
#define ANAGRAM_STDLIB_H
void *anagram_malloc( unsigned int numberOfBytes );
void anagram_qsort( void *va, unsigned long n, unsigned long es );
#endif

View File

@ -0,0 +1,27 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_strings.h
Author: Raymond Chen
Function: This header contains some C standard library functions used by anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_STRINGS_H
#define ANAGRAM_STRINGS_H
void anagram_bzero( char *p, unsigned long len );
#endif

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,649 @@
/*
This program is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram
Author: Raymond Chen
Function: A program that computes anagrams.
Source: See below.
Original name: anagram
Changes: See ChangeLog.txt
License: See below.
*/
/*
Anagram program by Raymond Chen,
inspired by a similar program by Brian Scearce
This program is Copyright 1991 by Raymond Chen.
(rjc@math.princeton.edu)
This program may be freely distributed provided all alterations
to the original are clearly indicated as such.
*/
/* There are two tricks. First is the Basic Idea:
When the user types in a phrase, the phrase is first preprocessed to
determine how many of each letter appears. A bit field is then constructed
dynamically, such that each field is large enough to hold the next power
of two larger than the number of times the character appears. For example,
if the phrase is hello, world, the bit field would be
00 00 00 000 000 00 00
d e h l o r w
The phrase hello, world, itself would be encoded as
01 01 01 011 010 01 01
d e h l o r w
and the word hollow would be encoded as
00 00 01 010 010 00 01
d e h l o r w
The top bit of each field is set in a special value called the sign.
Here, the sign would be
10 10 10 100 100 10 10
d e h l o r w
The reason for packing the values into a bit field is that the operation
of subtracting out the letters of a word from the current phrase can be
carried out in parallel. for example, subtracting the word hello from
the phrase hello, world, is merely
d e h l o r w
01 01 01 011 010 01 01 (dehllloorw)
- 00 00 01 010 010 00 01 (hlloow)
========================
01 01 00 001 000 01 00 (delr)
Since none of the sign bits is set, the word fits, and we can continue.
Suppose the next word we tried was hood.
d e h l o r w
01 01 00 001 000 01 00 (delr)
- 01 00 01 000 010 00 00 (hood)
========================
00 00 11 000 110 01 00
^ ^
A sign bit is set. (Two, actually.) This means that hood does not
fit in delr, so we skip it and try another word. (Observe that
when a sign bit becomes set, it screws up the values for the letters to
the left of that bit, but that's not important.)
The inner loop of an anagram program is testing to see if a
word fits in the collection of untried letters. Traditional methods
keep an array of 26 integers, which are then compared in turn. This
means that there are 26 comparisons per word.
This method reduces the number of comparisons to MAX_QUAD, typically 2.
Instead of looping through an array, we merely perform the indicated
subtraction and test if any of the sign bits is set.
*/
/* The nuts and bolts:
The dictionary is loaded and preprocessed. The preprocessed dictionary
is a concatenation of copies of the structure:
struct dictword {
char bStructureSize; -- size of this structure
char cLetters; -- number of letters in the word
char achWord[]; -- the word itself (0-terminated)
}
Since this is a variable-sized structure, we keep its size in the structure
itself for rapid stepping through the table.
When a phrase is typed in, it is first preprocessed as described in the
Basic Idea. We then go through the dictionary, testing each word. If
the word fits in our phrase, we build the bit field for its frequency
table and add it to the list of candidates.
*/
/*
The Second Trick:
Before diving into our anagram search, we then tabulate how many times
each letter appears in our list of candidates, and sort the table, with
the rarest letter first.
We then do our anagram search.
Like most anagram programs, this program does a depth-first search.
Although most anagram programs do some sort of heuristics to decide what
order to place words in the list_of_candidates, the search itself proceeds
according to a greedy algorithm. That is, once you find a word that fits,
subtract it and recurse.
This anagram program exercises some restraint and does not march down
every branch that shows itself. Instead, it only goes down branches
that use the rarest unused letter. This helps to find dead ends faster.
FindAnagram(unused_letters, list_of_candidates) {
l = the rarest letter as yet unused
For word in list_of_candidates {
if word does not fit in unused_letters, go on to the next word.
if word does not contain l, defer.
FindAnagram(unused_letters - word, list_of_candidates[word,...])
}
}
The heuristic of the Second Trick can probably be improved. I invite
anyone willing to improve it to do so.
*/
/* Before compiling, make sure Quad and MASK_BITS are set properly. For best
results, make Quad the largest integer size supported on your machine.
So if your machine has long longs, make Quad an unsigned long long.
(I called it Quad because on most machines, the largest integer size
supported is a four-byte unsigned long.)
If you need to be able to anagram larger phrases, increase MAX_QUADS.
If you increase it beyond 4, you'll have to add a few more loop unrolling
steps to FindAnagram.
*/
#include "anagram_ctype.h"
#include "anagram_stdlib.h"
#include "anagram_strings.h"
#include "anagram_compare.h"
/*
Defines
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
#define anagram_DICTWORDS 2279
#define anagram_MASK_BITS 32 /* number of bits in a Quad */
#define anagram_MAX_QUADS 2 /* controls largest phrase */
#define anagram_MAXCAND 100 /* candidates */
#define anagram_MAXSOL 51 /* words in the solution */
#define anagram_ALPHABET 26 /* letters in the alphabet */
#define anagram_OneStep(i) \
if ((aqNext[i] = pqMask[i] - pw->aqMask[i]) & anagram_aqMainSign[i]) { \
ppwStart++; \
continue; \
}
/*
Type definitions
*/
typedef unsigned int anagram_Quad; /* for building our bit mask */
/* A Word remembers the information about a candidate word. */
typedef struct {
char *pchWord; /* the word itself */
anagram_Quad aqMask[anagram_MAX_QUADS]; /* the word's mask */
unsigned cchLength; /* letters in the word */
char padding[4];
} anagram_Word;
typedef anagram_Word *anagram_PWord;
typedef anagram_Word **anagram_PPWord;
/* A Letter remembers information about each letter in the phrase to
be anagrammed. */
typedef struct {
unsigned uFrequency; /* how many times it appears */
unsigned uShift; /* how to mask */
unsigned uBits; /* the bit mask itself */
unsigned iq; /* which Quad to inspect? */
} anagram_Letter;
typedef anagram_Letter *anagram_PLetter;
/*
Forward declaration of functions
*/
void anagram_init(void);
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
anagram_main(void);
int anagram_return(void);
int anagram_ch2i(int ch);
void anagram_AddWords(void);
void anagram_BuildMask(char const *pchPhrase);
void anagram_BuildWord(char *pchWord);
void anagram_DumpWords(void);
void anagram_FindAnagram(anagram_Quad *pqMask, anagram_PPWord ppwStart,
int iLetter);
anagram_PWord anagram_NewWord(void);
anagram_PWord anagram_NextWord(void);
void anagram_ReadDict(void);
void anagram_Reset(void);
void anagram_SortCandidates(void);
/*
Declaration of global variables
*/
extern char const *anagram_achPhrase[3];
extern char const *anagram_dictionary[anagram_DICTWORDS];
/* candidates we've found so far */
static anagram_PWord anagram_apwCand[anagram_MAXCAND];
/* how many of them? */
static unsigned anagram_cpwCand;
/* statistics on the current phrase */
static anagram_Letter anagram_alPhrase[anagram_ALPHABET];
/* number of letters in phrase */
static int anagram_cchPhraseLength;
/* the bit field for the full phrase */
static anagram_Quad anagram_aqMainMask[anagram_MAX_QUADS];
/* where the sign bits are */
static anagram_Quad anagram_aqMainSign[anagram_MAX_QUADS];
static const int anagram_cchMinLength = 3;
/* auGlobalFrequency counts the number of times each letter appears,
summed over all candidate words. This is used to decide which letter
to attack first. */
static unsigned anagram_auGlobalFrequency[anagram_ALPHABET];
static int anagram_achByFrequency[anagram_ALPHABET]; /* for sorting */
/* the dictionary is read here */
static char *anagram_pchDictionary;
/* the answers */
static anagram_PWord anagram_apwSol[anagram_MAXSOL];
static int anagram_cpwLast;
/* buffer to write an answer */
static char anagram_buffer[30];
/*
Initialization- and return-value-related functions
*/
/* ReadDict -- read the dictionary file into memory and preprocess it
A word of length cch in the dictionary is encoded as follows:
byte 0 = cch + 3
byte 1 = number of letters in the word
byte 2... = the word itself, null-terminated
Observe that cch+3 is the length of the total encoding. These
byte streams are concatenated, and terminated with a 0.
*/
void
anagram_ReadDict(void) {
char *pch;
char *pchBase;
unsigned len;
unsigned cWords = 0;
unsigned cLetters;
int i;
volatile char bitmask = 0;
len = 0;
__pragma_loopbound(2279, 2279);
for (i = 0; i < anagram_DICTWORDS; i++) {
unsigned strlen = 0;
__pragma_loopbound(1, 5);
while (anagram_dictionary[i][strlen] != 0)
strlen++;
len += strlen + 3;
}
len++;
pchBase = anagram_pchDictionary = (char *) anagram_malloc(len);
__pragma_loopbound(2279, 2279);
for (i = 0; i < anagram_DICTWORDS; i++) {
int index = 0;
pch = pchBase + 2; /* reserve for length */
cLetters = 0;
__pragma_loopbound(1, 5);
while (anagram_dictionary[i][index] != '\0') {
if (anagram_isalpha(anagram_dictionary[i][index]))
cLetters++;
*pch++ = anagram_dictionary[i][index];
index++;
*(pch - 1) ^= bitmask;
}
*pch++ = '\0';
*pchBase = (char) (pch - pchBase);
pchBase[1] = (char) cLetters;
pchBase = pch;
cWords++;
}
*pchBase++ = 0;
}
void
anagram_init(void) {
anagram_ReadDict();
}
int
anagram_return(void) {
int i;
char const *answer = "duke yip arm";
_Pragma(
"loopbound min 12 max 12") for (i = 0; i < 12;
i++) if (answer[i] !=
anagram_buffer[i]) return 1;
return 0;
}
/*
Core benchmark functions
*/
/* convert letter to index */
int
anagram_ch2i(int ch) {
return ch - 'a';
}
int
anagram_CompareFrequency(char *pch1, char *pch2) {
return anagram_auGlobalFrequency[(*(int *) pch1)] <
anagram_auGlobalFrequency[(*(int *) pch2)]
? -1
: anagram_auGlobalFrequency[(*(int *) pch1)] ==
anagram_auGlobalFrequency[(*(int *) pch2)]
? 0
: 1;
}
void
anagram_Reset(void) {
anagram_bzero((char *) anagram_alPhrase,
sizeof(anagram_Letter) * anagram_ALPHABET);
anagram_bzero((char *) anagram_aqMainMask,
sizeof(anagram_Quad) * anagram_MAX_QUADS);
anagram_bzero((char *) anagram_aqMainSign,
sizeof(anagram_Quad) * anagram_MAX_QUADS);
anagram_bzero((char *) anagram_auGlobalFrequency,
sizeof(unsigned) * anagram_ALPHABET);
anagram_bzero((char *) anagram_achByFrequency,
sizeof(int) * anagram_ALPHABET);
anagram_bzero((char *) anagram_apwCand,
sizeof(anagram_PWord) * anagram_MAXCAND);
anagram_cchPhraseLength = 0;
anagram_cpwCand = 0;
}
void
anagram_BuildMask(char const *pchPhrase) {
int i;
int ch;
unsigned iq; /* which Quad? */
unsigned int cbtUsed; /* bits used in the current Quad */
unsigned int cbtNeed; /* bits needed for current letter */
anagram_Quad qNeed; /* used to build the mask */
/* Tabulate letter frequencies in the phrase */
anagram_cchPhraseLength = 0;
__pragma_loopbound(11, 11);
while ((ch = *pchPhrase++) != '\0') {
if (anagram_isalpha(ch)) {
ch = anagram_tolower(ch);
anagram_alPhrase[anagram_ch2i(ch)].uFrequency++;
anagram_cchPhraseLength++;
}
}
/* Build masks */
iq = 0; /* which quad being used */
cbtUsed = 0; /* bits used so far */
__pragma_loopbound(26, 26);
for (i = 0; i < anagram_ALPHABET; i++) {
if (anagram_alPhrase[i].uFrequency == 0) {
anagram_auGlobalFrequency[i] = ~0u; /* to make it sort last */
} else {
anagram_auGlobalFrequency[i] = 0u;
_Pragma(
"loopbound min 1 max 2") for (cbtNeed = 1, qNeed = 1;
anagram_alPhrase[i].uFrequency >=
qNeed;
cbtNeed++, qNeed <<= 1);
if (cbtUsed + cbtNeed > anagram_MASK_BITS)
cbtUsed = 0;
anagram_alPhrase[i].uBits = qNeed - 1;
if (cbtUsed)
qNeed <<= cbtUsed;
anagram_aqMainSign[iq] |= qNeed;
anagram_aqMainMask[iq] |=
(anagram_Quad) anagram_alPhrase[i].uFrequency << cbtUsed;
anagram_alPhrase[i].uShift = cbtUsed;
anagram_alPhrase[i].iq = iq;
cbtUsed += cbtNeed;
}
}
}
anagram_PWord
anagram_NewWord(void) {
anagram_PWord pw;
pw = (anagram_Word *) anagram_malloc(sizeof(anagram_Word));
return pw;
}
/* NextWord -- get another candidate entry, creating if necessary */
anagram_PWord
anagram_NextWord(void) {
anagram_PWord pw;
pw = anagram_apwCand[anagram_cpwCand++];
if (pw != 0)
return pw;
anagram_apwCand[anagram_cpwCand - 1] = anagram_NewWord();
return anagram_apwCand[anagram_cpwCand - 1];
}
/* BuildWord -- build a Word structure from an ASCII word
If the word does not fit, then do nothing. */
void
anagram_BuildWord(char *pchWord) {
unsigned char cchFrequency[anagram_ALPHABET];
int i;
char *pch = pchWord;
anagram_PWord pw;
unsigned int cchLength = 0;
anagram_bzero((char *) cchFrequency,
sizeof(unsigned char) * anagram_ALPHABET);
/* Build frequency table */
__pragma_loopbound(3, 5);
while ((i = *pch++) != '\0') {
if (!anagram_isalpha(i))
continue;
i = anagram_ch2i(anagram_tolower(i));
if (++cchFrequency[i] > anagram_alPhrase[i].uFrequency)
return;
++cchLength;
}
/* Update global count */
__pragma_loopbound(26, 26);
for (i = 0; i < anagram_ALPHABET; i++)
anagram_auGlobalFrequency[i] += cchFrequency[i];
/* Create a Word structure and fill it in, including building the
bitfield of frequencies. */
pw = anagram_NextWord();
anagram_bzero((char *) (pw->aqMask),
sizeof(anagram_Quad) * anagram_MAX_QUADS);
pw->pchWord = pchWord;
pw->cchLength = cchLength;
__pragma_loopbound(26, 26);
for (i = 0; i < anagram_ALPHABET; i++) {
pw->aqMask[anagram_alPhrase[i].iq] |= (anagram_Quad) cchFrequency[i]
<< anagram_alPhrase[i].uShift;
}
}
/* AddWords -- build the list of candidates */
void
anagram_AddWords(void) {
char *pch = anagram_pchDictionary; /* walk through the dictionary */
anagram_cpwCand = 0;
__pragma_loopbound(1967, 1967);
while (*pch) {
if ((pch[1] >= anagram_cchMinLength &&
pch[1] + anagram_cchMinLength <= anagram_cchPhraseLength) ||
pch[1] == anagram_cchPhraseLength)
anagram_BuildWord(pch + 2);
pch += *pch;
}
}
void
anagram_DumpWords(void) {
int i, j;
int offset = 0;
__pragma_loopbound(3, 3);
for (i = 0; i < anagram_cpwLast; i++) {
__pragma_loopbound(3, 5);
for (j = 0; anagram_apwSol[i]->pchWord[j] != '\0'; j++)
anagram_buffer[offset + j] = anagram_apwSol[i]->pchWord[j];
offset += j;
anagram_buffer[offset++] = ' ';
}
anagram_buffer[offset++] = '\0';
}
void
anagram_FindAnagram(anagram_Quad *pqMask, anagram_PPWord ppwStart,
int iLetter) {
anagram_Quad aqNext[anagram_MAX_QUADS];
register anagram_PWord pw;
anagram_Quad qMask;
unsigned iq;
anagram_PPWord ppwEnd = &anagram_apwCand[0];
ppwEnd += anagram_cpwCand;
__pragma_loopbound(0, 6);
while (1) {
iq = anagram_alPhrase[anagram_achByFrequency[iLetter]].iq;
qMask = anagram_alPhrase[anagram_achByFrequency[iLetter]].uBits
<< anagram_alPhrase[anagram_achByFrequency[iLetter]].uShift;
if (pqMask[iq] & qMask)
break;
iLetter++;
}
__pragma_loopbound(0, 11);
while (ppwStart < ppwEnd) {
pw = *ppwStart;
#if anagram_MAX_QUADS > 0
anagram_OneStep(0);
#endif
#if anagram_MAX_QUADS > 1
anagram_OneStep(1);
#endif
#if anagram_MAX_QUADS > 2
anagram_OneStep(2);
#endif
#if anagram_MAX_QUADS > 3
anagram_OneStep(3);
#endif
#if anagram_MAX_QUADS > 4
@@"Add more unrolling steps here, please." @ @
#endif
/* If the pivot letter isn't present, defer this word until later */
if ((pw->aqMask[iq] & qMask) == 0) {
*ppwStart = *(--ppwEnd);
*ppwEnd = pw;
continue;
}
/* If we get here, this means the word fits. */
anagram_apwSol[anagram_cpwLast++] = pw;
if (anagram_cchPhraseLength -= pw->cchLength) { /* recurse */
/* The recursive call scrambles the tail, so we have to be
pessimistic. */
ppwEnd = &anagram_apwCand[0];
ppwEnd += anagram_cpwCand;
anagram_FindAnagram(&aqNext[0], ppwStart, iLetter);
} else /* found one */
anagram_DumpWords();
anagram_cchPhraseLength += pw->cchLength;
--anagram_cpwLast;
ppwStart++;
continue;
}
}
void
anagram_SortCandidates(void) {
int i;
/* Sort the letters by frequency */
__pragma_loopbound(26, 26);
for (i = 0; i < anagram_ALPHABET; i++)
anagram_achByFrequency[i] = i;
anagram_qsort(anagram_achByFrequency, anagram_ALPHABET, sizeof(int));
}
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
anagram_main(void) {
int i;
__pragma_loopbound(3, 3);
for (i = 0; i < 3; i++) {
anagram_Reset();
anagram_BuildMask(anagram_achPhrase[i]);
anagram_AddWords();
if (anagram_cpwCand == 0 || anagram_cchPhraseLength == 0)
continue;
anagram_cpwLast = 0;
anagram_SortCandidates();
_Pragma("marker call_find")
anagram_FindAnagram(anagram_aqMainMask, anagram_apwCand, 0);
_Pragma("flowrestriction 1*anagram_FindAnagram <= 51*call_find");
}
}
/*
Main function
*/
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
anagram_init();
anagram_main();
return anagram_return();
}

View File

@ -0,0 +1,27 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_compare.h
Author: Raymond Chen
Function: This header contains the comparison functions used by anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_COMPARE_H
#define ANAGRAM_COMPARE_H
int anagram_CompareFrequency(char *pch1, char *pch2);
#endif

View File

@ -0,0 +1,45 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_ctype.h
Author: Raymond Chen
Function: This header contains some C library functions used by anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_CTYPE_H
#define ANAGRAM_CTYPE_H
int
anagram_islower(int c) {
return 'a' <= c && c <= 'z';
}
int
anagram_isupper(int c) {
return 'A' <= c && c <= 'Z';
}
int
anagram_isalpha(int c) {
return anagram_isupper(c) || anagram_islower(c);
}
int
anagram_tolower(int c) {
return anagram_isupper(c) ? c + ('a' - 'A') : c;
}
#endif

View File

@ -0,0 +1,320 @@
/*
This file is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_input.c
Author: Raymond Chen
Function: This file contains the input data used by anagram.
Source: anagram
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
/*
Forward declaration of global variables
*/
extern char const *anagram_achPhrase[3];
extern char const *anagram_dictionary[2279];
/*
Definition of global variables
*/
char const *anagram_achPhrase[3] = {"todd austin", "john alledy",
"mary updike"};
char const *anagram_dictionary[2279] = {
"2nd", "4th", "8th", "a", "ABA", "aback", "abash", "abbas",
"abbey", "abed", "abet", "abort", "abut", "Accra", "ACM", "acorn",
"Acts", "Ada", "adapt", "added", "addle", "Adele", "Aden", "admix",
"adore", "adult", "affix", "afire", "aft", "agate", "agave", "Agee",
"agent", "agile", "Agnew", "agone", "ahoy", "Aida", "aim", "Ainu",
"airy", "Ajax", "Alamo", "alarm", "alb", "Alcoa", "alder", "Aleck",
"alert", "algae", "alia", "alike", "alive", "allay", "alley", "Allis",
"allow", "ally", "Allyn", "aloe", "aloha", "along", "aloud", "also",
"alter", "Alton", "Alva", "amaze", "amber", "ami", "amigo", "amiss",
"Amman", "Amoco", "amok", "Amos", "ample", "amra", "amy", "Andes",
"angel", "Angie", "angry", "Angus", "Anne", "annex", "annoy", "annul",
"ante", "any", "apex", "apple", "apron", "apt", "arch", "argue",
"Aries", "arm", "army", "aroma", "array", "arrow", "Artie", "arty",
"arum", "a's", "ash", "ashen", "ashy", "askew", "assai", "Assam",
"Astor", "ate", "atlas", "atone", "audit", "Aug", "augur", "auk",
"aural", "avid", "avoid", "avow", "awash", "awe", "awn", "awry",
"axe", "axial", "axis", "axon", "Ayers", "Aztec", "b", "babe",
"Bach", "bad", "bait", "baldy", "balm", "balsa", "bam", "ban",
"bane", "banjo", "barb", "barn", "baron", "basal", "Basel", "basil",
"bassi", "baste", "batch", "Bates", "batik", "Bator", "bawd", "bay",
"bayed", "bayou", "be", "beak", "bean", "beard", "beat", "beck",
"Becky", "bed", "bedim", "bee", "beech", "beep", "beet", "befit",
"beg", "begin", "beige", "Bela", "belch", "belt", "beman", "bench",
"Benny", "bent", "Benz", "berth", "beset", "bet", "betel", "Bette",
"bevy", "Bible", "bide", "big", "bile", "bilk", "binge", "bit",
"bite", "black", "blanc", "bland", "blare", "blat", "blaze", "bled",
"blest", "blind", "Blinn", "bliss", "blitz", "blob", "blond", "blood",
"bloom", "blot", "blown", "blue", "bluff", "Blum", "blur", "board",
"boat", "bock", "bog", "bogy", "boil", "Boise", "bomb", "bon",
"bong", "bonus", "bonze", "booby", "book", "booky", "boon", "booze",
"bore", "Boris", "boron", "Bosch", "bosom", "bound", "bourn", "bowel",
"boy", "Boyce", "bract", "Brady", "brag", "brake", "brant", "brass",
"Braun", "bravo", "bread", "bream", "breve", "brew", "briar", "Brice",
"brief", "bring", "briny", "broad", "broth", "brunt", "BSTJ", "bub",
"buck", "Budd", "buddy", "Buick", "built", "bulge", "bulky", "bum",
"bump", "bunch", "bundy", "bunk", "Burch", "burg", "burl", "Burma",
"burnt", "Burr", "bury", "bush", "bushy", "bust", "busy", "butte",
"butyl", "buyer", "by", "bylaw", "Byrd", "byte", "cab", "cable",
"cacao", "cacti", "Cairo", "Caleb", "call", "calm", "canal", "canoe",
"canon", "can't", "cap", "caper", "capo", "card", "Carey", "Carib",
"Carla", "carol", "carve", "cash", "caste", "catch", "cater", "caulk",
"cause", "CBS", "cedar", "cent", "Cetus", "Chad", "chaff", "chair",
"champ", "char", "chasm", "chaw", "cheat", "cheer", "chef", "Chen",
"chew", "chick", "chief", "Chile", "chill", "chine", "chip", "chock",
"choir", "chomp", "chose", "Chris", "chuff", "chum", "chump", "CIA",
"cinch", "cite", "city", "clad", "clan", "clank", "Clara", "Claus",
"claw", "clean", "cleat", "clerk", "clime", "cling", "clink", "Clio",
"clod", "clomp", "cloth", "clove", "cluck", "clump", "clung", "Clyde",
"cobra", "coco", "coda", "Cody", "Cohn", "coin", "col", "Colby",
"coney", "Congo", "cony", "cool", "coon", "copra", "copy", "Corey",
"corn", "corps", "cos", "cosy", "couch", "cough", "count", "coup",
"cove", "cowry", "coy", "CPA", "crack", "craft", "Craig", "crank",
"crash", "crate", "crawl", "craze", "creak", "cream", "credo", "creek",
"Creon", "crept", "crest", "crew", "crib", "crime", "crimp", "crisp",
"crock", "croft", "crone", "crook", "crowd", "CRT", "crumb", "crump",
"crush", "crux", "cub", "cube", "cuff", "cup", "Cupid", "cur",
"curb", "curie", "cusp", "cute", "cycad", "cynic", "d", "daffy",
"dairy", "daisy", "dally", "dame", "Damon", "Dan", "dance", "Dane",
"dank", "Dante", "Dar", "darn", "dart", "dash", "davit", "day",
"De", "deaf", "deal", "death", "debit", "Dec", "decal", "Dee",
"Deere", "deify", "deity", "Della", "delta", "demur", "den", "Denny",
"dense", "deny", "depth", "desk", "deus", "devil", "dewar", "Dhabi",
"diary", "dick", "dicta", "did", "die", "Diego", "diety", "dill",
"din", "dine", "dirty", "disc", "ditch", "dive", "DNA", "dock",
"Dodd", "doff", "dogma", "dolce", "doll", "dolly", "done", "door",
"dope", "Doric", "dose", "dote", "doubt", "Doug", "dove", "dowel",
"doze", "Dr", "Draco", "drama", "drape", "drawl", "dread", "dreg",
"dress", "drew", "drib", "drier", "drill", "drip", "dross", "drown",
"druid", "drunk", "dry", "du", "Duane", "ducat", "duct", "duel",
"duff", "Duffy", "Dugan", "duke", "dull", "dulse", "duly", "dump",
"dumpy", "dunce", "dunk", "dupe", "dusky", "dwarf", "dwelt", "Dwyer",
"dyer", "Dyke", "dyne", "each", "eager", "ear", "earn", "ease",
"eat", "eater", "Eben", "Ecole", "Eden", "edge", "edgy", "edict",
"Edith", "EDT", "eel", "eft", "egg", "Egypt", "eject", "el",
"elan", "elate", "elect", "elfin", "elide", "elk", "Ella", "Ellis",
"Elmer", "else", "Elton", "elude", "elves", "ember", "Emile", "Emory",
"Eng", "Engle", "Enid", "Enos", "enter", "envoy", "epoxy", "equal",
"erase", "ere", "erg", "Erich", "Ernst", "Eros", "err", "Errol",
"Ervin", "e's", "essay", "ester", "Ethan", "Ethel", "ethic", "ethos",
"etude", "Eva", "Evans", "event", "evict", "exact", "exam", "excel",
"exit", "eye", "f", "Faber", "fable", "facet", "fad", "faery",
"fag", "fail", "faint", "fairy", "fake", "fang", "fare", "faro",
"fatal", "fatty", "fault", "faun", "Faust", "fay", "FBI", "fee",
"feed", "feign", "Felix", "Fermi", "ferry", "fest", "fetch", "fetus",
"few", "fiend", "fiery", "fifth", "fig", "fight", "filet", "film",
"finch", "fine", "finny", "fire", "first", "fish", "Fisk", "fist",
"Fitch", "flack", "flak", "flaky", "flame", "flank", "flare", "flat",
"flax", "flea", "fled", "flee", "fleet", "flint", "flit", "flock",
"flog", "flow", "Floyd", "flub", "fluke", "flute", "Flynn", "FM",
"foal", "focal", "Foley", "folk", "fond", "food", "foot", "fop",
"fore", "forge", "form", "fort", "forth", "forty", "Foss", "foul",
"fowl", "FPC", "frame", "Franz", "Frau", "fray", "freed", "fresh",
"friar", "fro", "frog", "from", "frost", "frown", "fry", "fuel",
"full", "fun", "fur", "furry", "fussy", "g", "gaff", "gag",
"Gail", "Galen", "gall", "game", "gamma", "gap", "gar", "garb",
"gas", "gasp", "gate", "gauge", "gaur", "gavel", "gawk", "gay",
"gecko", "gel", "gem", "Gemma", "gene", "genie", "genre", "genus",
"germ", "Gerry", "get", "giant", "gibby", "gig", "gild", "gilt",
"gin", "Gino", "given", "glare", "gleam", "glee", "glib", "glint",
"gloat", "glow", "glut", "GMT", "gnaw", "gnome", "GNP", "god",
"Goff", "gogo", "golf", "Goode", "goof", "goose", "gore", "gory",
"got", "gourd", "GPO", "grace", "Graff", "grape", "grasp", "grate",
"gravy", "graze", "grebe", "greed", "Greek", "Gregg", "grew", "grid",
"grime", "Grimm", "gripe", "grit", "groan", "gross", "grout", "grow",
"grown", "grub", "grunt", "GSA", "guano", "guess", "guide", "guile",
"guise", "gules", "gull", "gulp", "gumbo", "gun", "gunky", "guru",
"gush", "gust", "gusto", "guy", "Gwyn", "gyp", "gyro", "Habib",
"hack", "had", "Hades", "Hagen", "Hahn", "haiku", "hale", "halma",
"ham", "Haney", "Hans", "hard", "hare", "hark", "harm", "harsh",
"haste", "hasty", "hatch", "hater", "hawk", "Haydn", "hazel", "he",
"Healy", "hear", "heart", "heave", "heavy", "hedge", "heel", "hefty",
"Heinz", "held", "he'll", "hemp", "hertz", "hew", "hex", "hi",
"hick", "Hicks", "hike", "hilum", "hind", "hip", "hippy", "hire",
"his", "hive", "hobby", "hoc", "Hoff", "hogan", "Hokan", "hole",
"Holm", "holt", "home", "homo", "hondo", "hood", "hook", "hoop",
"hoot", "hope", "horn", "hose", "hot", "hound", "hovel", "how",
"howdy", "hub", "hubby", "hue", "huff", "huge", "huh", "hull",
"human", "Hun", "hung", "hunk", "hurt", "hurty", "hutch", "hydra",
"hyena", "hymen", "i", "ibid", "IBM", "icon", "I'd", "Idaho",
"ideal", "idiot", "idol", "IEEE", "iffy", "igloo", "iii", "ileum",
"Iliad", "ill", "Ilona", "image", "in", "inapt", "Inca", "incur",
"India", "inert", "infer", "infra", "Inman", "inn", "input", "ionic",
"Iowa", "ipso", "IR", "Iran", "irate", "Irene", "Irish", "Irma",
"is", "Ising", "Islam", "isle", "Italy", "it'd", "Ito", "iv",
"ivy", "j", "JACM", "jag", "James", "Jane", "Janos", "Japan",
"Jason", "jaw", "jean", "jeep", "Jeres", "jerky", "jess", "jet",
"jewel", "jig", "jilt", "Jo", "job", "jog", "join", "joke",
"jolt", "Jonas", "joule", "joust", "joy", "Juan", "judge", "judo",
"Judy", "juju", "juke", "julep", "jump", "junco", "junky", "junta",
"jure", "jut", "Kafka", "kapok", "Karp", "Kathy", "Kay", "Keats",
"keel", "keg", "kelly", "Kemp", "Kent", "Kenya", "kerry", "Kevin",
"keyed", "khaki", "Khmer", "kick", "Kiev", "kin", "Kiowa", "kirk",
"kiss", "kite", "kiva", "Klan", "Kline", "knee", "Knott", "Knox",
"koala", "Kong", "Korea", "kraft", "kraut", "Kuhn", "Kurd", "lac",
"lack", "lad", "ladle", "lag", "lain", "laity", "lam", "lame",
"lamp", "lance", "lane", "Lange", "Laos", "lapel", "lard", "Lares",
"Lars", "last", "late", "Latin", "latus", "law", "lay", "layup",
"lazy", "leach", "leafy", "leak", "leapt", "learn", "leash", "leave",
"ledge", "leech", "left", "leg", "leggy", "Leila", "lemma", "Lena",
"lens", "Leo", "Leona", "lest", "level", "levy", "lewd", "liar",
"lice", "lick", "lie", "lien", "life", "lift", "liken", "lilac",
"Lilly", "lily", "limb", "limit", "line", "lingo", "link", "Linus",
"Lise", "lisp", "live", "livre", "load", "loam", "loan", "lob",
"lobby", "local", "lock", "Loeb", "Logan", "logic", "loin", "Loki",
"loll", "Lomb", "long", "loon", "loose", "loot", "lope", "lord",
"Loren", "lose", "lossy", "Lotte", "loud", "lousy", "low", "Lowe",
"loy", "l's", "LTV", "Lucas", "lucky", "luge", "Luis", "lumen",
"lumpy", "lunar", "Lund", "Lura", "lure", "lurk", "lusty", "Lydia",
"lying", "Lynn", "Lyon", "Lyra", "m", "Mabel", "mace", "macho",
"macro", "madam", "magi", "magna", "mail", "main", "make", "Malay",
"male", "mall", "malt", "mamma", "mane", "mania", "manic", "manna",
"Mans", "Mao", "map", "mar", "Mardi", "maria", "Marin", "Mario",
"Mars", "Mary", "mask", "mast", "mat", "mate", "mater", "matte",
"maul", "Mavis", "maxim", "Maya", "Mayer", "Mayo", "mayst", "maze",
"me", "meal", "meaty", "media", "meet", "meld", "melt", "men",
"Menlo", "merge", "Merle", "merry", "mesh", "messy", "metro", "mew",
"Meyer", "mezzo", "mica", "midst", "mien", "mig", "mila", "milk",
"Mills", "milt", "Mimi", "mince", "mine", "mini", "mink", "minor",
"minot", "minus", "Mira", "mire", "mirth", "Missy", "misty", "mite",
"mitre", "mixup", "mob", "Mobil", "mock", "model", "Moen", "Mohr",
"moist", "molar", "mole", "month", "moody", "Moore", "moral", "Moran",
"morn", "Moser", "moss", "most", "motel", "moth", "motif", "motor",
"motto", "mousy", "Moyer", "Mrs", "m's", "mud", "muggy", "Muir",
"mulch", "mule", "mull", "mum", "mummy", "muon", "mural", "murre",
"mushy", "musk", "must", "Muzo", "my", "Myers", "mynah", "Myra",
"NAACP", "Nagy", "naive", "name", "Nancy", "nap", "nary", "nasal",
"natal", "NATO", "navy", "Nazi", "NBC", "NCR", "ne", "near",
"neath", "Ned", "need", "needy", "Nehru", "Nell", "neon", "Nero",
"net", "Neva", "neve", "new", "nice", "niche", "Niger", "night",
"Nikko", "Nile", "Niobe", "nitty", "NJ", "no", "Noah", "Nobel",
"nodal", "noise", "Nolan", "nolo", "noon", "nor", "nose", "notch",
"Nov", "now", "n's", "NTIS", "nude", "numb", "nurse", "NY",
"oaf", "oaken", "oar", "oasis", "oath", "obey", "objet", "ocean",
"Oct", "ode", "o'er", "off", "often", "ogle", "Okay", "old",
"oldy", "olive", "Olson", "omit", "once", "only", "onset", "onus",
"onyx", "ooze", "opera", "opium", "opt", "opus", "orb", "Orin",
"Orion", "osier", "ought", "our", "out", "ovate", "over", "Ovid",
"owing", "ox", "oxeye", "oxide", "Ozark", "p", "Pablo", "pace",
"pack", "pact", "padre", "pagan", "Paine", "pale", "palm", "pane",
"pansy", "Paoli", "papa", "papaw", "pappy", "parch", "pare", "Paris",
"park", "Parks", "parse", "Paso", "passe", "past", "path", "Patsy",
"Paul", "Pauli", "pax", "PBS", "peace", "peak", "Pease", "peck",
"pedal", "pee", "peek", "peep", "pen", "penny", "pep", "Pepsi",
"Perez", "perk", "Perle", "Perth", "peste", "Pete", "petri", "petty",
"pewee", "PhD", "phi", "phon", "phony", "phyla", "piano", "piece",
"pilot", "pinch", "ping", "pink", "pinto", "pious", "pipe", "pique",
"piss", "pithy", "pity", "pixy", "place", "plain", "plane", "plate",
"Plato", "play", "plaza", "plead", "pluck", "plug", "plump", "plunk",
"plus", "pod", "podia", "Poe", "poesy", "pogo", "poi", "poise",
"poke", "polis", "Polk", "poll", "polo", "Ponce", "pond", "pool",
"poop", "pop", "porch", "pork", "Porte", "Porto", "posh", "posse",
"post", "pour", "pow", "Prado", "Pratt", "pray", "press", "prey",
"price", "pride", "prig", "prime", "prior", "probe", "Prof", "prone",
"p's", "psych", "pub", "puck", "puffy", "Pugh", "pull", "puma",
"pun", "punky", "puny", "pupal", "puppy", "pure", "purl", "pus",
"PVC", "Pyle", "Pyrex", "Qatar", "quack", "quaff", "quash", "queen",
"quell", "query", "queue", "quick", "quill", "quint", "quirt", "quo",
"quote", "rabat", "rabbi", "radar", "radio", "radix", "Rae", "rag",
"rail", "rajah", "Ralph", "Ramo", "ran", "Rand", "randy", "Raoul",
"rape", "rare", "rasp", "rata", "rater", "rave", "raven", "razor",
"R&D", "reach", "ready", "real", "reb", "reck", "reedy", "reek",
"Reese", "regal", "Reid", "relax", "reman", "Rena", "rend", "ret",
"retch", "Rhea", "rheum", "rhino", "Rhoda", "rib", "rice", "rick",
"rid", "rifle", "rig", "rigid", "rill", "rim", "rimy", "rink",
"Rio", "rip", "ripen", "rise", "risk", "rite", "rival", "river",
"road", "roar", "rob", "robe", "robin", "rodeo", "roe", "roil",
"role", "Roman", "Rome", "romp", "roof", "room", "roost", "Rosen",
"rot", "rouge", "round", "rout", "rove", "Roy", "Royce", "r's",
"Ruben", "ruby", "rude", "Rudy", "rug", "rule", "rummy", "run",
"rung", "runt", "rupee", "ruse", "rusk", "Russo", "rusty", "Ruth",
"rutty", "Ryan", "rye", "sa", "sabra", "sad", "sag", "sage",
"sake", "sale", "Salk", "salty", "salve", "Sam", "same", "Samoa",
"sane", "sank", "Santa", "Sao", "sappy", "Sarah", "sari", "satyr",
"Saudi", "Sault", "save", "savvy", "SC", "scald", "scalp", "scarf",
"scat", "SCM", "scold", "scoot", "Scot", "scram", "scrub", "scud",
"scull", "scum", "SD", "seal", "seamy", "sect", "sedge", "seedy",
"seen", "seize", "semi", "sepal", "Sepoy", "septa", "serge", "serif",
"servo", "set", "Seton", "setup", "sewn", "shad", "shag", "shah",
"shaky", "shall", "shank", "shard", "Shari", "shaw", "Shea", "shed",
"sheer", "shied", "shift", "shill", "shin", "shirk", "shish", "shoo",
"shore", "shout", "shrew", "shrub", "shunt", "SIAM", "sib", "sibyl",
"side", "sigh", "sigma", "silk", "silly", "silt", "Simon", "since",
"sinew", "singe", "sinh", "Sioux", "sir", "siva", "sixty", "skeet",
"skew", "skid", "skimp", "skulk", "Skye", "slab", "slag", "slake",
"slap", "slay", "sleep", "sleet", "slick", "slim", "slimy", "slog",
"slosh", "sloth", "slow", "slug", "slum", "slung", "slurp", "sly",
"small", "smile", "smith", "smog", "smoky", "snack", "snark", "sneer",
"snell", "snip", "snoop", "snore", "snow", "snub", "snug", "so",
"soap", "soar", "soft", "soggy", "sold", "sole", "solid", "Solon",
"solve", "some", "son", "sonny", "soon", "sorb", "sore", "sort",
"south", "sow", "spa", "spade", "spare", "spark", "spasm", "spate",
"spawn", "spear", "speed", "spell", "Spica", "spicy", "spiky", "spire",
"Spiro", "splay", "spoil", "spook", "spool", "spore", "spout", "spree",
"sprue", "spur", "spy", "squaw", "s's", "St", "stag", "staid",
"stair", "stale", "stall", "stamp", "stand", "stark", "stash", "state",
"stay", "stead", "steak", "steam", "steed", "Steen", "steer", "stern",
"stew", "stile", "stilt", "stock", "stole", "stone", "stood", "stool",
"stop", "storm", "story", "stove", "strap", "straw", "strip", "strum",
"stud", "study", "stung", "stunt", "Sturm", "styli", "suave", "such",
"sud", "sue", "Suez", "suit", "sulky", "sung", "sunny", "sup",
"supra", "surge", "Sus", "sushi", "swank", "swap", "swear", "swelt",
"swig", "swine", "swish", "swiss", "sword", "swung", "Syria", "syrup",
"tab", "tabu", "tacit", "taffy", "Tahoe", "take", "tale", "talk",
"tamp", "tang", "tango", "tanh", "Tanya", "tap", "tape", "tapir",
"tappa", "tar", "tardy", "tarry", "task", "tasty", "tate", "tawny",
"taxi", "teach", "tease", "tecum", "Telex", "tempt", "tenon", "tense",
"tepid", "terry", "Tess", "Texas", "Thai", "than", "that", "Thea",
"thee", "them", "then", "theta", "they", "thick", "thigh", "thin",
"thing", "third", "three", "threw", "thug", "thus", "ti", "tibet",
"tic", "tid", "tidy", "tied", "tift", "til", "tile", "tilt",
"Timex", "Timon", "tinge", "tipsy", "tire", "tit", "tithe", "title",
"TNT", "toad", "today", "tog", "Togo", "toil", "token", "told",
"tome", "tommy", "tonal", "tong", "Toni", "tonk", "tony", "tool",
"tooth", "top", "tor", "torch", "tori", "torr", "torso", "torus",
"total", "totem", "tout", "tower", "town", "toxin", "track", "Tracy",
"trag", "trail", "trait", "tramp", "trap", "tread", "tree", "trend",
"tress", "trial", "tribe", "trill", "tripe", "troll", "troop", "trout",
"truck", "Trudy", "trunk", "trust", "TRW", "t's", "TTL", "tub",
"tube", "tuck", "Tudor", "tuft", "tulle", "tum", "tuna", "tune",
"tunic", "Turin", "turk", "turn", "tusk", "tutu", "tweak", "twice",
"twill", "twine", "twirl", "twit", "two", "tying", "ugly", "ultra",
"umbra", "uncle", "union", "unite", "upend", "upper", "upset", "Upton",
"urban", "urine", "us", "usage", "use", "USGS", "USIA", "usual",
"usurp", "Utah", "utile", "v", "vade", "vague", "vain", "valid",
"valve", "van", "vase", "vast", "Veda", "veer", "vein", "Vella",
"venom", "Venus", "verb", "Verde", "versa", "vest", "vetch", "vex",
"via", "vicar", "Vichy", "Vida", "vie", "Viet", "vigil", "viii",
"villa", "vise", "visor", "vitae", "Vito", "viva", "vixen", "vocal",
"voice", "Volta", "vowel", "v's", "w", "wack", "wacky", "wad",
"wade", "wafer", "wag", "wah", "wail", "wait", "waive", "waken",
"wale", "wally", "wan", "war", "ward", "ware", "warm", "warp",
"warty", "was", "washy", "water", "watt", "Watts", "way", "Wayne",
"weal", "wean", "wear", "web", "weber", "we'd", "wedge", "weed",
"week", "Wei", "weird", "Welch", "well", "welsh", "wept", "were",
"west", "wet", "wharf", "whee", "whelm", "when", "which", "whim",
"whir", "whisk", "white", "whiz", "whoa", "whole", "whoop", "whop",
"whose", "why", "widen", "widow", "wield", "Wier", "wile", "will",
"Wilma", "wilt", "win", "winch", "wino", "wipe", "wise", "wispy",
"witch", "withy", "witty", "woe", "wok", "wolve", "womb", "Wong",
"Woods", "wool", "wop", "wordy", "work", "worm", "worse", "worst",
"wove", "wow", "wreck", "wrest", "wrist", "Wu", "Wyatt", "Wylie",
"Wyner", "x", "xenon", "x's", "yacht", "Yale", "yam", "yang",
"yarn", "Yates", "year", "yeast", "Yeats", "Yemen", "yield", "yip",
"yodel", "yoga", "yoke", "yore", "you'd", "y's", "Yves", "YWCA",
"Zeiss", "zest", "zig", "zing", "zip", "Zoe", "zoo"};

View File

@ -0,0 +1,157 @@
/*
This file is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_stdlib.c
Author: Raymond Chen
Function: This file contains the C standard library functions used by anagram.
Source: anagram
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#include "anagram_stdlib.h"
#include "anagram_strings.h"
/* Includes anagram_CompareFrequency */
/* This function is included here because the WCC does not */
/* support function pointers */
#include "anagram_compare.h"
void
anagram_swapi(char *ii, char *ij, unsigned long es) {
char *i, *j, c;
i = (char *) ii;
j = (char *) ij;
_Pragma("loopbound min 4 max 4") do {
c = *i;
*i++ = *j;
*j++ = c;
es -= sizeof(char);
}
while (es != 0)
;
}
char *
anagram_pivot(char *a, unsigned long n, unsigned long es) {
unsigned long j;
char *pi, *pj, *pk;
j = n / 6 * es;
pi = a + j; /* 1/6 */
// Wasm loop bounds
__attribute__((import_module("__pragma"),
import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
j += j;
pj = pi + j; /* 1/2 */
pk = pj + j; /* 5/6 */
if (anagram_CompareFrequency(pi, pj) < 0) {
if (anagram_CompareFrequency(pi, pk) < 0) {
if (anagram_CompareFrequency(pj, pk) < 0)
return pj;
return pk;
}
return pi;
}
if (anagram_CompareFrequency(pj, pk) < 0) {
if (anagram_CompareFrequency(pi, pk) < 0)
return pi;
return pk;
}
return pj;
}
void
anagram_qsorts(char *a, unsigned long n, unsigned long es) {
unsigned long j;
char *pi, *pj, *pn;
volatile unsigned int flowfactdummy = 0;
__pragma_loopbound(0, 3);
while (n > 1) {
if (n > 10)
pi = anagram_pivot(a, n, es);
else
pi = a + (n >> 1) * es;
anagram_swapi(a, pi, es);
pi = a;
pn = a + n * es;
pj = pn;
__pragma_loopbound(0, 10);
while (1) {
/* wcc note: this assignment expression was added to avoid
assignment of multiple loop bound annotations to same loop (cf.
Ticket #0002323). */
flowfactdummy++;
__pragma_loopbound(1, 6);
do {
pi += es;
} while (pi < pn && anagram_CompareFrequency(pi, a) < 0);
__pragma_loopbound(1, 7);
do {
pj -= es;
} while (pj > a && anagram_CompareFrequency(pj, a) > 0);
if (pj < pi)
break;
anagram_swapi(pi, pj, es);
}
anagram_swapi(a, pj, es);
j = (unsigned long) (pj - a) / es;
n = n - j - 1;
if (j >= n) {
anagram_qsorts(a, j, es);
a += (j + 1) * es;
} else {
anagram_qsorts(a + (j + 1) * es, n, es);
n = j;
}
}
}
void
anagram_qsort(void *va, unsigned long n, unsigned long es) {
_Pragma("marker call_qsorts") anagram_qsorts((char *) va, n, es);
_Pragma("flowrestriction 1*anagram_qsorts <= 17*call_qsorts");
}
/* This must be redefined for each new benchmark */
#define ANAGRAM_HEAP_SIZE 21000
static char anagram_simulated_heap[ANAGRAM_HEAP_SIZE];
static unsigned int anagram_freeHeapPos;
void *
anagram_malloc(unsigned int numberOfBytes) {
void *currentPos = (void *) &anagram_simulated_heap[anagram_freeHeapPos];
/* Get a 4-byte address for alignment purposes */
// anagram_freeHeapPos += ( ( numberOfBytes + 4 ) & ( unsigned int
// )0xfffffffc );
unsigned int rem = (numberOfBytes & (unsigned int) 0x3);
unsigned int adjustment = rem ? 4 - rem : 0;
anagram_freeHeapPos += numberOfBytes + adjustment;
return currentPos;
}
void
anagram_bzero(char *p, unsigned long len) {
unsigned long i;
__pragma_loopbound(8, 800);
for (i = 0; i < len; ++i) {
*p++ = '\0';
}
}

View File

@ -0,0 +1,30 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_stdlib.h
Author: Raymond Chen
Function: This header contains some C standard library functions used by
anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_STDLIB_H
#define ANAGRAM_STDLIB_H
void *anagram_malloc(unsigned int numberOfBytes);
void anagram_qsort(void *va, unsigned long n, unsigned long es);
#endif

View File

@ -0,0 +1,28 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_strings.h
Author: Raymond Chen
Function: This header contains some C standard library functions used by
anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_STRINGS_H
#define ANAGRAM_STRINGS_H
void anagram_bzero(char *p, unsigned long len);
#endif

View File

@ -0,0 +1,661 @@
/*
This program is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram
Author: Raymond Chen
Function: A program that computes anagrams.
Source: See below.
Original name: anagram
Changes: See ChangeLog.txt
License: See below.
*/
/*
Anagram program by Raymond Chen,
inspired by a similar program by Brian Scearce
This program is Copyright 1991 by Raymond Chen.
(rjc@math.princeton.edu)
This program may be freely distributed provided all alterations
to the original are clearly indicated as such.
*/
/* There are two tricks. First is the Basic Idea:
When the user types in a phrase, the phrase is first preprocessed to
determine how many of each letter appears. A bit field is then constructed
dynamically, such that each field is large enough to hold the next power
of two larger than the number of times the character appears. For example,
if the phrase is hello, world, the bit field would be
00 00 00 000 000 00 00
d e h l o r w
The phrase hello, world, itself would be encoded as
01 01 01 011 010 01 01
d e h l o r w
and the word hollow would be encoded as
00 00 01 010 010 00 01
d e h l o r w
The top bit of each field is set in a special value called the sign.
Here, the sign would be
10 10 10 100 100 10 10
d e h l o r w
The reason for packing the values into a bit field is that the operation
of subtracting out the letters of a word from the current phrase can be
carried out in parallel. for example, subtracting the word hello from
the phrase hello, world, is merely
d e h l o r w
01 01 01 011 010 01 01 (dehllloorw)
- 00 00 01 010 010 00 01 (hlloow)
========================
01 01 00 001 000 01 00 (delr)
Since none of the sign bits is set, the word fits, and we can continue.
Suppose the next word we tried was hood.
d e h l o r w
01 01 00 001 000 01 00 (delr)
- 01 00 01 000 010 00 00 (hood)
========================
00 00 11 000 110 01 00
^ ^
A sign bit is set. (Two, actually.) This means that hood does not
fit in delr, so we skip it and try another word. (Observe that
when a sign bit becomes set, it screws up the values for the letters to
the left of that bit, but that's not important.)
The inner loop of an anagram program is testing to see if a
word fits in the collection of untried letters. Traditional methods
keep an array of 26 integers, which are then compared in turn. This
means that there are 26 comparisons per word.
This method reduces the number of comparisons to MAX_QUAD, typically 2.
Instead of looping through an array, we merely perform the indicated
subtraction and test if any of the sign bits is set.
*/
/* The nuts and bolts:
The dictionary is loaded and preprocessed. The preprocessed dictionary
is a concatenation of copies of the structure:
struct dictword {
char bStructureSize; -- size of this structure
char cLetters; -- number of letters in the word
char achWord[]; -- the word itself (0-terminated)
}
Since this is a variable-sized structure, we keep its size in the structure
itself for rapid stepping through the table.
When a phrase is typed in, it is first preprocessed as described in the
Basic Idea. We then go through the dictionary, testing each word. If
the word fits in our phrase, we build the bit field for its frequency
table and add it to the list of candidates.
*/
/*
The Second Trick:
Before diving into our anagram search, we then tabulate how many times
each letter appears in our list of candidates, and sort the table, with
the rarest letter first.
We then do our anagram search.
Like most anagram programs, this program does a depth-first search.
Although most anagram programs do some sort of heuristics to decide what
order to place words in the list_of_candidates, the search itself proceeds
according to a greedy algorithm. That is, once you find a word that fits,
subtract it and recurse.
This anagram program exercises some restraint and does not march down
every branch that shows itself. Instead, it only goes down branches
that use the rarest unused letter. This helps to find dead ends faster.
FindAnagram(unused_letters, list_of_candidates) {
l = the rarest letter as yet unused
For word in list_of_candidates {
if word does not fit in unused_letters, go on to the next word.
if word does not contain l, defer.
FindAnagram(unused_letters - word, list_of_candidates[word,...])
}
}
The heuristic of the Second Trick can probably be improved. I invite
anyone willing to improve it to do so.
*/
/* Before compiling, make sure Quad and MASK_BITS are set properly. For best
results, make Quad the largest integer size supported on your machine.
So if your machine has long longs, make Quad an unsigned long long.
(I called it Quad because on most machines, the largest integer size
supported is a four-byte unsigned long.)
If you need to be able to anagram larger phrases, increase MAX_QUADS.
If you increase it beyond 4, you'll have to add a few more loop unrolling
steps to FindAnagram.
*/
#include "anagram_ctype.h"
#include "anagram_stdlib.h"
#include "anagram_strings.h"
#include "anagram_compare.h"
/*
Defines
*/
// Wasm loop bounds
#include "anagram_input.c"
#include "anagram_stdlib.c"
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
#define anagram_DICTWORDS 2279
#define anagram_MASK_BITS 32 /* number of bits in a Quad */
#define anagram_MAX_QUADS 2 /* controls largest phrase */
#define anagram_MAXCAND 100 /* candidates */
#define anagram_MAXSOL 51 /* words in the solution */
#define anagram_ALPHABET 26 /* letters in the alphabet */
#define anagram_OneStep(i) \
if ((aqNext[i] = pqMask[i] - pw->aqMask[i]) & anagram_aqMainSign[i]) { \
ppwStart++; \
continue; \
}
/*
Type definitions
*/
typedef unsigned int anagram_Quad; /* for building our bit mask */
/* A Word remembers the information about a candidate word. */
typedef struct {
char *pchWord; /* the word itself */
anagram_Quad aqMask[anagram_MAX_QUADS]; /* the word's mask */
unsigned cchLength; /* letters in the word */
char padding[4];
} anagram_Word;
typedef anagram_Word *anagram_PWord;
typedef anagram_Word **anagram_PPWord;
/* A Letter remembers information about each letter in the phrase to
be anagrammed. */
typedef struct {
unsigned uFrequency; /* how many times it appears */
unsigned uShift; /* how to mask */
unsigned uBits; /* the bit mask itself */
unsigned iq; /* which Quad to inspect? */
} anagram_Letter;
typedef anagram_Letter *anagram_PLetter;
/*
Forward declaration of functions
*/
__attribute__((always_inline)) static inline void anagram_init(void);
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
anagram_main(void);
__attribute__((always_inline)) static inline int anagram_return(void);
__attribute__((always_inline)) static inline int anagram_ch2i(int ch);
__attribute__((always_inline)) static inline void anagram_AddWords(void);
__attribute__((always_inline)) static inline void
anagram_BuildMask(char const *pchPhrase);
__attribute__((always_inline)) static inline void
anagram_BuildWord(char *pchWord);
__attribute__((always_inline)) static inline void anagram_DumpWords(void);
__attribute__((always_inline)) static inline void
anagram_FindAnagram(anagram_Quad *pqMask, anagram_PPWord ppwStart, int iLetter);
__attribute__((always_inline)) static inline anagram_PWord
anagram_NewWord(void);
__attribute__((always_inline)) static inline anagram_PWord
anagram_NextWord(void);
__attribute__((always_inline)) static inline void anagram_ReadDict(void);
__attribute__((always_inline)) static inline void anagram_Reset(void);
__attribute__((always_inline)) static inline void anagram_SortCandidates(void);
/*
Declaration of global variables
*/
extern char const *anagram_achPhrase[3];
extern char const *anagram_dictionary[anagram_DICTWORDS];
/* candidates we've found so far */
static anagram_PWord anagram_apwCand[anagram_MAXCAND];
/* how many of them? */
static unsigned anagram_cpwCand;
/* statistics on the current phrase */
static anagram_Letter anagram_alPhrase[anagram_ALPHABET];
/* number of letters in phrase */
static int anagram_cchPhraseLength;
/* the bit field for the full phrase */
static anagram_Quad anagram_aqMainMask[anagram_MAX_QUADS];
/* where the sign bits are */
static anagram_Quad anagram_aqMainSign[anagram_MAX_QUADS];
static const int anagram_cchMinLength = 3;
/* auGlobalFrequency counts the number of times each letter appears,
summed over all candidate words. This is used to decide which letter
to attack first. */
static unsigned anagram_auGlobalFrequency[anagram_ALPHABET];
static int anagram_achByFrequency[anagram_ALPHABET]; /* for sorting */
/* the dictionary is read here */
static char *anagram_pchDictionary;
/* the answers */
static anagram_PWord anagram_apwSol[anagram_MAXSOL];
static int anagram_cpwLast;
/* buffer to write an answer */
static char anagram_buffer[30];
/*
Initialization- and return-value-related functions
*/
/* ReadDict -- read the dictionary file into memory and preprocess it
A word of length cch in the dictionary is encoded as follows:
byte 0 = cch + 3
byte 1 = number of letters in the word
byte 2... = the word itself, null-terminated
Observe that cch+3 is the length of the total encoding. These
byte streams are concatenated, and terminated with a 0.
*/
__attribute__((always_inline)) static inline void
anagram_ReadDict(void) {
char *pch;
char *pchBase;
unsigned len;
unsigned cWords = 0;
unsigned cLetters;
int i;
volatile char bitmask = 0;
len = 0;
__pragma_loopbound(2279, 2279);
for (i = 0; i < anagram_DICTWORDS; i++) {
unsigned strlen = 0;
__pragma_loopbound(1, 5);
while (anagram_dictionary[i][strlen] != 0)
strlen++;
len += strlen + 3;
}
len++;
pchBase = anagram_pchDictionary = (char *) anagram_malloc(len);
__pragma_loopbound(2279, 2279);
for (i = 0; i < anagram_DICTWORDS; i++) {
int index = 0;
pch = pchBase + 2; /* reserve for length */
cLetters = 0;
__pragma_loopbound(1, 5);
while (anagram_dictionary[i][index] != '\0') {
if (anagram_isalpha(anagram_dictionary[i][index]))
cLetters++;
*pch++ = anagram_dictionary[i][index];
index++;
*(pch - 1) ^= bitmask;
}
*pch++ = '\0';
*pchBase = (char) (pch - pchBase);
pchBase[1] = (char) cLetters;
pchBase = pch;
cWords++;
}
*pchBase++ = 0;
}
__attribute__((always_inline)) static inline void
anagram_init(void) {
anagram_ReadDict();
}
__attribute__((always_inline)) static inline int
anagram_return(void) {
int i;
char const *answer = "duke yip arm";
_Pragma(
"loopbound min 12 max 12") for (i = 0; i < 12;
i++) if (answer[i] !=
anagram_buffer[i]) return 1;
return 0;
}
/*
Core benchmark functions
*/
/* convert letter to index */
__attribute__((always_inline)) static inline int
anagram_ch2i(int ch) {
return ch - 'a';
}
__attribute__((always_inline)) static inline int
anagram_CompareFrequency(char *pch1, char *pch2) {
return anagram_auGlobalFrequency[(*(int *) pch1)] <
anagram_auGlobalFrequency[(*(int *) pch2)]
? -1
: anagram_auGlobalFrequency[(*(int *) pch1)] ==
anagram_auGlobalFrequency[(*(int *) pch2)]
? 0
: 1;
}
__attribute__((always_inline)) static inline void
anagram_Reset(void) {
anagram_bzero((char *) anagram_alPhrase,
sizeof(anagram_Letter) * anagram_ALPHABET);
anagram_bzero((char *) anagram_aqMainMask,
sizeof(anagram_Quad) * anagram_MAX_QUADS);
anagram_bzero((char *) anagram_aqMainSign,
sizeof(anagram_Quad) * anagram_MAX_QUADS);
anagram_bzero((char *) anagram_auGlobalFrequency,
sizeof(unsigned) * anagram_ALPHABET);
anagram_bzero((char *) anagram_achByFrequency,
sizeof(int) * anagram_ALPHABET);
anagram_bzero((char *) anagram_apwCand,
sizeof(anagram_PWord) * anagram_MAXCAND);
anagram_cchPhraseLength = 0;
anagram_cpwCand = 0;
}
__attribute__((always_inline)) static inline void
anagram_BuildMask(char const *pchPhrase) {
int i;
int ch;
unsigned iq; /* which Quad? */
unsigned int cbtUsed; /* bits used in the current Quad */
unsigned int cbtNeed; /* bits needed for current letter */
anagram_Quad qNeed; /* used to build the mask */
/* Tabulate letter frequencies in the phrase */
anagram_cchPhraseLength = 0;
__pragma_loopbound(11, 11);
while ((ch = *pchPhrase++) != '\0') {
if (anagram_isalpha(ch)) {
ch = anagram_tolower(ch);
anagram_alPhrase[anagram_ch2i(ch)].uFrequency++;
anagram_cchPhraseLength++;
}
}
/* Build masks */
iq = 0; /* which quad being used */
cbtUsed = 0; /* bits used so far */
__pragma_loopbound(26, 26);
for (i = 0; i < anagram_ALPHABET; i++) {
if (anagram_alPhrase[i].uFrequency == 0) {
anagram_auGlobalFrequency[i] = ~0u; /* to make it sort last */
} else {
anagram_auGlobalFrequency[i] = 0u;
_Pragma(
"loopbound min 1 max 2") for (cbtNeed = 1, qNeed = 1;
anagram_alPhrase[i].uFrequency >=
qNeed;
cbtNeed++, qNeed <<= 1);
if (cbtUsed + cbtNeed > anagram_MASK_BITS)
cbtUsed = 0;
anagram_alPhrase[i].uBits = qNeed - 1;
if (cbtUsed)
qNeed <<= cbtUsed;
anagram_aqMainSign[iq] |= qNeed;
anagram_aqMainMask[iq] |=
(anagram_Quad) anagram_alPhrase[i].uFrequency << cbtUsed;
anagram_alPhrase[i].uShift = cbtUsed;
anagram_alPhrase[i].iq = iq;
cbtUsed += cbtNeed;
}
}
}
__attribute__((always_inline)) static inline anagram_PWord
anagram_NewWord(void) {
anagram_PWord pw;
pw = (anagram_Word *) anagram_malloc(sizeof(anagram_Word));
return pw;
}
/* NextWord -- get another candidate entry, creating if necessary */
__attribute__((always_inline)) static inline anagram_PWord
anagram_NextWord(void) {
anagram_PWord pw;
pw = anagram_apwCand[anagram_cpwCand++];
if (pw != 0)
return pw;
anagram_apwCand[anagram_cpwCand - 1] = anagram_NewWord();
return anagram_apwCand[anagram_cpwCand - 1];
}
/* BuildWord -- build a Word structure from an ASCII word
If the word does not fit, then do nothing. */
__attribute__((always_inline)) static inline void
anagram_BuildWord(char *pchWord) {
unsigned char cchFrequency[anagram_ALPHABET];
int i;
char *pch = pchWord;
anagram_PWord pw;
unsigned int cchLength = 0;
anagram_bzero((char *) cchFrequency,
sizeof(unsigned char) * anagram_ALPHABET);
/* Build frequency table */
__pragma_loopbound(3, 5);
while ((i = *pch++) != '\0') {
if (!anagram_isalpha(i))
continue;
i = anagram_ch2i(anagram_tolower(i));
if (++cchFrequency[i] > anagram_alPhrase[i].uFrequency)
return;
++cchLength;
}
/* Update global count */
__pragma_loopbound(26, 26);
for (i = 0; i < anagram_ALPHABET; i++)
anagram_auGlobalFrequency[i] += cchFrequency[i];
/* Create a Word structure and fill it in, including building the
bitfield of frequencies. */
pw = anagram_NextWord();
anagram_bzero((char *) (pw->aqMask),
sizeof(anagram_Quad) * anagram_MAX_QUADS);
pw->pchWord = pchWord;
pw->cchLength = cchLength;
__pragma_loopbound(26, 26);
for (i = 0; i < anagram_ALPHABET; i++) {
pw->aqMask[anagram_alPhrase[i].iq] |= (anagram_Quad) cchFrequency[i]
<< anagram_alPhrase[i].uShift;
}
}
/* AddWords -- build the list of candidates */
__attribute__((always_inline)) static inline void
anagram_AddWords(void) {
char *pch = anagram_pchDictionary; /* walk through the dictionary */
anagram_cpwCand = 0;
__pragma_loopbound(1967, 1967);
while (*pch) {
if ((pch[1] >= anagram_cchMinLength &&
pch[1] + anagram_cchMinLength <= anagram_cchPhraseLength) ||
pch[1] == anagram_cchPhraseLength)
anagram_BuildWord(pch + 2);
pch += *pch;
}
}
__attribute__((always_inline)) static inline void
anagram_DumpWords(void) {
int i, j;
int offset = 0;
__pragma_loopbound(3, 3);
for (i = 0; i < anagram_cpwLast; i++) {
__pragma_loopbound(3, 5);
for (j = 0; anagram_apwSol[i]->pchWord[j] != '\0'; j++)
anagram_buffer[offset + j] = anagram_apwSol[i]->pchWord[j];
offset += j;
anagram_buffer[offset++] = ' ';
}
anagram_buffer[offset++] = '\0';
}
__attribute__((always_inline)) static inline void
anagram_FindAnagram(anagram_Quad *pqMask, anagram_PPWord ppwStart,
int iLetter) {
anagram_Quad aqNext[anagram_MAX_QUADS];
register anagram_PWord pw;
anagram_Quad qMask;
unsigned iq;
anagram_PPWord ppwEnd = &anagram_apwCand[0];
ppwEnd += anagram_cpwCand;
__pragma_loopbound(0, 6);
while (1) {
iq = anagram_alPhrase[anagram_achByFrequency[iLetter]].iq;
qMask = anagram_alPhrase[anagram_achByFrequency[iLetter]].uBits
<< anagram_alPhrase[anagram_achByFrequency[iLetter]].uShift;
if (pqMask[iq] & qMask)
break;
iLetter++;
}
__pragma_loopbound(0, 11);
while (ppwStart < ppwEnd) {
pw = *ppwStart;
#if anagram_MAX_QUADS > 0
anagram_OneStep(0);
#endif
#if anagram_MAX_QUADS > 1
anagram_OneStep(1);
#endif
#if anagram_MAX_QUADS > 2
anagram_OneStep(2);
#endif
#if anagram_MAX_QUADS > 3
anagram_OneStep(3);
#endif
#if anagram_MAX_QUADS > 4
@@"Add more unrolling steps here, please." @ @
#endif
/* If the pivot letter isn't present, defer this word until later */
if ((pw->aqMask[iq] & qMask) == 0) {
*ppwStart = *(--ppwEnd);
*ppwEnd = pw;
continue;
}
/* If we get here, this means the word fits. */
anagram_apwSol[anagram_cpwLast++] = pw;
if (anagram_cchPhraseLength -= pw->cchLength) { /* recurse */
/* The recursive call scrambles the tail, so we have to be
pessimistic. */
ppwEnd = &anagram_apwCand[0];
ppwEnd += anagram_cpwCand;
anagram_FindAnagram(&aqNext[0], ppwStart, iLetter);
} else /* found one */
anagram_DumpWords();
anagram_cchPhraseLength += pw->cchLength;
--anagram_cpwLast;
ppwStart++;
continue;
}
}
__attribute__((always_inline)) static inline void
anagram_SortCandidates(void) {
int i;
/* Sort the letters by frequency */
__pragma_loopbound(26, 26);
for (i = 0; i < anagram_ALPHABET; i++)
anagram_achByFrequency[i] = i;
anagram_qsort(anagram_achByFrequency, anagram_ALPHABET, sizeof(int));
}
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
anagram_main(void) {
int i;
__pragma_loopbound(3, 3);
for (i = 0; i < 3; i++) {
anagram_Reset();
anagram_BuildMask(anagram_achPhrase[i]);
anagram_AddWords();
if (anagram_cpwCand == 0 || anagram_cchPhraseLength == 0)
continue;
anagram_cpwLast = 0;
anagram_SortCandidates();
_Pragma("marker call_find")
anagram_FindAnagram(anagram_aqMainMask, anagram_apwCand, 0);
_Pragma("flowrestriction 1*anagram_FindAnagram <= 51*call_find");
}
}
/*
Main function
*/
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
anagram_init();
anagram_main();
return anagram_return();
}

View File

@ -0,0 +1,28 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_compare.h
Author: Raymond Chen
Function: This header contains the comparison functions used by anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_COMPARE_H
#define ANAGRAM_COMPARE_H
__attribute__((always_inline)) static inline int
anagram_CompareFrequency(char *pch1, char *pch2);
#endif

View File

@ -0,0 +1,45 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_ctype.h
Author: Raymond Chen
Function: This header contains some C library functions used by anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_CTYPE_H
#define ANAGRAM_CTYPE_H
__attribute__((always_inline)) static inline int
anagram_islower(int c) {
return 'a' <= c && c <= 'z';
}
__attribute__((always_inline)) static inline int
anagram_isupper(int c) {
return 'A' <= c && c <= 'Z';
}
__attribute__((always_inline)) static inline int
anagram_isalpha(int c) {
return anagram_isupper(c) || anagram_islower(c);
}
__attribute__((always_inline)) static inline int
anagram_tolower(int c) {
return anagram_isupper(c) ? c + ('a' - 'A') : c;
}
#endif

View File

@ -0,0 +1,320 @@
/*
This file is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_input.c
Author: Raymond Chen
Function: This file contains the input data used by anagram.
Source: anagram
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
/*
Forward declaration of global variables
*/
extern char const *anagram_achPhrase[3];
extern char const *anagram_dictionary[2279];
/*
Definition of global variables
*/
char const *anagram_achPhrase[3] = {"todd austin", "john alledy",
"mary updike"};
char const *anagram_dictionary[2279] = {
"2nd", "4th", "8th", "a", "ABA", "aback", "abash", "abbas",
"abbey", "abed", "abet", "abort", "abut", "Accra", "ACM", "acorn",
"Acts", "Ada", "adapt", "added", "addle", "Adele", "Aden", "admix",
"adore", "adult", "affix", "afire", "aft", "agate", "agave", "Agee",
"agent", "agile", "Agnew", "agone", "ahoy", "Aida", "aim", "Ainu",
"airy", "Ajax", "Alamo", "alarm", "alb", "Alcoa", "alder", "Aleck",
"alert", "algae", "alia", "alike", "alive", "allay", "alley", "Allis",
"allow", "ally", "Allyn", "aloe", "aloha", "along", "aloud", "also",
"alter", "Alton", "Alva", "amaze", "amber", "ami", "amigo", "amiss",
"Amman", "Amoco", "amok", "Amos", "ample", "amra", "amy", "Andes",
"angel", "Angie", "angry", "Angus", "Anne", "annex", "annoy", "annul",
"ante", "any", "apex", "apple", "apron", "apt", "arch", "argue",
"Aries", "arm", "army", "aroma", "array", "arrow", "Artie", "arty",
"arum", "a's", "ash", "ashen", "ashy", "askew", "assai", "Assam",
"Astor", "ate", "atlas", "atone", "audit", "Aug", "augur", "auk",
"aural", "avid", "avoid", "avow", "awash", "awe", "awn", "awry",
"axe", "axial", "axis", "axon", "Ayers", "Aztec", "b", "babe",
"Bach", "bad", "bait", "baldy", "balm", "balsa", "bam", "ban",
"bane", "banjo", "barb", "barn", "baron", "basal", "Basel", "basil",
"bassi", "baste", "batch", "Bates", "batik", "Bator", "bawd", "bay",
"bayed", "bayou", "be", "beak", "bean", "beard", "beat", "beck",
"Becky", "bed", "bedim", "bee", "beech", "beep", "beet", "befit",
"beg", "begin", "beige", "Bela", "belch", "belt", "beman", "bench",
"Benny", "bent", "Benz", "berth", "beset", "bet", "betel", "Bette",
"bevy", "Bible", "bide", "big", "bile", "bilk", "binge", "bit",
"bite", "black", "blanc", "bland", "blare", "blat", "blaze", "bled",
"blest", "blind", "Blinn", "bliss", "blitz", "blob", "blond", "blood",
"bloom", "blot", "blown", "blue", "bluff", "Blum", "blur", "board",
"boat", "bock", "bog", "bogy", "boil", "Boise", "bomb", "bon",
"bong", "bonus", "bonze", "booby", "book", "booky", "boon", "booze",
"bore", "Boris", "boron", "Bosch", "bosom", "bound", "bourn", "bowel",
"boy", "Boyce", "bract", "Brady", "brag", "brake", "brant", "brass",
"Braun", "bravo", "bread", "bream", "breve", "brew", "briar", "Brice",
"brief", "bring", "briny", "broad", "broth", "brunt", "BSTJ", "bub",
"buck", "Budd", "buddy", "Buick", "built", "bulge", "bulky", "bum",
"bump", "bunch", "bundy", "bunk", "Burch", "burg", "burl", "Burma",
"burnt", "Burr", "bury", "bush", "bushy", "bust", "busy", "butte",
"butyl", "buyer", "by", "bylaw", "Byrd", "byte", "cab", "cable",
"cacao", "cacti", "Cairo", "Caleb", "call", "calm", "canal", "canoe",
"canon", "can't", "cap", "caper", "capo", "card", "Carey", "Carib",
"Carla", "carol", "carve", "cash", "caste", "catch", "cater", "caulk",
"cause", "CBS", "cedar", "cent", "Cetus", "Chad", "chaff", "chair",
"champ", "char", "chasm", "chaw", "cheat", "cheer", "chef", "Chen",
"chew", "chick", "chief", "Chile", "chill", "chine", "chip", "chock",
"choir", "chomp", "chose", "Chris", "chuff", "chum", "chump", "CIA",
"cinch", "cite", "city", "clad", "clan", "clank", "Clara", "Claus",
"claw", "clean", "cleat", "clerk", "clime", "cling", "clink", "Clio",
"clod", "clomp", "cloth", "clove", "cluck", "clump", "clung", "Clyde",
"cobra", "coco", "coda", "Cody", "Cohn", "coin", "col", "Colby",
"coney", "Congo", "cony", "cool", "coon", "copra", "copy", "Corey",
"corn", "corps", "cos", "cosy", "couch", "cough", "count", "coup",
"cove", "cowry", "coy", "CPA", "crack", "craft", "Craig", "crank",
"crash", "crate", "crawl", "craze", "creak", "cream", "credo", "creek",
"Creon", "crept", "crest", "crew", "crib", "crime", "crimp", "crisp",
"crock", "croft", "crone", "crook", "crowd", "CRT", "crumb", "crump",
"crush", "crux", "cub", "cube", "cuff", "cup", "Cupid", "cur",
"curb", "curie", "cusp", "cute", "cycad", "cynic", "d", "daffy",
"dairy", "daisy", "dally", "dame", "Damon", "Dan", "dance", "Dane",
"dank", "Dante", "Dar", "darn", "dart", "dash", "davit", "day",
"De", "deaf", "deal", "death", "debit", "Dec", "decal", "Dee",
"Deere", "deify", "deity", "Della", "delta", "demur", "den", "Denny",
"dense", "deny", "depth", "desk", "deus", "devil", "dewar", "Dhabi",
"diary", "dick", "dicta", "did", "die", "Diego", "diety", "dill",
"din", "dine", "dirty", "disc", "ditch", "dive", "DNA", "dock",
"Dodd", "doff", "dogma", "dolce", "doll", "dolly", "done", "door",
"dope", "Doric", "dose", "dote", "doubt", "Doug", "dove", "dowel",
"doze", "Dr", "Draco", "drama", "drape", "drawl", "dread", "dreg",
"dress", "drew", "drib", "drier", "drill", "drip", "dross", "drown",
"druid", "drunk", "dry", "du", "Duane", "ducat", "duct", "duel",
"duff", "Duffy", "Dugan", "duke", "dull", "dulse", "duly", "dump",
"dumpy", "dunce", "dunk", "dupe", "dusky", "dwarf", "dwelt", "Dwyer",
"dyer", "Dyke", "dyne", "each", "eager", "ear", "earn", "ease",
"eat", "eater", "Eben", "Ecole", "Eden", "edge", "edgy", "edict",
"Edith", "EDT", "eel", "eft", "egg", "Egypt", "eject", "el",
"elan", "elate", "elect", "elfin", "elide", "elk", "Ella", "Ellis",
"Elmer", "else", "Elton", "elude", "elves", "ember", "Emile", "Emory",
"Eng", "Engle", "Enid", "Enos", "enter", "envoy", "epoxy", "equal",
"erase", "ere", "erg", "Erich", "Ernst", "Eros", "err", "Errol",
"Ervin", "e's", "essay", "ester", "Ethan", "Ethel", "ethic", "ethos",
"etude", "Eva", "Evans", "event", "evict", "exact", "exam", "excel",
"exit", "eye", "f", "Faber", "fable", "facet", "fad", "faery",
"fag", "fail", "faint", "fairy", "fake", "fang", "fare", "faro",
"fatal", "fatty", "fault", "faun", "Faust", "fay", "FBI", "fee",
"feed", "feign", "Felix", "Fermi", "ferry", "fest", "fetch", "fetus",
"few", "fiend", "fiery", "fifth", "fig", "fight", "filet", "film",
"finch", "fine", "finny", "fire", "first", "fish", "Fisk", "fist",
"Fitch", "flack", "flak", "flaky", "flame", "flank", "flare", "flat",
"flax", "flea", "fled", "flee", "fleet", "flint", "flit", "flock",
"flog", "flow", "Floyd", "flub", "fluke", "flute", "Flynn", "FM",
"foal", "focal", "Foley", "folk", "fond", "food", "foot", "fop",
"fore", "forge", "form", "fort", "forth", "forty", "Foss", "foul",
"fowl", "FPC", "frame", "Franz", "Frau", "fray", "freed", "fresh",
"friar", "fro", "frog", "from", "frost", "frown", "fry", "fuel",
"full", "fun", "fur", "furry", "fussy", "g", "gaff", "gag",
"Gail", "Galen", "gall", "game", "gamma", "gap", "gar", "garb",
"gas", "gasp", "gate", "gauge", "gaur", "gavel", "gawk", "gay",
"gecko", "gel", "gem", "Gemma", "gene", "genie", "genre", "genus",
"germ", "Gerry", "get", "giant", "gibby", "gig", "gild", "gilt",
"gin", "Gino", "given", "glare", "gleam", "glee", "glib", "glint",
"gloat", "glow", "glut", "GMT", "gnaw", "gnome", "GNP", "god",
"Goff", "gogo", "golf", "Goode", "goof", "goose", "gore", "gory",
"got", "gourd", "GPO", "grace", "Graff", "grape", "grasp", "grate",
"gravy", "graze", "grebe", "greed", "Greek", "Gregg", "grew", "grid",
"grime", "Grimm", "gripe", "grit", "groan", "gross", "grout", "grow",
"grown", "grub", "grunt", "GSA", "guano", "guess", "guide", "guile",
"guise", "gules", "gull", "gulp", "gumbo", "gun", "gunky", "guru",
"gush", "gust", "gusto", "guy", "Gwyn", "gyp", "gyro", "Habib",
"hack", "had", "Hades", "Hagen", "Hahn", "haiku", "hale", "halma",
"ham", "Haney", "Hans", "hard", "hare", "hark", "harm", "harsh",
"haste", "hasty", "hatch", "hater", "hawk", "Haydn", "hazel", "he",
"Healy", "hear", "heart", "heave", "heavy", "hedge", "heel", "hefty",
"Heinz", "held", "he'll", "hemp", "hertz", "hew", "hex", "hi",
"hick", "Hicks", "hike", "hilum", "hind", "hip", "hippy", "hire",
"his", "hive", "hobby", "hoc", "Hoff", "hogan", "Hokan", "hole",
"Holm", "holt", "home", "homo", "hondo", "hood", "hook", "hoop",
"hoot", "hope", "horn", "hose", "hot", "hound", "hovel", "how",
"howdy", "hub", "hubby", "hue", "huff", "huge", "huh", "hull",
"human", "Hun", "hung", "hunk", "hurt", "hurty", "hutch", "hydra",
"hyena", "hymen", "i", "ibid", "IBM", "icon", "I'd", "Idaho",
"ideal", "idiot", "idol", "IEEE", "iffy", "igloo", "iii", "ileum",
"Iliad", "ill", "Ilona", "image", "in", "inapt", "Inca", "incur",
"India", "inert", "infer", "infra", "Inman", "inn", "input", "ionic",
"Iowa", "ipso", "IR", "Iran", "irate", "Irene", "Irish", "Irma",
"is", "Ising", "Islam", "isle", "Italy", "it'd", "Ito", "iv",
"ivy", "j", "JACM", "jag", "James", "Jane", "Janos", "Japan",
"Jason", "jaw", "jean", "jeep", "Jeres", "jerky", "jess", "jet",
"jewel", "jig", "jilt", "Jo", "job", "jog", "join", "joke",
"jolt", "Jonas", "joule", "joust", "joy", "Juan", "judge", "judo",
"Judy", "juju", "juke", "julep", "jump", "junco", "junky", "junta",
"jure", "jut", "Kafka", "kapok", "Karp", "Kathy", "Kay", "Keats",
"keel", "keg", "kelly", "Kemp", "Kent", "Kenya", "kerry", "Kevin",
"keyed", "khaki", "Khmer", "kick", "Kiev", "kin", "Kiowa", "kirk",
"kiss", "kite", "kiva", "Klan", "Kline", "knee", "Knott", "Knox",
"koala", "Kong", "Korea", "kraft", "kraut", "Kuhn", "Kurd", "lac",
"lack", "lad", "ladle", "lag", "lain", "laity", "lam", "lame",
"lamp", "lance", "lane", "Lange", "Laos", "lapel", "lard", "Lares",
"Lars", "last", "late", "Latin", "latus", "law", "lay", "layup",
"lazy", "leach", "leafy", "leak", "leapt", "learn", "leash", "leave",
"ledge", "leech", "left", "leg", "leggy", "Leila", "lemma", "Lena",
"lens", "Leo", "Leona", "lest", "level", "levy", "lewd", "liar",
"lice", "lick", "lie", "lien", "life", "lift", "liken", "lilac",
"Lilly", "lily", "limb", "limit", "line", "lingo", "link", "Linus",
"Lise", "lisp", "live", "livre", "load", "loam", "loan", "lob",
"lobby", "local", "lock", "Loeb", "Logan", "logic", "loin", "Loki",
"loll", "Lomb", "long", "loon", "loose", "loot", "lope", "lord",
"Loren", "lose", "lossy", "Lotte", "loud", "lousy", "low", "Lowe",
"loy", "l's", "LTV", "Lucas", "lucky", "luge", "Luis", "lumen",
"lumpy", "lunar", "Lund", "Lura", "lure", "lurk", "lusty", "Lydia",
"lying", "Lynn", "Lyon", "Lyra", "m", "Mabel", "mace", "macho",
"macro", "madam", "magi", "magna", "mail", "main", "make", "Malay",
"male", "mall", "malt", "mamma", "mane", "mania", "manic", "manna",
"Mans", "Mao", "map", "mar", "Mardi", "maria", "Marin", "Mario",
"Mars", "Mary", "mask", "mast", "mat", "mate", "mater", "matte",
"maul", "Mavis", "maxim", "Maya", "Mayer", "Mayo", "mayst", "maze",
"me", "meal", "meaty", "media", "meet", "meld", "melt", "men",
"Menlo", "merge", "Merle", "merry", "mesh", "messy", "metro", "mew",
"Meyer", "mezzo", "mica", "midst", "mien", "mig", "mila", "milk",
"Mills", "milt", "Mimi", "mince", "mine", "mini", "mink", "minor",
"minot", "minus", "Mira", "mire", "mirth", "Missy", "misty", "mite",
"mitre", "mixup", "mob", "Mobil", "mock", "model", "Moen", "Mohr",
"moist", "molar", "mole", "month", "moody", "Moore", "moral", "Moran",
"morn", "Moser", "moss", "most", "motel", "moth", "motif", "motor",
"motto", "mousy", "Moyer", "Mrs", "m's", "mud", "muggy", "Muir",
"mulch", "mule", "mull", "mum", "mummy", "muon", "mural", "murre",
"mushy", "musk", "must", "Muzo", "my", "Myers", "mynah", "Myra",
"NAACP", "Nagy", "naive", "name", "Nancy", "nap", "nary", "nasal",
"natal", "NATO", "navy", "Nazi", "NBC", "NCR", "ne", "near",
"neath", "Ned", "need", "needy", "Nehru", "Nell", "neon", "Nero",
"net", "Neva", "neve", "new", "nice", "niche", "Niger", "night",
"Nikko", "Nile", "Niobe", "nitty", "NJ", "no", "Noah", "Nobel",
"nodal", "noise", "Nolan", "nolo", "noon", "nor", "nose", "notch",
"Nov", "now", "n's", "NTIS", "nude", "numb", "nurse", "NY",
"oaf", "oaken", "oar", "oasis", "oath", "obey", "objet", "ocean",
"Oct", "ode", "o'er", "off", "often", "ogle", "Okay", "old",
"oldy", "olive", "Olson", "omit", "once", "only", "onset", "onus",
"onyx", "ooze", "opera", "opium", "opt", "opus", "orb", "Orin",
"Orion", "osier", "ought", "our", "out", "ovate", "over", "Ovid",
"owing", "ox", "oxeye", "oxide", "Ozark", "p", "Pablo", "pace",
"pack", "pact", "padre", "pagan", "Paine", "pale", "palm", "pane",
"pansy", "Paoli", "papa", "papaw", "pappy", "parch", "pare", "Paris",
"park", "Parks", "parse", "Paso", "passe", "past", "path", "Patsy",
"Paul", "Pauli", "pax", "PBS", "peace", "peak", "Pease", "peck",
"pedal", "pee", "peek", "peep", "pen", "penny", "pep", "Pepsi",
"Perez", "perk", "Perle", "Perth", "peste", "Pete", "petri", "petty",
"pewee", "PhD", "phi", "phon", "phony", "phyla", "piano", "piece",
"pilot", "pinch", "ping", "pink", "pinto", "pious", "pipe", "pique",
"piss", "pithy", "pity", "pixy", "place", "plain", "plane", "plate",
"Plato", "play", "plaza", "plead", "pluck", "plug", "plump", "plunk",
"plus", "pod", "podia", "Poe", "poesy", "pogo", "poi", "poise",
"poke", "polis", "Polk", "poll", "polo", "Ponce", "pond", "pool",
"poop", "pop", "porch", "pork", "Porte", "Porto", "posh", "posse",
"post", "pour", "pow", "Prado", "Pratt", "pray", "press", "prey",
"price", "pride", "prig", "prime", "prior", "probe", "Prof", "prone",
"p's", "psych", "pub", "puck", "puffy", "Pugh", "pull", "puma",
"pun", "punky", "puny", "pupal", "puppy", "pure", "purl", "pus",
"PVC", "Pyle", "Pyrex", "Qatar", "quack", "quaff", "quash", "queen",
"quell", "query", "queue", "quick", "quill", "quint", "quirt", "quo",
"quote", "rabat", "rabbi", "radar", "radio", "radix", "Rae", "rag",
"rail", "rajah", "Ralph", "Ramo", "ran", "Rand", "randy", "Raoul",
"rape", "rare", "rasp", "rata", "rater", "rave", "raven", "razor",
"R&D", "reach", "ready", "real", "reb", "reck", "reedy", "reek",
"Reese", "regal", "Reid", "relax", "reman", "Rena", "rend", "ret",
"retch", "Rhea", "rheum", "rhino", "Rhoda", "rib", "rice", "rick",
"rid", "rifle", "rig", "rigid", "rill", "rim", "rimy", "rink",
"Rio", "rip", "ripen", "rise", "risk", "rite", "rival", "river",
"road", "roar", "rob", "robe", "robin", "rodeo", "roe", "roil",
"role", "Roman", "Rome", "romp", "roof", "room", "roost", "Rosen",
"rot", "rouge", "round", "rout", "rove", "Roy", "Royce", "r's",
"Ruben", "ruby", "rude", "Rudy", "rug", "rule", "rummy", "run",
"rung", "runt", "rupee", "ruse", "rusk", "Russo", "rusty", "Ruth",
"rutty", "Ryan", "rye", "sa", "sabra", "sad", "sag", "sage",
"sake", "sale", "Salk", "salty", "salve", "Sam", "same", "Samoa",
"sane", "sank", "Santa", "Sao", "sappy", "Sarah", "sari", "satyr",
"Saudi", "Sault", "save", "savvy", "SC", "scald", "scalp", "scarf",
"scat", "SCM", "scold", "scoot", "Scot", "scram", "scrub", "scud",
"scull", "scum", "SD", "seal", "seamy", "sect", "sedge", "seedy",
"seen", "seize", "semi", "sepal", "Sepoy", "septa", "serge", "serif",
"servo", "set", "Seton", "setup", "sewn", "shad", "shag", "shah",
"shaky", "shall", "shank", "shard", "Shari", "shaw", "Shea", "shed",
"sheer", "shied", "shift", "shill", "shin", "shirk", "shish", "shoo",
"shore", "shout", "shrew", "shrub", "shunt", "SIAM", "sib", "sibyl",
"side", "sigh", "sigma", "silk", "silly", "silt", "Simon", "since",
"sinew", "singe", "sinh", "Sioux", "sir", "siva", "sixty", "skeet",
"skew", "skid", "skimp", "skulk", "Skye", "slab", "slag", "slake",
"slap", "slay", "sleep", "sleet", "slick", "slim", "slimy", "slog",
"slosh", "sloth", "slow", "slug", "slum", "slung", "slurp", "sly",
"small", "smile", "smith", "smog", "smoky", "snack", "snark", "sneer",
"snell", "snip", "snoop", "snore", "snow", "snub", "snug", "so",
"soap", "soar", "soft", "soggy", "sold", "sole", "solid", "Solon",
"solve", "some", "son", "sonny", "soon", "sorb", "sore", "sort",
"south", "sow", "spa", "spade", "spare", "spark", "spasm", "spate",
"spawn", "spear", "speed", "spell", "Spica", "spicy", "spiky", "spire",
"Spiro", "splay", "spoil", "spook", "spool", "spore", "spout", "spree",
"sprue", "spur", "spy", "squaw", "s's", "St", "stag", "staid",
"stair", "stale", "stall", "stamp", "stand", "stark", "stash", "state",
"stay", "stead", "steak", "steam", "steed", "Steen", "steer", "stern",
"stew", "stile", "stilt", "stock", "stole", "stone", "stood", "stool",
"stop", "storm", "story", "stove", "strap", "straw", "strip", "strum",
"stud", "study", "stung", "stunt", "Sturm", "styli", "suave", "such",
"sud", "sue", "Suez", "suit", "sulky", "sung", "sunny", "sup",
"supra", "surge", "Sus", "sushi", "swank", "swap", "swear", "swelt",
"swig", "swine", "swish", "swiss", "sword", "swung", "Syria", "syrup",
"tab", "tabu", "tacit", "taffy", "Tahoe", "take", "tale", "talk",
"tamp", "tang", "tango", "tanh", "Tanya", "tap", "tape", "tapir",
"tappa", "tar", "tardy", "tarry", "task", "tasty", "tate", "tawny",
"taxi", "teach", "tease", "tecum", "Telex", "tempt", "tenon", "tense",
"tepid", "terry", "Tess", "Texas", "Thai", "than", "that", "Thea",
"thee", "them", "then", "theta", "they", "thick", "thigh", "thin",
"thing", "third", "three", "threw", "thug", "thus", "ti", "tibet",
"tic", "tid", "tidy", "tied", "tift", "til", "tile", "tilt",
"Timex", "Timon", "tinge", "tipsy", "tire", "tit", "tithe", "title",
"TNT", "toad", "today", "tog", "Togo", "toil", "token", "told",
"tome", "tommy", "tonal", "tong", "Toni", "tonk", "tony", "tool",
"tooth", "top", "tor", "torch", "tori", "torr", "torso", "torus",
"total", "totem", "tout", "tower", "town", "toxin", "track", "Tracy",
"trag", "trail", "trait", "tramp", "trap", "tread", "tree", "trend",
"tress", "trial", "tribe", "trill", "tripe", "troll", "troop", "trout",
"truck", "Trudy", "trunk", "trust", "TRW", "t's", "TTL", "tub",
"tube", "tuck", "Tudor", "tuft", "tulle", "tum", "tuna", "tune",
"tunic", "Turin", "turk", "turn", "tusk", "tutu", "tweak", "twice",
"twill", "twine", "twirl", "twit", "two", "tying", "ugly", "ultra",
"umbra", "uncle", "union", "unite", "upend", "upper", "upset", "Upton",
"urban", "urine", "us", "usage", "use", "USGS", "USIA", "usual",
"usurp", "Utah", "utile", "v", "vade", "vague", "vain", "valid",
"valve", "van", "vase", "vast", "Veda", "veer", "vein", "Vella",
"venom", "Venus", "verb", "Verde", "versa", "vest", "vetch", "vex",
"via", "vicar", "Vichy", "Vida", "vie", "Viet", "vigil", "viii",
"villa", "vise", "visor", "vitae", "Vito", "viva", "vixen", "vocal",
"voice", "Volta", "vowel", "v's", "w", "wack", "wacky", "wad",
"wade", "wafer", "wag", "wah", "wail", "wait", "waive", "waken",
"wale", "wally", "wan", "war", "ward", "ware", "warm", "warp",
"warty", "was", "washy", "water", "watt", "Watts", "way", "Wayne",
"weal", "wean", "wear", "web", "weber", "we'd", "wedge", "weed",
"week", "Wei", "weird", "Welch", "well", "welsh", "wept", "were",
"west", "wet", "wharf", "whee", "whelm", "when", "which", "whim",
"whir", "whisk", "white", "whiz", "whoa", "whole", "whoop", "whop",
"whose", "why", "widen", "widow", "wield", "Wier", "wile", "will",
"Wilma", "wilt", "win", "winch", "wino", "wipe", "wise", "wispy",
"witch", "withy", "witty", "woe", "wok", "wolve", "womb", "Wong",
"Woods", "wool", "wop", "wordy", "work", "worm", "worse", "worst",
"wove", "wow", "wreck", "wrest", "wrist", "Wu", "Wyatt", "Wylie",
"Wyner", "x", "xenon", "x's", "yacht", "Yale", "yam", "yang",
"yarn", "Yates", "year", "yeast", "Yeats", "Yemen", "yield", "yip",
"yodel", "yoga", "yoke", "yore", "you'd", "y's", "Yves", "YWCA",
"Zeiss", "zest", "zig", "zing", "zip", "Zoe", "zoo"};

View File

@ -0,0 +1,157 @@
/*
This file is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_stdlib.c
Author: Raymond Chen
Function: This file contains the C standard library functions used by anagram.
Source: anagram
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#include "anagram_stdlib.h"
#include "anagram_strings.h"
/* Includes anagram_CompareFrequency */
/* This function is included here because the WCC does not */
/* support function pointers */
#include "anagram_compare.h"
void
anagram_swapi(char *ii, char *ij, unsigned long es) {
char *i, *j, c;
i = (char *) ii;
j = (char *) ij;
_Pragma("loopbound min 4 max 4") do {
c = *i;
*i++ = *j;
*j++ = c;
es -= sizeof(char);
}
while (es != 0)
;
}
char *
anagram_pivot(char *a, unsigned long n, unsigned long es) {
unsigned long j;
char *pi, *pj, *pk;
j = n / 6 * es;
pi = a + j; /* 1/6 */
// Wasm loop bounds
__attribute__((import_module("__pragma"),
import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
j += j;
pj = pi + j; /* 1/2 */
pk = pj + j; /* 5/6 */
if (anagram_CompareFrequency(pi, pj) < 0) {
if (anagram_CompareFrequency(pi, pk) < 0) {
if (anagram_CompareFrequency(pj, pk) < 0)
return pj;
return pk;
}
return pi;
}
if (anagram_CompareFrequency(pj, pk) < 0) {
if (anagram_CompareFrequency(pi, pk) < 0)
return pi;
return pk;
}
return pj;
}
__attribute__((always_inline)) static inline void
anagram_qsorts(char *a, unsigned long n, unsigned long es) {
unsigned long j;
char *pi, *pj, *pn;
volatile unsigned int flowfactdummy = 0;
__pragma_loopbound(0, 3);
while (n > 1) {
if (n > 10)
pi = anagram_pivot(a, n, es);
else
pi = a + (n >> 1) * es;
anagram_swapi(a, pi, es);
pi = a;
pn = a + n * es;
pj = pn;
__pragma_loopbound(0, 10);
while (1) {
/* wcc note: this assignment expression was added to avoid
assignment of multiple loop bound annotations to same loop (cf.
Ticket #0002323). */
flowfactdummy++;
__pragma_loopbound(1, 6);
do {
pi += es;
} while (pi < pn && anagram_CompareFrequency(pi, a) < 0);
__pragma_loopbound(1, 7);
do {
pj -= es;
} while (pj > a && anagram_CompareFrequency(pj, a) > 0);
if (pj < pi)
break;
anagram_swapi(pi, pj, es);
}
anagram_swapi(a, pj, es);
j = (unsigned long) (pj - a) / es;
n = n - j - 1;
if (j >= n) {
anagram_qsorts(a, j, es);
a += (j + 1) * es;
} else {
anagram_qsorts(a + (j + 1) * es, n, es);
n = j;
}
}
}
__attribute__((always_inline)) static inline void
anagram_qsort(void *va, unsigned long n, unsigned long es) {
_Pragma("marker call_qsorts") anagram_qsorts((char *) va, n, es);
_Pragma("flowrestriction 1*anagram_qsorts <= 17*call_qsorts");
}
/* This must be redefined for each new benchmark */
#define ANAGRAM_HEAP_SIZE 21000
static char anagram_simulated_heap[ANAGRAM_HEAP_SIZE];
static unsigned int anagram_freeHeapPos;
__attribute__((always_inline)) static inline void *
anagram_malloc(unsigned int numberOfBytes) {
void *currentPos = (void *) &anagram_simulated_heap[anagram_freeHeapPos];
/* Get a 4-byte address for alignment purposes */
// anagram_freeHeapPos += ( ( numberOfBytes + 4 ) & ( unsigned int
// )0xfffffffc );
unsigned int rem = (numberOfBytes & (unsigned int) 0x3);
unsigned int adjustment = rem ? 4 - rem : 0;
anagram_freeHeapPos += numberOfBytes + adjustment;
return currentPos;
}
__attribute__((always_inline)) static inline void
anagram_bzero(char *p, unsigned long len) {
unsigned long i;
__pragma_loopbound(8, 800);
for (i = 0; i < len; ++i) {
*p++ = '\0';
}
}

View File

@ -0,0 +1,32 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_stdlib.h
Author: Raymond Chen
Function: This header contains some C standard library functions used by
anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_STDLIB_H
#define ANAGRAM_STDLIB_H
__attribute__((always_inline)) static inline void *
anagram_malloc(unsigned int numberOfBytes);
__attribute__((always_inline)) static inline void
anagram_qsort(void *va, unsigned long n, unsigned long es);
#endif

View File

@ -0,0 +1,29 @@
/*
This header is part of the TACLeBench benchmark suite.
Version 2.0
Name: anagram_strings.h
Author: Raymond Chen
Function: This header contains some C standard library functions used by
anagram.
Source: unknown
Original name: anagram
Changes: See ChangeLog.txt
License: See anagram.c
*/
#ifndef ANAGRAM_STRINGS_H
#define ANAGRAM_STRINGS_H
__attribute__((always_inline)) static inline void
anagram_bzero(char *p, unsigned long len);
#endif

View File

@ -0,0 +1,28 @@
# ~~~
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2026, Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU)
# ~~~
cmake_minimum_required(VERSION 3.20)
project(audiobeam)
set(TACLEBENCH_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../..")
set(REPOSITORY_ROOT_PATH "${CMAKE_CURRENT_LIST_DIR}/../../../..")
set(APP_TARGET_NAME "${CMAKE_PROJECT_NAME}")
if(DEFINED TACLEBENCH_VARIANT AND "${TACLEBENCH_VARIANT}" STREQUAL "inline")
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/inline/audiobeam.c")
else()
set(APP_SOURCE_FILE_PATH
"generated/modified_sources/default/audiobeam.c"
"generated/modified_sources/default/audiobeaminput.c"
"generated/modified_sources/default/audiobeamlibm.c"
"generated/modified_sources/default/audiobeamlibmalloc.c")
endif()
include(${REPOSITORY_ROOT_PATH}/cmake/taclebench_wasm.cmake)

View File

@ -0,0 +1,86 @@
Readme file for Oxygen beamforming source code distribution
-----------------------------------------------------------
This is a very very beta distribution of beamforming source code from
MIT LCS.
There is only one source file, main.c, and one header file,
main.h. You can compile everything using the Makefile included in the
distribution.
The input to the program is a text file containing floating
point values for the signal read on each of the microphones. For n
microphones, each line of the text files represents a temporal sample
and should contain n floating point values separated by spaces, e.g.:
-1.8569790e-004 -9.0919049e-004 3.6711283e-004 -1.0073081e-005 ...
There are several modes of operation for the program:
1. The most basic mode is to process the microphone data and to
calculate the output based on one beam focused on a particular point
in space. The coordinates for the microphones and the focus point are
specified inside main.c (eventually to be moved to a separate file).
2. Far field search mode. This mode assumes a far-field source (which
means we have a planar wavefront) and a linear array, and sweeps over
180 degrees in the plane of the array. The microphone coordinates are
specified in main.c, and the NUM_ANGLES constant defines how many
angle values should be tested (a value of 180 means one beam per each
degree). The energy of the signal over a particular window
(ANGLE_ENERGY_WINDOW_SIZE) is computed for each beam. The direction
with maximum energy is considered the direction that the speech signal
is coming from, and is printed out by the program.
3. Near-field hill climbing mode. This mode accepts a starting
coordinate and attempts to "hill-climb" through the space seeking the
maximum energy. Each of the x, y, and z coordinates are perturbed in
the positive and negative directions at each time interval
(GRID_ENERGY_WINDOW_SIZE) by a step size (GRID_STEP_SIZE). This
perturbation, along with the original coordinate, produces seven
coordinates to be tested. The direction with the maximum energy
replaces the current reference coordinate. For instance, if we have a
starting reference coordinate of (1,1,0) and our step size is 0.01, we
will evaluate the energy for the following seven beams:
(1,1,0)
(0.99,1,0)
(1.01,1,0)
(1,0.99,0)
(1,1.01,0)
(1,1,-0.01)
(1,1,0.01)
Now let's say the beam (1,1.01,0) has the maximum energy; then this
coordinate will replace the original reference coordinate of (1,1,0).
For methods 2, and 3, we are not outputting anything to disk, we are
just printing the result. This is because we have just started to work
with these methods, and have not applied them in real systems. This
code is currently being ported to RAW.
To get a list of parameters for the delay_and_sum executable that is
generated when the source is compiled, just type ./delay_and_sum .
There is some sample data included with the program, in the data
directory. There is some data for a near-field and far-field
source. The README.txt file in each directory specifies the microphone
and source position. The data1 file, when processed with a beamformer
aligned in the proper direction should produce something like a sinc
function (see
http://ccrma-www.stanford.edu/~jos/Interpolation/sinc_function.html).
The data2 file should produce an audio signal of a woman saying "the
simplest method". If the beamformer is aligned properly, the noise
should be reduced significantly over the source signal from only one
of the microphones (use print_datafile.pl to isolate one
microphone). You can convert the data file that the program produces
to wave files using sox.
---------------------------------
Eugene Weinstein
ecoder@mit.edu

View File

@ -0,0 +1,585 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeam
Author: Eugene Weinstein
Function: Audio beam former
Source: StreamIt
http://groups.csail.mit.edu/cag/streamit/
Changes: no functional changes
License: see license.txt
*/
/*
Include section
*/
#include "audiobeamlibm.h"
#include "audiobeamlibmalloc.h"
#include "audiobeam.h"
/*
Forward declaration of functions
*/
void audiobeam_init();
int audiobeam_return();
void audiobeam_main( void );
int main( void );
void audiobeam_preprocess_delays( struct audiobeam_PreprocessedDelays
prep_delays[ ], float *delays );
float *audiobeam_parse_line( float *float_arr, int num_mic );
long int audiobeam_find_max_in_arr( float *arr, int size );
long int audiobeam_find_min_in_arr( float *arr, int size );
int audiobeam_wrapped_inc_offset( int i, int offset, int max_i );
int audiobeam_wrapped_dec_offset( int i, int offset, int max_i );
int audiobeam_wrapped_inc( int i, int max_i );
int audiobeam_wrapped_dec( int i, int max_i );
struct audiobeam_DataQueue *audiobeam_init_data_queue( int max_delay,
int num_mic );
struct audiobeam_Delays *audiobeam_init_delays ( int num_angles, int num_mic );
void audiobeam_calc_distances( float *source_location,
float audiobeam_mic_locations[ 15 ][ 3 ],
float *distances,
int num_mic );
void audiobeam_calc_delays( float *distances, float *delays, int sound_speed,
int sampling_rate, int num_mic );
void audiobeam_adjust_delays( float *delays, int num_mic );
float *audiobeam_calc_weights_lr ( int num_mic );
float *audiobeam_calc_weights_left_only ( int num_mic );
float audiobeam_calculate_energy( float *samples, int num_samples );
float audiobeam_do_beamforming( struct audiobeam_PreprocessedDelays
preprocessed_delays[ ],
float **sample_queue,
int queue_head,
long int max_delay,
int num_mic,
float *weights );
int audiobeam_process_signal( struct audiobeam_Delays *delays, int num_mic,
float sampling_rate, float **beamform_results,
struct audiobeam_DataQueue *queue,
int num_beams, int window, float *weights );
int audiobeam_calc_beamforming_result( struct audiobeam_Delays *delays,
float **beamform_results,
float *energies,
struct audiobeam_DataQueue *queue,
int num_beams, int window,
int hamming );
void audiobeam_calc_single_pos( float source_location[ 3 ],
float audiobeam_mic_locations[ 15 ][ 3 ],
int hamming );
/*
Declaration of global variables
*/
extern float audiobeam_input[ 5760 ];
extern float audiobeam_mic_locations[ 15 ][ 3 ];
extern float audiobeam_source_location[ 3 ];
extern float audiobeam_origin_location[ 3 ];
int audiobeam_input_pos;
int audiobeam_checksum;
/*
Initialization- and return-value-related functions
*/
void audiobeam_init()
{
audiobeam_input_pos = 0;
audiobeam_checksum = 0;
unsigned int i;
unsigned char *p;
volatile char bitmask = 0;
/*
Apply volatile XOR-bitmask to entire input array.
*/
p = ( unsigned char * ) &audiobeam_input[ 0 ];
_Pragma( "loopbound min 23040 max 23040" )
for ( i = 0; i < sizeof( audiobeam_input ); ++i, ++p )
*p ^= bitmask;
p = ( unsigned char * ) &audiobeam_mic_locations[ 0 ];
_Pragma( "loopbound min 180 max 180" )
for ( i = 0; i < sizeof( audiobeam_mic_locations ); ++i, ++p )
*p ^= bitmask;
p = ( unsigned char * ) &audiobeam_source_location[ 0 ];
_Pragma( "loopbound min 12 max 12" )
for ( i = 0; i < sizeof( audiobeam_source_location ); ++i, ++p )
*p ^= bitmask;
p = ( unsigned char * ) &audiobeam_origin_location[ 0 ];
_Pragma( "loopbound min 12 max 12" )
for ( i = 0; i < sizeof( audiobeam_origin_location ); ++i, ++p )
*p ^= bitmask;
}
int audiobeam_return()
{
return ( audiobeam_checksum + 1 != 0 );
}
/*
Algorithm core functions
*/
void audiobeam_preprocess_delays( struct audiobeam_PreprocessedDelays
prep_delays[ ], float *delays )
{
int i;
_Pragma( "loopbound min 15 max 15" )
for ( i = 0; i < 15; i++ ) {
prep_delays[ i ].delay = delays[ i ];
prep_delays[ i ].high = ( int ) audiobeam_ceil( delays[ i ] );
prep_delays[ i ].low = ( int ) audiobeam_floor( delays[ i ] );
prep_delays[ i ].offset = delays[ i ] - prep_delays[ i ].low;
}
}
float *audiobeam_parse_line( float *float_arr, int num_mic )
{
int i;
_Pragma( "loopbound min 15 max 15" )
for ( i = 0; i < num_mic; i++ )
float_arr[ i ] = audiobeam_input[ audiobeam_input_pos++ ];
return float_arr;
}
long int audiobeam_find_max_in_arr( float *arr, int size )
{
int i;
float max = 0;
_Pragma( "loopbound min 15 max 15" )
for ( i = 0; i < size; i++ ) {
if ( arr[ i ] > max )
max = arr[ i ];
}
return audiobeam_ceil( max );
}
long int audiobeam_find_min_in_arr( float *arr, int size )
{
int i;
float min = arr[ 0 ];
_Pragma( "loopbound min 15 max 15" )
for ( i = 0; i < size; i++ ) {
if ( arr[ i ] < min )
min = arr[ i ];
}
return audiobeam_floor( min );
}
int audiobeam_wrapped_inc_offset( int i, int offset, int max_i )
{
if ( i + offset > max_i )
return ( i + offset - max_i - 1 );
else
return ( i + offset );
}
int audiobeam_wrapped_dec_offset( int i, int offset, int max_i )
{
if ( i - offset < 0 )
return ( max_i - ( offset - i ) + 1 );
else
return ( i - offset );
}
int audiobeam_wrapped_inc( int i, int max_i )
{
return audiobeam_wrapped_inc_offset( i, 1, max_i );
}
int audiobeam_wrapped_dec( int i, int max_i )
{
return audiobeam_wrapped_dec_offset( i, 1, max_i );
}
struct audiobeam_DataQueue *audiobeam_init_data_queue( int max_delay,
int num_mic )
{
int i, j;
struct audiobeam_DataQueue *queue;
queue = ( struct audiobeam_DataQueue * ) audiobeam_malloc( sizeof(
struct audiobeam_DataQueue ) );
queue->sample_queue = ( float ** ) audiobeam_malloc( ( max_delay + 1 )
* sizeof( float * ) );
_Pragma( "loopbound min 15 max 15" )
for ( i = 0; i < ( max_delay + 1 ); i++ ) {
( queue->sample_queue )[ i ] = ( float * ) audiobeam_malloc( num_mic
* sizeof( float ) );
_Pragma( "loopbound min 15 max 15" )
for ( j = 0; j < num_mic; j++ ) {
( queue->sample_queue )[ i ][ j ] = 0.0; // Initialize values to 0
}
}
queue->head = 0;
queue->tail = 0;
queue->full = 0;
return queue;
}
struct audiobeam_Delays *audiobeam_init_delays ( int num_angles, int num_mic )
{
struct audiobeam_Delays *delays;
int i;
delays = ( struct audiobeam_Delays * ) audiobeam_malloc( sizeof(
struct audiobeam_Delays ) );
// Initialize the delays array
delays->delay_values = ( float ** ) audiobeam_malloc( num_angles
* sizeof( float * ) );
_Pragma( "loopbound min 1 max 1" )
for ( i = 0; i < ( num_angles ); i++ ) {
delays->delay_values[ i ] = ( float * ) audiobeam_malloc( num_mic
* sizeof( float ) );
}
return delays;
}
void audiobeam_calc_distances( float *source_location,
float audiobeam_mic_locations[ 15 ][ 3 ],
float *distances,
int num_mic )
{
int i;
_Pragma( "loopbound min 15 max 15" )
for ( i = 0; i < num_mic; i++ ) {
distances[ i ] = ( audiobeam_sqrt( ( audiobeam_mic_locations[ i ][ 0 ]
- source_location[ 0 ] ) *
( audiobeam_mic_locations[ i ][ 0 ]
- source_location[ 0 ] ) +
( audiobeam_mic_locations[ i ][ 1 ]
- source_location[ 1 ] ) *
( audiobeam_mic_locations[ i ][ 1 ]
- source_location[ 1 ] ) +
( audiobeam_mic_locations[ i ][ 2 ]
- source_location[ 2 ] ) *
( audiobeam_mic_locations[ i ][ 2 ]
- source_location[ 2 ] ) ) );
}
}
void audiobeam_calc_delays( float *distances, float *delays, int sound_speed,
int sampling_rate, int num_mic )
{
int i;
_Pragma( "loopbound min 15 max 15" )
for ( i = 0; i < num_mic; i++ )
delays[ i ] = ( distances[ i ] / sound_speed ) * sampling_rate;
}
void audiobeam_adjust_delays( float *delays, int num_mic )
{
int i;
long int min_delay = audiobeam_find_min_in_arr ( delays, num_mic ) - 1;
_Pragma( "loopbound min 15 max 15" )
for ( i = 0; i < num_mic; i++ )
delays[ i ] -= min_delay;
}
float *audiobeam_calc_weights_lr ( int num_mic )
{
float *weights = ( float * ) audiobeam_malloc( num_mic * sizeof( float ) );
int index = 0;
int y, z;
int half = num_mic / 4;
_Pragma( "loopbound min 0 max 0" )
for ( z = 1; z >= -1; z -= 2 ) {
_Pragma( "loopbound min 0 max 0" )
for ( y = 0; y < half; y++ ) {
weights[ index ] = 0.54 + 0.46 * audiobeam_cos( audiobeam_M_PI * y
/ half );
index++;
}
_Pragma( "loopbound min 0 max 0" )
for ( y = 0; y < half; y++ ) {
weights[ index ] = 0.54 + 0.46 * audiobeam_cos( audiobeam_M_PI * ( -y )
/ half );
index++;
}
}
return weights;
}
float *audiobeam_calc_weights_left_only ( int num_mic )
{
float *weights = ( float * ) audiobeam_malloc( num_mic * sizeof( float ) );
int index = 0;
int y;
int half = num_mic / 2;
_Pragma( "loopbound min 15 max 15" )
for ( y = -half; y <= half; y++ ) {
weights[ index ] = 0.54 + 0.46 * audiobeam_cos( audiobeam_M_PI * y / half );
index++;
}
return weights;
}
float audiobeam_calculate_energy( float *samples, int num_samples )
{
int i;
float sum = 0.0;
_Pragma( "loopbound min 0 max 0" )
for ( i = 0; i < num_samples; i++ )
sum += ( samples[ i ] * samples[ i ] );
return sum;
}
float audiobeam_do_beamforming( struct audiobeam_PreprocessedDelays
preprocessed_delays[ ],
float **sample_queue,
int queue_head,
long int max_delay,
int num_mic,
float *weights )
{
int i;
float sum = 0;
int delay_floor;
int delay_ceil;
int low_index;
int high_index;
float interpolated_value;
// add up all the num_mic delayed samples
_Pragma( "loopbound min 15 max 15" )
for ( i = 0; i < num_mic; i++ ) {
delay_floor = preprocessed_delays[ i ].low;
delay_ceil = preprocessed_delays[ i ].high;
// Inline wrap around here
// Low index gets index of sample right before desired sample
low_index = queue_head + delay_floor;
if ( low_index > max_delay )
low_index -= ( max_delay + 1 );
// High index gets index of sample right after desired sample
high_index = queue_head + delay_ceil;
if ( high_index > max_delay )
high_index -= ( max_delay + 1 );
// i gives the value of the microphone we want. However, since
// the array only has microphones first_mic to last_mic, we
// need to offset our index by first_mic
interpolated_value = ( ( ( sample_queue[ high_index ][ i ] -
sample_queue[ low_index ][ i ] )
* ( preprocessed_delays[ i ].offset ) )
+ sample_queue[ low_index ][ i ] );
// If we have microphone weights, multiply the value by the weight
if ( weights != 0 )
sum += ( interpolated_value * weights[ i ] );
else
sum += interpolated_value;
}
return sum;
}
int audiobeam_process_signal( struct audiobeam_Delays *delays, int num_mic,
float sampling_rate, float **beamform_results,
struct audiobeam_DataQueue *queue,
int num_beams, int window, float *weights )
{
int i, j;
float time_index = 0;
float time_index_inc = ( 1.0 / sampling_rate );
float value;
int done = 0;
struct audiobeam_PreprocessedDelays preprocessed_delays[ 15 ];
audiobeam_preprocess_delays( preprocessed_delays, delays->delay_values[ 0 ] );
_Pragma( "loopbound min 13 max 13" )
for ( i = 0; i < delays->max_delay - 1; i++ ) {
if ( audiobeam_input_pos < 5760 )
audiobeam_parse_line( ( queue->sample_queue )[ queue->head ], 15 );
else
return -1;
queue->head = audiobeam_wrapped_inc( queue->head, delays->max_delay );
}
_Pragma( "loopbound min 371 max 371" )
for ( i = 0; ( i < window ) || ( window < 0 ) ; i++ ) {
if ( audiobeam_input_pos < 5760 )
audiobeam_parse_line( ( queue->sample_queue )[ queue->head ], 15 );
else {
done = 1;
break;
}
_Pragma( "loopbound min 1 max 1" )
for ( j = 0; j < num_beams; j++ ) {
value = audiobeam_do_beamforming( preprocessed_delays,
( queue->sample_queue ),
audiobeam_wrapped_inc( queue->head,
delays->max_delay ),
delays->max_delay, num_mic, weights );
value = value / num_mic;
if ( beamform_results != 0 )
beamform_results[ j ][ i ] = value;
}
queue->tail = queue->head;
queue->head = audiobeam_wrapped_inc( queue->head, delays->max_delay );
time_index += time_index_inc;
}
return ( done );
}
int audiobeam_calc_beamforming_result( struct audiobeam_Delays *delays,
float **beamform_results,
float *energies,
struct audiobeam_DataQueue *queue,
int num_beams, int window,
int hamming )
{
int i;
int done;
float *weights = 0;
if ( hamming ) {
if ( ( 15 % 2 ) == 1 )
weights = audiobeam_calc_weights_left_only( 15 );
else
weights = audiobeam_calc_weights_lr( 15 );
}
done = audiobeam_process_signal( delays, 15, 16000,
beamform_results,
queue, num_beams, window, weights );
if ( beamform_results != 0 ) {
_Pragma( "loopbound min 1 max 1" )
for ( i = 0; i < num_beams; i++ )
energies[ i ] = audiobeam_calculate_energy( beamform_results[ i ], window );
}
return done;
}
void audiobeam_calc_single_pos( float source_location[ 3 ],
float audiobeam_mic_locations[ 15 ][ 3 ],
int hamming )
{
float mic_distances[ 15 ];
struct audiobeam_Delays *delays = audiobeam_init_delays( 1, 15 );
struct audiobeam_DataQueue *queue;
float **beamform_results;
float *energies;
beamform_results = ( float ** ) audiobeam_malloc( 1 * sizeof( float * ) );
beamform_results[ 0 ] = ( float * ) audiobeam_malloc( 384 * sizeof( float ) );
energies = ( float * ) audiobeam_malloc( 1 * sizeof( float * ) );
// Calculate distances from source to each of mics
audiobeam_calc_distances( source_location, audiobeam_mic_locations,
mic_distances, 15 );
audiobeam_calc_delays( mic_distances,
delays->delay_values[ 0 ],
342, 16000, 15 );
audiobeam_adjust_delays( delays->delay_values[ 0 ], 15 );
delays->max_delay = audiobeam_find_max_in_arr ( delays->delay_values[ 0 ], 15 );
queue = audiobeam_init_data_queue( delays->max_delay, 15 );
audiobeam_calc_beamforming_result( delays, beamform_results,
energies, queue, 1, -1, hamming );
audiobeam_checksum += beamform_results[ 0 ][ 0 ] * 1000;
}
/*
Main functions
*/
void _Pragma( "entrypoint" ) audiobeam_main( void )
{
char hamming = 1;
audiobeam_calc_single_pos( audiobeam_source_location,
audiobeam_mic_locations,
hamming );
}
int main( void )
{
audiobeam_init();
audiobeam_main();
return ( audiobeam_return() );
}

View File

@ -0,0 +1,50 @@
#ifndef AUDIOBEAM_MAIN_H
#define AUDIOBEAM_MAIN_H
struct audiobeam_DataQueue {
float **sample_queue;
int head;
int tail;
unsigned char full;
};
struct audiobeam_Delays {
float **delay_values;
long int max_delay;
};
struct audiobeam_PreprocessedDelays {
float delay;
int low;
int high;
float offset;
};
#undef FLT_MAX
#define FLT_MAX 999e999
#define SOUND_SPEED 342
#define SAMPLING_RATE 16000
#define CARTESIAN_DISTANCE(x1,y1,z1,x2,y2,z2) (sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2)));
#define NUM_MIC 15
#define ANGLE_ENERGY_WINDOW_SIZE 400
#define GRID_STEP_SIZE 0.003 // .3cm
#define NUM_DIRS 7
#define NUM_TILES 16
#define MIC_HORIZ_SPACE 0.038257
#define MIC_VERT_SPACE 0.015001
#define TWO23 8388608.0 // 2^23
#define BUFFER_SIZE 384 // No of input-tupels (each with NUM_MIC elements)
#define NUM_MIC_IN_CHAIN 32
#define NUM_BOARDS_IN_CHAIN 16
#define INPUT_LENGTH 5760
#define INTERPOLATE(low_value, high_value, offset) (((high_value-low_value)*(offset)) + low_value)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,425 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeamlibm.c
Author: Ian Lance Taylor and J.T. Conklin
Function: IEEE754 software library routines.
Source: Sun Microsystems and Cygnus
Original name: Unknown
Changes: No major functional changes.
License: See the terms below.
*/
/*
====================================================
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Developed at SunPro, a Sun Microsystems, Inc. business.
Permission to use, copy, modify, and distribute this
software is freely granted, provided that this notice
is preserved.
====================================================
*/
#include "audiobeamlibm.h"
#include "audiobeamlibmath.h"
static const int audiobeam_npio2_hw[ ] = {
0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
0x4242c700, 0x42490f00
};
static const float
audiobeam_invpio2 = 6.3661980629e-01f, /* 0x3f22f984 */
audiobeam_pio2_1 = 1.5707855225e+00f, /* 0x3fc90f80 */
audiobeam_pio2_1t = 1.0804334124e-05f, /* 0x37354443 */
audiobeam_pio2_2 = 1.0804273188e-05f, /* 0x37354400 */
audiobeam_pio2_2t = 6.0770999344e-11f, /* 0x2e85a308 */
audiobeam_pio2_3 = 6.0770943833e-11f, /* 0x2e85a300 */
audiobeam_pio2_3t = 6.1232342629e-17f; /* 0x248d3132 */
static const float
audiobeam_C1 = 4.1666667908e-02f, /* 0x3d2aaaab */
audiobeam_C2 = -1.3888889225e-03f, /* 0xbab60b61 */
audiobeam_C3 = 2.4801587642e-05f, /* 0x37d00d01 */
audiobeam_C4 = -2.7557314297e-07f, /* 0xb493f27c */
audiobeam_C5 = 2.0875723372e-09f, /* 0x310f74f6 */
audiobeam_C6 = -1.1359647598e-11f; /* 0xad47d74e */
static const float
audiobeam_S1 = -1.6666667163e-01f, /* 0xbe2aaaab */
audiobeam_S2 = 8.3333337680e-03f, /* 0x3c088889 */
audiobeam_S3 = -1.9841270114e-04f, /* 0xb9500d01 */
audiobeam_S4 = 2.7557314297e-06f, /* 0x3638ef1b */
audiobeam_S5 = -2.5050759689e-08f, /* 0xb2d72f34 */
audiobeam_S6 = 1.5896910177e-10f; /* 0x2f2ec9d3 */
static const float
audiobeam_two25 = 3.355443200e+07f, /* 0x4c000000 */
audiobeam_twom25 = 2.9802322388e-08f; /* 0x33000000 */
int audiobeam___ieee754_rem_pio2f( float x, float *y )
{
float z, w, t, r, fn;
int i, j, n = 0, ix, hx;
AUDIOBEAM_GET_FLOAT_WORD( hx, x );
ix = hx & 0x7fffffff;
if ( ix <= 0x3f490fd8 ) {
y[ 0 ] = x;
y[ 1 ] = 0;
return 0;
}
if ( ix < 0x4016cbe4 ) {
if ( hx > 0 ) {
z = x - audiobeam_pio2_1;
if ( ( ix & 0xfffffff0 ) != 0x3fc90fd0 ) {
y[ 0 ] = z - audiobeam_pio2_1t;
y[ 1 ] = ( z - y[ 0 ] ) - audiobeam_pio2_1t;
} else {
z -= audiobeam_pio2_2;
y[ 0 ] = z - audiobeam_pio2_2t;
y[ 1 ] = ( z - y[ 0 ] ) - audiobeam_pio2_2t;
}
return 1;
} else {
z = x + audiobeam_pio2_1;
if ( ( ix & 0xfffffff0 ) != 0x3fc90fd0 ) {
y[ 0 ] = z + audiobeam_pio2_1t;
y[ 1 ] = ( z - y[ 0 ] ) + audiobeam_pio2_1t;
} else {
z += audiobeam_pio2_2;
y[ 0 ] = z + audiobeam_pio2_2t;
y[ 1 ] = ( z - y[ 0 ] ) + audiobeam_pio2_2t;
}
return -1;
}
}
if ( ix <= 0x43490f80 ) {
t = audiobeam_fabsf( x );
n = ( int ) ( t * audiobeam_invpio2 + audiobeam_half );
fn = ( float )n;
r = t - fn * audiobeam_pio2_1;
w = fn * audiobeam_pio2_1t;
if ( n < 32 && ( int )( ix & 0xffffff00 ) != audiobeam_npio2_hw[ n - 1 ] )
y[ 0 ] = r - w;
else {
unsigned int high;
j = ix >> 23;
y[ 0 ] = r - w;
AUDIOBEAM_GET_FLOAT_WORD( high, y[ 0 ] );
i = j - ( ( high >> 23 ) & 0xff );
if ( i > 8 ) {
t = r;
w = fn * audiobeam_pio2_2;
r = t - w;
w = fn * audiobeam_pio2_2t - ( ( t - r ) - w );
y[ 0 ] = r - w;
AUDIOBEAM_GET_FLOAT_WORD( high, y[ 0 ] );
i = j - ( ( high >> 23 ) & 0xff );
if ( i > 25 ) {
t = r;
w = fn * audiobeam_pio2_3;
r = t - w;
w = fn * audiobeam_pio2_3t - ( ( t - r ) - w );
y[ 0 ] = r - w;
}
}
}
y[ 1 ] = ( r - y[ 0 ] ) - w;
if ( hx < 0 ) {
y[ 0 ] = -y[ 0 ];
y[ 1 ] = -y[ 1 ];
return -n;
} else return n;
}
if ( ix >= 0x7f800000 ) {
y[ 0 ] = y[ 1 ] = x - x;
return 0;
}
return n;
}
float audiobeam___kernel_cosf( float x, float y )
{
float a, hz, z, r, qx;
int ix;
AUDIOBEAM_GET_FLOAT_WORD( ix, x );
ix &= 0x7fffffff;
if ( ix < 0x32000000 ) {
if ( ( ( int )x ) == 0 ) return audiobeam_one;
}
z = x * x;
r = z * ( audiobeam_C1 + z * ( audiobeam_C2 + z * ( audiobeam_C3 + z *
( audiobeam_C4 + z *
( audiobeam_C5 + z * audiobeam_C6 ) ) ) ) );
if ( ix < 0x3e99999a )
return audiobeam_one - ( ( float )0.5f * z - ( z * r - x * y ) );
else {
if ( ix > 0x3f480000 )
qx = ( float )0.28125f;
else
AUDIOBEAM_SET_FLOAT_WORD( qx, ix - 0x01000000 );
hz = ( float )0.5f * z - qx;
a = audiobeam_one - qx;
return a - ( hz - ( z * r - x * y ) );
}
}
float audiobeam___kernel_sinf( float x, float y, int iy )
{
float z, r, v;
int ix;
AUDIOBEAM_GET_FLOAT_WORD( ix, x );
ix &= 0x7fffffff;
if ( ix < 0x32000000 ) {
if ( ( int )x == 0 ) return x;
}
z = x * x;
v = z * x;
r = audiobeam_S2 + z * ( audiobeam_S3 + z * ( audiobeam_S4 + z *
( audiobeam_S5 + z * audiobeam_S6 ) ) );
if ( iy == 0 ) return x + v * ( audiobeam_S1 + z * r );
else return x - ( ( z * ( audiobeam_half * y - v * r ) - y ) - v *
audiobeam_S1 );
}
float audiobeam___copysignf( float x, float y )
{
unsigned int ix, iy;
AUDIOBEAM_GET_FLOAT_WORD( ix, x );
AUDIOBEAM_GET_FLOAT_WORD( iy, y );
AUDIOBEAM_SET_FLOAT_WORD( x, ( ix & 0x7fffffff ) | ( iy & 0x80000000 ) );
return x;
}
float audiobeam___cosf( float x )
{
float y[ 2 ], z = 0.0f;
int n, ix;
AUDIOBEAM_GET_FLOAT_WORD( ix, x );
ix &= 0x7fffffff;
if ( ix <= 0x3f490fd8 ) return audiobeam___kernel_cosf( x, z );
else
if ( ix >= 0x7f800000 ) return x - x;
else {
y[ 0 ] = 0.0;
y[ 1 ] = 0.0;
n = audiobeam___ieee754_rem_pio2f( x, y );
switch ( n & 3 ) {
case 0:
return audiobeam___kernel_cosf( y[ 0 ], y[ 1 ] );
case 1:
return -audiobeam___kernel_sinf( y[ 0 ], y[ 1 ], 1 );
case 2:
return -audiobeam___kernel_cosf( y[ 0 ], y[ 1 ] );
default:
return audiobeam___kernel_sinf( y[ 0 ], y[ 1 ], 1 );
}
}
}
float audiobeam___fabsf( float x )
{
unsigned int ix;
AUDIOBEAM_GET_FLOAT_WORD( ix, x );
AUDIOBEAM_SET_FLOAT_WORD( x, ix & 0x7fffffff );
return x;
}
float audiobeam___floorf( float x )
{
int i0, j0;
unsigned int i;
AUDIOBEAM_GET_FLOAT_WORD( i0, x );
j0 = ( ( i0 >> 23 ) & 0xff ) - 0x7f;
if ( j0 < 23 ) {
if ( j0 < 0 ) {
if ( audiobeam_huge + x > ( float )0.0f ) {
if ( i0 >= 0 )
i0 = 0;
else
if ( ( i0 & 0x7fffffff ) != 0 )
i0 = 0xbf800000;
}
} else {
i = ( 0x007fffff ) >> j0;
if ( ( i0 & i ) == 0 ) return x;
if ( audiobeam_huge + x > ( float )0.0f ) {
if ( i0 < 0 ) i0 += ( 0x00800000 ) >> j0;
i0 &= ( ~i );
}
}
} else {
if ( j0 == 0x80 ) return x + x;
else return x;
}
AUDIOBEAM_SET_FLOAT_WORD( x, i0 );
return x;
}
int audiobeam___isinff ( float x )
{
int ix, t;
AUDIOBEAM_GET_FLOAT_WORD( ix, x );
t = ix & 0x7fffffff;
t ^= 0x7f800000;
t |= -t;
return ~( t >> 31 ) & ( ix >> 30 );
}
float audiobeam___scalbnf ( float x, int n )
{
int k, ix;
AUDIOBEAM_GET_FLOAT_WORD( ix, x );
k = ( ix & 0x7f800000 ) >> 23;
if ( k == 0 ) {
if ( ( ix & 0x7fffffff ) == 0 ) return x;
x *= audiobeam_two25;
AUDIOBEAM_GET_FLOAT_WORD( ix, x );
k = ( ( ix & 0x7f800000 ) >> 23 ) - 25;
}
if ( k == 0xff ) return x + x;
k = k + n;
if ( n > 50000 || k > 0xfe )
return audiobeam_huge * audiobeam___copysignf( audiobeam_huge,
x );
if ( n < -50000 )
return audiobeam_tiny * audiobeam___copysignf( audiobeam_tiny,
x );
if ( k > 0 ) {
AUDIOBEAM_SET_FLOAT_WORD( x, ( ix & 0x807fffff ) | ( k << 23 ) );
return x;
}
if ( k <= -25 )
return audiobeam_tiny * audiobeam___copysignf( audiobeam_tiny,
x );
k += 25;
AUDIOBEAM_SET_FLOAT_WORD( x, ( ix & 0x807fffff ) | ( k << 23 ) );
return x * audiobeam_twom25;
}
float audiobeam___ceilf( float x )
{
int i0, j0;
unsigned int i;
AUDIOBEAM_GET_FLOAT_WORD( i0, x );
j0 = ( ( i0 >> 23 ) & 0xff ) - 0x7f;
if ( j0 < 23 ) {
if ( j0 < 0 ) {
if ( audiobeam_huge + x > ( float )0.0 ) {
if ( i0 < 0 )
i0 = 0x80000000;
else
if ( i0 != 0 )
i0 = 0x3f800000;
}
} else {
i = ( 0x007fffff ) >> j0;
if ( ( i0 & i ) == 0 ) return x;
if ( audiobeam_huge + x > ( float )0.0 ) {
if ( i0 > 0 ) i0 += ( 0x00800000 ) >> j0;
i0 &= ( ~i );
}
}
} else {
if ( j0 == 0x80 ) return x + x;
else return x;
}
AUDIOBEAM_SET_FLOAT_WORD( x, i0 );
return x;
}
float audiobeam___ieee754_sqrtf( float x )
{
float z;
int sign = ( int )0x80000000;
int ix, s, q, m, t, i;
unsigned int r;
AUDIOBEAM_GET_FLOAT_WORD( ix, x );
if ( ( ix & 0x7f800000 ) == 0x7f800000 )
return x * x + x;
if ( ix <= 0 ) {
if ( ( ix & ( ~sign ) ) == 0 ) return x;
else
if ( ix < 0 )
return ( x - x ) / ( x - x );
}
m = ( ix >> 23 );
if ( m == 0 ) {
_Pragma( "loopbound min 0 max 0" )
for ( i = 0; ( ix & 0x00800000 ) == 0; i++ )
ix <<= 1;
m -= i - 1;
}
m -= 127;
ix = ( ix & 0x007fffff ) | 0x00800000;
if ( m & 1 )
ix += ix;
m >>= 1;
ix += ix;
q = s = 0;
r = 0x01000000;
_Pragma( "loopbound min 25 max 25" )
while ( r != 0 ) {
t = s + r;
if ( t <= ix ) {
s = t + r;
ix -= t;
q += r;
}
ix += ix;
r >>= 1;
}
if ( ix != 0 ) {
z = audiobeam_one - audiobeam_tiny;
if ( z >= audiobeam_one ) {
z = audiobeam_one + audiobeam_tiny;
if ( z > audiobeam_one )
q += 2;
else
q += ( q & 1 );
}
}
ix = ( q >> 1 ) + 0x3f000000;
ix += ( m << 23 );
AUDIOBEAM_SET_FLOAT_WORD( z, ix );
return z;
}

View File

@ -0,0 +1,59 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: quicksortlibm.c
Author: Ian Lance Taylor
Function: IEEE754 software library routines.
Source: Sun Microsystems and Cygnus
Original name: Unknown
Changes: No major functional changes.
License: See audiobeamlibm.c
*/
#ifndef AUDIOBEAM_LIBM
#define AUDIOBEAM_LIBM
#define audiobeam_M_PI 3.14159265358979323846
static const float
audiobeam_one = 1.0f,
audiobeam_tiny = 1.0e-30f,
audiobeam_half = 5.0000000000e-01, /* 0x3f000000 */
audiobeam_huge = 1.0e30,
audiobeam_two8 = 2.5600000000e+02, /* 0x43800000 */
audiobeam_twon8 = 3.9062500000e-03, /* 0x3b800000 */
audiobeam_zero = 0.0;
#define audiobeam_cos audiobeam___cosf
#define audiobeam_fabs audiobeam___fabsf
#define audiobeam_fabsf audiobeam___fabsf
#define audiobeam_isinf audiobeam___isinff
#define audiobeam_sqrt audiobeam___ieee754_sqrtf
#define audiobeam_ceil audiobeam___ceilf
#define audiobeam_floor audiobeam___floorf
float audiobeam___copysignf( float x, float y );
float audiobeam___cosf( float x );
float audiobeam___fabsf( float x );
float audiobeam___floorf( float x );
int audiobeam___ieee754_rem_pio2f( float x, float *y );
float audiobeam___ieee754_sqrtf( float x );
int audiobeam___isinff ( float x );
float audiobeam___kernel_cosf( float x, float y );
float audiobeam___kernel_sinf( float x, float y, int iy );
int audiobeam___kernel_rem_pio2f( float *x, float *y, int e0, int nx,
int prec, const int *ipio2 );
float audiobeam___scalbnf ( float x, int n );
float audiobeam___ceilf( float x );
float audiobeam___floorf( float x );
#endif // AUDIOBEAM_LIBM

View File

@ -0,0 +1,14 @@
#include "audiobeamlibmalloc.h"
#define AUDIOBEAM_HEAP_SIZE 10000
static char audiobeam_simulated_heap[ AUDIOBEAM_HEAP_SIZE ];
static unsigned int audiobeam_freeHeapPos;
void *audiobeam_malloc( unsigned int numberOfBytes )
{
void *currentPos = ( void * )&audiobeam_simulated_heap[ audiobeam_freeHeapPos ];
/* Get a 4-byte address for alignment purposes */
audiobeam_freeHeapPos += ( ( numberOfBytes + 4 ) & ( unsigned int )0xfffffffc );
return currentPos;
}

View File

@ -0,0 +1,27 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeamlibmalloc.c
Author: unkown
Function: Memory allocation.
Source: Sun Microsystems and Cygnus
Original name: Unknown
Changes: No major functional changes.
License: see license.txt
*/
#ifndef AUDIOBEAM_MALLOC_H
#define AUDIOBEAM_MALLOC_H
void *audiobeam_malloc( unsigned int numberOfBytes );
#endif

View File

@ -0,0 +1,69 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeamlibmath.h
Author: Unknown
Function: IEEE754 software library routines.
Source: Sun Microsystems
Original name: math_private.h
Changes: No major functional changes.
License: See the terms below.
*/
/*
====================================================
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Developed at SunPro, a Sun Microsystems, Inc. business.
Permission to use, copy, modify, and distribute this
software is freely granted, provided that this notice
is preserved.
====================================================
*/
/*
from: @(#)fdlibm.h 5.1 93/09/24
*/
#ifndef AUDIOBEAM_MATH_PRIVATE_H_
#define AUDIOBEAM_MATH_PRIVATE_H_
#include "audiobeamlibm.h"
/* A union which permits us to convert between a float and a 32 bit
int. */
typedef union {
float value;
unsigned int word;
} audiobeam_ieee_float_shape_type;
/* Get a 32 bit int from a float. */
#define AUDIOBEAM_GET_FLOAT_WORD(i,d) \
{ \
audiobeam_ieee_float_shape_type gf_u; \
gf_u.value = (d); \
(i) = gf_u.word; \
}
/* Set a float from a 32 bit int. */
#define AUDIOBEAM_SET_FLOAT_WORD(d,i) \
{ \
audiobeam_ieee_float_shape_type sf_u; \
sf_u.word = (i); \
(d) = sf_u.value; \
}
#endif /* _MATH_PRIVATE_H_ */

View File

@ -0,0 +1,36 @@
File: audiobeam.c
Original provenience: StreamIt
http://groups.csail.mit.edu/cag/streamit/
2015-12-29:
- Removed original header comment, replaced by TACLeBench header.
- Renamed libraryfiles according to TACLeBench naming scheme.
- Removed all preprocessor macros, integrated them directly in the source code.
- Added prefix "audiobeam_" to all global symbols.
- Added explicit forward declarations of functions.
- Added an empty init function
- Added preprocessor command to determine if 32 or 64 bit in audiobeamlibmalloc.h
- Added new function audiobeam_return producing a checksum as return value.
- Added new function audiobeam_main according to TACLeBench guidelines.
audiobeam_main is annotated as entry-point for timing analysis.
- Applied code formatting according to the following rules
- Lines shall not be wider than 80 characters; whenever possible, appropriate
line breaks shall be inserted to keep lines below 80 characters
- Indentation is done using whitespaces only, no tabs. Code is indented by
two whitespaces
- Two empty lines are put between any two functions
- In non-empty lists or index expressions, opening '(' and '[' are followed by
one whitespace, closing ')' and ']' are preceded by one whitespace
- In comma- or colon-separated argument lists, one whitespace is put after
each comma/colon
- Names of functions and global variables all start with a benchmark-specific
prefix (here: bs_) followed by lowercase letter (e.g., bs_square)
- For pointer types, one whitespace is put before the '*'
- Operators within expressions shall be preceded and followed by one
whitespace
- Code of then- and else-parts of if-then-else statements shall be put in
separate lines, not in the same lines as the if-condition or the keyword
"else"
- Opening braces '{' denoting the beginning of code for some if-else or loop
body shall be put at the end of the same line where the keywords "if",
"else", "for", "while" etc. occur

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,542 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeam
Author: Eugene Weinstein
Function: Audio beam former
Source: StreamIt
http://groups.csail.mit.edu/cag/streamit/
Changes: no functional changes
License: see license.txt
*/
/*
Include section
*/
#include "audiobeam.h"
#include "audiobeamlibm.h"
#include "audiobeamlibmalloc.h"
/*
Forward declaration of functions
*/
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
void audiobeam_init();
int audiobeam_return();
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
audiobeam_main(void);
__attribute__((noinline)) __attribute__((export_name("main"))) int main(void);
void
audiobeam_preprocess_delays(struct audiobeam_PreprocessedDelays prep_delays[],
float *delays);
float *audiobeam_parse_line(float *float_arr, int num_mic);
long int audiobeam_find_max_in_arr(float *arr, int size);
long int audiobeam_find_min_in_arr(float *arr, int size);
int audiobeam_wrapped_inc_offset(int i, int offset, int max_i);
int audiobeam_wrapped_dec_offset(int i, int offset, int max_i);
int audiobeam_wrapped_inc(int i, int max_i);
int audiobeam_wrapped_dec(int i, int max_i);
struct audiobeam_DataQueue *audiobeam_init_data_queue(int max_delay,
int num_mic);
struct audiobeam_Delays *audiobeam_init_delays(int num_angles, int num_mic);
void audiobeam_calc_distances(float *source_location,
float audiobeam_mic_locations[15][3],
float *distances, int num_mic);
void audiobeam_calc_delays(float *distances, float *delays, int sound_speed,
int sampling_rate, int num_mic);
void audiobeam_adjust_delays(float *delays, int num_mic);
float *audiobeam_calc_weights_lr(int num_mic);
float *audiobeam_calc_weights_left_only(int num_mic);
float audiobeam_calculate_energy(float *samples, int num_samples);
float audiobeam_do_beamforming(
struct audiobeam_PreprocessedDelays preprocessed_delays[],
float **sample_queue, int queue_head, long int max_delay, int num_mic,
float *weights);
int audiobeam_process_signal(struct audiobeam_Delays *delays, int num_mic,
float sampling_rate, float **beamform_results,
struct audiobeam_DataQueue *queue, int num_beams,
int window, float *weights);
int audiobeam_calc_beamforming_result(struct audiobeam_Delays *delays,
float **beamform_results, float *energies,
struct audiobeam_DataQueue *queue,
int num_beams, int window, int hamming);
void audiobeam_calc_single_pos(float source_location[3],
float audiobeam_mic_locations[15][3],
int hamming);
/*
Declaration of global variables
*/
extern float audiobeam_input[5760];
extern float audiobeam_mic_locations[15][3];
extern float audiobeam_source_location[3];
extern float audiobeam_origin_location[3];
int audiobeam_input_pos;
int audiobeam_checksum;
/*
Initialization- and return-value-related functions
*/
void
audiobeam_init() {
audiobeam_input_pos = 0;
audiobeam_checksum = 0;
unsigned int i;
unsigned char *p;
volatile char bitmask = 0;
/*
Apply volatile XOR-bitmask to entire input array.
*/
p = (unsigned char *) &audiobeam_input[0];
__pragma_loopbound(23040, 23040);
for (i = 0; i < sizeof(audiobeam_input); ++i, ++p)
*p ^= bitmask;
p = (unsigned char *) &audiobeam_mic_locations[0];
__pragma_loopbound(180, 180);
for (i = 0; i < sizeof(audiobeam_mic_locations); ++i, ++p)
*p ^= bitmask;
p = (unsigned char *) &audiobeam_source_location[0];
__pragma_loopbound(12, 12);
for (i = 0; i < sizeof(audiobeam_source_location); ++i, ++p)
*p ^= bitmask;
p = (unsigned char *) &audiobeam_origin_location[0];
__pragma_loopbound(12, 12);
for (i = 0; i < sizeof(audiobeam_origin_location); ++i, ++p)
*p ^= bitmask;
}
int
audiobeam_return() {
return (audiobeam_checksum + 1 != 0);
}
/*
Algorithm core functions
*/
void
audiobeam_preprocess_delays(struct audiobeam_PreprocessedDelays prep_delays[],
float *delays) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < 15; i++) {
prep_delays[i].delay = delays[i];
prep_delays[i].high = (int) audiobeam_ceil(delays[i]);
prep_delays[i].low = (int) audiobeam_floor(delays[i]);
prep_delays[i].offset = delays[i] - prep_delays[i].low;
}
}
float *
audiobeam_parse_line(float *float_arr, int num_mic) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++)
float_arr[i] = audiobeam_input[audiobeam_input_pos++];
return float_arr;
}
long int
audiobeam_find_max_in_arr(float *arr, int size) {
int i;
float max = 0;
__pragma_loopbound(15, 15);
for (i = 0; i < size; i++) {
if (arr[i] > max)
max = arr[i];
}
return audiobeam_ceil(max);
}
long int
audiobeam_find_min_in_arr(float *arr, int size) {
int i;
float min = arr[0];
__pragma_loopbound(15, 15);
for (i = 0; i < size; i++) {
if (arr[i] < min)
min = arr[i];
}
return audiobeam_floor(min);
}
int
audiobeam_wrapped_inc_offset(int i, int offset, int max_i) {
if (i + offset > max_i)
return (i + offset - max_i - 1);
else
return (i + offset);
}
int
audiobeam_wrapped_dec_offset(int i, int offset, int max_i) {
if (i - offset < 0)
return (max_i - (offset - i) + 1);
else
return (i - offset);
}
int
audiobeam_wrapped_inc(int i, int max_i) {
return audiobeam_wrapped_inc_offset(i, 1, max_i);
}
int
audiobeam_wrapped_dec(int i, int max_i) {
return audiobeam_wrapped_dec_offset(i, 1, max_i);
}
struct audiobeam_DataQueue *
audiobeam_init_data_queue(int max_delay, int num_mic) {
int i, j;
struct audiobeam_DataQueue *queue;
queue = (struct audiobeam_DataQueue *) audiobeam_malloc(
sizeof(struct audiobeam_DataQueue));
queue->sample_queue =
(float **) audiobeam_malloc((max_delay + 1) * sizeof(float *));
__pragma_loopbound(15, 15);
for (i = 0; i < (max_delay + 1); i++) {
(queue->sample_queue)[i] =
(float *) audiobeam_malloc(num_mic * sizeof(float));
__pragma_loopbound(15, 15);
for (j = 0; j < num_mic; j++) {
(queue->sample_queue)[i][j] = 0.0; // Initialize values to 0
}
}
queue->head = 0;
queue->tail = 0;
queue->full = 0;
return queue;
}
struct audiobeam_Delays *
audiobeam_init_delays(int num_angles, int num_mic) {
struct audiobeam_Delays *delays;
int i;
delays = (struct audiobeam_Delays *) audiobeam_malloc(
sizeof(struct audiobeam_Delays));
// Initialize the delays array
delays->delay_values =
(float **) audiobeam_malloc(num_angles * sizeof(float *));
__pragma_loopbound(1, 1);
for (i = 0; i < (num_angles); i++) {
delays->delay_values[i] =
(float *) audiobeam_malloc(num_mic * sizeof(float));
}
return delays;
}
void
audiobeam_calc_distances(float *source_location,
float audiobeam_mic_locations[15][3], float *distances,
int num_mic) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++) {
distances[i] = (audiobeam_sqrt(
(audiobeam_mic_locations[i][0] - source_location[0]) *
(audiobeam_mic_locations[i][0] - source_location[0]) +
(audiobeam_mic_locations[i][1] - source_location[1]) *
(audiobeam_mic_locations[i][1] - source_location[1]) +
(audiobeam_mic_locations[i][2] - source_location[2]) *
(audiobeam_mic_locations[i][2] - source_location[2])));
}
}
void
audiobeam_calc_delays(float *distances, float *delays, int sound_speed,
int sampling_rate, int num_mic) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++)
delays[i] = (distances[i] / sound_speed) * sampling_rate;
}
void
audiobeam_adjust_delays(float *delays, int num_mic) {
int i;
long int min_delay = audiobeam_find_min_in_arr(delays, num_mic) - 1;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++)
delays[i] -= min_delay;
}
float *
audiobeam_calc_weights_lr(int num_mic) {
float *weights = (float *) audiobeam_malloc(num_mic * sizeof(float));
int index = 0;
int y, z;
int half = num_mic / 4;
__pragma_loopbound(0, 0);
for (z = 1; z >= -1; z -= 2) {
__pragma_loopbound(0, 0);
for (y = 0; y < half; y++) {
weights[index] =
0.54 + 0.46 * audiobeam_cos(audiobeam_M_PI * y / half);
index++;
}
__pragma_loopbound(0, 0);
for (y = 0; y < half; y++) {
weights[index] =
0.54 + 0.46 * audiobeam_cos(audiobeam_M_PI * (-y) / half);
index++;
}
}
return weights;
}
float *
audiobeam_calc_weights_left_only(int num_mic) {
float *weights = (float *) audiobeam_malloc(num_mic * sizeof(float));
int index = 0;
int y;
int half = num_mic / 2;
__pragma_loopbound(15, 15);
for (y = -half; y <= half; y++) {
weights[index] = 0.54 + 0.46 * audiobeam_cos(audiobeam_M_PI * y / half);
index++;
}
return weights;
}
float
audiobeam_calculate_energy(float *samples, int num_samples) {
int i;
float sum = 0.0;
__pragma_loopbound(0, 0);
for (i = 0; i < num_samples; i++)
sum += (samples[i] * samples[i]);
return sum;
}
float
audiobeam_do_beamforming(
struct audiobeam_PreprocessedDelays preprocessed_delays[],
float **sample_queue, int queue_head, long int max_delay, int num_mic,
float *weights) {
int i;
float sum = 0;
int delay_floor;
int delay_ceil;
int low_index;
int high_index;
float interpolated_value;
// add up all the num_mic delayed samples
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++) {
delay_floor = preprocessed_delays[i].low;
delay_ceil = preprocessed_delays[i].high;
// Inline wrap around here
// Low index gets index of sample right before desired sample
low_index = queue_head + delay_floor;
if (low_index > max_delay)
low_index -= (max_delay + 1);
// High index gets index of sample right after desired sample
high_index = queue_head + delay_ceil;
if (high_index > max_delay)
high_index -= (max_delay + 1);
// i gives the value of the microphone we want. However, since
// the array only has microphones first_mic to last_mic, we
// need to offset our index by first_mic
interpolated_value =
(((sample_queue[high_index][i] - sample_queue[low_index][i]) *
(preprocessed_delays[i].offset)) +
sample_queue[low_index][i]);
// If we have microphone weights, multiply the value by the weight
if (weights != 0)
sum += (interpolated_value * weights[i]);
else
sum += interpolated_value;
}
return sum;
}
int
audiobeam_process_signal(struct audiobeam_Delays *delays, int num_mic,
float sampling_rate, float **beamform_results,
struct audiobeam_DataQueue *queue, int num_beams,
int window, float *weights) {
int i, j;
float time_index = 0;
float time_index_inc = (1.0 / sampling_rate);
float value;
int done = 0;
struct audiobeam_PreprocessedDelays preprocessed_delays[15];
audiobeam_preprocess_delays(preprocessed_delays, delays->delay_values[0]);
__pragma_loopbound(13, 13);
for (i = 0; i < delays->max_delay - 1; i++) {
if (audiobeam_input_pos < 5760)
audiobeam_parse_line((queue->sample_queue)[queue->head], 15);
else
return -1;
queue->head = audiobeam_wrapped_inc(queue->head, delays->max_delay);
}
__pragma_loopbound(371, 371);
for (i = 0; (i < window) || (window < 0); i++) {
if (audiobeam_input_pos < 5760)
audiobeam_parse_line((queue->sample_queue)[queue->head], 15);
else {
done = 1;
break;
}
__pragma_loopbound(1, 1);
for (j = 0; j < num_beams; j++) {
value = audiobeam_do_beamforming(
preprocessed_delays, (queue->sample_queue),
audiobeam_wrapped_inc(queue->head, delays->max_delay),
delays->max_delay, num_mic, weights);
value = value / num_mic;
if (beamform_results != 0)
beamform_results[j][i] = value;
}
queue->tail = queue->head;
queue->head = audiobeam_wrapped_inc(queue->head, delays->max_delay);
time_index += time_index_inc;
}
return (done);
}
int
audiobeam_calc_beamforming_result(struct audiobeam_Delays *delays,
float **beamform_results, float *energies,
struct audiobeam_DataQueue *queue,
int num_beams, int window, int hamming) {
int i;
int done;
float *weights = 0;
if (hamming) {
if ((15 % 2) == 1)
weights = audiobeam_calc_weights_left_only(15);
else
weights = audiobeam_calc_weights_lr(15);
}
done = audiobeam_process_signal(delays, 15, 16000, beamform_results, queue,
num_beams, window, weights);
if (beamform_results != 0) {
__pragma_loopbound(1, 1);
for (i = 0; i < num_beams; i++)
energies[i] =
audiobeam_calculate_energy(beamform_results[i], window);
}
return done;
}
void
audiobeam_calc_single_pos(float source_location[3],
float audiobeam_mic_locations[15][3], int hamming) {
float mic_distances[15];
struct audiobeam_Delays *delays = audiobeam_init_delays(1, 15);
struct audiobeam_DataQueue *queue;
float **beamform_results;
float *energies;
beamform_results = (float **) audiobeam_malloc(1 * sizeof(float *));
beamform_results[0] = (float *) audiobeam_malloc(384 * sizeof(float));
energies = (float *) audiobeam_malloc(1 * sizeof(float *));
// Calculate distances from source to each of mics
audiobeam_calc_distances(source_location, audiobeam_mic_locations,
mic_distances, 15);
audiobeam_calc_delays(mic_distances, delays->delay_values[0], 342, 16000,
15);
audiobeam_adjust_delays(delays->delay_values[0], 15);
delays->max_delay = audiobeam_find_max_in_arr(delays->delay_values[0], 15);
queue = audiobeam_init_data_queue(delays->max_delay, 15);
audiobeam_calc_beamforming_result(delays, beamform_results, energies, queue,
1, -1, hamming);
audiobeam_checksum += beamform_results[0][0] * 1000;
}
/*
Main functions
*/
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
audiobeam_main(void) {
char hamming = 1;
audiobeam_calc_single_pos(audiobeam_source_location,
audiobeam_mic_locations, hamming);
}
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
audiobeam_init();
audiobeam_main();
return (audiobeam_return());
}

View File

@ -0,0 +1,50 @@
#ifndef AUDIOBEAM_MAIN_H
#define AUDIOBEAM_MAIN_H
struct audiobeam_DataQueue {
float **sample_queue;
int head;
int tail;
unsigned char full;
};
struct audiobeam_Delays {
float **delay_values;
long int max_delay;
};
struct audiobeam_PreprocessedDelays {
float delay;
int low;
int high;
float offset;
};
#undef FLT_MAX
#define FLT_MAX 999e999
#define SOUND_SPEED 342
#define SAMPLING_RATE 16000
#define CARTESIAN_DISTANCE(x1, y1, z1, x2, y2, z2) \
(sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + \
(z1 - z2) * (z1 - z2)));
#define NUM_MIC 15
#define ANGLE_ENERGY_WINDOW_SIZE 400
#define GRID_STEP_SIZE 0.003 // .3cm
#define NUM_DIRS 7
#define NUM_TILES 16
#define MIC_HORIZ_SPACE 0.038257
#define MIC_VERT_SPACE 0.015001
#define TWO23 8388608.0 // 2^23
#define BUFFER_SIZE 384 // No of input-tupels (each with NUM_MIC elements)
#define NUM_MIC_IN_CHAIN 32
#define NUM_BOARDS_IN_CHAIN 16
#define INPUT_LENGTH 5760
#define INTERPOLATE(low_value, high_value, offset) \
(((high_value - low_value) * (offset)) + low_value)
#endif

View File

@ -0,0 +1,425 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeamlibm.c
Author: Ian Lance Taylor and J.T. Conklin
Function: IEEE754 software library routines.
Source: Sun Microsystems and Cygnus
Original name: Unknown
Changes: No major functional changes.
License: See the terms below.
*/
/*
====================================================
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Developed at SunPro, a Sun Microsystems, Inc. business.
Permission to use, copy, modify, and distribute this
software is freely granted, provided that this notice
is preserved.
====================================================
*/
#include "audiobeamlibm.h"
#include "audiobeamlibmath.h"
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
static const int audiobeam_npio2_hw[] = {
0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
0x4242c700, 0x42490f00};
static const float audiobeam_invpio2 = 6.3661980629e-01f, /* 0x3f22f984 */
audiobeam_pio2_1 = 1.5707855225e+00f, /* 0x3fc90f80 */
audiobeam_pio2_1t = 1.0804334124e-05f, /* 0x37354443 */
audiobeam_pio2_2 = 1.0804273188e-05f, /* 0x37354400 */
audiobeam_pio2_2t = 6.0770999344e-11f, /* 0x2e85a308 */
audiobeam_pio2_3 = 6.0770943833e-11f, /* 0x2e85a300 */
audiobeam_pio2_3t = 6.1232342629e-17f; /* 0x248d3132 */
static const float audiobeam_C1 = 4.1666667908e-02f, /* 0x3d2aaaab */
audiobeam_C2 = -1.3888889225e-03f, /* 0xbab60b61 */
audiobeam_C3 = 2.4801587642e-05f, /* 0x37d00d01 */
audiobeam_C4 = -2.7557314297e-07f, /* 0xb493f27c */
audiobeam_C5 = 2.0875723372e-09f, /* 0x310f74f6 */
audiobeam_C6 = -1.1359647598e-11f; /* 0xad47d74e */
static const float audiobeam_S1 = -1.6666667163e-01f, /* 0xbe2aaaab */
audiobeam_S2 = 8.3333337680e-03f, /* 0x3c088889 */
audiobeam_S3 = -1.9841270114e-04f, /* 0xb9500d01 */
audiobeam_S4 = 2.7557314297e-06f, /* 0x3638ef1b */
audiobeam_S5 = -2.5050759689e-08f, /* 0xb2d72f34 */
audiobeam_S6 = 1.5896910177e-10f; /* 0x2f2ec9d3 */
static const float audiobeam_two25 = 3.355443200e+07f, /* 0x4c000000 */
audiobeam_twom25 = 2.9802322388e-08f; /* 0x33000000 */
int
audiobeam___ieee754_rem_pio2f(float x, float *y) {
float z, w, t, r, fn;
int i, j, n = 0, ix, hx;
AUDIOBEAM_GET_FLOAT_WORD(hx, x);
ix = hx & 0x7fffffff;
if (ix <= 0x3f490fd8) {
y[0] = x;
y[1] = 0;
return 0;
}
if (ix < 0x4016cbe4) {
if (hx > 0) {
z = x - audiobeam_pio2_1;
if ((ix & 0xfffffff0) != 0x3fc90fd0) {
y[0] = z - audiobeam_pio2_1t;
y[1] = (z - y[0]) - audiobeam_pio2_1t;
} else {
z -= audiobeam_pio2_2;
y[0] = z - audiobeam_pio2_2t;
y[1] = (z - y[0]) - audiobeam_pio2_2t;
}
return 1;
} else {
z = x + audiobeam_pio2_1;
if ((ix & 0xfffffff0) != 0x3fc90fd0) {
y[0] = z + audiobeam_pio2_1t;
y[1] = (z - y[0]) + audiobeam_pio2_1t;
} else {
z += audiobeam_pio2_2;
y[0] = z + audiobeam_pio2_2t;
y[1] = (z - y[0]) + audiobeam_pio2_2t;
}
return -1;
}
}
if (ix <= 0x43490f80) {
t = audiobeam_fabsf(x);
n = (int) (t * audiobeam_invpio2 + audiobeam_half);
fn = (float) n;
r = t - fn * audiobeam_pio2_1;
w = fn * audiobeam_pio2_1t;
if (n < 32 && (int) (ix & 0xffffff00) != audiobeam_npio2_hw[n - 1])
y[0] = r - w;
else {
unsigned int high;
j = ix >> 23;
y[0] = r - w;
AUDIOBEAM_GET_FLOAT_WORD(high, y[0]);
i = j - ((high >> 23) & 0xff);
if (i > 8) {
t = r;
w = fn * audiobeam_pio2_2;
r = t - w;
w = fn * audiobeam_pio2_2t - ((t - r) - w);
y[0] = r - w;
AUDIOBEAM_GET_FLOAT_WORD(high, y[0]);
i = j - ((high >> 23) & 0xff);
if (i > 25) {
t = r;
w = fn * audiobeam_pio2_3;
r = t - w;
w = fn * audiobeam_pio2_3t - ((t - r) - w);
y[0] = r - w;
}
}
}
y[1] = (r - y[0]) - w;
if (hx < 0) {
y[0] = -y[0];
y[1] = -y[1];
return -n;
} else
return n;
}
if (ix >= 0x7f800000) {
y[0] = y[1] = x - x;
return 0;
}
return n;
}
float
audiobeam___kernel_cosf(float x, float y) {
float a, hz, z, r, qx;
int ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
ix &= 0x7fffffff;
if (ix < 0x32000000) {
if (((int) x) == 0)
return audiobeam_one;
}
z = x * x;
r = z * (audiobeam_C1 +
z * (audiobeam_C2 +
z * (audiobeam_C3 +
z * (audiobeam_C4 +
z * (audiobeam_C5 + z * audiobeam_C6)))));
if (ix < 0x3e99999a)
return audiobeam_one - ((float) 0.5f * z - (z * r - x * y));
else {
if (ix > 0x3f480000)
qx = (float) 0.28125f;
else
AUDIOBEAM_SET_FLOAT_WORD(qx, ix - 0x01000000);
hz = (float) 0.5f * z - qx;
a = audiobeam_one - qx;
return a - (hz - (z * r - x * y));
}
}
float
audiobeam___kernel_sinf(float x, float y, int iy) {
float z, r, v;
int ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
ix &= 0x7fffffff;
if (ix < 0x32000000) {
if ((int) x == 0)
return x;
}
z = x * x;
v = z * x;
r = audiobeam_S2 +
z * (audiobeam_S3 +
z * (audiobeam_S4 + z * (audiobeam_S5 + z * audiobeam_S6)));
if (iy == 0)
return x + v * (audiobeam_S1 + z * r);
else
return x - ((z * (audiobeam_half * y - v * r) - y) - v * audiobeam_S1);
}
float
audiobeam___copysignf(float x, float y) {
unsigned int ix, iy;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
AUDIOBEAM_GET_FLOAT_WORD(iy, y);
AUDIOBEAM_SET_FLOAT_WORD(x, (ix & 0x7fffffff) | (iy & 0x80000000));
return x;
}
float
audiobeam___cosf(float x) {
float y[2], z = 0.0f;
int n, ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
ix &= 0x7fffffff;
if (ix <= 0x3f490fd8)
return audiobeam___kernel_cosf(x, z);
else if (ix >= 0x7f800000)
return x - x;
else {
y[0] = 0.0;
y[1] = 0.0;
n = audiobeam___ieee754_rem_pio2f(x, y);
switch (n & 3) {
case 0:
return audiobeam___kernel_cosf(y[0], y[1]);
case 1:
return -audiobeam___kernel_sinf(y[0], y[1], 1);
case 2:
return -audiobeam___kernel_cosf(y[0], y[1]);
default:
return audiobeam___kernel_sinf(y[0], y[1], 1);
}
}
}
float
audiobeam___fabsf(float x) {
unsigned int ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
AUDIOBEAM_SET_FLOAT_WORD(x, ix & 0x7fffffff);
return x;
}
float
audiobeam___floorf(float x) {
int i0, j0;
unsigned int i;
AUDIOBEAM_GET_FLOAT_WORD(i0, x);
j0 = ((i0 >> 23) & 0xff) - 0x7f;
if (j0 < 23) {
if (j0 < 0) {
if (audiobeam_huge + x > (float) 0.0f) {
if (i0 >= 0)
i0 = 0;
else if ((i0 & 0x7fffffff) != 0)
i0 = 0xbf800000;
}
} else {
i = (0x007fffff) >> j0;
if ((i0 & i) == 0)
return x;
if (audiobeam_huge + x > (float) 0.0f) {
if (i0 < 0)
i0 += (0x00800000) >> j0;
i0 &= (~i);
}
}
} else {
if (j0 == 0x80)
return x + x;
else
return x;
}
AUDIOBEAM_SET_FLOAT_WORD(x, i0);
return x;
}
int
audiobeam___isinff(float x) {
int ix, t;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
t = ix & 0x7fffffff;
t ^= 0x7f800000;
t |= -t;
return ~(t >> 31) & (ix >> 30);
}
float
audiobeam___scalbnf(float x, int n) {
int k, ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
k = (ix & 0x7f800000) >> 23;
if (k == 0) {
if ((ix & 0x7fffffff) == 0)
return x;
x *= audiobeam_two25;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
k = ((ix & 0x7f800000) >> 23) - 25;
}
if (k == 0xff)
return x + x;
k = k + n;
if (n > 50000 || k > 0xfe)
return audiobeam_huge * audiobeam___copysignf(audiobeam_huge, x);
if (n < -50000)
return audiobeam_tiny * audiobeam___copysignf(audiobeam_tiny, x);
if (k > 0) {
AUDIOBEAM_SET_FLOAT_WORD(x, (ix & 0x807fffff) | (k << 23));
return x;
}
if (k <= -25)
return audiobeam_tiny * audiobeam___copysignf(audiobeam_tiny, x);
k += 25;
AUDIOBEAM_SET_FLOAT_WORD(x, (ix & 0x807fffff) | (k << 23));
return x * audiobeam_twom25;
}
float
audiobeam___ceilf(float x) {
int i0, j0;
unsigned int i;
AUDIOBEAM_GET_FLOAT_WORD(i0, x);
j0 = ((i0 >> 23) & 0xff) - 0x7f;
if (j0 < 23) {
if (j0 < 0) {
if (audiobeam_huge + x > (float) 0.0) {
if (i0 < 0)
i0 = 0x80000000;
else if (i0 != 0)
i0 = 0x3f800000;
}
} else {
i = (0x007fffff) >> j0;
if ((i0 & i) == 0)
return x;
if (audiobeam_huge + x > (float) 0.0) {
if (i0 > 0)
i0 += (0x00800000) >> j0;
i0 &= (~i);
}
}
} else {
if (j0 == 0x80)
return x + x;
else
return x;
}
AUDIOBEAM_SET_FLOAT_WORD(x, i0);
return x;
}
float
audiobeam___ieee754_sqrtf(float x) {
float z;
int sign = (int) 0x80000000;
int ix, s, q, m, t, i;
unsigned int r;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
if ((ix & 0x7f800000) == 0x7f800000)
return x * x + x;
if (ix <= 0) {
if ((ix & (~sign)) == 0)
return x;
else if (ix < 0)
return (x - x) / (x - x);
}
m = (ix >> 23);
if (m == 0) {
__pragma_loopbound(0, 0);
for (i = 0; (ix & 0x00800000) == 0; i++)
ix <<= 1;
m -= i - 1;
}
m -= 127;
ix = (ix & 0x007fffff) | 0x00800000;
if (m & 1)
ix += ix;
m >>= 1;
ix += ix;
q = s = 0;
r = 0x01000000;
__pragma_loopbound(25, 25);
while (r != 0) {
t = s + r;
if (t <= ix) {
s = t + r;
ix -= t;
q += r;
}
ix += ix;
r >>= 1;
}
if (ix != 0) {
z = audiobeam_one - audiobeam_tiny;
if (z >= audiobeam_one) {
z = audiobeam_one + audiobeam_tiny;
if (z > audiobeam_one)
q += 2;
else
q += (q & 1);
}
}
ix = (q >> 1) + 0x3f000000;
ix += (m << 23);
AUDIOBEAM_SET_FLOAT_WORD(z, ix);
return z;
}

View File

@ -0,0 +1,56 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: quicksortlibm.c
Author: Ian Lance Taylor
Function: IEEE754 software library routines.
Source: Sun Microsystems and Cygnus
Original name: Unknown
Changes: No major functional changes.
License: See audiobeamlibm.c
*/
#ifndef AUDIOBEAM_LIBM
#define AUDIOBEAM_LIBM
#define audiobeam_M_PI 3.14159265358979323846
static const float audiobeam_one = 1.0f, audiobeam_tiny = 1.0e-30f,
audiobeam_half = 5.0000000000e-01, /* 0x3f000000 */
audiobeam_huge = 1.0e30, audiobeam_two8 = 2.5600000000e+02, /* 0x43800000 */
audiobeam_twon8 = 3.9062500000e-03, /* 0x3b800000 */
audiobeam_zero = 0.0;
#define audiobeam_cos audiobeam___cosf
#define audiobeam_fabs audiobeam___fabsf
#define audiobeam_fabsf audiobeam___fabsf
#define audiobeam_isinf audiobeam___isinff
#define audiobeam_sqrt audiobeam___ieee754_sqrtf
#define audiobeam_ceil audiobeam___ceilf
#define audiobeam_floor audiobeam___floorf
float audiobeam___copysignf(float x, float y);
float audiobeam___cosf(float x);
float audiobeam___fabsf(float x);
float audiobeam___floorf(float x);
int audiobeam___ieee754_rem_pio2f(float x, float *y);
float audiobeam___ieee754_sqrtf(float x);
int audiobeam___isinff(float x);
float audiobeam___kernel_cosf(float x, float y);
float audiobeam___kernel_sinf(float x, float y, int iy);
int audiobeam___kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec,
const int *ipio2);
float audiobeam___scalbnf(float x, int n);
float audiobeam___ceilf(float x);
float audiobeam___floorf(float x);
#endif // AUDIOBEAM_LIBM

View File

@ -0,0 +1,15 @@
#include "audiobeamlibmalloc.h"
#define AUDIOBEAM_HEAP_SIZE 10000
static char audiobeam_simulated_heap[AUDIOBEAM_HEAP_SIZE];
static unsigned int audiobeam_freeHeapPos;
void *
audiobeam_malloc(unsigned int numberOfBytes) {
void *currentPos =
(void *) &audiobeam_simulated_heap[audiobeam_freeHeapPos];
/* Get a 4-byte address for alignment purposes */
audiobeam_freeHeapPos += ((numberOfBytes + 4) & (unsigned int) 0xfffffffc);
return currentPos;
}

View File

@ -0,0 +1,27 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeamlibmalloc.c
Author: unkown
Function: Memory allocation.
Source: Sun Microsystems and Cygnus
Original name: Unknown
Changes: No major functional changes.
License: see license.txt
*/
#ifndef AUDIOBEAM_MALLOC_H
#define AUDIOBEAM_MALLOC_H
void *audiobeam_malloc(unsigned int numberOfBytes);
#endif

View File

@ -0,0 +1,68 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeamlibmath.h
Author: Unknown
Function: IEEE754 software library routines.
Source: Sun Microsystems
Original name: math_private.h
Changes: No major functional changes.
License: See the terms below.
*/
/*
====================================================
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Developed at SunPro, a Sun Microsystems, Inc. business.
Permission to use, copy, modify, and distribute this
software is freely granted, provided that this notice
is preserved.
====================================================
*/
/*
from: @(#)fdlibm.h 5.1 93/09/24
*/
#ifndef AUDIOBEAM_MATH_PRIVATE_H_
#define AUDIOBEAM_MATH_PRIVATE_H_
#include "audiobeamlibm.h"
/* A union which permits us to convert between a float and a 32 bit
int. */
typedef union {
float value;
unsigned int word;
} audiobeam_ieee_float_shape_type;
/* Get a 32 bit int from a float. */
#define AUDIOBEAM_GET_FLOAT_WORD(i, d) \
{ \
audiobeam_ieee_float_shape_type gf_u; \
gf_u.value = (d); \
(i) = gf_u.word; \
}
/* Set a float from a 32 bit int. */
#define AUDIOBEAM_SET_FLOAT_WORD(d, i) \
{ \
audiobeam_ieee_float_shape_type sf_u; \
sf_u.word = (i); \
(d) = sf_u.value; \
}
#endif /* _MATH_PRIVATE_H_ */

View File

@ -0,0 +1,569 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeam
Author: Eugene Weinstein
Function: Audio beam former
Source: StreamIt
http://groups.csail.mit.edu/cag/streamit/
Changes: no functional changes
License: see license.txt
*/
/*
Include section
*/
#include "audiobeam.h"
#include "audiobeamlibm.h"
#include "audiobeamlibmalloc.h"
/*
Forward declaration of functions
*/
// Wasm loop bounds
#include "audiobeaminput.c"
#include "audiobeamlibm.c"
#include "audiobeamlibmalloc.c"
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
__attribute__((always_inline)) static inline void audiobeam_init();
__attribute__((always_inline)) static inline int audiobeam_return();
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
audiobeam_main(void);
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void);
__attribute__((always_inline)) static inline void
audiobeam_preprocess_delays(struct audiobeam_PreprocessedDelays prep_delays[],
float *delays);
__attribute__((always_inline)) static inline float *
audiobeam_parse_line(float *float_arr, int num_mic);
__attribute__((always_inline)) static inline long int
audiobeam_find_max_in_arr(float *arr, int size);
__attribute__((always_inline)) static inline long int
audiobeam_find_min_in_arr(float *arr, int size);
__attribute__((always_inline)) static inline int
audiobeam_wrapped_inc_offset(int i, int offset, int max_i);
__attribute__((always_inline)) static inline int
audiobeam_wrapped_dec_offset(int i, int offset, int max_i);
__attribute__((always_inline)) static inline int
audiobeam_wrapped_inc(int i, int max_i);
__attribute__((always_inline)) static inline int
audiobeam_wrapped_dec(int i, int max_i);
__attribute__((always_inline)) static inline struct audiobeam_DataQueue *
audiobeam_init_data_queue(int max_delay, int num_mic);
__attribute__((always_inline)) static inline struct audiobeam_Delays *
audiobeam_init_delays(int num_angles, int num_mic);
__attribute__((always_inline)) static inline void
audiobeam_calc_distances(float *source_location,
float audiobeam_mic_locations[15][3], float *distances,
int num_mic);
__attribute__((always_inline)) static inline void
audiobeam_calc_delays(float *distances, float *delays, int sound_speed,
int sampling_rate, int num_mic);
__attribute__((always_inline)) static inline void
audiobeam_adjust_delays(float *delays, int num_mic);
__attribute__((always_inline)) static inline float *
audiobeam_calc_weights_lr(int num_mic);
__attribute__((always_inline)) static inline float *
audiobeam_calc_weights_left_only(int num_mic);
__attribute__((always_inline)) static inline float
audiobeam_calculate_energy(float *samples, int num_samples);
__attribute__((always_inline)) static inline float audiobeam_do_beamforming(
struct audiobeam_PreprocessedDelays preprocessed_delays[],
float **sample_queue, int queue_head, long int max_delay, int num_mic,
float *weights);
__attribute__((always_inline)) static inline int
audiobeam_process_signal(struct audiobeam_Delays *delays, int num_mic,
float sampling_rate, float **beamform_results,
struct audiobeam_DataQueue *queue, int num_beams,
int window, float *weights);
__attribute__((always_inline)) static inline int
audiobeam_calc_beamforming_result(struct audiobeam_Delays *delays,
float **beamform_results, float *energies,
struct audiobeam_DataQueue *queue,
int num_beams, int window, int hamming);
__attribute__((always_inline)) static inline void
audiobeam_calc_single_pos(float source_location[3],
float audiobeam_mic_locations[15][3], int hamming);
/*
Declaration of global variables
*/
extern float audiobeam_input[5760];
extern float audiobeam_mic_locations[15][3];
extern float audiobeam_source_location[3];
extern float audiobeam_origin_location[3];
int audiobeam_input_pos;
int audiobeam_checksum;
/*
Initialization- and return-value-related functions
*/
__attribute__((always_inline)) static inline void
audiobeam_init() {
audiobeam_input_pos = 0;
audiobeam_checksum = 0;
unsigned int i;
unsigned char *p;
volatile char bitmask = 0;
/*
Apply volatile XOR-bitmask to entire input array.
*/
p = (unsigned char *) &audiobeam_input[0];
__pragma_loopbound(23040, 23040);
for (i = 0; i < sizeof(audiobeam_input); ++i, ++p)
*p ^= bitmask;
p = (unsigned char *) &audiobeam_mic_locations[0];
__pragma_loopbound(180, 180);
for (i = 0; i < sizeof(audiobeam_mic_locations); ++i, ++p)
*p ^= bitmask;
p = (unsigned char *) &audiobeam_source_location[0];
__pragma_loopbound(12, 12);
for (i = 0; i < sizeof(audiobeam_source_location); ++i, ++p)
*p ^= bitmask;
p = (unsigned char *) &audiobeam_origin_location[0];
__pragma_loopbound(12, 12);
for (i = 0; i < sizeof(audiobeam_origin_location); ++i, ++p)
*p ^= bitmask;
}
__attribute__((always_inline)) static inline int
audiobeam_return() {
return (audiobeam_checksum + 1 != 0);
}
/*
Algorithm core functions
*/
__attribute__((always_inline)) static inline void
audiobeam_preprocess_delays(struct audiobeam_PreprocessedDelays prep_delays[],
float *delays) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < 15; i++) {
prep_delays[i].delay = delays[i];
prep_delays[i].high = (int) audiobeam_ceil(delays[i]);
prep_delays[i].low = (int) audiobeam_floor(delays[i]);
prep_delays[i].offset = delays[i] - prep_delays[i].low;
}
}
__attribute__((always_inline)) static inline float *
audiobeam_parse_line(float *float_arr, int num_mic) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++)
float_arr[i] = audiobeam_input[audiobeam_input_pos++];
return float_arr;
}
__attribute__((always_inline)) static inline long int
audiobeam_find_max_in_arr(float *arr, int size) {
int i;
float max = 0;
__pragma_loopbound(15, 15);
for (i = 0; i < size; i++) {
if (arr[i] > max)
max = arr[i];
}
return audiobeam_ceil(max);
}
__attribute__((always_inline)) static inline long int
audiobeam_find_min_in_arr(float *arr, int size) {
int i;
float min = arr[0];
__pragma_loopbound(15, 15);
for (i = 0; i < size; i++) {
if (arr[i] < min)
min = arr[i];
}
return audiobeam_floor(min);
}
__attribute__((always_inline)) static inline int
audiobeam_wrapped_inc_offset(int i, int offset, int max_i) {
if (i + offset > max_i)
return (i + offset - max_i - 1);
else
return (i + offset);
}
__attribute__((always_inline)) static inline int
audiobeam_wrapped_dec_offset(int i, int offset, int max_i) {
if (i - offset < 0)
return (max_i - (offset - i) + 1);
else
return (i - offset);
}
__attribute__((always_inline)) static inline int
audiobeam_wrapped_inc(int i, int max_i) {
return audiobeam_wrapped_inc_offset(i, 1, max_i);
}
__attribute__((always_inline)) static inline int
audiobeam_wrapped_dec(int i, int max_i) {
return audiobeam_wrapped_dec_offset(i, 1, max_i);
}
__attribute__((always_inline)) static inline struct audiobeam_DataQueue *
audiobeam_init_data_queue(int max_delay, int num_mic) {
int i, j;
struct audiobeam_DataQueue *queue;
queue = (struct audiobeam_DataQueue *) audiobeam_malloc(
sizeof(struct audiobeam_DataQueue));
queue->sample_queue =
(float **) audiobeam_malloc((max_delay + 1) * sizeof(float *));
__pragma_loopbound(15, 15);
for (i = 0; i < (max_delay + 1); i++) {
(queue->sample_queue)[i] =
(float *) audiobeam_malloc(num_mic * sizeof(float));
__pragma_loopbound(15, 15);
for (j = 0; j < num_mic; j++) {
(queue->sample_queue)[i][j] = 0.0; // Initialize values to 0
}
}
queue->head = 0;
queue->tail = 0;
queue->full = 0;
return queue;
}
__attribute__((always_inline)) static inline struct audiobeam_Delays *
audiobeam_init_delays(int num_angles, int num_mic) {
struct audiobeam_Delays *delays;
int i;
delays = (struct audiobeam_Delays *) audiobeam_malloc(
sizeof(struct audiobeam_Delays));
// Initialize the delays array
delays->delay_values =
(float **) audiobeam_malloc(num_angles * sizeof(float *));
__pragma_loopbound(1, 1);
for (i = 0; i < (num_angles); i++) {
delays->delay_values[i] =
(float *) audiobeam_malloc(num_mic * sizeof(float));
}
return delays;
}
__attribute__((always_inline)) static inline void
audiobeam_calc_distances(float *source_location,
float audiobeam_mic_locations[15][3], float *distances,
int num_mic) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++) {
distances[i] = (audiobeam_sqrt(
(audiobeam_mic_locations[i][0] - source_location[0]) *
(audiobeam_mic_locations[i][0] - source_location[0]) +
(audiobeam_mic_locations[i][1] - source_location[1]) *
(audiobeam_mic_locations[i][1] - source_location[1]) +
(audiobeam_mic_locations[i][2] - source_location[2]) *
(audiobeam_mic_locations[i][2] - source_location[2])));
}
}
__attribute__((always_inline)) static inline void
audiobeam_calc_delays(float *distances, float *delays, int sound_speed,
int sampling_rate, int num_mic) {
int i;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++)
delays[i] = (distances[i] / sound_speed) * sampling_rate;
}
__attribute__((always_inline)) static inline void
audiobeam_adjust_delays(float *delays, int num_mic) {
int i;
long int min_delay = audiobeam_find_min_in_arr(delays, num_mic) - 1;
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++)
delays[i] -= min_delay;
}
__attribute__((always_inline)) static inline float *
audiobeam_calc_weights_lr(int num_mic) {
float *weights = (float *) audiobeam_malloc(num_mic * sizeof(float));
int index = 0;
int y, z;
int half = num_mic / 4;
__pragma_loopbound(0, 0);
for (z = 1; z >= -1; z -= 2) {
__pragma_loopbound(0, 0);
for (y = 0; y < half; y++) {
weights[index] =
0.54 + 0.46 * audiobeam_cos(audiobeam_M_PI * y / half);
index++;
}
__pragma_loopbound(0, 0);
for (y = 0; y < half; y++) {
weights[index] =
0.54 + 0.46 * audiobeam_cos(audiobeam_M_PI * (-y) / half);
index++;
}
}
return weights;
}
__attribute__((always_inline)) static inline float *
audiobeam_calc_weights_left_only(int num_mic) {
float *weights = (float *) audiobeam_malloc(num_mic * sizeof(float));
int index = 0;
int y;
int half = num_mic / 2;
__pragma_loopbound(15, 15);
for (y = -half; y <= half; y++) {
weights[index] = 0.54 + 0.46 * audiobeam_cos(audiobeam_M_PI * y / half);
index++;
}
return weights;
}
__attribute__((always_inline)) static inline float
audiobeam_calculate_energy(float *samples, int num_samples) {
int i;
float sum = 0.0;
__pragma_loopbound(0, 0);
for (i = 0; i < num_samples; i++)
sum += (samples[i] * samples[i]);
return sum;
}
__attribute__((always_inline)) static inline float
audiobeam_do_beamforming(
struct audiobeam_PreprocessedDelays preprocessed_delays[],
float **sample_queue, int queue_head, long int max_delay, int num_mic,
float *weights) {
int i;
float sum = 0;
int delay_floor;
int delay_ceil;
int low_index;
int high_index;
float interpolated_value;
// add up all the num_mic delayed samples
__pragma_loopbound(15, 15);
for (i = 0; i < num_mic; i++) {
delay_floor = preprocessed_delays[i].low;
delay_ceil = preprocessed_delays[i].high;
// Inline wrap around here
// Low index gets index of sample right before desired sample
low_index = queue_head + delay_floor;
if (low_index > max_delay)
low_index -= (max_delay + 1);
// High index gets index of sample right after desired sample
high_index = queue_head + delay_ceil;
if (high_index > max_delay)
high_index -= (max_delay + 1);
// i gives the value of the microphone we want. However, since
// the array only has microphones first_mic to last_mic, we
// need to offset our index by first_mic
interpolated_value =
(((sample_queue[high_index][i] - sample_queue[low_index][i]) *
(preprocessed_delays[i].offset)) +
sample_queue[low_index][i]);
// If we have microphone weights, multiply the value by the weight
if (weights != 0)
sum += (interpolated_value * weights[i]);
else
sum += interpolated_value;
}
return sum;
}
__attribute__((always_inline)) static inline int
audiobeam_process_signal(struct audiobeam_Delays *delays, int num_mic,
float sampling_rate, float **beamform_results,
struct audiobeam_DataQueue *queue, int num_beams,
int window, float *weights) {
int i, j;
float time_index = 0;
float time_index_inc = (1.0 / sampling_rate);
float value;
int done = 0;
struct audiobeam_PreprocessedDelays preprocessed_delays[15];
audiobeam_preprocess_delays(preprocessed_delays, delays->delay_values[0]);
__pragma_loopbound(13, 13);
for (i = 0; i < delays->max_delay - 1; i++) {
if (audiobeam_input_pos < 5760)
audiobeam_parse_line((queue->sample_queue)[queue->head], 15);
else
return -1;
queue->head = audiobeam_wrapped_inc(queue->head, delays->max_delay);
}
__pragma_loopbound(371, 371);
for (i = 0; (i < window) || (window < 0); i++) {
if (audiobeam_input_pos < 5760)
audiobeam_parse_line((queue->sample_queue)[queue->head], 15);
else {
done = 1;
break;
}
__pragma_loopbound(1, 1);
for (j = 0; j < num_beams; j++) {
value = audiobeam_do_beamforming(
preprocessed_delays, (queue->sample_queue),
audiobeam_wrapped_inc(queue->head, delays->max_delay),
delays->max_delay, num_mic, weights);
value = value / num_mic;
if (beamform_results != 0)
beamform_results[j][i] = value;
}
queue->tail = queue->head;
queue->head = audiobeam_wrapped_inc(queue->head, delays->max_delay);
time_index += time_index_inc;
}
return (done);
}
__attribute__((always_inline)) static inline int
audiobeam_calc_beamforming_result(struct audiobeam_Delays *delays,
float **beamform_results, float *energies,
struct audiobeam_DataQueue *queue,
int num_beams, int window, int hamming) {
int i;
int done;
float *weights = 0;
if (hamming) {
if ((15 % 2) == 1)
weights = audiobeam_calc_weights_left_only(15);
else
weights = audiobeam_calc_weights_lr(15);
}
done = audiobeam_process_signal(delays, 15, 16000, beamform_results, queue,
num_beams, window, weights);
if (beamform_results != 0) {
__pragma_loopbound(1, 1);
for (i = 0; i < num_beams; i++)
energies[i] =
audiobeam_calculate_energy(beamform_results[i], window);
}
return done;
}
__attribute__((always_inline)) static inline void
audiobeam_calc_single_pos(float source_location[3],
float audiobeam_mic_locations[15][3], int hamming) {
float mic_distances[15];
struct audiobeam_Delays *delays = audiobeam_init_delays(1, 15);
struct audiobeam_DataQueue *queue;
float **beamform_results;
float *energies;
beamform_results = (float **) audiobeam_malloc(1 * sizeof(float *));
beamform_results[0] = (float *) audiobeam_malloc(384 * sizeof(float));
energies = (float *) audiobeam_malloc(1 * sizeof(float *));
// Calculate distances from source to each of mics
audiobeam_calc_distances(source_location, audiobeam_mic_locations,
mic_distances, 15);
audiobeam_calc_delays(mic_distances, delays->delay_values[0], 342, 16000,
15);
audiobeam_adjust_delays(delays->delay_values[0], 15);
delays->max_delay = audiobeam_find_max_in_arr(delays->delay_values[0], 15);
queue = audiobeam_init_data_queue(delays->max_delay, 15);
audiobeam_calc_beamforming_result(delays, beamform_results, energies, queue,
1, -1, hamming);
audiobeam_checksum += beamform_results[0][0] * 1000;
}
/*
Main functions
*/
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
audiobeam_main(void) {
char hamming = 1;
audiobeam_calc_single_pos(audiobeam_source_location,
audiobeam_mic_locations, hamming);
}
__attribute__((noinline)) __attribute__((export_name("main")))
__attribute__((noinline)) __attribute__((export_name("main"))) int
main(void) {
audiobeam_init();
audiobeam_main();
return (audiobeam_return());
}

View File

@ -0,0 +1,50 @@
#ifndef AUDIOBEAM_MAIN_H
#define AUDIOBEAM_MAIN_H
struct audiobeam_DataQueue {
float **sample_queue;
int head;
int tail;
unsigned char full;
};
struct audiobeam_Delays {
float **delay_values;
long int max_delay;
};
struct audiobeam_PreprocessedDelays {
float delay;
int low;
int high;
float offset;
};
#undef FLT_MAX
#define FLT_MAX 999e999
#define SOUND_SPEED 342
#define SAMPLING_RATE 16000
#define CARTESIAN_DISTANCE(x1, y1, z1, x2, y2, z2) \
(sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + \
(z1 - z2) * (z1 - z2)));
#define NUM_MIC 15
#define ANGLE_ENERGY_WINDOW_SIZE 400
#define GRID_STEP_SIZE 0.003 // .3cm
#define NUM_DIRS 7
#define NUM_TILES 16
#define MIC_HORIZ_SPACE 0.038257
#define MIC_VERT_SPACE 0.015001
#define TWO23 8388608.0 // 2^23
#define BUFFER_SIZE 384 // No of input-tupels (each with NUM_MIC elements)
#define NUM_MIC_IN_CHAIN 32
#define NUM_BOARDS_IN_CHAIN 16
#define INPUT_LENGTH 5760
#define INTERPOLATE(low_value, high_value, offset) \
(((high_value - low_value) * (offset)) + low_value)
#endif

View File

@ -0,0 +1,425 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: audiobeamlibm.c
Author: Ian Lance Taylor and J.T. Conklin
Function: IEEE754 software library routines.
Source: Sun Microsystems and Cygnus
Original name: Unknown
Changes: No major functional changes.
License: See the terms below.
*/
/*
====================================================
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Developed at SunPro, a Sun Microsystems, Inc. business.
Permission to use, copy, modify, and distribute this
software is freely granted, provided that this notice
is preserved.
====================================================
*/
#include "audiobeamlibm.h"
#include "audiobeamlibmath.h"
// Wasm loop bounds
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
static const int audiobeam_npio2_hw[] = {
0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
0x4242c700, 0x42490f00};
static const float audiobeam_invpio2 = 6.3661980629e-01f, /* 0x3f22f984 */
audiobeam_pio2_1 = 1.5707855225e+00f, /* 0x3fc90f80 */
audiobeam_pio2_1t = 1.0804334124e-05f, /* 0x37354443 */
audiobeam_pio2_2 = 1.0804273188e-05f, /* 0x37354400 */
audiobeam_pio2_2t = 6.0770999344e-11f, /* 0x2e85a308 */
audiobeam_pio2_3 = 6.0770943833e-11f, /* 0x2e85a300 */
audiobeam_pio2_3t = 6.1232342629e-17f; /* 0x248d3132 */
static const float audiobeam_C1 = 4.1666667908e-02f, /* 0x3d2aaaab */
audiobeam_C2 = -1.3888889225e-03f, /* 0xbab60b61 */
audiobeam_C3 = 2.4801587642e-05f, /* 0x37d00d01 */
audiobeam_C4 = -2.7557314297e-07f, /* 0xb493f27c */
audiobeam_C5 = 2.0875723372e-09f, /* 0x310f74f6 */
audiobeam_C6 = -1.1359647598e-11f; /* 0xad47d74e */
static const float audiobeam_S1 = -1.6666667163e-01f, /* 0xbe2aaaab */
audiobeam_S2 = 8.3333337680e-03f, /* 0x3c088889 */
audiobeam_S3 = -1.9841270114e-04f, /* 0xb9500d01 */
audiobeam_S4 = 2.7557314297e-06f, /* 0x3638ef1b */
audiobeam_S5 = -2.5050759689e-08f, /* 0xb2d72f34 */
audiobeam_S6 = 1.5896910177e-10f; /* 0x2f2ec9d3 */
static const float audiobeam_two25 = 3.355443200e+07f, /* 0x4c000000 */
audiobeam_twom25 = 2.9802322388e-08f; /* 0x33000000 */
__attribute__((always_inline)) static inline int
audiobeam___ieee754_rem_pio2f(float x, float *y) {
float z, w, t, r, fn;
int i, j, n = 0, ix, hx;
AUDIOBEAM_GET_FLOAT_WORD(hx, x);
ix = hx & 0x7fffffff;
if (ix <= 0x3f490fd8) {
y[0] = x;
y[1] = 0;
return 0;
}
if (ix < 0x4016cbe4) {
if (hx > 0) {
z = x - audiobeam_pio2_1;
if ((ix & 0xfffffff0) != 0x3fc90fd0) {
y[0] = z - audiobeam_pio2_1t;
y[1] = (z - y[0]) - audiobeam_pio2_1t;
} else {
z -= audiobeam_pio2_2;
y[0] = z - audiobeam_pio2_2t;
y[1] = (z - y[0]) - audiobeam_pio2_2t;
}
return 1;
} else {
z = x + audiobeam_pio2_1;
if ((ix & 0xfffffff0) != 0x3fc90fd0) {
y[0] = z + audiobeam_pio2_1t;
y[1] = (z - y[0]) + audiobeam_pio2_1t;
} else {
z += audiobeam_pio2_2;
y[0] = z + audiobeam_pio2_2t;
y[1] = (z - y[0]) + audiobeam_pio2_2t;
}
return -1;
}
}
if (ix <= 0x43490f80) {
t = audiobeam_fabsf(x);
n = (int) (t * audiobeam_invpio2 + audiobeam_half);
fn = (float) n;
r = t - fn * audiobeam_pio2_1;
w = fn * audiobeam_pio2_1t;
if (n < 32 && (int) (ix & 0xffffff00) != audiobeam_npio2_hw[n - 1])
y[0] = r - w;
else {
unsigned int high;
j = ix >> 23;
y[0] = r - w;
AUDIOBEAM_GET_FLOAT_WORD(high, y[0]);
i = j - ((high >> 23) & 0xff);
if (i > 8) {
t = r;
w = fn * audiobeam_pio2_2;
r = t - w;
w = fn * audiobeam_pio2_2t - ((t - r) - w);
y[0] = r - w;
AUDIOBEAM_GET_FLOAT_WORD(high, y[0]);
i = j - ((high >> 23) & 0xff);
if (i > 25) {
t = r;
w = fn * audiobeam_pio2_3;
r = t - w;
w = fn * audiobeam_pio2_3t - ((t - r) - w);
y[0] = r - w;
}
}
}
y[1] = (r - y[0]) - w;
if (hx < 0) {
y[0] = -y[0];
y[1] = -y[1];
return -n;
} else
return n;
}
if (ix >= 0x7f800000) {
y[0] = y[1] = x - x;
return 0;
}
return n;
}
__attribute__((always_inline)) static inline float
audiobeam___kernel_cosf(float x, float y) {
float a, hz, z, r, qx;
int ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
ix &= 0x7fffffff;
if (ix < 0x32000000) {
if (((int) x) == 0)
return audiobeam_one;
}
z = x * x;
r = z * (audiobeam_C1 +
z * (audiobeam_C2 +
z * (audiobeam_C3 +
z * (audiobeam_C4 +
z * (audiobeam_C5 + z * audiobeam_C6)))));
if (ix < 0x3e99999a)
return audiobeam_one - ((float) 0.5f * z - (z * r - x * y));
else {
if (ix > 0x3f480000)
qx = (float) 0.28125f;
else
AUDIOBEAM_SET_FLOAT_WORD(qx, ix - 0x01000000);
hz = (float) 0.5f * z - qx;
a = audiobeam_one - qx;
return a - (hz - (z * r - x * y));
}
}
__attribute__((always_inline)) static inline float
audiobeam___kernel_sinf(float x, float y, int iy) {
float z, r, v;
int ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
ix &= 0x7fffffff;
if (ix < 0x32000000) {
if ((int) x == 0)
return x;
}
z = x * x;
v = z * x;
r = audiobeam_S2 +
z * (audiobeam_S3 +
z * (audiobeam_S4 + z * (audiobeam_S5 + z * audiobeam_S6)));
if (iy == 0)
return x + v * (audiobeam_S1 + z * r);
else
return x - ((z * (audiobeam_half * y - v * r) - y) - v * audiobeam_S1);
}
__attribute__((always_inline)) static inline float
audiobeam___copysignf(float x, float y) {
unsigned int ix, iy;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
AUDIOBEAM_GET_FLOAT_WORD(iy, y);
AUDIOBEAM_SET_FLOAT_WORD(x, (ix & 0x7fffffff) | (iy & 0x80000000));
return x;
}
__attribute__((always_inline)) static inline float
audiobeam___cosf(float x) {
float y[2], z = 0.0f;
int n, ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
ix &= 0x7fffffff;
if (ix <= 0x3f490fd8)
return audiobeam___kernel_cosf(x, z);
else if (ix >= 0x7f800000)
return x - x;
else {
y[0] = 0.0;
y[1] = 0.0;
n = audiobeam___ieee754_rem_pio2f(x, y);
switch (n & 3) {
case 0:
return audiobeam___kernel_cosf(y[0], y[1]);
case 1:
return -audiobeam___kernel_sinf(y[0], y[1], 1);
case 2:
return -audiobeam___kernel_cosf(y[0], y[1]);
default:
return audiobeam___kernel_sinf(y[0], y[1], 1);
}
}
}
__attribute__((always_inline)) static inline float
audiobeam___fabsf(float x) {
unsigned int ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
AUDIOBEAM_SET_FLOAT_WORD(x, ix & 0x7fffffff);
return x;
}
__attribute__((always_inline)) static inline float
audiobeam___floorf(float x) {
int i0, j0;
unsigned int i;
AUDIOBEAM_GET_FLOAT_WORD(i0, x);
j0 = ((i0 >> 23) & 0xff) - 0x7f;
if (j0 < 23) {
if (j0 < 0) {
if (audiobeam_huge + x > (float) 0.0f) {
if (i0 >= 0)
i0 = 0;
else if ((i0 & 0x7fffffff) != 0)
i0 = 0xbf800000;
}
} else {
i = (0x007fffff) >> j0;
if ((i0 & i) == 0)
return x;
if (audiobeam_huge + x > (float) 0.0f) {
if (i0 < 0)
i0 += (0x00800000) >> j0;
i0 &= (~i);
}
}
} else {
if (j0 == 0x80)
return x + x;
else
return x;
}
AUDIOBEAM_SET_FLOAT_WORD(x, i0);
return x;
}
__attribute__((always_inline)) static inline int
audiobeam___isinff(float x) {
int ix, t;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
t = ix & 0x7fffffff;
t ^= 0x7f800000;
t |= -t;
return ~(t >> 31) & (ix >> 30);
}
__attribute__((always_inline)) static inline float
audiobeam___scalbnf(float x, int n) {
int k, ix;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
k = (ix & 0x7f800000) >> 23;
if (k == 0) {
if ((ix & 0x7fffffff) == 0)
return x;
x *= audiobeam_two25;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
k = ((ix & 0x7f800000) >> 23) - 25;
}
if (k == 0xff)
return x + x;
k = k + n;
if (n > 50000 || k > 0xfe)
return audiobeam_huge * audiobeam___copysignf(audiobeam_huge, x);
if (n < -50000)
return audiobeam_tiny * audiobeam___copysignf(audiobeam_tiny, x);
if (k > 0) {
AUDIOBEAM_SET_FLOAT_WORD(x, (ix & 0x807fffff) | (k << 23));
return x;
}
if (k <= -25)
return audiobeam_tiny * audiobeam___copysignf(audiobeam_tiny, x);
k += 25;
AUDIOBEAM_SET_FLOAT_WORD(x, (ix & 0x807fffff) | (k << 23));
return x * audiobeam_twom25;
}
__attribute__((always_inline)) static inline float
audiobeam___ceilf(float x) {
int i0, j0;
unsigned int i;
AUDIOBEAM_GET_FLOAT_WORD(i0, x);
j0 = ((i0 >> 23) & 0xff) - 0x7f;
if (j0 < 23) {
if (j0 < 0) {
if (audiobeam_huge + x > (float) 0.0) {
if (i0 < 0)
i0 = 0x80000000;
else if (i0 != 0)
i0 = 0x3f800000;
}
} else {
i = (0x007fffff) >> j0;
if ((i0 & i) == 0)
return x;
if (audiobeam_huge + x > (float) 0.0) {
if (i0 > 0)
i0 += (0x00800000) >> j0;
i0 &= (~i);
}
}
} else {
if (j0 == 0x80)
return x + x;
else
return x;
}
AUDIOBEAM_SET_FLOAT_WORD(x, i0);
return x;
}
__attribute__((always_inline)) static inline float
audiobeam___ieee754_sqrtf(float x) {
float z;
int sign = (int) 0x80000000;
int ix, s, q, m, t, i;
unsigned int r;
AUDIOBEAM_GET_FLOAT_WORD(ix, x);
if ((ix & 0x7f800000) == 0x7f800000)
return x * x + x;
if (ix <= 0) {
if ((ix & (~sign)) == 0)
return x;
else if (ix < 0)
return (x - x) / (x - x);
}
m = (ix >> 23);
if (m == 0) {
__pragma_loopbound(0, 0);
for (i = 0; (ix & 0x00800000) == 0; i++)
ix <<= 1;
m -= i - 1;
}
m -= 127;
ix = (ix & 0x007fffff) | 0x00800000;
if (m & 1)
ix += ix;
m >>= 1;
ix += ix;
q = s = 0;
r = 0x01000000;
__pragma_loopbound(25, 25);
while (r != 0) {
t = s + r;
if (t <= ix) {
s = t + r;
ix -= t;
q += r;
}
ix += ix;
r >>= 1;
}
if (ix != 0) {
z = audiobeam_one - audiobeam_tiny;
if (z >= audiobeam_one) {
z = audiobeam_one + audiobeam_tiny;
if (z > audiobeam_one)
q += 2;
else
q += (q & 1);
}
}
ix = (q >> 1) + 0x3f000000;
ix += (m << 23);
AUDIOBEAM_SET_FLOAT_WORD(z, ix);
return z;
}

View File

@ -0,0 +1,63 @@
/*
This program is part of the TACLeBench benchmark suite.
Version V 2.0
Name: quicksortlibm.c
Author: Ian Lance Taylor
Function: IEEE754 software library routines.
Source: Sun Microsystems and Cygnus
Original name: Unknown
Changes: No major functional changes.
License: See audiobeamlibm.c
*/
#ifndef AUDIOBEAM_LIBM
#define AUDIOBEAM_LIBM
#define audiobeam_M_PI 3.14159265358979323846
static const float audiobeam_one = 1.0f, audiobeam_tiny = 1.0e-30f,
audiobeam_half = 5.0000000000e-01, /* 0x3f000000 */
audiobeam_huge = 1.0e30, audiobeam_two8 = 2.5600000000e+02, /* 0x43800000 */
audiobeam_twon8 = 3.9062500000e-03, /* 0x3b800000 */
audiobeam_zero = 0.0;
#define audiobeam_cos audiobeam___cosf
#define audiobeam_fabs audiobeam___fabsf
#define audiobeam_fabsf audiobeam___fabsf
#define audiobeam_isinf audiobeam___isinff
#define audiobeam_sqrt audiobeam___ieee754_sqrtf
#define audiobeam_ceil audiobeam___ceilf
#define audiobeam_floor audiobeam___floorf
__attribute__((always_inline)) static inline float
audiobeam___copysignf(float x, float y);
__attribute__((always_inline)) static inline float audiobeam___cosf(float x);
__attribute__((always_inline)) static inline float audiobeam___fabsf(float x);
__attribute__((always_inline)) static inline float audiobeam___floorf(float x);
__attribute__((always_inline)) static inline int
audiobeam___ieee754_rem_pio2f(float x, float *y);
__attribute__((always_inline)) static inline float
audiobeam___ieee754_sqrtf(float x);
__attribute__((always_inline)) static inline int audiobeam___isinff(float x);
__attribute__((always_inline)) static inline float
audiobeam___kernel_cosf(float x, float y);
__attribute__((always_inline)) static inline float
audiobeam___kernel_sinf(float x, float y, int iy);
__attribute__((always_inline)) static inline int
audiobeam___kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec,
const int *ipio2);
__attribute__((always_inline)) static inline float audiobeam___scalbnf(float x,
int n);
__attribute__((always_inline)) static inline float audiobeam___ceilf(float x);
__attribute__((always_inline)) static inline float audiobeam___floorf(float x);
#endif // AUDIOBEAM_LIBM

Some files were not shown because too many files have changed in this diff Show More