1 /* TA-LIB Copyright (c) 1999-2007, Mario Fortier
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
6 * conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * - Neither name of author nor the names of its contributors
17 * may be used to endorse or promote products derived from this
18 * software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /* List of contributors:
35 *
36 * Initial Name/description
37 * -------------------------------------------------------------------
38 * MF Mario Fortier
39 *
40 *
41 * Change history:
42 *
43 * MMDDYY BY Description
44 * -------------------------------------------------------------------
45 * 112400 MF First version.
46 *
47 */
48
49 /* Description:
50 * Provide utility function internally used in ta_regtest only.
51 */
52
53 /**** Headers ****/
54 #ifdef WIN32
55 #include "windows.h"
56 #endif
57
58 #include <stdio.h>
59 #include <string.h>
60 #include <stdlib.h>
61 #include <time.h>
62 #include "ta_test_priv.h"
63 #include "ta_utility.h"
64 #include "ta_memory.h"
65
66
67 /**** External functions declarations. ****/
68 /* None */
69
70 /**** External variables declarations. ****/
71 extern int nbProfiledCall;
72 extern double timeInProfiledCall;
73 extern double worstProfiledCall;
74 extern int insufficientClockPrecision;
75
76 /**** Global variables definitions. ****/
77
78 /* Global temporary buffers used while testing. */
79 #define RESV_PATTERN_MEMGUARD_1 (2.4789205E-150)
80 #define RESV_PATTERN_MEMGUARD_2 (4.2302468E-165)
81
82 #define RESV_PATTERN_PREFIX (9.1349043E-200)
83 #define RESV_PATTERN_SUFFIX (8.1489031E-158)
84 #define RESV_PATTERN_IMPROBABLE (-2.849284E-199)
85
86 #define RESV_PATTERN_PREFIX_INT (TA_INTEGER_DEFAULT)
87 #define RESV_PATTERN_SUFFIX_INT (TA_INTEGER_DEFAULT)
88 #define RESV_PATTERN_IMPROBABLE_INT (TA_INTEGER_DEFAULT)
89
90 #define TA_BUF_PREFIX 100
91 #define TA_BUF_SUFFIX 100
92 #define TA_BUF_SIZE (TA_BUF_PREFIX+MAX_NB_TEST_ELEMENT+TA_BUF_SUFFIX)
93
94 #define TA_NB_OUT 3
95 #define TA_NB_IN 1
96 #define TA_NB_OUT_IN (TA_NB_OUT+TA_NB_IN)
97
98 TA_Real memoryGuard1 = RESV_PATTERN_MEMGUARD_1; /* Magic number to detect problem. */
99 TA_Real buf[NB_GLOBAL_BUFFER][TA_NB_OUT_IN][TA_BUF_SIZE]; /* The global buffers. */
100 TA_Real memoryGuard2 = RESV_PATTERN_MEMGUARD_2; /* Magic number to detect problem. */
101
102 #define NB_TOTAL_ELEMENTS (sizeof(buf)/sizeof(TA_Real))
103
104 TestBuffer gBuffer[5]; /* See initGlobalBuffer. */
105
106 /**** Local declarations. ****/
107 /* None */
108
109 /**** Local functions declarations. ****/
110 static ErrorNumber doRangeTestFixSize( RangeTestFunction testFunction,
111 void *opaqueData,
112 TA_Integer refOutBeg,
113 TA_Integer refOutNbElement,
114 TA_Integer refLookback,
115 const TA_Real *refBuffer,
116 const TA_Integer *refBufferInt,
117 TA_FuncUnstId unstId,
118 TA_Integer fixSize,
119 unsigned int outputNb,
120 unsigned int integerTolerance );
121
122 static int dataWithinReasonableRange( TA_Real val1, TA_Real val2,
123 unsigned int outputPosition,
124 TA_FuncUnstId unstId,
125 unsigned int integerTolerance );
126
127 static ErrorNumber doRangeTestForOneOutput( RangeTestFunction testFunction,
128 TA_FuncUnstId unstId,
129 void *opaqueData,
130 unsigned int outputNb,
131 unsigned int integerTolerance );
132
133 static TA_RetCode CallTestFunction( RangeTestFunction testFunction,
134 TA_Integer startIdx,
135 TA_Integer endIdx,
136 TA_Real *outputBuffer,
137 TA_Integer *outputBufferInt,
138 TA_Integer *outBegIdx,
139 TA_Integer *outNbElement,
140 TA_Integer *lookback,
141 void *opaqueData,
142 unsigned int outputNb,
143 unsigned int *isOutputInteger );
144
145 /**** Local variables definitions. ****/
146 /* None */
147
148 /**** Global functions definitions. ****/
149 static int ta_g_val = 0;
150 static const char *ta_g_wheel = "-\\|/";
showFeedback()151 void showFeedback()
152 {
153 if( ta_g_wheel[ta_g_val] == '\0' )
154 ta_g_val = 0;
155 putchar('\b');
156 putchar(ta_g_wheel[ta_g_val]);
157 fflush(stdout);
158 ta_g_val++;
159 }
160
hideFeedback()161 void hideFeedback()
162 {
163 putchar('\b');
164 fflush(stdout);
165 ta_g_val = 0;
166 }
167
allocLib()168 ErrorNumber allocLib()
169 {
170 TA_RetCode retCode;
171
172 /* Initialize the library. */
173 retCode = TA_Initialize();
174 if( retCode != TA_SUCCESS )
175 {
176 printf( "TA_Initialize failed [%d]\n", retCode );
177 return TA_TESTUTIL_INIT_FAILED;
178 }
179
180 return TA_TEST_PASS;
181 }
182
freeLib()183 ErrorNumber freeLib()
184 {
185 TA_RetCode retCode;
186
187 /* For testing purpose */
188 /* TA_FATAL_RET( "Test again", 100, 200, 0 ); */
189
190 retCode = TA_Shutdown();
191 if( retCode != TA_SUCCESS )
192 {
193 printf( "TA_Shutdown failed [%d]\n", retCode );
194 return TA_TESTUTIL_SHUTDOWN_FAILED;
195 }
196
197 return TA_TEST_PASS;
198 }
199
reportError(const char * str,TA_RetCode retCode)200 void reportError( const char *str, TA_RetCode retCode )
201 {
202 TA_RetCodeInfo retCodeInfo;
203
204 TA_SetRetCodeInfo( retCode, &retCodeInfo );
205
206 printf( "%s,%d==%s\n", str, retCode, retCodeInfo.enumStr );
207 printf( "[%s]\n", retCodeInfo.infoStr );
208 }
209
210 /* Need to be called only once. */
initGlobalBuffer(void)211 void initGlobalBuffer( void )
212 {
213 gBuffer[0].in = &buf[0][0][TA_BUF_PREFIX];
214 gBuffer[0].out0 = &buf[0][1][TA_BUF_PREFIX];
215 gBuffer[0].out1 = &buf[0][2][TA_BUF_PREFIX];
216 gBuffer[0].out2 = &buf[0][3][TA_BUF_PREFIX];
217
218 gBuffer[1].in = &buf[1][0][TA_BUF_PREFIX];
219 gBuffer[1].out0 = &buf[1][1][TA_BUF_PREFIX];
220 gBuffer[1].out1 = &buf[1][2][TA_BUF_PREFIX];
221 gBuffer[1].out2 = &buf[1][3][TA_BUF_PREFIX];
222
223 gBuffer[2].in = &buf[2][0][TA_BUF_PREFIX];
224 gBuffer[2].out0 = &buf[2][1][TA_BUF_PREFIX];
225 gBuffer[2].out1 = &buf[2][2][TA_BUF_PREFIX];
226 gBuffer[2].out2 = &buf[2][3][TA_BUF_PREFIX];
227
228 gBuffer[3].in = &buf[3][0][TA_BUF_PREFIX];
229 gBuffer[3].out0 = &buf[3][1][TA_BUF_PREFIX];
230 gBuffer[3].out1 = &buf[3][2][TA_BUF_PREFIX];
231 gBuffer[3].out2 = &buf[3][3][TA_BUF_PREFIX];
232
233 gBuffer[4].in = &buf[4][0][TA_BUF_PREFIX];
234 gBuffer[4].out0 = &buf[4][1][TA_BUF_PREFIX];
235 gBuffer[4].out1 = &buf[4][2][TA_BUF_PREFIX];
236 gBuffer[4].out2 = &buf[4][3][TA_BUF_PREFIX];
237 }
238
239 /* Will set some values in the buffers allowing
240 * to detect later if the function is writing
241 * out-of-bound (and to make sure the
242 * function is writing exactly the number
243 * of values it pretends to do).
244 */
clearAllBuffers(void)245 void clearAllBuffers( void )
246 {
247 unsigned int i,j,k;
248
249 for( i=0; i < NB_GLOBAL_BUFFER; i++ )
250 {
251 for( j=0; j < TA_NB_OUT_IN; j++ )
252 {
253 for( k=0; k < TA_BUF_PREFIX; k++ )
254 buf[i][j][k] = RESV_PATTERN_PREFIX;
255 for( ; k < TA_BUF_SIZE; k++ )
256 buf[i][j][k] = RESV_PATTERN_SUFFIX;
257 }
258 }
259 }
260
setInputBuffer(unsigned int i,const TA_Real * data,unsigned int nbElement)261 void setInputBuffer( unsigned int i, const TA_Real *data, unsigned int nbElement )
262 {
263 unsigned int j;
264 for( j=0; j < nbElement; j++ )
265 buf[i][0][j+TA_BUF_PREFIX] = data[j];
266 }
267
setInputBufferValue(unsigned int i,const TA_Real data,unsigned int nbElement)268 void setInputBufferValue( unsigned int i, const TA_Real data, unsigned int nbElement )
269 {
270 unsigned int j;
271 for( j=0; j < nbElement; j++ )
272 buf[i][0][j+TA_BUF_PREFIX] = data;
273
274 }
275
276 /* Check that a buffer (within a TestBuffer) is not containing
277 * NAN (or any reserved "impossible" value) within the specified
278 * range (it also checks that all out-of-bound values are untouch).
279 *
280 * Return 1 on success.
281 */
checkForNAN(const TA_Real * buffer,unsigned int nbElement)282 ErrorNumber checkForNAN( const TA_Real *buffer,
283 unsigned int nbElement )
284 {
285 unsigned int i;
286 unsigned int idx;
287
288 const TA_Real *theBuffer;
289 theBuffer = buffer - TA_BUF_PREFIX;
290
291 /* Check that the prefix are all still untouch. */
292 for( idx=0; idx < TA_BUF_PREFIX; idx++ )
293 {
294 if( theBuffer[idx] != RESV_PATTERN_PREFIX )
295 {
296 printf( "Fail: Out of range writing in prefix buffer (%d,%f)\n", idx, theBuffer[idx] );
297 return TA_TEST_TFRR_OVERLAP_OR_NAN_0;
298 }
299 }
300
301 if( nbElement > MAX_NB_TEST_ELEMENT )
302 {
303 printf( "Fail: outNbElement is out of range 0 (%d)\n", nbElement );
304 return TA_TEST_TFRR_NB_ELEMENT_OUT_OF_RANGE;
305 }
306
307 /* Check that no NAN (or reserved "impossible" value) exist
308 * in the specified range.
309 */
310 for( i=0; i < nbElement; i++,idx++ )
311 {
312 /* TODO Add back some nan/inf checking
313 if( trio_isnan(theBuffer[idx]) )
314 {
315 printf( "Fail: Not a number find within the data (%d,%f)\n", i, theBuffer[idx] );
316 return TA_TEST_TFRR_OVERLAP_OR_NAN_1;
317 }
318
319 if( trio_isinf(theBuffer[idx]) )
320 {
321 printf( "Fail: Not a number find within the data (%d,%f)\n", i, theBuffer[idx] );
322 return TA_TEST_TFRR_OVERLAP_OR_NAN_2;
323 }*/
324
325 if( theBuffer[idx] == RESV_PATTERN_PREFIX )
326 {
327 printf( "Fail: Not a number find within the data (%d,%f)\n", i, theBuffer[idx] );
328 return TA_TEST_TFRR_OVERLAP_OR_NAN_3;
329 }
330
331 if( theBuffer[idx] == RESV_PATTERN_SUFFIX )
332 {
333 printf( "Fail: Not a number find within the data (%d,%f)\n", i, theBuffer[idx] );
334 return TA_TEST_TFRR_OVERLAP_OR_NAN_4;
335 }
336 }
337
338 /* Make sure that the remaining of the buffer is untouch. */
339 for( ; idx < TA_BUF_SIZE; idx++ )
340 {
341 if( theBuffer[idx] != RESV_PATTERN_SUFFIX )
342 {
343 printf( "Fail: Out of range writing in suffix buffer (%d,%f)\n", idx, theBuffer[idx] );
344 return TA_TEST_TFRR_OVERLAP_OR_NAN_5;
345 }
346
347 idx++;
348 }
349
350 /* Make sure the global memory guard are untouch. */
351 if( memoryGuard1 != RESV_PATTERN_MEMGUARD_1 )
352 {
353 printf( "Fail: MemoryGuard1 have been modified (%f,%f)\n", memoryGuard1, RESV_PATTERN_MEMGUARD_1 );
354 return TA_TEST_TFRR_OVERLAP_OR_NAN_6;
355 }
356
357 if( memoryGuard2 != RESV_PATTERN_MEMGUARD_2 )
358 {
359 printf( "Fail: MemoryGuard2 have been modified (%f,%f)\n", memoryGuard2, RESV_PATTERN_MEMGUARD_2 );
360 return TA_TEST_TFRR_OVERLAP_OR_NAN_7;
361 }
362
363 /* Everything looks good! */
364 return TA_TEST_PASS;
365 }
366
367 /* Return 1 on success */
checkSameContent(TA_Real * buffer1,TA_Real * buffer2)368 ErrorNumber checkSameContent( TA_Real *buffer1,
369 TA_Real *buffer2 )
370 {
371 const TA_Real *theBuffer1;
372 const TA_Real *theBuffer2;
373
374 unsigned int i;
375
376 theBuffer1 = buffer1 - TA_BUF_PREFIX;
377 theBuffer2 = buffer2 - TA_BUF_PREFIX;
378
379 for( i=0; i < TA_BUF_SIZE; i++ )
380 {
381 /* TODO Add back nan/inf checking
382 (!trio_isnan(theBuffer1[i])) &&
383 (!trio_isinf(theBuffer1[i])) &&
384 */
385
386 if( (theBuffer1[i] != RESV_PATTERN_SUFFIX) &&
387 (theBuffer1[i] != RESV_PATTERN_PREFIX) )
388 {
389
390 if(!TA_REAL_EQ( theBuffer1[i], theBuffer2[i], 0.000001))
391 {
392 printf( "Fail: Large difference found between two value expected identical (%f,%f,%d)\n",
393 theBuffer1[i], theBuffer2[i], i );
394 return TA_TEST_TFRR_CHECK_SAME_CONTENT;
395 }
396 }
397 }
398
399 return TA_TEST_PASS;
400 }
401
checkDataSame(const TA_Real * data,const TA_Real * originalInput,unsigned int nbElement)402 ErrorNumber checkDataSame( const TA_Real *data,
403 const TA_Real *originalInput,
404 unsigned int nbElement )
405 {
406 unsigned int i;
407 ErrorNumber errNb;
408
409 errNb = checkForNAN( data, nbElement );
410
411 if( errNb != TA_TEST_PASS )
412 return errNb;
413
414 if( nbElement > MAX_NB_TEST_ELEMENT )
415 {
416 printf( "Fail: outNbElement is out of range 1 (%d)\n", nbElement );
417 return TA_TEST_TFRR_NB_ELEMENT_OUT_OF_RANGE;
418 }
419
420 for( i=0; i < nbElement; i++ )
421 {
422 if( originalInput[i] != data[i] )
423 {
424 printf( "Fail: Data was wrongly modified (%f,%f,%d)\n",
425 originalInput[i],
426 data[i], i );
427 return TA_TEST_TFRR_INPUT_HAS_BEEN_MODIFIED;
428 }
429 }
430
431 return TA_TEST_PASS;
432 }
433
checkExpectedValue(const TA_Real * data,TA_RetCode retCode,TA_RetCode expectedRetCode,unsigned int outBegIdx,unsigned int expectedBegIdx,unsigned int outNbElement,unsigned int expectedNbElement,TA_Real oneOfTheExpectedOutReal,unsigned int oneOfTheExpectedOutRealIndex)434 ErrorNumber checkExpectedValue( const TA_Real *data,
435 TA_RetCode retCode, TA_RetCode expectedRetCode,
436 unsigned int outBegIdx, unsigned int expectedBegIdx,
437 unsigned int outNbElement, unsigned int expectedNbElement,
438 TA_Real oneOfTheExpectedOutReal,
439 unsigned int oneOfTheExpectedOutRealIndex )
440 {
441 if( retCode != expectedRetCode )
442 {
443 printf( "Fail: RetCode %d different than expected %d\n", retCode, expectedRetCode );
444 return TA_TESTUTIL_TFRR_BAD_RETCODE;
445 }
446
447 if( retCode != TA_SUCCESS )
448 {
449 /* An error did occured, but it
450 * was expected. No need to go
451 * further.
452 */
453 return TA_TEST_PASS;
454 }
455
456 if( outNbElement > MAX_NB_TEST_ELEMENT )
457 {
458 printf( "Fail: outNbElement is out of range 2 (%d)\n", outNbElement );
459 return TA_TEST_TFRR_NB_ELEMENT_OUT_OF_RANGE;
460 }
461
462
463 /* Make sure the range of output does not contains NAN. */
464 /* TODO Add back nan/inf checking
465 for( i=0; i < outNbElement; i++ )
466 {
467 if( trio_isnan(data[i]) )
468 {
469 printf( "Fail: Not a number find within the data (%d,%f)\n", i, data[i] );
470 return TA_TEST_TFRR_OVERLAP_OR_NAN_3;
471 }
472 }*/
473
474 /* Verify that the expected output is there. */
475
476 if( outNbElement != expectedNbElement )
477 {
478 printf( "Fail: outNbElement expected %d but got %d\n",
479 expectedNbElement, outNbElement );
480 return TA_TESTUTIL_TFRR_BAD_OUTNBELEMENT;
481 }
482
483 if( expectedNbElement > 0 )
484 {
485 if( !TA_REAL_EQ( oneOfTheExpectedOutReal, data[oneOfTheExpectedOutRealIndex], 0.01 ) )
486 {
487 printf( "Fail: For index %d, Expected value = %f but calculate value is %f\n",
488 oneOfTheExpectedOutRealIndex,
489 oneOfTheExpectedOutReal,
490 data[oneOfTheExpectedOutRealIndex] );
491 return TA_TESTUTIL_TFRR_BAD_CALCULATION;
492 }
493
494 if( expectedBegIdx != outBegIdx )
495 {
496 printf( "Fail: outBegIdx expected %d but got %d\n", expectedBegIdx, outBegIdx );
497 return TA_TESTUTIL_TFRR_BAD_BEGIDX;
498 }
499 }
500
501 /* Succeed. */
502 return TA_TEST_PASS;
503 }
504
505
doRangeTest(RangeTestFunction testFunction,TA_FuncUnstId unstId,void * opaqueData,unsigned int nbOutput,unsigned int integerTolerance)506 ErrorNumber doRangeTest( RangeTestFunction testFunction,
507 TA_FuncUnstId unstId,
508 void *opaqueData,
509 unsigned int nbOutput,
510 unsigned int integerTolerance )
511 {
512 unsigned int outputNb;
513 ErrorNumber errNb;
514
515 /* Test all the outputs individually. */
516 for( outputNb=0; outputNb < nbOutput; outputNb++ )
517 {
518 errNb = doRangeTestForOneOutput( testFunction,
519 unstId,
520 opaqueData,
521 outputNb,
522 integerTolerance );
523 if( errNb != TA_TEST_PASS )
524 {
525 printf( "Failed: For output #%d of %d\n", outputNb+1, nbOutput );
526 return errNb;
527 }
528 }
529
530 return TA_TEST_PASS;
531 }
532
printRetCode(TA_RetCode retCode)533 void printRetCode( TA_RetCode retCode )
534 {
535 TA_RetCodeInfo retCodeInfo;
536
537 TA_SetRetCodeInfo( retCode, &retCodeInfo );
538 printf( "\nFailed: ErrorCode %d=%s:[%s]\n", retCode,
539 retCodeInfo.enumStr,
540 retCodeInfo.infoStr );
541 }
542
543
544
545 /**** Local functions definitions. ****/
doRangeTestForOneOutput(RangeTestFunction testFunction,TA_FuncUnstId unstId,void * opaqueData,unsigned int outputNb,unsigned int integerTolerance)546 static ErrorNumber doRangeTestForOneOutput( RangeTestFunction testFunction,
547 TA_FuncUnstId unstId,
548 void *opaqueData,
549 unsigned int outputNb,
550 unsigned int integerTolerance )
551 {
552 TA_RetCode retCode;
553 TA_Integer refOutBeg, refOutNbElement, refLookback;
554 TA_Integer fixSize;
555 TA_Real *refBuffer;
556 TA_Integer *refBufferInt;
557 ErrorNumber errNb;
558 TA_Integer unstablePeriod, temp;
559 unsigned int outputIsInteger;
560
561 showFeedback();
562
563 /* Caculate the whole range. This is going
564 * to be the reference for all subsequent test.
565 */
566 refBuffer = (TA_Real *)TA_Malloc( MAX_RANGE_SIZE * sizeof( TA_Real ) );
567
568 if( !refBuffer )
569 return TA_TESTUTIL_DRT_ALLOC_ERR;
570
571 refBufferInt = (TA_Integer *)TA_Malloc( MAX_RANGE_SIZE * sizeof( TA_Integer ) );
572
573 if( !refBufferInt )
574 {
575 TA_Free( refBuffer );
576 return TA_TESTUTIL_DRT_ALLOC_ERR;
577 }
578
579 if( unstId != TA_FUNC_UNST_NONE )
580 {
581 /* Caller wish to test for a range of unstable
582 * period values. But the reference is calculated
583 * on the whole range by keeping that unstable period
584 * to zero.
585 */
586 TA_SetUnstablePeriod( unstId, 0 );
587 }
588
589 outputIsInteger = 0;
590 retCode = CallTestFunction( testFunction, 0, MAX_RANGE_END, refBuffer, refBufferInt,
591 &refOutBeg, &refOutNbElement, &refLookback,
592 opaqueData, outputNb, &outputIsInteger );
593
594 if( retCode != TA_SUCCESS )
595 {
596 printf( "Fail: doRangeTest whole range failed (%d)\n", retCode );
597 TA_Free( refBuffer );
598 TA_Free( refBufferInt );
599 return TA_TESTUTIL_DRT_REF_FAILED;
600 }
601
602 /* When calculating for the whole range, the lookback and the
603 * refOutBeg are supppose to be equal.
604 */
605 if( refLookback != refOutBeg )
606 {
607 printf( "Fail: doRangeTest refLookback != refOutBeg (%d != %d)\n", refLookback, refOutBeg );
608 TA_Free( refBuffer );
609 TA_Free( refBufferInt );
610 return TA_TESTUTIL_DRT_LOOKBACK_INCORRECT;
611 }
612
613 temp = MAX_RANGE_SIZE-refLookback;
614 if( temp != refOutNbElement )
615 {
616 printf( "Fail: doRangeTest either refOutNbElement or refLookback bad (%d,%d)\n", temp, refOutNbElement );
617 TA_Free( refBuffer );
618 TA_Free( refBufferInt );
619 return TA_TESTUTIL_DRT_REF_OUTPUT_INCORRECT;
620 }
621
622 /* Calculate each value ONE by ONE and make sure it is identical
623 * to the reference.
624 *
625 * Then repeat the test but calculate TWO by TWO and so on...
626 */
627 for( fixSize=1; fixSize <= MAX_RANGE_SIZE; fixSize++ )
628 {
629 /* When a function has an unstable period, verify some
630 * unstable period between 0 and MAX_RANGE_SIZE.
631 */
632 if( unstId == TA_FUNC_UNST_NONE )
633 {
634 errNb = doRangeTestFixSize( testFunction, opaqueData,
635 refOutBeg, refOutNbElement, refLookback,
636 refBuffer, refBufferInt,
637 unstId, fixSize, outputNb, integerTolerance );
638 if( errNb != TA_TEST_PASS)
639 {
640 TA_Free( refBuffer );
641 TA_Free( refBufferInt );
642 return errNb;
643 }
644 }
645 else
646 {
647 for( unstablePeriod=0; unstablePeriod <= MAX_RANGE_SIZE; unstablePeriod++ )
648 {
649 TA_SetUnstablePeriod( unstId, unstablePeriod );
650
651 errNb = doRangeTestFixSize( testFunction, opaqueData,
652 refOutBeg, refOutNbElement, refLookback,
653 refBuffer, refBufferInt,
654 unstId, fixSize, outputNb, integerTolerance );
655 if( errNb != TA_TEST_PASS)
656 {
657 printf( "Fail: Using unstable period %d\n", unstablePeriod );
658 TA_Free( refBuffer );
659 TA_Free( refBufferInt );
660 return errNb;
661 }
662
663 /* Randomly skip the test of some unstable period (limit case are
664 * always tested though).
665 */
666 if( (unstablePeriod > 5) && (unstablePeriod < 240) )
667 {
668 /* Randomly skips from 0 to 239 tests. Never
669 * make unstablePeriod exceed 240.
670 */
671 temp = (rand() % 240);
672 unstablePeriod += temp;
673 if( unstablePeriod > 240 )
674 unstablePeriod = 240;
675 }
676 }
677
678 /* Because the tests with an unstable period are very intensive
679 * and kinda repetitive, skip the test of some fixSize (limit
680 * case are always tested though).
681 */
682 if( (fixSize > 5) && (fixSize < 240) )
683 {
684 /* Randomly skips from 0 to 239 tests. Never
685 * make fixSize exceed 240.
686 */
687 temp = (rand() % 239);
688 fixSize += temp;
689 if( fixSize > 240 )
690 fixSize = 240;
691 }
692 }
693 }
694
695 TA_Free( refBuffer );
696 TA_Free( refBufferInt );
697 return TA_TEST_PASS;
698 }
699
doRangeTestFixSize(RangeTestFunction testFunction,void * opaqueData,TA_Integer refOutBeg,TA_Integer refOutNbElement,TA_Integer refLookback,const TA_Real * refBuffer,const TA_Integer * refBufferInt,TA_FuncUnstId unstId,TA_Integer fixSize,unsigned int outputNb,unsigned int integerTolerance)700 static ErrorNumber doRangeTestFixSize( RangeTestFunction testFunction,
701 void *opaqueData,
702 TA_Integer refOutBeg,
703 TA_Integer refOutNbElement,
704 TA_Integer refLookback,
705 const TA_Real *refBuffer,
706 const TA_Integer *refBufferInt,
707 TA_FuncUnstId unstId,
708 TA_Integer fixSize,
709 unsigned int outputNb,
710 unsigned int integerTolerance )
711 {
712 TA_RetCode retCode;
713 TA_Real *outputBuffer;
714 TA_Real val1, val2;
715 TA_Integer i, temp;
716 TA_Integer outputBegIdx, outputNbElement, lookback;
717 TA_Integer startIdx, endIdx, relativeIdx, outputSizeByOptimalLogic;
718 TA_Integer *outputBufferInt;
719 unsigned int outputIsInteger;
720
721 (void)refLookback;
722
723 /* Allocate the output buffer (+prefix and suffix memory guard). */
724 outputBuffer = (TA_Real *)TA_Malloc( (fixSize+2) * sizeof( TA_Real ) );
725
726 if( !outputBuffer )
727 return TA_TESTUTIL_DRT_ALLOC_ERR;
728
729 outputBufferInt = (TA_Integer *)TA_Malloc( (fixSize+2) * sizeof( TA_Integer ) );
730
731 if( !refBufferInt )
732 {
733 TA_Free( outputBuffer );
734 return TA_TESTUTIL_DRT_ALLOC_ERR;
735 }
736
737 outputBuffer[0] = RESV_PATTERN_PREFIX;
738 outputBuffer[fixSize+1] = RESV_PATTERN_SUFFIX;
739
740 outputBufferInt[0] = RESV_PATTERN_PREFIX_INT;
741 outputBufferInt[fixSize+1] = RESV_PATTERN_SUFFIX_INT;
742
743 /* Initialize the outputs with improbable values. */
744 for( i=1; i <= fixSize; i++ )
745 {
746 outputBuffer[i] = RESV_PATTERN_IMPROBABLE;
747 outputBufferInt[i] = RESV_PATTERN_IMPROBABLE_INT;
748 }
749
750 /* Test for a large number of possible startIdx */
751 for( startIdx=0; startIdx <= (MAX_RANGE_SIZE-fixSize); startIdx++ )
752 {
753 /* Call the TA function. */
754 endIdx = startIdx+fixSize-1;
755 retCode = CallTestFunction( testFunction, startIdx, endIdx,
756 &outputBuffer[1], &outputBufferInt[1],
757 &outputBegIdx, &outputNbElement, &lookback,
758 opaqueData, outputNb, &outputIsInteger );
759
760 if( retCode != TA_SUCCESS )
761 {
762 /* No call shall never fail here. When the range
763 * is "out-of-range" the function shall still return
764 * TA_SUCCESS with the outNbElement equal to zero.
765 */
766 printf( "Fail: doRangeTestFixSize testFunction return error=(%d) (%d,%d)\n", retCode, fixSize, startIdx );
767 TA_Free( outputBuffer );
768 TA_Free( outputBufferInt );
769 return TA_TESTUTIL_DRT_RETCODE_ERR;
770 }
771 else
772 {
773 /* Possible startIdx gap of the output shall be always the
774 * same regardless of the range.
775 */
776 if( outputNbElement == 0 )
777 {
778 /* Trap cases where there is no output. */
779 if( (startIdx > lookback) || (endIdx > lookback) )
780 {
781 /* Whenever startIdx is greater than lookback, some data
782 * shall be return. Same idea with endIdx.
783 *
784 * Note:
785 * some output will never start at the startIdx, particularly
786 * when a TA function have multiple output. Usually, the first output
787 * will be between startIdx/endIdx and other outputs may have a "gap"
788 * from the startIdx.
789 *
790 * Example:
791 * Stochastic %K is between startIdx/endIdx, but %D output will
792 * have less data because it is a MA of %K. A gap will then
793 * exist for the %D output.
794 */
795 printf( "Fail: doRangeTestFixSize data missing (%d,%d,%d)\n", startIdx, endIdx, lookback );
796
797 TA_Free( outputBuffer );
798 TA_Free( outputBufferInt );
799 return TA_TESTUTIL_DRT_MISSING_DATA;
800 }
801 }
802 else
803 {
804 /* Some output was returned. Are the returned index correct? */
805 if( (outputBegIdx < startIdx) || (outputBegIdx > endIdx) || (outputBegIdx < refOutBeg))
806 {
807 printf( "Fail: doRangeTestFixSize bad outBegIdx\n" );
808 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
809 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
810 TA_Free( outputBuffer );
811 TA_Free( outputBufferInt );
812 return TA_TESTUTIL_DRT_BAD_OUTBEGIDX;
813 }
814
815 if( (outputNbElement > fixSize) || (outputNbElement > refOutNbElement) )
816 {
817 printf( "Fail: doRangeTestFixSize Incorrect outputNbElement\n" );
818 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
819 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
820 TA_Free( outputBuffer );
821 return TA_TESTUTIL_DRT_BAD_OUTNBLEMENT;
822 }
823
824 /* Is the calculated lookback too high? */
825 if( outputBegIdx < lookback )
826 {
827 printf( "Fail: doRangeTestFixSize Lookback calculation too high? (%d)\n", lookback );
828 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
829 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
830 TA_Free( outputBuffer );
831 TA_Free( outputBufferInt );
832 return TA_TESTUTIL_DRT_LOOKBACK_TOO_HIGH;
833 }
834
835 /* Is the output identical to the reference? */
836 relativeIdx = outputBegIdx-refOutBeg;
837 for( i=0; i < outputNbElement; i++ )
838 {
839 if( outputIsInteger )
840 {
841 if( outputBufferInt[1+i] != refBufferInt[relativeIdx+i] )
842 {
843 printf( "Fail: doRangeTestFixSize diff data for idx=%d (%d,%d)\n", i,
844 outputBufferInt[1+i], refBufferInt[relativeIdx+i] );
845 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
846 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
847 TA_Free( outputBuffer );
848 TA_Free( outputBufferInt );
849 return TA_TESTUTIL_DRT_DATA_DIFF_INT;
850 }
851 }
852 else
853 {
854 val1 = outputBuffer[1+i];
855 val2 = refBuffer[relativeIdx+i];
856 if( !dataWithinReasonableRange( val1, val2, i, unstId, integerTolerance ) )
857 {
858 printf( "Fail: doRangeTestFixSize diff data for idx=%d (%e,%e)\n", i, val1, val2 );
859 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
860 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
861 if( val1 != 0.0 )
862 printf( "Fail: Diff %g %%\n", ((val2-val1)/val1)*100.0 );
863 TA_Free( outputBuffer );
864 TA_Free( outputBufferInt );
865 return TA_TESTUTIL_DRT_DATA_DIFF;
866 }
867 }
868
869 /* Randomly skip the verification of some value. Limit
870 * cases are always checked though.
871 */
872 if( outputNbElement > 30 )
873 {
874 temp = outputNbElement-20;
875 if( (i > 20) && (i < temp) )
876 {
877 /* Randomly skips from 0 to 200 verification.
878 * Never make it skip the last 20 values.
879 */
880 i += (rand() % 200);
881 if( i > temp )
882 i = temp;
883 }
884 }
885 }
886
887 /* Verify out-of-bound writing in the output buffer. */
888 outputSizeByOptimalLogic = max(lookback,startIdx);
889 if( outputSizeByOptimalLogic > endIdx )
890 outputSizeByOptimalLogic = 0;
891 else
892 outputSizeByOptimalLogic = endIdx-outputSizeByOptimalLogic+1;
893
894 if( (fixSize != outputNbElement) && (outputBuffer[1+outputSizeByOptimalLogic] != RESV_PATTERN_IMPROBABLE) )
895 {
896 printf( "Fail: doRangeTestFixSize out-of-bound output (%e)\n", outputBuffer[1+outputSizeByOptimalLogic] );
897 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
898 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
899 TA_Free( outputBuffer );
900 TA_Free( outputBufferInt );
901 return TA_TESTUTIL_DRT_OUT_OF_BOUND_OUT;
902 }
903
904 if( (fixSize != outputNbElement) && (outputBufferInt[1+outputSizeByOptimalLogic] != RESV_PATTERN_IMPROBABLE_INT) )
905 {
906 printf( "Fail: doRangeTestFixSize out-of-bound output (%d)\n", outputBufferInt[1+outputSizeByOptimalLogic] );
907 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
908 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
909 TA_Free( outputBuffer );
910 TA_Free( outputBufferInt );
911 return TA_TESTUTIL_DRT_OUT_OF_BOUND_OUT_INT;
912 }
913
914 /* Verify that the memory guard were preserved. */
915 if( outputBuffer[0] != RESV_PATTERN_PREFIX )
916 {
917 printf( "Fail: doRangeTestFixSize bad RESV_PATTERN_PREFIX (%e)\n", outputBuffer[0] );
918 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
919 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
920 TA_Free( outputBuffer );
921 TA_Free( outputBufferInt );
922 return TA_TESTUTIL_DRT_BAD_PREFIX;
923 }
924
925 if( outputBufferInt[0] != RESV_PATTERN_PREFIX_INT )
926 {
927 printf( "Fail: doRangeTestFixSize bad RESV_PATTERN_PREFIX_INT (%d)\n", outputBufferInt[0] );
928 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
929 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
930 TA_Free( outputBuffer );
931 TA_Free( outputBufferInt );
932 return TA_TESTUTIL_DRT_BAD_PREFIX;
933 }
934
935 if( outputBuffer[fixSize+1] != RESV_PATTERN_SUFFIX )
936 {
937 printf( "Fail: doRangeTestFixSize bad RESV_PATTERN_SUFFIX (%e)\n", outputBuffer[fixSize+1] );
938 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
939 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
940 TA_Free( outputBuffer );
941 TA_Free( outputBufferInt );
942 return TA_TESTUTIL_DRT_BAD_SUFFIX;
943 }
944
945 if( outputBufferInt[fixSize+1] != RESV_PATTERN_SUFFIX_INT )
946 {
947 printf( "Fail: doRangeTestFixSize bad RESV_PATTERN_SUFFIX_INT (%d)\n", outputBufferInt[fixSize+1] );
948 printf( "Fail: doRangeTestFixSize (%d,%d,%d,%d,%d)\n", startIdx, endIdx, outputBegIdx, outputNbElement, fixSize );
949 printf( "Fail: doRangeTestFixSize refOutBeg,refOutNbElement (%d,%d)\n", refOutBeg, refOutNbElement );
950 TA_Free( outputBuffer );
951 TA_Free( outputBufferInt );
952 return TA_TESTUTIL_DRT_BAD_SUFFIX;
953 }
954
955 /* Clean-up for next test. */
956 if( outputIsInteger )
957 {
958 for( i=1; i <= fixSize; i++ )
959 outputBufferInt[i] = RESV_PATTERN_IMPROBABLE_INT;
960 }
961 else
962 {
963 for( i=1; i <= fixSize; i++ )
964 outputBuffer[i] = RESV_PATTERN_IMPROBABLE;
965 }
966 }
967
968 /* Skip some startIdx at random. Limit case are still
969 * tested though.
970 */
971 if( (startIdx > 30) && ((startIdx+100) <= (MAX_RANGE_SIZE-fixSize)) )
972 {
973 /* Randomly skips from 40 to 100 tests. */
974 temp = (rand() % 100)+40;
975 startIdx += temp;
976 }
977 }
978
979 /* Loop and move forward for the next startIdx to test. */
980 }
981
982 TA_Free( outputBuffer );
983 TA_Free( outputBufferInt );
984 return TA_TEST_PASS;
985 }
986
987 /* This function compares two value.
988 * The value is determined to be equal
989 * if it is within a certain error range.
990 */
dataWithinReasonableRange(TA_Real val1,TA_Real val2,unsigned int outputPosition,TA_FuncUnstId unstId,unsigned int integerTolerance)991 static int dataWithinReasonableRange( TA_Real val1, TA_Real val2,
992 unsigned int outputPosition,
993 TA_FuncUnstId unstId,
994 unsigned int integerTolerance )
995 {
996 TA_Real difference, tolerance, temp;
997 unsigned int val1_int, val2_int, tempInt, periodToIgnore;
998
999 if( integerTolerance == TA_DO_NOT_COMPARE )
1000 return 1; /* Don't compare, says that everything is fine */
1001
1002 /* If the function does not have an unstable period,
1003 * the compared value shall be identical.
1004 *
1005 * Because the algo may vary slightly allow for
1006 * a small epsilon error because of the nature
1007 * of floating point operations.
1008 */
1009 if( unstId == TA_FUNC_UNST_NONE )
1010 return TA_REAL_EQ( val1, val2, 0.000000001 );
1011
1012 /* In the context of the TA functions, all value
1013 * below 0.00001 are considered equal to zero and
1014 * are considered to be equal within a reasonable range.
1015 * (the percentage difference might be large, but
1016 * unsignificant at that level, so no tolerance
1017 * check is being done).
1018 */
1019 if( (val1 < 0.00001) && (val2 < 0.00001) )
1020 return 1;
1021
1022 /* When the function is unstable, the comparison
1023 * tolerate at first a large difference.
1024 *
1025 * As the number of "outputPosition" is higher
1026 * the tolerance is reduced.
1027 *
1028 * In the same way, as the unstable period
1029 * increase, the tolerance is reduced (that's
1030 * what the unstable period is for... reducing
1031 * difference).
1032 *
1033 * When dealing with an unstable period, the
1034 * first 100 values are ignored.
1035 *
1036 * Following 100, the tolerance is
1037 * progressively reduced as follow:
1038 *
1039 * 1 == 0.5/1 == 50 %
1040 * 2 == 0.5/2 == 25 %
1041 * ...
1042 * 100 == 0.5/100 == 0.005 %
1043 * ...
1044 *
1045 * Overall, the following is a fair estimation:
1046 * When using a unstable period of 200, you
1047 * can expect the output to not vary more
1048 * than 0.005 %
1049 *
1050 * The logic is sligthly different if the
1051 * output are rounded integer, but it is
1052 * the same idea.
1053 *
1054 * The following describe the special meaning of
1055 * the integerTolerance:
1056 *
1057 * Value 10 -> A tolerance of 1/10 is used.
1058 *
1059 * Value 100 -> A tolerance of 1/100 is used.
1060 *
1061 * Value 1000 -> A tolerance of 1/1000 is used.
1062 *
1063 * Value 360 -> Useful when the output are
1064 * degrees. In that case, a fix
1065 * tolerance of 1 degree is used.
1066 *
1067 * Value TA_DO_NOT_COMPARE ->
1068 * Indicate that NO COMPARISON take
1069 * place. This is useful for functions
1070 * that cannot be compare when changing
1071 * the range (like the accumulative
1072 * algorithm used for TA_AD and TA_ADOSC).
1073 */
1074
1075
1076 /* Some functions requires a longer unstable period.
1077 * These are trap here.
1078 */
1079 switch( unstId )
1080 {
1081 case TA_FUNC_UNST_T3:
1082 periodToIgnore = 200;
1083 break;
1084 default:
1085 periodToIgnore = 100;
1086 break;
1087 }
1088
1089 if( integerTolerance == 1000 )
1090 {
1091 /* Check for no difference of more
1092 * than 1/1000
1093 */
1094 if( val1 > val2 )
1095 difference = (val1-val2);
1096 else
1097 difference = (val2-val1);
1098
1099 difference *= 1000.0;
1100
1101 temp = outputPosition+TA_GetUnstablePeriod(unstId)+1;
1102 if( temp <= periodToIgnore )
1103 {
1104 /* Pretend it is fine. */
1105 return 1;
1106 }
1107 else if( (int)difference > 1 )
1108 {
1109 printf( "\nFail: Value diffferent by more than 1/1000 (%f)\n", difference );
1110 return 0;
1111 }
1112 }
1113 else if( integerTolerance == 100 )
1114 {
1115 /* Check for no difference of more
1116 * than 1/1000
1117 */
1118 if( val1 > val2 )
1119 difference = (val1-val2);
1120 else
1121 difference = (val2-val1);
1122
1123 difference *= 100.0;
1124
1125 temp = outputPosition+TA_GetUnstablePeriod(unstId)+1;
1126 if( temp <= periodToIgnore )
1127 {
1128 /* Pretend it is fine. */
1129 return 1;
1130 }
1131 else if( (int)difference > 1 )
1132 {
1133 printf( "\nFail: Value diffferent by more than 1/100 (%f)\n", difference );
1134 return 0;
1135 }
1136 }
1137 else if( integerTolerance == 10 )
1138 {
1139 /* Check for no difference of more
1140 * than 1/1000
1141 */
1142 if( val1 > val2 )
1143 difference = (val1-val2);
1144 else
1145 difference = (val2-val1);
1146
1147 difference *= 10.0;
1148
1149 temp = outputPosition+TA_GetUnstablePeriod(unstId)+1;
1150 if( temp <= periodToIgnore )
1151 {
1152 /* Pretend it is fine. */
1153 return 1;
1154 }
1155 else if( (int)difference > 1 )
1156 {
1157 printf( "\nFail: Value diffferent by more than 1/10 (%f)\n", difference );
1158 return 0;
1159 }
1160 }
1161 else if( integerTolerance == 360 )
1162 {
1163 /* Check for no difference of no more
1164 * than 10% when the value is higher than
1165 * 1 degree.
1166 *
1167 * Difference of less than 1 degree are not significant.
1168 */
1169 val1_int = (unsigned int)val1;
1170 val2_int = (unsigned int)val2;
1171 if( val1_int > val2_int )
1172 tempInt = val1_int - val2_int;
1173 else
1174 tempInt = val2_int - val1_int;
1175
1176 if( val1 > val2 )
1177 difference = (val1-val2)/val1;
1178 else
1179 difference = (val2-val1)/val2;
1180
1181 temp = outputPosition+TA_GetUnstablePeriod(unstId)+1;
1182 if( temp <= periodToIgnore )
1183 {
1184 /* Pretend it is fine. */
1185 return 1;
1186 }
1187 else if( (tempInt > 1) && (difference > 0.10) )
1188 {
1189 printf( "\nFail: Value diffferent by more than 10 percent over 1 degree (%d)\n", tempInt );
1190 return 0;
1191 }
1192 }
1193 else if( integerTolerance )
1194 {
1195 /* Check that the integer part of the value
1196 * is not different more than the specified
1197 * integerTolerance.
1198 */
1199 val1_int = (unsigned int)val1;
1200 val2_int = (unsigned int)val2;
1201 if( val1_int > val2_int )
1202 tempInt = val1_int - val2_int;
1203 else
1204 tempInt = val2_int - val1_int;
1205
1206 temp = outputPosition+TA_GetUnstablePeriod(unstId)+1;
1207 if( temp <= periodToIgnore )
1208 {
1209 /* Pretend it is fine. */
1210 return 1;
1211 }
1212 else if( temp < 100 )
1213 {
1214 if( tempInt >= 3*integerTolerance )
1215 {
1216 printf( "\nFail: Value out of 3*tolerance range (%d,%d)\n", tempInt, integerTolerance );
1217 return 0; /* Value considered different */
1218 }
1219 }
1220 else if( temp < 150 )
1221 {
1222 if( tempInt >= 2*integerTolerance )
1223 {
1224 printf( "\nFail: Value out of 2*tolerance range (%d,%d)\n", tempInt, integerTolerance );
1225 return 0; /* Value considered different */
1226 }
1227 }
1228 else if( temp < 200 )
1229 {
1230 if( tempInt >= integerTolerance )
1231 {
1232 printf( "\nFail: Value out of tolerance range (%d,%d)\n", tempInt, integerTolerance );
1233 return 0; /* Value considered different */
1234 }
1235 }
1236 else if( tempInt >= 1 )
1237 {
1238 printf( "\nFail: Value not equal (difference is %d)\n", tempInt );
1239 return 0; /* Value considered different */
1240 }
1241 }
1242 else
1243 {
1244 if( val1 > val2 )
1245 difference = (val1-val2)/val1;
1246 else
1247 difference = (val2-val1)/val2;
1248
1249 temp = outputPosition+TA_GetUnstablePeriod(unstId)+1;
1250 if( temp <= periodToIgnore )
1251 {
1252 /* Pretend it is fine. */
1253 return 1;
1254 }
1255 else
1256 {
1257 temp -= periodToIgnore;
1258 tolerance = 0.5/temp;
1259 }
1260
1261 if( difference > tolerance )
1262 {
1263 printf( "\nFail: Value out of tolerance range (%g,%g)\n", difference, tolerance );
1264 return 0; /* Out of tolerance... values are not equal. */
1265 }
1266 }
1267
1268 return 1; /* Value equal within tolerance. */
1269 }
1270
CallTestFunction(RangeTestFunction testFunction,TA_Integer startIdx,TA_Integer endIdx,TA_Real * outputBuffer,TA_Integer * outputBufferInt,TA_Integer * outBegIdx,TA_Integer * outNbElement,TA_Integer * lookback,void * opaqueData,unsigned int outputNb,unsigned int * isOutputInteger)1271 static TA_RetCode CallTestFunction( RangeTestFunction testFunction,
1272 TA_Integer startIdx,
1273 TA_Integer endIdx,
1274 TA_Real *outputBuffer,
1275 TA_Integer *outputBufferInt,
1276 TA_Integer *outBegIdx,
1277 TA_Integer *outNbElement,
1278 TA_Integer *lookback,
1279 void *opaqueData,
1280 unsigned int outputNb,
1281 unsigned int *isOutputInteger )
1282 {
1283 /* Call the function and do profiling. */
1284 TA_RetCode retCode;
1285 double clockDelta;
1286
1287 #ifdef WIN32
1288 LARGE_INTEGER startClock;
1289 LARGE_INTEGER endClock;
1290 #else
1291 clock_t startClock;
1292 clock_t endClock;
1293 #endif
1294
1295 #ifdef WIN32
1296 QueryPerformanceCounter(&startClock);
1297 #else
1298 startClock = clock();
1299 #endif
1300 retCode = testFunction( startIdx,
1301 endIdx,
1302 outputBuffer,
1303 outputBufferInt,
1304 outBegIdx,
1305 outNbElement,
1306 lookback,
1307 opaqueData,
1308 outputNb,
1309 isOutputInteger );
1310
1311 /* Profile only functions producing at least 20 values. */
1312 if( *outNbElement < 20 )
1313 {
1314 return retCode;
1315 }
1316
1317 #ifdef WIN32
1318 QueryPerformanceCounter(&endClock);
1319 clockDelta = (double)((__int64)endClock.QuadPart - (__int64) startClock.QuadPart);
1320 #else
1321 endClock = clock();
1322 clockDelta = (double)(endClock - startClock);
1323 #endif
1324
1325 if( clockDelta <= 0 )
1326 {
1327 insufficientClockPrecision = 1;
1328 }
1329 else
1330 {
1331 if( clockDelta > worstProfiledCall )
1332 worstProfiledCall = clockDelta;
1333 timeInProfiledCall += clockDelta;
1334 nbProfiledCall++;
1335 }
1336
1337 return retCode;
1338 }
1339