/* 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
 *  -------------------------------------------------------------------
 *  102304 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::cdlabandonedbaby`]: the number of leading input values consumed
    /// before the first output value can be produced.
    ///
    /// # Arguments
    ///
    /// * `optInPenetration` — Fraction of the 1st candle's real body the 3rd close must
    ///   penetrate; default 0.3, range \[0, TA_REAL_MAX] (default 0.3, minimum 0)
    ///
    /// Returns `usize::MAX` when a parameter is out of range. Integer parameters accept `i32::MIN`
    /// to select their default value.
    #[inline]
    pub fn cdlabandonedbaby_lookback(&self, mut optInPenetration: f64) -> 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 BodyLong_rangeType: i32 = self.candle_settings.body_long.range_type;
        #[allow(non_snake_case)]
        let BodyLong_avgPeriod: i32 = self.candle_settings.body_long.avg_period;
        #[allow(non_snake_case)]
        let BodyLong_factor: f64 = self.candle_settings.body_long.factor;
        #[allow(non_snake_case)]
        let BodyShort_rangeType: i32 = self.candle_settings.body_short.range_type;
        #[allow(non_snake_case)]
        let BodyShort_avgPeriod: i32 = self.candle_settings.body_short.avg_period;
        #[allow(non_snake_case)]
        let BodyShort_factor: f64 = self.candle_settings.body_short.factor;
        return (((BodyDoji_avgPeriod).max(BodyLong_avgPeriod)).max(BodyShort_avgPeriod) + 2) as usize;
    }
    /// A three-candle reversal pattern: a long body, then a gapped-away doji, then a body of
    /// opposite color that gaps back the other way and closes deep into the first body. Bullish
    /// (bottom) or bearish (top) reversal signal. Nonzero hit signals a reversal: +100 abandoned
    /// baby bottom (bullish), -100 abandoned baby top (bearish).
    ///
    /// # Notes
    ///
    /// * Does not verify the prior trend the pattern classically assumes for significance.
    ///
    /// # 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.
    /// * `optInPenetration` — Fraction of the 1st candle's real body the 3rd close must
    ///   penetrate; default 0.3, range \[0, TA_REAL_MAX] (default 0.3, minimum 0)
    /// * `outBegIdx` — Set to the input index of the first output value.
    /// * `outNBElement` — Set to the number of output values written.
    /// * `outInteger` — +100 at a bullish abandoned baby bottom (3rd candle white), -100 at a
    ///   bearish abandoned baby top (3rd candle black), 0 otherwise; sign = color of the 3rd
    ///   candle.
    ///
    /// # Errors
    ///
    /// Returns [`RetCode::OutOfRangeStartIndex`] when `endIdx < startIdx`, and
    /// [`RetCode::BadParam`] when an optional parameter is outside its documented range.
    ///
    /// # 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.cdlabandonedbaby(
    ///     0, open.len() - 1, &open, &high, &low, &close, 0.3,
    ///     &mut out_beg, &mut out_nb, &mut out,
    /// );
    /// assert_eq!(ret, RetCode::Success);
    /// assert!(out_nb > 0);
    /// ```
    ///
    /// # See also
    ///
    /// [`Core::cdleveningdojistar`] · [`Core::cdlmorningdojistar`] · [`Core::cdleveningstar`] ·
    /// [`Core::cdlmorningstar`]
    ///
    /// Further reading:
    /// [ta-lib.org/functions/cdlabandonedbaby](https://ta-lib.org/functions/cdlabandonedbaby/)
    #[doc(alias = "AbandonedBaby")]
    pub fn cdlabandonedbaby(
        &self,
        startIdx: usize,
        endIdx: usize,
        inOpen: &[f64],
        inHigh: &[f64],
        inLow: &[f64],
        inClose: &[f64],
        mut optInPenetration: 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 BodyLongPeriodTotal: f64 = 0.0_f64;
        let mut BodyShortPeriodTotal: f64 = 0.0_f64;
        let mut i: usize = 0_usize;
        let mut outIdx: usize = 0_usize;
        let mut BodyDojiTrailingIdx: usize = 0_usize;
        let mut BodyLongTrailingIdx: usize = 0_usize;
        let mut BodyShortTrailingIdx: 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 BodyLong_rangeType: i32 = self.candle_settings.body_long.range_type;
        #[allow(non_snake_case)]
        let BodyLong_avgPeriod: i32 = self.candle_settings.body_long.avg_period;
        #[allow(non_snake_case)]
        let BodyLong_factor: f64 = self.candle_settings.body_long.factor;
        #[allow(non_snake_case)]
        let BodyShort_rangeType: i32 = self.candle_settings.body_short.range_type;
        #[allow(non_snake_case)]
        let BodyShort_avgPeriod: i32 = self.candle_settings.body_short.avg_period;
        #[allow(non_snake_case)]
        let BodyShort_factor: f64 = self.candle_settings.body_short.factor;
        // Identify the minimum number of price bar needed
        // to calculate at least one output.
        lookbackTotal = self.cdlabandonedbaby_lookback(optInPenetration);
        // 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.
        BodyLongPeriodTotal = 0.0;
        BodyDojiPeriodTotal = 0.0;
        BodyShortPeriodTotal = 0.0;
        BodyLongTrailingIdx = startIdx - 2 - (BodyLong_avgPeriod) as usize;
        BodyDojiTrailingIdx = startIdx - 1 - (BodyDoji_avgPeriod) as usize;
        BodyShortTrailingIdx = startIdx - (BodyShort_avgPeriod) as usize;
        i = BodyLongTrailingIdx;
        while i < startIdx - 2 {
            let mut _candlerange_0: f64;
            match BodyLong_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;
                }
            }
            BodyLongPeriodTotal += _candlerange_0;
            i += 1;
        }
        i = BodyDojiTrailingIdx;
        while i < startIdx - 1 {
            let mut _candlerange_1: f64;
            match BodyDoji_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;
                }
            }
            BodyDojiPeriodTotal += _candlerange_1;
            i += 1;
        }
        i = BodyShortTrailingIdx;
        while i < startIdx {
            let mut _candlerange_2: f64;
            match BodyShort_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;
                }
            }
            BodyShortPeriodTotal += _candlerange_2;
            i += 1;
        }
        i = startIdx;
        // Proceed with the calculation for the requested range.
        // Must have:
        // - first candle: long white (black) real body
        // - second candle: doji
        // - third candle: black (white) real body that moves well within the first candle's real body
        // - upside (downside) gap between the first candle and the doji (the shadows of the two candles don't touch)
        // - downside (upside) gap between the doji and the third candle (the shadows of the two candles don't touch)
        // The meaning of "doji" and "long" is specified with TA_SetCandleSettings
        // The meaning of "moves well within" is specified with optInPenetration and "moves" should mean the real body should
        // not be short ("short" is specified with TA_SetCandleSettings) - Greg Morris wants it to be long, someone else want
        // it to be relatively long
        // outInteger is positive (1 to 100) when it's an abandoned baby bottom or negative (-1 to -100) when it's
        // an abandoned baby top; the user should consider that an abandoned baby is significant when it appears in
        // an uptrend or downtrend, while this function does not consider the trend
        outIdx = 0;
        loop {
            if (inClose[i - 2] - inOpen[i - 2]).abs() > ((BodyLong_factor) * (if (BodyLong_avgPeriod) != 0 { (BodyLongPeriodTotal) / (BodyLong_avgPeriod as f64) } else { match BodyLong_rangeType { 0 => (inClose[i - 2] - inOpen[i - 2]).abs(), 1 => (inHigh[i - 2]) - (inLow[i - 2]), _ => (inHigh[i - 2]) - (inLow[i - 2]) - ((inClose[i - 2]) - (inOpen[i - 2])).abs() } }) / (if (BodyLong_rangeType) == 2 { 2.0 } else { 1.0 })) && // 1st: long
               (inClose[i - 1] - inOpen[i - 1]).abs() <= ((BodyDoji_factor) * (if (BodyDoji_avgPeriod) != 0 { (BodyDojiPeriodTotal) / (BodyDoji_avgPeriod as f64) } else { match BodyDoji_rangeType { 0 => (inClose[i - 1] - inOpen[i - 1]).abs(), 1 => (inHigh[i - 1]) - (inLow[i - 1]), _ => (inHigh[i - 1]) - (inLow[i - 1]) - ((inClose[i - 1]) - (inOpen[i - 1])).abs() } }) / (if (BodyDoji_rangeType) == 2 { 2.0 } else { 1.0 })) && // 2nd: doji
               (inClose[i] - inOpen[i]).abs() > ((BodyShort_factor) * (if (BodyShort_avgPeriod) != 0 { (BodyShortPeriodTotal) / (BodyShort_avgPeriod as f64) } else { match BodyShort_rangeType { 0 => (inClose[i] - inOpen[i]).abs(), 1 => (inHigh[i]) - (inLow[i]), _ => (inHigh[i]) - (inLow[i]) - ((inClose[i]) - (inOpen[i])).abs() } }) / (if (BodyShort_rangeType) == 2 { 2.0 } else { 1.0 })) && // 3rd: longer than short
               ((if inClose[i - 2] >= inOpen[i - 2] { 1 } else { 0 - 1 }) == 1 && ((if inClose[i] >= inOpen[i] { 1 } else { 0 - 1 })) as i32 == 0 - 1 && inClose[i] < inClose[i - 2] - (inClose[i - 2] - inOpen[i - 2]).abs() * optInPenetration && ((if inLow[i - 1] > inHigh[i - 2] { 1 } else { 0 }) != 0) && ((if inHigh[i] < inLow[i - 1] { 1 } else { 0 }) != 0) || ((if inClose[i - 2] >= inOpen[i - 2] { 1 } else { 0 - 1 })) as i32 == 0 - 1 && (if inClose[i] >= inOpen[i] { 1 } else { 0 - 1 }) == 1 && inClose[i] > ((inClose[i - 2] - inOpen[i - 2]).abs() as f64).mul_add(optInPenetration, inClose[i - 2]) && ((if inHigh[i - 1] < inLow[i - 2] { 1 } else { 0 }) != 0) && ((if inLow[i] > inHigh[i - 1] { 1 } else { 0 }) != 0)) // 1st white 3rd black 3rd closes well within 1st rb upside gap between 1st and 2nd downside gap between 2nd and 3rd 1st black 3rd white 3rd closes well within 1st rb downside gap between 1st and 2nd upside gap between 2nd and 3rd
            {
                outInteger[outIdx] = ((if inClose[i] >= inOpen[i] { 1 } else { 0 - 1 }) * 100) as i32;
                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 BodyLong_rangeType {
                0 => {
                    _candlerange_3 = (inClose[i - 2] - inOpen[i - 2]).abs();
                }
                1 => {
                    _candlerange_3 = inHigh[i - 2] - inLow[i - 2];
                }
                2 => {
                    _candlerange_3 = inHigh[i - 2] - inLow[i - 2] - (inClose[i - 2] - inOpen[i - 2]).abs();
                }
                _ => {
                    _candlerange_3 = 0.0;
                }
            }
            let mut _candlerange_4: f64;
            match BodyLong_rangeType {
                0 => {
                    _candlerange_4 = (inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx]).abs();
                }
                1 => {
                    _candlerange_4 = inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx];
                }
                2 => {
                    _candlerange_4 = inHigh[BodyLongTrailingIdx] - inLow[BodyLongTrailingIdx] - (inClose[BodyLongTrailingIdx] - inOpen[BodyLongTrailingIdx]).abs();
                }
                _ => {
                    _candlerange_4 = 0.0;
                }
            }
            BodyLongPeriodTotal += _candlerange_3 - _candlerange_4;
            let mut _candlerange_5: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_5 = (inClose[i - 1] - inOpen[i - 1]).abs();
                }
                1 => {
                    _candlerange_5 = inHigh[i - 1] - inLow[i - 1];
                }
                2 => {
                    _candlerange_5 = inHigh[i - 1] - inLow[i - 1] - (inClose[i - 1] - inOpen[i - 1]).abs();
                }
                _ => {
                    _candlerange_5 = 0.0;
                }
            }
            let mut _candlerange_6: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_6 = (inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx]).abs();
                }
                1 => {
                    _candlerange_6 = inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx];
                }
                2 => {
                    _candlerange_6 = inHigh[BodyDojiTrailingIdx] - inLow[BodyDojiTrailingIdx] - (inClose[BodyDojiTrailingIdx] - inOpen[BodyDojiTrailingIdx]).abs();
                }
                _ => {
                    _candlerange_6 = 0.0;
                }
            }
            BodyDojiPeriodTotal += _candlerange_5 - _candlerange_6;
            let mut _candlerange_7: f64;
            match BodyShort_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 BodyShort_rangeType {
                0 => {
                    _candlerange_8 = (inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx]).abs();
                }
                1 => {
                    _candlerange_8 = inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx];
                }
                2 => {
                    _candlerange_8 = inHigh[BodyShortTrailingIdx] - inLow[BodyShortTrailingIdx] - (inClose[BodyShortTrailingIdx] - inOpen[BodyShortTrailingIdx]).abs();
                }
                _ => {
                    _candlerange_8 = 0.0;
                }
            }
            BodyShortPeriodTotal += _candlerange_7 - _candlerange_8;
            i += 1;
            BodyLongTrailingIdx += 1;
            BodyDojiTrailingIdx += 1;
            BodyShortTrailingIdx += 1;
            if !(i <= endIdx) { break; }
        }
        // All done. Indicate the output limits and return.
        (*outNBElement) = outIdx;
        (*outBegIdx) = startIdx;
        return RetCode::Success;
    }
    /// Unchecked variant of [`Core::cdlabandonedbaby`], used for internal cross-indicator calls.
    ///
    /// Skips parameter validation and uses unchecked indexing internally. Every argument must
    /// satisfy the constraints documented on [`Core::cdlabandonedbaby`]; 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::cdlabandonedbaby`].
    #[inline]
    pub fn cdlabandonedbaby_unguarded(
        &self,
        mut startIdx: usize,
        endIdx: usize,
        inOpen: &[f64],
        inHigh: &[f64],
        inLow: &[f64],
        inClose: &[f64],
        mut optInPenetration: f64,
        outBegIdx: &mut usize,
        outNBElement: &mut usize,
        outInteger: &mut [i32],
    ) -> RetCode {
        let mut BodyDojiPeriodTotal: f64 = 0.0_f64;
        let mut BodyLongPeriodTotal: f64 = 0.0_f64;
        let mut BodyShortPeriodTotal: f64 = 0.0_f64;
        let mut i: usize = 0_usize;
        let mut outIdx: usize = 0_usize;
        let mut BodyDojiTrailingIdx: usize = 0_usize;
        let mut BodyLongTrailingIdx: usize = 0_usize;
        let mut BodyShortTrailingIdx: 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 BodyLong_rangeType: i32 = self.candle_settings.body_long.range_type;
        #[allow(non_snake_case)]
        let BodyLong_avgPeriod: i32 = self.candle_settings.body_long.avg_period;
        #[allow(non_snake_case)]
        let BodyLong_factor: f64 = self.candle_settings.body_long.factor;
        #[allow(non_snake_case)]
        let BodyShort_rangeType: i32 = self.candle_settings.body_short.range_type;
        #[allow(non_snake_case)]
        let BodyShort_avgPeriod: i32 = self.candle_settings.body_short.avg_period;
        #[allow(non_snake_case)]
        let BodyShort_factor: f64 = self.candle_settings.body_short.factor;
        unsafe {
        assert!(endIdx < inOpen.len());
        assert!(endIdx < inHigh.len());
        assert!(endIdx < inLow.len());
        assert!(endIdx < inClose.len());
        let _assertLb = self.cdlabandonedbaby_lookback(optInPenetration);
        let _assertStart = if startIdx > _assertLb { startIdx } else { _assertLb };
        assert!(_assertStart > endIdx || endIdx - _assertStart < outInteger.len());
        lookbackTotal = self.cdlabandonedbaby_lookback(optInPenetration);
        if startIdx < lookbackTotal {
            startIdx = lookbackTotal;
        }
        if startIdx > endIdx {
            (*outBegIdx) = 0;
            (*outNBElement) = 0;
            return RetCode::Success;
        }
        BodyLongPeriodTotal = 0.0;
        BodyDojiPeriodTotal = 0.0;
        BodyShortPeriodTotal = 0.0;
        BodyLongTrailingIdx = startIdx - 2 - (BodyLong_avgPeriod) as usize;
        BodyDojiTrailingIdx = startIdx - 1 - (BodyDoji_avgPeriod) as usize;
        BodyShortTrailingIdx = startIdx - (BodyShort_avgPeriod) as usize;
        i = BodyLongTrailingIdx;
        while i < startIdx - 2 {
            let mut _candlerange_0: f64;
            match BodyLong_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;
                }
            }
            BodyLongPeriodTotal += _candlerange_0;
            i += 1;
        }
        i = BodyDojiTrailingIdx;
        while i < startIdx - 1 {
            let mut _candlerange_1: f64;
            match BodyDoji_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;
                }
            }
            BodyDojiPeriodTotal += _candlerange_1;
            i += 1;
        }
        i = BodyShortTrailingIdx;
        while i < startIdx {
            let mut _candlerange_2: f64;
            match BodyShort_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;
                }
            }
            BodyShortPeriodTotal += _candlerange_2;
            i += 1;
        }
        i = startIdx;
        outIdx = 0;
        loop {
            if (*inClose.as_ptr().add(i - 2) - *inOpen.as_ptr().add(i - 2)).abs() > ((BodyLong_factor) * (if (BodyLong_avgPeriod) != 0 { (BodyLongPeriodTotal) / (BodyLong_avgPeriod as f64) } else { match BodyLong_rangeType { 0 => (*inClose.as_ptr().add(i - 2) - *inOpen.as_ptr().add(i - 2)).abs(), 1 => (*inHigh.as_ptr().add(i - 2)) - (*inLow.as_ptr().add(i - 2)), _ => (*inHigh.as_ptr().add(i - 2)) - (*inLow.as_ptr().add(i - 2)) - ((*inClose.as_ptr().add(i - 2)) - (*inOpen.as_ptr().add(i - 2))).abs() } }) / (if (BodyLong_rangeType) == 2 { 2.0 } else { 1.0 })) && (*inClose.as_ptr().add(i - 1) - *inOpen.as_ptr().add(i - 1)).abs() <= ((BodyDoji_factor) * (if (BodyDoji_avgPeriod) != 0 { (BodyDojiPeriodTotal) / (BodyDoji_avgPeriod as f64) } else { match BodyDoji_rangeType { 0 => (*inClose.as_ptr().add(i - 1) - *inOpen.as_ptr().add(i - 1)).abs(), 1 => (*inHigh.as_ptr().add(i - 1)) - (*inLow.as_ptr().add(i - 1)), _ => (*inHigh.as_ptr().add(i - 1)) - (*inLow.as_ptr().add(i - 1)) - ((*inClose.as_ptr().add(i - 1)) - (*inOpen.as_ptr().add(i - 1))).abs() } }) / (if (BodyDoji_rangeType) == 2 { 2.0 } else { 1.0 })) && (*inClose.as_ptr().add(i) - *inOpen.as_ptr().add(i)).abs() > ((BodyShort_factor) * (if (BodyShort_avgPeriod) != 0 { (BodyShortPeriodTotal) / (BodyShort_avgPeriod as f64) } else { match BodyShort_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 (BodyShort_rangeType) == 2 { 2.0 } else { 1.0 })) && ((if *inClose.as_ptr().add(i - 2) >= *inOpen.as_ptr().add(i - 2) { 1 } else { 0 - 1 }) == 1 && ((if *inClose.as_ptr().add(i) >= *inOpen.as_ptr().add(i) { 1 } else { 0 - 1 })) as i32 == 0 - 1 && *inClose.as_ptr().add(i) < *inClose.as_ptr().add(i - 2) - (*inClose.as_ptr().add(i - 2) - *inOpen.as_ptr().add(i - 2)).abs() * optInPenetration && ((if *inLow.as_ptr().add(i - 1) > *inHigh.as_ptr().add(i - 2) { 1 } else { 0 }) != 0) && ((if *inHigh.as_ptr().add(i) < *inLow.as_ptr().add(i - 1) { 1 } else { 0 }) != 0) || ((if *inClose.as_ptr().add(i - 2) >= *inOpen.as_ptr().add(i - 2) { 1 } else { 0 - 1 })) as i32 == 0 - 1 && (if *inClose.as_ptr().add(i) >= *inOpen.as_ptr().add(i) { 1 } else { 0 - 1 }) == 1 && *inClose.as_ptr().add(i) > ((*inClose.as_ptr().add(i - 2) - *inOpen.as_ptr().add(i - 2)).abs() as f64).mul_add(optInPenetration, *inClose.as_ptr().add(i - 2)) && ((if *inHigh.as_ptr().add(i - 1) < *inLow.as_ptr().add(i - 2) { 1 } else { 0 }) != 0) && ((if *inLow.as_ptr().add(i) > *inHigh.as_ptr().add(i - 1) { 1 } else { 0 }) != 0)) {
                *outInteger.as_mut_ptr().add(outIdx) = ((if *inClose.as_ptr().add(i) >= *inOpen.as_ptr().add(i) { 1 } else { 0 - 1 }) * 100) as i32;
                outIdx += 1;
            } else {
                *outInteger.as_mut_ptr().add(outIdx) = 0;
                outIdx += 1;
            }
            let mut _candlerange_3: f64;
            match BodyLong_rangeType {
                0 => {
                    _candlerange_3 = (*inClose.as_ptr().add(i - 2) - *inOpen.as_ptr().add(i - 2)).abs();
                }
                1 => {
                    _candlerange_3 = *inHigh.as_ptr().add(i - 2) - *inLow.as_ptr().add(i - 2);
                }
                2 => {
                    _candlerange_3 = *inHigh.as_ptr().add(i - 2) - *inLow.as_ptr().add(i - 2) - (*inClose.as_ptr().add(i - 2) - *inOpen.as_ptr().add(i - 2)).abs();
                }
                _ => {
                    _candlerange_3 = 0.0;
                }
            }
            let mut _candlerange_4: f64;
            match BodyLong_rangeType {
                0 => {
                    _candlerange_4 = (*inClose.as_ptr().add(BodyLongTrailingIdx) - *inOpen.as_ptr().add(BodyLongTrailingIdx)).abs();
                }
                1 => {
                    _candlerange_4 = *inHigh.as_ptr().add(BodyLongTrailingIdx) - *inLow.as_ptr().add(BodyLongTrailingIdx);
                }
                2 => {
                    _candlerange_4 = *inHigh.as_ptr().add(BodyLongTrailingIdx) - *inLow.as_ptr().add(BodyLongTrailingIdx) - (*inClose.as_ptr().add(BodyLongTrailingIdx) - *inOpen.as_ptr().add(BodyLongTrailingIdx)).abs();
                }
                _ => {
                    _candlerange_4 = 0.0;
                }
            }
            BodyLongPeriodTotal += _candlerange_3 - _candlerange_4;
            let mut _candlerange_5: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_5 = (*inClose.as_ptr().add(i - 1) - *inOpen.as_ptr().add(i - 1)).abs();
                }
                1 => {
                    _candlerange_5 = *inHigh.as_ptr().add(i - 1) - *inLow.as_ptr().add(i - 1);
                }
                2 => {
                    _candlerange_5 = *inHigh.as_ptr().add(i - 1) - *inLow.as_ptr().add(i - 1) - (*inClose.as_ptr().add(i - 1) - *inOpen.as_ptr().add(i - 1)).abs();
                }
                _ => {
                    _candlerange_5 = 0.0;
                }
            }
            let mut _candlerange_6: f64;
            match BodyDoji_rangeType {
                0 => {
                    _candlerange_6 = (*inClose.as_ptr().add(BodyDojiTrailingIdx) - *inOpen.as_ptr().add(BodyDojiTrailingIdx)).abs();
                }
                1 => {
                    _candlerange_6 = *inHigh.as_ptr().add(BodyDojiTrailingIdx) - *inLow.as_ptr().add(BodyDojiTrailingIdx);
                }
                2 => {
                    _candlerange_6 = *inHigh.as_ptr().add(BodyDojiTrailingIdx) - *inLow.as_ptr().add(BodyDojiTrailingIdx) - (*inClose.as_ptr().add(BodyDojiTrailingIdx) - *inOpen.as_ptr().add(BodyDojiTrailingIdx)).abs();
                }
                _ => {
                    _candlerange_6 = 0.0;
                }
            }
            BodyDojiPeriodTotal += _candlerange_5 - _candlerange_6;
            let mut _candlerange_7: f64;
            match BodyShort_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 BodyShort_rangeType {
                0 => {
                    _candlerange_8 = (*inClose.as_ptr().add(BodyShortTrailingIdx) - *inOpen.as_ptr().add(BodyShortTrailingIdx)).abs();
                }
                1 => {
                    _candlerange_8 = *inHigh.as_ptr().add(BodyShortTrailingIdx) - *inLow.as_ptr().add(BodyShortTrailingIdx);
                }
                2 => {
                    _candlerange_8 = *inHigh.as_ptr().add(BodyShortTrailingIdx) - *inLow.as_ptr().add(BodyShortTrailingIdx) - (*inClose.as_ptr().add(BodyShortTrailingIdx) - *inOpen.as_ptr().add(BodyShortTrailingIdx)).abs();
                }
                _ => {
                    _candlerange_8 = 0.0;
                }
            }
            BodyShortPeriodTotal += _candlerange_7 - _candlerange_8;
            i += 1;
            BodyLongTrailingIdx += 1;
            BodyDojiTrailingIdx += 1;
            BodyShortTrailingIdx += 1;
            if !(i <= endIdx) { break; }
        }
        (*outNBElement) = outIdx;
        (*outBegIdx) = startIdx;
        return RetCode::Success;
        } // unsafe
    }
}
/***************/
/* End of File */
/***************/
