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

/* Important:
 *  This file is automatically generated by the utility ta_codegen.
 *  Any modifications will be lost on next execution of ta_codegen.
 *
 *  Modifications should instead be done with the "C" source file
 *  in ta-lib\src\ta_func
 */

/* List of contributors:
 *
 *  Initial  Name/description
 *  -------------------------------------------------------------------
 *  AC       Angelo Ciceri
 *
 *
 * Change history:
 *
 *  MMDDYY BY   Description
 *  -------------------------------------------------------------------
 *  011505 AC   Creation
 */

// Import types from parent module
use super::*;

// Allow non-snake-case names to maintain TA-Lib API compatibility
#[allow(non_snake_case)]
#[allow(unused_variables)]
#[allow(dead_code)]
#[allow(unused_mut)]
#[allow(unused_assignments)]
impl Core {
    /// Lookback period for [`Core::cdltakuri`]: the number of leading input values consumed before
    /// the first output value can be produced.
    pub fn cdltakuri_lookback(&self) -> usize {
        #[allow(non_snake_case)]
        let BodyDoji_rangeType: i32 = self.candle_settings.body_doji.range_type;
        #[allow(non_snake_case)]
        let BodyDoji_avgPeriod: i32 = self.candle_settings.body_doji.avg_period;
        #[allow(non_snake_case)]
        let BodyDoji_factor: f64 = self.candle_settings.body_doji.factor;
        #[allow(non_snake_case)]
        let ShadowVeryLong_rangeType: i32 = self.candle_settings.shadow_very_long.range_type;
        #[allow(non_snake_case)]
        let ShadowVeryLong_avgPeriod: i32 = self.candle_settings.shadow_very_long.avg_period;
        #[allow(non_snake_case)]
        let ShadowVeryLong_factor: f64 = self.candle_settings.shadow_very_long.factor;
        #[allow(non_snake_case)]
        let ShadowVeryShort_rangeType: i32 = self.candle_settings.shadow_very_short.range_type;
        #[allow(non_snake_case)]
        let ShadowVeryShort_avgPeriod: i32 = self.candle_settings.shadow_very_short.avg_period;
        #[allow(non_snake_case)]
        let ShadowVeryShort_factor: f64 = self.candle_settings.shadow_very_short.factor;
        return (((BodyDoji_avgPeriod).max(ShadowVeryShort_avgPeriod)).max(ShadowVeryLong_avgPeriod)) as usize;
    }
    /// Single-candle pattern: a doji whose open and close sit at the high (no/very short upper
    /// shadow) with a very long lower shadow, i.e. a dragonfly doji with an exceptionally long
    /// lower shadow. Emitted as a positive signal, but its directional meaning depends on the
    /// prevailing trend, which the code does not check. A hit marks a takuri (dragonfly-doji) line;
    /// a potential reversal only when read against the trend (typically a bottom/bullish reversal
    /// after a downtrend), which the code itself does not verify.
    ///
    /// # Arguments
    ///
    /// * `startIdx` — Start index of the requested calculation range.
    /// * `endIdx` — End index of the requested calculation range (inclusive).
    /// * `inOpen` — Open prices per bar.
    /// * `inHigh` — High prices per bar.
    /// * `inLow` — Low prices per bar.
    /// * `inClose` — Close prices per bar.
    /// * `outBegIdx` — Set to the input index of the first output value.
    /// * `outNBElement` — Set to the number of output values written.
    /// * `outInteger` — +100 when the takuri pattern is detected, 0 otherwise. Never negative;
    ///   the positive sign is a convention and does not by itself imply bullishness.
    ///
    /// # Errors
    ///
    /// Returns [`RetCode::OutOfRangeStartIndex`] when `endIdx < startIdx`.
    ///
    /// # Panics
    ///
    /// Input slices must cover `startIdx..=endIdx` and output slices must hold the number of values
    /// produced for that range: undersized slices panic or, for functions that forward to unchecked
    /// internals, cause undefined behavior. Sizing every output slice to the input length is always
    /// sufficient.
    ///
    /// # Examples
    ///
    /// ```
    /// use ta_lib::{Core, RetCode};
    ///
    /// let open: Vec<f64> = (0..252).map(|i| 100.0 + 10.0 * (0.1 * i as f64 - 0.05).sin()).collect();
    /// let high: Vec<f64> = (0..252).map(|i| 101.0 + 10.0 * (0.1 * i as f64).sin()).collect();
    /// let low: Vec<f64> = (0..252).map(|i| 99.0 + 10.0 * (0.1 * i as f64).sin()).collect();
    /// let close: Vec<f64> = (0..252).map(|i| 100.0 + 10.0 * (0.1 * i as f64).sin()).collect();
    ///
    /// let core = Core::new();
    /// let mut out_beg = 0;
    /// let mut out_nb = 0;
    /// let mut out = vec![0i32; 252];
    ///
    /// let ret = core.cdltakuri(
    ///     0, open.len() - 1, &open, &high, &low, &close,
    ///     &mut out_beg, &mut out_nb, &mut out,
    /// );
    /// assert_eq!(ret, RetCode::Success);
    /// assert!(out_nb > 0);
    /// ```
    ///
    /// # See also
    ///
    /// [`Core::cdldragonflydoji`] · [`Core::cdldoji`] · [`Core::cdlhammer`] ·
    /// [`Core::cdlgravestonedoji`]
    ///
    /// Further reading: [ta-lib.org/functions/cdltakuri](https://ta-lib.org/functions/cdltakuri/)
    #[doc(alias = "Takuri")]
    #[doc(alias = "Takuriline")]
    pub fn cdltakuri(
        &self,
        startIdx: usize,
        endIdx: usize,
        inOpen: &[f64],
        inHigh: &[f64],
        inLow: &[f64],
        inClose: &[f64],
        outBegIdx: &mut usize,
        outNBElement: &mut usize,
        outInteger: &mut [i32],
    ) -> RetCode {
        if endIdx < startIdx {
            return RetCode::OutOfRangeStartIndex;
        }
        let mut startIdx = startIdx;
        let mut BodyDojiPeriodTotal: f64 = 0.0_f64;
        let mut ShadowVeryShortPeriodTotal: f64 = 0.0_f64;
        let mut ShadowVeryLongPeriodTotal: f64 = 0.0_f64;
        let mut i: usize = 0_usize;
        let mut outIdx: usize = 0_usize;
        let mut BodyDojiTrailingIdx: usize = 0_usize;
        let mut ShadowVeryShortTrailingIdx: usize = 0_usize;
        let mut ShadowVeryLongTrailingIdx: usize = 0_usize;
        let mut lookbackTotal: usize = 0_usize;
        #[allow(non_snake_case)]
        let BodyDoji_rangeType: i32 = self.candle_settings.body_doji.range_type;
        #[allow(non_snake_case)]
        let BodyDoji_avgPeriod: i32 = self.candle_settings.body_doji.avg_period;
        #[allow(non_snake_case)]
        let BodyDoji_factor: f64 = self.candle_settings.body_doji.factor;
        #[allow(non_snake_case)]
        let ShadowVeryLong_rangeType: i32 = self.candle_settings.shadow_very_long.range_type;
        #[allow(non_snake_case)]
        let ShadowVeryLong_avgPeriod: i32 = self.candle_settings.shadow_very_long.avg_period;
        #[allow(non_snake_case)]
        let ShadowVeryLong_factor: f64 = self.candle_settings.shadow_very_long.factor;
        #[allow(non_snake_case)]
        let ShadowVeryShort_rangeType: i32 = self.candle_settings.shadow_very_short.range_type;
        #[allow(non_snake_case)]
        let ShadowVeryShort_avgPeriod: i32 = self.candle_settings.shadow_very_short.avg_period;
        #[allow(non_snake_case)]
        let ShadowVeryShort_factor: f64 = self.candle_settings.shadow_very_short.factor;
        // Identify the minimum number of price bar needed
        // to calculate at least one output.
        lookbackTotal = self.cdltakuri_lookback();
        // Move up the start index if there is not
        // enough initial data.
        if startIdx < lookbackTotal {
            startIdx = lookbackTotal;
        }
        // Make sure there is still something to evaluate.
        if startIdx > endIdx {
            (*outBegIdx) = 0;
            (*outNBElement) = 0;
            return RetCode::Success;
        }
        // Do the calculation using tight loops.
        // Add-up the initial period, except for the last value.
        BodyDojiPeriodTotal = 0.0;
        BodyDojiTrailingIdx = startIdx - (BodyDoji_avgPeriod) as usize;
        ShadowVeryShortPeriodTotal = 0.0;
        ShadowVeryShortTrailingIdx = startIdx - (ShadowVeryShort_avgPeriod) as usize;
        ShadowVeryLongPeriodTotal = 0.0;
        ShadowVeryLongTrailingIdx = startIdx - (ShadowVeryLong_avgPeriod) as usize;
        i = BodyDojiTrailingIdx;
        while i < startIdx {
            let mut _candlerange_0: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_0 = (inClose[i] - inOpen[i]).abs();
                }
                1 => {
                    _candlerange_0 = inHigh[i] - inLow[i];
                }
                2 => {
                    _candlerange_0 = inHigh[i] - inLow[i] - (inClose[i] - inOpen[i]).abs();
                }
                _ => {
                    _candlerange_0 = 0.0;
                }
            }
            BodyDojiPeriodTotal += _candlerange_0;
            i += 1;
        }
        i = ShadowVeryShortTrailingIdx;
        while i < startIdx {
            let mut _candlerange_1: f64;
            match ShadowVeryShort_rangeType {
                0 => {
                    _candlerange_1 = (inClose[i] - inOpen[i]).abs();
                }
                1 => {
                    _candlerange_1 = inHigh[i] - inLow[i];
                }
                2 => {
                    _candlerange_1 = inHigh[i] - inLow[i] - (inClose[i] - inOpen[i]).abs();
                }
                _ => {
                    _candlerange_1 = 0.0;
                }
            }
            ShadowVeryShortPeriodTotal += _candlerange_1;
            i += 1;
        }
        i = ShadowVeryLongTrailingIdx;
        while i < startIdx {
            let mut _candlerange_2: f64;
            match ShadowVeryLong_rangeType {
                0 => {
                    _candlerange_2 = (inClose[i] - inOpen[i]).abs();
                }
                1 => {
                    _candlerange_2 = inHigh[i] - inLow[i];
                }
                2 => {
                    _candlerange_2 = inHigh[i] - inLow[i] - (inClose[i] - inOpen[i]).abs();
                }
                _ => {
                    _candlerange_2 = 0.0;
                }
            }
            ShadowVeryLongPeriodTotal += _candlerange_2;
            i += 1;
        }
        // Proceed with the calculation for the requested range.
        //
        // Must have:
        // - doji body
        // - open and close at the high of the day = no or very short upper shadow
        // - very long lower shadow
        // The meaning of "doji", "very short" and "very long" is specified with TA_SetCandleSettings
        // outInteger is always positive (1 to 100) but this does not mean it is bullish: takuri must be considered
        // relatively to the trend
        outIdx = 0;
        loop {
            if (inClose[i] - inOpen[i]).abs() <= ((BodyDoji_factor) * (if (BodyDoji_avgPeriod) != 0 { (BodyDojiPeriodTotal) / (BodyDoji_avgPeriod as f64) } else { match BodyDoji_rangeType { 0 => (inClose[i] - inOpen[i]).abs(), 1 => (inHigh[i]) - (inLow[i]), _ => (inHigh[i]) - (inLow[i]) - ((inClose[i]) - (inOpen[i])).abs() } }) / (if (BodyDoji_rangeType) == 2 { 2.0 } else { 1.0 })) && (inHigh[i] - (if inClose[i] >= inOpen[i] { inClose[i] } else { inOpen[i] })) < ((ShadowVeryShort_factor) * (if (ShadowVeryShort_avgPeriod) != 0 { (ShadowVeryShortPeriodTotal) / (ShadowVeryShort_avgPeriod as f64) } else { match ShadowVeryShort_rangeType { 0 => (inClose[i] - inOpen[i]).abs(), 1 => (inHigh[i]) - (inLow[i]), _ => (inHigh[i]) - (inLow[i]) - ((inClose[i]) - (inOpen[i])).abs() } }) / (if (ShadowVeryShort_rangeType) == 2 { 2.0 } else { 1.0 })) && ((if inClose[i] >= inOpen[i] { inOpen[i] } else { inClose[i] }) - inLow[i]) > ((ShadowVeryLong_factor) * (if (ShadowVeryLong_avgPeriod) != 0 { (ShadowVeryLongPeriodTotal) / (ShadowVeryLong_avgPeriod as f64) } else { match ShadowVeryLong_rangeType { 0 => (inClose[i] - inOpen[i]).abs(), 1 => (inHigh[i]) - (inLow[i]), _ => (inHigh[i]) - (inLow[i]) - ((inClose[i]) - (inOpen[i])).abs() } }) / (if (ShadowVeryLong_rangeType) == 2 { 2.0 } else { 1.0 })) {
                outInteger[outIdx] = 100;
                outIdx += 1;
            } else {
                outInteger[outIdx] = 0;
                outIdx += 1;
            }
            // add the current range and subtract the first range: this is done after the pattern recognition
            // when avgPeriod is not 0, that means "compare with the previous candles" (it excludes the current candle)
            let mut _candlerange_3: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_3 = (inClose[i] - inOpen[i]).abs();
                }
                1 => {
                    _candlerange_3 = inHigh[i] - inLow[i];
                }
                2 => {
                    _candlerange_3 = inHigh[i] - inLow[i] - (inClose[i] - inOpen[i]).abs();
                }
                _ => {
                    _candlerange_3 = 0.0;
                }
            }
            let mut _candlerange_4: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_4 = (inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx]).abs();
                }
                1 => {
                    _candlerange_4 = inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx];
                }
                2 => {
                    _candlerange_4 = inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx] - (inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx]).abs();
                }
                _ => {
                    _candlerange_4 = 0.0;
                }
            }
            BodyDojiPeriodTotal += _candlerange_3 - _candlerange_4;
            let mut _candlerange_5: f64;
            match ShadowVeryShort_rangeType {
                0 => {
                    _candlerange_5 = (inClose[i] - inOpen[i]).abs();
                }
                1 => {
                    _candlerange_5 = inHigh[i] - inLow[i];
                }
                2 => {
                    _candlerange_5 = inHigh[i] - inLow[i] - (inClose[i] - inOpen[i]).abs();
                }
                _ => {
                    _candlerange_5 = 0.0;
                }
            }
            let mut _candlerange_6: f64;
            match ShadowVeryShort_rangeType {
                0 => {
                    _candlerange_6 = (inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx]).abs();
                }
                1 => {
                    _candlerange_6 = inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx];
                }
                2 => {
                    _candlerange_6 = inHigh[ShadowVeryShortTrailingIdx] - inLow[ShadowVeryShortTrailingIdx] - (inClose[ShadowVeryShortTrailingIdx] - inOpen[ShadowVeryShortTrailingIdx]).abs();
                }
                _ => {
                    _candlerange_6 = 0.0;
                }
            }
            ShadowVeryShortPeriodTotal += _candlerange_5 - _candlerange_6;
            let mut _candlerange_7: f64;
            match ShadowVeryLong_rangeType {
                0 => {
                    _candlerange_7 = (inClose[i] - inOpen[i]).abs();
                }
                1 => {
                    _candlerange_7 = inHigh[i] - inLow[i];
                }
                2 => {
                    _candlerange_7 = inHigh[i] - inLow[i] - (inClose[i] - inOpen[i]).abs();
                }
                _ => {
                    _candlerange_7 = 0.0;
                }
            }
            let mut _candlerange_8: f64;
            match ShadowVeryLong_rangeType {
                0 => {
                    _candlerange_8 = (inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx]).abs();
                }
                1 => {
                    _candlerange_8 = inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx];
                }
                2 => {
                    _candlerange_8 = inHigh[ShadowVeryLongTrailingIdx] - inLow[ShadowVeryLongTrailingIdx] - (inClose[ShadowVeryLongTrailingIdx] - inOpen[ShadowVeryLongTrailingIdx]).abs();
                }
                _ => {
                    _candlerange_8 = 0.0;
                }
            }
            ShadowVeryLongPeriodTotal += _candlerange_7 - _candlerange_8;
            i += 1;
            BodyDojiTrailingIdx += 1;
            ShadowVeryShortTrailingIdx += 1;
            ShadowVeryLongTrailingIdx += 1;
            if !(i <= endIdx) { break; }
        }
        // All done. Indicate the output limits and return.
        (*outNBElement) = outIdx;
        (*outBegIdx) = startIdx;
        return RetCode::Success;
    }
    /// Unchecked variant of [`Core::cdltakuri`], used for internal cross-indicator calls.
    ///
    /// Skips parameter validation and uses unchecked indexing internally. Every argument must
    /// satisfy the constraints documented on [`Core::cdltakuri`]; an out-of-range parameter, an
    /// input slice not covering `startIdx..=endIdx`, or an undersized output slice may panic or
    /// cause undefined behavior. Prefer [`Core::cdltakuri`].
    #[inline]
    pub fn cdltakuri_unguarded(
        &self,
        mut startIdx: usize,
        endIdx: usize,
        inOpen: &[f64],
        inHigh: &[f64],
        inLow: &[f64],
        inClose: &[f64],
        outBegIdx: &mut usize,
        outNBElement: &mut usize,
        outInteger: &mut [i32],
    ) -> RetCode {
        let mut BodyDojiPeriodTotal: f64 = 0.0_f64;
        let mut ShadowVeryShortPeriodTotal: f64 = 0.0_f64;
        let mut ShadowVeryLongPeriodTotal: f64 = 0.0_f64;
        let mut i: usize = 0_usize;
        let mut outIdx: usize = 0_usize;
        let mut BodyDojiTrailingIdx: usize = 0_usize;
        let mut ShadowVeryShortTrailingIdx: usize = 0_usize;
        let mut ShadowVeryLongTrailingIdx: usize = 0_usize;
        let mut lookbackTotal: usize = 0_usize;
        #[allow(non_snake_case)]
        let BodyDoji_rangeType: i32 = self.candle_settings.body_doji.range_type;
        #[allow(non_snake_case)]
        let BodyDoji_avgPeriod: i32 = self.candle_settings.body_doji.avg_period;
        #[allow(non_snake_case)]
        let BodyDoji_factor: f64 = self.candle_settings.body_doji.factor;
        #[allow(non_snake_case)]
        let ShadowVeryLong_rangeType: i32 = self.candle_settings.shadow_very_long.range_type;
        #[allow(non_snake_case)]
        let ShadowVeryLong_avgPeriod: i32 = self.candle_settings.shadow_very_long.avg_period;
        #[allow(non_snake_case)]
        let ShadowVeryLong_factor: f64 = self.candle_settings.shadow_very_long.factor;
        #[allow(non_snake_case)]
        let ShadowVeryShort_rangeType: i32 = self.candle_settings.shadow_very_short.range_type;
        #[allow(non_snake_case)]
        let ShadowVeryShort_avgPeriod: i32 = self.candle_settings.shadow_very_short.avg_period;
        #[allow(non_snake_case)]
        let ShadowVeryShort_factor: f64 = self.candle_settings.shadow_very_short.factor;
        unsafe {
        assert!(endIdx < inOpen.len());
        assert!(endIdx < inHigh.len());
        assert!(endIdx < inLow.len());
        assert!(endIdx < inClose.len());
        let _assertLb = self.cdltakuri_lookback();
        let _assertStart = if startIdx > _assertLb { startIdx } else { _assertLb };
        assert!(_assertStart > endIdx || endIdx - _assertStart < outInteger.len());
        lookbackTotal = self.cdltakuri_lookback();
        if startIdx < lookbackTotal {
            startIdx = lookbackTotal;
        }
        if startIdx > endIdx {
            (*outBegIdx) = 0;
            (*outNBElement) = 0;
            return RetCode::Success;
        }
        BodyDojiPeriodTotal = 0.0;
        BodyDojiTrailingIdx = startIdx - (BodyDoji_avgPeriod) as usize;
        ShadowVeryShortPeriodTotal = 0.0;
        ShadowVeryShortTrailingIdx = startIdx - (ShadowVeryShort_avgPeriod) as usize;
        ShadowVeryLongPeriodTotal = 0.0;
        ShadowVeryLongTrailingIdx = startIdx - (ShadowVeryLong_avgPeriod) as usize;
        i = BodyDojiTrailingIdx;
        while i < startIdx {
            let mut _candlerange_0: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_0 = (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                1 => {
                    _candlerange_0 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i);
                }
                2 => {
                    _candlerange_0 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i) - (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                _ => {
                    _candlerange_0 = 0.0;
                }
            }
            BodyDojiPeriodTotal += _candlerange_0;
            i += 1;
        }
        i = ShadowVeryShortTrailingIdx;
        while i < startIdx {
            let mut _candlerange_1: f64;
            match ShadowVeryShort_rangeType {
                0 => {
                    _candlerange_1 = (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                1 => {
                    _candlerange_1 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i);
                }
                2 => {
                    _candlerange_1 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i) - (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                _ => {
                    _candlerange_1 = 0.0;
                }
            }
            ShadowVeryShortPeriodTotal += _candlerange_1;
            i += 1;
        }
        i = ShadowVeryLongTrailingIdx;
        while i < startIdx {
            let mut _candlerange_2: f64;
            match ShadowVeryLong_rangeType {
                0 => {
                    _candlerange_2 = (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                1 => {
                    _candlerange_2 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i);
                }
                2 => {
                    _candlerange_2 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i) - (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                _ => {
                    _candlerange_2 = 0.0;
                }
            }
            ShadowVeryLongPeriodTotal += _candlerange_2;
            i += 1;
        }
        outIdx = 0;
        loop {
            if (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs() <= ((BodyDoji_factor) * (if (BodyDoji_avgPeriod) != 0 { (BodyDojiPeriodTotal) / (BodyDoji_avgPeriod as f64) } else { match BodyDoji_rangeType { 0 => (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs(), 1 => (*inHigh.as_ptr().add(i)) - (*inLow.as_ptr().add(i)), _ => (*inHigh.as_ptr().add(i)) - (*inLow.as_ptr().add(i)) - ((*inClose.as_ptr().add(i)) - (*inOpen.as_ptr().add(i))).abs() } }) / (if (BodyDoji_rangeType) == 2 { 2.0 } else { 1.0 })) && (*inHigh.as_ptr().add(i) - (if *inClose.as_ptr().add(i) >= *inOpen.as_ptr().add(i) { *inClose.as_ptr().add(i) } else { *inOpen.as_ptr().add(i) })) < ((ShadowVeryShort_factor) * (if (ShadowVeryShort_avgPeriod) != 0 { (ShadowVeryShortPeriodTotal) / (ShadowVeryShort_avgPeriod as f64) } else { match ShadowVeryShort_rangeType { 0 => (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs(), 1 => (*inHigh.as_ptr().add(i)) - (*inLow.as_ptr().add(i)), _ => (*inHigh.as_ptr().add(i)) - (*inLow.as_ptr().add(i)) - ((*inClose.as_ptr().add(i)) - (*inOpen.as_ptr().add(i))).abs() } }) / (if (ShadowVeryShort_rangeType) == 2 { 2.0 } else { 1.0 })) && ((if *inClose.as_ptr().add(i) >= *inOpen.as_ptr().add(i) { *inOpen.as_ptr().add(i) } else { *inClose.as_ptr().add(i) }) - *inLow.as_ptr().add(i)) > ((ShadowVeryLong_factor) * (if (ShadowVeryLong_avgPeriod) != 0 { (ShadowVeryLongPeriodTotal) / (ShadowVeryLong_avgPeriod as f64) } else { match ShadowVeryLong_rangeType { 0 => (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs(), 1 => (*inHigh.as_ptr().add(i)) - (*inLow.as_ptr().add(i)), _ => (*inHigh.as_ptr().add(i)) - (*inLow.as_ptr().add(i)) - ((*inClose.as_ptr().add(i)) - (*inOpen.as_ptr().add(i))).abs() } }) / (if (ShadowVeryLong_rangeType) == 2 { 2.0 } else { 1.0 })) {
                *outInteger.as_mut_ptr().add(outIdx) = 100;
                outIdx += 1;
            } else {
                *outInteger.as_mut_ptr().add(outIdx) = 0;
                outIdx += 1;
            }
            let mut _candlerange_3: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_3 = (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                1 => {
                    _candlerange_3 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i);
                }
                2 => {
                    _candlerange_3 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i) - (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                _ => {
                    _candlerange_3 = 0.0;
                }
            }
            let mut _candlerange_4: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_4 = (*inClose.as_ptr().add(BodyDojiTrailingIdx) - *inOpen.as_ptr().add(BodyDojiTrailingIdx)).abs();
                }
                1 => {
                    _candlerange_4 = *inHigh.as_ptr().add(BodyDojiTrailingIdx) - *inLow.as_ptr().add(BodyDojiTrailingIdx);
                }
                2 => {
                    _candlerange_4 = *inHigh.as_ptr().add(BodyDojiTrailingIdx) - *inLow.as_ptr().add(BodyDojiTrailingIdx) - (*inClose.as_ptr().add(BodyDojiTrailingIdx) - *inOpen.as_ptr().add(BodyDojiTrailingIdx)).abs();
                }
                _ => {
                    _candlerange_4 = 0.0;
                }
            }
            BodyDojiPeriodTotal += _candlerange_3 - _candlerange_4;
            let mut _candlerange_5: f64;
            match ShadowVeryShort_rangeType {
                0 => {
                    _candlerange_5 = (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                1 => {
                    _candlerange_5 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i);
                }
                2 => {
                    _candlerange_5 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i) - (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                _ => {
                    _candlerange_5 = 0.0;
                }
            }
            let mut _candlerange_6: f64;
            match ShadowVeryShort_rangeType {
                0 => {
                    _candlerange_6 = (*inClose.as_ptr().add(ShadowVeryShortTrailingIdx) - *inOpen.as_ptr().add(ShadowVeryShortTrailingIdx)).abs();
                }
                1 => {
                    _candlerange_6 = *inHigh.as_ptr().add(ShadowVeryShortTrailingIdx) - *inLow.as_ptr().add(ShadowVeryShortTrailingIdx);
                }
                2 => {
                    _candlerange_6 = *inHigh.as_ptr().add(ShadowVeryShortTrailingIdx) - *inLow.as_ptr().add(ShadowVeryShortTrailingIdx) - (*inClose.as_ptr().add(ShadowVeryShortTrailingIdx) - *inOpen.as_ptr().add(ShadowVeryShortTrailingIdx)).abs();
                }
                _ => {
                    _candlerange_6 = 0.0;
                }
            }
            ShadowVeryShortPeriodTotal += _candlerange_5 - _candlerange_6;
            let mut _candlerange_7: f64;
            match ShadowVeryLong_rangeType {
                0 => {
                    _candlerange_7 = (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                1 => {
                    _candlerange_7 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i);
                }
                2 => {
                    _candlerange_7 = *inHigh.as_ptr().add(i) - *inLow.as_ptr().add(i) - (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs();
                }
                _ => {
                    _candlerange_7 = 0.0;
                }
            }
            let mut _candlerange_8: f64;
            match ShadowVeryLong_rangeType {
                0 => {
                    _candlerange_8 = (*inClose.as_ptr().add(ShadowVeryLongTrailingIdx) - *inOpen.as_ptr().add(ShadowVeryLongTrailingIdx)).abs();
                }
                1 => {
                    _candlerange_8 = *inHigh.as_ptr().add(ShadowVeryLongTrailingIdx) - *inLow.as_ptr().add(ShadowVeryLongTrailingIdx);
                }
                2 => {
                    _candlerange_8 = *inHigh.as_ptr().add(ShadowVeryLongTrailingIdx) - *inLow.as_ptr().add(ShadowVeryLongTrailingIdx) - (*inClose.as_ptr().add(ShadowVeryLongTrailingIdx) - *inOpen.as_ptr().add(ShadowVeryLongTrailingIdx)).abs();
                }
                _ => {
                    _candlerange_8 = 0.0;
                }
            }
            ShadowVeryLongPeriodTotal += _candlerange_7 - _candlerange_8;
            i += 1;
            BodyDojiTrailingIdx += 1;
            ShadowVeryShortTrailingIdx += 1;
            ShadowVeryLongTrailingIdx += 1;
            if !(i <= endIdx) { break; }
        }
        (*outNBElement) = outIdx;
        (*outBegIdx) = startIdx;
        return RetCode::Success;
        } // unsafe
    }
}
/***************/
/* End of File */
/***************/
