text:
/* List of contributors:
 *
 *  Initial  Name/description
 *  -------------------------------------------------------------------
 *  MF       Mario Fortier
 *  PP       Peter Pudaite
 *  CF       Christo Fogelberg
 *
 * Change history:
 *
 *  MMDDYY BY    Description
 *  -------------------------------------------------------------------
 *  120802 MF    Template creation.
 *  091503 PP    Reworked TA_SAR to allow customisation of more SAR params.
 *  092103 MF    Some changes related on first round of tests
 *  092303 PP    Minor bug fixes.
 *  122104 MF,CF Fix#1089506 for out-of-bound access to ep_temp.
 *
 */

/* SAR_ROUNDING is just for test purpose when cross-referencing that
 * function with example from Wilder's book. Wilder is using two
 * decimal rounding for simplification. TA-Lib does not round.
 */
/* #define SAR_ROUNDING(x) x=round_pos_2(x) */
#define SAR_ROUNDING(x)

/**** 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::SarExtLookback( double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                         double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationMaxShort )  /* From 0 to TA_REAL_MAX */
/* Generated */
/* Generated */ #elif defined( _JAVA )
/* Generated */ public int sarExtLookback( double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                          double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                          double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                          double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                          double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                          double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                          double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                          double        optInAccelerationMaxShort )  /* From 0 to TA_REAL_MAX */
/* Generated */
/* Generated */ #else
/* Generated */ int TA_SAREXT_Lookback( double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                       double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationMaxShort )  /* From 0 to TA_REAL_MAX */
/* 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 */    if( optInStartValue == TA_REAL_DEFAULT )
/* Generated */       optInStartValue = 0.000000e+0;
/* Generated */    else if( (optInStartValue < -3.000000e+37) ||/* Generated */  (optInStartValue > 3.000000e+37) )
/* Generated */       return -1;
/* Generated */
/* Generated */    if( optInOffsetOnReverse == TA_REAL_DEFAULT )
/* Generated */       optInOffsetOnReverse = 0.000000e+0;
/* Generated */    else if( (optInOffsetOnReverse < 0.000000e+0) ||/* Generated */  (optInOffsetOnReverse > 3.000000e+37) )
/* Generated */       return -1;
/* Generated */
/* Generated */    if( optInAccelerationInitLong == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationInitLong = 2.000000e-2;
/* Generated */    else if( (optInAccelerationInitLong < 0.000000e+0) ||/* Generated */  (optInAccelerationInitLong > 3.000000e+37) )
/* Generated */       return -1;
/* Generated */
/* Generated */    if( optInAccelerationLong == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationLong = 2.000000e-2;
/* Generated */    else if( (optInAccelerationLong < 0.000000e+0) ||/* Generated */  (optInAccelerationLong > 3.000000e+37) )
/* Generated */       return -1;
/* Generated */
/* Generated */    if( optInAccelerationMaxLong == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationMaxLong = 2.000000e-1;
/* Generated */    else if( (optInAccelerationMaxLong < 0.000000e+0) ||/* Generated */  (optInAccelerationMaxLong > 3.000000e+37) )
/* Generated */       return -1;
/* Generated */
/* Generated */    if( optInAccelerationInitShort == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationInitShort = 2.000000e-2;
/* Generated */    else if( (optInAccelerationInitShort < 0.000000e+0) ||/* Generated */  (optInAccelerationInitShort > 3.000000e+37) )
/* Generated */       return -1;
/* Generated */
/* Generated */    if( optInAccelerationShort == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationShort = 2.000000e-2;
/* Generated */    else if( (optInAccelerationShort < 0.000000e+0) ||/* Generated */  (optInAccelerationShort > 3.000000e+37) )
/* Generated */       return -1;
/* Generated */
/* Generated */    if( optInAccelerationMaxShort == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationMaxShort = 2.000000e-1;
/* Generated */    else if( (optInAccelerationMaxShort < 0.000000e+0) ||/* Generated */  (optInAccelerationMaxShort > 3.000000e+37) )
/* Generated */       return -1;
/* Generated */
/* Generated */ #endif /* TA_FUNC_NO_RANGE_CHECK */
/**** END GENCODE SECTION 2 - DO NOT DELETE THIS LINE ****/

   /* insert lookback code here. */
   UNUSED_VARIABLE(optInStartValue);
   UNUSED_VARIABLE(optInOffsetOnReverse);
   UNUSED_VARIABLE(optInAccelerationInitLong);
   UNUSED_VARIABLE(optInAccelerationLong);
   UNUSED_VARIABLE(optInAccelerationMaxLong);
   UNUSED_VARIABLE(optInAccelerationInitShort);
   UNUSED_VARIABLE(optInAccelerationShort);
   UNUSED_VARIABLE(optInAccelerationMaxShort);

   /* SAR always sacrifices one price bar to establish the
    * initial extreme price.
    */

   return 1;
}

/**** START GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/
/*
 * TA_SAREXT - Parabolic SAR - Extended
 *
 * Input  = High, Low
 * Output = double
 *
 * Optional Parameters
 * -------------------
 * optInStartValue:(From TA_REAL_MIN to TA_REAL_MAX)
 *    Start value and direction. 0 for Auto, >0 for Long, <0 for Short
 *
 * optInOffsetOnReverse:(From 0 to TA_REAL_MAX)
 *    Percent offset added/removed to initial stop on short/long reversal
 *
 * optInAccelerationInitLong:(From 0 to TA_REAL_MAX)
 *    Acceleration Factor initial value for the Long direction
 *
 * optInAccelerationLong:(From 0 to TA_REAL_MAX)
 *    Acceleration Factor for the Long direction
 *
 * optInAccelerationMaxLong:(From 0 to TA_REAL_MAX)
 *    Acceleration Factor maximum value for the Long direction
 *
 * optInAccelerationInitShort:(From 0 to TA_REAL_MAX)
 *    Acceleration Factor initial value for the Short direction
 *
 * optInAccelerationShort:(From 0 to TA_REAL_MAX)
 *    Acceleration Factor for the Short direction
 *
 * optInAccelerationMaxShort:(From 0 to TA_REAL_MAX)
 *    Acceleration Factor maximum value for the Short direction
 *
 *
 */
/* Generated */
/* Generated */ #if defined( _MANAGED ) && defined( USE_SUBARRAY )
/* Generated */ enum class Core::RetCode Core::SarExt( int    startIdx,
/* Generated */                                        int    endIdx,
/* Generated */                                        SubArray^    inHigh,
/* Generated */                                        SubArray^    inLow,
/* Generated */                                        double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                                        double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationMaxShort, /* From 0 to TA_REAL_MAX */
/* Generated */                                        [Out]int%    outBegIdx,
/* Generated */                                        [Out]int%    outNBElement,
/* Generated */                                        cli::array<double>^  outReal )
/* Generated */ #elif defined( _MANAGED )
/* Generated */ enum class Core::RetCode Core::SarExt( int    startIdx,
/* Generated */                                        int    endIdx,
/* Generated */                                        cli::array<double>^ inHigh,
/* Generated */                                        cli::array<double>^ inLow,
/* Generated */                                        double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                                        double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationMaxShort, /* From 0 to TA_REAL_MAX */
/* Generated */                                        [Out]int%    outBegIdx,
/* Generated */                                        [Out]int%    outNBElement,
/* Generated */                                        cli::array<double>^  outReal )
/* Generated */ #elif defined( _JAVA )
/* Generated */ public RetCode sarExt( int    startIdx,
/* Generated */                        int    endIdx,
/* Generated */                        double       inHigh[],
/* Generated */                        double       inLow[],
/* Generated */                        double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                        double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationMaxShort, /* From 0 to TA_REAL_MAX */
/* Generated */                        MInteger     outBegIdx,
/* Generated */                        MInteger     outNBElement,
/* Generated */                        double        outReal[] )
/* Generated */ #else
/* Generated */ TA_RetCode TA_SAREXT( int    startIdx,
/* Generated */                       int    endIdx,
/* Generated */                       const double inHigh[],
/* Generated */                       const double inLow[],
/* Generated */                       double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                       double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                       double        optInAccelerationMaxShort, /* From 0 to TA_REAL_MAX */
/* Generated */                       int          *outBegIdx,
/* Generated */                       int          *outNBElement,
/* Generated */                       double        outReal[] )
/* Generated */ #endif
/**** END GENCODE SECTION 3 - DO NOT DELETE THIS LINE ****/
{
	/* insert local variable here */
   ENUM_DECLARATION(RetCode) retCode;

   int isLong; /* > 0 indicates long. == 0 indicates short */
   int todayIdx, outIdx;

   VALUE_HANDLE_INT(tempInt);

   double newHigh, newLow, prevHigh, prevLow;
   double afLong, afShort, ep, sar;
   ARRAY_LOCAL(ep_temp,1);

/**** 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 */    /* Verify required price component. */
/* Generated */    if(!inHigh||!inLow)
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */
/* Generated */    #endif /* !defined(_JAVA)*/
/* Generated */    if( optInStartValue == TA_REAL_DEFAULT )
/* Generated */       optInStartValue = 0.000000e+0;
/* Generated */    else if( (optInStartValue < -3.000000e+37) ||/* Generated */  (optInStartValue > 3.000000e+37) )
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */
/* Generated */    if( optInOffsetOnReverse == TA_REAL_DEFAULT )
/* Generated */       optInOffsetOnReverse = 0.000000e+0;
/* Generated */    else if( (optInOffsetOnReverse < 0.000000e+0) ||/* Generated */  (optInOffsetOnReverse > 3.000000e+37) )
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */
/* Generated */    if( optInAccelerationInitLong == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationInitLong = 2.000000e-2;
/* Generated */    else if( (optInAccelerationInitLong < 0.000000e+0) ||/* Generated */  (optInAccelerationInitLong > 3.000000e+37) )
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */
/* Generated */    if( optInAccelerationLong == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationLong = 2.000000e-2;
/* Generated */    else if( (optInAccelerationLong < 0.000000e+0) ||/* Generated */  (optInAccelerationLong > 3.000000e+37) )
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */
/* Generated */    if( optInAccelerationMaxLong == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationMaxLong = 2.000000e-1;
/* Generated */    else if( (optInAccelerationMaxLong < 0.000000e+0) ||/* Generated */  (optInAccelerationMaxLong > 3.000000e+37) )
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */
/* Generated */    if( optInAccelerationInitShort == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationInitShort = 2.000000e-2;
/* Generated */    else if( (optInAccelerationInitShort < 0.000000e+0) ||/* Generated */  (optInAccelerationInitShort > 3.000000e+37) )
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */
/* Generated */    if( optInAccelerationShort == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationShort = 2.000000e-2;
/* Generated */    else if( (optInAccelerationShort < 0.000000e+0) ||/* Generated */  (optInAccelerationShort > 3.000000e+37) )
/* Generated */       return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */
/* Generated */    if( optInAccelerationMaxShort == TA_REAL_DEFAULT )
/* Generated */       optInAccelerationMaxShort = 2.000000e-1;
/* Generated */    else if( (optInAccelerationMaxShort < 0.000000e+0) ||/* Generated */  (optInAccelerationMaxShort > 3.000000e+37) )
/* 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. */

   /* This function is the same as TA_SAR, except that the caller has
    * greater control on the SAR dynamic and initial state.
    *
    * In additon, the TA_SAREXT returns negative values when the position
    * is short. This allow to distinguish when the SAR do actually reverse.
    */

   /* Implementation of the SAR has been a little bit open to interpretation
    * since Wilder (the original author) did not define a precise algorithm
    * on how to bootstrap the algorithm. Take any existing software application
    * and you will see slight variation on how the algorithm was adapted.
    *
    * What is the initial trade direction? Long or short?
    * ===================================================
    * The interpretation of what should be the initial SAR values is
    * open to interpretation, particularly since the caller to the function
    * does not specify the initial direction of the trade.
    *
    * In TA-Lib, the following default logic is used:
    *  - Calculate +DM and -DM between the first and
    *    second bar. The highest directional indication will
    *    indicate the assumed direction of the trade for the second
    *    price bar.
    *  - In the case of a tie between +DM and -DM,
    *    the direction is LONG by default.
    *
    * What is the initial "extreme point" and thus SAR?
    * =================================================
    * The following shows how different people took different approach:
    *  - Metastock use the first price bar high/low depending of
    *    the direction. No SAR is calculated for the first price
    *    bar.
    *  - Tradestation use the closing price of the second bar. No
    *    SAR are calculated for the first price bar.
    *  - Wilder (the original author) use the SIP from the
    *    previous trade (cannot be implement here since the
    *    direction and length of the previous trade is unknonw).
    *  - The Magazine TASC seems to follow Wilder approach which
    *    is not practical here.
    *
    * TA-Lib "consume" the first price bar and use its high/low as the
    * initial SAR of the second price bar. I found that approach to be
    * the closest to Wilders idea of having the first entry day use
    * the previous extreme point, except that here the extreme point is
    * derived solely from the first price bar. I found the same approach
    * to be used by Metastock.
    *
    *
    * Can I force the initial SAR?
    * ============================
    * Yes. Using the optInStartValue_0 parameter:
    *  optInStartValue_0 >  0 : SAR is long at optInStartValue_0.
    *  optInStartValue_0 <  0 : SAR is short at fabs(optInStartValue_0).
    *
    * And when optInStartValue_0 == 0, the logic is the same as for TA_SAR
    * (See previous two sections).
    */

   /* Identify the minimum number of price bar needed
    * to calculate at least one output.
    *
    * Move up the start index if there is not
    * enough initial data.
    */
   if( startIdx < 1 )
      startIdx = 1;

   /* 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);
   }

   /* Check if the acceleration factors are being defined by the user.
    * Make sure the acceleration and maximum are coherent.
    * If not, correct the acceleration.
    * Default afLong = 0.02
    * Default afShort = 0.02
    */

   afLong = optInAccelerationInitLong;
   afShort = optInAccelerationInitShort;

   if( afLong > optInAccelerationMaxLong )
      afLong = optInAccelerationInitLong = optInAccelerationMaxLong;

   if( optInAccelerationLong > optInAccelerationMaxLong )
      optInAccelerationLong = optInAccelerationMaxLong;

   if( afShort > optInAccelerationMaxShort)
      afShort = optInAccelerationInitShort = optInAccelerationMaxShort;

   if( optInAccelerationShort > optInAccelerationMaxShort )
      optInAccelerationShort = optInAccelerationMaxShort;

   /* Initialise SAR calculations */

   if(optInStartValue == 0) /* Default action */
   {
      /* Identify if the initial direction is long or short.
       * (ep is just used as a temp buffer here, the name
       *  of the parameter is not significant).
       */
      retCode = FUNCTION_CALL(MINUS_DM)( startIdx, startIdx, inHigh, inLow, 1,
                                         VALUE_HANDLE_OUT(tempInt), VALUE_HANDLE_OUT(tempInt),
									     ep_temp );
      if( ep_temp[0] > 0 )
         isLong = 0;
      else
         isLong = 1;

      if( retCode != ENUM_VALUE(RetCode,TA_SUCCESS,Success) )
      {
         VALUE_HANDLE_DEREF_TO_ZERO(outBegIdx);
         VALUE_HANDLE_DEREF_TO_ZERO(outNBElement);
         return retCode;
      }
   }
   else if( optInStartValue > 0 ) /* Start Long */
   {
      isLong = 1;
   }
   else /* optInStartValue_0 < 0 => Start Short */
   {
      isLong = 0;
   }

   VALUE_HANDLE_DEREF(outBegIdx) = startIdx;
   outIdx = 0;

   /* Write the first SAR. */
   todayIdx = startIdx;

   newHigh = inHigh[todayIdx-1];
   newLow  = inLow[todayIdx-1];

   SAR_ROUNDING(newHigh);
   SAR_ROUNDING(newLow);

   if(optInStartValue == 0) /* Default action */
   {
      if( isLong == 1 )
      {
         ep  = inHigh[todayIdx];
         sar = newLow;
      }
      else
      {
         ep  = inLow[todayIdx];
         sar = newHigh;
      }
   }
   else if ( optInStartValue > 0 ) /* Start Long at specified value. */
   {
      ep  = inHigh[todayIdx];
      sar = optInStartValue;
   }
   else /* if optInStartValue < 0 => Start Short at specified value. */
   {
      ep  = inLow[todayIdx];
      sar = std_fabs(optInStartValue);
   }

   SAR_ROUNDING(sar);

   /* Cheat on the newLow and newHigh for the
    * first iteration.
    */
   newLow  = inLow[todayIdx];
   newHigh = inHigh[todayIdx];

   while( todayIdx <= endIdx )
   {
      prevLow  = newLow;
      prevHigh = newHigh;
      newLow  = inLow[todayIdx];
      newHigh = inHigh[todayIdx];
      todayIdx++;

      SAR_ROUNDING(newLow);
      SAR_ROUNDING(newHigh);

      if( isLong == 1 )
      {
         /* Switch to short if the low penetrates the SAR value. */
         if( newLow <= sar )
         {
            /* Switch and Overide the SAR with the ep */
            isLong = 0;
            sar = ep;

            /* Make sure the overide SAR is within
             * yesterday's and today's range.
             */
            if( sar < prevHigh )
               sar = prevHigh;
            if( sar < newHigh )
               sar = newHigh;

            /* Output the overide SAR  */
            if( optInOffsetOnReverse != 0.0 )
               sar += sar * optInOffsetOnReverse;
            outReal[outIdx++] = -sar;

            /* Adjust afShort and ep */
            afShort = optInAccelerationInitShort;
            ep = newLow;

            /* Calculate the new SAR */
            sar = sar + afShort * (ep - sar);
            SAR_ROUNDING( sar );

            /* Make sure the new SAR is within
             * yesterday's and today's range.
             */
            if( sar < prevHigh )
               sar = prevHigh;
            if( sar < newHigh )
               sar = newHigh;
         }
         else
         {
            /* No switch */

            /* Output the SAR (was calculated in the previous iteration) */
            outReal[outIdx++] = sar;

            /* Adjust afLong and ep. */
            if( newHigh > ep )
            {
               ep = newHigh;
               afLong += optInAccelerationLong;
               if( afLong > optInAccelerationMaxLong )
                  afLong = optInAccelerationMaxLong;
            }

            /* Calculate the new SAR */
            sar = sar + afLong * (ep - sar);
            SAR_ROUNDING( sar );

            /* Make sure the new SAR is within
             * yesterday's and today's range.
             */
            if( sar > prevLow )
               sar = prevLow;
            if( sar > newLow )
               sar = newLow;
         }
      }
      else
      {
         /* Switch to long if the high penetrates the SAR value. */
         if( newHigh >= sar )
         {
            /* Switch and Overide the SAR with the ep */
            isLong = 1;
            sar = ep;

            /* Make sure the overide SAR is within
             * yesterday's and today's range.
             */
            if( sar > prevLow )
               sar = prevLow;
            if( sar > newLow )
               sar = newLow;

            /* Output the overide SAR  */
            if( optInOffsetOnReverse != 0.0 )
               sar -= sar * optInOffsetOnReverse;
            outReal[outIdx++] = sar;

            /* Adjust afLong and ep */
            afLong = optInAccelerationInitLong;
            ep = newHigh;

            /* Calculate the new SAR */
            sar = sar + afLong * (ep - sar);
            SAR_ROUNDING( sar );

            /* Make sure the new SAR is within
             * yesterday's and today's range.
             */
            if( sar > prevLow )
               sar = prevLow;
            if( sar > newLow )
               sar = newLow;
         }
         else
         {
            /* No switch */

            /* Output the SAR (was calculated in the previous iteration) */
            outReal[outIdx++] = -sar;

            /* Adjust afShort and ep. */
            if( newLow < ep )
            {
               ep = newLow;
               afShort += optInAccelerationShort;
               if( afShort > optInAccelerationMaxShort )
                  afShort = optInAccelerationMaxShort;
            }

            /* Calculate the new SAR */
            sar = sar + afShort * (ep - sar);
            SAR_ROUNDING( sar );

            /* Make sure the new SAR is within
             * yesterday's and today's range.
             */
            if( sar < prevHigh )
               sar = prevHigh;
            if( sar < newHigh )
               sar = newHigh;
         }
      }
   }

   VALUE_HANDLE_DEREF(outNBElement) = outIdx;

   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::SarExt( int    startIdx,
/* Generated */                                        int    endIdx,
/* Generated */                                        cli::array<float>^ inHigh,
/* Generated */                                        cli::array<float>^ inLow,
/* Generated */                                        double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                                        double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                                        double        optInAccelerationMaxShort, /* From 0 to TA_REAL_MAX */
/* Generated */                                        [Out]int%    outBegIdx,
/* Generated */                                        [Out]int%    outNBElement,
/* Generated */                                        cli::array<double>^  outReal )
/* Generated */ #elif defined( _JAVA )
/* Generated */ public RetCode sarExt( int    startIdx,
/* Generated */                        int    endIdx,
/* Generated */                        float        inHigh[],
/* Generated */                        float        inLow[],
/* Generated */                        double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                        double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                        double        optInAccelerationMaxShort, /* From 0 to TA_REAL_MAX */
/* Generated */                        MInteger     outBegIdx,
/* Generated */                        MInteger     outNBElement,
/* Generated */                        double        outReal[] )
/* Generated */ #else
/* Generated */ TA_RetCode TA_S_SAREXT( int    startIdx,
/* Generated */                         int    endIdx,
/* Generated */                         const float  inHigh[],
/* Generated */                         const float  inLow[],
/* Generated */                         double        optInStartValue, /* From TA_REAL_MIN to TA_REAL_MAX */
/* Generated */                         double        optInOffsetOnReverse, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationInitLong, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationLong, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationMaxLong, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationInitShort, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationShort, /* From 0 to TA_REAL_MAX */
/* Generated */                         double        optInAccelerationMaxShort, /* From 0 to TA_REAL_MAX */
/* Generated */                         int          *outBegIdx,
/* Generated */                         int          *outNBElement,
/* Generated */                         double        outReal[] )
/* Generated */ #endif
/* Generated */ {
/* Generated */    ENUM_DECLARATION(RetCode) retCode;
/* Generated */    int isLong;
/* Generated */    int todayIdx, outIdx;
/* Generated */    VALUE_HANDLE_INT(tempInt);
/* Generated */    double newHigh, newLow, prevHigh, prevLow;
/* Generated */    double afLong, afShort, ep, sar;
/* Generated */    ARRAY_LOCAL(ep_temp,1);
/* 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(!inHigh||!inLow)
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     #endif
/* Generated */     if( optInStartValue == TA_REAL_DEFAULT )
/* Generated */        optInStartValue = 0.000000e+0;
/* Generated */     else if( (optInStartValue < -3.000000e+37) ||  (optInStartValue > 3.000000e+37) )
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     if( optInOffsetOnReverse == TA_REAL_DEFAULT )
/* Generated */        optInOffsetOnReverse = 0.000000e+0;
/* Generated */     else if( (optInOffsetOnReverse < 0.000000e+0) ||  (optInOffsetOnReverse > 3.000000e+37) )
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     if( optInAccelerationInitLong == TA_REAL_DEFAULT )
/* Generated */        optInAccelerationInitLong = 2.000000e-2;
/* Generated */     else if( (optInAccelerationInitLong < 0.000000e+0) ||  (optInAccelerationInitLong > 3.000000e+37) )
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     if( optInAccelerationLong == TA_REAL_DEFAULT )
/* Generated */        optInAccelerationLong = 2.000000e-2;
/* Generated */     else if( (optInAccelerationLong < 0.000000e+0) ||  (optInAccelerationLong > 3.000000e+37) )
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     if( optInAccelerationMaxLong == TA_REAL_DEFAULT )
/* Generated */        optInAccelerationMaxLong = 2.000000e-1;
/* Generated */     else if( (optInAccelerationMaxLong < 0.000000e+0) ||  (optInAccelerationMaxLong > 3.000000e+37) )
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     if( optInAccelerationInitShort == TA_REAL_DEFAULT )
/* Generated */        optInAccelerationInitShort = 2.000000e-2;
/* Generated */     else if( (optInAccelerationInitShort < 0.000000e+0) ||  (optInAccelerationInitShort > 3.000000e+37) )
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     if( optInAccelerationShort == TA_REAL_DEFAULT )
/* Generated */        optInAccelerationShort = 2.000000e-2;
/* Generated */     else if( (optInAccelerationShort < 0.000000e+0) ||  (optInAccelerationShort > 3.000000e+37) )
/* Generated */        return ENUM_VALUE(RetCode,TA_BAD_PARAM,BadParam);
/* Generated */     if( optInAccelerationMaxShort == TA_REAL_DEFAULT )
/* Generated */        optInAccelerationMaxShort = 2.000000e-1;
/* Generated */     else if( (optInAccelerationMaxShort < 0.000000e+0) ||  (optInAccelerationMaxShort > 3.000000e+37) )
/* 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 */    if( startIdx < 1 )
/* Generated */       startIdx = 1;
/* 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 */    afLong = optInAccelerationInitLong;
/* Generated */    afShort = optInAccelerationInitShort;
/* Generated */    if( afLong > optInAccelerationMaxLong )
/* Generated */       afLong = optInAccelerationInitLong = optInAccelerationMaxLong;
/* Generated */    if( optInAccelerationLong > optInAccelerationMaxLong )
/* Generated */       optInAccelerationLong = optInAccelerationMaxLong;
/* Generated */    if( afShort > optInAccelerationMaxShort)
/* Generated */       afShort = optInAccelerationInitShort = optInAccelerationMaxShort;
/* Generated */    if( optInAccelerationShort > optInAccelerationMaxShort )
/* Generated */       optInAccelerationShort = optInAccelerationMaxShort;
/* Generated */    if(optInStartValue == 0)
/* Generated */    {
/* Generated */       retCode = FUNCTION_CALL(MINUS_DM)( startIdx, startIdx, inHigh, inLow, 1,
/* Generated */                                          VALUE_HANDLE_OUT(tempInt), VALUE_HANDLE_OUT(tempInt),
/* Generated */ 									     ep_temp );
/* Generated */       if( ep_temp[0] > 0 )
/* Generated */          isLong = 0;
/* Generated */       else
/* Generated */          isLong = 1;
/* Generated */       if( retCode != ENUM_VALUE(RetCode,TA_SUCCESS,Success) )
/* Generated */       {
/* Generated */          VALUE_HANDLE_DEREF_TO_ZERO(outBegIdx);
/* Generated */          VALUE_HANDLE_DEREF_TO_ZERO(outNBElement);
/* Generated */          return retCode;
/* Generated */       }
/* Generated */    }
/* Generated */    else if( optInStartValue > 0 )
/* Generated */    {
/* Generated */       isLong = 1;
/* Generated */    }
/* Generated */    else
/* Generated */    {
/* Generated */       isLong = 0;
/* Generated */    }
/* Generated */    VALUE_HANDLE_DEREF(outBegIdx) = startIdx;
/* Generated */    outIdx = 0;
/* Generated */    todayIdx = startIdx;
/* Generated */    newHigh = inHigh[todayIdx-1];
/* Generated */    newLow  = inLow[todayIdx-1];
/* Generated */    SAR_ROUNDING(newHigh);
/* Generated */    SAR_ROUNDING(newLow);
/* Generated */    if(optInStartValue == 0)
/* Generated */    {
/* Generated */       if( isLong == 1 )
/* Generated */       {
/* Generated */          ep  = inHigh[todayIdx];
/* Generated */          sar = newLow;
/* Generated */       }
/* Generated */       else
/* Generated */       {
/* Generated */          ep  = inLow[todayIdx];
/* Generated */          sar = newHigh;
/* Generated */       }
/* Generated */    }
/* Generated */    else if ( optInStartValue > 0 )
/* Generated */    {
/* Generated */       ep  = inHigh[todayIdx];
/* Generated */       sar = optInStartValue;
/* Generated */    }
/* Generated */    else
/* Generated */    {
/* Generated */       ep  = inLow[todayIdx];
/* Generated */       sar = std_fabs(optInStartValue);
/* Generated */    }
/* Generated */    SAR_ROUNDING(sar);
/* Generated */    newLow  = inLow[todayIdx];
/* Generated */    newHigh = inHigh[todayIdx];
/* Generated */    while( todayIdx <= endIdx )
/* Generated */    {
/* Generated */       prevLow  = newLow;
/* Generated */       prevHigh = newHigh;
/* Generated */       newLow  = inLow[todayIdx];
/* Generated */       newHigh = inHigh[todayIdx];
/* Generated */       todayIdx++;
/* Generated */       SAR_ROUNDING(newLow);
/* Generated */       SAR_ROUNDING(newHigh);
/* Generated */       if( isLong == 1 )
/* Generated */       {
/* Generated */          if( newLow <= sar )
/* Generated */          {
/* Generated */             isLong = 0;
/* Generated */             sar = ep;
/* Generated */             if( sar < prevHigh )
/* Generated */                sar = prevHigh;
/* Generated */             if( sar < newHigh )
/* Generated */                sar = newHigh;
/* Generated */             if( optInOffsetOnReverse != 0.0 )
/* Generated */                sar += sar * optInOffsetOnReverse;
/* Generated */             outReal[outIdx++] = -sar;
/* Generated */             afShort = optInAccelerationInitShort;
/* Generated */             ep = newLow;
/* Generated */             sar = sar + afShort * (ep - sar);
/* Generated */             SAR_ROUNDING( sar );
/* Generated */             if( sar < prevHigh )
/* Generated */                sar = prevHigh;
/* Generated */             if( sar < newHigh )
/* Generated */                sar = newHigh;
/* Generated */          }
/* Generated */          else
/* Generated */          {
/* Generated */             outReal[outIdx++] = sar;
/* Generated */             if( newHigh > ep )
/* Generated */             {
/* Generated */                ep = newHigh;
/* Generated */                afLong += optInAccelerationLong;
/* Generated */                if( afLong > optInAccelerationMaxLong )
/* Generated */                   afLong = optInAccelerationMaxLong;
/* Generated */             }
/* Generated */             sar = sar + afLong * (ep - sar);
/* Generated */             SAR_ROUNDING( sar );
/* Generated */             if( sar > prevLow )
/* Generated */                sar = prevLow;
/* Generated */             if( sar > newLow )
/* Generated */                sar = newLow;
/* Generated */          }
/* Generated */       }
/* Generated */       else
/* Generated */       {
/* Generated */          if( newHigh >= sar )
/* Generated */          {
/* Generated */             isLong = 1;
/* Generated */             sar = ep;
/* Generated */             if( sar > prevLow )
/* Generated */                sar = prevLow;
/* Generated */             if( sar > newLow )
/* Generated */                sar = newLow;
/* Generated */             if( optInOffsetOnReverse != 0.0 )
/* Generated */                sar -= sar * optInOffsetOnReverse;
/* Generated */             outReal[outIdx++] = sar;
/* Generated */             afLong = optInAccelerationInitLong;
/* Generated */             ep = newHigh;
/* Generated */             sar = sar + afLong * (ep - sar);
/* Generated */             SAR_ROUNDING( sar );
/* Generated */             if( sar > prevLow )
/* Generated */                sar = prevLow;
/* Generated */             if( sar > newLow )
/* Generated */                sar = newLow;
/* Generated */          }
/* Generated */          else
/* Generated */          {
/* Generated */             outReal[outIdx++] = -sar;
/* Generated */             if( newLow < ep )
/* Generated */             {
/* Generated */                ep = newLow;
/* Generated */                afShort += optInAccelerationShort;
/* Generated */                if( afShort > optInAccelerationMaxShort )
/* Generated */                   afShort = optInAccelerationMaxShort;
/* Generated */             }
/* Generated */             sar = sar + afShort * (ep - sar);
/* Generated */             SAR_ROUNDING( sar );
/* Generated */             if( sar < prevHigh )
/* Generated */                sar = prevHigh;
/* Generated */             if( sar < newHigh )
/* Generated */                sar = newHigh;
/* Generated */          }
/* Generated */       }
/* Generated */    }
/* Generated */    VALUE_HANDLE_DEREF(outNBElement) = outIdx;
/* 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 ****/


text:
Q: Push type to the end of the tuple with skipping optional I've found out how to push type to the end of the tuple:
type Cons<H, T extends readonly any[]> =
    ((head: H, ...tail: T) => void) extends ((...cons: infer R) => void) ? R : never;

type Push<T extends readonly any[], V>
    = T extends any ? Cons<void, T> extends infer U ?
    { [K in keyof U]: K extends keyof T ? T[K] : V } : never : never;

And in general it works:
type A = Push<[1, 2, 3], 4>;  // [1, 2, 3, 4]
type B = Push<[1, 2, 3?], 4>; // [1, 2, 3 | undefined, 4?]

But I actually want it not to contain undefined if some parameters are optional:
A = [1, 2, 3, 4]
B = [1, 2, 3, 4] | [1, 2, 4] // How can I get this?
B = [1, 2, 3 | undefined, 4] | [1, 2, 4] // or this?

Demo

Actually I'm trying to do this:
function doSmth<F extends (...args: any) => number>(f: F, ...args: Push<Parameters<F>, string>) {
  var x: string = args.pop();
  return f(...args) + x;
}

function f1(x: number, y: number) {
  return x + y;
}

function f2(x: number, y?: number) {
  return x + (y || 0);
}

doSmth(f1, 1, 2, "A");
doSmth(f2, 1, 2, "B");
doSmth(f2, 1, "C"); // Problem here: should compile, but it doen't
doSmth(f2, 1, 2);   // And here: should not compile as last is not a string, but it does
doSmth(f2, 1, undefined, "D"); // Possible, but actually I do not care

A: UPDATE: TypeScript 4.0 will feature variadic tuple types, which will allow more flexible built-in tuple manipulation. Push<T, V> will be simply implemented as [...T, V].

Pre-TS4.0 answer:
Ugh, why?!  Ahem, I mean, I can maybe do this, but the more type-juggling involved, the less I'd recommend doing this for anything important.  There's a library called ts-toolbelt which is close to being "officially supported" by TypeScript (although it doesn't work in the Playground, at least not yet, so I'm not about to make an Stack Overflow answer that requires it) where you can probably build something that works.
How I'd approach this is to convert tuples with optional elements to unions of tuples without them.  Unfortunately, I'm missing a built-in way to take a number type like 6 and get a tuple of that length.  So I'm making a hardcoded list of tuples-of-various-lengths that I can map over.  You can extend it if you need this to work on longer tuples.  Here we go:
type Cons<H, T extends readonly any[]> =
    ((head: H, ...tail: T) => void) extends ((...cons: infer R) => void) ? R : never;

That's just the standard Cons<1, [2,3,4]> becomes [1,2,3,4].
type Tup = [[], [0], [0, 0], [0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; // make as long as you need

That's the big list of tuples.  So Tup[4] is [0,0,0,0], etc.
type TruncateTuple<T extends readonly any[], N extends number> = Extract<
    Tup[N] extends infer R ? { [K in keyof R]: K extends keyof T ? T[K] : never }
    : never, readonly any[]>;

That type takes a tuple T and a length N and truncates T to length N.  So TruncateTuple<[1,2,3,4], 2> should be [1,2].  It works by getting a tuple of length N from Tup, and maps over it with properties from T.
type OptTupleToUnion<T extends readonly any[]> =
    TruncateTuple<Required<T>, T['length']>;

Here's the main event... OptTupleToUnion takes a tuple T and produces a union from it of non-optional tuples.  It works by truncating Required<T> (that is, T with optional elements turned into required ones) to length T['length'] which is the union of possible lengths of T.  So OptTupleToUnion<[1,2,3?,4?]> should become [1,2] | [1,2,3] | [1,2,3,4].
Then I'll rename my old Push out of the way to _Push:
type _Push<T extends readonly any[], V>
    = T extends any ? Cons<void, T> extends infer U ?
    { [K in keyof U]: K extends keyof T ? T[K] : V } : never : never;

and make Push<T, V> act on OptTupleToUnion<T> instead of T:
type Push<T extends readonly any[], V> = T extends any ?
    _Push<OptTupleToUnion<T>, V> : never;

(with the same T extends any ? ..T.. : never to make sure unions get distributed)
Let's see if it works:
type A = Push<[1, 2, 3], 4>;  // [1, 2, 3, 4]
type B = Push<[1, 2, 3?], 4>; // [1, 2, 3, 4] | [1, 2, 4]

Yay, looks good.    I might have to give up if you start asking for more functionality here... maybe someone else has more stamina!
Okay, hope that helps; good luck!
Link to code

redpajama_set_name: RedPajamaStackExchange


Current ironman goals - 43 prayer and monkey madness to get free Bond.
Gratz! Good luck on the new goals.
It's an HCIM gonna leave it f2p for a little bit to get basic skills, mining, smithing, wc, cooking etc.. Since the xp/hr is pretty much the same then get it member. I can use bonds from a regular account onto my HCIM right?
Correct, just a right-click -> 'Use' onto your HCIM.


There's a new cat lady in town, and her name is…Lisa Simpson! Hoping to pad her college-bound resume with community service, Lisa lends a helping hand to Eleanor Abernathy (aka The Cat Lady) only to find that the feline-friendly female has gone missing. Soon, Lisa becomes responsible for the care and well-being of the wacky woman's whole kit and kaboodle of kitty cats.


When the lovely team at Soap N Skin sent me their Try Me Selection box. I have to say I was a little it, well OK, rather a lot excited… Why?!
Firstly, I love beauty, second, I love natural beauty and finally, since my battle with Cancer I am always on the lookout for standout products that work with my overly sensitive skin!
So who are Soap N Skin?
Two friends, whose parents are also friends, creating a perfect unity in thoughts and ideas, what better way to start a project?! Samar and Rabia have set out to create products that they believe will unlock the benefits of combining nature's own remedies and harmonies.
Bringing Ingredients that they know work together, how? (well because their mothers told them so!) ensure the best combinations and result in fantastic products that are a treat to your body and a delight to your senses.
So back to the box I received, the box comes beautifully wrapped in tissue and was presented in an elegant white gift box.
So here is what was in the box.
I have to say, there is something about handmade natural products that gives you that exclusive feeling of luxury, as soon as you start touching and smelling them.
The Soap N Skin range is no different. As soon as you open the box, the intense aromas of the oils envelop your senses and transport you to gardens of pleasure and peace.
The Rosemary and Peppermint shampoo is a great cleanser and I'm sure it is great for helping with dandruff over a longer period of time. Brilliantly invigorating and perfect for the morning hair ritual!
with Calendula Oil Bodywash. The lavender and lime really mesh together welland the Calendula Oil leaves the skin feeling really soft too.
The Neroli & Patchouli with Jojoba Oil Soap was a brilliant and I absolutely love how this makes your skin feel. My daughter has hijacked this and has been using it daily with much love!
Finally the Rose, Sandalwood & Neem Body Butter is a really lovely body cream, the rose and sandlewood give it a real exotic appeal and the neem makes it feel like a treatment product. Again my daughter loves it, as it is gorgeous smelling yet light for her delicate skin.
Definitely looking forward to trying other products in the range and an absolute thumbs up for those that want a natural addition to their bath and body collection.


Selecting a Slide? What to look for!
Just in case you don't live and breathe slide products, the following information will help you gain a better understanding of how slides work, their attributes and what to consider in your process.
Whether perusing the catalog or using our handy Slide Selector, asking the following questions will help filter products into a manageable number of choices..
How wide is your drawer?
Whether the slides are intended to hold a drawer, door, component, or chassis, the width of the pull-out unit has a large effect on performance. If the slide does not have the strength and load capacity that corresponds to the width, it can cause racking or side-to-side movement. Excessive racking causes instability and can result in drawer failure.
Take note of the maximum recommended drawer widths for the slide products you are considering. When widths are 24" or greater, adding stability by using a slide with a larger cross section and a higher load rating is often the best solution.
Will the drawer hold dish towels or bricks? Equipment or paper medical gowns? As with drawer width, exceeding the established load rating may cause the drawer to fail. Be sure to include the weight of the drawer into the total anticipated weight the slides will carry. Accuride specifies a maximum load based on specific conditions, such as 18-inch slides mounted on a 16-inch-wide drawer. Refer to the product technical sheet to determine how load capacity is affected if your application calls for a drawer that is deeper or wider than the tested load conditions. Always test the slide in the intended application if it differs from the typical usage for the product.
Where and how will the drawer be used?
The slide selected for a residential kitchen drawer will be different than a slide chosen for an identically sized drawer in a toolbox. In commercial, institutional, or industrial environments, drawers encounter greater use--and abuse. Think about your intended application and the environment. You will want to select a more robust slide to offset conditions that are more rigorous.
What is the expected usage and lifetime of the product?
Will use be infrequent and require a low cycle count or will the application require greater durability with usage reaching 50,000 to 75,000 cycles—or more? Review the testing data on the product technical sheet to determine if it is appropriate for your application. If you are having trouble with slide selection, contact Technical Support for assistance. If you can't find an off-the-shelf solution that meets your specifications, don't rule out custom options. For larger projects, we offer customized options such as additional slide lengths, varied hole patterns, materials, finishes, and mounting brackets to help meet the specific needs of your project.
Just a slight push inward and the slide latch releases, propelling the drawer open 2.
Testing varies based on market applications. Performance can be affected by factors unique to a specific application, so testing slides in the intended application is recommended. See below for specific industry test details.
Slides for wood and furniture applications are tested in accordance with the guidelines of applicable ANSI/BIFMA specifications. Certain models have been BHMA certified or WI approved. In most cases, hardware alone cannot be rated; the testing standards pertain to the end product. Our goal is to provide products that, when combined with the purchaser's product, deliver a system that meets the governing standard.
Unless otherwise stated, Accuride slides are rated for the dynamic (cycled) load that an 18" pair of slides will carry without failure. This load rating decreases proportionally beyond the 18" length.
In the dynamic test, the center of gravity of the load is balanced between and at the midpoint of the drawer members.
Static (resting) load testing is based on placing 2 times the maximum permissible load in a fully extended drawer for 24 hours. The slides are measured for deflection at 0 hours and again at 24 hours.
In all cases, the static load capacity of each model is at least twice the dynamic load rating, providing at minimum, a 100% static safety factor, even when the slide is loaded to its maximum rating.
A total of 75,000 dynamic cycle tests: 55,000 cycles from the center of the drawer and 10,000 cycles from each side.
The maximum load rating is based on a pair of side-mounted slides.
The center of gravity of the load is centered between and at the midpoint of the drawer/chassis members.
Unless otherwise stated, testing is based on 18" slides mounted on a 16" wide drawer. This load rating decreases proportionally beyond the 18" length.
Dynamic tests are based on 10,000-cycles and include a 100% static safety factor.


text:
Women / Clothing / Sweaters / Women's Lisbon Long Cardigan
Paper Label Women's Lisbon Long Cardigan
CAD$ 170.00 CAD$ 84.94 (50% off)
The ultimate grandpa-style sweater taken to new heights, the Lisbon Long Cardigan from Paper Label is unbelievably soft and comfortable. Draping to below the knee, this generous knit is perfect for casual and cozy styling.
Yak fiber wool has been utilized by nomads in the Tran-Himalayan region for over a thousand years to make clothing, tents, ropes and blankets. Recently the fiber has also been used to produce premium-priced clothing and accessories. The coat of the yak is composed of three different types of Fiber that vary greatly in appearance and characteristics. The fur is usually dense, yet soft to the touch. This makes it perfect for conducting and holding heat.
Products with stretch offer a number of benefits depending on use. Certain fabrics, weaves and technologies allow for comfortable movement and overall range of motion. Stretch products often expand to create a secure fit for various body types.
Fabric: 52% Acrylic | 27% Nylon | 14% Cotton | 5% Yak | 2% Spandex
Ribbed knit detail
Dual side patch pockets
Vendor Style#: ANY-1903-374
Ladies "Junior" & Casual Fit
00 0 1 3 5 7 9 11 13 15
30" 31" 32" 33" 34" 35" 36" 38" 39" 40"
23" 23" 24" 25" 26" 27" 28" 29.5" 31" 32"
32.5" 33.3" 34.5" 35.5" 36.5" 37.5" 38.5" 40" 41.5" 43"
19" 19.5" 20" 20.5" 21" 21.5" 22" 22.5" 23" 23.5"
Ladies Modern & Contemporary Fit
-- 32" 32.5" 33.5" 34.5" 35.5" 36.5" 37.5" 38.5" 40"
-- 24" 25" 26" 26.5" 27" 28" 29.5" 31" 33"
-- 34.3" 35" 36" 37" 38" 39" 40" 42" 43"
-- 19" 20" 20.5" 21" 22" 22.5" 23.5" 24.5" 26"
Ladies Classic Fit
-- 32.5" 33.5" 34.5" 35.5" 36.5" 38" 39.5" 41" --
-- 25" 26" 27" 28" 29" 30" 31" 33" --
-- 35" 36" 37" 38" 39" 40.5" 42" 43.5" --
-- 20" 20.5" 21" 22" 23" 24" 25" 26.5" --
2 4 32 30 36 6 5
6 8 36 34 40 10 9

redpajama_set_name: RedPajamaCommonCrawl


Nashville's Earth Day Festival is a prime time for families to kick off spring by learning —and practicing — new ways to protect our environment.
The 17th annual free family festival in Centennial Park, which is 11 a.m. to 6 p.m. Saturday, is all about living green and learning about conservation, recycling, composting and other creative ways to protect Mother Earth.
The festival will feature more than 100 booths that are hosted by community groups, environmental organizations and government agencies, according to Brian Taylor, chair of Nashville Parks Foundation, the lead organizer for the event.
"Festivalgoers will have opportunities to learn how they can help improve the planet and our community each and every day."
In addition to the educational booths, there will be live music, including the Rock & Roll Playhouse kids music program at 2:15 p.m. and the Sam Bush Band at 4:05 p.m.
There will be a beer garden, as well as a green market with environmentally friendly items such as locally made clothing, organic products, locally made or grown food, environmental publications and other green items.
Unused or expired pharmaceuticals: Bring your unused or expired pharmaceuticals for safe and proper disposal at the Metro Nashville Police Department's exhibit.
Creative supplies: Visit the Reuse Village and bring any creative supplies, including ink and toner cartridges and used cellphones, for Turnip Green Creative Reuse.
When asked what she wanted attendees to take away from the Earth Day event, Laurel Creech said she'd love to hear them say: "Wow, I learned how to (blank) that I'm going to try at home and share with my neighbors and friends, too."
Parking is free in and around Centennial Park, and organizers encourage using the MTA bus service (West End No. 3, Charlotte No. 10 or University Connector No. 21). Biking is another good option, and there will be free bike valet parking provided by Walk/Bike Nashville.
Saturday also will be Nashville's Citywide Spring Clean event, and the mayor invites us all to help spruce up the city.
Shelby Bottoms Nature Center is kicking off the Earth Day weekend with a Friday night Full Moon Hike that will end with a campfire and s'mores. The evening is for all ages from 8 to 9:30 at Shelby Bottoms at 1900 Davidson St.
Williamson County Parks and Recreation will host its Earth Day on April 27 at Timberland Park with a 2-mile nature hike, two shorter walks — one focusing on wildflowers and one a nature poetry walk — and a nature lesson on butterflies.


text:
Brexit LIVE: Macron taunts Tory leader hopefuls over no deal threats - 'We're not scared!'
FRANCE's President Emmanuel Macron has taunted Britain by saying the EU should not be scared by the prospect of a no-deal Brexit - and suggested any further delay to Article 50 was far from guaranteed, even if Britain was to ask for one.
By Ciaran McGrath Ciaran McGrath
Mr Macron was speaking at a news conference after the confirmation of nominations for top EU roles, including Ursula von der Leyen, who is in line to replace Jean-Claude Juncker as European Commission President. He said there were no guarantees as to how Prime Minister Theresa May's replacement would act, but emphasised there was no need to be scared of a no deal scenario, nor should the EU "waste time" on the issue.
Emmanuel Macron has told Boris Johnson the EU is "not scared" of no deal (Image: GETTY)
"That is why I resigned over Chequers. It is a terrible moral blackmail it puts on the UK Government. We can't have that."
Elsewhere, veteran politician Ann Widdecombe is plotting an audacious return to Westminster as a Brexit Party MP almost 10 years after she stood down.
Mrs Widdecombe, 71, sat in the Commons until the 2010 general election when she retired from politics but made a surprise comeback in May when she was voted into the European parliament with Nigel Farage's new party.
She has now set her sights on getting back to Westminster alongside more than a dozen other Brexit Party MEPs planning to fight for a Commons seat.
Brexit-blocking Remain MPs suffer huge blow as clock runs down
Brexit latest: Boris Johnson and Jeremy Hunt battle over no-deal
The French President warned being afraid of the consequences of a crash out would leave the bloc "captive" to the demands of the UK's next PM.
He said: "We must not have fear of No Deal. Because if you fear No Deal you are a hostage to the ones you are facing.
Meawhile Tory leadership hopeful Boris Johnson has accused the EU of 'moral blackmail' over the Northern Ireland backstop as he insisted he would never allow the return of a hard border with the Republic.
In the latest Tory leadership hustings held in Belfast, former Foreign Secretary Mr Johnson said: "Under no circumstances, whatever happens, will I allow the EU or anyone else to create any kind of division down the Irish Sea or attenuate our Union.
Boris Johnson has accused Jean-Claude Juncker's EU of (Image: GETTY)
Ms Widdecombe told The Times her goal as an MP would be to "get Britain out of the EU" but said she would serve her full term if elected.
She said: "I'm not going early, certainly not. Running for parliament again was not what I would have chosen, but I am very, very clear that that is where duty lies. And I will do it with enthusiasm."
Ms Widdecombe was criticised last month after suggesting science could change a person's sexuality.
The Brexit Party has refused to release the names of its candidates. MEPs are not allowed to serve as MPs as well so any elected to Westminster would have to give up their European seats.
SCROLL DOWN FOR BREXIT LIVE UPDATES
Boris Johnson accused the EU of 'moral blackmail' (Image: PA)
8.20pm update: Europe "should not be scare" of no-deal Brexit, says Macron
French President Emmanuel Macron has said Europe should not be scared of a no-deal Brexit, but were Britain's new leadership to ask for an extension beyond October 31 it would have to provide something new to justify it.
Mr Macron told a news conference at the end of an EU Summit
"I hope from my side that we finish before.
"We shouldn't be scared of the worst-case scenario, which is always a possible option, and at the end of the day will be the responsibility of the British because at the end of the day until the last second the British government has the possibility to withdraw Article 50 and decide not to leave."
7.20pm update: Varadkar "confident" Juncker's replacement will show solidarity with Ireland over Brexit
Irish prime minister Leo Varadkar said he was confident the nominee to lead the European Commission, Germany's Ursula von den Leyen, would show the same solidarity with Ireland over Brexit as its outgoing president, Jean-Claude Juncker.
Varadkar also welcomed the naming of Belgium's Charles Michel as the next head of the European Council, the European Union's intergovernmental body, saying "he understands Brexit".
7.11pm update: Touted replacement for Juncker wants EU army
A German European federalist who says Brexit is behind her belief in the need for creation of an EU army is on the cusp of replacing Jean-Claude Juncker.
EU leaders finally settled on a deal after they were forced to return to Brussels today after spending nearly 20 hours rowing over the appointment of the next European Commission president.
Ursula Von Der Leyen, Germany's defence minister, became the compromise candidate after a Franco-German plot, cooked up at the G20 summit in Japan last week, failed to fill the EU's most senior roles.
Leaders threw out Dutch socialist Frans Timmermans for the role during the longest-running summit in recent years.
7.07pm update: Lagarde nominated as president of European Central Bank
The Council nominated International Monetary Fund managing director Christine Lagarde as president of the European Central Bank, while Spanish politician Josep Borrell Fontelles has been nominated as High Representative for Foreign Affairs and Security Policy.
Their nominations will be sent to the European Parliament for approval.
The new holders of the top positions will play a key role in negotiating the UK's future relationship with the EU with the next prime minister.
They will be responsible for deciding whether to agree to any changes to the Withdrawal Agreement - which both Tory leadership candidates are pledging to make - in order to avoid a no-deal Brexit.
7.05pm update: EU confirm Michel as next European Council president
EU leaders have elected Belgium prime minister Charles Michel to be the next European Council president, and proposed to install a German defence minister as the next head of the Commission in a decision with big implications for Brexit.
Following marathon talks at a special summit in Brussels, Donald Tusk - the current Council president - announced the EU 28 had agreed on the future leadership of the EU institutions.
He said the European Council proposed Ursula von der Leyen as European Commission president, replacing Jean-Claude Juncker.
6.20pm update: "They should have mooned EU," says Fabricant
Tory MP Michael Fabricant has criticised Brexit MEPs for turning their backs to the European Parliament - because he thinks their protest did not go far enough.
The 29 newly elected MEPs staged their protest on their first day at the assembly as a jazz band played the EU's anthem, Ode to Joy.
Mr Fabricat tweeted: "How disappointing that when the #Brexit MEPs turned their back on the #EU National Anthem (Ode to Joy) in the EU #Parliament, they didn't moon."
Michael Fabricant's tweet (Image: Twitter)
6.10pm update: Outgoing Brexit Party MEP's website is hijacked by pornographers
A departing MEP who quit Ukip for the Brexit Party has seen his official website taken over by pornographers and plastered with explicit images.
A link on Bill Etheridge's official European Parliament profile now takes visitors to a web service asking them if they are "looking for sex in Brussels?".
Mr Etheridge was elected to the assembly as a Ukip MEP in 2014 - but jumped ship earlier this year to join Nigel Farage's Brexit Party. He leaves office this week, handing over to a new batch of MEPs who were elected in May.
Visitors to www.billetheridge.co.uk are now asked to confirm whether they are over 18. If they click yes, they are told: "Many of these women are desperate single moms and cheating wives looking for some fun. They could be your neighbours or someone you know."
5.27pm update: "Government would be wrong to pursue no-deal policy," says Hammond
Chancellor Philip Hammond has said a British Government "would be wrong" to pursue a no-deal policy, in a clear indication of how far he is removed politically from both Tory leadership contenders.
In exchanges with shadow chancellor John McDonnell in the Commons, Mr Hammond said: "I think I have been consistently clear that I believe leaving with a no-deal exit will be bad for the UK, bad for the British economy, bad for the British people.
"We cannot however rule out that that could happen, because it is not entirely in our hands, but I do agree with him that it would be wrong for a British government to seek to pursue no-deal as a policy, and I believe that it will be for the House of Commons, of which I will continue proudly to be a member, to ensure that that doesn't happen."
5.06pm update: EU "stole" Ode to Joy, claims Brexit Party
European Union stooges have today been accused of appropriating Beethoven's Ode to Joy for the bloc's own self-gratification and as part of a plot to create a federalist superstate.
The European Parliament dragged in a brass quartet and opera singer to play the final movement of Beethoven's 9th Symphony as a welcoming gift to its new MEPs.
The classical piece has been adopted as the so-called "Anthem of Europe" by eurocrats wishing to emphasis the EU's importance.
Controversy was sparked this morning when Nigel Farage's Brexit Party turned their back as the anthem was played and Scottish National Party and Catalonian representatives refused to stand in protest.
4.36pm update: EU's trade deal with South American company "a death knell" for Irish beef sector
The trade deal between the European Union and South America's Mercosur trade bloc signals the "death knell" for the Irish beef sector, it has been claimed.
Fianna Fail leader Micheal Martin said the trade deal has angered the farming community in Ireland who face increasing pressure from Brexit and climate change issues.
The Mercosur bloc and the EU agreed on a free-trade deal after two decades of negotiations that concluded amid global trade tensions.
The proposed deal will allow imports of 99,000 tonnes of beef, 180,000 tonnes of poultry and 25,000 tonnes of pigmeat.
Mr Martin told the Dail that farming organisations have described the deal as "reckless" and "wrong".
"In many ways this trade agreement is outdated in that it ignores the impact of Brexit both now and into the future," he added.
"It potentially signals the death knell of a sector that has suffered unduly in recent times.
4.30pm update: No deal Brexit could cost economy £90 billion, claims Hammond
Chancellor Philip Hammond claimed a "disruptive" no-deal Brexit could have a £90 billion "hit" on the exchequer and suggested there will be "no money available" for Theresa May's successor.
Speaking in the Commons, he said: "We've built up around £26/27 billion of fiscal headroom and the purpose of having that headroom is precisely in order to protect the UK economy from the immediate effects of a possible no-deal exit.
"But I have no doubt whatsoever that in a no-deal exit we will need all of that money and more to respond to the immediate impacts of the disruption of a no-deal exit, and that will mean there is no money available for longer-term either tax cuts or spending increases.
"But let me go further, the Government's analysis suggests that in a disruptive no-deal exit there will be a hit to the exchequer of about £90 billion.
4.07pm update: MEPs irked by Brexit Party stunt
Irked rival MEPs have been left unimpressed by the Brexit Party's Ode to Joy stunt in Brussels.
Labour MEP Richard Corbett tweeted: "Nigel Farage and his band of Brexit company MEPs think they're being clever by standing with their backs to the chair at the opening session of the European Parliament.
"Looks pathetic and not impressed anyone."
Ska Keller, a German politician and member of the European Greens said: "They've been standing to represent citizens inside the European Parliament, and then the first thing they do is totally disrespect the basics of the European Union, its values and the house in which they wanted to represent citizens."
3.50pm update: Bercow shuts down Remainers' Brexit plot
Speaker John Bercow has not selected an amendment designed to shut down Department for Work and Pensions spending in the event of a no-deal Brexit.
Deputy Speaker Dame Rosie Winterton informed MPs of the Speaker's decision at the start of the estimates debate, which is linked to the approval of Government spending for the department.
Labour grandee Dame Margaret Beckett and Tory former attorney general Dominic Grieve tabled the amendment to four estimates motions.
On Monday, Mr Bercow did not select it for consideration for two motions connected to international development and education.
The same amendment is also tabled to a further estimates motion on the Ministry of Housing, Communities and Local Government.
This debate will take place later on Tuesday and a decision on amendment selection will follow.
3.34pm update: Parliament CAN block no-deal Brexit, admits Hunt
Parliament does have the power to block a no deal Brexit, Tory leadership contender Jeremy Hunt has acknowledged - while emphasising his belief that a technological answer to the Irish border conundrum can be found.
Mr Hunt said: "It has succeeded before and it may succeed again which is
why the safest and quickest way of getting out of the European Union is to choose a prime minister who can negotiate a deal that can get through parliament."
As for the border issue, the Foreign Secretary said: "What I would say is that there is nowhere anywhere in the world that is like the island of Ireland, with its very unique history and the resilience of its people and the way that it has overcome challenges in a way that frankly has been the envy of the world.
"So I think we can find a solution on the island of Ireland that may well blaze a trail around the world for how invisible borders can actually work."
3.22pm update: Hunt calls for "different solution" to border issue
Also speaking at the hustings, Jeremy Hunt, the Foreign Secretary, said that he also had opposed the backstop in Cabinet but had not made his misgivings public.
He said he opposed the measure, intended to ensure there is no return of a hard border on the island of Ireland, because it meant the UK could trapped in the EU customs regime indefinitely.
He added: "I do recognise that we are never going to have a deal to leave the EU with the backstop. So it has to change or it has to go.
"I was one of the people who argued against accepting the backstop in the Cabinet, but I think it is important the prime minister has a loyal foreign secretary so I kept those discussions private.
"But that has to change and we have to find a different solution."
2.28pm update: Johnson accuses Brussels of 'moral blackmail'
Boris Johnson has accused the European Union of "moral blackmail" over the Northern Ireland backstop as he insisted he would never allow the return of a hard border with the Republic.
In the latest Tory leadership hustings held in Belfast, both Mr Johnson and his rival Jeremy Hunt insisted the backstop had to go if there was to be a Brexit deal with Brussels.
Mr Johnson told party members he had felt so strongly over the issue he had resigned from Theresa May's Cabinet over the the Chequers plan which included the backstop.
"Under no circumstances, whatever happens, will I allow the EU or anyone else to create any kind of division down the Irish Sea or attenuate our Union," he said.
"That is why I resigned over Chequers. It is a terrible moral blackmail it puts on the UK Government. We can't have that.
"The way to protect the Union is to come out the EU whole and entire. Solve the border issues where they belong in the FTA (free trade agreement) we are going to do."
Leaders meet to break DEADLOCK over Brussels top jobs
Farage reveals the 'unspeakable' abuse MEPs hurl at Brexiteers
1.11pm update: Hammond wants of £90bn no deal Brexit hit
Chancellor Philip Hammond claimed a "disruptive" no deal Brexit could have a £90 billion "hit" on the exchequer and suggested there will be "no money available" for Theresa May's successor.
Mr Hammond poured scorn on pledges from Tory leadership hopefuls Jeremy Hunt and Boris Johnson, telling MPs he is not in favour of "ad hoc" spending or tax cut commitments being made.
He added all of the £26-27 billion "fiscal headroom" built up, and more, would be needed to respond to the immediate impacts of the UK leaving the EU without a deal.
In a further nod to the pledges made by Mr Hunt and Mr Johnson, the Chancellor said this meant there would be no cash available for long-term tax cuts or spending increases.
He said Government analysis suggesting a multibillion-pound "hit" to the exchequer in a no deal scenario would also have to be factored in to future decisions,
Mr Hammond's intervention comes after Mr Hunt and Mr Johnson both declared they are prepared to take the UK out of the EU without a deal.
11.30am update: Anger at Brexit Party MEP's European anthem stunt
Brexit Party MEPs who turned their back on the European Union anthem have been criticised back in the UK.
Leader Nigel Farage and newly elected candidates including Ann Widdecombe and Annunziata Rees-Mogg performed the protest as Beethoven'e Ode To Joy was played while MEPs gathered for the first session since May's European elections.
Mr Farage tweeted an image of his party's protest, saying: "The Brexit Party has already made its presence felt."
But Labour MP David Lammy was unimpressed.
He posted: "Brexit Party MEPs turning their backs on Europe, as they do their best to isolate the UK from the world.
"This is petty, small-minded little England at its worst. These plonkers do a proud and open nation a disservice. Shame on them."
Conservative MP Nicholas Soames tweeted: "Truly pathetic, oafish, childish behaviour by Brexit and Liberal MEPs. Grow up."
Brexiteer savages Macron for 'poisonous obstructionism' on Brexit
Chaos in Strasbourg as Leavers and Remainers carry out EU 'takeover'
10.31am update: DUP welcomes Tory leadership hopefuls' Brexit stance
DUP leaders have welcomed the hardline Brexit stances taken by Tory leadership hopefuls Boris Johnson and Jeremy Hunt.
The Northern Ireland party's Brexit spokesman Sammy Wilson said he welcomed commitments from both men to ditch the backstop arrangements designed to avoid physical checks on the Irish border.
He told BBC Radio 4's Today programme: "What we've heard so far, we're very pleased about.
"They have said that the current agreement is not going to work.
"They have both said that they are committed to the union. And thirdly, they're both saying that we will leave on 31 October."
Theresa May arrives in Brussels (Image: GETTY)
10am update: May arrives in Brussels for EU leaders meeting
Theresa May has arrived at the EU leaders summit for a third day of talks to decide on who takes over the bloc's top jobs.
The leaders of the 28 member states have been negotiating since Sunday with the top jobs at the EU Commission, European Council, European Parliament, and European Central Bank all up for grabs as well as the high representative for foreign affairs and security policy post.
Brexit Party MEPs turn their backs during the European Union anthem (Image: TWITTER/JAMES MATES)
9.45am update: Lineker brands Brexit Party stunt 'embarrassingly childish'
Brexit Party MEPs have turned their backs during the playing of the European Union anthem at the opening session of the European Parliament in Strasbourg.
ITV correspondent James Mates tweeted a picture of the scenes inside the debating chamber.
BBC presenter Gary Lineker branded the stunt 'embarrassingly childish' on social media.
Lib Dems wore their distinctive shirts (Image: TWITTER/GUY VERHOFSTADT)
9.39am update: Lib Dem MEP's wear B******* to Brexit shirts in EU chamber
Lib Dem MEPs have turned up for the plenary session on the European Parliament wearing B******* to Brexit shirts.
Guy Verhofstadt tweeted a photo and said: "Here's my new view in the plenary of the European Parliament!"
9.20am update: Annunziata Rees-Mogg 'We have a very serious job to do'
Brexit Party MEP Annunziata Rees-Mogg said she and her colleagues had serious work to do.
She told Express.co.uk: "I wish I weren't here. We voted to leave, we were promised we would leave. We haven't, and now we've got a very serious job to do on behalf of the British people - to get us out quickly."
When asked if she had spoken to her Eurosceptic Tory MP brother Jacob Rees-Mogg she said: "I haven't spoken to him since I've been here.
"But he is just as aware as I am that there is one thing we need to do and that is to get the United Kingdom's Democratic right to leave enacted.
"And we must leave by October 31, as Boris says, if you believe him, by hell or high water."
Brexit Party MEPs arrive in Strasbourg (Image: EXPRESS/JOE BARNES)
9.15am: Farage takes defiant stance in European Parliament
Brexit Party leader Nigel Farage has warned EU leaders his MEPs are in Strasbourg to be defiant.
"We are here to be defiant. We shouldn't be here at all. We are hoping we are only going to be here until October 31.
"And if we have to stay longer than that they'll know we're here.
"At the moment, we are cheerful because we won the election. We are the biggest party in the whole of Europe - how about that?
"We will behave ourselves unless we hear our country being traduced."
9am update: Farage's Brexit Party army of MEPs march on EU threatening 'turquoise takeover'
Brexit Party MEPs have descended on Strasbourg ready to be sworn in as they send a message to EU bosses they are ready to stand up for Britain.
The 751 MEPs elected in the May European elections will be sworn in today, including the 29 MEPs from Nigel Farage's eurosceptic movement.
Speaking in Strasbourg, Mr Farage promised a "turquoise takeover" if Brexit is not delivered.
The Brexit Party on Sunday unveiled its first 100 candidates ready to stand at a general election - and pledged to have every Westminster seat covered before a new Tory leader is in place.
8.54am update: Johnson 'to make EU free trade offer'
Boris Johnson will make an offer to the European Union over post-Brexit free trade but if it rejects his proposals Britain will leave the without a deal on October 31, according to Iain Duncan Smith.
Mr Duncan Smith, Mr Johnson's campaign chairman, told Sky News: "With Boris, what he's actually said clearly is: 'We're not going to go back and renegotiate'.
"What we're going to do is we will put a different offer down and say to them: 'Look - we want to get to free trade. Now we can either start talking about that now if you are serious and you want to have a process that means we don't end up with tariffs etcetera after the 31st - if that's what you want, the EU, then we are prepared to talk.
"But if all you are interested in doing is saying: 'All you can have is this deal', then the answer is: we will be prepared to leave on the 31st."
Boris Johnson (Image: GETTY)
8.33am update: Johnson and Hunt face questions in Northern Ireland
Tory leadership hopefuls Boris Johnson and Jeremy Hunt are set to face further questions about their Brexit plans at a hustings in Northern Ireland.
The pair will visit Belfast as they seek to win over party members, and are likely to be grilled on their proposals to resolve the Irish border issue and remove the controversial backstop.
Mr Hunt has said he believes there is "technology there now" to provide a solution, while Mr Johnson has suggested the backstop issue could be solved during the implementation period.
Mr Hunt and Mr Johnson are likely to face questions on the investigation of Northern Ireland military veterans, as well as their spending pledges.
Over the weekend they both backed calls for increased legal protection for UK troops and veterans.
Ann Widdecombe hopes to make a return to Parliament as a Brexit Party MP (Image: GETTY)
8.13am update: Benn insists Parliament can block no deal
Meanwhile Hilary Benn, Labour chairman of the Exiting The European Union Committee, insisted it was still possible to stop the UK crashing out of the EU, despite an attempt to shut down Government spending in the event of a no-deal Brexit appearing to have stalled.
He said: "When you get to the moment when Parliament is actually looking at this, then I believe the House of Commons will act, because I am still of the view that there is not a majority in Parliament for a no-deal Brexit."
Jeremy Hunt has secured the backing of William Hague (Image: GETTY)
7.30am update: Hague backs Hunt for Tory leadership
Former Conservative leader William Hague will back Jeremy Hunt in the Tory leadership race, saying he is "logically and inescapably drawn to vote" for the Foreign Secretary.
Ballot papers will be issued to Conservative Party members from later this week in the contest between Boris Johnson and Mr Hunt.
Mr Hague, who served as leader of the opposition between 1997 and 2001, said he and other members were facing a "decision made more difficult by the knowledge that if we collectively get this wrong there will probably be no further time to correct it".
He said: "The whole idea of a broad, centre-right party, which has an unbroken history in this country from Robert Peel to Theresa May, is now under threat.
"Serious mistakes in the coming months could be terminal for the world's most enduring political force."
Boris will 'revitalise' the UK and destroy Scottish nationalism
Green MEP mocks Leave voters with claim she has 'stopped Brexit'
Tory leadership LIVE: Rivals accused of turning UK into tax haven
Brexit News Brexit Party
First strike capability! Royal Navy industrial action will cripple Britain's fleet
Chile ace Alexis Sanchez limps off injured in Argentina game - Man Utd fans in meltdown
Chile star Alexis Sanchez backed to quit Man Utd for one reason - 'I feel sorry for him'
England finish fourth in Women's World Cup after 2-1 defeat to Sweden in play-off
EU divided: Anger as Brussels hits out at Ireland and suspends millions in fishing aid
Theresa May forced to sleep on sofa in Brussels after EU summit overruns - 'she's stoical'
Brexit boost: Johnson warns EU he is not bluffing over leaving with no deal on October 31
Jeremy Hunt reveals new treason law to imprison jihadist fighters and their supporters
Tory leadership LIVE: Seven in 10 Tories BACK Boris or Hunt suspending Parliament
Brexit breakthrough: Is THIS the shock solution to £39billion divorce row?
Boris Johnson condemns EU 'soft peddling' on Russia - 'UK forefront of Putin AGGRESSION!'
Tory leadership: Khan attacks Boris over historic 'homophobic' comments at Pride
Johnson calls on immigrants to learn English to integrate and 'feel British'
Jeremy Hunt tells EU to help make Brexit work for everyone
Brexit LIVE: Farage launches ferocious EU attack - 'Destroys nations in monstrous ways!'
Jeremy Hunt savaged for 'random' policies on BBC Newsnight by David Cameron's adviser
Boris Johnson vows to increase stop and search powers in his war against soft justice
Boris Johnson given 24 hour police protection amid concerns of random attack
Johnson vs Hunt: Tory voters regret casting ballot already as they 'flip-flop' over rivals
The real reason Labour is facing an 'identity crisis' over its Brexit stance
Revealed: Remainer Cabinet ministers' secret meetings to plot SABOTAGING no deal Brexit
Why a Labour government would be more DAMAGING to the UK economy than no deal Brexit
Brexit warning: Kate Hoey condemns EU exit delay - 'Unacceptable!'
Express.co.uk poll: Is it right for Tories to auction off access to Johnson and Hunt? VOTE
Brexit LIVE: Nicola Sturgeon attacked for failing to prepare for no deal -'Disappointing!'
Tory leadership LIVE: Hunt reported to Parliament over possible 'rule breach' - shock blow
Labour in chaos: Lawyer quits Labour's anti-Semitism inquiry legal team after just a year
Farage's warning to the EU: UK won't tolerate EU plot to freeze out London's financial hub
Parliament porn habits censored by Westminster in bid to protect MPs from hackers
Tory leadership debate: When is the ITV leaders debate?
EU shock: Controversial replacement for Juncker slated by shock German poll
Tories 'pimp out' next Tory leader by selling £300,000 dinner with Boris or Hunt
Brexit Britain under Boris Johnson will spark major new US trade deal says Duncan Smith
MOD shock: Top secret Porton Down files DUMPED in wheelie bin - 'terrorist's dream'
Boris Johnson shock: Tory leadership frontrunner not 'trusted' with classified secrets
Brexit Secretary's WARNING to Tory leader hopefuls - No deal plans MUST be 'turbo-charged'
EU split: Ireland threatens to reject new Brussels trade deal which took 20 years to agree
Brexit LIVE: Remainer Tory minister says John Bercow will plot with MPs to BLOCK no deal
May spotted eyeing up Boris Johnson's office as she prepares to be booted from No10
Boris Johnson COULD prorogue Parliament says Attorney-General in boost for no deal Brexit
Perfect for the top job! New EU chief watched naval repair budget spiral from £9m to £121m
European Central Bank shock: Fraud case which rocked EU nominee Christine Lagarde
George Osborne plots sensational comeback to REPLACE Lagarde as first Briton to head IMF
Boris Johnson attacks May for 'dithering' Brexit leadership - 'Three years of decay'
Brexit LIVE: Alarm bells in Westminster as Brexit-bashing EU Army fanatic set for top job
Tory leader LIVE: Boris Johnson's half a MILLION pound war chest to beat Hunt revealed
Brexit Party says Tories 'running scared' as Brecon candidate warns 'they face wipeout'
BREXIT SHOCK: How on August 1 people in a corner of Wales could swing Brexit
Juncker replacement nominee Ursula von der Leyen speaks out on Brexit and EU army – VIDEO
Who is Juncker replacement nominee Ursula von der Leyen? What does she say on Brexit?
Sunday, 7th July 2019


How much typing do you do on your smartphone? All those instant messages, search requests, snarky social media comments and more quickly add up to a whole load of text input, every single day. Speeding up that input can make a big difference to how much time you spend glued to the screen, so here's everything that can help.
You might just accept autocorrect and predictive text as they are, flaws and all, but you don't have to settle for the default configurations on Android or iOS—delve a little deeper and you can customize them to suit your own typing style, keeping the smart features you find helpful and ditching the rest.
On (stock) Android, you want to open up Settings then tap System, Languages & input, Virtual keyboard, Gboard, then Text correction. From this screen you can enable or disable autocorrect, the predictive text suggestion strip at the top of the keyboard, auto-spacing after punctuation, and auto-capitalization after periods.
You can also enable Personalized suggestions—which uses your typing and text input across all Google's services to make predictive text smarter—and Next-word suggestions, where the sentence is taken as a whole to improve the quality of predictions. These options should improve the accuracy of your text input in most cases.
Over on iOS, you can make changes to the default autocorrect behavior by opening up the Settings app then choosing General and Keyboard. You don't get as many options as you do with Android, but you can turn auto-capitalization on or off, as well as enabling or disabling the shortcut that lets you double-tap Space to drop in period at the end of a sentence and start a new one.
Autocorrect (where misspelled words are automatically corrected) and predictive text (where suggested words are shown above the keyboard) can both be turned on or off as you prefer. If your iPhone's autocorrect often slows you down rather than speeding you up, you might find it easier to turn it off.
Besides the autocorrect and predictive text features on your phone's keyboard, you can tweak a host of other settings without having to install any extra apps. It's worth playing around with these to see if any of them can improve your typing speed (and as a result, how productive you are on your phone).
If you're an Android user on the default Gboard keyboard, for example, long-press on the comma then slide to the right-hand icon to enable one-handed mode—making it much easier to type on one hand. Hit the arrow to change between left and right handedness, or the expand button to go back to normal.
From Settings, choose System, Languages & input, Virtual keyboard, Gboard, and Preferences to make more changes: You can change the keyboard height you make it easier to tap on, as well as change the way you access emojis and symbols (you might find it quicker to long-press for symbols rather than switch keyboard layouts).
Choose Glide typing instead of Preferences on the Gboard menu and you can switch on glide typing, where you can slide your finger along the keyboard without lifting it up from the screen—based on your starting and stopping, the keyboard should be able to work out what you're trying to type, and you might find it a faster input method.
iOS also has a one-handed keyboard mode if you're finding it tricky to get your digits stretched all the way across the screen. You can either long-press on the globe icon on the keyboard to access it, or go to General and Keyboards in Settings and then tap the One-Handed Keyboard option.
Just like macros on your desktop or laptop, mobile keyboard macros let you unfurl whole phrases and sentences with just a few well-chosen letters. You might want to use "omw" as a shortcut for "on my way" perhaps, which is actually one of the default macros you get with the iPhone keyboard.
The functionality is fairly easy to set up on both Android and iOS. On phones powered by Google's mobile OS, go to Settings then tap on System, Languages & input, Virtual keyboard, Gboard, Dictionary, and Personal dictionary. Choose your language, then tap the Plus icon (top right) to start adding words.
For example, you might input the text phrase "in my humble opinion" and then use the text shortcut "imho" to refer to it. The next time you type "imho" into the Gboard keyboard in any app, you'll see "in my humble opinion" appear as a suggestion—just tap on it to enter the full phrase.
Over on iOS, the same sort of trick can be achieved by opening up Settings and then tapping General, Keyboard, and Text Replacement. Apple provides two examples that you can check and edit, and then to make your own, tap on the Plus icon to the top right. Enter your phrase and your shortcut and you're done—again, the shortcuts appear as options in predictive text.
Whatever platform of phone you're on, you can set up as many shortcuts as you like, though if you start adding hundreds then the keyboard suggestions bar can get a little crowded. Make a note of the phrases you type a lot and put together some shortcuts to save yourself some time. This trick also works if you want to use ASCII emoticons. So "shrug" can become ¯\_(ツ)_/¯ and "glare" can become ಠ_ಠ.
Both Android and iOS support third-party keyboards, so you don't have to accept the default one you're given if you don't want to—you might find you can type quicker on an alternative one. Gboard, for example, is available on both Android and iOS, so you can take advantage of the next-word suggestions, the glide typing, and the other features no matter what your make of phone.
SwiftKey (Android, iOS) has long been one of the best alternative keyboards out there if you want to speed up your typing: It uses some AI trickery to work out your particular typing habits and favorite words choices, right down to when you like adding in emoji. That means its predictive text is smarter, and that means you can tap through whatever it is you're trying to say more quickly.
We also recommend giving Fleksy (Android, iOS) a whirl—here you can take advantage of keyboard customizations, to get a layout that particularly suits your digits, and gesture controls, so you can remove a word or phrase with a single swipe of the finger. It has a ton of additional features too, including GIF support, but not all of them are necessarily focused on improving your typing speed.
Other keyboards worthy of your attention that we'd like to point out are Hydrogen Keyboard Chrooma for Android, which includes features like gesture support and a split layout option, and Thumbly for iOS, which redesigns the entire keyboard so you can operate it more easily with just your thumb. The best (and fastest) option for you will depend on your own preferences and typing style.
Whenever you install a third-party keyboard, it will take you through the process of setting it up. To swap between keyboards later, go to System, Languages & input, Virtual keyboard and Manage keyboards in Android Settings, or General, Keyboard and Keyboards in iOS Settings.