fast_utils
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © f4r33x

//@version=5

// @description This library contains my favourite functions. Will be updated frequently
library("fast_utils")

// @function : Count int digits in number
// @returns  : number of int digits in number
export count_int_digits(float a) =>
    b = (int(a))
    counter = int(math.log10(b))+1 

// @function : Count float digits in number
// @returns  : number of float digits in number
export count_float_digits(float a) =>
    b = (a%1)*math.pow(10, 16)
    counter = int(math.log10(b))+1

// @function : convert values in array or matrix into string values
// @returns  : array or matrix of string values
export stringify(float[] arr) =>
	string res = na
	for val in arr
		res += str.tostring(val) + ';'
	arr_res = str.split(res, ';')
    array.pop(arr_res)
    arr_res

export stringify(int[] arr) =>
	string res = na
	for val in arr
		res += str.tostring(val) + ';'
	arr_res = str.split(res, ';')
    array.pop(arr_res)
    arr_res
export stringify(bool[] arr) =>
	string res = na
	for val in arr
		res += str.tostring(val) + ';'
	arr_res = str.split(res, ';')
    array.pop(arr_res)
    arr_res
export stringify(matrix<float> mat) =>
	result =matrix.new<string>() 
	string res = na
	for i= 0 to matrix.rows(mat)-1 
		arr = matrix.row(mat, i)
		for val in arr
			res += str.tostring(val) + ';'
		matrix.add_row(result, i, str.split(res, ';'))
	result
export stringify(matrix<bool> mat) =>
	result =matrix.new<string>() 
	string res = na
	for i= 0 to matrix.rows(mat)-1 
		arr = matrix.row(mat, i)
		for val in arr
			res += str.tostring(val) + ';'
		arr_res = str.split(res, ';')
        array.pop(arr_res)
        matrix.add_row(result, i, arr_res)
	result
export stringify(matrix<int> mat) =>
	result =matrix.new<string>() 
	string res = na
	for i= 0 to matrix.rows(mat)-1 
		arr = matrix.row(mat, i)
		for val in arr
			res += str.tostring(val) + ';'
		arr_res = str.split(res, ';')
        array.pop(arr_res)
        matrix.add_row(result, i, arr_res)
	result
// @function : compare values in arrays 
// @returns  : bool value
export arrcompare(float[] arr_a, float[] arr_b) =>
    bool res = true
    if array.size(arr_a)>0
        for [index, value] in arr_a
            if value != array.get(arr_b, index) 
                res := false
                break
    else 
		res := false   
    res 
export arrcompare(int[] arr_a, int[] arr_b) =>
    bool res = true
    if array.size(arr_a)>0
        for [index, value] in arr_a
            if value != array.get(arr_b, index) 
                res := false
                break
    else 
		res := false   
    res 
export arrcompare(bool[] arr_a, bool[] arr_b) =>
    bool res = true
    if array.size(arr_a)>0
        for [index, value] in arr_a
            if value != array.get(arr_b, index) 
                res := false
                break
    else 
		res := false   
    res 
export arrcompare(string[] arr_a, string[] arr_b) =>
    bool res = true
    if array.size(arr_a)>0
        for [index, value] in arr_a
            if value != array.get(arr_b, index) 
                res := false
                break
    else 
		res := false   
    res

export arrcompare(line[] arr_a, line[] arr_b) =>
    bool res = true
    if array.size(arr_a)>0
        for [index, value] in arr_a
            if value != array.get(arr_b, index) 
                res := false
                break
    else 
		res := false   
    res 

export arrcompare(label[] arr_a, label[] arr_b) =>
    bool res = true
    if array.size(arr_a)>0
        for [index, value] in arr_a
            if value != array.get(arr_b, index) 
                res := false
                break
    else 
		res := false   
    res
          
// @function : remove duplicate values in array 
// @returns  : array without duplicates
export arrdedup(int[] arr) => 
    int _size = array.size(arr)
    if _size > 0
        _dict = array.from(array.get(arr, 0)) 
        for _i = 1 to _size-1
            _value = array.get(arr, _i)
            if array.indexof(_dict, _value) < 0
                array.push(_dict, _value)
        _dict
    else
        //runtime.error('array must have atleast one element.')
        array.copy(arr)
export arrdedup(float[] arr) => 
    int _size = array.size(arr)
    if _size > 0
        _dict = array.from(array.get(arr, 0)) 
        for _i = 1 to _size-1
            _value = array.get(arr, _i)
            if array.indexof(_dict, _value) < 0
                array.push(_dict, _value)
        _dict
    else
        //runtime.error('array must have atleast one element.')
        array.copy(arr)
