Add wasm tacle-bench targets
This commit is contained in:
25
targets/wasm-tacle/sequential/adpcm_dec/CMakeLists.txt
Normal file
25
targets/wasm-tacle/sequential/adpcm_dec/CMakeLists.txt
Normal 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)
|
||||
|
||||
|
||||
32
targets/wasm-tacle/sequential/adpcm_dec/ChangeLog.txt
Executable file
32
targets/wasm-tacle/sequential/adpcm_dec/ChangeLog.txt
Executable 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
|
||||
710
targets/wasm-tacle/sequential/adpcm_dec/adpcm_dec.c
Executable file
710
targets/wasm-tacle/sequential/adpcm_dec/adpcm_dec.c
Executable 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() );
|
||||
}
|
||||
BIN
targets/wasm-tacle/sequential/adpcm_dec/generated/default/adpcm_dec.wasm
Executable file
BIN
targets/wasm-tacle/sequential/adpcm_dec/generated/default/adpcm_dec.wasm
Executable file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -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());
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
25
targets/wasm-tacle/sequential/adpcm_enc/CMakeLists.txt
Normal file
25
targets/wasm-tacle/sequential/adpcm_enc/CMakeLists.txt
Normal 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)
|
||||
|
||||
|
||||
34
targets/wasm-tacle/sequential/adpcm_enc/ChangeLog.txt
Executable file
34
targets/wasm-tacle/sequential/adpcm_enc/ChangeLog.txt
Executable 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
|
||||
756
targets/wasm-tacle/sequential/adpcm_enc/adpcm_enc.c
Executable file
756
targets/wasm-tacle/sequential/adpcm_enc/adpcm_enc.c
Executable 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();
|
||||
}
|
||||
BIN
targets/wasm-tacle/sequential/adpcm_enc/generated/default/adpcm_enc.wasm
Executable file
BIN
targets/wasm-tacle/sequential/adpcm_enc/generated/default/adpcm_enc.wasm
Executable file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
28
targets/wasm-tacle/sequential/ammunition/CMakeLists.txt
Normal file
28
targets/wasm-tacle/sequential/ammunition/CMakeLists.txt
Normal 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)
|
||||
|
||||
|
||||
66
targets/wasm-tacle/sequential/ammunition/ChangeLog.txt
Executable file
66
targets/wasm-tacle/sequential/ammunition/ChangeLog.txt
Executable 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.
|
||||
86
targets/wasm-tacle/sequential/ammunition/README
Executable file
86
targets/wasm-tacle/sequential/ammunition/README
Executable 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
|
||||
1179
targets/wasm-tacle/sequential/ammunition/ammunition.c
Executable file
1179
targets/wasm-tacle/sequential/ammunition/ammunition.c
Executable file
File diff suppressed because it is too large
Load Diff
166
targets/wasm-tacle/sequential/ammunition/ammunition_libc.c
Executable file
166
targets/wasm-tacle/sequential/ammunition/ammunition_libc.c
Executable 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;
|
||||
}
|
||||
35
targets/wasm-tacle/sequential/ammunition/ammunition_limits.h
Executable file
35
targets/wasm-tacle/sequential/ammunition/ammunition_limits.h
Executable 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 */
|
||||
8
targets/wasm-tacle/sequential/ammunition/ammunition_stdio.h
Executable file
8
targets/wasm-tacle/sequential/ammunition/ammunition_stdio.h
Executable 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
|
||||
6
targets/wasm-tacle/sequential/ammunition/ammunition_stdlib.h
Executable file
6
targets/wasm-tacle/sequential/ammunition/ammunition_stdlib.h
Executable file
@ -0,0 +1,6 @@
|
||||
#ifndef AMMUNITION_STDLIB_H
|
||||
#define AMMUNITION_STDLIB_H
|
||||
|
||||
int ammunition_atoi ( const char *str );
|
||||
|
||||
#endif
|
||||
18
targets/wasm-tacle/sequential/ammunition/ammunition_string.h
Executable file
18
targets/wasm-tacle/sequential/ammunition/ammunition_string.h
Executable 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 */
|
||||
|
||||
1383
targets/wasm-tacle/sequential/ammunition/arithm.c
Executable file
1383
targets/wasm-tacle/sequential/ammunition/arithm.c
Executable file
File diff suppressed because it is too large
Load Diff
123
targets/wasm-tacle/sequential/ammunition/arithm.h
Executable file
123
targets/wasm-tacle/sequential/ammunition/arithm.h
Executable 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__ */
|
||||
313
targets/wasm-tacle/sequential/ammunition/bits.c
Executable file
313
targets/wasm-tacle/sequential/ammunition/bits.c
Executable 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;
|
||||
}
|
||||
60
targets/wasm-tacle/sequential/ammunition/bits.h
Executable file
60
targets/wasm-tacle/sequential/ammunition/bits.h
Executable 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__ */
|
||||
BIN
targets/wasm-tacle/sequential/ammunition/generated/default/ammunition.wasm
Executable file
BIN
targets/wasm-tacle/sequential/ammunition/generated/default/ammunition.wasm
Executable file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
@ -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 */
|
||||
@ -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
|
||||
@ -0,0 +1,7 @@
|
||||
|
||||
#ifndef AMMUNITION_STDLIB_H
|
||||
#define AMMUNITION_STDLIB_H
|
||||
|
||||
int ammunition_atoi(const char *str);
|
||||
|
||||
#endif
|
||||
@ -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 */
|
||||
File diff suppressed because it is too large
Load Diff
@ -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__ */
|
||||
@ -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;
|
||||
}
|
||||
@ -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__ */
|
||||
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
@ -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 */
|
||||
@ -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
|
||||
@ -0,0 +1,8 @@
|
||||
|
||||
#ifndef AMMUNITION_STDLIB_H
|
||||
#define AMMUNITION_STDLIB_H
|
||||
|
||||
__attribute__((always_inline)) static inline int
|
||||
ammunition_atoi(const char *str);
|
||||
|
||||
#endif
|
||||
@ -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 */
|
||||
File diff suppressed because it is too large
Load Diff
@ -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__ */
|
||||
@ -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;
|
||||
}
|
||||
@ -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__ */
|
||||
27
targets/wasm-tacle/sequential/anagram/CMakeLists.txt
Normal file
27
targets/wasm-tacle/sequential/anagram/CMakeLists.txt
Normal 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)
|
||||
|
||||
|
||||
125
targets/wasm-tacle/sequential/anagram/ChangeLog.txt
Executable file
125
targets/wasm-tacle/sequential/anagram/ChangeLog.txt
Executable 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.
|
||||
661
targets/wasm-tacle/sequential/anagram/anagram.c
Executable file
661
targets/wasm-tacle/sequential/anagram/anagram.c
Executable 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();
|
||||
}
|
||||
27
targets/wasm-tacle/sequential/anagram/anagram_compare.h
Executable file
27
targets/wasm-tacle/sequential/anagram/anagram_compare.h
Executable 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
|
||||
45
targets/wasm-tacle/sequential/anagram/anagram_ctype.h
Executable file
45
targets/wasm-tacle/sequential/anagram/anagram_ctype.h
Executable 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
|
||||
2317
targets/wasm-tacle/sequential/anagram/anagram_input.c
Executable file
2317
targets/wasm-tacle/sequential/anagram/anagram_input.c
Executable file
File diff suppressed because it is too large
Load Diff
149
targets/wasm-tacle/sequential/anagram/anagram_stdlib.c
Executable file
149
targets/wasm-tacle/sequential/anagram/anagram_stdlib.c
Executable 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';}
|
||||
}
|
||||
|
||||
29
targets/wasm-tacle/sequential/anagram/anagram_stdlib.h
Executable file
29
targets/wasm-tacle/sequential/anagram/anagram_stdlib.h
Executable 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
|
||||
27
targets/wasm-tacle/sequential/anagram/anagram_strings.h
Executable file
27
targets/wasm-tacle/sequential/anagram/anagram_strings.h
Executable 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
|
||||
BIN
targets/wasm-tacle/sequential/anagram/generated/default/anagram.wasm
Executable file
BIN
targets/wasm-tacle/sequential/anagram/generated/default/anagram.wasm
Executable file
Binary file not shown.
2403
targets/wasm-tacle/sequential/anagram/generated/default/anagram.wat
Normal file
2403
targets/wasm-tacle/sequential/anagram/generated/default/anagram.wat
Normal file
File diff suppressed because one or more lines are too long
@ -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();
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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"};
|
||||
@ -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';
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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();
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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"};
|
||||
@ -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';
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
28
targets/wasm-tacle/sequential/audiobeam/CMakeLists.txt
Normal file
28
targets/wasm-tacle/sequential/audiobeam/CMakeLists.txt
Normal 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)
|
||||
|
||||
|
||||
86
targets/wasm-tacle/sequential/audiobeam/README
Executable file
86
targets/wasm-tacle/sequential/audiobeam/README
Executable 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
|
||||
585
targets/wasm-tacle/sequential/audiobeam/audiobeam.c
Executable file
585
targets/wasm-tacle/sequential/audiobeam/audiobeam.c
Executable 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() );
|
||||
}
|
||||
|
||||
50
targets/wasm-tacle/sequential/audiobeam/audiobeam.h
Executable file
50
targets/wasm-tacle/sequential/audiobeam/audiobeam.h
Executable 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
|
||||
|
||||
5784
targets/wasm-tacle/sequential/audiobeam/audiobeaminput.c
Executable file
5784
targets/wasm-tacle/sequential/audiobeam/audiobeaminput.c
Executable file
File diff suppressed because it is too large
Load Diff
425
targets/wasm-tacle/sequential/audiobeam/audiobeamlibm.c
Executable file
425
targets/wasm-tacle/sequential/audiobeam/audiobeamlibm.c
Executable 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;
|
||||
}
|
||||
59
targets/wasm-tacle/sequential/audiobeam/audiobeamlibm.h
Executable file
59
targets/wasm-tacle/sequential/audiobeam/audiobeamlibm.h
Executable 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
|
||||
14
targets/wasm-tacle/sequential/audiobeam/audiobeamlibmalloc.c
Executable file
14
targets/wasm-tacle/sequential/audiobeam/audiobeamlibmalloc.c
Executable 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;
|
||||
}
|
||||
27
targets/wasm-tacle/sequential/audiobeam/audiobeamlibmalloc.h
Executable file
27
targets/wasm-tacle/sequential/audiobeam/audiobeamlibmalloc.h
Executable 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
|
||||
69
targets/wasm-tacle/sequential/audiobeam/audiobeamlibmath.h
Executable file
69
targets/wasm-tacle/sequential/audiobeam/audiobeamlibmath.h
Executable 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_ */
|
||||
36
targets/wasm-tacle/sequential/audiobeam/changeLog.txt
Executable file
36
targets/wasm-tacle/sequential/audiobeam/changeLog.txt
Executable 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
|
||||
BIN
targets/wasm-tacle/sequential/audiobeam/generated/default/audiobeam.wasm
Executable file
BIN
targets/wasm-tacle/sequential/audiobeam/generated/default/audiobeam.wasm
Executable file
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -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());
|
||||
}
|
||||
@ -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
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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_ */
|
||||
@ -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());
|
||||
}
|
||||
@ -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
@ -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;
|
||||
}
|
||||
@ -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
Reference in New Issue
Block a user