mirror of
https://github.com/BelfrySCAD/BOSL2.git
synced 2025-01-01 09:49:45 +00:00
Optimize sorting
Optimize _sort_general and change accordingly sort and sortidx. Introduce _valid_idx() to simplify teh validations of arg idx. Add input validation to subindex().
This commit is contained in:
parent
e06519bbfb
commit
c6b472318f
1 changed files with 53 additions and 68 deletions
121
arrays.scad
121
arrays.scad
|
@ -709,40 +709,36 @@ function _sort_vectors4(arr) =
|
||||||
) concat( _sort_vectors4(lesser), equal, _sort_vectors4(greater) );
|
) concat( _sort_vectors4(lesser), equal, _sort_vectors4(greater) );
|
||||||
|
|
||||||
|
|
||||||
|
// when idx==undef, returns the sorted array
|
||||||
|
// otherwise, returns the indices of the sorted array
|
||||||
function _sort_general(arr, idx=undef) =
|
function _sort_general(arr, idx=undef) =
|
||||||
(len(arr)<=1) ? arr :
|
(len(arr)<=1) ? arr :
|
||||||
|
is_undef(idx)
|
||||||
|
? _sort_scalar(arr)
|
||||||
|
: let( arrind=[for(k=[0:len(arr)-1], ark=[arr[k]]) [ k, [for (i=idx) ark[i]] ] ] )
|
||||||
|
_indexed_sort(arrind);
|
||||||
|
|
||||||
|
// given a list of pairs, return the first element of each pair of the list sorted by the second element of the pair
|
||||||
|
// the sorting is done using compare_vals()
|
||||||
|
function _indexed_sort(arrind) =
|
||||||
|
arrind==[] ? [] : len(arrind)==1? [arrind[0][0]] :
|
||||||
|
let( pivot = arrind[floor(len(arrind)/2)][1] )
|
||||||
let(
|
let(
|
||||||
pivot = arr[floor(len(arr)/2)],
|
lesser = [ for (entry=arrind) if (compare_vals(entry[1], pivot) <0 ) entry ],
|
||||||
pivotval = idx==undef? pivot : [for (i=idx) pivot[i]],
|
equal = [ for (entry=arrind) if (compare_vals(entry[1], pivot)==0 ) entry[0] ],
|
||||||
compare =
|
greater = [ for (entry=arrind) if (compare_vals(entry[1], pivot) >0 ) entry ]
|
||||||
is_undef(idx) ? [for(entry=arr) compare_vals(entry, pivotval) ] :
|
)
|
||||||
[ for (entry = arr)
|
concat(_indexed_sort(lesser), equal, _indexed_sort(greater));
|
||||||
let( val = [for (i=idx) entry[i] ] )
|
|
||||||
compare_vals(val, pivotval) ] ,
|
|
||||||
lesser = [ for (i = [0:1:len(arr)-1]) if (compare[i] < 0) arr[i] ],
|
|
||||||
equal = [ for (i = [0:1:len(arr)-1]) if (compare[i] ==0) arr[i] ],
|
|
||||||
greater = [ for (i = [0:1:len(arr)-1]) if (compare[i] > 0) arr[i] ]
|
|
||||||
)
|
|
||||||
concat(_sort_general(lesser,idx), equal, _sort_general(greater,idx));
|
|
||||||
|
|
||||||
|
|
||||||
function _sort_general(arr, idx=undef) =
|
// returns true for valid index specifications idx in the interval [imin, imax)
|
||||||
(len(arr)<=1) ? arr :
|
// note that idx can't have any value greater or EQUAL to imax
|
||||||
let(
|
function _valid_idx(idx,imin,imax) =
|
||||||
pivot = arr[floor(len(arr)/2)],
|
is_undef(idx)
|
||||||
pivotval = idx==undef? pivot : [for (i=idx) pivot[i]],
|
|| ( is_finite(idx) && idx>=imin && idx< imax )
|
||||||
compare = [
|
|| ( is_list(idx) && min(idx)>=imin && max(idx)< imax )
|
||||||
for (entry = arr) let(
|
|| ( valid_range(idx) && idx[0]>=imin && idx[2]< imax );
|
||||||
val = idx==undef? entry : [for (i=idx) entry[i]],
|
|
||||||
cmp = compare_vals(val, pivotval)
|
|
||||||
) cmp
|
|
||||||
],
|
|
||||||
lesser = [ for (i = [0:1:len(arr)-1]) if (compare[i] < 0) arr[i] ],
|
|
||||||
equal = [ for (i = [0:1:len(arr)-1]) if (compare[i] ==0) arr[i] ],
|
|
||||||
greater = [ for (i = [0:1:len(arr)-1]) if (compare[i] > 0) arr[i] ]
|
|
||||||
)
|
|
||||||
concat(_sort_general(lesser,idx), equal, _sort_general(greater,idx));
|
|
||||||
|
|
||||||
|
|
||||||
// Function: sort()
|
// Function: sort()
|
||||||
// Usage:
|
// Usage:
|
||||||
|
@ -761,19 +757,21 @@ function _sort_general(arr, idx=undef) =
|
||||||
// sorted = sort(l); // Returns [2,3,8,9,12,16,23,34,37,45,89]
|
// sorted = sort(l); // Returns [2,3,8,9,12,16,23,34,37,45,89]
|
||||||
function sort(list, idx=undef) =
|
function sort(list, idx=undef) =
|
||||||
!is_list(list) || len(list)<=1 ? list :
|
!is_list(list) || len(list)<=1 ? list :
|
||||||
assert( is_undef(idx) || is_finite(idx) || is_vector(idx) || is_range(idx) , "Invalid indices.")
|
is_def(idx)
|
||||||
is_def(idx) ? _sort_general(list,idx) :
|
? assert( _valid_idx(idx,0,len(list)) , "Invalid indices.")
|
||||||
let(size = array_dim(list))
|
let( sarr = _sort_general(list,idx) )
|
||||||
len(size)==1 ? _sort_scalars(list) :
|
[for(i=[0:len(sarr)-1]) list[sarr[i]] ]
|
||||||
len(size)==2 && size[1] <=4
|
: let(size = array_dim(list))
|
||||||
? (
|
len(size)==1 ? _sort_scalars(list) :
|
||||||
size[1]==0 ? list :
|
len(size)==2 && size[1] <=4
|
||||||
size[1]==1 ? _sort_vectors1(list) :
|
? (
|
||||||
size[1]==2 ? _sort_vectors2(list) :
|
size[1]==0 ? list :
|
||||||
size[1]==3 ? _sort_vectors3(list)
|
size[1]==1 ? _sort_vectors1(list) :
|
||||||
/*size[1]==4*/ : _sort_vectors4(list)
|
size[1]==2 ? _sort_vectors2(list) :
|
||||||
)
|
size[1]==3 ? _sort_vectors3(list)
|
||||||
: _sort_general(list);
|
/*size[1]==4*/ : _sort_vectors4(list)
|
||||||
|
)
|
||||||
|
: _sort_general(list);
|
||||||
|
|
||||||
|
|
||||||
// Function: sortidx()
|
// Function: sortidx()
|
||||||
|
@ -799,13 +797,13 @@ function sort(list, idx=undef) =
|
||||||
// idxs3 = sortidx(lst, idx=[1,3]); // Returns: [3,0,2,1]
|
// idxs3 = sortidx(lst, idx=[1,3]); // Returns: [3,0,2,1]
|
||||||
function sortidx(list, idx=undef) =
|
function sortidx(list, idx=undef) =
|
||||||
assert( is_list(list) || is_string(list) , "Invalid input to sort." )
|
assert( is_list(list) || is_string(list) , "Invalid input to sort." )
|
||||||
assert( is_undef(idx) || is_finite(idx) || is_vector(idx) , "Invalid indices.")
|
assert( _valid_idx(idx,0,len(list)) , "Invalid indices.")
|
||||||
list==[] ? [] :
|
list==[] ? [] :
|
||||||
let(
|
let(
|
||||||
size = array_dim(list),
|
size = array_dim(list),
|
||||||
aug = is_undef(idx) && (len(size) == 1 || (len(size) == 2 && size[1]<=4))
|
aug = is_undef(idx) && (len(size) == 1 || (len(size) == 2 && size[1]<=4))
|
||||||
? zip(list, list_range(len(list)))
|
? zip(list, list_range(len(list)))
|
||||||
: enumerate(list,idx=idx)
|
: 0
|
||||||
)
|
)
|
||||||
is_undef(idx) && len(size) == 1? subindex(_sort_vectors1(aug),1) :
|
is_undef(idx) && len(size) == 1? subindex(_sort_vectors1(aug),1) :
|
||||||
is_undef(idx) && len(size) == 2 && size[1] <=4
|
is_undef(idx) && len(size) == 2 && size[1] <=4
|
||||||
|
@ -817,27 +815,9 @@ function sortidx(list, idx=undef) =
|
||||||
/*size[1]==4*/ : subindex(_sort_vectors4(aug),4)
|
/*size[1]==4*/ : subindex(_sort_vectors4(aug),4)
|
||||||
)
|
)
|
||||||
: // general case
|
: // general case
|
||||||
subindex(_sort_general(aug, idx=list_range(s=1,n=len(aug)-1)), 0);
|
_sort_general(list,idx);
|
||||||
|
|
||||||
|
|
||||||
function sortidx(list, idx=undef) =
|
|
||||||
list==[] ? [] : let(
|
|
||||||
size = array_dim(list),
|
|
||||||
aug = is_undef(idx) && (len(size) == 1 || (len(size) == 2 && size[1]<=4))?
|
|
||||||
zip(list, list_range(len(list))) :
|
|
||||||
enumerate(list,idx=idx)
|
|
||||||
)
|
|
||||||
is_undef(idx) && len(size) == 1? subindex(_sort_vectors1(aug),1) :
|
|
||||||
is_undef(idx) && len(size) == 2 && size[1] <=4? (
|
|
||||||
size[1]==0? list_range(len(arr)) :
|
|
||||||
size[1]==1? subindex(_sort_vectors1(aug),1) :
|
|
||||||
size[1]==2? subindex(_sort_vectors2(aug),2) :
|
|
||||||
size[1]==3? subindex(_sort_vectors3(aug),3) :
|
|
||||||
/*size[1]==4*/ subindex(_sort_vectors4(aug),4)
|
|
||||||
) :
|
|
||||||
// general case
|
|
||||||
subindex(_sort_general(aug, idx=list_range(s=1,n=len(aug)-1)), 0);
|
|
||||||
|
|
||||||
// sort() does not accept strings but sortidx does; isn't inconsistent ?
|
// sort() does not accept strings but sortidx does; isn't inconsistent ?
|
||||||
|
|
||||||
|
|
||||||
|
@ -911,10 +891,10 @@ function idx(list, step=1, end=-1,start=0) =
|
||||||
// for (p=enumerate(colors)) right(20*p[0]) color(p[1]) circle(d=10);
|
// for (p=enumerate(colors)) right(20*p[0]) color(p[1]) circle(d=10);
|
||||||
function enumerate(l,idx=undef) =
|
function enumerate(l,idx=undef) =
|
||||||
assert(is_list(l)||is_string(list), "Invalid input." )
|
assert(is_list(l)||is_string(list), "Invalid input." )
|
||||||
assert(is_undef(idx)||is_finite(idx)||is_vector(idx) ||is_range(idx), "Invalid index/indices." )
|
assert( _valid_idx(idx,0,len(l)), "Invalid index/indices." )
|
||||||
(idx==undef)
|
(idx==undef)
|
||||||
? [for (i=[0:1:len(l)-1]) [i,l[i]]]
|
? [for (i=[0:1:len(l)-1]) [i,l[i]]]
|
||||||
: [for (i=[0:1:len(l)-1]) concat([i], [for (j=idx) l[i][j]])];
|
: [for (i=[0:1:len(l)-1]) [ i, for (j=idx) l[i][j]] ];
|
||||||
|
|
||||||
|
|
||||||
// Function: force_list()
|
// Function: force_list()
|
||||||
|
@ -1130,8 +1110,9 @@ function add_scalar(v,s) =
|
||||||
// subindex(M, idx)
|
// subindex(M, idx)
|
||||||
// Description:
|
// Description:
|
||||||
// Extracts the entries listed in idx from each entry in M. For a matrix this means
|
// Extracts the entries listed in idx from each entry in M. For a matrix this means
|
||||||
// selecting a specified set of columsn. If idx is a number the return is a vector, otherwise
|
// selecting a specified set of columns. If idx is a number the return is a vector,
|
||||||
// it is a list of lists (the submatrix).
|
// otherwise it is a list of lists (the submatrix).
|
||||||
|
// This function will return `undef` at all entry positions indexed by idx not found in the input list M.
|
||||||
// Arguments:
|
// Arguments:
|
||||||
// M = The given list of lists.
|
// M = The given list of lists.
|
||||||
// idx = The index, list of indices, or range of indices to fetch.
|
// idx = The index, list of indices, or range of indices to fetch.
|
||||||
|
@ -1141,8 +1122,12 @@ function add_scalar(v,s) =
|
||||||
// subindex(M,[2]); // Returns [[3], [7], [11], [15]]
|
// subindex(M,[2]); // Returns [[3], [7], [11], [15]]
|
||||||
// subindex(M,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]]
|
// subindex(M,[2,1]); // Returns [[3, 2], [7, 6], [11, 10], [15, 14]]
|
||||||
// subindex(M,[1:3]); // Returns [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]]
|
// subindex(M,[1:3]); // Returns [[2, 3, 4], [6, 7, 8], [10, 11, 12], [14, 15, 16]]
|
||||||
|
// N = [ [1,2], [3], [4,5], [6,7,8] ];
|
||||||
|
// subindex(N,[0,1]); // Returns [ [1,2], [3,undef], [4,5], [6,7] ]
|
||||||
function subindex(M, idx) =
|
function subindex(M, idx) =
|
||||||
is_num(idx)
|
assert( is_list(M), "The input is not a list." )
|
||||||
|
assert( !is_undef(idx) && _valid_idx(idx,0,1/0), "Invalid index input." )
|
||||||
|
is_finite(idx)
|
||||||
? [for(row=M) row[idx]]
|
? [for(row=M) row[idx]]
|
||||||
: [for(row=M) [for(i=idx) row[i]]];
|
: [for(row=M) [for(i=idx) row[i]]];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue