insert sorted, return tuple instead of strange signed index from binary search methods
This commit is contained in:
parent
1a4055a69a
commit
cd21ecb782
|
|
@ -21,6 +21,7 @@ global vec_get
|
||||||
global vec_drop
|
global vec_drop
|
||||||
global vec_find
|
global vec_find
|
||||||
global vec_insert
|
global vec_insert
|
||||||
|
global vec_insert_sorted
|
||||||
global vec_binary_search_by
|
global vec_binary_search_by
|
||||||
|
|
||||||
global vec_tests
|
global vec_tests
|
||||||
|
|
@ -507,7 +508,7 @@ vec_insert:
|
||||||
;; rsi: pointer to key
|
;; rsi: pointer to key
|
||||||
;; rdx: compare function fn(ctx: *const (), a: *const T, b: *const T) -> i32
|
;; rdx: compare function fn(ctx: *const (), a: *const T, b: *const T) -> i32
|
||||||
;; rcx: compare_fn context
|
;; rcx: compare_fn context
|
||||||
;;fn vec_binary_search_by(vec: *mut Vec, key: *const T, compare: fn(ctx: *const (), a: *const T, b: *const T) -> i32, ctx: *const ()) -> isize
|
;;fn vec_binary_search_by(vec: *mut Vec, key: *const T, compare: fn(ctx: *const (), a: *const T, b: *const T) -> i32, ctx: *const ()) -> (usize, bool)
|
||||||
vec_binary_search_by:
|
vec_binary_search_by:
|
||||||
push rbp
|
push rbp
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
|
|
@ -518,6 +519,7 @@ vec_binary_search_by:
|
||||||
mov [rsp + 0x18], rcx ; save compare fn context
|
mov [rsp + 0x18], rcx ; save compare fn context
|
||||||
|
|
||||||
mov rax, [rdi + 8] ; len
|
mov rax, [rdi + 8] ; len
|
||||||
|
dec rax ; high
|
||||||
mov qword [rsp + 0x20], 0 ; low
|
mov qword [rsp + 0x20], 0 ; low
|
||||||
mov [rsp + 0x28], rax ; mid
|
mov [rsp + 0x28], rax ; mid
|
||||||
mov [rsp + 0x30], rax ; high
|
mov [rsp + 0x30], rax ; high
|
||||||
|
|
@ -551,31 +553,55 @@ vec_binary_search_by:
|
||||||
; greater
|
; greater
|
||||||
mov rax, [rsp + 0x28] ; mid
|
mov rax, [rsp + 0x28] ; mid
|
||||||
inc rax
|
inc rax
|
||||||
|
mov [rsp + 0x28], rax ; mid
|
||||||
mov [rsp + 0x20], rax ; low = mid + 1
|
mov [rsp + 0x20], rax ; low = mid + 1
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.less:
|
.less:
|
||||||
mov rax, [rsp + 0x28] ; mid
|
mov rax, [rsp + 0x28] ; mid
|
||||||
|
cmp rax, 0
|
||||||
|
je .not_found ; if mid == 0, not found
|
||||||
dec rax
|
dec rax
|
||||||
mov [rsp + 0x30], rax ; high = mid - 1
|
mov [rsp + 0x30], rax ; high = mid - 1
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.found:
|
.found:
|
||||||
mov rax, [rsp + 0x28]
|
mov rax, [rsp + 0x28]
|
||||||
|
xor rdx, rdx
|
||||||
jmp .epilogue
|
jmp .epilogue
|
||||||
.not_found:
|
.not_found:
|
||||||
mov rax, [rsp + 0x20]
|
mov rax, [rsp + 0x28]
|
||||||
not rax
|
mov rdx, 1
|
||||||
|
|
||||||
.epilogue:
|
.epilogue:
|
||||||
add rsp, 0x40
|
add rsp, 0x40
|
||||||
pop rbp
|
pop rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;; rdi: pointer to Vec struct
|
||||||
|
;; rsi: pointer to key
|
||||||
|
;; rdx: compare function fn(ctx: *const (), a: *const T, b: *const T) -> i32
|
||||||
|
;; rcx: compare_fn context
|
||||||
|
;;fn vec_insert_sorted(vec: *mut Vec, key: *const T, compare: fn(ctx: *const (), a: *const T, b: *const T) -> i32, ctx: *const ()) -> (usize, bool)
|
||||||
|
vec_insert_sorted:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
sub rsp, 0x18
|
||||||
|
mov [rsp], rdi ; vec
|
||||||
|
mov [rsp + 8], rsi ; element ptr
|
||||||
|
call vec_binary_search_by
|
||||||
|
test rdx, rdx
|
||||||
|
jnz .insert
|
||||||
|
; element already exists
|
||||||
|
jmp .epilogue
|
||||||
|
.insert:
|
||||||
|
mov [rsp + 0x10], rax ; index
|
||||||
|
mov rdi, [rsp] ; vec
|
||||||
|
mov rsi, rax ; index
|
||||||
|
mov rdx, [rsp + 8] ; element ptr
|
||||||
|
call vec_insert
|
||||||
|
mov rax, [rsp + 0x10] ; index
|
||||||
|
mov rdx, 1 ; indicate inserted
|
||||||
|
|
||||||
|
.epilogue:
|
||||||
|
add rsp, 0x18
|
||||||
|
pop rbp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,7 @@ impl<T> VecT<T> {
|
||||||
fn push(&mut self, value: T) {
|
fn push(&mut self, value: T) {
|
||||||
let value = core::mem::ManuallyDrop::new(value);
|
let value = core::mem::ManuallyDrop::new(value);
|
||||||
unsafe {
|
unsafe {
|
||||||
vec_push(
|
vec_push(&mut self.vec, &raw const value as *const T as *const u8);
|
||||||
&mut self.vec,
|
|
||||||
&raw const value as *const T as *const u8,
|
|
||||||
core::mem::size_of::<T>(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,19 +168,47 @@ impl<T> VecT<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let index = vec_binary_search_by(
|
let (index, vacant) = vec_binary_search_by(
|
||||||
&raw const self.vec as *mut _,
|
&raw const self.vec as *mut _,
|
||||||
elem as *const T as *const u8,
|
elem as *const T as *const u8,
|
||||||
cmp_trampoline::<T, F>,
|
cmp_trampoline::<T, F>,
|
||||||
&raw mut cmp as *mut F as *mut (),
|
&raw mut cmp as *mut F as *mut (),
|
||||||
);
|
);
|
||||||
if (index as isize) < 0 {
|
if vacant {
|
||||||
Err(!index)
|
Err(index)
|
||||||
} else {
|
} else {
|
||||||
Ok(index)
|
Ok(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn insert_sorted<F>(&self, elem: T, mut cmp: F) -> Result<usize, usize>
|
||||||
|
where
|
||||||
|
F: FnMut(&T, &T) -> i32,
|
||||||
|
{
|
||||||
|
extern "C" fn cmp_trampoline<T, F: FnMut(&T, &T) -> i32>(
|
||||||
|
f: *const (),
|
||||||
|
a: *const u8,
|
||||||
|
b: *const u8,
|
||||||
|
) -> i32 {
|
||||||
|
let f = unsafe { &mut *(f as *mut F) };
|
||||||
|
let a = unsafe { &*(a as *const T) };
|
||||||
|
let b = unsafe { &*(b as *const T) };
|
||||||
|
f(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut elem = core::mem::ManuallyDrop::new(elem);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let (index, inserted) = vec_insert_sorted(
|
||||||
|
&raw const self.vec as *mut _,
|
||||||
|
&raw const elem as *const u8,
|
||||||
|
cmp_trampoline::<T, F>,
|
||||||
|
&raw mut cmp as *mut F as *mut (),
|
||||||
|
);
|
||||||
|
Ok(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
|
|
@ -203,7 +227,7 @@ unsafe extern "C" {
|
||||||
drop: Option<extern "C" fn(*mut u8)>,
|
drop: Option<extern "C" fn(*mut u8)>,
|
||||||
cap: usize,
|
cap: usize,
|
||||||
);
|
);
|
||||||
unsafe fn vec_push(vec: *mut BlobVec, elem: *const u8, size: usize);
|
unsafe fn vec_push(vec: *mut BlobVec, elem: *const u8);
|
||||||
unsafe fn vec_insert(vec: *mut BlobVec, index: usize, elem: *const u8);
|
unsafe fn vec_insert(vec: *mut BlobVec, index: usize, elem: *const u8);
|
||||||
unsafe fn vec_pop(vec: *mut BlobVec);
|
unsafe fn vec_pop(vec: *mut BlobVec);
|
||||||
unsafe fn vec_drop_last(vec: *mut BlobVec);
|
unsafe fn vec_drop_last(vec: *mut BlobVec);
|
||||||
|
|
@ -226,7 +250,13 @@ unsafe extern "C" {
|
||||||
elem: *const u8,
|
elem: *const u8,
|
||||||
cmp: extern "C" fn(*const (), *const u8, *const u8) -> i32,
|
cmp: extern "C" fn(*const (), *const u8, *const u8) -> i32,
|
||||||
cmp_data: *mut (),
|
cmp_data: *mut (),
|
||||||
) -> usize;
|
) -> (usize, bool);
|
||||||
|
unsafe fn vec_insert_sorted(
|
||||||
|
vec: *mut BlobVec,
|
||||||
|
elem: *const u8,
|
||||||
|
cmp: extern "C" fn(*const (), *const u8, *const u8) -> i32,
|
||||||
|
cmp_data: *mut (),
|
||||||
|
) -> (usize, bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
@ -266,7 +296,7 @@ fn main() {
|
||||||
vec_init(&mut vec, 4, Some(drop));
|
vec_init(&mut vec, 4, Some(drop));
|
||||||
let mut value: u32 = 2;
|
let mut value: u32 = 2;
|
||||||
assert_eq!(vec.len, 0);
|
assert_eq!(vec.len, 0);
|
||||||
vec_push(&mut vec, &value as *const u32 as *const u8, 4);
|
vec_push(&mut vec, &value as *const u32 as *const u8);
|
||||||
assert_eq!(vec.len, 1);
|
assert_eq!(vec.len, 1);
|
||||||
assert_eq!(as_slice::<u32>(&vec), &[2]);
|
assert_eq!(as_slice::<u32>(&vec), &[2]);
|
||||||
let retrieved = *(vec_get(&mut vec, 0) as *mut u32);
|
let retrieved = *(vec_get(&mut vec, 0) as *mut u32);
|
||||||
|
|
@ -276,10 +306,10 @@ fn main() {
|
||||||
assert_eq!(vec.len, 0);
|
assert_eq!(vec.len, 0);
|
||||||
assert_eq!(get_drops(), 2);
|
assert_eq!(get_drops(), 2);
|
||||||
value = 3;
|
value = 3;
|
||||||
vec_push(&mut vec, &value as *const u32 as *const u8, 4);
|
vec_push(&mut vec, &value as *const u32 as *const u8);
|
||||||
assert_eq!(as_slice::<u32>(&vec), &[3]);
|
assert_eq!(as_slice::<u32>(&vec), &[3]);
|
||||||
value = 5;
|
value = 5;
|
||||||
vec_push(&mut vec, &value as *const u32 as *const u8, 4);
|
vec_push(&mut vec, &value as *const u32 as *const u8);
|
||||||
assert_eq!(as_slice::<u32>(&vec), &[3, 5]);
|
assert_eq!(as_slice::<u32>(&vec), &[3, 5]);
|
||||||
assert_eq!(vec.len, 2);
|
assert_eq!(vec.len, 2);
|
||||||
vec_drop_last(&mut vec);
|
vec_drop_last(&mut vec);
|
||||||
|
|
@ -322,8 +352,12 @@ fn main() {
|
||||||
core::cmp::Ordering::Equal => 0,
|
core::cmp::Ordering::Equal => 0,
|
||||||
core::cmp::Ordering::Greater => 1,
|
core::cmp::Ordering::Greater => 1,
|
||||||
};
|
};
|
||||||
|
assert_eq!(vec.binary_search_by(&35, cmp), Err(2));
|
||||||
assert_eq!(vec.binary_search_by(&25, cmp), Err(1));
|
assert_eq!(vec.binary_search_by(&25, cmp), Err(1));
|
||||||
assert_eq!(vec.binary_search_by(&30, cmp), Ok(1));
|
assert_eq!(vec.binary_search_by(&30, cmp), Ok(1));
|
||||||
assert_eq!(vec.binary_search_by(&5, cmp), Err(0));
|
assert_eq!(vec.binary_search_by(&5, cmp), Err(0));
|
||||||
assert_eq!(vec.binary_search_by(&55, cmp), Err(5));
|
assert_eq!(vec.binary_search_by(&55, cmp), Err(4));
|
||||||
|
|
||||||
|
vec.insert_sorted(35, cmp);
|
||||||
|
assert_eq!(vec.as_slice(), &[20, 30, 35, 40, 50]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue