/* 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
 *  -------------------------------------------------------------------
 *  MF       Mario Fortier
 *  AM       Adrian Michel
 *  MIF      Mirek Fontan (mira@fontan.cz)
 *
 * Change history:
 *
 *  MMDDYY BY   Description
 *  -------------------------------------------------------------------
 *  010802 MF   Template creation.
 *  052603 MF   Adapt code to compile with .NET Managed C++
 *  082303 MF   Fix #792298. Remove rounding. Bug reported by AM.
 *  062704 MF   Fix #965557. Div by zero bug reported by MIF.
 */

// 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::dx`]: the number of leading input values consumed before the
    /// first output value can be produced.
    ///
    /// # Arguments
    ///
    /// * `optInTimePeriod` — Smoothing period for the DM and TR sums (default 14, range
    ///   2..=100000)
    ///
    /// Returns `usize::MAX` when a parameter is out of range. Integer parameters accept `i32::MIN`
    /// to select their default value.
    #[inline]
    pub fn dx_lookback(&self, mut optInTimePeriod: i32) -> usize {
        if ((optInTimePeriod) as i32) == (i32::MIN) {
            optInTimePeriod = 14;
        } else if (((optInTimePeriod) as i32) < 2) || (((optInTimePeriod) as i32) > 100000) {
            return usize::MAX;
        }
        if optInTimePeriod > 1 {
            return (optInTimePeriod + self.unstable_period[FuncUnstId::Dx as usize]) as usize;
        } else {
            return (2) as usize;
        }
    }
    /// Wilder's Directional Movement Index: the normalized spread between +DI and -DI. Measures the
    /// strength of directional (trending) movement, irrespective of direction. Higher DX = stronger
    /// trend (either direction); low DX = ranging market.
    ///
    /// # Formula
    ///
    /// ```text
    /// Seed +DM14, -DM14, TR14 as sums of the first (period-1) one-period values, then Wilder-smooth each: X = X - X/period + today. +DI = 100*(+DM14/TR14), -DI = 100*(-DM14/TR14). DX = 100 * |(-DI) - (+DI)| / ((-DI) + (+DI)).
    /// ```
    ///
    /// # Notes
    ///
    /// * Wilder's original integer rounding is not applied (it can be unreliable when values are
    ///   near 1).
    /// * When +DI and -DI sum to zero the value is undefined; the previous bar's DX is carried
    ///   forward instead (the first such bar outputs zero).
    ///
    /// # Arguments
    ///
    /// * `startIdx` — Start index of the requested calculation range.
    /// * `endIdx` — End index of the requested calculation range (inclusive).
    /// * `inHigh` — High prices per bar.
    /// * `inLow` — Low prices per bar.
    /// * `inClose` — Close prices per bar.
    /// * `optInTimePeriod` — Smoothing period for the DM and TR sums (default 14, range
    ///   2..=100000)
    /// * `outBegIdx` — Set to the input index of the first output value.
    /// * `outNBElement` — Set to the number of output values written.
    /// * `outReal` — DX directional movement index value.
    ///
    /// Integer parameters accept `i32::MIN` to select their default value.
    ///
    /// # 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 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![0.0; 252];
    ///
    /// let ret = core.dx(
    ///     0, high.len() - 1, &high, &low, &close, 14,
    ///     &mut out_beg, &mut out_nb, &mut out,
    /// );
    /// assert_eq!(ret, RetCode::Success);
    /// assert!(out_nb > 0);
    /// ```
    ///
    /// # See also
    ///
    /// [`Core::adx`] · [`Core::adxr`] · [`Core::plus_di`] · [`Core::minus_di`] ·
    /// [`Core::plus_dm`] · [`Core::minus_dm`] · [`Core::trange`]
    ///
    /// # References
    ///
    /// * J. Welles Wilder, *New Concepts in Technical Trading Systems*, Trend Research (ISBN
    ///   0894590278)
    ///
    /// Further reading: [ta-lib.org/functions/dx](https://ta-lib.org/functions/dx/)
    #[doc(alias = "DirectionalMovementIndex")]
    #[doc(alias = "DMI")]
    pub fn dx(
        &self,
        startIdx: usize,
        endIdx: usize,
        inHigh: &[f64],
        inLow: &[f64],
        inClose: &[f64],
        mut optInTimePeriod: i32,
        outBegIdx: &mut usize,
        outNBElement: &mut usize,
        outReal: &mut [f64],
    ) -> RetCode {
        if endIdx < startIdx {
            return RetCode::OutOfRangeStartIndex;
        }
        if ((optInTimePeriod) as i32) == (i32::MIN) {
            optInTimePeriod = 14;
        } else if (((optInTimePeriod) as i32) < 2) || (((optInTimePeriod) as i32) > 100000) {
            return RetCode::BadParam;
        }
        let mut startIdx = startIdx;
        let mut today: usize = 0_usize;
        let mut lookbackTotal: usize = 0_usize;
        let mut outIdx: usize = 0_usize;
        let mut prevHigh: f64 = 0.0_f64;
        let mut prevLow: f64 = 0.0_f64;
        let mut prevClose: f64 = 0.0_f64;
        let mut prevMinusDM: f64 = 0.0_f64;
        let mut prevPlusDM: f64 = 0.0_f64;
        let mut prevTR: f64 = 0.0_f64;
        let mut tempReal: f64 = 0.0_f64;
        let tempReal2: f64 = 0.0_f64;
        let mut diffP: f64 = 0.0_f64;
        let mut diffM: f64 = 0.0_f64;
        let mut minusDI: f64 = 0.0_f64;
        let mut plusDI: f64 = 0.0_f64;
        let mut i: usize = 0_usize;
        //
        // The DM1 (one period) is base on the largest part of
        // today's range that is outside of yesterdays range.
        //
        // The following 7 cases explain how the +DM and -DM are
        // calculated on one period:
        //
        // Case 1:                       Case 2:
        //    C|                        A|
        //     |                         | C|
        //     | +DM1 = (C-A)           B|  | +DM1 = 0
        //     | -DM1 = 0                   | -DM1 = (B-D)
        // A|  |                           D|
        //  | D|
        // B|
        //
        // Case 3:                       Case 4:
        //    C|                           C|
        //     |                        A|  |
        //     | +DM1 = (C-A)            |  | +DM1 = 0
        //     | -DM1 = 0               B|  | -DM1 = (B-D)
        // A|  |                            |
        //  |  |                           D|
        // B|  |
        //    D|
        //
        // Case 5:                      Case 6:
        // A|                           A| C|
        //  | C| +DM1 = 0                |  |  +DM1 = 0
        //  |  | -DM1 = 0                |  |  -DM1 = 0
        //  | D|                         |  |
        // B|                           B| D|
        //
        //
        // Case 7:
        //
        //    C|
        // A|  |
        //  |  | +DM=0
        // B|  | -DM=0
        //    D|
        //
        // In case 3 and 4, the rule is that the smallest delta between
        // (C-A) and (B-D) determine which of +DM or -DM is zero.
        //
        // In case 7, (C-A) and (B-D) are equal, so both +DM and -DM are
        // zero.
        //
        // The rules remain the same when A=B and C=D (when the highs
        // equal the lows).
        //
        // When calculating the DM over a period > 1, the one-period DM
        // for the desired period are initialy sum. In other word,
        // for a -DM14, sum the -DM1 for the first 14 days (that's
        // 13 values because there is no DM for the first day!)
        // Subsequent DM are calculated using the Wilder's
        // smoothing approach:
        //
        //                                    Previous -DM14
        //  Today's -DM14 = Previous -DM14 -  -------------- + Today's -DM1
        //                                         14
        //
        // Calculation of a -DI14 is as follow:
        //
        //               -DM14
        //     -DI14 =  --------
        //                TR14
        //
        // Calculation of the TR14 is:
        //
        //                                   Previous TR14
        //    Today's TR14 = Previous TR14 - -------------- + Today's TR1
        //                                         14
        //
        //    The first TR14 is the summation of the first 14 TR1. See the
        //    TA_TRANGE function on how to calculate the true range.
        //
        // Calculation of the DX14 is:
        //
        //    diffDI = ABS( (-DI14) - (+DI14) )
        //    sumDI  = (-DI14) + (+DI14)
        //
        //    DX14 = 100 * (diffDI / sumDI)
        //
        // Reference:
        //    New Concepts In Technical Trading Systems, J. Welles Wilder Jr
        // Original implementation from Wilder's book was doing some integer
        // rounding in its calculations.
        //
        // This was understandable in the context that at the time the book
        // was written, most user were doing the calculation by hand.
        //
        // For a computer, rounding is unnecessary (and even problematic when inputs
        // are close to 1).
        //
        // TA-Lib does not do the rounding. Still, if you want to reproduce Wilder's examples,
        // you can comment out the following #undef/#define and rebuild the library.
        if optInTimePeriod > 1 {
            lookbackTotal = (optInTimePeriod + self.unstable_period[FuncUnstId::Dx as usize]) as usize;
        } else {
            lookbackTotal = 2;
        }
        // Adjust startIdx to account for the lookback period.
        if startIdx < lookbackTotal {
            startIdx = lookbackTotal;
        }
        // Make sure there is still something to evaluate.
        if startIdx > endIdx {
            (*outBegIdx) = 0;
            (*outNBElement) = 0;
            return RetCode::Success;
        }
        // Indicate where the next output should be put
        // in the outReal.
        outIdx = 0;
        // Process the initial DM and TR
        today = startIdx;
        (*outBegIdx) = today;
        prevMinusDM = 0.0;
        prevPlusDM = 0.0;
        prevTR = 0.0;
        today = startIdx - lookbackTotal;
        prevHigh = inHigh[today];
        prevLow = inLow[today];
        prevClose = inClose[today];
        i = (optInTimePeriod - 1) as usize;
        while { let _v = i; i = i.wrapping_sub(1); _v } > 0 {
            today += 1;
            tempReal = inHigh[today];
            diffP = tempReal - prevHigh;
            // Plus Delta
            prevHigh = tempReal;
            tempReal = inLow[today];
            diffM = prevLow - tempReal;
            // Minus Delta
            prevLow = tempReal;
            if diffM > 0_f64 && diffP < diffM {
                // Case 2 and 4: +DM=0,-DM=diffM
                prevMinusDM += diffM;
            } else if diffP > 0_f64 && diffP > diffM {
                // Case 1 and 3: +DM=diffP,-DM=0
                prevPlusDM += diffP;
            }
            let mut _true_range_0: f64;
            let mut range_0: f64 = prevHigh - prevLow;
            let mut tmp_0: f64 = (prevHigh - prevClose).abs();
            if tmp_0 > range_0 {
                range_0 = tmp_0;
            }
            tmp_0 = (prevLow - prevClose).abs();
            if tmp_0 > range_0 {
                range_0 = tmp_0;
            }
            _true_range_0 = range_0;
            tempReal = _true_range_0;
            prevTR += tempReal;
            prevClose = inClose[today];
        }
        // Skip the unstable period. Note that this loop must be executed
        // at least ONCE to calculate the first DI.
        i = (self.unstable_period[FuncUnstId::Dx as usize] + 1) as usize;
        while { let _v = i; i = i.wrapping_sub(1); _v } != 0 {
            // Calculate the prevMinusDM and prevPlusDM
            today += 1;
            tempReal = inHigh[today];
            diffP = tempReal - prevHigh;
            // Plus Delta
            prevHigh = tempReal;
            tempReal = inLow[today];
            diffM = prevLow - tempReal;
            // Minus Delta
            prevLow = tempReal;
            prevMinusDM -= prevMinusDM / ((optInTimePeriod) as f64);
            prevPlusDM -= prevPlusDM / ((optInTimePeriod) as f64);
            if diffM > 0_f64 && diffP < diffM {
                // Case 2 and 4: +DM=0,-DM=diffM
                prevMinusDM += diffM;
            } else if diffP > 0_f64 && diffP > diffM {
                // Case 1 and 3: +DM=diffP,-DM=0
                prevPlusDM += diffP;
            }
            // Calculate the prevTR
            let mut _true_range_1: f64;
            let mut range_1: f64 = prevHigh - prevLow;
            let mut tmp_1: f64 = (prevHigh - prevClose).abs();
            if tmp_1 > range_1 {
                range_1 = tmp_1;
            }
            tmp_1 = (prevLow - prevClose).abs();
            if tmp_1 > range_1 {
                range_1 = tmp_1;
            }
            _true_range_1 = range_1;
            tempReal = _true_range_1;
            prevTR = prevTR - prevTR / ((optInTimePeriod) as f64) + tempReal;
            prevClose = inClose[today];
        }
        // Write the first DX output
        if !((prevTR).abs() < 1e-14) {
            minusDI = (100.0 * (prevMinusDM / prevTR));
            plusDI = (100.0 * (prevPlusDM / prevTR));
            tempReal = minusDI + plusDI;
            if !((tempReal).abs() < 1e-14) {
                outReal[0] = (100.0 * ((minusDI - plusDI).abs() / tempReal));
            } else {
                outReal[0] = 0.0;
            }
        } else {
            outReal[0] = 0.0;
        }
        outIdx = 1;
        while today < endIdx {
            // Calculate the prevMinusDM and prevPlusDM
            today += 1;
            tempReal = inHigh[today];
            diffP = tempReal - prevHigh;
            // Plus Delta
            prevHigh = tempReal;
            tempReal = inLow[today];
            diffM = prevLow - tempReal;
            // Minus Delta
            prevLow = tempReal;
            prevMinusDM -= prevMinusDM / ((optInTimePeriod) as f64);
            prevPlusDM -= prevPlusDM / ((optInTimePeriod) as f64);
            if diffM > 0_f64 && diffP < diffM {
                // Case 2 and 4: +DM=0,-DM=diffM
                prevMinusDM += diffM;
            } else if diffP > 0_f64 && diffP > diffM {
                // Case 1 and 3: +DM=diffP,-DM=0
                prevPlusDM += diffP;
            }
            // Calculate the prevTR
            let mut _true_range_2: f64;
            let mut range_2: f64 = prevHigh - prevLow;
            let mut tmp_2: f64 = (prevHigh - prevClose).abs();
            if tmp_2 > range_2 {
                range_2 = tmp_2;
            }
            tmp_2 = (prevLow - prevClose).abs();
            if tmp_2 > range_2 {
                range_2 = tmp_2;
            }
            _true_range_2 = range_2;
            tempReal = _true_range_2;
            prevTR = prevTR - prevTR / ((optInTimePeriod) as f64) + tempReal;
            prevClose = inClose[today];
            // Calculate the DX. The value is rounded (see Wilder book).
            if !((prevTR).abs() < 1e-14) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                // This loop is just to accumulate the initial DX
                tempReal = minusDI + plusDI;
                if !((tempReal).abs() < 1e-14) {
                    outReal[outIdx] = (100.0 * ((minusDI - plusDI).abs() / tempReal));
                } else {
                    outReal[outIdx] = ((outReal[outIdx - 1]) as f64);
                }
            } else {
                outReal[outIdx] = ((outReal[outIdx - 1]) as f64);
            }
            outIdx += 1;
        }
        (*outNBElement) = outIdx;
        return RetCode::Success;
    }
    /// Unchecked variant of [`Core::dx`], used for internal cross-indicator calls.
    ///
    /// Skips parameter validation and uses unchecked indexing internally. Every argument must
    /// satisfy the constraints documented on [`Core::dx`]; 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::dx`].
    #[inline]
    pub fn dx_unguarded(
        &self,
        mut startIdx: usize,
        endIdx: usize,
        inHigh: &[f64],
        inLow: &[f64],
        inClose: &[f64],
        mut optInTimePeriod: i32,
        outBegIdx: &mut usize,
        outNBElement: &mut usize,
        outReal: &mut [f64],
    ) -> RetCode {
        let mut today: usize = 0_usize;
        let mut lookbackTotal: usize = 0_usize;
        let mut outIdx: usize = 0_usize;
        let mut prevHigh: f64 = 0.0_f64;
        let mut prevLow: f64 = 0.0_f64;
        let mut prevClose: f64 = 0.0_f64;
        let mut prevMinusDM: f64 = 0.0_f64;
        let mut prevPlusDM: f64 = 0.0_f64;
        let mut prevTR: f64 = 0.0_f64;
        let mut tempReal: f64 = 0.0_f64;
        let tempReal2: f64 = 0.0_f64;
        let mut diffP: f64 = 0.0_f64;
        let mut diffM: f64 = 0.0_f64;
        let mut minusDI: f64 = 0.0_f64;
        let mut plusDI: f64 = 0.0_f64;
        let mut i: usize = 0_usize;
        unsafe {
        assert!(endIdx < inHigh.len());
        assert!(endIdx < inLow.len());
        assert!(endIdx < inClose.len());
        let _assertLb = self.dx_lookback(optInTimePeriod);
        let _assertStart = if startIdx > _assertLb { startIdx } else { _assertLb };
        assert!(_assertStart > endIdx || endIdx - _assertStart < outReal.len());
        if optInTimePeriod > 1 {
            lookbackTotal = (optInTimePeriod + self.unstable_period[FuncUnstId::Dx as usize]) as usize;
        } else {
            lookbackTotal = 2;
        }
        if startIdx < lookbackTotal {
            startIdx = lookbackTotal;
        }
        if startIdx > endIdx {
            (*outBegIdx) = 0;
            (*outNBElement) = 0;
            return RetCode::Success;
        }
        outIdx = 0;
        today = startIdx;
        (*outBegIdx) = today;
        prevMinusDM = 0.0;
        prevPlusDM = 0.0;
        prevTR = 0.0;
        today = startIdx - lookbackTotal;
        prevHigh = *inHigh.as_ptr().add(today);
        prevLow = *inLow.as_ptr().add(today);
        prevClose = *inClose.as_ptr().add(today);
        i = (optInTimePeriod - 1) as usize;
        while { let _v = i; i = i.wrapping_sub(1); _v } > 0 {
            today += 1;
            tempReal = *inHigh.as_ptr().add(today);
            diffP = tempReal - prevHigh;
            prevHigh = tempReal;
            tempReal = *inLow.as_ptr().add(today);
            diffM = prevLow - tempReal;
            prevLow = tempReal;
            if diffM > 0_f64 && diffP < diffM {
                prevMinusDM += diffM;
            } else if diffP > 0_f64 && diffP > diffM {
                prevPlusDM += diffP;
            }
            let mut _true_range_0: f64;
            let mut range_0: f64 = prevHigh - prevLow;
            let mut tmp_0: f64 = (prevHigh - prevClose).abs();
            if tmp_0 > range_0 {
                range_0 = tmp_0;
            }
            tmp_0 = (prevLow - prevClose).abs();
            if tmp_0 > range_0 {
                range_0 = tmp_0;
            }
            _true_range_0 = range_0;
            tempReal = _true_range_0;
            prevTR += tempReal;
            prevClose = *inClose.as_ptr().add(today);
        }
        i = (self.unstable_period[FuncUnstId::Dx as usize] + 1) as usize;
        while { let _v = i; i = i.wrapping_sub(1); _v } != 0 {
            today += 1;
            tempReal = *inHigh.as_ptr().add(today);
            diffP = tempReal - prevHigh;
            prevHigh = tempReal;
            tempReal = *inLow.as_ptr().add(today);
            diffM = prevLow - tempReal;
            prevLow = tempReal;
            prevMinusDM -= prevMinusDM / ((optInTimePeriod) as f64);
            prevPlusDM -= prevPlusDM / ((optInTimePeriod) as f64);
            if diffM > 0_f64 && diffP < diffM {
                prevMinusDM += diffM;
            } else if diffP > 0_f64 && diffP > diffM {
                prevPlusDM += diffP;
            }
            let mut _true_range_1: f64;
            let mut range_1: f64 = prevHigh - prevLow;
            let mut tmp_1: f64 = (prevHigh - prevClose).abs();
            if tmp_1 > range_1 {
                range_1 = tmp_1;
            }
            tmp_1 = (prevLow - prevClose).abs();
            if tmp_1 > range_1 {
                range_1 = tmp_1;
            }
            _true_range_1 = range_1;
            tempReal = _true_range_1;
            prevTR = prevTR - prevTR / ((optInTimePeriod) as f64) + tempReal;
            prevClose = *inClose.as_ptr().add(today);
        }
        if !((prevTR).abs() < 1e-14) {
            minusDI = (100.0 * (prevMinusDM / prevTR));
            plusDI = (100.0 * (prevPlusDM / prevTR));
            tempReal = minusDI + plusDI;
            if !((tempReal).abs() < 1e-14) {
                *outReal.as_mut_ptr().add(0) = (100.0 * ((minusDI - plusDI).abs() / tempReal));
            } else {
                *outReal.as_mut_ptr().add(0) = 0.0;
            }
        } else {
            *outReal.as_mut_ptr().add(0) = 0.0;
        }
        outIdx = 1;
        while today < endIdx {
            today += 1;
            tempReal = *inHigh.as_ptr().add(today);
            diffP = tempReal - prevHigh;
            prevHigh = tempReal;
            tempReal = *inLow.as_ptr().add(today);
            diffM = prevLow - tempReal;
            prevLow = tempReal;
            prevMinusDM -= prevMinusDM / ((optInTimePeriod) as f64);
            prevPlusDM -= prevPlusDM / ((optInTimePeriod) as f64);
            if diffM > 0_f64 && diffP < diffM {
                prevMinusDM += diffM;
            } else if diffP > 0_f64 && diffP > diffM {
                prevPlusDM += diffP;
            }
            let mut _true_range_2: f64;
            let mut range_2: f64 = prevHigh - prevLow;
            let mut tmp_2: f64 = (prevHigh - prevClose).abs();
            if tmp_2 > range_2 {
                range_2 = tmp_2;
            }
            tmp_2 = (prevLow - prevClose).abs();
            if tmp_2 > range_2 {
                range_2 = tmp_2;
            }
            _true_range_2 = range_2;
            tempReal = _true_range_2;
            prevTR = prevTR - prevTR / ((optInTimePeriod) as f64) + tempReal;
            prevClose = *inClose.as_ptr().add(today);
            if !((prevTR).abs() < 1e-14) {
                minusDI = (100.0 * (prevMinusDM / prevTR));
                plusDI = (100.0 * (prevPlusDM / prevTR));
                tempReal = minusDI + plusDI;
                if !((tempReal).abs() < 1e-14) {
                    *outReal.as_mut_ptr().add(outIdx) = (100.0 * ((minusDI - plusDI).abs() / tempReal));
                } else {
                    *outReal.as_mut_ptr().add(outIdx) = ((*outReal.as_ptr().add(outIdx - 1)) as f64);
                }
            } else {
                *outReal.as_mut_ptr().add(outIdx) = ((*outReal.as_ptr().add(outIdx - 1)) as f64);
            }
            outIdx += 1;
        }
        (*outNBElement) = outIdx;
        return RetCode::Success;
        } // unsafe
    }
}
/***************/
/* End of File */
/***************/
