/* TA-LIB Copyright (c) 1999-2007, Mario Fortier
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 *
 * - Neither name of author nor the names of its contributors
 *   may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* List of contributors:
 *
 *  Initial  Name/description
 *  -------------------------------------------------------------------
 *  MF       Mario Fortier
 *  CR       Chris (crokusek@hotmail.com)
 *
 * Change history:
 *
 *  MMDDYY BY   Description
 *  -------------------------------------------------------------------
 *  010503 MF   Initial Coding
 *  031703 MF   Fix #701060. Correct logic when using a range with
 *              startIdx/endIdx. Thanks to Chris for reporting this.
 *  052603 MF   Adapt code to compile with .NET Managed C++
 *              
 */

/**** START GENCODE SECTION 1 - DO NOT DELETE THIS LINE ****/
/* All code within this section is automatically
 * generated by gen_code. Any modification will be lost
 * next time gen_code is run.
 */
/* Generated */ 
/* Generated */ #if defined( _MANAGED )
/* Generated */    #include "TA-Lib-Core.h"
/* Generated */    #define TA_INTERNAL_ERROR(Id) (RetCode::InternalError)
/* Generated */    namespace TicTacTec { namespace TA { namespace Library {
/* Generated */ #elif defined( _JAVA )
/* Generated */    #include "ta_defs.h"
/* Generated */    #include "ta_java_defs.h"
/* Generated */    #define TA_INTERNAL_ERROR(Id) (RetCode.InternalError)
/* Generated */ #else
/* Generated */    #include <string.h>
/* Generated */    #include <math.h>
/* Generated */    #include "ta_func.h"
/* Generated */ #endif
/* Generated */ 
/* Generated */ #ifndef TA_UTILITY_H
/* Generated */    #include "ta_utility.h"
/* Generated */ #endif
/* Generated */ 
/* Generated */ #ifndef TA_MEMORY_H
/* Generated */    #include "ta_memory.h"
/* Generated */ #endif
/* Generated */ 
/* Generated */ #define TA_PREFIX(x) TA_##x
/* Generated */ #define INPUT_TYPE   double
/* Generated */ 
/* Generated */ #if defined( _MANAGED )
/* Generated */ int Core::TrimaLookback( int           optInTimePeriod )  /* From 2 to 100000 */
/* Generated */ 
/* Generated */ #elif defined( _JAVA )
/* Generated */ public int trimaLookback( int           optInTimePeriod )  /* From 2 to 100000 */
/* Generated */ 
/* Generated */ #else
/* Generated */ int TA_TRIMA_Lookback( int           optInTimePeriod )  /* From 2 to 100000 */
/* Generated */ 
/* Generated */ #endif
/**** END GENCODE SECTION 1 - DO NOT DELETE THIS LINE ****/
{
   /* insert local variable here */

/**** START GENCODE SECTION 2 - DO NOT DELETE THIS LINE ****/
/* Generated */ #ifndef TA_FUNC_NO_RANGE_CHECK
/* Generated */    /* min/max are checked for optInTimePeriod. */
/* Generated */    if( (int)optInTimePeriod == TA_INTEGER_DEFAULT )
/* Generated */       optInTimePeriod = 30;
/* Generated */    else if( ((int)optInTimePeriod < 2) || ((int)optInTimePeriod > 100000) )
/* Generated */       return -1;
/* Generated */ 
/* Generated */ #endif /* TA_FUNC_NO_RANGE_CHECK */
/**** END GENCODE SECTION 2 - DO NOT DELETE THIS LINE ****/

   /* insert lookback code here. */
   return optInTimePeriod-1;
}

/**** START GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/
/*
 * TA_TRIMA - Triangular Moving Average
 * 
 * Input  = double
 * Output = double
 * 
 * Optional Parameters
 * -------------------
 * optInTimePeriod:(From 2 to 100000)
 *    Number of period
 * 
 * 
 */
/* Generated */ 
/* Generated */ #if defined( _MANAGED ) && defined( USE_SUBARRAY )
/* Generated */ enum class Core::RetCode Core::Trima( int    startIdx,
/* Generated */                                       int    endIdx,
/* Generated */                                       SubArray^    inReal,
/* Generated */                                       int           optInTimePeriod, /* From 2 to 100000 */
/* Generated */                                       [Out]int%    outBegIdx,
/* Generated */                                       [Out]int%    outNBElement,
/* Generated */                                       cli::array<double>^  outReal )
/* Generated */ #elif defined( _MANAGED )
/* Generated */ enum class Core::RetCode Core::Trima( int    startIdx,
/* Generated */                                       int    endIdx,
/* Generated */                                       cli::array<double>^ inReal,
/* Generated */                                       int           optInTimePeriod, /* From 2 to 100000 */
/* Generated */                                       [Out]int%    outBegIdx,
/* Generated */                                       [Out]int%    outNBElement,
/* Generated */                                       cli::array<double>^  outReal )
/* Generated */ #elif defined( _JAVA )
/* Generated */ public RetCode trima( int    startIdx,
/* Generated */                       int    endIdx,
/* Generated */                       double       inReal[],
/* Generated */                       int           optInTimePeriod, /* From 2 to 100000 */
/* Generated */                       MInteger     outBegIdx,
/* Generated */                       MInteger     outNBElement,
/* Generated */                       double        outReal[] )
/* Generated */ #else
/* Generated */ TA_RetCode TA_TRIMA( int    startIdx,
/* Generated */                      int    endIdx,
/* Generated */                      const double inReal[],
/* Generated */                      int           optInTimePeriod, /* From 2 to 100000 */
/* Generated */                      int          *outBegIdx,
/* Generated */                      int          *outNBElement,
/* Generated */                      double        outReal[] )
/* Generated */ #endif
/**** END GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/
{
	/* insert local variable here */
   int lookbackTotal;

   double numerator;
   double numeratorSub;
   double numeratorAdd;

   int i, outIdx, todayIdx, trailingIdx, middleIdx;
   double factor, tempReal;

/**** START GENCODE SECTION 4 - DO NOT DELETE THIS LINE ****/
/* Generated */ 
/* Generated */ #ifndef TA_FUNC_NO_RANGE_CHECK
/* Generated */ 
/* Generated */    /* Validate the requested output range. */
/* Generated */    if( startIdx < 0 )
/* Generated */       return ENUM_VALUE(RetCode,TA_OUT_OF_RANGE_START_INDEX,OutOfRangeStartIndex);
/* Generated */    if( (endIdx < 0) || (endIdx < startIdx))
/* Generated */       return ENUM_VALUE(RetCode,TA_OUT_OF_RANGE_END_INDEX,OutOfRangeEndIndex);
/* Generated */ 
/* Generated */    #if !defined(_JAVA)
/* Generated */    if( !inReal ) return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */    #endif /* !defined(_JAVA)*/
/* Generated */    /* min/max are checked for optInTimePeriod. */
/* Generated */    if( (int)optInTimePeriod == TA_INTEGER_DEFAULT )
/* Generated */       optInTimePeriod = 30;
/* Generated */    else if( ((int)optInTimePeriod < 2) || ((int)optInTimePeriod > 100000) )
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */ 
/* Generated */    #if !defined(_JAVA)
/* Generated */    if( !outReal )
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */ 
/* Generated */    #endif /* !defined(_JAVA) */
/* Generated */ #endif /* TA_FUNC_NO_RANGE_CHECK */
/* Generated */ 
/**** END GENCODE SECTION 4 - DO NOT DELETE THIS LINE ****/

   /* Insert TA function code here. */

   /* Identify the minimum number of price bar needed
    * to calculate at least one output.
    */
   lookbackTotal = (optInTimePeriod-1);

   /* Move up the start index if there is not
    * enough initial data.
    */
   if( startIdx < lookbackTotal )
      startIdx = lookbackTotal;

   /* Make sure there is still something to evaluate. */
   if( startIdx > endIdx )
   {
      VALUE_HANDLE_DEREF_TO_ZERO(outBegIdx);
      VALUE_HANDLE_DEREF_TO_ZERO(outNBElement);
      return ENUM_VALUE(RetCode,TA_SUCCESS,Success);
   }

   /* TRIMA Description
    * =================
    * The triangular MA is a weighted moving average. Instead of the
    * TA_WMA who put more weigth on the latest price bar, the triangular
    * put more weigth on the data in the middle of the specified period.
    *
    * Examples:
    *   For TimeSerie={a,b,c,d,e,f...} ('a' is the older price)
    *
    *   1st value for TRIMA 4-Period is:  ((1*a)+(2*b)+(2*c)+(1*d)) / 6
    *   2nd value for TRIMA 4-Period is:  ((1*b)+(2*c)+(2*d)+(1*e)) / 6
    *
    *   1st value for TRIMA 5-Period is:  ((1*a)+(2*b)+(3*c)+(2*d)+(1*e)) / 9
    *   2nd value for TRIMA 5-Period is:  ((1*b)+(2*c)+(3*d)+(2*e)+(1*f)) / 9
    *
    * Generally Accepted Implementation
    * ==================================
    * Using algebra, it can be demonstrated that the TRIMA is equivalent to
    * doing a SMA of a SMA. The following explain the rules:
    *
    *  (1) When the period is even, TRIMA(x,period)=SMA(SMA(x,period/2),(period/2)+1)
    *  (2) When the period is odd,  TRIMA(x,period)=SMA(SMA(x,(period+1)/2),(period+1)/2)
    *
    * In other word:
    *  (1) A period of 4 becomes TRIMA(x,4) = SMA( SMA( x, 2), 3 )
    *  (2) A period of 5 becomes TRIMA(x,5) = SMA( SMA( x, 3), 3 )
    *
    * The SMA of a SMA is the algorithm generaly found in books.
    *
    * Tradestation Implementation
    * ===========================
    * Tradestation deviate from the generally accepted implementation by
    * making the TRIMA to be as follow:
    *    TRIMA(x,period) = SMA( SMA( x, (int)(period/2)+1), (int)(period/2)+1 );
    * This formula is done regardless if the period is even or odd.
    *
    * In other word:
    *  (1) A period of 4 becomes TRIMA(x,4) = SMA( SMA( x, 3), 3 )
    *  (2) A period of 5 becomes TRIMA(x,5) = SMA( SMA( x, 3), 3 )
    *  (3) A period of 6 becomes TRIMA(x,5) = SMA( SMA( x, 4), 4 )
    *  (4) A period of 7 becomes TRIMA(x,5) = SMA( SMA( x, 4), 4 )
    *
    * It is not clear to me if the Tradestation approach is a bug or a deliberate
    * decision to do things differently.
    *    
    * Metastock Implementation
    * ========================
    * Output is the same as the generally accepted implementation.
    *
    * TA-Lib Implementation
    * =====================
    * Output is also the same as the generally accepted implementation.
    *
    * For speed optimization and avoid memory allocation, TA-Lib use
    * a better algorithm than the usual SMA of a SMA.
    *
    * The calculation from one TRIMA value to the next is done by doing 4
    * little adjustment (the following show a TRIMA 4-period):
    *
    * TRIMA at time 'd': ((1*a)+(2*b)+(2*c)+(1*d)) / 6
    * TRIMA at time 'e': ((1*b)+(2*c)+(2*d)+(1*e)) / 6
    * 
    * To go from TRIMA 'd' to 'e', the following is done:
    *       1) 'a' and 'b' are substract from the numerator.
    *       2) 'd' is added to the numerator.
    *       3) 'e' is added to the numerator.
    *       4) Calculate TRIMA by doing numerator / 6
    *       5) Repeat sequence for next output
    *
    * These operations are the same steps done by TA-LIB:
    *       1) is done by numeratorSub
    *       2) is done by numeratorAdd.
    *       3) is obtain from the latest input
    *       4) Calculate and write TRIMA in the output
    *       5) Repeat for next output.
    *
    * Of course, numerotrAdd and numeratorSub needs to be
    * adjusted for each iteration.
    *
    * The update of numeratorSub needs values from the input at
    * the trailingIdx and middleIdx position.
    *
    * The update of numeratorAdd needs values from the input at
    * the middleIdx and todayIdx.
    */

   outIdx = 0;

   if( (optInTimePeriod % 2) == 1 )
   {
      /* Logic for Odd period */

      /* Calculate the factor which is 1 divided by the
       * sumation of the weight.
       *
       * The sum of the weight is calculated as follow:
       *
       * The simple sumation serie 1+2+3... n can be
       * express as n(n+1)/2
       *
       * From this logic, a "triangular" sumation formula
       * can be found depending if the period is odd or even.
       *
       * Odd Period Formula:
       *  period = 5 and with n=(int)(period/2)
       *  the formula for a "triangular" serie is:
       *    1+2+3+2+1 = (n*(n+1))+n+1
       *              = (n+1)*(n+1)
       *              = 3 * 3 = 9
       *
       * Even period Formula:
       *   period = 6 and with n=(int)(period/2)
       *   the formula for a "triangular" serie is:
       *    1+2+3+3+2+1 = n*(n+1)
       *                = 3 * 4 = 12
       */

      /* Note: entirely done with int and becomes double only 
       *       on assignement to the factor variable.
       */
      i = (optInTimePeriod>>1);
      factor = (i+1)*(i+1); 
      factor = 1.0/factor;

      /* Initialize all the variable before
       * starting to iterate for each output.
       */
      trailingIdx = startIdx-lookbackTotal;
      middleIdx   = trailingIdx + i;
      todayIdx    = middleIdx + i;
      numerator   = 0.0;
      numeratorSub = 0.0;
      for( i=middleIdx; i >= trailingIdx; i-- )
      {
         tempReal      = inReal[i];
         numeratorSub += tempReal;
         numerator    += numeratorSub;
      }
      numeratorAdd = 0.0;
      middleIdx++;
      for( i=middleIdx; i <= todayIdx; i++ )
      {
         tempReal      = inReal[i];
         numeratorAdd += tempReal;
         numerator    += numeratorAdd;
      }

      /* Write the first output */
      outIdx = 0;
      tempReal = inReal[trailingIdx++]; 
      outReal[outIdx++] = numerator * factor;
      todayIdx++;

      /* Note: The value at the trailingIdx was saved
       *       in tempReal to account for the case where
       *       outReal and inReal are ptr on the same
       *       buffer.
       */

      /* Iterate for remaining output */
      while( todayIdx <= endIdx )
      {
         /* Step (1) */
         numerator    -= numeratorSub;
         numeratorSub -= tempReal;
         tempReal      = inReal[middleIdx++];
         numeratorSub += tempReal;

         /* Step (2) */
         numerator    += numeratorAdd;
         numeratorAdd -= tempReal;
         tempReal      = inReal[todayIdx++];
         numeratorAdd += tempReal;

         /* Step (3) */
         numerator    += tempReal;

         /* Step (4) */
         tempReal = inReal[trailingIdx++]; 
         outReal[outIdx++] = numerator * factor;
      }
   }
   else
   {
      /* Even logic. 
       *
       * Very similar to the odd logic, except:
       *  - calculation of the factor is different.
       *  - the coverage of the numeratorSub and numeratorAdd is
       *    slightly different.
       *  - Adjustment of numeratorAdd is different. See Step (2).
       */
      i = (optInTimePeriod>>1);
      factor = i*(i+1); 
      factor = 1.0/factor;

      /* Initialize all the variable before
       * starting to iterate for each output.
       */
      trailingIdx = startIdx-lookbackTotal;
      middleIdx   = trailingIdx + i - 1;
      todayIdx    = middleIdx + i;
      numerator   = 0.0;

      numeratorSub = 0.0;

      for( i=middleIdx; i >= trailingIdx; i-- )
      {
         tempReal      = inReal[i];
         numeratorSub += tempReal;
         numerator    += numeratorSub;
      }
      numeratorAdd = 0.0;
      middleIdx++;
      for( i=middleIdx; i <= todayIdx; i++ )
      {
         tempReal      = inReal[i];
         numeratorAdd += tempReal;
         numerator    += numeratorAdd;
      }

      /* Write the first output */
      outIdx = 0;
      tempReal = inReal[trailingIdx++]; 
      outReal[outIdx++] = numerator * factor;
      todayIdx++;

      /* Note: The value at the trailingIdx was saved
       *       in tempReal to account for the case where
       *       outReal and inReal are ptr on the same
       *       buffer.
       */

      /* Iterate for remaining output */
      while( todayIdx <= endIdx )
      {
         /* Step (1) */
         numerator    -= numeratorSub;
         numeratorSub -= tempReal;
         tempReal      = inReal[middleIdx++];
         numeratorSub += tempReal;

         /* Step (2) */
         numeratorAdd -= tempReal;
         numerator    += numeratorAdd;
         tempReal      = inReal[todayIdx++];
         numeratorAdd += tempReal;

         /* Step (3) */
         numerator    += tempReal;

         /* Step (4) */
         tempReal = inReal[trailingIdx++]; 
         outReal[outIdx++] = numerator * factor;
      }

   }
   
   VALUE_HANDLE_DEREF(outNBElement) = outIdx;
   VALUE_HANDLE_DEREF(outBegIdx)    = startIdx;

   return ENUM_VALUE(RetCode,TA_SUCCESS,Success);
}

/**** START GENCODE SECTION 5 - DO NOT DELETE THIS LINE ****/
/* Generated */ 
/* Generated */ #define  USE_SINGLE_PRECISION_INPUT
/* Generated */ #if !defined( _MANAGED ) && !defined( _JAVA )
/* Generated */    #undef   TA_PREFIX
/* Generated */    #define  TA_PREFIX(x) TA_S_##x
/* Generated */ #endif
/* Generated */ #undef   INPUT_TYPE
/* Generated */ #define  INPUT_TYPE float
/* Generated */ #if defined( _MANAGED )
/* Generated */ enum class Core::RetCode Core::Trima( int    startIdx,
/* Generated */                                       int    endIdx,
/* Generated */                                       cli::array<float>^ inReal,
/* Generated */                                       int           optInTimePeriod, /* From 2 to 100000 */
/* Generated */                                       [Out]int%    outBegIdx,
/* Generated */                                       [Out]int%    outNBElement,
/* Generated */                                       cli::array<double>^  outReal )
/* Generated */ #elif defined( _JAVA )
/* Generated */ public RetCode trima( int    startIdx,
/* Generated */                       int    endIdx,
/* Generated */                       float        inReal[],
/* Generated */                       int           optInTimePeriod, /* From 2 to 100000 */
/* Generated */                       MInteger     outBegIdx,
/* Generated */                       MInteger     outNBElement,
/* Generated */                       double        outReal[] )
/* Generated */ #else
/* Generated */ TA_RetCode TA_S_TRIMA( int    startIdx,
/* Generated */                        int    endIdx,
/* Generated */                        const float  inReal[],
/* Generated */                        int           optInTimePeriod, /* From 2 to 100000 */
/* Generated */                        int          *outBegIdx,
/* Generated */                        int          *outNBElement,
/* Generated */                        double        outReal[] )
/* Generated */ #endif
/* Generated */ {
/* Generated */    int lookbackTotal;
/* Generated */    double numerator;
/* Generated */    double numeratorSub;
/* Generated */    double numeratorAdd;
/* Generated */    int i, outIdx, todayIdx, trailingIdx, middleIdx;
/* Generated */    double factor, tempReal;
/* Generated */  #ifndef TA_FUNC_NO_RANGE_CHECK
/* Generated */     if( startIdx < 0 )
/* Generated */        return ENUM_VALUE(RetCode,TA_OUT_OF_RANGE_START_INDEX,OutOfRangeStartIndex);
/* Generated */     if( (endIdx < 0) || (endIdx < startIdx))
/* Generated */        return ENUM_VALUE(RetCode,TA_OUT_OF_RANGE_END_INDEX,OutOfRangeEndIndex);
/* Generated */     #if !defined(_JAVA)
/* Generated */     if( !inReal ) return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     #endif 
/* Generated */     if( (int)optInTimePeriod == TA_INTEGER_DEFAULT )
/* Generated */        optInTimePeriod = 30;
/* Generated */     else if( ((int)optInTimePeriod < 2) || ((int)optInTimePeriod > 100000) )
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     #if !defined(_JAVA)
/* Generated */     if( !outReal )
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     #endif 
/* Generated */  #endif 
/* Generated */    lookbackTotal = (optInTimePeriod-1);
/* Generated */    if( startIdx < lookbackTotal )
/* Generated */       startIdx = lookbackTotal;
/* Generated */    if( startIdx > endIdx )
/* Generated */    {
/* Generated */       VALUE_HANDLE_DEREF_TO_ZERO(outBegIdx);
/* Generated */       VALUE_HANDLE_DEREF_TO_ZERO(outNBElement);
/* Generated */       return ENUM_VALUE(RetCode,TA_SUCCESS,Success);
/* Generated */    }
/* Generated */    outIdx = 0;
/* Generated */    if( (optInTimePeriod % 2) == 1 )
/* Generated */    {
/* Generated */       i = (optInTimePeriod>>1);
/* Generated */       factor = (i+1)*(i+1); 
/* Generated */       factor = 1.0/factor;
/* Generated */       trailingIdx = startIdx-lookbackTotal;
/* Generated */       middleIdx   = trailingIdx + i;
/* Generated */       todayIdx    = middleIdx + i;
/* Generated */       numerator   = 0.0;
/* Generated */       numeratorSub = 0.0;
/* Generated */       for( i=middleIdx; i >= trailingIdx; i-- )
/* Generated */       {
/* Generated */          tempReal      = inReal[i];
/* Generated */          numeratorSub += tempReal;
/* Generated */          numerator    += numeratorSub;
/* Generated */       }
/* Generated */       numeratorAdd = 0.0;
/* Generated */       middleIdx++;
/* Generated */       for( i=middleIdx; i <= todayIdx; i++ )
/* Generated */       {
/* Generated */          tempReal      = inReal[i];
/* Generated */          numeratorAdd += tempReal;
/* Generated */          numerator    += numeratorAdd;
/* Generated */       }
/* Generated */       outIdx = 0;
/* Generated */       tempReal = inReal[trailingIdx++]; 
/* Generated */       outReal[outIdx++] = numerator * factor;
/* Generated */       todayIdx++;
/* Generated */       while( todayIdx <= endIdx )
/* Generated */       {
/* Generated */          numerator    -= numeratorSub;
/* Generated */          numeratorSub -= tempReal;
/* Generated */          tempReal      = inReal[middleIdx++];
/* Generated */          numeratorSub += tempReal;
/* Generated */          numerator    += numeratorAdd;
/* Generated */          numeratorAdd -= tempReal;
/* Generated */          tempReal      = inReal[todayIdx++];
/* Generated */          numeratorAdd += tempReal;
/* Generated */          numerator    += tempReal;
/* Generated */          tempReal = inReal[trailingIdx++]; 
/* Generated */          outReal[outIdx++] = numerator * factor;
/* Generated */       }
/* Generated */    }
/* Generated */    else
/* Generated */    {
/* Generated */       i = (optInTimePeriod>>1);
/* Generated */       factor = i*(i+1); 
/* Generated */       factor = 1.0/factor;
/* Generated */       trailingIdx = startIdx-lookbackTotal;
/* Generated */       middleIdx   = trailingIdx + i - 1;
/* Generated */       todayIdx    = middleIdx + i;
/* Generated */       numerator   = 0.0;
/* Generated */       numeratorSub = 0.0;
/* Generated */       for( i=middleIdx; i >= trailingIdx; i-- )
/* Generated */       {
/* Generated */          tempReal      = inReal[i];
/* Generated */          numeratorSub += tempReal;
/* Generated */          numerator    += numeratorSub;
/* Generated */       }
/* Generated */       numeratorAdd = 0.0;
/* Generated */       middleIdx++;
/* Generated */       for( i=middleIdx; i <= todayIdx; i++ )
/* Generated */       {
/* Generated */          tempReal      = inReal[i];
/* Generated */          numeratorAdd += tempReal;
/* Generated */          numerator    += numeratorAdd;
/* Generated */       }
/* Generated */       outIdx = 0;
/* Generated */       tempReal = inReal[trailingIdx++]; 
/* Generated */       outReal[outIdx++] = numerator * factor;
/* Generated */       todayIdx++;
/* Generated */       while( todayIdx <= endIdx )
/* Generated */       {
/* Generated */          numerator    -= numeratorSub;
/* Generated */          numeratorSub -= tempReal;
/* Generated */          tempReal      = inReal[middleIdx++];
/* Generated */          numeratorSub += tempReal;
/* Generated */          numeratorAdd -= tempReal;
/* Generated */          numerator    += numeratorAdd;
/* Generated */          tempReal      = inReal[todayIdx++];
/* Generated */          numeratorAdd += tempReal;
/* Generated */          numerator    += tempReal;
/* Generated */          tempReal = inReal[trailingIdx++]; 
/* Generated */          outReal[outIdx++] = numerator * factor;
/* Generated */       }
/* Generated */    }
/* Generated */    VALUE_HANDLE_DEREF(outNBElement) = outIdx;
/* Generated */    VALUE_HANDLE_DEREF(outBegIdx)    = startIdx;
/* Generated */    return ENUM_VALUE(RetCode,TA_SUCCESS,Success);
/* Generated */ }
/* Generated */ 
/* Generated */ #if defined( _MANAGED )
/* Generated */ }}} // Close namespace TicTacTec.TA.Lib
/* Generated */ #endif
/**** END GENCODE SECTION 5 - DO NOT DELETE THIS LINE ****/

