static ErrorNumber do_test( TA_Libc *libHandle, const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; /* Set to NAN all the elements of the gBuffers. */ clearAllBuffers(); /* Build the input. */ setInputBuffer( 0, history->high, history->nbBars ); setInputBuffer( 1, history->low, history->nbBars ); setInputBuffer( 2, history->close, history->nbBars ); /* Set the unstable period requested for that test. */ switch( test->optInMethod_3 ) { case TA_STOCH_EXPONENTIAL: retCode = TA_SetUnstablePeriod( libHandle, TA_FUNC_UNST_EMA, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; break; default: /* No unstable period for other methods. */ break; } /* Make a simple first call. */ retCode = TA_STOCH( libHandle, test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInKPeriod_0, test->optInKSlowPeriod_1, test->optInDPeriod_2, test->optInMethod_3, &outBegIdx, &outNbElement, gBuffer[0].out0, gBuffer[0].out1 ); errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].out0, 0 ); CHECK_EXPECTED_VALUE( gBuffer[0].out1, 1 ); outBegIdx = outNbElement = 0; /* Make another call where the input and the output are the * same buffer. */ retCode = TA_STOCH( libHandle, test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInKPeriod_0, test->optInKSlowPeriod_1, test->optInDPeriod_2, test->optInMethod_3, &outBegIdx, &outNbElement, gBuffer[0].in, gBuffer[1].in ); /* The previous call should have the same output as this call. * * checkSameContent verify that all value different than NAN in * the first parameter is identical in the second parameter. */ errNb = checkSameContent( gBuffer[0].out0, gBuffer[0].in ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkSameContent( gBuffer[0].out1, gBuffer[1].in ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].in, 0 ); CHECK_EXPECTED_VALUE( gBuffer[1].in, 1 ); if( errNb != TA_TEST_PASS ) return errNb; /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.high = history->high; testParam.low = history->low; testParam.close = history->close; if( test->doRangeTestFlag ) { errNb = doRangeTest( libHandle, rangeTestFunction, TA_FUNC_UNST_EMA, (void *)&testParam, 2 ); if( errNb != TA_TEST_PASS ) return errNb; } return TA_TEST_PASS; }
static ErrorNumber do_test( const TA_History *history, const TA_Test *test ) { TA_RetCode retCode; ErrorNumber errNb; TA_Integer outBegIdx; TA_Integer outNbElement; TA_RangeTestParam testParam; /* Set to NAN all the elements of the gBuffers. */ clearAllBuffers(); /* Build the input. */ setInputBuffer( 0, history->high, history->nbBars ); setInputBuffer( 1, history->low, history->nbBars ); setInputBuffer( 2, history->close, history->nbBars ); /* Set the unstable period requested for that test. */ switch( test->optInSlowK_MAType_2 ) { case TA_MAType_EMA: retCode = TA_SetUnstablePeriod( TA_FUNC_UNST_EMA, test->unstablePeriod ); if( retCode != TA_SUCCESS ) return TA_TEST_TFRR_SETUNSTABLE_PERIOD_FAIL; break; default: /* No unstable period for other methods. */ break; } /* Make a simple first call. */ retCode = TA_STOCH( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInFastK_Period_0, test->optInSlowK_Period_1, test->optInSlowK_MAType_2, test->optInSlowD_Period_3, test->optInSlowD_MAType_4, &outBegIdx, &outNbElement, gBuffer[0].out0, gBuffer[0].out1 ); errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].out0, 0 ); CHECK_EXPECTED_VALUE( gBuffer[0].out1, 1 ); outBegIdx = outNbElement = 0; /* Compare to the non-optimized version */ retCode = referenceStoch( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInFastK_Period_0, test->optInSlowK_Period_1, test->optInSlowK_MAType_2, test->optInSlowD_Period_3, test->optInSlowD_MAType_4, &outBegIdx, &outNbElement, gBuffer[1].out0, gBuffer[1].out1 ); errNb = checkDataSame( gBuffer[0].in, history->high,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[1].in, history->low, history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkDataSame( gBuffer[2].in, history->close,history->nbBars ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[1].out0, 0 ); CHECK_EXPECTED_VALUE( gBuffer[1].out1, 1 ); /* The non-optimized reference shall be identical to the optimzied TA-Lib * implementation. * * checkSameContent verify that all value different than NAN in * the first parameter is identical in the second parameter. */ errNb = checkSameContent( gBuffer[1].out0, gBuffer[0].out0 ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkSameContent( gBuffer[1].out1, gBuffer[0].out1 ); if( errNb != TA_TEST_PASS ) return errNb; /* Make another call where the input and the output are the * same buffer. */ retCode = TA_STOCH( test->startIdx, test->endIdx, gBuffer[0].in, gBuffer[1].in, gBuffer[2].in, test->optInFastK_Period_0, test->optInSlowK_Period_1, test->optInSlowK_MAType_2, test->optInSlowD_Period_3, test->optInSlowD_MAType_4, &outBegIdx, &outNbElement, gBuffer[0].in, gBuffer[1].in ); /* The previous call should have the same output as this call. * * checkSameContent verify that all value different than NAN in * the first parameter is identical in the second parameter. */ errNb = checkSameContent( gBuffer[0].out0, gBuffer[0].in ); if( errNb != TA_TEST_PASS ) return errNb; errNb = checkSameContent( gBuffer[0].out1, gBuffer[1].in ); if( errNb != TA_TEST_PASS ) return errNb; CHECK_EXPECTED_VALUE( gBuffer[0].in, 0 ); CHECK_EXPECTED_VALUE( gBuffer[1].in, 1 ); if( errNb != TA_TEST_PASS ) return errNb; /* Do a systematic test of most of the * possible startIdx/endIdx range. */ testParam.test = test; testParam.high = history->high; testParam.low = history->low; testParam.close = history->close; if( test->doRangeTestFlag ) { errNb = doRangeTest( rangeTestFunction, TA_FUNC_UNST_EMA, (void *)&testParam, 2, 0 ); if( errNb != TA_TEST_PASS ) return errNb; } /* Call a local non-optimized version of the function. * This way, we make sure that the currently speed optimized * version in TA-Lib is not broken. */ return TA_TEST_PASS; }
/**** Local functions definitions. ****/ static TA_RetCode rangeTestFunction( TA_Libc *libHandle, TA_Integer startIdx, TA_Integer endIdx, TA_Real *outputBuffer, TA_Integer *outBegIdx, TA_Integer *outNbElement, TA_Integer *lookback, void *opaqueData, unsigned int outputNb ) { TA_RetCode retCode; TA_RangeTestParam *testParam; TA_Real *dummyOutput; testParam = (TA_RangeTestParam *)opaqueData; dummyOutput = TA_Malloc( libHandle, (endIdx-startIdx+1) * sizeof(TA_Real) ); if( outputNb == 0 ) { retCode = TA_STOCH( libHandle, startIdx, endIdx, testParam->high, testParam->low, testParam->close, testParam->test->optInKPeriod_0, testParam->test->optInKSlowPeriod_1, testParam->test->optInDPeriod_2, testParam->test->optInMethod_3, outBegIdx, outNbElement, outputBuffer, dummyOutput ); } else { retCode = TA_STOCH( libHandle, startIdx, endIdx, testParam->high, testParam->low, testParam->close, testParam->test->optInKPeriod_0, testParam->test->optInKSlowPeriod_1, testParam->test->optInDPeriod_2, testParam->test->optInMethod_3, outBegIdx, outNbElement, dummyOutput, outputBuffer ); } TA_Free( libHandle, dummyOutput ); *lookback = TA_STOCH_Lookback( testParam->test->optInKPeriod_0, testParam->test->optInKSlowPeriod_1, testParam->test->optInDPeriod_2, testParam->test->optInMethod_3 ); return retCode; }
/**** Local functions definitions. ****/ static TA_RetCode rangeTestFunction( TA_Integer startIdx, TA_Integer endIdx, TA_Real *outputBuffer, TA_Integer *outBegIdx, TA_Integer *outNbElement, TA_Integer *lookback, void *opaqueData, unsigned int outputNb ) { TA_RetCode retCode; TA_RangeTestParam *testParam; TA_Real *dummyOutput; testParam = (TA_RangeTestParam *)opaqueData; dummyOutput = TA_Malloc( (endIdx-startIdx+1) * sizeof(TA_Real) ); if( outputNb == 0 ) { retCode = TA_STOCH( startIdx, endIdx, testParam->high, testParam->low, testParam->close, testParam->test->optInFastK_Period_0, testParam->test->optInSlowK_Period_1, testParam->test->optInSlowK_MAType_2, testParam->test->optInSlowD_Period_3, testParam->test->optInSlowD_MAType_4, outBegIdx, outNbElement, outputBuffer, dummyOutput ); } else { retCode = TA_STOCH( startIdx, endIdx, testParam->high, testParam->low, testParam->close, testParam->test->optInFastK_Period_0, testParam->test->optInSlowK_Period_1, testParam->test->optInSlowK_MAType_2, testParam->test->optInSlowD_Period_3, testParam->test->optInSlowD_MAType_4, outBegIdx, outNbElement, dummyOutput, outputBuffer ); } TA_Free( dummyOutput ); *lookback = TA_STOCH_Lookback( testParam->test->optInFastK_Period_0, testParam->test->optInSlowK_Period_1, testParam->test->optInSlowK_MAType_2, testParam->test->optInSlowD_Period_3, testParam->test->optInSlowD_MAType_4 ); return retCode; }