1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
#!/usr/bin/env bash
if [[ ! ${BLE_VERSION-} ]]; then
source ../../src/benchmark.sh
fi
declare RANDSUP=32768
function fill-rand {
data=()
local i n=${1:-10000}
for ((i=0;i<n;i++)); do
data[i]=$RANDOM
done
}
function sort.command {
data=($(printf '%s\n' "${data[@]}"|sort -n))
}
function sort.qsort1.1 {
local L=$1 U=$2
local p=${data[L+RANDOM*(U-L)/RANDSUP]}
local i=$L j=$((U-1)) t
while :; do
while ((data[i]<p)); do ((i++)); done
while ((i<j&&p<=data[j])); do ((j--)); done
((i<j)) || break
((t=data[i],data[i++]=data[j],data[j--]=t))
done
while ((data[j]==p)); do ((j++)); done
#((j++))
((L+1<i)) && sort.qsort1.1 "$L" "$i"
((j+1<U)) && sort.qsort1.1 "$j" "$U"
}
function sort.qsort1 {
local L=0 U=${#data[@]}
((L+1<U)) && sort.qsort1.1 "$L" "$U"
}
#------------------------------------------------------------------------------
function sort.qsort3.1 {
local L=$1 U=$2
local length=$((U-L))
if ((length<=1)); then
return 0
elif ((length==2)); then
local a=${data[L]} b=${data[L+1]}
if ((a>b)); then
data[L]=$b
data[L+1]=$a
fi
return 0
elif ((length==3)); then
local a=${data[L]} b=${data[L+1]} c=${data[L+2]}
if ((b<a)); then
if ((a<c)); then # bac
data[L]=$b data[L+1]=$a
elif ((b<c)); then # bca
data[L]=$b data[L+1]=$c data[L+2]=$a
else # cba
data[L]=$c data[L+2]=$a
fi
else # ab
if ((c<a)); then # cab
data[L]=$c data[L+1]=$a data[L+2]=$b
elif ((c<b)); then # acb
data[L+1]=$c data[L+2]=$b
fi
fi
elif ((length==4)); then
local a=${data[L]} b=${data[L+1]} c=${data[L+2]} d=${data[L+3]}
((b<a)) && local a=$b b=$a
((d<c)) && local c=$d d=$c
if ((a<c)); then
#a|b,cd
if ((b<c)); then # abcd
data[L]=$a data[L+1]=$b data[L+2]=$c data[L+3]=$d
elif ((b<d)); then # acbd
data[L]=$a data[L+1]=$c data[L+2]=$b data[L+3]=$d
else # acdb
data[L]=$a data[L+1]=$c data[L+2]=$d data[L+3]=$b
fi
else
#c|ab,d
if ((d<a)); then # cdab
data[L]=$c data[L+1]=$d data[L+2]=$a data[L+3]=$b
elif ((d<b)); then # cadb
data[L]=$c data[L+1]=$a data[L+2]=$d data[L+3]=$b
else # cabd
data[L]=$c data[L+1]=$a data[L+2]=$b data[L+3]=$d
fi
fi
elif ((length<=64)); then
local M=$((L+length/2))
sort.qsort3.1 "$L" "$M"
sort.qsort3.1 "$M" "$U"
# merge
local index=$L lhs rhs out=
for rhs in "${data[@]:M:U-M}"; do
while ((index<M&&(lhs=data[index])<rhs)); do
out="$out $lhs"
((index++))
done
out="$out $rhs"
done
out="$out ${data[*]:index:M-index}"
data=("${data[@]::L}" $out "${data[@]:U}")
else #elif ((length<10)); then
# quick sort
local L=$1 U=$2
local p=${data[L+RANDOM*(U-L)/RANDSUP]}
local i=$L j=$((U-1)) t
while :; do
while ((data[i]<p)); do ((i++)); done
while ((i<j&&p<=data[j])); do ((j--)); done
((i<j)) || break
((t=data[i],data[i++]=data[j],data[j--]=t))
done
while ((data[j]==p)); do ((j++)); done
#((j++))
((L+1<i)) && sort.qsort3.1 "$L" "$i"
((j+1<U)) && sort.qsort3.1 "$j" "$U"
fi
}
function sort.qsort3 {
local L=0 U=${#data[@]}
((L+1<U)) && sort.qsort3.1 "$L" "$U"
}
#------------------------------------------------------------------------------
function sort.array {
local -a dict
local a dup=0
for a in "${data[@]}"; do ((dict[a]++&&dup++)); done
if ((dup)); then
# 重複があると駄目…
data=()
for a in "${!dict[@]}"; do
for ((i=0;i<dict[a];i++)); do
data+=("$a")
done
done
else
data=("${!dict[@]}")
fi
}
#------------------------------------------------------------------------------
function sort._insert {
local L=${1:-0} U=${2:-${#data[@]}}
for ((i=L+1;i<U;i++)); do
for ((j=i;j>L;j--)); do
((data[j-1]<=data[j])) && break
# ■
done
done
}
# fill-rand
# declare -p data
# sort.command
# declare -p data
ble-measure 'fill-rand'
ble-measure 'fill-rand && sort.qsort1'
ble-measure 'fill-rand && sort.qsort3'
ble-measure 'fill-rand && sort.command'
ble-measure 'fill-rand && sort.array'
function check-sort-algorithm {
local algorithm=$1
local i
for ((i=0;i<100;i++)); do
fill-rand
eval "$algorithm"
prev=${data[0]}
for v in "${data[@]}"; do
((prev<=v)) || return 1
prev=$v
done
done
}
#check-sort-algorithm sort.qsort1 || echo failed
#check-sort-algorithm sort.qsort3 || echo failed
#------------------------------------------------------------------------------
# swap の速度
#
# 長さ2の配列の swap は data=(...) の方が速い
# 長さ2の配列の swap は t=${data[0]} data[0]=${data[1]} data[1]=$t の方が速い
#
# data=(4321 1324)
# ble-measure 'local t=${data[0]}; data[0]=${data[1]}; data[1]=$t' # 5.88u(chat)
# ble-measure 'data=("${data[1]}" "${data[0]}")' # 4.88u(chat)
# data=(4321 123 1324)
# ble-measure 'local t=${data[0]}; data[0]=${data[2]}; data[2]=$t' # 5.88u(chat)
# ble-measure 'data=("${data[2]}" "${data[1]}" "${data[0]}")' # 4.88u(chat)
|