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