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
use super::sort::{sort_by};
use num::{Float,zero};
use unreachable::unreachable;
pub fn sort_floats<T: Float>(v: &mut [T]) {
if v.len() <= 1 {
return;
}
let mut rnan = v.len() - 1;
while rnan > 0 && v[rnan].is_nan() {
rnan -= 1;
}
let mut p = rnan;
while p > 0 {
p -= 1;
if v[p].is_nan() {
v.swap(p, rnan);
rnan -= 1;
}
}
sort_by(&mut v[..rnan + 1], &|x: &T, y: &T|
match x.partial_cmp(y) {
Some(ord) => ord,
None => unsafe { unreachable() }
});
let left = find_first_zero(&v[..rnan + 1]);
let mut zeros = 0;
let mut neg_zeros = 0;
for x in v[left..].iter() {
if *x != zero() {
break;
}
if x.is_sign_negative() {
neg_zeros += 1;
} else {
zeros += 1;
}
}
for x in v[left..].iter_mut() {
if neg_zeros > 0 {
*x = Float::neg_zero();
neg_zeros -= 1;
} else if zeros > 0 {
*x = zero();
zeros -= 1;
} else {
break;
}
}
}
fn find_first_zero<T: Float>(v: &[T]) -> usize {
if v.len() == 0 { return 0; }
let mut hi = v.len() - 1;
let mut left = 0;
while left < hi {
let mid = ((hi - left) / 2) + left;
if v[mid] < zero() {
left = mid + 1;
} else {
hi = mid;
}
}
while left < v.len() && v[left] < zero() {
left += 1;
}
return left;
}