// // AUTOTEST: identity // void autotest_matrixcf_eye() { float complex x[16]= { 9+ 4*_I, 4+ 9*_I, 5+ 4*_I, 4+ 5*_I, 3+ 9*_I, 9+ 2*_I, 9+ 7*_I, 9+ 2*_I, 9+ 4*_I, 1+ 9*_I, 8+ 6*_I, 0+ 2*_I, 4+ 9*_I, 3+ 6*_I, 3+ 3*_I, 7+ 8*_I }; float complex I4_test[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}; float complex y[16]; float complex z[16]; // generate identity matrix matrixcf_eye(y,4); CONTEND_SAME_DATA(y, I4_test, 16*sizeof(float complex)); // multiply with input matrixcf_mul(x, 4, 4, y, 4, 4, z, 4, 4); CONTEND_SAME_DATA(x, z, 16*sizeof(float complex)); }
// // AUTOTEST: wdelayf // void autotest_wdelayf() { float v; // reader unsigned int i; // create wdelay // wdelay: 0 0 0 0 wdelayf w = wdelayf_create(4); wdelayf_read(w, &v); CONTEND_EQUALITY(v, 0); float x0[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; float y0_test[10] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6}; float y0[10]; for (i=0; i<10; i++) { wdelayf_read(w, &y0[i]); wdelayf_push(w, x0[i]); //printf("%3u : %6.2f (%6.2f)\n", i, y0[i], y0_test[i]); } // 7 8 9 10 CONTEND_SAME_DATA(y0, y0_test, 10*sizeof(float)); // re-create wdelay object // wdelay: 0 0 7 8 9 10 w = wdelayf_recreate(w,6); float x1[10] = {3, 4, 5, 6, 7, 8, 9, 2, 2, 2}; float y1_test[10]= {0, 0, 7, 8, 9, 10,3, 4, 5, 6}; float y1[10]; for (i=0; i<10; i++) { wdelayf_read(w, &y1[i]); wdelayf_push(w, x1[i]); //printf("%3u : %6.2f (%6.2f)\n", i, y1[i], y1_test[i]); } // wdelay: 7 8 9 2 2 2 CONTEND_SAME_DATA(y1, y1_test, 10*sizeof(float)); // re-create wdelay object // wdelay: 8 9 2 2 2 w = wdelayf_recreate(w,5); float x2[10] = {1, 1, 1, 1, 1, 1, 1, 2, 3, 4}; float y2_test[10]= {8, 9, 2, 2, 2, 1, 1, 1, 1, 1}; float y2[10]; for (i=0; i<10; i++) { wdelayf_read(w, &y2[i]); wdelayf_push(w, x2[i]); //printf("%3u : %6.2f (%6.2f)\n", i, y1[i], y1_test[i]); } // wdelay: 1 1 2 3 4 CONTEND_SAME_DATA(y2, y2_test, 10*sizeof(float)); // destroy object wdelayf_destroy(w); }
void autotest_fft_shift_8() { float complex x[] = { 0 + 0*_Complex_I, 1 + 1*_Complex_I, 2 + 2*_Complex_I, 3 + 3*_Complex_I, 4 + 4*_Complex_I, 5 + 5*_Complex_I, 6 + 6*_Complex_I, 7 + 7*_Complex_I }; float complex test[] = { 4 + 4*_Complex_I, 5 + 5*_Complex_I, 6 + 6*_Complex_I, 7 + 7*_Complex_I, 0 + 0*_Complex_I, 1 + 1*_Complex_I, 2 + 2*_Complex_I, 3 + 3*_Complex_I }; fft_shift(x,8); CONTEND_SAME_DATA(x,test,8*sizeof(float complex)); }
// // AUTOTEST: Test matrixcf ops // void autotest_matrixcf_mul() { float complex x[6] = { 9+ 9*_I, 3+ 4*_I, 8+ 3*_I, 0+ 3*_I, 6+ 10*_I, 6+ 1*_I }; float complex y[9] = { 8+ 7*_I, 4+ 9*_I, 4+ 1*_I, 5+ 6*_I, 10+ 2*_I, 6+ 3*_I, 6+ 9*_I, 2+ 8*_I, 5+ 5*_I }; float complex z[6]; float complex ztest[6] = { 21+263*_I, -31+233*_I, 58+133*_I, -24+170*_I, 17+174*_I, 28+125*_I }; matrixcf_mul(x,2,3, y,3,3, z,2,3); if (liquid_autotest_verbose) matrixcf_print(z,2,3); CONTEND_SAME_DATA(z,ztest,sizeof(z)); }
// test unscrambling of soft bits (helper function to keep code base small) void liquid_scramble_soft_test(unsigned int _n) { unsigned char msg_org[_n]; // input data unsigned char msg_enc[_n]; // scrambled data unsigned char msg_soft[8*_n]; // scrambled data (soft bits) unsigned char msg_dec[_n]; // unscrambled data unsigned int i; // initialize data array (random) for (i=0; i<_n; i++) msg_org[i] = rand() & 0xff; // scramble input memmove(msg_enc, msg_org, _n); scramble_data(msg_enc,_n); // convert to soft bits for (i=0; i<_n; i++) liquid_unpack_soft_bits(msg_enc[i], 8, &msg_soft[8*i]); // unscramble result unscramble_data_soft(msg_soft, _n); // unpack soft bits for (i=0; i<_n; i++) { unsigned int sym_out; liquid_pack_soft_bits(&msg_soft[8*i], 8, &sym_out); msg_dec[i] = sym_out; } // ensure data are equivalent CONTEND_SAME_DATA(msg_org, msg_dec, _n); }
// helper function to keep code base small void liquid_scramble_test(unsigned int _n) { unsigned char x[_n]; // input data unsigned char y[_n]; // scrambled data unsigned char z[_n]; // unscrambled data unsigned int i; // initialize data array for (i=0; i<_n; i++) x[i] = 0x00; // scramble input memmove(y,x,_n); scramble_data(y,_n); // unscramble result memmove(z,y,_n); unscramble_data(z,_n); // ensure data are equivalent CONTEND_SAME_DATA(x,z,_n*sizeof(unsigned char)); // compute entropy metric float H = liquid_scramble_test_entropy(y,_n); CONTEND_EXPRESSION( H > 0.8f ); }
// Helper function to keep code base small void fec_test_codec(fec_scheme _fs, unsigned int _n, void * _opts) { #if !LIBFEC_ENABLED if ( _fs == LIQUID_FEC_CONV_V27 || _fs == LIQUID_FEC_CONV_V29 || _fs == LIQUID_FEC_CONV_V39 || _fs == LIQUID_FEC_CONV_V615 || _fs == LIQUID_FEC_CONV_V27P23 || _fs == LIQUID_FEC_CONV_V27P34 || _fs == LIQUID_FEC_CONV_V27P45 || _fs == LIQUID_FEC_CONV_V27P56 || _fs == LIQUID_FEC_CONV_V27P67 || _fs == LIQUID_FEC_CONV_V27P78 || _fs == LIQUID_FEC_CONV_V29P23 || _fs == LIQUID_FEC_CONV_V29P34 || _fs == LIQUID_FEC_CONV_V29P45 || _fs == LIQUID_FEC_CONV_V29P56 || _fs == LIQUID_FEC_CONV_V29P67 || _fs == LIQUID_FEC_CONV_V29P78 || _fs == LIQUID_FEC_RS_M8) { AUTOTEST_WARN("convolutional, Reed-Solomon codes unavailable (install libfec)\n"); return; } #endif // generate fec object fec q = fec_create(_fs,_opts); // create arrays unsigned int n_enc = fec_get_enc_msg_length(_fs,_n); unsigned char msg[_n]; // original message unsigned char msg_enc[n_enc]; // encoded message unsigned char msg_dec[_n]; // decoded message // initialze message unsigned int i; for (i=0; i<_n; i++) { msg[i] = rand() & 0xff; msg_dec[i] = 0; } // encode message fec_encode(q,_n,msg,msg_enc); // channel: add single error msg_enc[0] ^= 0x01; // decode message fec_decode(q,_n,msg_enc,msg_dec); // validate output CONTEND_SAME_DATA(msg,msg_dec,_n); // clean up objects fec_destroy(q); }
// // AUTOTEST: repeat/3 codec // void autotest_rep5_codec() { unsigned int n=4; unsigned char msg[] = {0x25, 0x62, 0x3F, 0x52}; fec_scheme fs = LIQUID_FEC_REP5; // create arrays unsigned int n_enc = fec_get_enc_msg_length(fs,n); unsigned char msg_dec[n]; unsigned char msg_enc[n_enc]; // create object fec q = fec_create(fs,NULL); if (liquid_autotest_verbose) fec_print(q); // encode message fec_encode(q, n, msg, msg_enc); // corrupt encoded message, but no so much that it // can't be decoded msg_enc[ 0] = ~msg_enc[ 0]; msg_enc[ 4] = ~msg_enc[ 4]; // msg_enc[ 8] = ~msg_enc[ 8]; // msg_enc[12] = ~msg_enc[12]; // msg_enc[16] = ~msg_enc[16]; msg_enc[ 1] = ~msg_enc[ 1]; // msg_enc[ 5] = ~msg_enc[ 5]; msg_enc[ 9] = ~msg_enc[ 9]; // msg_enc[13] = ~msg_enc[13]; // msg_enc[17] = ~msg_enc[17]; // msg_enc[ 2] = ~msg_enc[ 2]; // msg_enc[ 6] = ~msg_enc[ 6]; msg_enc[10] = ~msg_enc[10]; msg_enc[14] = ~msg_enc[14]; // msg_enc[18] = ~msg_enc[18]; msg_enc[ 3] = ~msg_enc[ 3]; // msg_enc[ 7] = ~msg_enc[ 7]; // msg_enc[11] = ~msg_enc[11]; // msg_enc[15] = ~msg_enc[15]; msg_enc[19] = ~msg_enc[19]; // decode message fec_decode(q, n, msg_enc, msg_dec); // validate data are the same CONTEND_SAME_DATA(msg, msg_dec, n); // clean up objects fec_destroy(q); }
// // AUTOTEST : rbshift // void autotest_rbshift() { // input : 1000 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1000 0001 1110 1111 0101 1111 1010 1010 // output [1] : 0100 0000 1111 0111 1010 1111 1101 0101 // output [2] : 0010 0000 0111 1011 1101 0111 1110 1010 // output [3] : 0001 0000 0011 1101 1110 1011 1111 0101 // output [4] : 0000 1000 0001 1110 1111 0101 1111 1010 // output [5] : 0000 0100 0000 1111 0111 1010 1111 1101 // output [6] : 0000 0010 0000 0111 1011 1101 0111 1110 // output [7] : 0000 0001 0000 0011 1101 1110 1011 1111 unsigned char input[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x81, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0x40, 0xF7, 0xAF, 0xD5}; unsigned char output_test_2[4] = {0x20, 0x7B, 0xD7, 0xEA}; unsigned char output_test_3[4] = {0x10, 0x3D, 0xEB, 0xF5}; unsigned char output_test_4[4] = {0x08, 0x1E, 0xF5, 0xFA}; unsigned char output_test_5[4] = {0x04, 0x0F, 0x7A, 0xFD}; unsigned char output_test_6[4] = {0x02, 0x07, 0xBD, 0x7E}; unsigned char output_test_7[4] = {0x01, 0x03, 0xDE, 0xBF}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<8; i++) { memmove(output, input, 4); liquid_rbshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; case 5: CONTEND_SAME_DATA( output, output_test_5, 4 ); break; case 6: CONTEND_SAME_DATA( output, output_test_6, 4 ); break; case 7: CONTEND_SAME_DATA( output, output_test_7, 4 ); break; default:; } } }
// // AUTOTEST : lbcircshift // void autotest_lbcircshift() { // input : 1001 0001 1110 1111 0101 1111 1010 1010 // output [0] : 1001 0001 1110 1111 0101 1111 1010 1010 // output [1] : 0010 0011 1101 1110 1011 1111 0101 0101 // output [2] : 0100 0111 1011 1101 0111 1110 1010 1010 // output [3] : 1000 1111 0111 1010 1111 1101 0101 0100 // output [4] : 0001 1110 1111 0101 1111 1010 1010 1001 // output [5] : 0011 1101 1110 1011 1111 0101 0101 0010 // output [6] : 0111 1011 1101 0111 1110 1010 1010 0100 // output [7] : 1111 0111 1010 1111 1101 0101 0100 1000 unsigned char input[4] = {0x91, 0xEF, 0x5F, 0xAA}; unsigned char output_test_0[4] = {0x91, 0xEF, 0x5F, 0xAA}; unsigned char output_test_1[4] = {0x23, 0xDE, 0xBF, 0x55}; unsigned char output_test_2[4] = {0x47, 0xBD, 0x7E, 0xAA}; unsigned char output_test_3[4] = {0x8F, 0x7A, 0xFD, 0x54}; unsigned char output_test_4[4] = {0x1E, 0xF5, 0xFA, 0xA9}; unsigned char output_test_5[4] = {0x3D, 0xEB, 0xF5, 0x52}; unsigned char output_test_6[4] = {0x7B, 0xD7, 0xEA, 0xA4}; unsigned char output_test_7[4] = {0xF7, 0xAF, 0xD5, 0x48}; unsigned char output[4]; // // run tests // unsigned int i; for (i=0; i<8; i++) { memmove(output, input, 4); liquid_lbcircshift( output, 4, i); switch (i) { case 0: CONTEND_SAME_DATA( output, output_test_0, 4 ); break; case 1: CONTEND_SAME_DATA( output, output_test_1, 4 ); break; case 2: CONTEND_SAME_DATA( output, output_test_2, 4 ); break; case 3: CONTEND_SAME_DATA( output, output_test_3, 4 ); break; case 4: CONTEND_SAME_DATA( output, output_test_4, 4 ); break; case 5: CONTEND_SAME_DATA( output, output_test_5, 4 ); break; case 6: CONTEND_SAME_DATA( output, output_test_6, 4 ); break; case 7: CONTEND_SAME_DATA( output, output_test_7, 4 ); break; default:; } } }
// // AUTOTEST : test simple recovery of frame in noise // void qpacketmodem_test(unsigned int _payload_len, int _check, int _fec0, int _fec1, int _ms) { // derived values unsigned int i; // create and configure packet encoder/decoder object qpacketmodem q = qpacketmodem_create(); qpacketmodem_configure(q, _payload_len, _check, _fec0, _fec1, _ms); if (liquid_autotest_verbose) qpacketmodem_print(q); // initialize payload unsigned char payload_tx[_payload_len]; unsigned char payload_rx[_payload_len]; // initialize payload for (i=0; i<_payload_len; i++) { payload_tx[i] = rand() & 0xff; payload_rx[i] = rand() & 0xff; } // get frame length unsigned int frame_len = qpacketmodem_get_frame_len(q); // allocate memory for frame samples float complex frame[frame_len]; // encode frame qpacketmodem_encode(q, payload_tx, frame); // decode frame int crc_pass = qpacketmodem_decode(q, frame, payload_rx); // destroy object qpacketmodem_destroy(q); // check to see that frame was recovered CONTEND_EQUALITY( crc_pass, 1 ); CONTEND_SAME_DATA( payload_tx, payload_rx, _payload_len ); }
void autotest_fft_shift_4() { float complex x[] = { 0 + 0*_Complex_I, 1 + 1*_Complex_I, 2 + 2*_Complex_I, 3 + 3*_Complex_I }; float complex test[] = { 2 + 2*_Complex_I, 3 + 3*_Complex_I, 0 + 0*_Complex_I, 1 + 1*_Complex_I }; fft_shift(x,4); CONTEND_SAME_DATA(x,test,4*sizeof(float complex)); }
// // AUTOTEST: Test matrixcf add // void autotest_matrixcf_add() { float complex x[6] = { 2+ 3*_I, 10+ 9*_I, 1+ 3*_I, 7+ 2*_I, 8+ 6*_I, 3+ 1*_I }; float complex y[6] = { 7+ 3*_I, 4+ 8*_I, 6+ 6*_I, 1+ 9*_I, 7+ 10*_I, 5+ 1*_I }; float complex z[6]; float complex ztest[6] = { 9+ 6*_I, 14+ 17*_I, 7+ 9*_I, 8+ 11*_I, 15+ 16*_I, 8+ 2*_I }; matrixcf_add(x,y,z,2,3); CONTEND_SAME_DATA(z,ztest,sizeof(z)); }
// // AUTOTEST: Hamming (7,4) codec // void autotest_hamming74_codec() { unsigned int n=4; unsigned char msg[] = {0x25, 0x62, 0x3F, 0x52}; fec_scheme fs = LIQUID_FEC_HAMMING74; // create arrays unsigned int n_enc = fec_get_enc_msg_length(fs,n); unsigned char msg_dec[n]; unsigned char msg_enc[n_enc]; // create object fec q = fec_create(fs,NULL); if (liquid_autotest_verbose) fec_print(q); // encode message fec_encode(q, n, msg, msg_enc); // corrupt encoded message msg_enc[0] ^= 0x04; // position 5 #if 0 msg_enc[1] ^= 0x04; // msg_enc[2] ^= 0x02; // msg_enc[3] ^= 0x01; // msg_enc[4] ^= 0x80; // msg_enc[5] ^= 0x40; // msg_enc[6] ^= 0x20; // #endif // decode message fec_decode(q, n, msg_enc, msg_dec); // validate data are the same CONTEND_SAME_DATA(msg, msg_dec, n); // clean up objects fec_destroy(q); }
// floating point void autotest_cbufferf() { // input array of values float v[] = {1, 2, 3, 4, 5, 6, 7, 8}; // output test arrays float test1[] = {1, 2, 3, 4}; float test2[] = {3, 4, 1, 2, 3, 4, 5, 6, 7, 8}; float test3[] = {3, 4, 5, 6, 7, 8}; float test4[] = {3, 4, 5, 6, 7, 8, 1, 2, 3}; float *r; // output read pointer unsigned int num_requested; // number of samples requested unsigned int num_read; // number of samples read // create new circular buffer with 10 elements cbufferf q = cbufferf_create(10); // cbuffer: { <empty> } // part 1: write 4 elements to the buffer cbufferf_write(q, v, 4); // cbuffer: {1 2 3 4} // part 2: try to read 4 elements num_requested = 4; cbufferf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,4); CONTEND_SAME_DATA(r,test1,4*sizeof(float)); // part 3: release two elements, write 8 more, read 10 cbufferf_release(q, 2); // cbuffer: {3 4} cbufferf_write(q, v, 8); // cbuffer: {3 4 1 2 3 4 5 6 7 8} num_requested = 10; cbufferf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,10); CONTEND_SAME_DATA(r,test2,10*sizeof(float)); // part 4: pop single element from buffer CONTEND_EQUALITY( cbufferf_size(q), 10 ); cbufferf_pop(q, r); // cbuffer: {4 1 2 3 4 5 6 7 8} CONTEND_EQUALITY( cbufferf_size(q), 9 ); CONTEND_EQUALITY( *r, 3.0f ); // part 5: release three elements, and try reading 10 cbufferf_release(q, 3); // cbuffer: {3 4 5 6 7 8} num_requested = 10; cbufferf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,6); CONTEND_SAME_DATA(r,test3,6*sizeof(float)); // part 6: test pushing multiple elements cbufferf_push(q, 1); cbufferf_push(q, 2); cbufferf_push(q, 3); // cbuffer: {3 4 5 6 7 8 1 2 3} num_requested = 10; cbufferf_read(q, num_requested, &r, &num_read); CONTEND_EQUALITY(num_read,9); CONTEND_SAME_DATA(r,test4,9*sizeof(float)); // part 7: add one more element; buffer should be full CONTEND_EXPRESSION( cbufferf_is_full(q)==0 ); cbufferf_push(q, 1); // cbuffer: {3 4 5 6 7 8 1 2 3 1} CONTEND_EXPRESSION( cbufferf_is_full(q)==1 ); // memory leaks are evil cbufferf_destroy(q); }
// // AUTOTEST: windowf // void autotest_windowf() { float v[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; float *r; // reader pointer float x; // temporary value holder unsigned int i; float test0[10] = {0,0,0,0,0,0,0,0,0,0}; float test1[10] = {0,0,0,0,0,0,1,1,1,1}; float test2[10] = {0,0,1,1,1,1,9,8,7,6}; float test3[10] = {1,1,9,8,7,6,3,3,3,3}; float test4[10] = {7,6,3,3,3,3,5,5,5,5}; float test5[6] = {3,3,5,5,5,5}; float test6[6] = {5,5,5,5,6,7}; float test7[10] = {0,0,0,0,5,5,5,5,6,7}; float test8[10] = {0,0,0,0,0,0,0,0,0,0}; // create window // 0 0 0 0 0 0 0 0 0 0 windowf w = windowf_create(10); windowf_read(w, &r); CONTEND_SAME_DATA(r,test0,10*sizeof(float)); // push 4 elements // 0 0 0 0 0 0 1 1 1 1 windowf_push(w, 1); windowf_push(w, 1); windowf_push(w, 1); windowf_push(w, 1); windowf_read(w, &r); CONTEND_SAME_DATA(r,test1,10*sizeof(float)); // push 4 more elements // 0 0 1 1 1 1 9 8 7 6 windowf_write(w, v, 4); windowf_read(w, &r); CONTEND_SAME_DATA(r,test2,10*sizeof(float)); // push 4 more elements // 1 1 9 8 7 6 3 3 3 3 windowf_push(w, 3); windowf_push(w, 3); windowf_push(w, 3); windowf_push(w, 3); windowf_read(w, &r); CONTEND_SAME_DATA(r,test3,10*sizeof(float)); // test indexing operation windowf_index(w, 0, &x); CONTEND_EQUALITY(x, 1); windowf_index(w, 1, &x); CONTEND_EQUALITY(x, 1); windowf_index(w, 2, &x); CONTEND_EQUALITY(x, 9); windowf_index(w, 3, &x); CONTEND_EQUALITY(x, 8); windowf_index(w, 4, &x); CONTEND_EQUALITY(x, 7); windowf_index(w, 5, &x); CONTEND_EQUALITY(x, 6); windowf_index(w, 6, &x); CONTEND_EQUALITY(x, 3); windowf_index(w, 7, &x); CONTEND_EQUALITY(x, 3); windowf_index(w, 8, &x); CONTEND_EQUALITY(x, 3); windowf_index(w, 9, &x); CONTEND_EQUALITY(x, 3); // push 4 more elements // 7 6 3 3 3 3 5 5 5 5 windowf_push(w, 5); windowf_push(w, 5); windowf_push(w, 5); windowf_push(w, 5); windowf_read(w, &r); CONTEND_SAME_DATA(r,test4,10*sizeof(float)); if (liquid_autotest_verbose) windowf_debug_print(w); // recreate window (truncate to last 6 elements) // 3 3 5 5 5 5 w = windowf_recreate(w,6); windowf_read(w, &r); CONTEND_SAME_DATA(r,test5,6*sizeof(float)); // push 2 more elements // 5 5 5 5 6 7 windowf_push(w, 6); windowf_push(w, 7); windowf_read(w, &r); CONTEND_SAME_DATA(r,test6,6*sizeof(float)); // recreate window (extend to 10 elements) // 0 0 0 0 5 5 5 5 6 7 w = windowf_recreate(w,10); windowf_read(w,&r); CONTEND_SAME_DATA(r,test7,10*sizeof(float)); // reset // 0 0 0 0 0 0 0 0 0 0 windowf_reset(w); windowf_read(w, &r); CONTEND_SAME_DATA(r,test8,10*sizeof(float)); if (liquid_autotest_verbose) { // manual print printf("manual output:\n"); for (i=0; i<10; i++) printf("%6u : %f\n", i, r[i]); windowf_debug_print(w); } windowf_destroy(w); printf("done.\n"); }