* Shell Sort (for 16-bit Elements)
* changes: 14.03.2005
/*
function ShellSort(arr,length) {
var j, i, v, h, k;
for (h=1; h < length; h=3*h+1);
while (h=(h-1)/3)
for (i=h, j=i, v=arr[i]; i<=length; arr[j+h]=v, i++, j=i, v=arr[i])
while((j-=h) >= 0 && arr[j] > v)
arr[j+h]=arr[j];
}
*/
org $2000 ; Start address.
v_plus_1 = $80
h = v_plus_1 + 2
arr_start = h + 2
j = $fb ; Uses two bytes. Has to be on zero-page
j_plus_h = $fd ; Uses two bytes. Has to be on zero-page
arr_length = j_plus_h ; Can safely use the same location as
; j_plus_h, but doesn't have to be on ZP
lda
table
jsr shell_sort
lda #$26
sta 712
loop jmp loop
/*
lda table
jsr shell_sort.insertion_sort
*/
.proc shell_sort
ldy #h_high-h_low-1
bne sort_main ; Always branch
insertion_sort ldy #0
sort_main sty h_start_index
cld
sta j
sta in_address
clc
adc #2
sta arr_start
stx j+1
stx in_address+1
txa
adc #0
sta arr_start+1
ldy #0
lda (j),y
sta arr_length
clc
adc arr_start
sta arr_end
iny
lda (j),y
sta arr_length+1
adc arr_start+1
sta arr_end+1
; for (h=1; h < length; h=3*h+1);
ldx h_start_index ; Start with highest value of h
chk_prev_h lda h_low,x
cmp arr_length
lda h_high,x
sbc arr_length+1
bcc end_of_init ; If h < array_length, we've found the right h
dex
bpl chk_prev_h
rts ; array length is 0 or 1. No sorting needed.
end_of_init inx
stx h_index
; while (h=(h-1)/3)
h_loop dec h_index
bpl get_h
rts ; All done!
get_h ldy h_index
lda h_low,y
sta h
clc
adc in_address ; ( in_address is arr_start - 2)
sta i
lda h_high,y
sta h+1
adc in_address+1
sta i+1
; for (i=h, j=i, v=arr[i]; i<=length; arr[j+h]=v, i++, j=i, v=arr[i])
i_loop lda i
clc
adc #2
sta i
sta j
lda i+1
adc #0
sta i+1
sta j+1
ldx i
cpx arr_end
lda i+1
sbc arr_end+1
bcs h_loop
ldy #0
lda (j),y
sta v
clc
adc #1
sta v_plus_1
iny
lda (j),y
sta v+1
adc #0
bcs i_loop ; v=$ffff, so no j-loop necessary
sta v_plus_1+1
dey ; Set y=0
; while((j-=h) >= 0 && arr[j] > v)
j_loop lda j
sta j_plus_h
sec
sbc h
sta j
tax
lda j+1
sta j_plus_h+1
sbc h+1
sta j+1
; Check if we've reached the bottom of the array
bcc exit_j_loop
cpx arr_start
sbc arr_start+1
bcc exit_j_loop
; Do the actual comparison: arr[j] > v
lda (j),y
tax
iny ; Set y=1
lda (j),y
cpx v_plus_1
sbc v_plus_1+1
bcc exit_j_loop
; arr[j+h]=arr[j];
lda (j),y
sta (j_plus_h),y
dey ; Set y=0
txa
sta (j_plus_h),y
bcs j_loop ; Always branch
; for (i=h, j=i, v=arr[i]; i2, >8, >26, >80, >242, >728, >2186, >6560, >19682
h_start_index .byte
h_index .byte
in_address .word
arr_end .word
i .word
v .word
.endp
/*
unsorted values (type WORD)
*/
org $bc40
table .word 960
.word rnd( 0 , $FFFF , 960 / 2 )
run $2000