export arrdedup(bool[] arr) => 
    int _size = array.size(arr)
    if _size > 0
        _dict = array.from(array.get(arr, 0)) 
        for _i = 1 to _size-1
            _value = array.get(arr, _i)
            if array.indexof(_dict, _value) < 0
                array.push(_dict, _value)
        _dict
    else
        //runtime.error('array must have atleast one element.')
        array.copy(arr)
export arrdedup(string[] arr) => 
    int _size = array.size(arr)
    if _size > 0
        _dict = array.from(array.get(arr, 0)) 
        for _i = 1 to _size-1
            _value = array.get(arr, _i)
            if array.indexof(_dict, _value) < 0
                array.push(_dict, _value)
        _dict
    else
        //runtime.error('array must have atleast one element.')
        array.copy(arr)
export arrdedup(box[] arr) => 
    int _size = array.size(arr)
    if _size > 0
        _dict = array.from(array.get(arr, 0)) 
        for _i = 1 to _size-1
            _value = array.get(arr, _i)
            if array.indexof(_dict, _value) < 0
                array.push(_dict, _value)
        _dict
    else
        //runtime.error('array must have atleast one element.')
        array.copy(arr)
export arrdedup(line[] arr) => 
    int _size = array.size(arr)
    if _size > 0
        _dict = array.from(array.get(arr, 0)) 
        for _i = 1 to _size-1
            _value = array.get(arr, _i)
            if array.indexof(_dict, _value) < 0
                array.push(_dict, _value)
        _dict
    else
        //runtime.error('array must have atleast one element.')
        array.copy(arr)
export arrdedup(linefill[] arr) => 
    int _size = array.size(arr)
    if _size > 0
        _dict = array.from(array.get(arr, 0)) 
        for _i = 1 to _size-1
            _value = array.get(arr, _i)
            if array.indexof(_dict, _value) < 0
                array.push(_dict, _value)
        _dict
    else
        //runtime.error('array must have atleast one element.')
        array.copy(arr)
export arrdedup(label[] arr) => 
    int _size = array.size(arr)
    if _size > 0
        _dict = array.from(array.get(arr, 0)) 
        for _i = 1 to _size-1
            _value = array.get(arr, _i)
            if array.indexof(_dict, _value) < 0
                array.push(_dict, _value)
        _dict
    else
        //runtime.error('array must have atleast one element.')
        array.copy(arr)
export arrdedup(table[] arr) => 
    int _size = array.size(arr)
    if _size > 0
        _dict = array.from(array.get(arr, 0)) 
        for _i = 1 to _size-1
            _value = array.get(arr, _i)
            if array.indexof(_dict, _value) < 0
                array.push(_dict, _value)
        _dict
    else
        //runtime.error('array must have atleast one element.')
        array.copy(arr)
export resource(string string_a, int h = 0) =>
    float offset_src  = switch string_a
        'close' => close[h]
        'open' => open[h]
        'high' => high[h]
        'low' => low[h]
        'hl2' => hl2[h]
        'hlc3' => hlc3[h]
        'hlcc4' => hlcc4[h]
        'ohlc4' => ohlc4[h]
        'tr' => ta.tr(true)[h]

// @function : converts current resolution in minutes
// @returns  : return float number of minuted
export ResInMins() => 
    _resInMinutes = timeframe.multiplier * (
      timeframe.isseconds ? 1. / 60. :
      timeframe.isminutes ? 1.       :
      timeframe.isdaily   ? 1440.    :
      timeframe.isweekly  ? 10080.   :
      timeframe.ismonthly ? 43800.   : na)

// @function : Convert current float TF in minutes to target string TF in "timeframe.period" format.
// @param res : current resolution in minutes
// @param mult : Multiple of current TF to be calculated.
// @returns  : timeframe format string
export MultOfRes(float resolution, float mult) => 

    res =  resolution * math.max(mult, 1)

    res   <= 0.083 ? "5S"  :
      res <= 0.251 ? "15S" :
      res <= 0.501 ? "30S" :
      res <= 1440  ? str.tostring(math.round(res)) :
      res <= 43800 ? str.tostring(math.round(math.min(res / 1440, 365))) + "D" :
      str.tostring(math.round(math.min(res / 43800, 12))) + "M"