IN: sorting-internals
USING: kernel math sequences ;
-: midpoint ( seq -- elt ) dup length 2 /i swap nth ; inline
-
TUPLE: sorter seq start end mid ;
C: sorter ( seq start end -- sorter )
2drop
] ifte 2drop ; inline
+: partition ( seq -1/1 -- seq )
+ >r dup midpoint@ swap r> 1 <
+ [ head-slice ] [ tail-slice ] ifte ; inline
+
+: (binsearch) ( elt quot seq -- i )
+ dup length 1 <= [
+ 2nip slice-from
+ ] [
+ 3dup midpoint swap call dup 0 = [
+ drop 2nip dup slice-from swap slice-to + 2 /i
+ ] [
+ partition (binsearch)
+ ] ifte
+ ] ifte ; inline
+
+: binsearch-slice ( seq -- slice )
+ #! Binsearch returns an index relative to the sequence
+ #! being sliced, so if we are given a slice as input,
+ #! unexpected behavior will result.
+ dup slice? [ >vector ] when 0 over length rot <slice> ;
+ inline
+
IN: sequences
: nsort ( seq quot -- | quot: elt elt -- -1/0/1 )
: sort ( seq quot -- seq | quot: elt elt -- -1/0/1 )
swap [ swap nsort ] immutable ; inline
+
+: binsearch ( elt seq quot -- i | quot: elt elt -- -1/0/1 )
+ swap dup empty?
+ [ 3drop -1 ] [ binsearch-slice (binsearch) ] ifte ;
+ inline
+
+: binsearch-range ( from to seq quot -- from to )
+ [ binsearch ] 2keep rot >r binsearch r> ;
1000 [ drop 0 1000 random-int ] map [ - ] sort [ - ] sorted?
] all?
] unit-test
+
+[ -1 ] [ 3 { } [ - ] binsearch ] unit-test
+[ 0 ] [ 3 { 3 } [ - ] binsearch ] unit-test
+[ 1 ] [ 2 { 1 2 3 } [ - ] binsearch ] unit-test
+[ 3 ] [ 4 { 1 2 3 4 5 6 } [ - ] binsearch ] unit-test
+[ 1 ] [ 3.5 { 1 2 3 4 5 6 7 8 } [ - ] binsearch ] unit-test
+[ 3 ] [ 5.5 { 1 2 3 4 5 6 7 8 } [ - ] binsearch ] unit-test
+[ 10 ] [ 10 20 >vector [ - ] binsearch ] unit-test
FUNCTION: int err_no ( ) ;
LIBRARY: libc
-FUNCTION: char* strerror ( int ) ;
+FUNCTION: char* strerror ( int errno ) ;
FUNCTION: int open ( char* path, int flags, int prot ) ;
FUNCTION: void close ( int fd ) ;
FUNCTION: int fcntl ( int fd, int cmd, int arg ) ;