//+------------------------------------------------------------------+ //| np.mqh | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" #include #include #include #define _NP_ #define BEGIN 0 #define STEP 1 #define END LONG_MAX #define BEGIN_REVERSE -1 #define STEP_REVERSE -1 #define END_REVERSE LONG_MIN //+------------------------------------------------------------------+ //| library constants | //+------------------------------------------------------------------+ namespace np { namespace internal { //+------------------------------------------------------------------+ //|find index of a sorted array such that arr[i] <= key < arr[i + 1] | //+------------------------------------------------------------------+ int binary_search(const double key, const double &arr[]) { int imin = 0; int imax = ArraySize(arr)-1; int mid = -1; /* Handle keys outside of the arr range first */ if(key > arr[arr.Size()-1]) { return ArraySize(arr); // Key exceeds maximum value; return out-of-bounds upper limit } else if(key < arr[0]) { return -1; // Key is lower than minimum value; return out-of-bounds lower limit } // Standard binary search convergence loop while(imin<=imax) { mid = (imin+imax)/2; // Safe midpoint extraction (using integer truncation) // Check if key sits perfectly between the current midpoint index and the next index if(midkey) return mid; else { if(key void col(const T &Matrix[], T &Col[], int column, int cols) { int rows = ArraySize(Matrix)/cols; // Infer implicit matrix row count via total size and column count ArrayResize(Col,rows); int start = 0; for(int i=0; i T prodArray(T &in_array[], uint from=0) { T result = T(1); // Set multiplicative identity base for(uint i = from; i=size)?0:start; return s; } //+------------------------------------------------------------------+ //|process stop parameter | //+------------------------------------------------------------------+ long normalizestop(long stop, ulong size) { // Standardizes terminal slicing markers allowing negative wrap limits or hard clamp size thresholds long s = (stop>0 && ulong(stop)>=size)?long(size):(stop<0 && ulong(fabs(stop))>size)?-1:(stop<0 && ulong(fabs(stop))<=size)?long(size)+stop:stop; return s; } //+------------------------------------------------------------------+ //| validate all calculated params | //+------------------------------------------------------------------+ bool invalidparams(long start,long stop, long step, ulong size) { // Bounds safety verification checks protecting slice loops from infinite ranges, empty outputs, or overflows if(step==0 || start==stop || ulong(start)>=size || start<0 || ulong(fabs(stop))>size || (step<0 && start0 && start>stop)) return true; return false; } //+------------------------------------------------------------------+ //| quantiles helper function | //+------------------------------------------------------------------+ vector quantile(vector &in,vector &abprobs,vector &probs) { vector x = in; if(!sort(x)) { Print(__FUNCTION__, " sort failure "); vector::Zeros(probs.Size()); } ulong n = x.Size(); if(!x.Size()) { Print(__FUNCTION__, " invalid parameter, empty vector "); vector::Zeros(probs.Size()); } // Compute localized continuous positional interpolation mapping ranges vector aleph = (double(n)*probs+abprobs); vector k = aleph; if(!k.Clip(1.0, double(n-1))) // Enforce boundary clamp constraints within valid indexing limits { Print(__FUNCTION__, " error ", GetLastError()); return vector::Zeros(probs.Size()); } k = floor(k); // Isolate base array structural address segments vector gamma = aleph-k; // Isolate remaining fractional weight offset scalars if(!gamma.Clip(0.0, 1.0)) { Print(__FUNCTION__, " error ", GetLastError()); return vector::Zeros(probs.Size()); } vector k1 = k-1.0; ulong index[]; if(!np::vecAsArray(k1,index)) { Print(__FUNCTION__, " error ", GetLastError()); return vector::Zeros(probs.Size()); } vector x1 = np::select(k1,index); // Select values at structural lower-bound thresholds ArrayFree(index); if(!np::vecAsArray(k,index)) { Print(__FUNCTION__, " error ", GetLastError()); return vector::Zeros(probs.Size()); } vector x2 = np::select(k,index); // Select values at structural upper-bound thresholds return (1.0-gamma)*x1+gamma*x2; // Linearly blend the values using calculated interpolation weights } } // namespace internal //+------------------------------------------------------------------+ //| Return arrays representing indices of a grid | //+------------------------------------------------------------------+ void indices(ulong rows, ulong cols, matrix &outRC[]) { ulong N = 2; // Expected dual coordinate dimension tracking layers count (row mapping matrix, col mapping matrix) if(ArrayResize(outRC,2)<0 || !outRC[0].Resize(rows,cols) || !outRC[1].Resize(rows,cols)) { Print(__FUNCTION__, " resize error "); return; } vector v = np::arange(rows); outRC[0] = np::repeat_vector_as_rows_cols(v,cols,false); // Broaden row axis coordinates across columns array grid v = np::arange(cols); outRC[1] = np::repeat_vector_as_rows_cols(v,rows,true); // Broaden column axis coordinates across rows array grid } //+------------------------------------------------------------------+ //| QuickSort core tracking driver algorithm implementation | //+------------------------------------------------------------------+ template bool quickSort(vector &in,bool ascending,long first,long last) { long i,j; T p_double,t_double; //--- check if(first<0 || last<0) { return false; } //--- sort i=first; j=last; while(i>1" is quick bitwise division by 2 to extract the midpoint index safely p_double=in[(first+last)>>1]; while(ip_double)) { if(i==in.Size()-1) break; i++; } while((ascending && in[j]>p_double) || (!ascending && in[j] bool quickSortIndices(vector& _in,bool ascending,long &indices[],long first,long last) { vector in = _in; // Fork internal local proxy replica tracking arrays long i,j,t_int; T p_double,t_double; //--- check if(first<0 || last<0) { return false; } //--- sort i=first; j=last; while(i>1" is quick bitwise division by 2 to extract the pivot index p_double=in[(first+last)>>1]; while(ip_double)) { if(i==in.Size()-1) break; i++; } while((ascending && in[j]>p_double) || (!ascending && in[j] bool sort(vector&in, bool ascending=true) { if(in.Size()<1) return false; return quickSort(in,ascending,0,in.Size()-1); // Redirect processing straight to the vector-based QuickSort engine } //+------------------------------------------------------------------+ //| sort matrix by columns or rows | //+------------------------------------------------------------------+ template bool sort(matrix&in, bool by_rows, bool ascending=true) { if(by_rows) { // Iterate sequentially over rows, isolating vector subsets to sort in-place for(ulong i = 0; i vector sliceVector(vector &in, const long index_start=BEGIN, const long index_stop = END, const long index_step = STEP) { //---local variables long st,sp,stp,size; //---check function parameters st = internal::normalizestart(index_start,in.Size()); sp = internal::normalizestop(index_stop,in.Size()); stp = index_step; //---error handling if(internal::invalidparams(st,sp,stp,in.Size())) { Print(__FUNCTION__," invalid function parameters "); return vector::Zeros(0); } //---calculate size of new vector size = internal::calculatesize(st,sp,stp); //---initialize output vector vector out(ulong(size)); //---assign elements to output for(long pos = st, index=0; index bool fillVector(vector &in, T value, const long index_start=BEGIN, const long index_stop = END, const long index_step = STEP) { //---local variables long st,sp,stp,size; //---check function parameters st = internal::normalizestart(index_start,in.Size()); sp = internal::normalizestop(index_stop,in.Size()); stp = index_step; //---error handling if(internal::invalidparams(st,sp,stp,in.Size())) { Print(__FUNCTION__," invalid function parameters "); return false; } //---calculate size of new vector size = internal::calculatesize(st,sp,stp); //---assign elements directly to internal working targets in-place for(long pos = st, index=0; index bool reverseVector(vector &in) { if(in.Size()<2) return in.Size()!=0; ulong size = in.Size()-1; ulong half = (in.Size())>>1; // Shift bits down rightwards by 1 to isolate midpoint boundaries safely for(ulong i = 0; i matrix sliceMatrix(matrix &in, const long row_start=BEGIN, const long row_stop = END, const long row_step = STEP,const long column_start=BEGIN, const long column_stop = END, const long column_step = STEP) { //---local variables long rst,rsp,rstp,rsize,cst,csp,cstp,csize; //---check function parameters for row manipulation rst =internal::normalizestart(row_start,in.Rows()); rsp =internal::normalizestop(row_stop,in.Rows()); rstp = row_step; //---error handling if(internal::invalidparams(rst,rsp,rstp,in.Rows())) { Print(__FUNCTION__," invalid function parameters for row specification "); return matrix::Zeros(0,0); } //---calculate size of new matrix rows rsize = internal::calculatesize(rst,rsp,rstp); //---check function parameters for column manipulation cst = internal::normalizestart(column_start,in.Cols()); csp = internal::normalizestop(column_stop,in.Cols()); cstp = column_step; //---error handling if(internal::invalidparams(cst,csp,cstp,in.Cols())) { Print(__FUNCTION__," invalid function parameters for column specification "); return matrix::Zeros(0,0); } //---calculate size of new matrix columns csize = internal::calculatesize(cst,csp,cstp); //---initialize output matrix matrix out(ulong(rsize),ulong(csize)); //---assign elements to output grid using row/column combinations for(long rpos = rst,row_index = 0; row_index bool fillMatrix(matrix &in, const T value,const long row_start=BEGIN, const long row_stop = END, const long row_step = STEP,const long column_start=BEGIN, const long column_stop = END, const long column_step = STEP) { //---local variables long rst,rsp,rstp,rsize,cst,csp,cstp,csize; //---check function parameters for row manipulation rst =internal::normalizestart(row_start,in.Rows()); rsp =internal::normalizestop(row_stop,in.Rows()); rstp = row_step; //---error handling if(internal::invalidparams(rst,rsp,rstp,in.Rows())) { Print(__FUNCTION__," invalid function parameters for row specification "); return false; } //---calculate size of new matrix rows rsize = internal::calculatesize(rst,rsp,rstp); //---check function parameters for column manipulation cst = internal::normalizestart(column_start,in.Cols()); csp = internal::normalizestop(column_stop,in.Cols()); cstp = column_step; //---error handling if(internal::invalidparams(cst,csp,cstp,in.Cols())) { Print(__FUNCTION__," invalid function parameters for column specification "); return false; } //---calculate size of new matrix columns csize = internal::calculatesize(cst,csp,cstp); //---assign elements directly inside working inputs in-place for(long rpos = rst,row_index = 0; row_index matrix sliceMatrixCols(matrix &in, const long column_start=BEGIN, const long column_stop = END, const long column_step = STEP) { // Leverages base sliceMatrix function while keeping full range settings intact along row tracks return sliceMatrix(in,BEGIN,END,STEP,column_start,column_stop,column_step); } //+------------------------------------------------------------------+ //|reverse columns of matrix | //+------------------------------------------------------------------+ template bool reverseMatrixCols(matrix &in) { ulong cols = in.Cols()-1; if(in.Cols()<2) return in.Cols()!=0; ulong cols_end = (in.Cols())>>1; // Derive column processing boundary limits safely via right shift bits // Swaps columns inwards sequentially toward structural midlines for(ulong i = 0; i matrix sliceMatrixRows(matrix &in, const long row_start=BEGIN, const long row_stop = END, const long row_step = STEP) { // Leverages base sliceMatrix function while keeping full range settings intact along column tracks return sliceMatrix(in,row_start,row_stop,row_step); } //+------------------------------------------------------------------+ //|reverse rows of matrix | //+------------------------------------------------------------------+ template bool reverseMatrixRows(matrix &in) { ulong rows = in.Rows()-1; if(in.Rows()<2) return in.Rows()!=0; ulong rows_end = (in.Rows())>>1; // Swaps rows inwards sequentially toward structural midlines for(ulong i = 0; i bool matrixCopyCols(matrix ©to,matrix ©from, const long dest_start=BEGIN, const long dest_stop = END, const long dest_step = STEP) { return matrixCopy(copyto,copyfrom,BEGIN,END,STEP,dest_start,dest_stop,dest_step); } //+------------------------------------------------------------------+ //| assign values to a portion of matrix selected within range rows | //+------------------------------------------------------------------+ template bool matrixCopyRows(matrix ©to, matrix ©from, const long dest_start=BEGIN, const long dest_stop = END, const long dest_step = STEP) { return matrixCopy(copyto,copyfrom,dest_start,dest_stop,dest_step); } //+------------------------------------------------------------------+ //|return vector of arbitrary elements (Generic Index Type Array) | //+------------------------------------------------------------------+ template vector select(vector &in,const P &indices[]) { P size = (P)MathMin(in.Size(),indices.Size()); // Safe clamp checking allocation targets // Guard checks protecting structural lookups against out of bounds array values if(size<1 || indices[ArrayMaximum(indices,0,int(size))]>=P(in.Size())) { Print(__FUNCTION__, " invalid function parameter "); return vector::Zeros(1); } vector out(size); // Populate return vectors via targeted indexes arrays mapping for(P i=0; i vector select(vector &in,vector &indices) { ulong size = (ulong)MathMin(in.Size(),indices.Size()); if(size<1 || indices.ArgMax()>=in.Size()) { Print(__FUNCTION__, " invalid function parameter "); return vector::Zeros(1); } vector out(size); for(ulong i=0; i vector shiftVector(vector &_in, long shift, T placeholder) { if(shift == 0) return _in; //--- vector shifted = vector::Zeros(_in.Size()); //--- Fill vector with place holder value if(!shifted.Fill(placeholder)) { Print(__FUNCTION__,": Vector fill failed ", GetLastError()); return vector::Zeros(0); } //---Copy values if(shift>0) for(long i = shift; i matrix shiftMatrix(matrix &_in, long shift, T placeholder) { if(shift == 0) return _in; //--- matrix shifted = matrix::Zeros(_in.Rows(),_in.Cols()); //--- Fill vector with place holder value if(!shifted.Fill(placeholder)) { Print(__FUNCTION__,": Matrix fill failed ", GetLastError()); return matrix::Zeros(0,0); } //---Copy values if(shift>0) for(long i = shift; i vector select(vector &in,const ulong &indices[]) { ulong size = (ulong)MathMin(in.Size(),indices.Size()); if(size<1 || indices[ArrayMaximum(indices,0,int(size))]>=ulong(in.Size())) { Print(__FUNCTION__, " invalid function parameter "); return vector::Zeros(1); } vector out(size); for(ulong i=0; i vector select(vector &in,const int &indices[]) { int size = (int)MathMin(in.Size(),indices.Size()); if(size<1 || indices[ArrayMaximum(indices,0,int(size))]>=int(in.Size())) { Print(__FUNCTION__, " invalid function parameter "); return vector::Zeros(1); } vector out(size); for(int i=0; i vector select(vector &in,const uint &indices[]) { uint size = (uint)MathMin(in.Size(),indices.Size()); if(size<1 || indices[ArrayMaximum(indices,0,int(size))]>=uint(in.Size())) { Print(__FUNCTION__, " invalid function parameter "); return vector::Zeros(1); } vector out(size); for(uint i=0; i matrix selectMatrixCols(matrix &in,const long &indices[]) { ulong size = (ulong)MathMin(in.Cols(),indices.Size()); if(size<1 || indices[ArrayMaximum(indices,0,int(size))]>=long(in.Cols())) { Print(__FUNCTION__," invalid function parameters "); return matrix::Zeros(0,0); } matrix out(in.Rows(),size); // Extract specific source column layouts sequentially into target positions for(ulong i=0; i matrix selectMatrixRows(matrix &in,const long &indices[]) { ulong size = (ulong)MathMin(in.Rows(),indices.Size()); if(size<1 || indices[ArrayMaximum(indices,0,int(size))]>=long(in.Rows())) { Print(__FUNCTION__," invalid function parameters "); return matrix::Zeros(0,0); } matrix out(size,in.Cols()); // Extract specific source row layouts sequentially into target positions for(ulong i=0; i matrix selectMatrixCols(matrix &in,const ulong &indices[]) { ulong size = (ulong)MathMin(in.Cols(),indices.Size()); if(size<1 || indices[ArrayMaximum(indices,0,int(size))]>=ulong(in.Cols())) { Print(__FUNCTION__," invalid function parameters "); return matrix::Zeros(0,0); } matrix out(in.Rows(),size); for(ulong i=0; i matrix selectMatrixRows(matrix &in,const ulong &indices[]) { ulong size = (ulong)MathMin(in.Rows(),indices.Size()); if(size<1 || indices[ArrayMaximum(indices,0,int(size))]>=ulong(in.Rows())) { Print(__FUNCTION__," invalid function parameters "); return matrix::Zeros(0,0); } matrix out(size,in.Cols()); for(ulong i=0; i matrix selectMatrixCols(matrix &in,vector& indices) { ulong size = (ulong)MathMin(in.Cols(),indices.Size()); if(size<1 || indices.Max()>=double(in.Cols()) || indices.Min()<0.0) { Print(__FUNCTION__," invalid function parameters "); return matrix::Zeros(0,0); } matrix out(in.Rows(),size); for(ulong i=0; i bool vectorCopy(vector ©to, vector ©from, const long dest_start=BEGIN, const long dest_stop = END, const long dest_step = STEP) { //--- Local variables to store normalized indices and size long st, sp, stp, size; //--- Convert potentially negative/default boundaries to concrete vector indices st = internal::normalizestart(dest_start, copyto.Size()); sp = internal::normalizestop(dest_stop, copyto.Size()); stp = dest_step; //--- Ensure parameters conform to limits and step logic if(internal::invalidparams(st, sp, stp, copyto.Size())) { Print(__FUNCTION__, " invalid function parameters "); return false; } //--- Calculate total number of elements to copy based on step and bounds size = internal::calculatesize(st, sp, stp); //--- Ensure source vector has enough elements to satisfy the slice size if(copyfrom.Size() < ulong(size)) { Print(__FUNCTION__, " source vector is of insufficient size "); return false; } //--- Map elements from source to destination using the slicing sequence for(long pos = st, index = 0; index < size; ++index, pos += stp) copyto[pos] = copyfrom[index]; return true; } //+------------------------------------------------------------------+ //| Assign selected elements of vector the value /fill_value/ | //+------------------------------------------------------------------+ template bool vectorFill(vector ©to, T fill_value, const long dest_start=BEGIN, const long dest_stop = END, const long dest_step = STEP) { //--- Local variables for boundaries and sizing long st, sp, stp, size; //--- Normalize start, stop and step values for the destination vector st = internal::normalizestart(dest_start, copyto.Size()); sp = internal::normalizestop(dest_stop, copyto.Size()); stp = dest_step; //--- Validate normalized index bounds if(internal::invalidparams(st, sp, stp, copyto.Size())) { Print(__FUNCTION__, " invalid function parameters "); return false; } //--- Compute how many targeted index points match the slice criteria size = internal::calculatesize(st, sp, stp); //--- Sequentially write the fixed fill_value to the specified step indices for(long pos = st, index = 0; index < size; ++index, pos += stp) copyto[pos] = fill_value; return true; } //+------------------------------------------------------------------+ //| Copy matrix copyfrom into specified positions of matrix copyto | //| with support for negative indexing python style | //+------------------------------------------------------------------+ template bool matrixCopy(matrix ©to, matrix ©from, const long row_dest_start=BEGIN, const long row_dest_stop = END, const long row_dest_step = STEP, const long column_dest_start=BEGIN, const long column_dest_stop = END, const long column_dest_step = STEP) { //--- Variables tracking row/column properties: bounds, steps, and sizes long rst, rsp, rstp, rsize, cst, csp, cstp, csize; //--- Process and normalize row dimensions rst = internal::normalizestart(row_dest_start, copyto.Rows()); rsp = internal::normalizestop(row_dest_stop, copyto.Rows()); rstp = row_dest_step; if(internal::invalidparams(rst, rsp, rstp, copyto.Rows())) { Print(__FUNCTION__, " invalid function parameters for row specification "); return false; } rsize = internal::calculatesize(rst, rsp, rstp); //--- Process and normalize column dimensions cst = internal::normalizestart(column_dest_start, copyto.Cols()); csp = internal::normalizestop(column_dest_stop, copyto.Cols()); cstp = column_dest_step; if(internal::invalidparams(cst, csp, cstp, copyto.Cols())) { Print(__FUNCTION__, " invalid function parameters for column specification "); return false; } csize = internal::calculatesize(cst, csp, cstp); //--- Verify the incoming matrix is large enough to supply data for calculated bounds if(copyfrom.Cols() < ulong(csize) || copyfrom.Rows() < ulong(rsize)) { Print(__FUNCTION__, " source matrix has insufficient number of columns and/or rows "); return false; } //--- Multi-dimensional iteration over row and column targets to perform submatrix copying for(long rpos = rst, row_index = 0; row_index < rsize; rpos += rstp, ++row_index) for(long cpos = cst, column_index = 0; column_index < csize; ++column_index, cpos += cstp) copyto[rpos][cpos] = copyfrom[row_index][column_index]; return true; } //+------------------------------------------------------------------+ //| Assign selected elements of matrix the value /fill_value/ | //+------------------------------------------------------------------+ template bool matrixFill(matrix ©to, T fill_value, const long row_dest_start=BEGIN, const long row_dest_stop = END, const long row_dest_step = STEP, const long column_dest_start=BEGIN, const long column_dest_stop = END, const long column_dest_step = STEP) { //--- Variables tracking row/column properties: bounds, steps, and sizes long rst, rsp, rstp, rsize, cst, csp, cstp, csize; //--- Process and validate row ranges rst = internal::normalizestart(row_dest_start, copyto.Rows()); rsp = internal::normalizestop(row_dest_stop, copyto.Rows()); rstp = row_dest_step; if(internal::invalidparams(rst, rsp, rstp, copyto.Rows())) { Print(__FUNCTION__, " invalid function parameters for row specification "); return false; } rsize = internal::calculatesize(rst, rsp, rstp); //--- Process and validate column ranges cst = internal::normalizestart(column_dest_start, copyto.Cols()); csp = internal::normalizestop(column_dest_stop, copyto.Cols()); cstp = column_dest_step; if(internal::invalidparams(cst, csp, cstp, copyto.Cols())) { Print(__FUNCTION__, " invalid function parameters for column specification "); return false; } csize = internal::calculatesize(cst, csp, cstp); //--- Run nested loops to flood targeted coordinate blocks with fill_value for(long rpos = rst, row_index = 0; row_index < rsize; rpos += rstp, ++row_index) for(long cpos = cst, column_index = 0; column_index < csize; ++column_index, cpos += cstp) copyto[rpos][cpos] = fill_value; return true; } //+------------------------------------------------------------------+ //| Returns double vector generated incrementally over a fixed size | //+------------------------------------------------------------------+ vector arange(const ulong size, double value=0, double step_value=1) { //--- Initialize output sequence container vector out(size); //--- Compute linearly increasing elements starting from base value for(ulong i = 0; i < size; ++i, value += step_value) out[i] = value; return out; } //+------------------------------------------------------------------+ //| Returns generic type vector bounded by start and stop conditions | //+------------------------------------------------------------------+ template vector arange(T start_value, T stop_value, T step_value) { //--- Calculate the distance between stop and start points T numerator = (stop_value - start_value); ulong size = ulong((numerator) / step_value); //--- Include trailing fractional segment step if remainder exists if(MathMod(numerator, step_value) > T(0)) size += 1; //--- Instantiate a zeroed tracking vector vector out = vector::Zeros(size); //--- Loop-populate sequential steps onto the template typed container for(ulong i = 0; i < size; ++i, start_value += step_value) out[i] = start_value; return out; } //+------------------------------------------------------------------+ //| Returns vector covering inclusive integer limits up to stop value| //+------------------------------------------------------------------+ vector range(int stop_value, int start_value = 0, int step_value = 1) { //--- Round up mathematical size calculation to catch non-divisible ranges double size = ceil(double(stop_value - start_value) / double(step_value)); vector out(ulong(size)); double value = double(start_value); double step = double(step_value); //--- Linearly step up double tracking sequence for(ulong i = 0; i < ulong(size); ++i, value += step) out[i] = value; return out; } //+------------------------------------------------------------------+ //| Outputs range sequence via mutable passing of classic array structures | //+------------------------------------------------------------------+ template bool arange(T &in_out[], const int size, T value = 0, T step_value = 1) { //--- Fail immediately if array size is specified as zero if(!size) return false; //--- Try resizing array reference, checking for allocation failures if(ArrayResize(in_out, fabs(size)) != fabs(size)) { Print(__FUNCTION__, " error ", GetLastError()); return false; } //--- Populate step values across linear dynamic allocations for(int i = 0; i < size; ++i, value += step_value) in_out[i] = value; return true; } //+------------------------------------------------------------------+ //| Equivalent to NumPy linspace(), outputs evenly spaced intervals | //+------------------------------------------------------------------+ template vector linspace(T start, T stop, ulong num=50) { vector out(num); //--- Edge Case handling: Return empty vector if no points requested if(!num) return vector::Zeros(num); //--- Edge Case handling: If 1 point, matching NumPy convention, use start value if(num == 1) { out[0] = start; return out; } //--- Identify physical step size (chunk delta) per element gap T chunk = (stop - start) / T(num - 1); //--- Construct discrete segments relative to baseline position for(ulong i = 0; i < out.Size(); ++i) out[i] = start + (T(i) * chunk); return out; } //+------------------------------------------------------------------+ //| Equivalent to NumPy logspace(), logs linear space out to custom bases| //+------------------------------------------------------------------+ vector logspace(double start, double stop, ulong num=50, double base = 10.0) { //--- Generate base exponent ranges linearly using internal linspace vector out = linspace(start, stop, num); //--- Elevate logarithmic scales per value index transformation for(ulong i = 0; i < out.Size(); ++i) out[i] = pow(base, out[i]); return out; } //+------------------------------------------------------------------+ //| Fill main diagonal of square matrix with standard value | //+------------------------------------------------------------------+ template bool fillDiagonal(matrix &in_out, T fill_value) { //--- Enforce square matrix condition constraints if(in_out.Rows() != in_out.Cols()) { Print(__FUNCTION__ "Invalid Input. Matrix is not square "); return false; } //--- Traverse uniform index coordinate paths [i][i] for(ulong i = 0; i < in_out.Rows(); ++i) in_out[i][i] = fill_value; return true; } //+------------------------------------------------------------------+ //| Copy an array of matrices (simulating a 3D structural container) | //+------------------------------------------------------------------+ bool copy3D(matrix ©_from[], matrix ©_to[]) { //--- Realign destination tracking array allocations to match donor length if(ArraySize(copy_to) != ArraySize(copy_from)) ArrayResize(copy_to, (int)copy_from.Size()); //--- Individually pass reference matrix blocks over the layer arrays for(uint i = 0; i < copy_to.Size(); ++i) copy_to[i] = copy_from[i]; return true; } //+-----------------------------------------------------------------------+ //| Generate a Vandermonde matrix | //| in : vector | //| num_columns : ulong, default: size of in input vector. | //| ascending : bool, (default: false) Order of the powers of the columns.| //| If true, the powers increase | //| from left to right, if false (the default) they are reversed | //+-----------------------------------------------------------------------+ template matrix vander(vector &in, ulong num_columns = 0, bool ascending = false) { //--- Default column sizing relies entirely on incoming reference limits ulong n = num_columns ? num_columns : in.Size(); matrix out(in.Size(), n); //--- Populate matrix column vectors with exponential powers of input terms for(ulong i = 0; i < n; ++i) out.Col(pow(in, ascending ? i : n - 1 - i), i); return out; } //+------------------------------------------------------------------+ //| Generic vector extraction to a raw typed data array | //+------------------------------------------------------------------+ template bool vecAsArray(const vector &in, T &out[], uint srce_start = 0, uint count = 0) { //--- Validate input data presence if(in.Size() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } //--- Calculate target footprint slice if(!count) count = uint(in.Size()); //--- Allocate backing arrays to accept target conversion sequences if(out.Size() != count && ArrayResize(out, int(count)) < int(count)) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } //--- Iteratively populate matching element indices via explicit cast conversions for(uint i = srce_start; i < (srce_start + count); ++i) out[i - srce_start] = T(in[i]); return true; } //+------------------------------------------------------------------+ //| Type-specific specialization: Vector to Double Array | //+------------------------------------------------------------------+ template bool vecAsArray(const vector &in, double &out[]) { if(in.Size() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } if(ulong(out.Size()) != in.Size() && ArrayResize(out, int(in.Size())) != int(in.Size())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } for(uint i = 0; i < out.Size(); ++i) out[i] = double(in[i]); return true; } //+------------------------------------------------------------------+ //| Type-specific specialization: Vector to Integer Array | //+------------------------------------------------------------------+ template bool vecAsArray(const vector &in, int &out[]) { if(in.Size() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } if(ulong(out.Size()) != in.Size() && ArrayResize(out, int(in.Size())) != int(in.Size())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } for(uint i = 0; i < out.Size(); ++i) out[i] = int(in[i]); return true; } //+------------------------------------------------------------------+ //| Type-specific specialization: Vector to Unsigned Int Array | //+------------------------------------------------------------------+ template bool vecAsArray(const vector &in, uint &out[]) { if(in.Size() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } if(ulong(out.Size()) != in.Size() && ArrayResize(out, int(in.Size())) != int(in.Size())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } for(uint i = 0; i < out.Size(); ++i) out[i] = uint(in[i]); return true; } //+------------------------------------------------------------------+ //| Type-specific specialization: Vector to Long Integer Array | //+------------------------------------------------------------------+ template bool vecAsArray(const vector &in, long &out[]) { if(in.Size() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } if(ulong(out.Size()) != in.Size() && ArrayResize(out, int(in.Size())) != int(in.Size())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } for(uint i = 0; i < out.Size(); ++i) out[i] = long(in[i]); return true; } //+------------------------------------------------------------------+ //| Type-specific specialization: Vector to Unsigned Long Array | //+------------------------------------------------------------------+ template bool vecAsArray(const vector &in, ulong &out[]) { if(in.Size() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } if(ulong(out.Size()) != in.Size() && ArrayResize(out, int(in.Size())) != int(in.Size())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } for(uint i = 0; i < out.Size(); ++i) out[i] = ulong(in[i]); return true; } //+------------------------------------------------------------------+ //| Generic matrix flattening wrapper to 1-D Double Array | //+------------------------------------------------------------------+ template bool matAsArray(const matrix &in, double &out[]) { //--- Confirm dimensional sizing viability across matrix fields if(in.Cols() + in.Rows() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } //--- Validate flat linear destination scaling space matches rows * columns if(ulong(out.Size()) != in.Cols() * in.Rows() && ArrayResize(out, int(in.Cols() * in.Rows())) != int(in.Cols() * in.Rows())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } //--- Stream sequentially flattened structural offsets directly using .Flat() indices for(uint i = 0; i < out.Size(); ++i) out[i] = double(in.Flat(i)); return true; } //+------------------------------------------------------------------+ //| Generic matrix flattening wrapper to 1-D Integer Array | //+------------------------------------------------------------------+ template bool matAsArray(const matrix &in, int &out[]) { if(in.Cols() + in.Rows() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } if(ulong(out.Size()) != in.Cols() * in.Rows() && ArrayResize(out, int(in.Cols() * in.Rows())) != int(in.Cols() * in.Rows())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } for(uint i = 0; i < out.Size(); ++i) out[i] = int(in.Flat(i)); return true; } //+------------------------------------------------------------------+ //| Generic matrix flattening wrapper to 1-D Unsigned Int Array | //+------------------------------------------------------------------+ template bool matAsArray(const matrix &in, uint &out[]) { if(in.Cols() + in.Rows() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } if(ulong(out.Size()) != in.Cols() * in.Rows() && ArrayResize(out, int(in.Cols() * in.Rows())) != int(in.Cols() * in.Rows())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } for(uint i = 0; i < out.Size(); ++i) out[i] = uint(in.Flat(i)); return true; } //+------------------------------------------------------------------+ //| Generic matrix flattening wrapper to 1-D Long Integer Array | //+------------------------------------------------------------------+ template bool matAsArray(const matrix &in, long &out[]) { if(in.Cols() + in.Rows() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } if(ulong(out.Size()) != in.Cols() * in.Rows() && ArrayResize(out, int(in.Cols() * in.Rows())) != int(in.Cols() * in.Rows())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } for(uint i = 0; i < out.Size(); ++i) out[i] = long(in.Flat(i)); return true; } //+------------------------------------------------------------------+ //| Least squares polynomial fit (Curve Fitting Functionality) | //+------------------------------------------------------------------+ vector polyfit(vector& x, vector& y, int deg) { int order = deg + 1; //--- Verify error validation criteria constraints if(deg < 0) { Print(__FUNCTION__, ": Param deg should be >= 0."); return vector::Zeros(0); } if(!x.Size()) { Print(__FUNCTION__, ": Param x is empty."); return vector::Zeros(0); } if(x.Size() != y.Size()) { Print(__FUNCTION__, ": Params x and y not of equal size"); return vector::Zeros(0); } //--- Generate left-hand side values utilizing a Vandermonde structural matrix matrix lhs = vander(x, ulong(order)); vector rhs = y; //--- Normalize scale parameters to guard algorithmic stability against floating anomalies vector scale = sqrt((lhs * lhs).Sum(0)); lhs = divide(lhs, scale); //--- Solve regularized expressions applying native Least Squares algorithm (.LstSq) vector c = lhs.LstSq(rhs); c /= scale; // Reverse scaling multiplier offset adjustment factors return c; } //+------------------------------------------------------------------+ //| Generic matrix flattening wrapper to 1-D Unsigned Long Array | //+------------------------------------------------------------------+ template bool matAsArray(const matrix &in, ulong &out[]) { if(in.Cols() + in.Rows() < 1) { Print(__FUNCTION__, " Empty vector"); return false; } if(ulong(out.Size()) != in.Cols() * in.Rows() && ArrayResize(out, int(in.Cols() * in.Rows())) != int(in.Cols() * in.Rows())) { Print(__FUNCTION__, " resize error ", GetLastError()); return false; } for(uint i = 0; i < out.Size(); ++i) out[i] = ulong(in.Flat(i)); return true; } //+------------------------------------------------------------------+ //| Difference vector according to calculation order degree | //+------------------------------------------------------------------+ template vector diff(vector &in, ulong degree = 1) { //--- Out of bounds/invalid param check if(in.Size() < 1 || degree < 1 || in.Size() < degree + 1) { Print(__FUNCTION__, " Invalid parameter "); return vector::Zeros(0); } vector yy, zz; //--- Generate matching slices offset by degree to evaluate consecutive deltas yy = sliceVector(in, long(degree)); zz = sliceVector(in, BEGIN, long(in.Size() - degree)); //--- Return differential subtraction matrices directly return yy - zz; } //+------------------------------------------------------------------+ //| Difference matrix computed independently relative to rows/columns| //+------------------------------------------------------------------+ template matrix diff(matrix &in, ulong degree = 1, bool by_row = true) { //--- Parameter bounds structural check validation if(in.Cols() + in.Rows() < 1 || degree < 1 || (by_row && in.Cols() < degree + 1) || (!by_row && in.Rows() < degree + 1)) { Print(__FUNCTION__, " Invalid function parameter "); return matrix::Zeros(0, 0); } matrix yy, zz; //--- Slice configuration mapped relative to active evaluation pathways (row vs col) if(by_row) { yy = sliceMatrix(in, BEGIN, END, STEP, long(degree)); zz = sliceMatrix(in, BEGIN, END, STEP, BEGIN, long(in.Cols() - degree)); } else { yy = sliceMatrix(in, long(degree)); zz = sliceMatrix(in, BEGIN, long(in.Rows() - degree)); } return yy - zz; } //+------------------------------------------------------------------+ //| Generate vector expanding copies of original internal elements | //+------------------------------------------------------------------+ template vector repeat_vector_elements(vector &vect, ulong num_repetitions) { //--- Allocate output matrix sized exactly to handle expanded tracking allocations vector out(num_repetitions * vect.Size()); //--- Repeatedly clone structural sets using core vector copy subroutines for(ulong i = 0; i < out.Size(); i += vect.Size()) vectorCopy(out, vect, i, i + vect.Size()); return out; } //+------------------------------------------------------------------+ //| Generate vector matching multi-reps of internal matrix elements | //+------------------------------------------------------------------+ template vector repeat_matrix_elements(matrix &in, ulong num_repetitions) { vector out(num_repetitions * in.Cols() * in.Rows()); //--- Sequentially step through grid layers flattening individual row segments for(ulong i = 0; i < out.Size(); i += (in.Cols() * num_repetitions)) { vector copy = repeat_vector_elements(in.Row(i / (in.Cols() * num_repetitions)), num_repetitions); vectorCopy(out, copy, i, i + copy.Size()); } return out; } //+------------------------------------------------------------------+ //| Generate matrix broadcasting vectors along matching grid spaces | //+------------------------------------------------------------------+ template matrix repeat_vector_as_rows_cols(vector &in, ulong num_repetitions, bool as_rows = true) { //--- Calculate inverted dimensions mapping configuration targets matrix out(as_rows ? num_repetitions : in.Size(), as_rows ? in.Size() : num_repetitions); //--- Direct matrix dimension line assignment mapping loop for(ulong i = 0; i < num_repetitions; ++i) as_rows ? out.Row(in, i) : out.Col(in, i); return out; } //+------------------------------------------------------------------+ //| Generate matrix mirroring structured lines of raw input matrixes| //+------------------------------------------------------------------+ template matrix repeat_matrix_rows_cols(matrix &in, ulong num_repetitions, bool by_rows) { if(num_repetitions < 1) { Print(__FUNCTION__, " invalid function parameter "); return matrix::Zeros(0, 0); } //--- Pre-allocate memory reflecting global row/col repetition factor dimensions matrix out((by_rows) ? num_repetitions * in.Rows() : in.Rows(), (!by_rows) ? num_repetitions * in.Cols() : in.Cols()); //--- Block map assignments matching indexed layout coordinates if(by_rows) for(ulong i = 0; i < out.Rows(); ++i) out.Row(in.Row(i / num_repetitions), i); else for(ulong i = 0; i < out.Cols(); ++i) out.Col(in.Col(i / num_repetitions), i); return out; } //+------------------------------------------------------------------+ //| Generate variable scaled matrix sequences matching discrete array maps| //+------------------------------------------------------------------+ template matrix repeat_matrix_rows_cols(matrix &in, ulong &reps[], bool by_rows) { ulong max = 0; //--- Aggregate compound structural element spans for(uint i = 0; i < reps.Size(); ++i) max += reps[i]; //--- Enforce input size conformance constraints against raw processing limits if((by_rows && in.Rows() != ulong(reps.Size())) || (!by_rows && in.Cols() != ulong(reps.Size())) || reps[ArrayMinimum(reps)] < 1) { Print(__FUNCTION__, " invalid function parameters "); return matrix::Zeros(0, 0); } matrix out((by_rows) ? max : in.Rows(), (!by_rows) ? max : in.Cols()); //--- Segment-slice elements processing arbitrary variable dimension arrays if(by_rows) for(ulong i = 0, j = 0; i < out.Rows(); i += reps[j], ++j) { matrix sliced = sliceRows(in, j, j + 1); matrix rpl = repeat_matrix_rows_cols(sliced, reps[j], true); copyRows(out, rpl, i, i + reps[j]); } else for(ulong i = 0, j = 0; i < out.Cols(); i += reps[j], ++j) { matrix sliced = sliceCols(in, j, j + 1); matrix rpl = repeat_matrix_rows_cols(sliced, reps[j], false); copyCols(out, rpl, i, i + reps[j]); } return out; } //+------------------------------------------------------------------+ //| Helper wrapper converting vector into an expanded column matrix | //+------------------------------------------------------------------+ template matrix vectorAsColumnMatrix(vector &in, ulong num_cols) { return repeat_vector_as_rows_cols(in, num_cols, false); } //+------------------------------------------------------------------+ //| Helper wrapper converting vector into an expanded row matrix | //+------------------------------------------------------------------+ template matrix vectorAsRowMatrix(vector &in, ulong num_rows) { return repeat_vector_as_rows_cols(in, num_rows, true); } //+------------------------------------------------------------------+ //| The function extracts the unique values from the vector. | //| | //| Arguments: | //| in : vector with values | //| | //| | //| Return value: out vector of unique values . | //+------------------------------------------------------------------+ template vector unique(vector &in) { //--- check array size ulong size=in.Size(); if(size==0) { Print(__FUNCTION__," Invalid function parameter "); return vector::Zeros(1); } //--- prepare additional tracker array to flag processed indices bool checked[]; if(ArrayResize(checked,int(size))!=int(size)) { Print(__FUNCTION__," error ",GetLastError()); return vector::Zeros(0) ; } ArrayFill(checked,0,int(size),false); //--- prepare out vector with maximum possible unique size vectorout(size); //--- find unique elements ulong unique_count=0; T value=0; while(true) { bool flag=false; // Loop through the vector starting from the current unique item baseline for(ulong i=unique_count; i bool unique(vector &in, vector &out, long &indices[],long &counts[]) { //--- check vector size ulong size=in.Size(); if(size==0) { Print(__FUNCTION__," Invalid function parameter "); return false; } //--- prepare internal and output buffers matching maximum possible allocation sizes bool checked[]; if(ArrayResize(checked,int(size))!=int(size) || ArrayResize(indices,int(size))!=int(size) || ArrayResize(counts,int(size))!=int(size) || !out.Resize(size)) { Print(__FUNCTION__, " error ", GetLastError()); return(false); } ArrayFill(checked,0,int(size),false); ArrayFill(indices,0,int(size),-1); ArrayFill(counts,0,int(size),1); //--- prepare out vector out.Resize(size); //--- find unique elements along with their first occurrences and frequency counts ulong unique_count=0; T value=0; while(true) { bool flag=false; for(ulong i=unique_count; i matrix unique(matrix &in,int axis = 0) { // Sum cross-sections along the axis to act as a footprint signature proxy for rows/columns vector sum = in.Sum(axis); vector spec; long indices[],counts[]; // Find uniqueness positions based on structural proxy data signatures if(!unique(sum,spec,indices,counts)) { Print(__FUNCTION__,": error "); return matrix::Zeros(0,0); } // Select and form the unique output sub-matrix based on extracted valid axis indices if(axis) return selectMatrixRows(in,indices); else return selectMatrixCols(in,indices); } //+------------------------------------------------------------------+ //|Integrate using the composite trapezoidal rule | //+------------------------------------------------------------------+ template T trapezoid(vector&y, vector&x,T dx=1) { vectord; // If specific coordinates are not given, generate evenly distributed steps using dx if(x.Size()==0) { d = vector::Zeros(y.Size()); d.Fill(dx); } else d = diff(x); // Calculate step increments between points // Compute area boundaries: step * average heights of neighboring trapezoid segments vector ret = (d*(sliceVector(y,1) + sliceVector(y,0,-1)))/2.0; // Sum up individual slices to return total definite integration value return ret.Sum(); } //+---------------------------------------------------------------------------------+ //| One-dimensional linear interpolation for monotonically increasing sample points.| //+---------------------------------------------------------------------------------+ template vectorinterp(vector &xv,vector& xpoints,vector &ypoints,double left=DBL_MIN,double right=DBL_MAX, double period=EMPTY_VALUE) { vectorout = vector::Zeros(xv.Size()); // Check if a periodic wrap (e.g. angle wrap-around interpolation) is specified if(period != EMPTY_VALUE) { if(period == 0.0) { Print(__FUNCTION__," period should be non zero"); return out; } vector x = xv; vector xp = xpoints; vector yp = ypoints; vector vp(x.Size()); vp.Fill(MathAbs(period)); // Wrap input values inside the bounded range using modulo x = MathMod(xv,vp); xp = MathMod(xpoints,vp); long indices[]; // Generate sequence range and sort internal parameters on period wrapper if(!arange(indices,int(xp.Size())) || !quickSortIndices(xp,true,indices,0,long(xp.Size()-1))) { Print(__FUNCTION__, " ", __LINE__); return out; } xp = select(xp,indices); yp = select(yp,indices); // Scale buffers up to handle repeating boundary edge conditions if(!xpoints.Resize((xp.Size()*2)+1) || !ypoints.Resize((yp.Size()*2)+1)) { Print(__FUNCTION__, " ", __LINE__, " error ", GetLastError()); return out; } if(!vectorCopy(xpoints,xp,xp.Size(),xp.Size()*2) || !vectorCopy(ypoints,yp,yp.Size(),yp.Size()*2)) { Print(__FUNCTION__, " ", __LINE__); return out; } xpoints[xpoints.Size()-1] = xp[0]+MathAbs(period); ypoints[ypoints.Size()-1] = yp[0]; if(!reverseVector(xp)) { Print(__FUNCTION__, " ", __LINE__); return out; } vector temp = xp-vp; if(!vectorCopy(xpoints,temp,0,temp.Size())) { Print(__FUNCTION__, " ", __LINE__); return out; } if(!reverseVector(yp) && !vectorCopy(ypoints,yp,0,yp.Size())) { Print(__FUNCTION__, " ", __LINE__); return out; } xv = x; } double lval,rval; double xvals[]; // Copy point references onto a basic array structure for binary exploration lookup if(!vecAsArray(xpoints,xvals) || !ArraySort(xvals)) { Print(__FUNCTION__, " ", __LINE__," error ", GetLastError()); return out; } // Define edge fallback values if input elements fall entirely out of range boundaries lval=(left==DBL_MIN)?ypoints[0]:left; rval=(right==DBL_MAX)?ypoints[ypoints.Size()-1]:right; // Handle special edge configuration where only a single data point mapping exists if(xpoints.Size()==1) { for(ulong i =0; ixpoints[0])?rval:ypoints[0]; } else { // Calculate slopes beforehand if points structural size accommodates them vector slopes=vector::Zeros(0); if(xpoints.Size()<=xv.Size()) slopes = vector::Zeros(xpoints.Size()-1); if(slopes.Size()) { vector ypd = sliceVector(ypoints,1) - sliceVector(ypoints,0,ypoints.Size()-1); vector xpd = sliceVector(xpoints,1) - sliceVector(xpoints,0,xpoints.Size()-1); slopes = ypd/xpd; // Pre-calculated rise over run variations } int j = 0; // Loop over every target interpolation coordinate element for(ulong i = 0; i matrix matmul(const matrix& matrix_a, const matrix& matrix_b) { matrix matrix_c = matrix::Zeros(0,0); // Validation rule check: Columns count of factor matrix A must match row count of factor matrix B if(matrix_a.Cols()!=matrix_b.Rows()) return(matrix_c); ulong M=matrix_a.Rows(); ulong K=matrix_a.Cols(); ulong N=matrix_b.Cols(); matrix_c=matrix::Zeros(M,N); // Perform manual standard triple nested loop cross-dot-product calculations for(ulong m=0; m vector matmul(const matrix& matrix_a, const vector& vector_b) { // Adapt the vector input format structurally into a single column matrix layout matrix matrix_b_mod = matrix::Zeros(vector_b.Size(),1); matrix_b_mod.Col(vector_b,0); // Call standard matrix-to-matrix multiplication handler matrixout = matmul(matrix_a,matrix_b_mod); return out.Col(0); // Return result converted back as a flattened flat vector array } //+------------------------------------------------------------------+ //| Find indices where elements should be inserted to maintain order | //+------------------------------------------------------------------+ template bool searchsorted(vector&sorted,vector&sample,bool right_side, vector &out) { out = vector::Zeros(sample.Size()); vector samplesorted = sample; // Verify array profile data orientation before launching comparative scans if(!np::sort(samplesorted,sorted[0]<=sorted[sorted.Size()-1])) { Print(__FUNCTION__, " error ", GetLastError()); return false; } // Search insertions tracking boundaries item by item for(ulong j = 0; jsorted.Max()) || (right_side && sample[j]>=sorted.Max())) { out[j] = double(sorted.Size()); break; } } } } } return true; } //+------------------------------------------------------------------+ //|matrix and vector addition with broadcasting | //+------------------------------------------------------------------+ template matrix add(matrix&mat, vector&vec) { // Broadcaster layout safety constraint check if(vec.Size()!=mat.Cols() && vec.Size()!=mat.Rows()) { Print(__FUNCTION__, " operands could not be broadcast together ", " (",mat.Rows(),":",mat.Cols(), ") and (", vec.Size(),")"); return matrix::Zeros(0,0); } matrixout=matrix::Zeros(mat.Rows(),mat.Cols()); // Apply vector addition row-by-row if vector dimensions line up with columns count if(vec.Size() == mat.Cols()) for(ulong i = 0; i matrix minus(matrix&mat, vector&vec) { if(vec.Size()!=mat.Cols() && vec.Size()!=mat.Rows()) { Print(__FUNCTION__, " operands could not be broadcast together ", " (",mat.Rows(),":",mat.Cols(), ") and (", vec.Size(),")"); return matrix::Zeros(0,0); } matrixout; // Subtract vector values element-by-element across matrix row profiles if(vec.Size() == mat.Cols()) { out = matrix::Zeros(mat.Rows(),mat.Cols()); for(ulong i = 0; i matrix minus(vector&vec, matrix&mat) { if(vec.Size()!=mat.Cols() && vec.Size()!=mat.Rows()) { Print(__FUNCTION__, " operands could not be broadcast together ", " (",mat.Rows(),":",mat.Cols(), ") and (", vec.Size(),")"); return matrix::Zeros(0,0); } matrixout=matrix::Zeros(mat.Rows(),mat.Cols()); // Inverse dimension order subtraction (Vector - Matrix elements) along rows orientation if(vec.Size()==mat.Cols()) for(ulong i = 0; i vector minus(vector& va, vector& vb) { // Direct subtraction shortcut if structural sizes are identical if(va.Size()==vb.Size()) return va-vb; else { // If sizes differ, one must strictly be a scalar singleton (Size = 1) to enable broadcasting if(va.Size()!=1 && vb.Size()!=1) { Print(__FUNCTION__, " operands could not be broadcast together "); return vector::Zeros(0); } else { // Subtract scalar va from array vb or scalar vb from array va depending on sizes layout if(vb.Size()>va.Size()) return va[0] - vb; else return va - vb[0]; } } } //+------------------------------------------------------------------+ //| vector addition with broadcasting | //+------------------------------------------------------------------+ template vector add(vector& va, vector& vb) { if(va.Size()==vb.Size()) return va+vb; else { if(va.Size()!=1 && vb.Size()!=1) { Print(__FUNCTION__, " operands could not be broadcast together "); return vector::Zeros(0); } else { if(vb.Size()>va.Size()) return va[0] + vb; else return va + vb[0]; } } } //+------------------------------------------------------------------+ //| vector multiplication with broadcasting | //+------------------------------------------------------------------+ template vector multiply(vector& va, vector& vb) { if(va.Size()==vb.Size()) return va*vb; else { if(va.Size()!=1 && vb.Size()!=1) { Print(__FUNCTION__, " operands could not be broadcast together "); return vector::Zeros(0); } else { if(vb.Size()>va.Size()) return va[0]*vb; else return va*vb[0]; } } } //+------------------------------------------------------------------+ //| vector division with broadcasting | //+------------------------------------------------------------------+ template vector divide(vector& va, vector& vb) { if(va.Size()==vb.Size()) return va/vb; else { if(va.Size()!=1 && vb.Size()!=1) { Print(__FUNCTION__, " operands could not be broadcast together "); return vector::Zeros(0); } else { if(vb.Size()>va.Size()) return va[0]/vb; else return va/vb[0]; } } } //+------------------------------------------------------------------+ //|matrix and vector multiplication with broadcasting | //+------------------------------------------------------------------+ template matrix multiply(matrix&mat, vector&vec) { if(vec.Size()!=mat.Cols() && vec.Size()!=mat.Rows()) { Print(__FUNCTION__, " operands could not be broadcast together ", " (",mat.Rows(),":",mat.Cols(), ") and (", vec.Size(),")"); return matrix::Zeros(0,0); } matrixout=matrix::Zeros(mat.Rows(),mat.Cols()); // Scalar-by-vector multiplication applied uniformly across structural rows or columns layers if(vec.Size() == mat.Cols()) for(ulong i = 0; i matrix divide(matrix&mat, vector&vec) { if(vec.Size()!=mat.Cols() && vec.Size()!=mat.Rows()) { Print(__FUNCTION__, " operands could not be broadcast together ", " (",mat.Rows(),":",mat.Cols(), ") and (", vec.Size(),")"); return matrix::Zeros(0,0); } matrixout=matrix::Zeros(mat.Rows(),mat.Cols()); // Divide structural matrix values uniformly by the broadcaster vector values profile if(vec.Size() == mat.Cols()) for(ulong i = 0; i matrix divide(vector&vec, matrix&mat) { if(vec.Size()!=mat.Cols() && vec.Size()!=mat.Rows()) { Print(__FUNCTION__, " operands could not be broadcast together ", " (",mat.Rows(),":",mat.Cols(), ") and (", vec.Size(),")"); return matrix::Zeros(0,0); } matrixout=matrix::Zeros(mat.Rows(),mat.Cols()); // Inverted dimension order division (Vector elements divided by Matrix cells) row/col loops if(vec.Size() == mat.Cols()) for(ulong i = 0; i vectorravelMultiIndex(vector &in[], ulong&dims[]) { vector vdims; // Convert raw dimension limits into manageable vectors tracking format lengths if(!vdims.Assign(dims)) { Print(__FUNCTION__, " error ", GetLastError()); return vector::Zeros(1); } // Extract stride steps configuration specifications vector vec = np::sliceVector(vdims,1); if(!np::reverseVector(vec)) { Print(__FUNCTION__, " error ", GetLastError()); return vector::Zeros(1); } // Compute cumulative products of shapes to define sub-dimensional stride offsets lengths vec = vec.CumProd(); if(!np::reverseVector(vec)) { Print(__FUNCTION__, " error ", GetLastError()); return vector::Zeros(1); } // Expand layout mapping tracker buffer to account for the leading dimensionality level vector nvec = vector::Ones(vec.Size()+1); if(!vectorCopy(nvec,vec,1)) { Print(__FUNCTION__, " error ", GetLastError()); return vector::Zeros(1); } // Initialize data conversion matrices targeting multi-index parameters dimensions matrixout(in.Size(),in[0].Size()); for(ulong i = 0; i vector binEdges(vector&in, ulong numbins=3) { // Determine range limits boundaries across the entire input cluster vector T first_edge = in.Min(); T last_edge = in.Max(); // Construct linear evenly-spaced coordinate boundaries arrays matching numbins scale return np::linspace(first_edge,last_edge,numbins); } /*+------------------------------------------------------------------+ //| numpy digitize for scalar values | //+------------------------------------------------------------------+ template long digitize(T sample, vector&edges, bool right_side=false) { for(long i = 1; iedges.Max()) || (!right_side && sample>=edges.Max())) return long(edges.Size()); } } } return -1; } //+------------------------------------------------------------------+ //| Compute the multidimensional histogram of some data. | //+------------------------------------------------------------------+ template bool histogramdd(matrix&in, ulong bins, vector &hist, vector &edges[]) { hist = vector::Zeros(ulong(pow(bins,in.Cols()))); if(edges.Size()) ArrayFree(edges); if(!bins) bins=3; if(ArrayResize(edges,int(in.Cols()))<0) { Print(__FUNCTION__, " error ", GetLastError()); return false; } for(ulong i = 0; irow = in.Row(i); long final_index=0; for(ulong j =0; j=long(hist.Size()) || final_index<0) { Print(__FUNCTION__, " hist index out of bounds. Index ", final_index, " hist size ", hist.Size()); return false; } hist[final_index] +=1.0; } return true; } //+------------------------------------------------------------------+ //| Compute the multidimensional histogram of some data. | //+------------------------------------------------------------------+ template bool histogramdd(matrix&in, ulong &bins[], vector &hist, vector &edges[]) { hist = vector::Zeros(np::internal::prodArray(bins)); if(edges.Size()) ArrayFree(edges); if(ulong(bins.Size())row = in.Row(i); long final_index=0; for(ulong j =0; j=long(hist.Size()) || final_index<0) { Print(__FUNCTION__, " hist index out of bounds. Index ", final_index, " hist size ", hist.Size()); return false; } hist[final_index] +=1.0; } return true; } //+------------------------------------------------------------------+ //| Compute the one dimensional histogram of some data. | //+------------------------------------------------------------------+ template bool histogram(vector&in, ulong bins, vector &hist, vector &edges) { hist = vector::Zeros(in.Size()); if(!bins) bins=3; if(in.Size()/2 < bins) { Print(__FUNCTION__, " invalid parameters, too few observations relative to the number of bins "); return false; } edges = np::linspace(in.Min(), in.Max(),bins+1); for(ulong j =0; j vectorbitwiseNot(vector&left) { int aleft[]; int res[]; // Input validation: ensure the vector contains elements if(left.Size()<1) { Print(__FUNCTION__, " invalid function input "); return vector::Zeros(left.Size()); } // Convert the MQL vector object into a standard array for Math bitwise operations if(!vecAsArray(left,aleft)) { Print(__FUNCTION__, " vector conversion failed "); return vector::Zeros(left.Size()); } // Execute the internal MQL mathematical bitwise NOT operation if(!MathBitwiseNot(aleft,res)) { Print(__FUNCTION__ " MathBitwiseNot failed ", GetLastError()); return vector::Zeros(left.Size()); } vector vec; // Assign the resulting native array back into the native vector object if(!vec.Assign(res)) { Print(__FUNCTION__ " Array assignment to vector failed ", GetLastError()); return vector::Zeros(left.Size()); } return vec; } //+------------------------------------------------------------------+ //| BitwiseAnd | //| Computes the bitwise AND operation between two vectors. | //+------------------------------------------------------------------+ template vectorbitwiseAnd(vector&left,vector&right) { int aleft[]; int aright[]; int res[]; // Validation: Vectors must be of identical size and not empty if(left.Size()!=right.Size() || right.Size()<1) { Print(__FUNCTION__, " invalid function inputs "); return vector::Zeros(left.Size()); } // Convert both input vectors into native array types if(!vecAsArray(left,aleft) || !vecAsArray(right,aright)) { Print(__FUNCTION__, " vector conversion failed "); return vector::Zeros(left.Size()); } // Perform element-wise bitwise AND if(!MathBitwiseAnd(aleft,aright,res)) { Print(__FUNCTION__ " MathBitwiseAnd failed ", GetLastError()); // Fixed log message to match operation return vector::Zeros(left.Size()); } vector vec; // Re-populate and return the vector object if(!vec.Assign(res)) { Print(__FUNCTION__ " Array assignment to vector failed ", GetLastError()); return vector::Zeros(left.Size()); } return vec; } //+------------------------------------------------------------------+ //| BitwiseOr | //| Computes the bitwise OR operation between two vectors. | //+------------------------------------------------------------------+ template vectorbitwiseOr(vector&left,vector&right) { int aleft[]; int aright[]; int res[]; // Validation: Dimension matching and size boundary check if(left.Size()!=right.Size() || right.Size()<1) { Print(__FUNCTION__, " invalid function inputs "); return vector::Zeros(left.Size()); } // Convert vector objects into internal raw arrays if(!vecAsArray(left,aleft) || !vecAsArray(right,aright)) { Print(__FUNCTION__, " vector conversion failed "); return vector::Zeros(left.Size()); } // Execute the mathematical bitwise OR function if(!MathBitwiseOr(aleft,aright,res)) { Print(__FUNCTION__ " MathBitwiseOr failed ", GetLastError()); // Fixed log string return vector::Zeros(left.Size()); } vector vec; // Re-assign raw array data back onto the generic vector if(!vec.Assign(res)) { Print(__FUNCTION__ " Array assignment to vector failed ", GetLastError()); return vector::Zeros(left.Size()); } return vec; } //+------------------------------------------------------------------+ //| BitwiseXor | //| Computes the bitwise XOR operation between two vectors. | //+------------------------------------------------------------------+ template vectorbitwiseXor(vector&left,vector&right) { int aleft[]; int aright[]; int res[]; // Validation: Match dimensions and check for empty elements if(left.Size()!=right.Size() || right.Size()<1) { Print(__FUNCTION__, " invalid function inputs "); return vector::Zeros(left.Size()); } // Convert matrix vector wrappers to system arrays if(!vecAsArray(left,aleft) || !vecAsArray(right,aright)) { Print(__FUNCTION__, " vector conversion failed "); return vector::Zeros(left.Size()); // Added missing semicolon } // Run the mathematical bitwise Exclusive OR (XOR) if(!MathBitwiseXor(aleft,aright,res)) { Print(__FUNCTION__ " MathBitwiseXor failed ", GetLastError()); // Fixed log string return vector::Zeros(left.Size()); } vector vec; // Repack results array into a generic MQL vector if(!vec.Assign(res)) { Print(__FUNCTION__ " Array assignment to vector failed ", GetLastError()); return vector::Zeros(left.Size()); } return vec; } //+------------------------------------------------------------------+ //| BitwiseShiftL | //| Shifts bits to the left for all vector elements. | //+------------------------------------------------------------------+ template vectorbitwiseShiftL(vector&left,int shift) { int aleft[]; int res[]; // Validation: Vector must have contents and shift amount must be positive if(!left.Size() || shift<1) { Print(__FUNCTION__, " invalid function inputs "); return vector::Zeros(left.Size()); } // Map vector to temporary calculations array if(!vecAsArray(left,aleft)) { Print(__FUNCTION__, " vector conversion failed "); return vector::Zeros(left.Size()); // Added missing semicolon } // Call internal bit shifting calculation if(!MathBitwiseShiftL(aleft,shift,res)) { Print(__FUNCTION__ " MathBitwiseShiftL failed ", GetLastError()); // Fixed log string return vector::Zeros(left.Size()); } vector vec; // Assign result buffer back to structural vector if(!vec.Assign(res)) { Print(__FUNCTION__ " Array assignment to vector failed ", GetLastError()); return vector::Zeros(left.Size()); } return vec; } //+------------------------------------------------------------------+ //| BitwiseShiftR | //| Shifts bits to the right for all vector elements. | //+------------------------------------------------------------------+ template vectorbitwiseShiftR(vector&left,int shift) { int aleft[]; int res[]; // Validation: Check array bounds and enforce positive shift count if(!left.Size() || shift<1) { Print(__FUNCTION__, " invalid function inputs "); return vector::Zeros(left.Size()); } // Extract flat layout array from vector template object if(!vecAsArray(left,aleft)) { Print(__FUNCTION__, " vector conversion failed "); return vector::Zeros(left.Size()); // Added missing semicolon } // Compute systemic right-shift math logic if(!MathBitwiseShiftR(aleft,shift,res)) { Print(__FUNCTION__ " MathBitwiseShiftR failed ", GetLastError()); // Fixed log string return vector::Zeros(left.Size()); } vector vec; // Map array primitives back into your vector struct object if(!vec.Assign(res)) { Print(__FUNCTION__ " Array assignment to vector failed ", GetLastError()); return vector::Zeros(left.Size()); } return vec; } //+------------------------------------------------------------------+ //| BitwiseNot (Matrix Overload) | //| Computes the bitwise NOT operation element-wise on a matrix. | //+------------------------------------------------------------------+ template matrixbitwiseNot(matrix&left) { int aleft[]; int res[]; // Structure Integrity Verification: Reject flat matrices if(!left.Rows() || !left.Cols()) { Print(__FUNCTION__, " invalid function input "); return matrix::Zeros(left.Rows(),left.Cols()); } // Flatten the 2D matrix into a 1D continuous array format if(!matAsArray(left,aleft)) { Print(__FUNCTION__, " matrix conversion failed "); return matrix::Zeros(left.Rows(),left.Cols()); // Added missing semicolon } // Run bitwise processing on array representation if(!MathBitwiseNot(aleft,res)) { Print(__FUNCTION__ " MathBitwiseNot failed ", GetLastError()); return matrix::Zeros(left.Rows(),left.Cols()); } matrix mat; // Reconstruct the array output back into matrix dimensionality structures if(!mat.Assign(res) || !mat.Reshape(left.Rows(),left.Cols())) { Print(__FUNCTION__ " Array assignment to matrix failed ", GetLastError()); return matrix::Zeros(left.Rows(),left.Cols()); } return mat; } //+------------------------------------------------------------------+ //| BitwiseAnd (Matrix Overload) | //| Computes the bitwise AND operation element-wise on two matrices. | //+------------------------------------------------------------------+ template matrixbitwiseAnd(matrix&left,matrix&right) { int aleft[]; int aright[]; int res[]; // Bound check validations across both matrices axes if(!left.Rows() || !left.Cols() || !right.Cols() || !right.Rows()) { Print(__FUNCTION__, " invalid function inputs "); return matrix::Zeros(left.Rows(),left.Cols()); } // Convert multi-dimensional templates down to processing raw arrays if(!matAsArray(left,aleft) || !matAsArray(right,aright)) { Print(__FUNCTION__, " matrix conversion failed "); return matrix::Zeros(left.Rows(),left.Cols()); // Added missing semicolon } // Compute element-by-element intersection bits if(!MathBitwiseAnd(aleft,aright,res)) { Print(__FUNCTION__ " MathBitwiseAnd failed ", GetLastError()); // Fixed log string return matrix::Zeros(left.Rows(),left.Cols()); } matrix mat; // Map flattened operational logs into target output dimensions if(!mat.Assign(res) || !mat.Reshape(left.Rows(),left.Cols())) { Print(__FUNCTION__ " Array assignment to matrix failed ", GetLastError()); return matrix::Zeros(left.Rows(),left.Cols()); } return mat; } //+------------------------------------------------------------------+ //| BitwiseOr (Matrix Overload) | //| Computes the bitwise OR operation element-wise on two matrices. | //+------------------------------------------------------------------+ template matrixbitwiseOr(matrix&left,matrix&right) { int aleft[]; int aright[]; int res[]; // Validation checks for size bounds if(!left.Rows() || !left.Cols() || !right.Cols() || !right.Rows()) { Print(__FUNCTION__, " invalid function inputs "); return matrix::Zeros(left.Rows(),left.Cols()); } // Flatten processing structures if(!matAsArray(left,aleft) || !matAsArray(right,aright)) { Print(__FUNCTION__, " matrix conversion failed "); return matrix::Zeros(left.Rows(),left.Cols()); // Added missing semicolon } // Run MQL bit math block logic if(!MathBitwiseOr(aleft,aright,res)) { Print(__FUNCTION__ " MathBitwiseOr failed ", GetLastError()); // Fixed log string return matrix::Zeros(left.Rows(),left.Cols()); } matrix mat; // Copy layout matrix back onto instance object if(!mat.Assign(res) || !mat.Reshape(left.Rows(),left.Cols())) { Print(__FUNCTION__ " Array assignment to matrix failed ", GetLastError()); return matrix::Zeros(left.Rows(),left.Cols()); } return mat; } //+------------------------------------------------------------------+ //| BitwiseXor (Matrix Overload) | //| Computes the bitwise XOR operation element-wise on two matrices. | //+------------------------------------------------------------------+ template matrixbitwiseXor(matrix&left,matrix&right) { int aleft[]; int aright[]; int res[]; // Matrix non-empty structure assertions if(!left.Rows() || !left.Cols() || !right.Cols() || !right.Rows()) { Print(__FUNCTION__, " invalid function inputs "); return matrix::Zeros(left.Rows(),left.Cols()); } // Extract raw values if(!matAsArray(left,aleft) || !matAsArray(right,aright)) { Print(__FUNCTION__, " matrix conversion failed "); return matrix::Zeros(left.Rows(),left.Cols()); // Added missing semicolon } // Perform XOR math processing calculation if(!MathBitwiseXor(aleft,aright,res)) { Print(__FUNCTION__ " MathBitwiseXor failed ", GetLastError()); // Fixed log string return matrix::Zeros(left.Rows(),left.Cols()); } matrix mat; // Build spatial coordinate tracking fields back into the result container if(!mat.Assign(res) || !mat.Reshape(left.Rows(),left.Cols())) { Print(__FUNCTION__ " Array assignment to matrix failed ", GetLastError()); return matrix::Zeros(left.Rows(),left.Cols()); } return mat; } //+------------------------------------------------------------------+ //| BitwiseShiftL (Matrix Overload) | //| Shifts bits left for all matrix elements. | //+------------------------------------------------------------------+ template matrixbitwiseShiftL(matrix&left,int shift) { int aleft[]; int res[]; // Ensure valid boundaries and positive values if(!left.Rows() || !left.Cols() || shift<1) { Print(__FUNCTION__, " invalid function inputs "); return matrix::Zeros(left.Rows(),left.Cols()); } // Convert matrix format down into array buffers if(!matAsArray(left,aleft)) { Print(__FUNCTION__, " matrix conversion failed "); return matrix::Zeros(left.Rows(),left.Cols()); // Added missing semicolon } // Execute left-shift execution pipeline if(!MathBitwiseShiftL(aleft,shift,res)) { Print(__FUNCTION__ " MathBitwiseShiftL failed ", GetLastError()); // Fixed log string return matrix::Zeros(left.Rows(),left.Cols()); } matrix mat; // Reshape into original grid profile constraints if(!mat.Assign(res) || !mat.Reshape(left.Rows(),left.Cols())) { Print(__FUNCTION__ " Array assignment to matrix failed ", GetLastError()); return matrix::Zeros(left.Rows(),left.Cols()); } return mat; } //+------------------------------------------------------------------+ //| BitwiseShiftR (Matrix Overload) | //| Shifts bits right for all matrix elements. | //+------------------------------------------------------------------+ template matrixbitwiseShiftR(matrix&left,int shift) { int aleft[]; int res[]; // Structural parameter sanitization check if(!left.Rows() || !left.Cols() || shift<1) { Print(__FUNCTION__, " invalid function inputs "); return matrix::Zeros(left.Rows(),left.Cols()); } // Convert matrix wrapper instance properties into native array blocks if(!matAsArray(left,aleft)) { Print(__FUNCTION__, " matrix conversion failed "); return matrix::Zeros(left.Rows(),left.Cols()); // Added missing semicolon } // Perform binary structural shift calculation if(!MathBitwiseShiftR(aleft,shift,res)) { Print(__FUNCTION__ " MathBitwiseShiftR failed ", GetLastError()); // Fixed log string return matrix::Zeros(left.Rows(),left.Cols()); } matrix mat; // Reconstruct geometric configuration layouts matching the parent element dimensions if(!mat.Assign(res) || !mat.Reshape(left.Rows(),left.Cols())) { Print(__FUNCTION__ " Array assignment to matrix failed ", GetLastError()); return matrix::Zeros(left.Rows(),left.Cols()); } return mat; } //+------------------------------------------------------------------+ //| Write matrix to CSV file | //| Outputs content from a generic matrix instance to filesystem log | //+------------------------------------------------------------------+ template bool matrix2csv(string csv_name, matrix &matrix_, string header_string="", bool common=false, int digits=8) { // Erase pre-existing file configurations safely before writing new assets FileDelete(csv_name); int handle = FileOpen(csv_name,FILE_WRITE|FILE_CSV|FILE_ANSI|(common?FILE_COMMON:FILE_ANSI),",",CP_UTF8); // Generate default programmatic numeric indexing string headers if left blank if(header_string == "") for(ulong i=0; i row = {}; datetime time_start = GetTickCount(), current_time; string header[]; ushort u_sep = StringGetCharacter(",",0); // Tokenize structural headers using selected formatting character split configurations StringSplit(header_string,u_sep, header); vector colsinrows = matrix_.Row(0); // Verify parsed configuration strings match explicit geometric column widths if(ArraySize(header) != (int)colsinrows.Size()) { printf("headers=%d and columns=%d from the matrix vary is size ",ArraySize(header),colsinrows.Size()); FileClose(handle); // Added tracking file close protection execution return false; } // Construct clean file header string outputs string header_str = ""; for(int i=0; i0) { ++all_size; ArrayResize(Arr,all_size); Arr[all_size-1] = data; } // Monitor tracking checks across string character transitions points if(FileIsLineEnding(handle)) { cols_total=column; ++rows; column = 0; } } FileClose(handle); } // Compute total matrix properties matching calculations mapping arrays int rows = all_size/cols_total; Comment(""); matrix mat(rows, cols_total); string Col[]; // Distribute parsed cell text data back across vertical structural column segments for(int i=0; i bool sampleVector(vector &in,const ulong count,vector &result) { if(!in.Size()) return false; // Ensure target allocation space is sized adequately if(result.Size() vector choice(vector& a, vector& p, ulong size = 0, bool replace = true) { ulong pop_size = a.Size(); vector idx; // Structural boundaries validation if(!pop_size && size) { Print(__FUNCTION__, " a cannot be empty unless no samples are taken "); return vector::Zeros(0); } // Custom distribution setup and validation routines if(p.Size()) { ulong d = p.Size(); double atol = DBL_EPSILON; if(d!=pop_size) { Print(__FUNCTION__, " a and p must have same size "); return vector::Zeros(0); } double psum = p.Sum(); if(p.Min()<0.0) { Print(__FUNCTION__, " probabilities cannot be negative "); return vector::Zeros(0); } if(psum-1.>atol) { Print(__FUNCTION__, " probabilities must sum to 1 "); return vector::Zeros(0); } } // Initialize the high-quality crypto-grade pseudo-random state structure objects CHighQualityRandStateShell rstate; CHighQualityRand::HQRndRandomize(rstate.GetInnerObj()); bool is_scalar = (size==0); ulong shape = 0; vector cdf; if(!is_scalar) shape = size; else size = 1; // CASE 1: Sampling with Replacement allowed if(replace) { if(p.Size()) { // Create a Cumulative Distribution Function array track matching probabilities cdf = p.CumSum(); cdf/=cdf[cdf.Size()-1]; // Normalize cumulative tracks vector uniform_samples = vector::Zeros(shape); // Gather uniform random values between 0.0 and 1.0 for(ulong i = 0; i::Zeros(0); } } else { // Default path: Generate uniform completely unweighted random index maps idx = vector::Zeros(size); for(ulong i = 0; ipop_size) { Print(__FUNCTION__, " cannot take a larger sample than population when replace = false "); return vector::Zeros(0); } if(p.Size()) { ulong n_uniq = 0; vector pp = p; vector found = vector::Zeros(shape); vector _new,temp; long uindices[],counted[]; // Loop structure selection blocks until we hit unique requested limit records while(n_uniq0) { for(ulong i = 0; i bool sampleVector(vector &in,const ulong count,const bool replace,vector &result) { // Shortcut directly back onto default handler if replacement paths are chosen if(replace) return sampleVector(in,count,result); if(!in.Size()) return(false); // Resize target objects validation check structures if(result.Size() bool sampleArray(T &array[],const ulong count,T &result[]) { if(!array.Size()) return false; // Allocation scaling checks for array buffers structures types parameters if(result.Size() bool sampleArray(T &array[],const ulong count,const bool replace,T &result[]) { // Route over tracking patterns back directly to baseline execution states if(replace) return sampleArray(array,count,result); if(!array.Size()) return(false); // Resize system buffer tracks sizes validations checks controls if(result.Size() bool epdf(const vector &vec, const ulong count, vector &x, vector &pdf) { // Bins must be greater than 1 to establish intervals if(count<=1) return(false); ulong size=vec.Size(); if(size==0) return(false); //--- check NaN values // Verify all elements are valid numbers before proceeding for(ulong i=0; i bool ecdf(const vector &vec, const ulong count, vector &x, vector &cdf) { if(count<1) return(false); ulong size=vec.Size(); if(size==0) return(false); //--- check NaN values if(vec.HasNan()) { Print(__FUNCTION__," input data contains invalid number(s)"); return false; } //--- prepare output arrays if(x.Size() pdf; if(!pdf.Resize(count)) return(false); for(ulong i=0; i double spearmanRho(vector &vec1, vector &vec2) { ulong size=vec1.Size(); if(size<1 || vec2.Size()!=size) { Print(__FUNCTION__, " vector lengths donot match "); return(EMPTY_VALUE); } //--- calculate ranks // Converts raw values into rank orders to perform non-parametric correlation vector rank_x = rankVector(vec1); vector rank_y = rankVector(vec2); //--- // Spearman correlation is equivalent to Pearson correlation on ranked variables return rank_x.CorrCoef(rank_y); } //+------------------------------------------------------------------+ //| MathCorrelationKendall | //| Computes Kendall's Tau-b rank correlation coefficient | //| measuring concordant and discordant pairs. | //+------------------------------------------------------------------+ template double kendalTau(const vector &vec1, const vector &vec2) { double tau = double("nan"); ulong size=vec1.Size(); if(size==0 || vec2.Size()!=size) { Print(__FUNCTION__, " size of input vectors donot match "); return(tau); } // cnt1/cnt2 track non-tied elements in each vector, cnt tracks (concordant - discordant) long cnt1=0, cnt2=0, cnt=0; //--- Compare every possible pair combination (i, j) for(long i=0; i0.0) ++cnt; // Concordant pair else cnt--; // Discordant pair } } } //--- calculate Kendall tau long den=cnt1*cnt2; if(den==0) { Print(__FUNCTION__, " failed zero check at line 3139 "); return tau; } // Calculate Tau formula adjusting for ties tau=double(cnt)/MathSqrt(den); return(tau); } //+------------------------------------------------------------------+ //| MathRank | //| Ranks the elements of a vector, assigning average fractional | //| ranks to tied elements. Uses an in-place Heap Sort routine. | //+------------------------------------------------------------------+ template vector rankVector(vector &in_vec) { vector rank = vector::Ones(in_vec.Size()); ulong size=in_vec.Size(); if(size<1) return rank; if(size==1) { rank[0]=1; return rank; } //--- prepare arrays vectorvalues = in_vec; ulong indices[]; // Create an index sequence tracking original positions [0, 1, 2... size-1] if(!arange(indices, int(size))) return rank; ulong i, j, k, t, tmpi; double tmp; //--- sort (Heap Sort Implementation keeping track of data indices) if(size!=1) { i=2; do { t=i; while(t!=1) { k=t/2; if(values[k-1]>=values[t-1]) t=1; else { //--- swap values and tracking indices tmp=values[k-1]; values[k-1]=values[t-1]; values[t-1]=tmp; tmpi=indices[k-1]; indices[k-1]=indices[t-1]; indices[t-1]=tmpi; t=k; } } i=i+1; } while(i<=size); i=size-1; do { //--- swap root with current boundary element tmp=values[i]; values[i]=values[0]; values[0]=tmp; tmpi=indices[i]; indices[i]=indices[0]; indices[0]=tmpi; t=1; while(t!=0) { k=2*t; if(k>i) t=0; else { if(kvalues[k-1]) ++k; if(values[t-1]>=values[k-1]) t=0; else { //--- swap tmp=values[k-1]; values[k-1]=values[t-1]; values[t-1]=tmp; tmpi=indices[k-1]; indices[k-1]=indices[t-1]; indices[t-1]=tmpi; t=k; } } } i=i-1; } while(i>=1); } //--- compute tied ranks // Finds contiguous repeating values and updates them to their fractional rank average i=0; while(i void whereIsEqual(vector&in, const T value, const T maxdiff) { in -= value; whereIsLessEqual(fabs(in), fabs(maxdiff)); } //+------------------------------------------------------------------+ //| Modifies matrix in place: elements matching 'value' (within | //| maxdiff tolerance) become 1.0, others become 0.0. | //+------------------------------------------------------------------+ template void whereIsEqual(matrix&in, const T value, const T maxdiff) { in -= value; whereIsLessEqual(fabs(in), fabs(maxdiff)); } //+------------------------------------------------------------------+ //| Sets vector elements to 1.0 if less than value, else 0.0 | //+------------------------------------------------------------------+ template void whereIsLess(vector&in, const T value) { for(ulong i = 0; i void whereIsGreater(vector&in, const T value) { for(ulong i = 0; ivalue?1.0:0.0; } //+------------------------------------------------------------------+ //| Sets vector elements to 1.0 if less or equal to value, else 0.0 | //+------------------------------------------------------------------+ template void whereIsLessEqual(vector&in, const T value) { for(ulong i = 0; i void whereIsGreaterEqual(vector&in, const T value) { for(ulong i = 0; i=value?1.0:0.0; } //+------------------------------------------------------------------+ //| Sets matrix elements to 1.0 if less than value, else 0.0 | //+------------------------------------------------------------------+ template void whereIsLess(matrix&in, const T value) { for(ulong i = 0; i void whereIsLessEqual(matrix&in, const T value) { for(ulong i = 0; i void whereIsGreater(matrix&in, const T value) { for(ulong i = 0; ivalue?1.0:0.0; } //+------------------------------------------------------------------+ //| Sets matrix elements to 1.0 if greater or equal to value, else 0.| //+------------------------------------------------------------------+ template void whereIsGreaterEqual(matrix&in, const T value) { for(ulong i = 0; i=value?1.0:0.0; } //+------------------------------------------------------------------+ //| Returns a new binary mask vector: 1.0 if element < value, else 0.| //+------------------------------------------------------------------+ template vector whereVectorIsLt(vector&in, const T value) { vectorout = vector::Zeros(in.Size()); for(ulong i = 0; i vector whereVectorIsLte(vector&in, const T value) { vectorout = vector::Zeros(in.Size()); for(ulong i = 0; i value, else 0.| //+------------------------------------------------------------------+ template vector whereVectorIsGt(vector&in, const T value) { vectorout = vector::Zeros(in.Size()); for(ulong i = 0; ivalue) out[i] = 1.0; } return out; } //+------------------------------------------------------------------+ //| Returns a new binary mask vector: 1.0 if element >= value, else 0| //+------------------------------------------------------------------+ template vector whereVectorIsGte(vector&in, const T value) { vectorout = vector::Zeros(in.Size()); for(ulong i = 0; i=value) out[i] = 1.0; } return out; } //+------------------------------------------------------------------+ //| Returns a new binary mask matrix: 1.0 if element < value, else 0.| //+------------------------------------------------------------------+ template matrix whereMatrixIsLt(matrix&in, const T value) { matrixout = matrix::Zeros(in.Rows(),in.Cols()); for(ulong i = 0; i matrix whereMatrixIsLte(matrix&in, const T value) { matrixout = matrix::Zeros(in.Rows(),in.Cols()); for(ulong i = 0; i value, else 0.| //+------------------------------------------------------------------+ template matrix whereMatrixIsGt(matrix&in, const T value) { matrixout = matrix::Zeros(in.Rows(),in.Cols()); for(ulong i = 0; ivalue) out[i][j] = 1.0; } return out; } //+------------------------------------------------------------------+ //| Returns a new binary mask matrix: 1.0 if element >= value, else 0| //+------------------------------------------------------------------+ template matrix whereMatrixIsGte(matrix&in, const T value) { matrixout = matrix::Zeros(in.Rows(),in.Cols()); for(ulong i = 0; i=value) out[i][j] = 1.0; } return out; } //+------------------------------------------------------------------+ //| Returns a vector mask: 1.0 if rounded values equal target value. | //+------------------------------------------------------------------+ template vector whereVectorIsEq(vector&in, const T value, int _digits = 8) { vectorout = vector::Zeros(in.Size()); for(ulong i = 0; i= value instead of == value. | //+------------------------------------------------------------------+ template matrix whereMatrixIsEq(matrix&in, const T value, int _digits = 8) { matrixout = matrix::Zeros(in.Rows(),in.Cols()); for(ulong i = 0; i=value) // Double check if this should be == out[i][j] = 1.0; } return out; } //+------------------------------------------------------------------+ //| Returns a copy of the vector with NaN / irregular items replaced | //| by a fallback filler value. | //+------------------------------------------------------------------+ template vector replace_whereVectorIsNaN(vector&in, const T fill = 0.0) { vectorout = in; // Quick exit check if the entire vector is completely made of NaN values if(in.HasNan()==in.Size()) { out.Fill(fill); return out; } for(ulong i = 0; i matrix replace_whereMatrixIsNaN(matrix&in, const T fill = 0.0) { matrixout = in; // Quick exit check if every single matrix location is NaN if(in.HasNan()==(in.Rows()*in.Cols())) { out.Fill(fill); return out; } for(ulong i = 0; i bool copyToSelectCols(matrix ©to, matrix &from, vector &v_mask) { // Bounds verification checking that shapes/dimensions line up correctly if(from.Cols()!=copyto.Cols() || v_mask.Size()!=copyto.Cols()) { Print(__FUNCTION__, " invalid parameters "); return false; } for(ulong i = 0; i bool copyToSelectRows(matrix ©to, matrix from, vector &v_mask) { // Validate dimension compatibility: source, destination, and mask must match row-wise if(from.Rows()!=copyto.Rows() || v_mask.Size()!=copyto.Rows()) { Print(__FUNCTION__, " invalid parameters "); return false; } // Iterate through each row for(ulong i = 0; i bool copySelectElements(vector ©to, vector &from, vector &v_mask) { // Ensure all vectors share the same length if(from.Size()!=copyto.Size() || v_mask.Size()!=copyto.Size()) { Print(__FUNCTION__, " invalid parameters "); return false; } // Transfer elements conditionally based on mask values for(ulong i = 0; i T sign(const T a) { if(aT(0)) return T(1); else return T(0); } //+------------------------------------------------------------------+ //| Calculation of raw moment about specified center | //| Computes statistical moments efficiently using a binary | //| exponentiation breakdown to calculate power transformations. | //+------------------------------------------------------------------+ double moment(vector& a, ulong order, double mean=NULL) { // Edge case: Empty vector defaults to statistical mean if(!a.Size()) return a.Mean(); // Direct results for 0th or 1st-order basic moments if(order == 0 || (order == 1 && !mean)) return order==0?1.0:0.; // Build an execution chain for dynamic power processing (binary exponentiation) ulong list[]; ArrayResize(list,list.Size()+1,100); list[list.Size()-1]=order; ulong current = order; while(current>2) { if(MathMod(current,2)) current=(current-1)/2; else current/=2; ArrayResize(list,list.Size()+1,100); list[list.Size()-1]= current; } // Identify the distribution center (mean) double mn = (mean == 0.0)?a.Mean():mean; // Center the data values vector azeromean = a - mn; vector s; if(list[list.Size()-1] == 1) s = azeromean; else s = pow(azeromean,2.); // Unwind the exponentiation tree to compute final elevated matrix/vector power states for(int i = int(list.Size())-2; i>=0; --i) { s = pow(s,2.0); if(MathMod(i,2)) s*=azeromean; } return s.Mean(); } //+------------------------------------------------------------------+ //| sin(pi*x) implementation | //| Computes sin(pi*x) reliably by wrapping the argument inside the | //| standard period range [0, 2) to eliminate large float errors. | //+------------------------------------------------------------------+ template T sinpi(T x) { T s = 1.0; // Force input positivity and track original quadrant sign if(x < 0.0) { x = -x; s = -1.0; } // Map value into a standard [0.0, 2.0) periodicity window T r = fmod(x, 2.0); if(r < 0.5) { return s * sin(M_PI * r); } else if(r > 1.5) { return s * sin(M_PI * (r - 2.0)); } else { return -s * sin(M_PI * (r - 1.0)); } } //+------------------------------------------------------------------+ //| Log Gamma asymptotic expansion for large values of x | //| Uses Stirling's approximation to prevent overflow on large input | //+------------------------------------------------------------------+ double lgam_large_x(double x) { const double LS2PI = 0.91893853320467274178; // Logarithm of sqrt(2*PI) double q = (x - 0.5) * log(x) - x + LS2PI; // If x is massively large, additional fraction expansions drop below precision limits if(x > 1.0e8) { return (q); } // Polynomial correction factor optimization double p = 1.0 / (x * x); p = ((7.9365079365079365079365e-4 * p - 2.7777777777777777777778e-3) * p + 0.0833333333333333333333) / x; return q + p; } //+------------------------------------------------------------------+ //| Horner's Method Polynomial Evaluation | //| Evaluates standard algebraic polynomials given standard coefficients| //+------------------------------------------------------------------+ double polevl(double x, double &coef[], int N) { double ans; int i; int p; p = 0; ans = coef[p++]; i = N; do { ans = ans * x + coef[p++]; } while(--i != 0); return (ans); } //+------------------------------------------------------------------+ //| Horner's Method Variant for Monic Polynomials | //| Polynomial evaluation with assumptions that the highest order | //| coefficient equals 1. | //+------------------------------------------------------------------+ double p1evl(double x, double &coef[], int N) { double ans; uint p; int i; p = 0; ans = x + coef[p++]; i = N - 1; do ans = ans * x + coef[p++]; while(--i != 0); return (ans); } //+------------------------------------------------------------------+ //| Sign-aware Log Gamma Calculation | //| Computes ln(|Gamma(x)|) and returns the sign of Gamma(x) via ref.| //+------------------------------------------------------------------+ double lgam_sgn(double x, int &sign) { double p, q, u, w, z; int i; const double LS2PI = 0.91893853320467274178; const double MAXLGM = 2.556348e305; // Guard rails for double numeric limitations // Coefficients for minimax approximations over specific scalar domains double gamma_A[] = { 8.11614167470508450300E-4, -5.95061904284301438324E-4, 7.93650340457716943945E-4, -2.77777777730099687205E-3, 8.33333333333331927722E-2 }; double gamma_B[] = { -1.37825152569120859100E3, -3.88016315134637840924E4, -3.31612992738871184744E5, -1.16237097492762307383E6, -1.72173700820839662146E6, -8.53555664245765465627E5 }; double gamma_C[] = { -3.51815701436523470549E2, -1.70642106651881159223E4, -2.20528590553854454839E5, -1.13933444367982507207E6, -2.53252307177582951285E6, -2.01889141433532773231E6 }; sign = 1; // Reject NaNs or Infinite structures immediately if(MathClassify(x)!=FP_NORMAL) { return x; } // Use Reflection Formula transformation principles for highly negative inputs if(x < -34.0) { q = -x; w = lgam_sgn(q, sign); p = floor(q); if(p == q) { Print(__FUNCTION__, " singular error "); return (double("inf")); // Gamma undefined for negative integers } i = (int)p; if((i & 1) == 0) { sign = -1; } else { sign = 1; } z = q - p; if(z > 0.5) { p += 1.0; z = p - q; } z = q * sinpi(z); if(z == 0.0) { Print(__FUNCTION__, " singular error "); return (double("inf")); } z = log(M_PI) - log(z) - w; return (z); } // For small to mid ranges, recurse and rely on rational evaluations if(x < 13.0) { z = 1.0; p = 0.0; u = x; while(u >= 3.0) { p -= 1.0; u = x + p; z *= u; } while(u < 2.0) { if(u == 0.0) { Print(__FUNCTION__, " singular error "); return (double("inf")); } z /= u; p += 1.0; u = x + p; } if(z < 0.0) { sign = -1; z = -z; } else { sign = 1; } if(u == 2.0) { return (log(z)); } p -= 2.0; x = x + p; p = x * polevl(x, gamma_B, 5) / p1evl(x, gamma_C, 6); return (log(z) + p); } // Handle large inputs via Stirling scaling variations if(x>MAXLGM) return sign*double("inf"); if(x>=1000.) return lgam_large_x(x); q = (x-0.5)*log(x) - x +LS2PI; p = 1./(x*x); return q+polevl(p,gamma_A,4)/x; } //+-------------------------------------------------------------------------+ //| Asymptotic expansion for ln(|B(a, b)|) for a > ASYMP_FACTOR*max(|b|, 1) | //| Prevents serious cancellation precision losses when parameters differ | //| significantly by magnitude scale. | //+-------------------------------------------------------------------------+ double lbeta_asymp(double a, double b, int &sgn) { double r = lgam_sgn(b, sgn); r -= b * log(a); // Infinite series correction structures r += b * (1 - b) / (2 * a); r += b * (1 - b) * (1 - 2 * b) / (12 * a * a); r += -b * b * (1 - b) * (1 - b) / (12 * a * a * a); return r; } //+------------------------------------------------------------------+ //| Special case Beta handling for negative integer inputs | //+------------------------------------------------------------------+ double beta_negint(int a, double b) { int sgn; if(b == int(b) && 1 - a - b > 0) { sgn = (MathMod(b, 2) == 0) ? 1 : -1; return sgn * CBetaF::Beta(1. - a - b, b); } else { Print(__FUNCTION__, " overflow error "); return double("inf"); } } //+------------------------------------------------------------------+ //| Special case Log Beta handling for negative integers | //+------------------------------------------------------------------+ double lbeta_negint(int a, double b) { double r; if(b == int(b) && 1 - a - b > 0) { r = lbeta(1 - a - b, b); return r; } else { Print(__FUNCTION__, " overflow error "); return double("inf"); } } //+------------------------------------------------------------------+ //| Log Beta Function: ln(B(a,b)) | //| Handles reflection limits, variable sorting, and asymptotic scaling| //+------------------------------------------------------------------+ double lbeta(double a, double b) { double y; int sign; const double MAXGAM = 171.624376956302725; // Standard double precision cutoff limit for basic gamma const double beta_ASYMP_FACTOR = 1e6; sign = 1; // Process negative or integer domain transitions for 'a' if(a <= 0.0) { if(a == floor(a)) { if(a == int(a)) { return lbeta_negint(int(a), b); } else { Print(__FUNCTION__, " overflow error "); return (sign * double("inf")); } } } // Process negative or integer domain transitions for 'b' if(b <= 0.0) { if(b == floor(b)) { if(b == int(b)) { return lbeta_negint(int(b), a); } else { Print(__FUNCTION__, " overflow error "); return (sign * double("inf")); } } } // Enforce optimization symmetry mapping (a >= b) if(MathAbs(a) < MathAbs(b)) { y = a; a = b; b = y; } // Deploy specialized fast asymptotic formulas if a is dramatically larger than b if(MathAbs(a) > beta_ASYMP_FACTOR * MathAbs(b) && a > beta_ASYMP_FACTOR) { /* Avoid loss of precision in lgam(a + b) - lgam(a) */ y = lbeta_asymp(a, b, sign); return y; } // Use Log Gamma components directly if standard values bypass safe range thresholds y = a + b; if(MathAbs(y) > MAXGAM || MathAbs(a) > MAXGAM || MathAbs(b) > MAXGAM) { int sgngam; y = lgam_sgn(y, sgngam); sign *= sgngam; /* keep track of the sign */ y = lgam_sgn(b, sgngam) - y; sign *= sgngam; y = lgam_sgn(a, sgngam) + y; sign *= sgngam; return (y); } // Direct native calculation if arguments fit inside reliable evaluation limits y = CGammaFunc::GammaFunc(y); a = CGammaFunc::GammaFunc(a); b = CGammaFunc::GammaFunc(b); if(y == 0.0) { Print(__FUNCTION__, " overflow error "); return (sign * double("inf")); } // Dynamic ratio factorization balancing to maximize float precision accuracy if(MathAbs(MathAbs(a) - MathAbs(y)) > MathAbs(MathAbs(b) - MathAbs(y))) { y = b / y; y *= a; } else { y = a / y; y *= b; } if(y < 0) { y = -y; } return (log(y)); } //+------------------------------------------------------------------+ //| Generalized Binomial Coefficient calculation | //| Computes combinations allowing real parameters (n choose k) | //+------------------------------------------------------------------+ double binom(double n, double k) { double kx,nx,num, den, dk, sgn; // Undefined conditions validation if(n < 0) { nx = floor(n); if(n == nx) { return double("nan"); // Undefined for negative integer 'n' } } kx = floor(k); // Optimization layer targeting standard small integer fields if(k == kx && (MathAbs(n) > 1e-8 || n == 0)) { nx = floor(n); if(nx == n && kx > nx / 2 && nx > 0) { // Reduce kx using identity properties of symmetry kx = nx - kx; } // Explicit iterative loops for low ranges if(kx >= 0 && kx < 20) { num = 1.0; den = 1.0; for(int i = 1; i < 1 + int(kx); i++) { num *= i + n - kx; den *= i; // Balance scale to check overflow mid-loop if(MathAbs(num) > 1e50) { num /= den; den = 1.0; } } return num / den; } } // General Log-Beta path logic for large scales to minimize overflow if(n >= 1e10 * k && k > 0) { return exp(-lbeta(1 + n - k, 1 + k) - log(n + 1)); } // Approximation mechanisms for extremely large indices using Sine reflection properties if(k > 1e8 * MathAbs(n)) { num = CGammaFunc::GammaFunc(1 + n) / MathAbs(k) + CGammaFunc::GammaFunc(1 + n) * n / (2 * k * k); num /= M_PI * pow(MathAbs(k), n); if(k > 0) { kx = floor(k); if(int(kx) == kx) { dk = k - kx; sgn = (MathMod(int(kx), 2) == 0) ? 1 : -1; } else { dk = k; sgn = 1; } return num * sin((dk - n) * M_PI) * sgn; } kx = floor(k); if(int(kx) == kx) { return 0; } return num * sin(k * M_PI); } return 1 / (n + 1) / CBetaF::Beta(1 + n - k, 1 + k); } //+------------------------------------------------------------------+ //| Combination Count interface: N choose K | //| Supports variations containing exact matching or repetition paths| //+------------------------------------------------------------------+ template T comb(ulong N, T k, bool exact=false, bool repetition = false) { // Handle combinations with replacements allowed if(repetition) return comb(N+ulong(k)-1,(T)k,exact); if(exact) return comb(N,k); else { // Boundary error protection evaluation bool cond = false; cond = ((k<=T(N)) && (N>=0) && (k>=0)); T val = (T)binom(double(N),double(k)); if(!cond) val = 0; // Return zero for mathematically invalid constraints return val; } } //+------------------------------------------------------------------+ //| Compute the kurtosis (Fisher or Pearson) of a dataset | //+------------------------------------------------------------------+ double kurtosis(vector& in,bool fisher=true, bool bias=true) { ulong n = in.Size(); double out; double mean = in.Mean(); double m2 = moment(in,2,mean); // 2nd Moment (Variance) double m4 = moment(in,4,mean); // 4th Moment // Guard logic against zero-variance inputs bool zero = (m2<= pow(mean*2.e-16,2.)); out = (!zero)?m4/pow(m2,2.):double("nan"); // Strip biases for small sample profiles if flagged if(!bias) { bool cancorrect = (~zero&(n>3)); double nval = 1.0/(n-2)/(n-3) * ((pow(n,2)-1.0)*m4/pow(m2,2.0) - 3*pow((n-1),2.0)); if(cancorrect) out = nval + 3.; else out = double("nan"); } // Convert from Pearson default format to Fisher excess metrics if flagged if(fisher) out = out - 3.; return out; } //+------------------------------------------------------------------+ //| Get Element-wise Vector Maximum | //| Returns a vector containing the largest item at matching steps | //+------------------------------------------------------------------+ vector maximum(vector &x, vector &y) { if(x.Size()!=y.Size()) { Print(__FUNCTION__, " vector size mismatch "); return vector::Zeros(0); } // Bundle both inputs horizontally to evaluate row-wise metrics matrix xy(x.Size(),2); if(!xy.Col(x,0) || !xy.Col(y,1)) { Print(__FUNCTION__, " column insertion error ", GetLastError()); return vector::Zeros(0); } return xy.Max(1); // Column axis evaluation } //+------------------------------------------------------------------+ //| Get Element-wise Vector Minimum | //| Returns a vector containing the smallest item at matching steps | //+------------------------------------------------------------------+ vector minimum(vector &x, vector &y) { if(x.Size()!=y.Size()) { Print(__FUNCTION__, " vector size mismatch "); return vector::Zeros(0); } matrix xy(x.Size(),2); if(!xy.Col(x,0) || !xy.Col(y,1)) { Print(__FUNCTION__, " column insertion error ", GetLastError()); return vector::Zeros(0); } return xy.Min(1); } //+------------------------------------------------------------------+ //| Get Element-wise Vector/Scalar Maximum | //+------------------------------------------------------------------+ vector maximum(vector &x, double v) { vector y(x.Size()); y.Fill(v); matrix xy(x.Size(),2); if(!xy.Col(x,0) || !xy.Col(y,1)) { Print(__FUNCTION__, " column insertion error ", GetLastError()); return vector::Zeros(0); } return xy.Max(1); } //+------------------------------------------------------------------+ //| Get Element-wise Vector/Scalar Minimum | //+------------------------------------------------------------------+ vector minimum(vector &x, double v) { vector y(x.Size()); y.Fill(v); matrix xy(x.Size(),2); if(!xy.Col(x,0) || !xy.Col(y,1)) { Print(__FUNCTION__, " column insertion error ", GetLastError()); return vector::Zeros(0); } return xy.Min(1); } //+------------------------------------------------------------------+ //| Return mask highlighting matching NaN conditions | //+------------------------------------------------------------------+ template vector whereIsNan(vector& in) { ulong any = in.HasNan(); if(any) { vector out = vector::Zeros(any); ulong count = 0; for(ulong i = 0; i vector whereIsNotNan(vector& in) { ulong any = in.HasNan(); if(any) { vector out = vector::Zeros(in.Size() - any); ulong count = 0; for(ulong i = 0; i matrix toeplitz(vector& x) { ulong n = x.Size(); matrix out(n,n); for(ulong i = 0; icuttoff[i]) s[i] = 1./s[i]; else s[i] = 0.0; // Reconstruct inversion states via matrix composition maps (V * S_inv * U^T) matrix mats = matrix::Zeros(s.Size(),1); mats.Col(s,0); matrix vm = multiply(u.Transpose(),s); return v.Transpose().MatMul(vm); } //+------------------------------------------------------------------+ //| Shuffle elements of a vector | //| Implements a random index permutation using the Fisher-Yates method| //+------------------------------------------------------------------+ template vector shuffleVector(vector &in,CHighQualityRandStateShell* rstate=NULL) { vectorout(in.Size()); bool destroy = false; // Instantiate local random state if caller did not supply one if(rstate == NULL) { destroy = true; rstate = new CHighQualityRandStateShell(); CHighQualityRand::HQRndRandomize(rstate.GetInnerObj()); } ulong k=0; ulong size=in.Size(); out=in; T tmp; // Perform element position swaps across uniform random distributions for(ulong i=0; i=size) k=size-1; tmp = out[i]; out[i]=out[k]; out[k]=tmp; } if(destroy) delete rstate; return out; } //+------------------------------------------------------------------+ //| Shuffle elements of an array | //+------------------------------------------------------------------+ template bool shuffleArray(T &in[],CHighQualityRandStateShell* rstate=NULL) { bool destroy = false; if(rstate == NULL) { destroy = true; rstate = new CHighQualityRandStateShell(); CHighQualityRand::HQRndRandomize(rstate.GetInnerObj()); } ulong k=0; uint size=in.Size(); T tmp; for(ulong i=0; i=size) k=size-1; tmp = in[i]; in[i]=in[k]; in[k]=tmp; } if(destroy) delete rstate; return true; } //+------------------------------------------------------------------+ //| Shuffle matrix components (either row-wise or column-wise) | //+------------------------------------------------------------------+ template matrix shuffleMatrix(matrix &in,bool by_rows=true,CHighQualityRandStateShell* rstate=NULL) { matrixout(in.Rows(), in.Cols()); bool destroy = false; if(rstate == NULL) { destroy = true; rstate = new CHighQualityRandStateShell(); CHighQualityRand::HQRndRandomize(rstate.GetInnerObj()); } ulong size=by_rows?in.Rows():in.Cols(); vector vec; out=in; // Process and re-inject vectors individually for(ulong i=0; i2) { // Slice vectors to compute partial values efficiently in blocks vector xm = sliceVector(x,1,long(x.Size()-1)); vector xm_m1 = sliceVector(x,0,long(x.Size()-2)); vector xm_p1 = sliceVector(x,2); vector temp = (200.0 * (xm - pow(xm_m1,2.0)) - 400.0 * (xm_p1 - pow(xm,2.0)) * xm - 2.0 * (1.0 - xm)); if(!vectorCopy(grad,temp,1,long(grad.Size()-1))) return vector::Zeros(0); } // Explicit derivative boundary conditions for head and tail variables grad[0] = -400.0 * x[0] * (x[1] - pow(x[0],2.0)) - 2.0 * (1.0 - x[0]); grad[grad.Size()-1] = 200.0 * (x[x.Size()-1] - pow(x[x.Size()-2],2.0)); return grad; } //+------------------------------------------------------------------+ //| Hessian Matrix of the Rosenbrock function | //| Constructs the square matrix of second-order partial derivatives. | //+------------------------------------------------------------------+ matrix rosen_hess(vector &x) { vector x1 = sliceVector(x,0,long(x.Size()-1)); vector x2 = sliceVector(x,1,long(x.Size()-1)); vector x3 = vector::Zeros(x.Size()); matrix h1,h2,h3,H; // Set up off-diagonal element bands if(!h1.Diag(-400.0*x1,1) || !h2.Diag(400.0*x1,-1)) { Print(__FUNCTION__, " error ", GetLastError()); return matrix::Zeros(0,0); } H = h1 - h2; // Calculate primary diagonal values x3[0] = 1200.0 * pow(x[0],2.0) - 400.0 * x[1] + 2.0; vector temp = 202.0 + 1200.0 * pow(x2,2) - 400.0 * sliceVector(x,2); x3[x3.Size()-1] = 200.0; if(!vectorCopy(x3,temp,1,long(x3.Size()-1))) return matrix::Zeros(0,0); if(!h3.Diag(x3)) { Print(__FUNCTION__, " error ", GetLastError()); return matrix::Zeros(0,0); } // Combine off-diagonal and main diagonal matrices to complete the Hessian return H+h3; } //+------------------------------------------------------------------+ //|Convert vector into either a column or row matrix | //+------------------------------------------------------------------+ template matrix asMatrix(vector& in , bool as_column_matrix = true) { // Prepare output matrix matrix mat = as_column_matrix?matrix::Zeros(in.Size(),1):matrix::Zeros(1,in.Size()); // Add vector to new matrix if((as_column_matrix && !mat.Col(in,0)) || (!as_column_matrix && !mat.Row(in,0))) { Print(__FUNCTION__," Row insertion failure ", GetLastError()); return matrix::Zeros(0,0); } // Return matrix return mat; } //+------------------------------------------------------------------+ //|Mahalanobis distance calculation | //+------------------------------------------------------------------+ double mahalanobis(vector& u,vector& v, matrix& VI) { //--- vector delta = u - v; //--- return sqrt((delta.MatMul(VI)).Dot(delta)); //--- } } //+------------------------------------------------------------------+