40 #if (_MSC_VER == 1500 || _MSC_VER == 1600)
41 #define NO_INCLUDE_FENV
47 #define NO_INCLUDE_FENV
49 #ifdef NO_INCLUDE_FENV
65 #error The constant DBL_MANT_DIG could not be defined.
67 #define T_FLOAT_MANT_DIG DBL_MANT_DIG
73 #error The constant LONG_MAX could not be defined.
76 #error The constant INT_MAX could not be defined.
82 #define __STDC_LIMIT_MACROS
85 typedef __int32 int_fast32_t;
86 typedef __int64 int64_t;
89 #define __STDC_LIMIT_MACROS
94 #define FILL_N std::fill_n
98 #define FILL_N stdext::unchecked_fill_n
104 #pragma warning(disable : 4700)
107 #ifndef HAVE_DIAGNOSTIC
108 #if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6))
109 #define HAVE_DIAGNOSTIC 1
113 #ifndef HAVE_VISIBILITY
115 #define HAVE_VISIBILITY 1
126 #pragma GCC visibility push(hidden)
131 #define MAX_INDEX 0x7fffffffL
133 #define MAX_INDEX INT32_MAX
135 #if (LONG_MAX < MAX_INDEX)
136 #error The integer format "t_index" must not have a greater range than "long int".
138 #if (INT_MAX > MAX_INDEX)
139 #error The integer format "int" must not have a greater range than "t_index".
176 template <
typename type>
184 template <
typename index>
188 template <
typename index,
typename value>
199 template <
typename index>
202 ptr =
new type[size];
204 template <
typename index,
typename value>
205 void init(index
const size, value
const val)
210 inline operator type *()
const {
return ptr; }
233 Z[pos].node1 = node1;
234 Z[pos].node2 = node2;
246 for (
node *ZZ = Z; ZZ != Z + pos; ++ZZ) {
247 ZZ->dist = std::sqrt(ZZ->dist);
258 for (
node *ZZ = Z; ZZ != Z + pos; ++ZZ) {
259 ZZ->dist = std::sqrt(2 * ZZ->dist);
266 #define my_pow std::pow
272 for (
node *ZZ = Z; ZZ != Z + pos; ++ZZ) {
273 ZZ->dist =
my_pow(ZZ->dist, q);
279 for (
node *ZZ = Z; ZZ != Z + pos; ++ZZ) {
286 for (
node *ZZ = Z; ZZ != Z + pos; ++ZZ) {
313 :
start(0),
succ(size + 1), pred(size + 1)
315 for (
t_index i = 0; i < size; ++i) {
332 pred[
succ[idx]] = pred[idx];
343 #define D_(r_, c_) (D[(static_cast<std::ptrdiff_t>(2 * N - 3 - (r_)) * (r_) >> 1) + (c_)-1])
345 #define Z_(_r, _c) (Z[(_r)*4 + (_c)])
365 if (parent[idx] != 0) {
368 if (parent[idx] != 0) {
371 }
while (parent[idx] != 0);
376 }
while (parent[p] != idx);
414 min = std::numeric_limits<t_float>::infinity();
415 for (i = 1; i < N; ++i) {
418 #pragma GCC diagnostic push
419 #pragma GCC diagnostic ignored "-Wfloat-equal"
427 #pragma GCC diagnostic pop
432 for (
t_index j = 1; j < N - 1; ++j) {
434 active_nodes.remove(prev_node);
436 idx2 = active_nodes.succ[0];
438 for (i = idx2; i < prev_node; i = active_nodes.succ[i]) {
441 #pragma GCC diagnostic push
442 #pragma GCC diagnostic ignored "-Wfloat-equal"
449 #pragma GCC diagnostic pop
456 for (; i < N; i = active_nodes.succ[i]) {
459 #pragma GCC diagnostic push
460 #pragma GCC diagnostic ignored "-Wfloat-equal"
467 #pragma GCC diagnostic pop
474 Z2.
append(prev_node, idx2, min);
492 *b = s * a + t * (*b);
495 #pragma GCC diagnostic push
496 #pragma GCC diagnostic ignored "-Wfloat-equal"
502 #pragma GCC diagnostic pop
511 #pragma GCC diagnostic push
512 #pragma GCC diagnostic ignored "-Wfloat-equal"
518 #pragma GCC diagnostic pop
525 *b = ((v + s) * a - v *
c + (v + t) * (*b)) / (s + t + v);
529 #pragma GCC diagnostic push
530 #pragma GCC diagnostic ignored "-Wfloat-equal"
536 #pragma GCC diagnostic pop
542 *b = s * a - stc + t * (*b);
548 #pragma GCC diagnostic pop
554 *b = (a + (*b)) * .5 - c_4;
557 #pragma GCC diagnostic push
558 #pragma GCC diagnostic ignored "-Wfloat-equal"
564 #pragma GCC diagnostic pop
569 template <method_codes method,
typename t_members>
594 for (
t_float const *DD = D; DD != D + (
static_cast<std::ptrdiff_t
>(N) * (N - 1) >> 1); ++DD) {
596 #pragma GCC diagnostic push
597 #pragma GCC diagnostic ignored "-Wfloat-equal"
603 #pragma GCC diagnostic pop
608 if (feclearexcept(FE_INVALID))
612 for (
t_index j = 0; j < N - 1; ++j) {
613 if (NN_chain_tip <= 3) {
614 NN_chain[0] = idx1 = active_nodes.start;
617 idx2 = active_nodes.succ[idx1];
618 min =
D_(idx1, idx2);
619 for (i = active_nodes.succ[idx2]; i < N; i = active_nodes.succ[i]) {
620 if (
D_(idx1, i) < min) {
628 idx1 = NN_chain[NN_chain_tip - 1];
629 idx2 = NN_chain[NN_chain_tip];
630 min = idx1 < idx2 ?
D_(idx1, idx2) :
D_(idx2, idx1);
634 NN_chain[NN_chain_tip] = idx2;
636 for (i = active_nodes.start; i < idx2; i = active_nodes.succ[i]) {
637 if (
D_(i, idx2) < min) {
642 for (i = active_nodes.succ[idx2]; i < N; i = active_nodes.succ[i]) {
643 if (
D_(idx2, i) < min) {
650 idx1 = NN_chain[NN_chain_tip++];
652 }
while (idx2 != NN_chain[NN_chain_tip - 2]);
654 Z2.
append(idx1, idx2, min);
663 size1 =
static_cast<t_float>(members[idx1]);
664 size2 =
static_cast<t_float>(members[idx2]);
665 members[idx2] += members[idx1];
669 active_nodes.remove(idx1);
679 for (i = active_nodes.start; i < idx1; i = active_nodes.succ[i])
680 f_single(&
D_(i, idx2),
D_(i, idx1));
682 for (; i < idx2; i = active_nodes.succ[i])
683 f_single(&
D_(i, idx2),
D_(idx1, i));
685 for (i = active_nodes.succ[idx2]; i < N; i = active_nodes.succ[i])
686 f_single(&
D_(idx2, i),
D_(idx1, i));
696 for (i = active_nodes.start; i < idx1; i = active_nodes.succ[i])
697 f_complete(&
D_(i, idx2),
D_(i, idx1));
699 for (; i < idx2; i = active_nodes.succ[i])
700 f_complete(&
D_(i, idx2),
D_(idx1, i));
702 for (i = active_nodes.succ[idx2]; i < N; i = active_nodes.succ[i])
703 f_complete(&
D_(idx2, i),
D_(idx1, i));
713 t_float s = size1 / (size1 + size2);
714 t_float t = size2 / (size1 + size2);
715 for (i = active_nodes.start; i < idx1; i = active_nodes.succ[i])
716 f_average(&
D_(i, idx2),
D_(i, idx1), s, t);
718 for (; i < idx2; i = active_nodes.succ[i])
719 f_average(&
D_(i, idx2),
D_(idx1, i), s, t);
721 for (i = active_nodes.succ[idx2]; i < N; i = active_nodes.succ[i])
722 f_average(&
D_(idx2, i),
D_(idx1, i), s, t);
733 for (i = active_nodes.start; i < idx1; i = active_nodes.succ[i])
734 f_weighted(&
D_(i, idx2),
D_(i, idx1));
736 for (; i < idx2; i = active_nodes.succ[i])
737 f_weighted(&
D_(i, idx2),
D_(idx1, i));
739 for (i = active_nodes.succ[idx2]; i < N; i = active_nodes.succ[i])
740 f_weighted(&
D_(idx2, i),
D_(idx1, i));
752 for (i = active_nodes.start; i < idx1; i = active_nodes.succ[i])
753 f_ward(&
D_(i, idx2),
D_(i, idx1), min, size1, size2,
static_cast<t_float>(members[i]));
755 for (; i < idx2; i = active_nodes.succ[i])
756 f_ward(&
D_(i, idx2),
D_(idx1, i), min, size1, size2,
static_cast<t_float>(members[i]));
758 for (i = active_nodes.succ[idx2]; i < N; i = active_nodes.succ[i])
759 f_ward(&
D_(idx2, i),
D_(idx1, i), min, size1, size2,
static_cast<t_float>(members[i]));
762 default:
throw std::runtime_error(std::string(
"Invalid method."));
766 if (fetestexcept(FE_INVALID))
809 for (
t_index i = 0; i < size; ++i)
814 : A(A_), size(size1), I(size1), R(size2)
817 for (
t_index i = 0; i < size; ++i) {
834 for (idx = (size >> 1); idx > 0;) {
861 if (H(size) <= A[idx]) {
870 R[idxnew] = R[idxold];
871 I[R[idxnew]] = idxnew;
872 if (val <= A[idxold])
903 void update_leq_(
t_index i)
const
906 for (; (i > 0) && (H(i) < H(j = (i - 1) >> 1)); i = j)
910 void update_geq_(
t_index i)
const
913 for (; (j = 2 * i + 1) < size; i = j) {
916 if (j >= size || H(j) >= H(i))
918 }
else if (j + 1 < size && H(j + 1) < H(j))
937 template <method_codes method,
typename t_members>
963 for (i = 0; i < N; ++i)
972 for (i = 0; i < N_1; ++i) {
973 min = std::numeric_limits<t_float>::infinity();
974 for (idx = j = i + 1; j < N; ++j, ++DD) {
976 #pragma GCC diagnostic push
977 #pragma GCC diagnostic ignored "-Wfloat-equal"
986 #pragma GCC diagnostic pop
994 nn_distances.heapify();
997 if (feclearexcept(FE_INVALID))
1002 for (i = 0; i < N_1; ++i) {
1036 idx1 = nn_distances.argmin();
1038 while (mindist[idx1] <
D_(idx1, n_nghbr[idx1])) {
1040 n_nghbr[idx1] = j = active_nodes.succ[idx1];
1042 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1043 if (
D_(idx1, j) < min) {
1050 nn_distances.update_geq(idx1, min);
1051 idx1 = nn_distances.argmin();
1055 nn_distances.heap_pop();
1056 idx2 = n_nghbr[idx1];
1059 node1 = row_repr[idx1];
1060 node2 = row_repr[idx2];
1063 size1 =
static_cast<t_float>(members[idx1]);
1064 size2 =
static_cast<t_float>(members[idx2]);
1065 members[idx2] += members[idx1];
1067 Z2.
append(node1, node2, mindist[idx1]);
1070 active_nodes.remove(idx1);
1072 row_repr[idx2] = N + i;
1083 for (j = active_nodes.start; j < idx1; j = active_nodes.succ[j]) {
1084 f_single(&
D_(j, idx2),
D_(j, idx1));
1085 if (n_nghbr[j] == idx1)
1089 for (; j < idx2; j = active_nodes.succ[j]) {
1090 f_single(&
D_(j, idx2),
D_(idx1, j));
1093 if (
D_(j, idx2) < mindist[j]) {
1094 nn_distances.update_leq(j,
D_(j, idx2));
1101 min = mindist[idx2];
1102 for (j = active_nodes.succ[idx2]; j < N; j = active_nodes.succ[j]) {
1103 f_single(&
D_(idx2, j),
D_(idx1, j));
1104 if (
D_(idx2, j) < min) {
1109 nn_distances.update_leq(idx2, min);
1120 for (j = active_nodes.start; j < idx1; j = active_nodes.succ[j]) {
1121 f_complete(&
D_(j, idx2),
D_(j, idx1));
1122 if (n_nghbr[j] == idx1)
1126 for (; j < idx2; j = active_nodes.succ[j])
1127 f_complete(&
D_(j, idx2),
D_(idx1, j));
1129 for (j = active_nodes.succ[idx2]; j < N; j = active_nodes.succ[j])
1130 f_complete(&
D_(idx2, j),
D_(idx1, j));
1140 t_float s = size1 / (size1 + size2);
1141 t_float t = size2 / (size1 + size2);
1142 for (j = active_nodes.start; j < idx1; j = active_nodes.succ[j]) {
1143 f_average(&
D_(j, idx2),
D_(j, idx1), s, t);
1144 if (n_nghbr[j] == idx1)
1148 for (; j < idx2; j = active_nodes.succ[j]) {
1149 f_average(&
D_(j, idx2),
D_(idx1, j), s, t);
1150 if (
D_(j, idx2) < mindist[j]) {
1151 nn_distances.update_leq(j,
D_(j, idx2));
1157 n_nghbr[idx2] = j = active_nodes.succ[idx2];
1158 f_average(&
D_(idx2, j),
D_(idx1, j), s, t);
1160 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1161 f_average(&
D_(idx2, j),
D_(idx1, j), s, t);
1162 if (
D_(idx2, j) < min) {
1167 nn_distances.update(idx2, min);
1179 for (j = active_nodes.start; j < idx1; j = active_nodes.succ[j]) {
1180 f_weighted(&
D_(j, idx2),
D_(j, idx1));
1181 if (n_nghbr[j] == idx1)
1185 for (; j < idx2; j = active_nodes.succ[j]) {
1186 f_weighted(&
D_(j, idx2),
D_(idx1, j));
1187 if (
D_(j, idx2) < mindist[j]) {
1188 nn_distances.update_leq(j,
D_(j, idx2));
1194 n_nghbr[idx2] = j = active_nodes.succ[idx2];
1195 f_weighted(&
D_(idx2, j),
D_(idx1, j));
1197 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1198 f_weighted(&
D_(idx2, j),
D_(idx1, j));
1199 if (
D_(idx2, j) < min) {
1204 nn_distances.update(idx2, min);
1216 for (j = active_nodes.start; j < idx1; j = active_nodes.succ[j]) {
1217 f_ward(&
D_(j, idx2),
D_(j, idx1), mindist[idx1], size1, size2,
static_cast<t_float>(members[j]));
1218 if (n_nghbr[j] == idx1)
1222 for (; j < idx2; j = active_nodes.succ[j]) {
1223 f_ward(&
D_(j, idx2),
D_(idx1, j), mindist[idx1], size1, size2,
static_cast<t_float>(members[j]));
1224 if (
D_(j, idx2) < mindist[j]) {
1225 nn_distances.update_leq(j,
D_(j, idx2));
1231 n_nghbr[idx2] = j = active_nodes.succ[idx2];
1232 f_ward(&
D_(idx2, j),
D_(idx1, j), mindist[idx1], size1, size2,
static_cast<t_float>(members[j]));
1234 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1235 f_ward(&
D_(idx2, j),
D_(idx1, j), mindist[idx1], size1, size2,
static_cast<t_float>(members[j]));
1236 if (
D_(idx2, j) < min) {
1241 nn_distances.update(idx2, min);
1253 t_float s = size1 / (size1 + size2);
1254 t_float t = size2 / (size1 + size2);
1255 t_float stc = s * t * mindist[idx1];
1256 for (j = active_nodes.start; j < idx1; j = active_nodes.succ[j]) {
1257 f_centroid(&
D_(j, idx2),
D_(j, idx1), stc, s, t);
1258 if (
D_(j, idx2) < mindist[j]) {
1259 nn_distances.update_leq(j,
D_(j, idx2));
1261 }
else if (n_nghbr[j] == idx1)
1265 for (; j < idx2; j = active_nodes.succ[j]) {
1266 f_centroid(&
D_(j, idx2),
D_(idx1, j), stc, s, t);
1267 if (
D_(j, idx2) < mindist[j]) {
1268 nn_distances.update_leq(j,
D_(j, idx2));
1274 n_nghbr[idx2] = j = active_nodes.succ[idx2];
1275 f_centroid(&
D_(idx2, j),
D_(idx1, j), stc, s, t);
1277 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1278 f_centroid(&
D_(idx2, j),
D_(idx1, j), stc, s, t);
1279 if (
D_(idx2, j) < min) {
1284 nn_distances.update(idx2, min);
1297 t_float c_4 = mindist[idx1] * .25;
1298 for (j = active_nodes.start; j < idx1; j = active_nodes.succ[j]) {
1299 f_median(&
D_(j, idx2),
D_(j, idx1), c_4);
1300 if (
D_(j, idx2) < mindist[j]) {
1301 nn_distances.update_leq(j,
D_(j, idx2));
1303 }
else if (n_nghbr[j] == idx1)
1307 for (; j < idx2; j = active_nodes.succ[j]) {
1308 f_median(&
D_(j, idx2),
D_(idx1, j), c_4);
1309 if (
D_(j, idx2) < mindist[j]) {
1310 nn_distances.update_leq(j,
D_(j, idx2));
1316 n_nghbr[idx2] = j = active_nodes.succ[idx2];
1317 f_median(&
D_(idx2, j),
D_(idx1, j), c_4);
1319 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1320 f_median(&
D_(idx2, j),
D_(idx1, j), c_4);
1321 if (
D_(idx2, j) < min) {
1326 nn_distances.update(idx2, min);
1331 default:
throw std::runtime_error(std::string(
"Invalid method."));
1335 if (fetestexcept(FE_INVALID))
1344 template <
typename t_dissimilarity>
1367 min = std::numeric_limits<t_float>::infinity();
1368 for (i = 1; i < N; ++i) {
1371 #pragma GCC diagnostic push
1372 #pragma GCC diagnostic ignored "-Wfloat-equal"
1380 #pragma GCC diagnostic pop
1386 for (
t_index j = 1; j < N - 1; ++j) {
1388 active_nodes.remove(prev_node);
1390 idx2 = active_nodes.succ[0];
1393 for (i = idx2; i < N; i = active_nodes.succ[i]) {
1394 t_float tmp = dist(i, prev_node);
1396 #pragma GCC diagnostic push
1397 #pragma GCC diagnostic ignored "-Wfloat-equal"
1404 #pragma GCC diagnostic pop
1411 Z2.
append(prev_node, idx2, min);
1415 template <method_codes_vector method,
typename t_dissimilarity>
1440 for (i = 0; i < N; ++i)
1448 for (i = 0; i < N_1; ++i) {
1449 min = std::numeric_limits<t_float>::infinity();
1451 for (idx = j = i + 1; j < N; ++j) {
1455 default: tmp = dist.template sqeuclidean<true>(i, j);
1463 case METHOD_VECTOR_WARD: mindist[i] = t_dissimilarity::ward_initial_conversion(min);
break;
1464 default: mindist[i] = min;
1471 nn_distances.heapify();
1474 for (i = 0; i < N_1; ++i) {
1475 idx1 = nn_distances.argmin();
1477 while (active_nodes.is_inactive(n_nghbr[idx1])) {
1479 n_nghbr[idx1] = j = active_nodes.succ[idx1];
1482 min = dist.ward(idx1, j);
1483 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1484 t_float const tmp = dist.ward(idx1, j);
1492 min = dist.template sqeuclidean<true>(idx1, j);
1493 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1494 t_float const tmp = dist.template sqeuclidean<true>(idx1, j);
1503 nn_distances.update_geq(idx1, min);
1504 idx1 = nn_distances.argmin();
1507 nn_distances.heap_pop();
1508 idx2 = n_nghbr[idx1];
1511 node1 = row_repr[idx1];
1512 node2 = row_repr[idx2];
1514 Z2.
append(node1, node2, mindist[idx1]);
1520 default:
throw std::runtime_error(std::string(
"Invalid method."));
1524 row_repr[idx2] = N + i;
1526 active_nodes.remove(idx1);
1538 for (j = active_nodes.start; j < idx1; j = active_nodes.succ[j]) {
1539 if (n_nghbr[j] == idx2) {
1544 for (; j < idx2; j = active_nodes.succ[j]) {
1545 t_float const tmp = dist.ward(j, idx2);
1546 if (tmp < mindist[j]) {
1547 nn_distances.update_leq(j, tmp);
1549 }
else if (n_nghbr[j] == idx2) {
1555 n_nghbr[idx2] = j = active_nodes.succ[idx2];
1556 min = dist.ward(idx2, j);
1557 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1558 t_float const tmp = dist.ward(idx2, j);
1564 nn_distances.update(idx2, min);
1575 for (j = active_nodes.start; j < idx2; j = active_nodes.succ[j]) {
1576 t_float const tmp = dist.template sqeuclidean<true>(j, idx2);
1577 if (tmp < mindist[j]) {
1578 nn_distances.update_leq(j, tmp);
1580 }
else if (n_nghbr[j] == idx2)
1585 n_nghbr[idx2] = j = active_nodes.succ[idx2];
1586 min = dist.template sqeuclidean<true>(idx2, j);
1587 for (j = active_nodes.succ[j]; j < N; j = active_nodes.succ[j]) {
1588 t_float const tmp = dist.template sqeuclidean<true>(idx2, j);
1594 nn_distances.update(idx2, min);
1600 template <method_codes_vector method,
typename t_dissimilarity>
1601 static void generic_linkage_vector_alternative(
const t_index N, t_dissimilarity &dist,
cluster_result &Z2)
1628 for (i = 1; i < N; ++i) {
1629 min = std::numeric_limits<t_float>::infinity();
1631 for (idx = j = 0; j < i; ++j) {
1635 default: tmp = dist.template sqeuclidean<true>(i, j);
1643 case METHOD_VECTOR_WARD: mindist[i] = t_dissimilarity::ward_initial_conversion(min);
break;
1644 default: mindist[i] = min;
1651 nn_distances.heapify();
1654 for (i = N; i < N + N_1; ++i) {
1674 idx1 = nn_distances.argmin();
1675 while (active_nodes.is_inactive(n_nghbr[idx1])) {
1677 n_nghbr[idx1] = j = active_nodes.start;
1680 min = dist.ward_extended(idx1, j);
1681 for (j = active_nodes.succ[j]; j < idx1; j = active_nodes.succ[j]) {
1682 t_float tmp = dist.ward_extended(idx1, j);
1690 min = dist.sqeuclidean_extended(idx1, j);
1691 for (j = active_nodes.succ[j]; j < idx1; j = active_nodes.succ[j]) {
1692 t_float const tmp = dist.sqeuclidean_extended(idx1, j);
1701 nn_distances.update_geq(idx1, min);
1702 idx1 = nn_distances.argmin();
1705 idx2 = n_nghbr[idx1];
1706 active_nodes.remove(idx1);
1707 active_nodes.remove(idx2);
1709 Z2.
append(idx1, idx2, mindist[idx1]);
1718 default:
throw std::runtime_error(std::string(
"Invalid method."));
1721 n_nghbr[i] = active_nodes.start;
1729 min = dist.ward_extended(active_nodes.start, i);
1730 for (j = active_nodes.succ[active_nodes.start]; j < i; j = active_nodes.succ[j]) {
1731 t_float tmp = dist.ward_extended(j, i);
1744 min = dist.sqeuclidean_extended(active_nodes.start, i);
1745 for (j = active_nodes.succ[active_nodes.start]; j < i; j = active_nodes.succ[j]) {
1746 t_float tmp = dist.sqeuclidean_extended(j, i);
1753 if (idx2 < active_nodes.start) {
1754 nn_distances.remove(active_nodes.start);
1756 nn_distances.remove(idx2);
1758 nn_distances.replace(idx1, i, min);
1764 #pragma GCC visibility pop